uhubctl
uhubctl es una utilidad para controlar la alimentación USB por puerto en concentradores USB inteligentes.
Un concentrador inteligente se define como aquel que implementa conmutación de alimentación por puerto.
La idea original de este código se inspiró en hub-ctrl.c de Niibe Yutaka:
https://www.gniibe.org/development/ac-power-control-by-USB-hub
Concentradores USB compatibles
Ten en cuenta que no muchos concentradores USB admiten correctamente la conmutación de alimentación por puerto.
Algunos ya no se fabrican y pueden ser difíciles de encontrar.
Esta es una lista de concentradores USB compatibles conocidos:
| Fabricante | Producto | Puertos | USB | VID:PID | Lanzamiento | EOL |
|---|
| Acer | Monitor BE270U (ver) | 4 | 3.0 | 2109:2811 | 2016 | |
| AmazonBasics | HU3641V1 (problema de RPi) | 4 | 3.0 | 2109:2811 | 2013 | |
| AmazonBasics | HU3770V1 (problema de RPi) | 7 | 3.0 | 2109:2811 | 2013 | |
| AmazonBasics | HU9003V1EBL, HUC9003V1EBL | 7 | 3.1 | 2109:2817 | 2018 | |
| AmazonBasics | HU9002V1SBL, HU9002V1EBL, HU9002V1ESL, HHU9002V1EZPR01 (nota) | 10 | 3.1 | 2109:2817 | 2018 | |
| AmazonBasics | HUC9002V1SBL, HUC9002V1EBL, HUC9002V1ESL | 10 | 3.1 | 2109:2817 | 2018 | |
| AmazonBasics | U3-7HUB (solo funciona para 1 puerto de carga) | 7 | 3.0 | 2109:2813 | 2020 | |
| Anker | AK-68ANHUB-BV7A-0004 (nota) | 7 | 3.0 |
Esta tabla no es, ni mucho menos, completa.
Si tu concentrador funciona con uhubctl, pero no aparece en la lista anterior, por favor repórtalo
abriendo un nuevo issue en https://github.com/mvp/uhubctl/issues,
para que podamos añadirlo a la tabla de compatibilidad. En tu informe, proporciona
el modelo exacto del producto y añade la salida de uhubctl
y prueba por favor la compatibilidad con el corte de VBUS como se describe abajo en las FAQ.
Ten en cuenta que bastantes placas base modernas tienen concentradores raíz integrados que
sí son compatibles con esta función; puede que ni siquiera necesites comprar un concentrador externo.
Nota sobre la dualidad de USB 3.0
Si tienes un concentrador USB 3.0 conectado al puerto ascendente USB3, se detectará
como 2 concentradores virtuales independientes: USB2 y USB3, y tus dispositivos USB se conectarán
al concentrador virtual USB2 o USB3 según sus capacidades y velocidad de conexión.
Para controlar la alimentación de estos concentradores, es necesario apagar/encender la alimentación en ambos concentradores virtuales
USB2 y USB3 para que los cambios de apagado/encendido surtan efecto. uhubctl intentará hacerlo automáticamente
(a menos que deshabilites este comportamiento con la opción -e).
Desafortunadamente, aunque la mayoría de los concentradores cortan la conexión USB de datos, algunos pueden no cortar el VBUS al puerto,
lo que significa que un teléfono conectado puede seguir cargándose desde un puerto que uhubctl ha apagado.
Instalación
Para Linux y MacOS, uhubctl está disponible en los gestores de paquetes estándar
y se puede instalar con los siguientes comandos:
- MacOS:
brew install uhubctl o sudo port install uhubctl
- ⚠️ ¡MacOS 26+ requiere libusb 1.0.30 o posterior!
- 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
Sin embargo, la versión de uhubctl instalada desde el gestor de paquetes estándar puede no
ser necesariamente la última, o incluso ir muy por detrás de la versión actual.
Si la última versión publicada de uhubctl
es más reciente que la que ofrece tu gestor de paquetes, puede que necesites compilar e instalar
desde el código fuente como se describe abajo.
Compilación
Esta utilidad se ha probado para compilar y funcionar en Linux (Ubuntu/Debian/Raspbian,
Redhat/EPEL/Fedora/CentOS, Arch Linux, Gentoo, openSUSE, Buildroot),
FreeBSD, NetBSD, SunOS y MacOS.
Aunque uhubctl compila en Windows, la conmutación de alimentación USB no funciona en Windows porque libusb
usa el controlador winusb.sys, que según Microsoft no admite
las solicitudes de control USB necesarias.
Esto podría solucionarse si libusb comienza a admitir un controlador diferente en Windows.
Ten en cuenta que es muy recomendable tener instalada la utilidad pkgconf (o pkg-config)
(a menudo viene instalada por defecto).
Primero, necesitas instalar la librería libusb-1.0 (se requiere la versión 1.0.13 o posterior,
se recomienda 1.0.23 o posterior):
- 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, o sudo port install libusb-devel pkgconf
- FreeBSD:
pkg install gmake pkgconf (libusb está incluido por defecto)
- NetBSD:
sudo pkgin install libusb1 gmake pkgconf
- Windows: ¿por determinar?
Para obtener el código fuente de uhubctl y compilarlo:
git clone https://github.com/mvp/uhubctl
cd uhubctl
make
Esto debería generar el binario uhubctl.
Puedes instalarlo en tu sistema como /usr/sbin/uhubctl usando:
Ten en cuenta que en algunos sistemas operativos (p. ej. FreeBSD/NetBSD) necesitas usar gmake en su lugar para compilar.
Uso
⚠️ En Linux, usa sudo o configura los permisos USB como se describe abajo!
Para listar todos los concentradores compatibles:
Puedes controlar la alimentación de uno o varios puertos USB de la siguiente manera:
Esto significa operar sobre el concentrador inteligente predeterminado y apagar la alimentación (-a off, o -a 0)
en el puerto 2 (-p 2). Las acciones admitidas son off/on/cycle/toggle (o 0/1/2/3).
cycle significa apagar la alimentación, esperar un retraso (configurable con -d) y volver a encenderla.
Los puertos pueden ser una lista separada por comas, y pueden usar - para rangos, p. ej. 2, o , o , o .> ⚠️ Apagar los puertos USB integrados puede cortar el teclado o el ratón,
así que ten cuidado con qué puertos apagas.
Si tienes más de un hub USB inteligente conectado, debes elegir
el hub específico a controlar usando el parámetro -l (ubicación).
Para encontrar las ubicaciones de los hubs, simplemente ejecuta uhubctl sin parámetros.
Las ubicaciones de los hubs tienen el formato b-x.y.z, donde b es el número de bus USB, y x, y, z...
son los números de puerto de todos los hubs en la cadena, empezando por el hub raíz de un bus USB determinado.
Esta dirección es semi-estable: no cambiará si desconectas/reconectas (o apagas/enciendes)
un dispositivo USB en el mismo puerto USB físico (este método también se usa en el kernel de Linux).
Permisos USB en Linux
En Linux, debes configurar los permisos USB de udev (de lo contrario tendrás que ejecutarlo como root usando sudo uhubctl).
A partir del kernel de Linux 6.0 hay una interfaz estándar para encender o apagar los puertos del hub USB,
y uhubctl intentará usarla (en lugar de libusb) para establecer el estado del puerto.
Por eso hay reglas adicionales para kernels 6.0+.
No hay ningún problema en tener estas reglas en sistemas con versiones anteriores del kernel.
Para corregir los permisos USB, primero ejecuta sudo uhubctl y anota todos los vid:pid de los hubs que necesitas controlar.
Luego, añade reglas de udev como las siguientes al archivo /etc/udev/rules.d/52-usb.rules
(reemplaza 2001 con el id de proveedor de tu hub, o elimina por completo el filtro ATTR{idVendor} para permitir el acceso a cualquier hub USB):
SUBSYSTEM=="usb", DRIVER=="hub|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=="hub|usb", \
RUN="/bin/sh -c \"chmod -f 666 $sys$devpath/*port*/disable || true\""
Ten en cuenta que para los hubs USB3, algunos hubs usan un ID de proveedor diferente para los componentes USB2 y USB3 del mismo chip,
y ambos necesitan permisos para que uhubctl funcione correctamente.
P. ej., para Raspberry Pi 4B, necesitas añadir estas 2 líneas (o eliminar el filtro idVendor):
SUBSYSTEM=="usb", DRIVER=="hub|usb", MODE="0666", ATTR{idVendor}=="2109"
SUBSYSTEM=="usb", DRIVER=="hub|usb", MODE="0666", ATTR{idVendor}=="1d6b"
Si no te gusta el modo totalmente abierto 0666, puedes restringir el acceso por grupo de esta manera:
SUBSYSTEM=="usb", DRIVER=="hub|usb", MODE="0664", GROUP="dialout"
# Linux 6.0 or later (its ok to have this block present for older Linux kernels):
SUBSYSTEM=="usb", DRIVER=="hub|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\""
y luego añade los usuarios permitidos al grupo dialout:
sudo usermod -a -G dialout $USER
Para que los cambios en las reglas de udev tengan efecto, reinicia o ejecuta:
sudo udevadm trigger --attr-match=subsystem=usb
Para tu comodidad, se proporciona una regla udev lista para usar aquí.
FAQ
¿Qué es la conmutación de alimentación por puerto USB?
Según la especificación USB 2.0, los hubs USB pueden anunciar ausencia de conmutación de alimentación,
conmutación de alimentación en grupo (todos los puertos a la vez) o conmutación de alimentación por puerto (individual).
Ten en cuenta que, por defecto, uhubctl solo detectará hubs USB que soporten conmutación de alimentación por puerto
(pero puedes forzarlo a intentar operar en hubs no compatibles con la opción -f).
Puedes averiguar qué tipo de conmutación de alimentación soporta tu hardware usando sudo lsusb -v:
Sin conmutación de alimentación:
wHubCharacteristic 0x000a
No power switching (usb 1.0)
Per-port overcurrent protection
Conmutación de alimentación en grupo:
wHubCharacteristic 0x0008
Ganged power switching
Per-port overcurrent protection
Conmutación de alimentación por puerto:
wHubCharacteristic 0x0009
Per-port power switching
Per-port overcurrent protection
¿Cómo compruebo si mi hub USB es compatible con uhubctl?
- Ejecuta
sudo uhubctl. Si tu hub no aparece en la lista, no es compatible.
Alternativamente, puedes ejecutar sudo lsusb -v y buscar
Per-port power switching - si no ves esa línea en la salida de lsusb,
el hub no es compatible.
- Comprueba la compatibilidad con el apagado de VBUS (voltaje): enchufa un teléfono, una luz USB
o un ventilador USB en el puerto USB de tu hub.
Intenta usar
uhubctl para apagar la alimentación de ese puerto y comprueba
que el teléfono deja de cargarse, la luz USB deja de brillar o el ventilador USB deja de girar.
Si VBUS no se apaga, el fabricante de tu hub no incluyó el circuito
necesario para cortar la alimentación realmente. Ese hub seguiría funcionando
para cortar la conexión de datos USB, pero no puede apagar la alimentación,
y no lo consideramos un dispositivo compatible.
- Si las pruebas anteriores tuvieron éxito, por favor informa sobre tu hub
abriendo un nuevo issue en https://github.com/mvp/uhubctl/issues,
para que podamos añadirlo a la lista de dispositivos compatibles.
Por favor, no informes sobre hubs no compatibles, a menos que sea una revisión
de hardware diferente de algún modelo compatible ya listado.
Los dispositivos USB no se eliminan después de apagar la alimentación del puerto en Linux
Después de apagar la alimentación de un puerto USB, udev no recibe ningún evento, por lo que mantiene los archivos de dispositivo.
Sin embargo, intentar acceder a los archivos de dispositivo provocará un error de E/S.
Esto es un problema del kernel de Linux y está corregido
desde uhubctl 2.5.0 para sistemas con kernel de Linux 6.0 o posterior.
Si todavía usas Linux 5.x o anterior, puedes usar esta solución alternativa para este problema:
sudo uhubctl -a off -l ${location} -p ${port}
sudo udevadm trigger --action=remove /sys/bus/usb/devices/${location}.${port}/
El archivo de dispositivo será eliminado por udev, pero el dispositivo USB seguirá siendo visible en lsusb.
Ten en cuenta que la ruta /sys/bus/usb/devices/${location}.${port} solo existirá si el dispositivo fue detectado en ese puerto.
Cuando vuelvas a encender la alimentación, el dispositivo debería re-enumerarse correctamente (no es necesario volver a llamar a udevadm).
La alimentación vuelve a encenderse después de unos segundos en Linux
Algunos controladores de dispositivos en el kernel se sorprenden al ver que un dispositivo USB se apaga e intentan automáticamente volver a encenderlo.
Esto es un problema del kernel de Linux y está corregido
desde uhubctl 2.5.0 para sistemas con kernel de Linux 6.0 o posterior.
Si todavía usas Linux 5.x o anterior:
Puedes usar la opción -r N, donde N es un número entre 10 y 1000 para solucionarlo:
uhubctl intentará apagar la alimentación muchas veces en sucesión rápida, y debería suprimir ese comportamiento.
Deshabilitar la autorización USB para el dispositivo en cuestión antes de apagar la alimentación con uhubctl debería ayudar:
echo 0 > sudo tee /sys/bus/usb/devices/${location}.${port}/authorized
Si tu dispositivo es un almacenamiento masivo USB, invocar udisksctl antes de llamar a uhubctl también debería ayudar:
sudo udisksctl power-off --block-device /dev/disk/...`
sudo uhubctl -a off ...
Se detectan varios hubs de 4 puertos, pero solo tengo un hub de 7 puertos conectado
Muchos fabricantes de hubs construyen sus hubs USB usando chips USB básicos de 4 puertos.
P. ej., para hacer un hub de 7 puertos, conectan en cadena dos hubs de 4 puertos: se pierde 1 puerto en la conexión en cadena,
por lo que resulta un hub de 4+4-1=7 puertos. De manera similar, un hub de 10 puertos podría construirse con 3 hubs de 4 puertos
conectados en cadena, lo que da 4+4+4-2=10 puertos utilizables.
Ten en cuenta que nunca debes intentar cambiar el estado de alimentación de los puertos utilizados para conectar en cadena los hubs internos.
Hacerlo confundirá el circuito interno del hub y provocará un comportamiento impredecible.
Raspberry Pi apaga la alimentación de todos los puertos, no solo la del que especifiqué
Esta es una limitación del diseño de hardware de Raspberry Pi.
Como solución alternativa, puedes comprar cualquier hub USB externo de la lista de compatibles anterior,
conectarlo a cualquier puerto USB de Raspberry Pi y controlar la alimentación de sus puertos de forma independiente.
Además, hay hubs compatibles diseñados específicamente para Raspberry Pi, p. ej., UUGear MEGA4.
Para referencia, los modelos de Raspberry Pi compatibles tienen la siguiente topología USB interna:
Raspberry Pi B+,2B,3B
-
Hub único 1-1, puertos 2-5 en grupo, todos controlados por el puerto 2:
Intentar controlar los puertos 3, 4 y 5 no hará nada.
El puerto 1 controla la alimentación de Ethernet+WiFi.
Raspberry Pi 3B+
-
Hub principal 1-1, los 4 puertos en grupo, todos controlados por el puerto 2 (también apaga los puertos del hub secundario).
El puerto 1 conecta con el hub 1-1.1 siguiente; los puertos 2 y 3 están conectados al exterior, y el puerto 4 no está conectado.
-
Hub secundario 1-1.1 (conectado en cadena al principal): 3 puertos,
el puerto 1 se usa para Ethernet+WiFi, y los puertos 2 y 3 están conectados al exterior.
Raspberry Pi 4B
⚠️ Si tu firmware VL805 es anterior a 00137ad (compruébalo con sudo rpi-eeprom-update),
tienes que actualizar el firmware
para que la conmutación de alimentación funcione en RPi 4B.
-
USB2 hub 1, 1 puerto, solo conecta con el hub 1-1 siguiente.
-
USB2 hub 1-1, 4 puertos en grupo, gemelo del hub USB3 2 siguiente:
-
USB3 hub 2, 4 puertos en grupo, gemelo del hub USB2 1-1 anterior:
-
USB2 hub 3, 1 puerto, controlador OTG. La conmutación de alimentación no es compatible.
Raspberry Pi 5
Raspberry Pi 5 tiene dos puertos USB2 y dos puertos USB3 (4 en total).
Estos puertos están conectados a 4 hubs USB distintos 1, 2, 3, 4 en una configuración realmente extraña
(pero dependiendo del SO y de la revisión de hardware, los hubs de interés pueden ser 2, 3, 4, 5).
Si un dispositivo USB3 se conecta al conector azul, se detectará en el hub USB3 2 o 4.
Si un dispositivo USB2 se conecta a cualquier conector, o un dispositivo USB3 se conecta al conector negro,
se detectará en el hub USB2 1 o 3.
Independientemente del tipo de conexión USB2/USB3, los conectores azules son siempre el puerto 1,
y los conectores negros son siempre el puerto 2.
Cada uno de los 4 hubs USB integrados se anuncia como compatible con la conmutación de alimentación por puerto, pero esto no es cierto.
En realidad, en Raspberry Pi 5 los 4 puertos están agrupados juntos en un solo grupo,
a pesar de pertenecer a 4 hubs USB lógicos diferentes.
Para apagar la alimentación VBUS, debe deshabilitarse en todos los hubs y puertos integrados con: ```
uhubctl -l 2 -a 0
uhubctl -l 4 -a 0
Para volver a activarlo: ```
uhubctl -l 2 -a 1
uhubctl -l 4 -a 1
Ten en cuenta que la alimentación de VBUS solo se corta si todos los puertos están apagados:
habilitar un solo puerto restablece VBUS en los 4 puertos.
Proyectos notables que usan uhubctl
Copyright
Copyright (C) 2009-2026 Vadim Mikhailov
Este archivo puede distribuirse bajo los términos y condiciones de la
Licencia Pública General de GNU versión 2.