Linux USB: turning the power on and off?

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!

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.


Solution 1:

There is a sys entry for this in Linux. From 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.)

Something like: 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!

Solution 2:

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.

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 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:

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.

See also the udevadm command.