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
https://www.gniibe.org/development/ac-power-control-by-USB-hub
Compatible USB hubs
Note that not many USB hubs correctly 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:
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.
https://github.com/mvp/uhubctl/issues
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.
Installing
For Linux and MacOS uhubctl is available in standard package managers
and can be installed with following commands:
MacOS: brew install uhubctl or sudo port install uhubctl
⚠️ MacOS 26+ requires libusb 1.0.30 or later!
⚠️ MacOS 26+ requires libusb 1.0.30 or later!
Ubuntu/Debian/Raspbian: sudo apt install uhubctl
Redhat/EPEL/Fedora/CentOS: sudo yum install uhubctl
OpenSUSE: sudo zypper install uhubctl
FreeBSD: cd /usr/ports/sysutils/uhubctl && sudo make install
However, uhubctl installed from standard package manager may not
necessarily be latest version, or even severely lag behind current version.
If latest published uhubctl version
is newer than what your package manager offers, you may need to compile and install
from source as described below.
Compiling
This utility was tested to compile and work on Linux (Ubuntu/Debian/Raspbian,
Redhat/EPEL/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.
necessary USB control requests
Note that it is highly recommended to have utility pkgconf (or pkg-config) installed
(often it is installed by default).
First, you need to install library libusb-1.0 (version 1.0.13 or later is required,
1.0.23 or later is recommended):
Ubuntu: sudo apt-get install libusb-1.0-0-dev pkgconf
Redhat: sudo yum install libusb1-devel pkgconf
OpenSUSE: sudo zypper install libusb-1_0-devel pkgconf
MacOS: brew install libusb pkgconf, or sudo port install libusb-devel pkgconf
FreeBSD: pkg install gmake pkgconf (libusb is included by default)
NetBSD: sudo pkgin install libusb1 gmake pkgconf
Windows: TBD?
To fetch uhubctl source and compile it:
This should generate uhubctl binary.
You can install it in your system as /usr/sbin/uhubctl using:
Note that on some OS (e.g. FreeBSD/NetBSD) you need to use gmake instead to build.
Usage
⚠️ On Linux, use sudo or configure USB permissions as described below!
To list all supported hubs:
You can control the power on a USB port(s) like this:
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.
⚠️ 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):
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):
If you don't like wide open mode 0666, you can restrict access by group like this:
and then add permitted users to dialout group:
For your udev rule changes to take effect, reboot or run:
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:
Ganged power switching:
Per-port power switching:
How do I check if my USB hub is supported by uhubctl?
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.
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.
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.
https://github.com/mvp/uhubctl/issues
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:
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:
If your device is USB mass storage, invoking udisksctl before calling uhubctl should help too:
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:
Single hub 1-1, ports 2-5 ganged, all controlled by port 2:
uhubctl -l 1-1 -p 2 -a 0
Trying to control ports 3,4,5 will not do anything.
Port 1 controls power for Ethernet+WiFi.
Single hub 1-1, ports 2-5 ganged, all controlled by port 2:
Trying to control ports 3,4,5 will not do anything.
Port 1 controls power for Ethernet+WiFi.
Main hub 1-1, all 4 ports ganged, all controlled by port 2 (turns off secondary hub ports as well).
Port 1 connects hub 1-1.1 below, ports 2 and 3 are wired outside, port 4 not wired.
uhubctl -l 1-1 -p 2 -a 0
Main hub 1-1, all 4 ports ganged, all controlled by port 2 (turns off secondary hub ports as well).
Port 1 connects hub 1-1.1 below, ports 2 and 3 are wired outside, port 4 not wired.
Secondary hub 1-1.1 (daisy-chained to main): 3 ports,
port 1 is used for Ethernet+WiFi, and ports 2 and 3 are wired outside.
Secondary hub 1-1.1 (daisy-chained to main): 3 ports,
port 1 is used for Ethernet+WiFi, and ports 2 and 3 are wired outside.
⚠️ 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.
USB2 hub 1, 1 port, only connects hub 1-1 below.
USB2 hub 1, 1 port, only connects hub 1-1 below.
USB2 hub 1-1, 4 ports ganged, dual to USB3 hub 2 below:
uhubctl -l 1-1 -a 0
USB2 hub 1-1, 4 ports ganged, dual to USB3 hub 2 below:
USB3 hub 2, 4 ports ganged, dual to USB2 hub 1-1 above:
uhubctl -l 2 -a 0
USB3 hub 2, 4 ports ganged, dual to USB2 hub 1-1 above:
USB2 hub 3, 1 port, OTG controller. Power switching is not supported.
USB2 hub 3, 1 port, OTG controller. Power switching is not supported.
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
(but depending on OS and HW revision hubs of interest can be 2,3,4,5).
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:
To turn it back on:
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
USB drives with no phantom load
Copyright
Copyright (C) 2009-2025 Vadim Mikhailov
This file can be distributed under the terms and conditions of the
GNU General Public License version 2.