Linux USB:打开和closures电源?

如何以编程方式启用和禁用Linux上特定USB端口的电源? 这样的事情甚至可能吗? (没有 – 见下文) Mac的答案也赞赏!

我正在尝试一个中国银行(不要假装你也没有试图获得一个!),并结束了其中一个,并希望通过连接到我们的服务器显示器来获得一些用途。

更新:这似乎不可能。 所有暂停电源的API基本上都会告诉连接的设备closures,但引脚1上的电源仍然可用,所以这些灯的简单设备不能直接通过编程方式进行控制。 也许提到的枢纽解决scheme将工作。

挖掘书签

http://blog.andrew.net.au/2009/01/01#usb_power_control

好像你需要将它连接到集线器,并控制集线器的电源。 我所见过的根中心似乎都不能支持电源控制。

在Linux中有一个sys入口。 从文档/ usb / power-management.txt :

能量等级

 This file contains one of three words: "on", "auto", or "suspend". You can write those words to the file to change the device's setting. "on" means that the device should be resumed and autosuspend is not allowed. (Of course, system suspends are still allowed.) "auto" is the normal state in which the kernel is allowed to autosuspend and autoresume the device. "suspend" means that the device should remain suspended, and autoresume is not allowed. (But remote wakeup may still be allowed, since it is controlled separately by the power/wakeup attribute.) 

例如: echo on > /sys/bus/usb/devices/usb5/power/level

您可能还需要使用autosuspend设置。 没有告诉内核停止尝试,它可能会自动暂停端口。

祝你好运!

自从这个问题最初被回答以来,usbfs交互似乎已经发生了多次变化。 所以,下面是我如何从Bash shell的Ubuntu Oneiric Ocelot循环集线器端口电源。

search巴士和设备号码:

 sudo lsusb -v|less 

使用总线和设备编号在总线/集线器端口层次结构中find设备:

 sudo lsusb -t|less 

语法似乎是“bus-port.port.port.port.port …”例如,我的鼠标连接到外部集线器,它连接到我的计算机集线器,它在内部连接到根集线器:

 /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/2p, 480M |__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/6p, 480M |__ Port 1: Dev 3, If 0, Class=hub, Driver=hub/3p, 480M |__ Port 1: Dev 6, If 0, Class=HID, Driver=usbhid, 1.5M 

因此,在上述情况下,“2-1.1.1”。 最后,循环端口电源:

 echo '2-1.1.1'|sudo tee /sys/bus/usb/drivers/usb/unbind sleep 1 echo '2-1.1.1'|sudo tee /sys/bus/usb/drivers/usb/bind 

我没有连接一个协议分析器来查看总线上发生了什么事情,但是我知道当我解开它时鼠标指示灯会熄灭。 我在下层猜测,这是与EHCI主机控制器交互,实际上closures端口的电源。 这对于embedded式设备特别有用,例如UVCnetworking摄像头,它们似乎从未正常工作,否则需要重新启动系统。

另请参阅udevadm命令。

@Kristian通常你不会发现软件控制的端口功率控制广告,因为用户不应该意识到这一层。 我不认为有很多使用情况,除了强迫行为不当的总线供电设备进入已知状态,并将其作为仅使用USB供电的后置设备来处理。 也许马克的装置属于后一类。 这是一个粗暴的,最后的手段机制。

正如我所提到的,我没有研究过绑定黑客的实现细节,我只是在embedded在我的主板上的EHCI主机控制器(“Intel公司的6系列/ C200系列芯片组家族USB增强主机控制器05版)“。 我猜测这个主机控制器的HCPCARAMS的PPC位被置位,表明每个EHCI规范的端口电源开关的软件控制。

如果您正在连接外部集线器,根据USB 2.0规范,“集线器通过在wHubCharacteristics中设置逻辑电源切换模式字段来指示是否支持电源切换”。 我不记得一致性testing是否确保这个function,但如果他们这样做,你只需要find一个带有USB 2.0标志的集线器。 我猜测黑客会发送一个设置的端口function请求,但是它可能循环的不仅仅是目标端口。 同样,根据USB 2.0规范,“一个带有电源开关的集线器可以将所有端口作为一个组/一个组,每个端口单独切换,或者拥有一个或多个端口的任意数量的组。 我不确定是否有一个很好的命令行工具来获取wHubCharacteristics。

总之,就我所知,没有一个很好的通用的方法来处理这个问题。 但是,可以询问内部或外部枢纽以确定其支持水平,然后在支持的情况下使用它。 这只是一个问题,你想花多less时间来这样做。

这是一个在Linux下的罗技USB无线鼠标的例子。

根据您的设备“供应商”(供应商ID)和“ProdID”(产品ID)或“制造商”和“产品”(所有这些值对于每个设备都是不变的)阅读“/ proc / bus / usb / devices” 。

 cat /proc/bus/usb/devices 

(第一段设备上电,第二段电源closures但仍插入)

 T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=1.5 MxCh= 0 D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=046d ProdID=c50e Rev=25.10 S: Manufacturer=Logitech S: Product=USB RECEIVER C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 70mA I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=10ms T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=1.5 MxCh= 0 D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=046d ProdID=c50e Rev=25.10 S: Manufacturer=Logitech S: Product=USB RECEIVER C: #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 70mA I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver= E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=10ms 

这里需要两个variables。 它们位于“T:”行(段落的第一行)。 这些variables是:总线(在这个例子中总线= 01)Cnt(在这个例子中Cnt = 01)

您需要将“1”(算术一)添加到“Cnt”以获得秩Rank = Cnt + 1(这是一个math函数,在本例中Rank = 2)

所以你要找的设备是下面的string:Bus-Rank(这不是一个math函数,它是一个string,在这个例子中是1-2)

还要注意“C: ”这一行。 它包含有关设备功率(电stream)的信息。 如果在“C: ”中有一个星号 (就像我们的第一个例子中那样),那么这个设备就会被启动。 如果不是(“C:”),则设备“或多或less”closures,这意味着当设备被插入时总是有微小的电stream,否则我们将无法读取所有这些信息。

铭记最后的“我:”线。 如果字段“我:*”包含星号(就像在我们的第一个例子中),那么从设备input或input设备,我不确定,也许两者都有。 最后一行字段包含使用的驱动程序(在我们的第一个示例中为“usbhid”)

我们准备好切换设备的电源:

关机

 echo -n "Bus-Rank" > /sys/bus/usb/drivers/usb/unbind echo -n "1-2" > /sys/bus/usb/drivers/usb/unbind (in our example) 

打开

 echo -n "Bus-Rank" > /sys/bus/usb/drivers/usb/bind echo -n "1-2" > /sys/bus/usb/drivers/usb/bind (in our example) 

以下是一个简单的bash脚本“USBMS”(USB鼠标开关),用于控制上述示例中设备的电源。 它不是很dynamic,它使用“Product”和“Manufacturer”常量来定位“/ proc / bus / usb / devices”的相关段落。您应该使用“Vendor” ID)。 它还检查设备的电源状态。 以超级用户身份运行。

命令:./USBMS操作

参数:动作=“关”或“0”关机 – 动作=“开”或“1”开机(不带引号)

 #!/bin/bash USBmouseProduct="USB RECEIVER" USBmouseManufacturer="Logitech" signal=$1 nr3=$(awk '/Product='"$USBmouseProduct"'/ {print NR}' /proc/bus/usb/devices) nr3=$(expr $nr3 + 0) nr2=$(awk '/Manufacturer='"$USBmouseManufacturer"'/ {print NR}' /proc/bus/usb/devices) nr2=$(expr $nr2 + 0) nr1=$(expr $nr2 - 3) nr4=$(expr $nr3 + 1) nrdiff=$(expr $nr3 - $nr2) [ $nr3 != 0 -a $nr2 != 0 -a $nrdiff = 1 ] && ( usbmbus0=$(awk 'NR=='$nr1' {print $2}' /proc/bus/usb/devices | awk -F= '{print $2}') usbmbus=$(expr $usbmbus0 + 0) usbmdev=$(awk 'NR=='$nr1' {print $8}' /proc/bus/usb/devices) usbmrank=$(awk 'NR=='$nr1' {print $5}' /proc/bus/usb/devices | awk -F= '{print $2}') usbmrank=$(expr $usbmrank + 1) usbmbusrank="$usbmbus""-""$usbmrank" usbmpower=$(awk 'NR=='$nr4' {if ( $1=="C:" ) {print 0}; if ( $1=="C:*" ) {print 1}}' /proc/bus/usb/devices) case $signal in off|0) [ $usbmpower = 1 ] && echo -n "$usbmbusrank" > /sys/bus/usb/drivers/usb/unbind ;; on|1) [ $usbmpower = 0 ] && echo -n "$usbmbusrank" > /sys/bus/usb/drivers/usb/bind ;; esac ) 

在OS X中,您可以从用户空间访问USB设备并请求暂停。

您可以在USB设备接口指南中find一个通用示例。 您将需要使用IOUSBDeviceInterface182 (或更高版本)的USBDeviceSuspend方法。

注意:集线器和控制器端口可能具有联动电源,这意味着同一个交换机被多个端口共享。 如果是这种情况,并且您的设备与另一个有源设备在同一组中,则不会closures它。

能量等级

“on”表示应该恢复设备并且不允许autosuspend(当然,系统暂停仍然是允许的)。

“auto”是允许内核自动挂起并自动恢复设备的正常状态。

“暂停”意味着设备应该保持暂停状态,并且不允许自动恢复。 (但是远程唤醒可能仍然被允许,因为它被电源/唤醒属性分开控制。)

第1步:所以我有,usb1,usb2,usb3,usb4 ….

 $ cat /sys/bus/usb/devices/usb*/power/level auto auto auto auto 

第二步:我怎么知道哪一个是哪个? (

 # echo "on" | tee /sys/bus/usb/devices/usb*/power/level # cat /sys/bus/usb/devices/usb*/power/level on on on on 

Optional 1:如果lsusb显示并需要查找特定的一个

 #!/bin/bash usb="046d:082d" # Find ME, Replace the ID cam=$(lsusb | awk "/$usb/ {print $6}") echo $cam if [ ! -z "$cam" -a "$cam" != " " ]; then for X in /sys/bus/usb/devices/*; do a=$(cat "$X/idVendor" 2>/dev/null) b=$(cat "$X/idProduct" 2>/dev/null) c="$a:$b" if [ ! -z "$c" -a "$c" != " " ] && [ "$c" == "$usb" ]; then d=$(echo $X | sed "s/\/sys\/bus\/usb\/devices\///g") echo "[FOUND] $d" #sudo sh -c "echo on > /sys/bus/usb/devices/$d/authorized" sleep 2 #sudo sh -c "echo on > /sys/bus/usb/devices/$d/authorized" lsusb break fi done; fi 

可选2:在没有发现的情况下 – 重新启动无法重新启动通过udp使用Arduino中继

 #!/bin/bash file="/var/www/html/video/now.jpeg" function age() { local filename=$1 local changed=`stat -c %Y "$filename"` local now=`date +%s` local elapsed let elapsed=now-changed echo $elapsed } while true do target="/dev/video99" foundon="none" warn="[WARNING]:" ok="[OK]:" for i in 0 1 2 3 4 do tmp="/dev/video$i" if [ -e $tmp ]; then foundon="/dev/video$i" #else # echo "no $i" fi done b="none" if [ "$foundon" = "$b" ]; then echo "$warn No camera is found - inform reboot or arduino boot" else echo "$ok ln -s $foundon $target" ### Camera is available but something is not correct so ### file_age=$(age "$file") echo The age of $file is $file_age seconds. if [[ ! -f $file ]]; then echo "file is not found. Kernel sucks for 500mA USB's" else echo "found file: $file_age" if [[ $file_age -gt 240 ]]; then echo "$warn greater then 240 seconds" else echo "$ok - less then 240 seconds" fi fi fi ls /dev/video* sleep 5 done 

Arduino中继:

 #include <SPI.h> #include <Ethernet.h> #include <EthernetUdp.h> byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD}; IPAddress ip(10,109,4,166); byte gateway[]= {10,109, 0, 1}; byte subnet[]= {255, 255, 248,0}; unsigned int localPort = 8888; char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; char ReplyBuffer[] = "ackv1"; EthernetUDP Udp; int led1 = 2; int led2 = 3; void setup() { Ethernet.begin(mac,ip); //Ethernet.begin(mac, ip, '8.8.8.8', gateway, subnet); Udp.begin(localPort); pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); digitalWrite(led1, LOW); digitalWrite(led2, LOW); } void loop() { int packetSize = Udp.parsePacket(); if(packetSize) { delay(1000); digitalWrite(led1, HIGH); // turn the LED off by making the voltage LOW delay(3000); digitalWrite(led1, LOW); // turn the LED on (HIGH is the voltage level) delay(1000); digitalWrite(led2, HIGH); // turn the LED off by making the voltage LOW delay(3000); digitalWrite(led2, LOW); // turn the LED on (HIGH is the voltage level) Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(ReplyBuffer); Udp.endPacket(); } delay(10); } 

您可以使用uhubctl – 命令行实用程序来控制兼容USB集线器的每个端口的USB电源。

它只能在支持每端口电源切换的集线器上工作,但请注意,许多现代主板都具有支持此function的USB集线器。

编译:

 git clone https://github.com/mvp/uhubctl cd uhubctl make 

要列出可以由uhubctl控制的所有集线器和端口的状态:

 uhubctl 

您可能需要添加-i来查看内部USB集线器的状态(默认情况下,它们被排除)。

要closures单个兼容集线器的端口5的电源:

 uhubctl -a 0 -p 5 

要打开所有兼容集线器的所有端口的电源

 uhubctl -a 1 

要closures电源然后打开:

 uhubctl -a 2 -p 5 

在这里阅读更多 。

免责声明 – 我是uhubctl的作者。

我更倾向于切断电线,并把它连接到一个串行端口上,这个串行端口有一个“接收就绪”的简单继电器。 然后,每当有一些问题时,你就可以把信号线(信号“我准备好接收”)连接到串口文件。 完成后,只需发出'我已满'

然而,我对这些事情的理解是,他们在充满电容器之前吸取大量电stream,然后立即释放,以使灯泡闪烁。 我无法想象这样的突然放电对电脑的电路是有好处的。 您可能需要一些二极pipe电stream陷阱来防止反馈到串行端口。

每当我的闹钟响起,电脑关机!

你正在运行只是“回声”作为根,尝试:

 echo suspend | sudo tee /sys/bus/usb/devices/usb3/power/level 

一些USB集线器可以开关它们的端口,如链接中所述。 我还没有find一个可以启用或禁用USB端口的主板。

不要为了打开和closuresUSB小工具而购买昂贵的智能集线器。
所有你需要的是一个微控制器。

Arduino Nano™ATmega328 * 1 在这里输入图像说明

Nano是一款16MHz 8位计算机,具有2K RAM和32K闪存。
它有22个可编程引脚(8个模拟和14个数字)。
它可以读/写 USB,并由5.0V microUSB端口供电(外部电压高达12.0V)。

 // USB Blinker // Blink LED while receiving USB stream // // For Arduino Nano™ int LED = 13; // setup() is run once at powerup or when reset button is pressed // void setup() { pinMode(LED, OUTPUT); // Configure pin D13 as output Serial.begin(9600); // Open 9600bps USB stream } // loop() runs forever at 16Mhz, blinking the LED at 1Hz when receiving USB data. // void loop() { if (Serial.available() > 0) { // When stream is buffering digitalWrite(LED, HIGH); // turn on LED delay(500); // wait half second digitalWrite(LED, LOW); // turn off LED delay(500); // wait half second while (Serial.available() > 0) // drain the buffer Serial.read(); } } 

精致的小案例可用(也是免费的3D printables )。

C4Labs斑马黑冰盒
6

*只使用真正的Arduino Nano™。 谨防假冒 。

更新:微型ATtiny和无线微控制器也可用。

据我所知,您的设备由USB电源线VCC(〜5V)提供。 问题在于,除非将设备与启用了电源控制的集线器连接,否则此电源线不能在标准Linux框架中的用户空间中进行控制。 Ony内核代码可以触摸这条电源线。