uhubctl: cutting USB hub ports loose with a single C file
uhubctl - USB hub per-port power control
At a glance
- What is it?
- A small libusb utility that toggles power per port on smart USB hubs, plus a compatibility table longer than its documentation. Useful for flaky peripherals, awkward to trust without checking the hardware list first.
- Who is it for?
- uhubctl earns its keep in the specific case of a device that only recovers when its USB power is actually removed, which is more common than most documentation suggests. What it does not give you is discovery: the whole value of the tool depends on whether your hub appears in the README's compatibility table, and the README says outright that not many hubs implement per-port switching correctly.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 74 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One C file against libusb, built with make
The repository is small enough to describe in a sentence: `uhubctl.c`, a `Makefile`, a `VERSION` file, a `COPYING` and `LICENSE` pair, a `udev/` directory and a README that is mostly a hardware table. The description calls it a utility to control USB power per port on smart USB hubs, where a smart hub is defined as one that implements per-port power switching. That definition is the whole project. There is no daemon, no configuration format and no GUI.
The build is a plain Makefile with no configure step. It compiles a single translation unit against libusb-1.0, and it prefers `pkg-config` for the cflags and libs, falling back to hand written paths when pkg-config is missing:
prefix ?= /usr
sbindir ?= $(prefix)/sbin
CFLAGS += -Wall -Wextra -Wno-zero-length-array -std=c99 -pedanticThe version string comes from `git describe`, falling back to the contents of `VERSION` when git metadata is not available, and is compiled in with a `-DPROGRAM_VERSION` define. On Linux the Makefile also adds `-Wl,-zrelro,-znow`. So building and installing is:
make
sudo make installInstall goes to `$(DESTDIR)$(sbindir)`, which resolves to `/usr/sbin` unless you change `prefix`. GitHub reports the last push on 2026-07-25.
The compatibility table is the actual product documentation
The README opens with a warning that deserves to be quoted: not many USB hubs correctly support per-port power switching, and some of them are no longer manufactured and can be hard to find. What follows is a table with columns for manufacturer, product, port count, USB version, VID:PID, release year and end-of-life status, running to dozens of rows.
That table is why the project is worth reading rather than just installing. A few rows carry footnotes that change how the tool behaves on that hardware:
AK-68ANHUB-BV7A-0004
HU3641V1
U3-7HUB (only works for 1 charge port)
DUB-H4 rev D,E (black). Note: rev A,C,F not supportedThe pattern is consistent. Product revisions matter, sometimes down to the letter, and some hubs expose only a subset of ports. The Dell Wyse 3040 row is annotated as needing `-f`, the AmazonBasics U3-7HUB row says only one charge port works, and the BenQ PD2700U is marked as working only in USB2 mode. Several entries carry short links to issue threads where the real behaviour is discussed.
For a reader deciding whether to bother, the practical order is: run the tool, see whether your hub shows up, then look up its VID:PID in the table rather than the marketing name, because the marketing names repeat across revisions with different support.
What releases 2.4 through 2.6 actually changed
The release notes are terse, which makes them easy to read. Version 2.6.0, published 2024-08-31, added Raspberry Pi 5 support, fixed a bug on big-endian platforms, fixed a sysfs path bug affecting Linux kernel 6.x and later, added a flash option that turns power on and then off as an inverted cycle, improved Linux detection and extended the supported device table.
Version 2.5.0, published 2022-11-02, is the one that changes the reliability story. It added support for sysfs based power switching provided by Linux kernel 6.0 and later, which the notes say allows reliability issues when turning power off on Linux to be solved. Same release added `--nodesc` to skip querying device string descriptors, described as necessary for some buggy devices that would otherwise freeze completely, and introduced a simpler udev rule setup on Linux where one rule works for any USB hub.
Version 2.4.0, published 2021-02-14, added the toggle action, which turns a port on or off opposite to its current power state, improved error reporting when enumerating devices that lack permissions, and allowed a `pkg-config` override to keep build systems such as Chromium OS happy.
Read together, these describe a utility that spent 2022 fixing the operating system interaction and 2024 widening hardware coverage. Two of the three features a user is most likely to want, toggle and flash, arrived in 2024 or later, so an older packaged build is missing them.
Where the udev rules fit and why they matter
The `udev/` directory in the tree and the 2.5.0 note about a single rule working for any USB hub point at the same problem: without a udev rule, non-root users generally cannot send the control transfers that switch port power, because the USB device nodes belong to root. A rule that assigns a group to the relevant nodes is what lets an unprivileged user cycle a port.
The release note says the configuration got simpler in 2.5.0 because one rule now covers any USB hub, rather than one rule per device. That is a small thing to get wrong, though: the identifiers a rule matches on are exactly the VID:PID values in the compatibility table, so a hub that is not in the table is also a hub whose udev rule nobody has written.
For a machine where the person logging in already has sudo, none of this matters and you can skip straight to invoking the tool. For a shared test bench or a lab where several people cycle ports on the same box, the rule is the difference between a usable setup and a workflow that requires a password every time. The README links to udev documentation upstream rather than restating it, so expect to consult the Linux documentation for the exact syntax.
What the utility is not, and the honest limits of the docs
It is worth being direct about the edges. This is a port power switch, not a device manager: it cannot tell you which physical socket a port corresponds to on a hub with an undocumented port order, it does not verify that a device came back after power was restored, and it has no notion of what is on the other end. The features list in the repository topics is about hardware control, with libusb and the per-port switch as the substance.
The second limit is documentation. There is no wiki, no manual page and no usage section with worked examples anywhere in this repository. The README is a compatibility table, a short description, a credit to the original `hub-ctrl.c` idea by Niibe Yutaka, and links out. Everything a new user needs beyond install has to come from the command line itself, which for a utility with as many device specific edge cases as this one is a real gap.
Compare it with what else exists in the same space. A hardware power switch or smart plug placed inline gives you the same physical effect with no compatibility table to consult, at the cost of one socket. A kernel driver that already handles per-port power for your hub gives you power control without a userspace tool. uhubctl is the right answer when you want software control across many ports on hardware you cannot replace, and you have verified your hub is in the list.
Editorial conclusion
uhubctl earns its keep in the specific case of a device that only recovers when its USB power is actually removed, which is more common than most documentation suggests. What it does not give you is discovery: the whole value of the tool depends on whether your hub appears in the README's compatibility table, and the README says outright that not many hubs implement per-port switching correctly. Build it with make, run it once without arguments to see what it detects, then check the model against the table before writing anything into cron.
Frequently asked questions
Which USB hubs does uhubctl support?
The README maintains a table of known compatible hubs with manufacturer, product, port count, USB version and VID:PID, and it warns that not many hubs correctly support per-port power switching. Some rows carry footnotes restricting them to specific revisions or to a subset of ports.
Do I need root to use uhubctl?
The repository ships a udev directory, and the 2.5.0 release notes describe a simpler udev setup where one rule works for any USB hub, which is how non-root access is normally arranged. Without a rule, the control transfers the tool sends require elevated permissions.
How do I build uhubctl from source?
There is a single source file and a Makefile with no configure step. Compilation needs libusb-1.0, detected through pkg-config when available, and installs into sbindir under /usr by default.
What does the flash option do?
Added in version 2.6.0, it is described as an inverted cycle that turns power on and then off. That differs from toggle, which version 2.4.0 added to switch a port opposite to its current state.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mvp-uhubctl)