Controlling a USB power supply (on/off) with Linux
Asked Answered
N

11

201

Is it possible to turn on/off power supplies from USB manually with Linux?

There's this external USB cooling fan (the kind you use to cool yourself off, not the PC), and it would be nice to be able to control it from the terminal, because I want to position the fan somewhere far away.

I suppose this could also be useful for a variety of other things as well, because there's a lot of USB toys out there. Maybe air purifiers, etc. (I heard they don't really work though).

Nectareous answered 15/1, 2011 at 21:19 Comment(6)
Let me recap for Linux >= 2.6.38: The file power/level is deprecated now; use power/control instead. (power/wakeup is ok.) Furthermore, it accepts only "auto" and "on", not "suspend" any more. "auto" is smart enough, and if the power isn't turned off while idle, it's the device's fault. Anyway you can't turn the power off manually. For more, see the answer below by tlwhitec and the kernel's doc: kernel.org/doc/Documentation/usb/power-management.txtYb
Possible duplicate of https://mcmap.net/q/129625/-linux-usb-turning-the-power-on-and-off/1967396Expertize
This feature really deserves a good GUIHeadphone
Does it require any special hardware? It is not quite clear from answers,Giselegisella
@VojtěchDohnal See unix.stackexchange.com/a/321945/111181Borlow
If the fan has is a usb client then you could activate/deactivate it over USB. Otherwise USB pin power is always on, unless it is connected to a 'smart hub'.Recoverable
C
66

Note. The information in this answer is relevant for the older kernels (up to 2.6.32). See tlwhitec's answer for the information on the newer kernels.

# disable external wake-up; do this only once
echo disabled > /sys/bus/usb/devices/usb1/power/wakeup 

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

(You may need to change usb1 to usb n)

Source: Documentation/usb/power-management.txt.gz

Culture answered 15/1, 2011 at 21:42 Comment(12)
Whoa, thanks for that. I was thinking I had to go through libUSB no matter what. Any idea how to get the names of the attached devices as well?Nectareous
According to this post, without special hardware it isn't possible? blog.andrew.net.au/2009/01/17Cheesewood
I'm getting permission denied error even if I use sudo!Daft
This disables the usb port, but typically that will not stop power flowing to it.Terrance
same for me " permission denied" even after using sudoKries
The permission is denied because a command in the form of sudo foo > bar is parsed as direct the output to bar, then run foo using sudo. The redirection fails because it happens before you get root access. The solution is to use sudo sh -c 'echo disabled > /sys/bus/usb/devices/usb1/power/wakeup', and so on: gain root, run a new hell to perform a redirect, then output something into the redirected file descriptor.Pinna
On Ubuntu 15.04, kernel 3.19.0-28-generic, echo 'auto' turned the power off. 'echo suspend' gave 'write error: Invalid argument'. echo disabled to wakeup worked. I'm able to cycle power on and off. My device directory was also more involved. '/sys/bus/usb/devices/usb1/1-13/power/(wakeup|level). For example, ftdi is found from /sys/bus/usb/drivers/ftdi_sio/(1-13:1.0)Alsacelorraine
Sorry if I'm raising the dead here, but when I run echo suspend > /sys/bus/usb/devices/usb1/power/level in a root shell (bash), I am given an error message: bash: echo: write error: Invalid argument. Not sure what this means exactly... Any ideas?Sanitarian
@Sanitarian suspend also doesn't work for me either - while value auto and autosuspend_delay_ms seems to be responsible for disconnects due to power-saving. unix.stackexchange.com/a/166601/110101Exhibitionism
Why should wake up be disabled?Flowerage
@Pinna "Run a new hell" made me ROTFL ;-)Vibrate
sudo sh -c 'echo disabled > /sys/bus/usb/devices/usb1/power/wakeup' sh: 1: cannot create /sys/bus/usb/devices/usb1/power/wakeup: Read-only file systemDodgson
H
71

According to the docs, there were several changes to the USB power management from kernels 2.6.32, which seem to settle in 2.6.38. Now you'll need to wait for the device to become idle, which is governed by the particular device driver. The driver needs to support it, otherwise the device will never reach this state. Unluckily, now the user has no chance to force this. However, if you're lucky and your device can become idle, then to turn this off you need to:

echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend"
echo "auto" > "/sys/bus/usb/devices/usbX/power/level"

or, for kernels around 2.6.38 and above:

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

This literally means, go suspend at the moment the device becomes idle.

So unless your fan is something "intelligent" that can be seen as a device and controlled by a driver, you probably won't have much luck on current kernels.

Hb answered 1/10, 2012 at 14:56 Comment(9)
It seems this will cause the USB device to continuously get powered off...(?) How should power be resumed by me, after this worked? My goal is to restart the device once, not to permanently change its suspension configuration.Sac
To resume a suspended device, you can disable again the "autosuspend" with echo "on" > "/sys/bus/usb/devices/usbX/power/control", but I think you need to understand the original purpose. The autosuspend feature is here merely to enable idling devices to enter a low-power state (where it might appear turned off), only to be resumed later when it's needed, either by the host or some external event. That happens (or should happen) automatically. The port itself is actually never truly turned off. Really, do read the docs ;)Hb
I can confirm it works with kernels > 3.10. Just have to be sure that the device "id" you are using is correct : dmesg | grep "usb" and use the number after "usb", for example: usb 2-4.4: SerialNumber: A0848020 you will use: /sys/bus/usb/devices/2-4.4/power/.... Also, be sure that the device is not in use. I created a script to simplify this processShed
Is there a way to save this configuration so that each time it's plugged in it won't change back to defaults? I have a device that I need to set power control to "on" in order for it to charge.Pyretotherapy
@Pyretotherapy sounds like an udev rule to me.Hb
It seems that udev has now been either deprecated or subsumed by systemd. The OP's question here is now almost 10 years old, and in that time, the solutions all seem to be "hit-or-miss" - sometimes they work, sometimes they don't. Why? At least part of the issue seems to be that the term "USB Standard" is an oxymoron.Course
@Seamus I think udev is not going anywhere. The wiki article only covers firmware loading. Not that I'd watch what's happening around it, by I haven't heard of it having any substitute. As far as I can tell using udev on the latest Fedora is definitely still a thing.Hb
@Shed Does it work under VirtualBox? It looks like it does not. Is there a way to make it work under VirtualBox?Dominions
@Dominions I can confirm your findings. I doubt power can be controlled under VirtualBox as harware is emulated (specially USB has special configuration under VirtualBox). You should create a separate question for that. Sorry I'm not that helpful.Shed
C
66

Note. The information in this answer is relevant for the older kernels (up to 2.6.32). See tlwhitec's answer for the information on the newer kernels.

# disable external wake-up; do this only once
echo disabled > /sys/bus/usb/devices/usb1/power/wakeup 

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

(You may need to change usb1 to usb n)

Source: Documentation/usb/power-management.txt.gz

Culture answered 15/1, 2011 at 21:42 Comment(12)
Whoa, thanks for that. I was thinking I had to go through libUSB no matter what. Any idea how to get the names of the attached devices as well?Nectareous
According to this post, without special hardware it isn't possible? blog.andrew.net.au/2009/01/17Cheesewood
I'm getting permission denied error even if I use sudo!Daft
This disables the usb port, but typically that will not stop power flowing to it.Terrance
same for me " permission denied" even after using sudoKries
The permission is denied because a command in the form of sudo foo > bar is parsed as direct the output to bar, then run foo using sudo. The redirection fails because it happens before you get root access. The solution is to use sudo sh -c 'echo disabled > /sys/bus/usb/devices/usb1/power/wakeup', and so on: gain root, run a new hell to perform a redirect, then output something into the redirected file descriptor.Pinna
On Ubuntu 15.04, kernel 3.19.0-28-generic, echo 'auto' turned the power off. 'echo suspend' gave 'write error: Invalid argument'. echo disabled to wakeup worked. I'm able to cycle power on and off. My device directory was also more involved. '/sys/bus/usb/devices/usb1/1-13/power/(wakeup|level). For example, ftdi is found from /sys/bus/usb/drivers/ftdi_sio/(1-13:1.0)Alsacelorraine
Sorry if I'm raising the dead here, but when I run echo suspend > /sys/bus/usb/devices/usb1/power/level in a root shell (bash), I am given an error message: bash: echo: write error: Invalid argument. Not sure what this means exactly... Any ideas?Sanitarian
@Sanitarian suspend also doesn't work for me either - while value auto and autosuspend_delay_ms seems to be responsible for disconnects due to power-saving. unix.stackexchange.com/a/166601/110101Exhibitionism
Why should wake up be disabled?Flowerage
@Pinna "Run a new hell" made me ROTFL ;-)Vibrate
sudo sh -c 'echo disabled > /sys/bus/usb/devices/usb1/power/wakeup' sh: 1: cannot create /sys/bus/usb/devices/usb1/power/wakeup: Read-only file systemDodgson
R
43

PowerTOP from Intel allows you to toggle devices such as usb peripherals in real-time. These are called 'tunables'.

sudo apt install powertop
sudo powertop
  • Tab over to 'tunables'.
  • Scroll down to your device.
  • Hit enter to toggle power saving mode (Good/Bad)

enter image description here

Note that Bad means the device is always on. Toggling to Good will turn off the device after the preset inactive saving time (default is 2000ms).

See the PowerTOP docs for details on how to make these changes permanent.
It generates the config scripts for you (pretty much as described by other posters on this thread).

NOTE: These scripts do not affect USB pin power (which is always on).
These only send the driver protocol to activate and deactivate a device.

If you want to control pin power, you could use either a supported smart USB hub, or better yet a microcontroller.

Recoverable answered 6/5, 2016 at 5:54 Comment(3)
Awesome! :D I think this is the userfriendliest way to do it (although on low level it makes the same operations as outlined in the other answers.) Thank you, and may your answer reach the top ;)Chinkiang
Thanks for your answer. Where do I have to start digging to change the preset inactive saving time?Booking
As mentioned by previous posters, kernel docs are here: kernel.org/doc/Documentation/usb/power-management.txtRecoverable
E
35

I have found these solutions that at least work for properly configured Terminus FE 1.1 USB hub chip:

1.To turn off power on all USB ports of a hub, you may unbind the hub from kernel using:

echo "1-4.4.4" > /sys/bus/usb/drivers/usb/unbind

to turn power back on - you may bind it back using

echo "1-4.4.4" > /sys/bus/usb/drivers/usb/bind

2.Switching power at each port individually is trickier: I was able to use hubpower to control each port - but it comes with a downside: hubpower first disconnects the usbdevfs wich causes all of the USB devices to disconect from system, at least on ubuntu:

usb_ioctl.ioctl_code = USBDEVFS_DISCONNECT;
rc = ioctl(fd, USBDEVFS_IOCTL, &usb_ioctl);

With this ioctl disabled I was able to switch off individual port power without detaching all devices - but the power goes back on immediately (probably due to kernel seeing an uninitialized device) which causes USB device just to do a "cold restart" which is what I generally wanted to do. My patched hubpower is here

Erotica answered 7/8, 2013 at 8:12 Comment(5)
The bind/unbind entries are confirmed to work on linux kernel 2.6.34, the ICH8 chipset, and Ubuntu 10.04.Oceanid
bind/unbind doesn't poweroff the USB port regardless the chipset. The device still gets power...Israelite
mouse laser is off, keyboard cant type, modem stops blinking - all good on my platformFolium
@Erotica does this still work? I get segfaultOw
Devices will continue to get power, regardless of what you're doing. But, it permits doing a cold reboot indeed. I've coded a script that automatises this at github.com/netinvent/usb_resetter and works great to reset poorly created devicesShowery
M
25

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

Marcheshvan answered 8/11, 2016 at 20:0 Comment(6)
fine tool on osx, but doesnt find any 'supported smart hub' on debian for me.Counterstatement
On Linux, you need to either run it as root (under sudo), or to configure udev device permissions. It's also possible that your Linux host doesn't have compatible hubs connected.Marcheshvan
it's a 'beagle bone green' btw.Counterstatement
I tried this on my computer's hub and the program show power is off for the port, but a LED of the connected device is still on. So apparently there is some power in the port anyway. (Version 2.1.0)Borlow
@jarno, many USB hub manufacturers save few cents on adding power switches. This is why I am maintaining list of all hubs that actually do work properly at github.com/mvp/uhubctlMarcheshvan
Works like a charm on Beaglebone Black.Vertex
E
9
echo '2-1' |sudo tee /sys/bus/usb/drivers/usb/unbind

works for ubuntu

Equipoise answered 12/4, 2014 at 16:46 Comment(3)
YOURS IS THE ONLY SOLUTION THAT WORKED ON MY CASE. I am using an acer make laptop 12.04LTS Ubuntu.Sungod
Doesn't poweroff the device, only removes it from the device list. How can I poweroff the USB port?August
This is also the only solution that worked for me for powering off a Wacom Intuos5 touch M tablet without unplugging it (on Fedora 28)Tomasatomasina
M
7

I wanted to do this, and with my USB hardware I couldn't. I wrote a hacky way how to do it here:

http://pintant.cat/2012/05/12/power-off-usb-device/ .

In a short way: I used a USB relay to open/close the VCC of another USB cable...

Matthiew answered 20/5, 2012 at 10:25 Comment(0)
A
6

The reason why folks post questions such as this is due to the dreaded- indeed "EVIL"- USB Auto-Suspend "feature".

Auto suspend winds-down the power to an "idle" USB device and unless the device's driver supports this feature correctly, the device can become uncontactable. So powering a USB port on/off is a symptom of the problem, not the problem in itself.

I'll show you how to GLOBALLY disable auto-suspend, negating the need to manually toggle the USB ports on & off:

Short Answer:

You do NOT need to edit "autosuspend_delay_ms" individually: USB autosuspend can be disabled globally and PERSISTENTLY using the following commands:

sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/&usbcore.autosuspend=-1 /' /etc/default/grub

update-grub

systemctl reboot

An Ubuntu 18.04 screen-grab follows at the end of the "Long Answer" illustrating how my results were achieved.

Long Answer:

It's true that the USB Power Management Kernel Documentation states autosuspend is to be deprecated and in in its' place "autosuspend_delay_ms" used to disable USB autosuspend:

"In 2.6.38 the "autosuspend" file will be deprecated
and replaced by the "autosuspend_delay_ms" file."

HOWEVER my testing reveals that setting usbcore.autosuspend=-1 in /etc/default/grub as below can be used as a GLOBAL toggle for USB autosuspend functionality- you do NOT need to edit individual "autosuspend_delay_ms" files.

The same document linked above states a value of "0" is ENABLED and a negative value is DISABLED:

power/autosuspend_delay_ms

    <snip> 0 means to autosuspend
    as soon as the device becomes idle, and negative
    values mean never to autosuspend.  You can write a
    number to the file to change the autosuspend
    idle-delay time.

In the annotated Ubuntu 18.04 screen-grab below illustrating how my results were achieved (and reproducible), please remark the default is "0" (enabled) in autosuspend_delay_ms.

Then note that after ONLY setting usbcore.autosuspend=-1 in Grub, these values are now negative (disabled) after reboot. This will save me the bother of editing individual values and can now script disabling USB autosuspend.

screengrab: autosuspend values Before and after globally editing

Hope this makes disabling USB autosuspend a little easier and more scriptable-

Athalee answered 2/8, 2019 at 13:33 Comment(0)
C
3

I had a problem when connecting my android phone, I couldn't charge my phone because the power switch on and then off ... PowerTop let me find this setting and was useful to fix the issue ( auto value was causing issue):

echo 'on' | sudo tee /sys/bus/usb/devices/1-1/power/control
Cairo answered 17/7, 2017 at 8:51 Comment(0)
C
1

USB 5v power is always on (even when the computer is turned off, on some computers and on some ports.) You will probably need to program an Arduino with some sort of switch, and control it via Serial library from USB plugged in to the computer.

In other words, a combination of this switch tutorial and this tutorial on communicating via Serial libary to Arduino plugged in via USB.

Cheesewood answered 24/11, 2016 at 2:55 Comment(1)
On nearly all hardware, the power to the USB host port is supplied via a current-limited power switch IC (e.g. Texas Instruments TPS2001D). It's pretty common for these switches to be controllable from software. So long as both the hardware, and the USB host controller device driver includes support for the hardware, then it can be controlled from software.Cuticle
S
0

So far I came to the conclusion that you cannot control the power of a USB port. The 5V USB is always provided, and it's up to the device to use it or not. You can check this with a 5V fan or light. I've tried various methods (disconnect/reconnect/bind/unbind/reset signal). Best so far are bind/unbind as it forces a cold restart of the device (but no power cycle).

I came up with a solution to reset USB devices, ports and controllers in a python script, which supports all of the above methods. You can find the script at my Github page

Install with:

pip install usb_resetter

Usage:

usb_resetter -l  # List devices
usb_resetter -d 8086:1001 --reset-hub  # Reset hub where 8086:1001 is attached

The script uses among others the following solution to reset USB hubs/controllers:

Unbindind a USB port / controller works best via:

echo "myhub" > "/sys/bus/usb/drivers/usb/unbind"
echo "myhub" > "/sys/bus/usb/drivers/usb/bind"

Where myhub is found in /sys/bus/usb/devices/*

Or litteral controllers:

echo "mycontroller" > "/sys/bus/pci/drivers/unbind"
echo "mycontroller" > "/sys/bus/pci/drivers/bind"

Where mycontroller is found in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*

Showery answered 28/10, 2022 at 9:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.