Turning off power to usb port. Or turn off power to entire usb subsystem

120,180

Solution 1

You could use my tool uhubctl - command line utility to control USB power per port for compatible USB hubs.

It works only on hubs that support per-port power switching, but note that many modern motherboards have USB hubs that support this feature.

First off, your OS may already have uhubctl present in package repositories, refer to README for how to install it, but make sure you use most recent version (2.4.0 as of this writing).

If your OS does not have recent version of this package, you can install it from source as follows:

To compile:

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

To install system-wide as /usr/sbin/uhubctl:

sudo make install

To list status of all hubs, their locations and ports that can be controlled by uhubctl:

sudo uhubctl

(you can avoid using sudo if you configure udev USB permissions).

To turn off power on port 5 of single compatible hub:

sudo uhubctl -a 0 -p 5

If you have more than one compatible hub connected, use -l to specify hub location to control it:

sudo uhubctl -a 0 -p 5 -l 3-1.2

To toggle power off then on:

sudo uhubctl -a 2 -p 5

Note that USB 3.0 hubs are also supported, and quite a few new USB 3.0 hubs actually work well.

Read more here.

Solution 2

See Controlling a USB power supply (on/off) with linux, short version, for newer kernels "suspend" does not work anymore:

echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend_delay_ms"
echo "auto" > "/sys/bus/usb/devices/usbX/power/control"

But it doesn't literally cut the power: it signals the device to poweroff, and it's up to the device to implement power management and do the right thing.

You have a lot of details in the official documentation in the kernel, there it explains the various files in /sys/bus/usb/devices/.../power/ and how to manage the devices and ports.

For things that are not real USB devices (does your USB lamp show up in lsusb?) you might be out of luck, I have tried myself with an usb lamp and with a GPS logger that charges its battery and transfers data through USB that shows up as a cp210x USB-to-serial, and neither does poweroff. I can "disconnect" the GPS with echo '5-4.6' > /sys/bus/usb/drivers/usb/unbind and reconnect it with echo '5-4.6' > /sys/bus/usb/drivers/usb/bind but the battery charging light is always on.

But it seems that some hubs do it properly.

Share:
120,180

Related videos on Youtube

balasaheb barde
Author by

balasaheb barde

Updated on September 18, 2022

Comments

  • balasaheb barde
    balasaheb barde over 1 year

    I have a usb lamp which I specifically bought in order to turn it off programmatically at a certain time, thus I need to remove the power to its usb port.

    I believe I have a usb-hub at usb6. The lamp is connected to one of the ports in this hub:

    #myhost$ lsusb 
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 008 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    ...
    ...
    Bus 008 Device 006: ID 050d:0234 Belkin Components F5U234 USB 2.0 4-Port Hub
    

    Here's what I've tried:

    Two solutions are here, the first suggests:

    echo disabled > /sys/bus/usb/devices/usb1/power/wakeup 
    echo suspend > /sys/bus/usb/devices/usb1/power/level  # turn off
    

    but I get write error: Invalid argument when trying to write to /sys/bus/usb/devices/usb1/power/level:

    $sudo bash -c 'echo disabled > /sys/bus/usb/devices/usb6/power/wakeup'
    $echo suspend|sudo tee /sys/bus/usb/devices/usb6/power/level suspend
    tee: /sys/bus/usb/devices/usb6/power/level: Invalid argument
    $sudo bash -c 'echo suspend> /sys/bus/usb/devices/usb6/power/level'bash: line 0: echo: write error: Invalid argument
    

    The second solution:

    sudo bash -c 'echo 0 > /sys/bus/usb/devices/usb6/power/autosuspend_delay_ms; echo auto > /sys/bus/usb/devices/usb6/power/control'
    

    which does turn off power to the usb-hub device.

    I was also trying to follow this:

    But the output of lsusb -t just hangs:

    $lsusb -t
    4-1:0.0: No such file or directory
    4-1:0.1: No such file or directory
    ^C
    

    Which prevents me from using this method to get the '2-1.1' part to this:

    echo '2-1.1' > /sys/bus/usb/drivers/usb/unbind
    

    Is there an alternative way of getting this information?

    Alternatively, is there a way to shut off power to the entire usb subsystem? Something like modprobe -r usb_etc?

    My kernel is:

    $uname -r
    3.2.0-4-amd64
    
  • Zachary Brady
    Zachary Brady over 7 years
    A little more information would be nice. Especially because you're the author and it's not a standard package examples of how to use it, what if any capabilities/limitations it has, risks if any, Link only answers are not preferred.
  • mvp
    mvp over 7 years
    Well, copy/pasting whole README file doesn't seem like bright idea to me. It has all caveats explained.
  • Zachary Brady
    Zachary Brady over 7 years
    No, the whole readme would be excessive. Just how you can use the program to solve the problem posed in the question. And if there are any caveats to that particular use case, not the whole application. Sorry if I wasn't clear in my first comment.
  • Admin
    Admin over 6 years
    FYI: This method does work for the Renesas UPD720202 family of PCIe-USB host controllers. :) Thanks.
  • mvp
    mvp over 6 years
    Thanks @Wossname. Do you mind adding it as new issue at github.com/mvp/uhubctl/issues ? I will update supported devices list.
  • Unknown123
    Unknown123 almost 4 years
    How do you turn it on/off using device and product id? For example sudo uhubctl -a 1 0bda:a811?
  • mvp
    mvp almost 4 years
    uhubctl -n 0bda:a811 -a 1
  • mallwright
    mallwright about 3 years
    @mvp I think one thing that would improve this answer is to briefly explain the underlying API or mechanism that this program is using to switch ports on/off. I also couldn't clearly see this information in the README on Github.
  • Cheetaiean
    Cheetaiean almost 3 years
    This answer is about disabling autosuspend. However, the question is how to turn on autosuspend, or more precisely, how to power off USB devices.
  • Throw Away Account
    Throw Away Account over 2 years
    How does the 3-1.2 notation translate into the bus/port notation used in the output of lsusb -t?
  • mvp
    mvp over 2 years
    It does not directly. Hub locations look like b-x.y.z, where b is USB bus number, and x, y, z... are port numbers for all hubs in chain, starting from root hub for a given USB bus. This address is semi-stable - it will not change if you unplug/replug (or turn off/on) USB device into the same physical USB port