Linux USB:打开和关闭电源?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1163824/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:32:59  来源:igfitidea点击:

Linux USB: turning the power on and off?

linuxmacosusb

提问by Mark Harrison

How can I programmatically enable and disable the power to a particular USB port on Linux? Is such a thing even possible? Mac answers appreciated as well!

如何以编程方式启用和禁用 Linux 上特定 USB 端口的电源?这样的事情甚至可能吗?Mac 的回答也很受欢迎!

I was trying for a BOC(don't pretend you weren't try to get one too!) and ended up with one of these, and would like to get some use out of the thing by hooking it up to our server monitor.

我正在尝试BOC(不要假装您也没有尝试获得一个!)并最终获得了其中一个,并希望通过将其连接到我们的服务器监视器来利用它。

采纳答案by Savant Degrees

Digs through bookmarks

通过书签挖掘

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

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

Seems like you need to connect it to a hub and control the hub's power. None of the root hubs I have seen seems to be able to support power control.

似乎您需要将其连接到集线器并控制集线器的电源。我见过的根集线器似乎都无法支持电源控制。

回答by mixonic

There is a sys entry for this in Linux. From Documentation/usb/power-management.txt:

在 Linux 中有一个 sys 条目。从Documentation/usb/power-management.txt

power/level

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.)

能量等级

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.)

Something like: echo on > /sys/bus/usb/devices/usb5/power/level

就像是: echo on > /sys/bus/usb/devices/usb5/power/level

You may need to play with the autosuspend setting as well. Without telling the kernel to stop trying, it may suspend the port automatically.

您可能还需要使用自动挂起设置。在不告诉内核停止尝试的情况下,它可能会自动挂起端口。

Good luck!

祝你好运!

回答by Ape-inago

I'd be more inclined to cut the wire and hook it up to a serial port w/ some type of simple relay running ofF one of the 'recieve ready'pin. Then you could just pull the line down (signal 'i'm ready to receive') to the serial port file every time there is some isssue. When it's done, just signal 'i'm full'

我更倾向于切断电线并将其连接到带有某种类型的简单继电器的串行端口,该继电器从“接收就绪”引脚之一运行。然后,每次出现问题时,您都可以将线路(信号“我已准备好接收”)拉到串行端口文件中。完成后,只需发出“我已满”的信号

My understanding of those things, however, is that they draw a lot of current until they fully charge the capacitor, then release it all at once to flash the bulb. I can't imagine such a sudden discharge is good for the circuitry of the computer. you may need some diode current traps to prevent feedback into the serial port.

然而,我对这些事情的理解是,它们吸收大量电流,直到将电容器完全充电,然后立即释放所有电流以使灯泡闪光。我无法想象这种突然放电对计算机电路有好处。您可能需要一些二极管电流陷阱来防止反馈到串行端口。

Every time my alarm goes off, the computer shuts down!

每次闹钟响起,电脑就关机!

回答by Hasturkun

In OS X you can access a USB device from user space and request it to suspend.

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

You can find a general example in the USB Device Interface Guide. You will need to use the IOUSBDeviceInterface182(or higher) USBDeviceSuspendmethod.

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

Note: Hubs and controller ports may have ganged power supplies, meaning the same switch is shared by multiple ports. if this is the case and your device is in the same group as another active device, it will not be powered down.

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

回答by Ada?

Your are running just "echo" as root, try:

您正在以 root 身份运行“echo”,请尝试:

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

回答by RVF16

This is an example with a Logitech USB wireless mouse under linux.

这是一个在linux下使用Logitech USB无线鼠标的例子。

Read relevant paragraph of "/proc/bus/usb/devices" according to your devices "Vendor" (vendor id) and "ProdID" (product id) or "Manufacturer" and "Product" (all these values are constant per device).

根据您的设备“供应商”(供应商 ID)和“产品 ID”(产品 ID)或“制造商”和“产品”(所有这些值对于每个设备都是恒定的)阅读“/proc/bus/usb/devices”的相关段落.

cat /proc/bus/usb/devices

(first paragraph with device powered on, second one with same device powered off but still pluged in)

(第一段设备已开机,第二段设备已关闭但仍插入)

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

You need two variables here. They are located in the "T:" line (first line of paragraph). These variables are : Bus (Bus=01 in this example) Cnt (Cnt=01 in this example)

这里需要两个变量。它们位于“T:”行(段落的第一行)。这些变量是: Bus (Bus=01 in this example) Cnt (Cnt=01 in this example)

You will need to add "1" (arithmetic one) to "Cnt" to get the rank Rank=Cnt+1 (this is a mathematical function, Rank=2 in this example)

您需要将“1”(算术一)添加到“Cnt”以获得排名 Rank=Cnt+1(这是一个数学函数,在此示例中为 Rank=2)

So the device you are looking for is the following string : Bus-Rank (this is not a mathematical function, its a string, 1-2 in this example)

因此,您要查找的设备是以下字符串:Bus-Rank(这不是数学函数,它是一个字符串,在此示例中为 1-2)

Mind also the "C:" line. It contains info regarding the power (current) of the device. If there is an asterisk in "C:" (like in our 1st example) then the device is powered. If not ("C:") then the device is "more or less" powered off meaning there is always a tiny current when a device is pluged, otherwise we wouldn't be able to read all this info.

还要注意“C:”行。它包含有关设备功率(电流)的信息。如果“C:”中有星号(如我们的第一个示例),则设备已通电。如果不是(“C:”),则设备“或多或少”断电,这意味着插入设备时总是有微小的电流,否则我们将无法读取所有这些信息。

Mind finaly the "I:" line. If the field "I:*" contains asterisk (like in our 1st example) then there is input, from or to the device, i am not sure, maybe both. The final line field contains the driver used ("usbhid" in our 1st example)

最后记住“我:”行。如果字段“I:*”包含星号(如我们的第一个示例),则有输入,来自设备或设备,我不确定,也许两者都有。最后一行字段包含使用的驱动程序(在我们的第一个示例中为“usbhid”)

We are ready to switch the power of our device :

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

power off

关机

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

power on

打开

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

The following is a simple bash script "USBMS" (USB Mouse Switch) that controls the power of the device in our example above. It is not very dynamical and it uses the "Product" and "Manufacturer" constants to locate the relevant paragraph of "/proc/bus/usb/devices" You should use the "Vendor" (vendor id) and "ProdID" (product id) instead. It also checks the power state of the device. Run as superuser.

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

Command : ./USBMS action

命令:./USBMS 动作

parameter : action = "off" or "0" to power off - action = "on" or "1" to power on (without the quotes)

参数:action = "off" or "0" to power off - action = "on" or "1" to power on (不带引号)

#!/bin/bash

     USBmouseProduct="USB RECEIVER"
USBmouseManufacturer="Logitech"

              signal=

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 }' /proc/bus/usb/devices | awk -F= '{print }')
                                                  usbmbus=$(expr $usbmbus0 + 0)
                                                  usbmdev=$(awk 'NR=='$nr1' {print }' /proc/bus/usb/devices)
                                                 usbmrank=$(awk 'NR=='$nr1' {print }' /proc/bus/usb/devices | awk -F= '{print }')
                                                 usbmrank=$(expr $usbmrank + 1)
                                               usbmbusrank="$usbmbus""-""$usbmrank"
                                                usbmpower=$(awk 'NR=='$nr4' {if ( =="C:" ) {print 0}; if ( =="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
                                             )

回答by Stephen Niedzielski

The usbfs interaction seems to have changed a number of times since this question was originally answered. So, here's how I cycle hub port power on Ubuntu Oneiric Ocelot from a Bash shell.

自从最初回答这个问题以来,usbfs 交互似乎已经改变了很多次。所以,这就是我如何从 Bash shell 在 Ubuntu Oneiric Ocelot 上循环集线器端口电源的方法。

Search for the bus and device number:

搜索总线和设备号:

sudo lsusb -v|less

Locate the device in the bus / hub port hierarchy using the bus and device number:

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

sudo lsusb -t|less

The syntax seems to be 'bus-port.port.port.port.port...' For example, my mouse is connected to an external hub which connects to my computer's hub which internally connects to a root hub:

语法似乎是 '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

So, '2-1.1.1' in the above case. Finally, cycle the port power:

因此,在上述情况下为 '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

I haven't hooked up a protocol analyzer to see what's actually happening on the bus, but I know my mouse light turns off when I unbind it. I'm guessing at a lower layer this is interacting with the EHCI host controller to actually shut power off on the port. This is particularly useful for embedded devices, such as a UVC webcams, which never seem to function properly and would otherwise require a system reboot to reset.

我还没有连接协议分析器来查看总线上实际发生的情况,但我知道当我解除绑定时,我的鼠标灯会关闭。我猜测在较低层,这是与 EHCI 主机控制器交互以实际关闭端口电源。这对于嵌入式设备特别有用,例如 UVC 网络摄像头,它们似乎永远不会正常工作,否则需要重新启动系统才能重置。

See also the udevadmcommand.

另请参阅udevadm命令。

回答by Stephen Niedzielski

@Kristian Typically you won't find software controlled port power controlled advertised because users shouldn't be conscious of this layer. I don't think there's many use cases for it other than to force misbehaving bus powered devices into a known state, and handle dumb as a post devices that only use USB for power. Perhaps Mark's device falls into the latter category. It's a crude, last resort mechanism.

@Kristian 通常,您不会发现广告中的软件控制端口功率控制,因为用户不应该意识到这一层。我不认为它有很多用例,除了强制行为不端的总线供电设备进入已知状态,并将哑巴作为仅使用 USB 供电的后置设备处理。也许马克的设备属于后一类。这是一种粗糙的、不得已的机制。

As I mentioned, I haven't looked into the implementation details for the unbinding hack and I've only tried it on the EHCI host controller embedded in my motherboard, an "Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller (rev 05)." I would guess that this host controller has the PPC bit of HCSPARAMS set, indicating software control of port power switches, per EHCI spec.

正如我所提到的,我还没有研究解除绑定黑客的实现细节,我只在我的主板中嵌入的 EHCI 主机控制器上进行了尝试,“英特尔公司 6 系列/C200 系列芯片组系列 USB 增强型主机控制器(修订版 05)。” 我猜想这个主机控制器设置了 HCSPARAMS 的 PPC 位,指示端口电源开关的软件控制,根据 EHCI 规范。

If you're interfacing with an external hub, "a hub indicates whether or not it supports power switching by the setting of the Logical Power Switching Mode field in wHubCharacteristics," according to the USB 2.0 spec. I don't rememeber if the compliance tests ensure this functionality or not, but if they do, you'd need only find a hub with the USB 2.0 logo. I speculate the hack would send a set port feature request, but it may cycle more than just the target port. Again, per USB 2.0 spec, "a hub with power switches can switch power to all ports as a group/ gang, to each port individually, or have an arbitrary number of gangs of one or more ports." I'm not sure if there's a nice command line tool to get wHubCharacteristics.

如果您与外部集线器接口,“集线器通过设置 wHubCharacteristics 中的逻辑电源切换模式字段来指示它是否支持电源切换,”根据 USB 2.0 规范。我不记得合规性测试是否确保了此功能,但如果确实如此,您只需要找到带有 USB 2.0 徽标的集线器即可。我推测黑客会发送一个设置端口功能请求,但它可能不仅仅是目标端口。同样,根据 USB 2.0 规范,“带有电源开关的集线器可以将电源作为一组/组切换到所有端口,单独切换到每个端口,或者具有任意数量的一个或多个端口组。” 我不确定是否有一个不错的命令行工具来获取 wHubCharacteristics。

In short, there's not a great generic way to handle this problem, as far as I know. However, it is possible to interrogate an internal or external hub to determine its level of support and then, if supported, use it. It's just a question of how much time you want to spend doing so.

简而言之,据我所知,没有一个很好的通用方法来处理这个问题。但是,可以询问内部或外部集线器以确定其支持级别,然后在支持时使用它。这只是你想花多少时间这样做的问题。

回答by ptonelli

A few usb hubscan switch their ports on and off, as explained in the link. I have yet to find a motherboard with usb ports which can be enabled or disabled.

一个小USB集线器可以打开和关闭的端口,如链接解释。我还没有找到带有可以启用或禁用的 USB 端口的主板。

回答by ptonelli

power/level

"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 separaely by the power/wakeup attribute.)

能量等级

“on”表示应该恢复设备,不允许自动挂起。(当然,系统挂起仍然是允许的。)

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

“挂起”表示设备应保持挂起状态,不允许自动恢复。(但仍然允许远程唤醒,因为它是由 power/wakeup 属性单独控制的。)

Step 1:so i have, usb1, usb2, usb3, usb4 ....

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

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

Step 2:how would i know which one is which? (

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

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

Optional 1:in case the lsusb shows and need to find specific one

Optional 1:如果 lsusb 显示并需要找到特定的

#!/bin/bash
usb="046d:082d" # Find ME, Replace the ID 

cam=$(lsusb | awk "/$usb/ {print }")
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

Optional 2:in case none found - reboot fails to power cycle use Arduino relay over udp

可选 2:如果没有找到 - 重启无法通过 udp 使用 Arduino 中继重新启动

#!/bin/bash

file="/var/www/html/video/now.jpeg"

function age() {
   local filename=
   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 relay:

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);
}