Home

Awesome

uhubctl

uhubctl is utility to control USB power per-port on smart USB hubs. Smart hub is defined as one that implements per-port power switching.

Original idea for this code was inspired by hub-ctrl.c by Niibe Yutaka: https://www.gniibe.org/development/ac-power-control-by-USB-hub

Compatible USB hubs

Note that very few hubs actually support per-port power switching. Some of them are no longer manufactured and can be hard to find.

This is list of known compatible USB hubs:

ManufacturerProductPortsUSBVID:PIDReleaseEOL
AcerBE270U monitor (see)43.02109:28112016
AmazonBasicsHU3641V1 (RPi issue)43.02109:28112013
AmazonBasicsHU3770V1 (RPi issue)73.02109:28112013
AmazonBasicsHU9003V1EBL, HUC9003V1EBL73.12109:28172018
AmazonBasicsHU9002V1SBL, HU9002V1EBL, HU9002V1ESL (note)103.12109:28172018
AmazonBasicsHUC9002V1SBL, HUC9002V1EBL, HUC9002V1ESL103.12109:28172018
AmazonBasicsU3-7HUB (only works for 1 charge port)73.02109:28132020
AnkerAK-68ANHUB-BV7A-0004 (note)73.02109:08122014
ApplePro Display XDR MWPE2LL/A (internal USB hub)42.005AC:91392019
AppleThunderbolt Display 27" (internal USB hub)62.020112016
AppleUSB Keyboard With Numeric Pad (internal USB hub)32.02011
AsusZ77 Sabertooth Motherboard (onboard USB hub)62.02012
AsusZ87-PLUS Motherboard (onboard USB hub)43.020132016
AukeyCB-C5943.02109:28132017
B+B SmartWorxUHR20442.00856:DB002013
B+B SmartWorxUSH30443.004B4:650620172019
Basler200003623443.00451:80462016
BelkinF5U10142.00451:204620052010
BelkinF5U238UKCRL-MOB42.00409:005920042010
BenQPD2700U 4K Monitor (works only in USB2 mode)43.005E3:06102018
BenQPD3220U43.105E3:06102019
ByteccBT-UH340 (warning)43.02109:81102010
CentechCT-USB4HUB ReTRY HUB43.00424:27442017
CircuitcoBeagleboard-xM (internal USB hub)42.00424:95142010
Club3DCSV-3242HD Dual Display Docking Station43.02109:28112015
CoolgearUSBG-12U2ML122.005e3:06072015
CypressCY4608 HX2VL devkit (note)42.004B4:65702012
D-LinkDUB-H4 rev D,E (black). Note: rev A,C,F not supported42.005E3:06082012
D-LinkDUB-H7 rev A (silver)72.02001:F10320052010
D-LinkDUB-H7 rev D,E (black). Rev B,C,F,G not supported72.005E3:06082012
DellP2416D 24" QHD Monitor (note)42.02017
DellS2719DGF 27" WQHD Gaming-Monitor53.00424:57342018
DellUltraSharp 1704FPT 17" LCD Monitor42.00424:A70020052015
DellUltraSharp U2415 24" LCD Monitor53.02014
DellUltraSharp U3419W 34" Curved Monitor63.02020
DellWyse 3040 (-f required)63.02017
Delock6253743.020172021
Delock87445 (note)42.005E3:060820092013
ElecomU2H-G4S42.020062011
GigabyteG27Q monitor (see43.02109:08172020
GlobalScaleESPRESSObin SBUD102 V513.01D6B:00032017
HardkernelODROID-C4 (note)43.02020
Hawking TechnologyUH21442.020032008
Hewlett PackardUSB-C Dock G5 5TW10AA53.003F0:076B2019
Hewlett PackardP5Q58UT33.02019
InateckHB2025A (USB2 only)43.12109:28222021
IOIU3H415E143.02012
j5createJUH377 (note)73.02016
j5createJUH470 (note)33.005E3:06102014
Juiced Systems6HUB-0173.00BDA:041120142018
KUNBUS GmbHRevPi Connect (+) / S / SE22.00424:95142018
KUNBUS GmbHRevPi Connect 423.02022
KUNBUS GmbHRevPi Core 3 / S / SE22.00424:95142017
LG Electronics27MD5KL-B monitor43.0043E:9A602019
LG Electronics27GL850-B monitor43.00451:81422019
LG Electronics27UK850-W monitor23.02018
LG Electronics27UN83A-W monitor23.00451:81422020
LG Electronics38WK95C-W monitor43.00451:81422018
LenovoThinkPad Ultra Docking Station (40A20090EU)62.017EF:100F2015
LenovoThinkPad Ultra Docking Station (40AJ0135EU)73.117EF:30702018
LenovoThinkPad X200 Ultrabase 42X496332.017EF:100520082011
LenovoThinkPad X6 Ultrabase 42W310742.017EF:100020062009
LenovoThinkPlus 4-in-1 USB-C hub 4X90W8649733.02021
LenovoThinkVision T24i-10 Monitor42.017EF:06102018
LenovoUSB-C to 4 Port USB-A Hub42.017EF:103A2020
LindyUSB serial converter 4 port41.1058F:92542008
LinksysUSB2HUB4 (note)42.020042010
MaplinA08CQ72.00409:005920082011
MetadotDas Keyboard 423.02014
MicrochipEVB951222.02009
MicrochipEVB-USB251772.02008
MicrochipEVB-USB2534BC42.02013
MicrochipEVB-USB580773.02016
MoxaUport-40772.0110A:04072009
NVidiaJetson Nano B01 (details)43.02019
NVidiaJetson Xavier NX (details)43.02020
PhidgetsHUB0003_072.01A40:02012017
Philips346B1C UltraWide 34" Curved Monitor43.005E3:06102019
PlugableUSB3-HUB7BC73.02109:08132015
PlugableUSB3-HUB7C (only works for 2 charge ports)73.02109:08132015
PlugableUSBC-HUB7BC (works for 6/7 ports, not the rightmost)73.02109:08172021
PlugableUSB3-HUB10-C2 (only works for 2 charge ports)103.02014
Port IncNWUSB0141.10451:144619992003
Raspberry PiB+, 2B, 3B (see below)42.02011
Raspberry Pi3B+ (see below)42.00424:25142018
Raspberry Pi4B (see below)43.02109:34312019
Raspberry Pi5 (see below)43.01d6b:00022023
RenesasuPD720202 PCIe USB 3.0 host controller23.02013
RosewillRHUB-21042.00409:005A20112014
RosonwayRSH-518C (note)73.02109:08172021
RosonwayRSH-A10 (see)103.00bda:04112020
RosonwayRSH-A13 (warning)133.12109:28222021
RosonwayRSH-A16 (note, warning)163.00bda:04112020
RosonwayRSH-A104 (USB2 only)43.12109:28222022
RosonwayRSH-A107 (aka ikuai A107-5)73.10bda:54112022
RosonwayRSH-ST07C (only 4)73.02109:28222023
Sanwa SupplyUSB-HUB14GPH41.120012003
SeagateBackup Plus Hub STEL800010023.00BC2:AB442016
Seeed StudioreTerminal CM410403222.00424:25142021
StarTechHB30A4AIB (warning)43.02109:28172018
SunixSHB4200MA42.00409:005820062009
System TalksSugoi USB2-HUB4X42.02007
TargusPA095UZ22.02004
TargusPAUH212/PAUH212U72.020042009
Texas InstrumentsTUSB4041PAPEVM42.10451:81422015
UUGearMEGA4 (for Raspberry Pi 4B)43.02109:08172021
VirtualHereUSB3 4-port hub (note)43.02024

This table is by no means complete. If your hub works with uhubctl, but is not listed above, please report it by opening new issue at https://github.com/mvp/uhubctl/issues, so we can add it to supported table. In your report, please provide exact product model and add output from uhubctl and please test VBUS off support as described below in FAQ.

Note that quite a few modern motherboards have built-in root hubs that do support this feature - you may not even need to buy any external hub.

USB 3.0 duality note

If you have USB 3.0 hub connected to USB3 upstream port, it will be detected as 2 independent virtual hubs: USB2 and USB3, and your USB devices will be connected to USB2 or USB3 virtual hub depending on their capabilities and connection speed. To control power for such hubs, it is necessary to turn off/on power on both USB2 and USB3 virtual hubs for power off/on changes to take effect. uhubctl will try to do this automatically (unless you disable this behavior with option -e).

Unfortunately, while most hubs will cut off data USB connection, some may still not cut off VBUS to port, which means connected phone may still continue to charge from port that is powered off by uhubctl.

Compiling

This utility was tested to compile and work on Linux (Ubuntu/Debian, Redhat/Fedora/CentOS, Arch Linux, Gentoo, openSUSE, Buildroot), FreeBSD, NetBSD, SunOS and MacOS.

While uhubctl compiles on Windows, USB power switching does not work on Windows because libusb is using winusb.sys driver, which according to Microsoft does not support necessary USB control requests. This may be fixed if libusb starts supporting different driver on Windows.

Note that it is highly recommended to have pkg-config installed (many platforms provide it by default).

First, you need to install library libusb-1.0 (version 1.0.12 or later, 1.0.16 or later is recommended):

To fetch uhubctl source and compile it:

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

This should generate uhubctl binary. You can install it in your system as /usr/sbin/uhubctl using:

sudo make install

Note that on some OS (e.g. FreeBSD/NetBSD) you need to use gmake instead to build.

Also, on MacOS you can install uhubctl with all necessary dependencies in one shot using Homebrew tap:

brew tap mvp/uhubctl https://github.com/mvp/uhubctl
brew install uhubctl

To build/install from master branch, use --HEAD:

brew install uhubctl --HEAD

Usage

:warning: On Linux, use sudo or configure USB permissions as described below!

To list all supported hubs:

uhubctl

You can control the power on a USB port(s) like this:

uhubctl -a off -p 2

This means operate on default smart hub and turn power off (-a off, or -a 0) on port 2 (-p 2). Supported actions are off/on/cycle/toggle (or 0/1/2/3). cycle means turn power off, wait some delay (configurable with -d) and turn it back on. Ports can be comma separated list, and may use - for ranges e.g. 2, or 2,4, or 2-5, or 1-2,5-8.

:warning: Turning off built-in USB ports may cut off your keyboard or mouse, so be careful which ports you are turning off!

If you have more than one smart USB hub connected, you should choose specific hub to control using -l (location) parameter. To find hub locations, simply run uhubctl without any parameters. 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 (this method is also used in Linux kernel).

Linux USB permissions

On Linux, you should configure udev USB permissions (otherwise you will have to run it as root using sudo uhubctl).

Starting with Linux Kernel 6.0 there is a standard interface to turn USB hub ports on or off, and uhubctl will try to use it (instead of libusb) to set the port status. This is why there are additional rules for 6.0+ kernels. There is no harm in having these rules on systems running older kernel versions.

To fix USB permissions, first run sudo uhubctl and note all vid:pid for hubs you need to control. Then, add udev rules like below to file /etc/udev/rules.d/52-usb.rules (replace 2001 with your hub vendor id, or completely remove ATTR{idVendor} filter to allow any USB hub access):

SUBSYSTEM=="usb", DRIVER=="usb", MODE="0666", ATTR{idVendor}=="2001"
# Linux 6.0 or later (its ok to have this block present for older Linux kernels):
SUBSYSTEM=="usb", DRIVER=="usb", \
  RUN="/bin/sh -c \"chmod -f 666 $sys$devpath/*-port*/disable || true\""

Note that for USB3 hubs, some hubs use different vendor ID for USB2 vs USB3 components of the same chip, and both need permissions to make uhubctl work properly. E.g. for Raspberry Pi 4B, you need to add these 2 lines (or remove idVendor filter):

SUBSYSTEM=="usb", DRIVER=="usb", MODE="0666", ATTR{idVendor}=="2109"
SUBSYSTEM=="usb", DRIVER=="usb", MODE="0666", ATTR{idVendor}=="1d6b"

If you don't like wide open mode 0666, you can restrict access by group like this:

SUBSYSTEM=="usb", DRIVER=="usb", MODE="0664", GROUP="dialout"
# Linux 6.0 or later (its ok to have this block present for older Linux kernels):
SUBSYSTEM=="usb", DRIVER=="usb", \
  RUN+="/bin/sh -c \"chown -f root:dialout $sys$devpath/*-port*/disable || true\"" \
  RUN+="/bin/sh -c \"chmod -f 660 $sys$devpath/*-port*/disable || true\""

and then add permitted users to dialout group:

sudo usermod -a -G dialout $USER

For your udev rule changes to take effect, reboot or run:

sudo udevadm trigger --attr-match=subsystem=usb

For your convenience, ready to use udev rule is provided here.

FAQ

What is USB per-port power switching?

According to USB 2.0 specification, USB hubs can advertise no power switching, ganged (all ports at once) power switching or per-port (individual) power switching. Note that by default uhubctl will only detect USB hubs which support per-port power switching (but you can force it to try operating on unsupported hubs with option -f). You can find what kind of power switching your hardware supports by using sudo lsusb -v:

No power switching:

wHubCharacteristic 0x000a
  No power switching (usb 1.0)
  Per-port overcurrent protection

Ganged power switching:

wHubCharacteristic 0x0008
  Ganged power switching
  Per-port overcurrent protection

Per-port power switching:

wHubCharacteristic 0x0009
  Per-port power switching
  Per-port overcurrent protection

How do I check if my USB hub is supported by uhubctl?

  1. Run sudo uhubctl. If your hub is not listed, it is not supported. Alternatively, you can run sudo lsusb -v and check for Per-port power switching - if you cannot see such line in lsusb output, hub is not supported.
  2. Check for VBUS (voltage) off support: plug a phone, USB light or USB fan into USB port of your hub. Try using uhubctl to turn power off on that port, and check that phone stops charging, USB light stops shining or USB fan stops spinning. If VBUS doesn't turn off, your hub manufacturer did not include circuitry to actually cut power off. Such hub would still work to cut off USB data connection, but it cannot turn off power, and we do not consider this supported device.
  3. If tests above were successful, please report your hub by opening new issue at https://github.com/mvp/uhubctl/issues, so we can add it to list of supported devices. Please do not report unsupported hubs, unless it is different hardware revision of some already listed supported model.

USB devices are not removed after port power down on Linux

After powering down USB port, udev does not get any event, so it keeps the device files around. However, trying to access the device files will lead to an IO error.

This is Linux kernel issue and is fixed since uhubctl 2.5.0 for systems with Linux kernel 6.0 or later.

If you are still using Linux 5.x or older, you can use this workaround for this issue:

sudo uhubctl -a off -l ${location} -p ${port}
sudo udevadm trigger --action=remove /sys/bus/usb/devices/${location}.${port}/

Device file will be removed by udev, but USB device will be still visible in lsusb. Note that path /sys/bus/usb/devices/${location}.${port} will only exist if device was detected on that port. When you turn power back on, device should re-enumerate properly (no need to call udevadm again).

Power comes back on after few seconds on Linux

Some device drivers in kernel are surprised by USB device being turned off and automatically try to power it back on.

This is Linux kernel issue and is fixed since uhubctl 2.5.0 for systems with Linux kernel 6.0 or later.

If you are still using Linux 5.x or older:

You can use option -r N, where N is some number from 10 to 1000 to fix this - uhubctl will try to turn power off many times in quick succession, and it should suppress that.

Disabling USB authorization for device in question before turning power off with uhubctl should help:

echo 0 > sudo tee /sys/bus/usb/devices/${location}.${port}/authorized

If your device is USB mass storage, invoking udisksctl before calling uhubctl should help too:

sudo udisksctl power-off --block-device /dev/disk/...`
sudo uhubctl -a off ...

Multiple 4-port hubs are detected, but I only have one 7-port hub connected

Many hub manufacturers build their USB hubs using basic 4 port USB chips. E.g. to make 7 port hub, they daisy-chain two 4 port hubs - 1 port is lost to daisy-chaining, so it makes it 4+4-1=7 port hub. Similarly, 10 port hub could be built as 3 4-port hubs daisy-chained together, which gives 4+4+4-2=10 usable ports.

Note that you should never try to change power state for ports used to daisy-chain internal hubs together. Doing so will confuse internal hub circuitry and will cause unpredictable behavior.

Raspberry Pi turns power off on all ports, not just the one I specified

This is the limitation of Raspberry Pi hardware design. As a workaround, you can buy any external USB hub from supported list above, attach it to any USB port of Raspberry Pi, and control power on its ports independently. Also, there are supported hubs designed specifically for Raspberry Pi, e.g. UUGear MEGA4.

For reference, supported Raspberry Pi models have following internal USB topology:

Raspberry Pi B+,2B,3B
Raspberry Pi 3B+
Raspberry Pi 4B

:warning: If your VL805 firmware is older than 00137ad (check with sudo rpi-eeprom-update), you have to update firmware to make power switching work on RPi 4B.

Raspberry Pi 5

Raspberry Pi 5 has two USB2 ports and two USB3 ports (total 4). These ports are connected to 4 distinct USB hubs 1,2,3,4 in really weird configuration. If USB3 device is connected to blue socket, it will be detected on USB3 hub 2 or 4. If USB2 device is connected to any socket or USB3 device connected to black socket, it will be detected on USB2 hub 1 or 3. Regardless of USB2/USB3 connection type, blue sockets are always port 1, and black sockets are always port 2.

Each of 4 USB onboard hubs advertises as supporting per-port power switching, but this is not true. In reality, Raspberry Pi 5 all 4 ports are ganged together in one group, despite belonging to 4 different logical USB hubs.

To turn off VBUS power it has to be disabled across all onboard hubs and ports with:

uhubctl -l 1 -a 0
uhubctl -l 3 -a 0

To turn it back on:

uhubctl -l 1 -a 1
uhubctl -l 3 -a 1

Note that VBUS power goes down only if all ports are off - enabling any single port enables VBUS back for all 4 ports.

Notable projects using uhubctl

ProjectDescription
Morse code USB lightFlash a message in Morse code with USB light
Webcam USB lightTurn on/off LED when webcam is turned on/off
Cinema LightboxTurn on/off Cinema Lightbox from iOS Home app
Build Status LightCreate a build status light in under 10 minutes
BuildenlightsGitLab/GitHub project build status as green/red light
Weather StationReset Weather Station when it freezes
sysmoQMODReset cellular modems when necessary
Smog SensorRaspberry Pi based smog sensor power reset
Terrible ClusterPower on/off Raspberry Pi cluster nodes as needed
Ideal Music ServerTurn off unused USB ports to improve audio quality
USB drives with no phantom loadPower USB drives only when needed to save power
USB drive data recoveryRecover data from failing USB hard drive
Control power to 3D printerOctoPrint web plugin for USB power control
USB fan for Raspberry PiControl USB fan to avoid Raspberry Pi overheating
Raspberry Pi Reboot RouterAutomatically reboot router if internet isn't working
Control USB Lamp With VoiceVoice Control of USB Lamp using Siri and Raspberry Pi
Control USB LED StripControlling USB powered LED Light Strip
Brew beer with Raspberry PiAutomated beer brewing system using Raspberry Pi
Webcam On-Air SignAutomatically light up a sign when webcam is in use
Do it yourself PPPSSolder wires in your USB hub to support uhubctl
Open source PPPS hubOpen source hardware project for uhubctl compatible hub
Python Wrapper for uhubctlModule to use uhubctl with Python
labgridFramework for testing embedded Linux on hardware

Copyright

Copyright (C) 2009-2024 Vadim Mikhailov

This file can be distributed under the terms and conditions of the GNU General Public License version 2.