uhubctl — это утилита для управления питанием отдельных USB-портов. Она работает только с так называемыми «умными» USB-хабами — теми, которые поддерживают переключение питания на каждый порт по отдельности. Идею взяли из кода hub-ctrl.c от Niibe Yutaka.
Проблема в том, что подходящих хабов на рынке не так много, многие уже сняты с производства. Авторы ведут таблицу совместимости — там и мониторы от Dell и LG, и Raspberry Pi (модели 3B+, 4B, 5), и док-станции Lenovo, и даже клавиатура Apple с Thunderbolt Display. Важный нюанс: USB 3.0 хаб видится системой как два виртуальных — USB2 и USB3. Чтобы выключить питание, нужно отключать оба. uhubctl делает это автоматически, если не отключать опцией -e.
Но и тут есть подвох: даже после отключения некоторые хабы не режут линию VBUS. Телефон может продолжать заряжаться, хотя данные уже отключены.
Установка простая — uhubctl есть в пакетных менеджерах: brew на MacOS, apt на Ubuntu/Debian, yum на Fedora. Но в репозиториях версия может устареть, так что автор рекомендует собирать из исходников через git clone. Для сборки нужна libusb-1.0 (версия 1.0.13+, лучше 1.0.23+).
Утилита проверена на Linux, FreeBSD, NetBSD, SunOS и MacOS. На Windows не работает — libusb использует winusb.sys, а он, по словам Microsoft, не поддерживает нужные управляющие запросы.
Команды простые: uhubctl -a off -p 2 выключает питание на втором порту. Можно делать cycle (выкл, пауза, вкл), toggle или on. Порты задаются списком или диапазоном: 2,4 или 2-5. Если хабов несколько — нужен параметр -l с локацией в формате b-x.y.z.
На Linux обязательно настраивать права через udev, иначе придётся всё делать через sudo. Начиная с ядра 6.0 uhubctl использует стандартный интерфейс ядра вместо libusb для управления портами.
Есть известные проблемы. На Raspberry Pi все порты могут выключаться разом — это аппаратное ограничение. Для Raspberry Pi 4B нужно обновить прошивку VL805 до версии 00137ad, иначе переключение не сработает. На Raspberry Pi 5 четыре порта «привязаны» друг к другу: VBUS отключается только если выключить все, а включение одного включает питание на всех.
Если после выключения устройство не исчезает из системы — это баг ядра Linux до версии 5.x. Начиная с uhubctl 2.5.0 и ядра 6.0 это пофикшено. Для старых ядер есть костыль через udevadm trigger --action=remove.
Проект живёт на GitHub, автор — Vadim Mikhailov, лицензия — GPL v2. Если ваш хаб работает, но не в списке — можно открыть issue и добавить его.