uhubctl
uhubctl est un utilitaire permettant de contrôler l'alimentation USB par port sur les hubs USB intelligents.
Un hub intelligent est défini comme un hub qui implémente la commutation d'alimentation par port.
L'idée originale de ce code a été inspirée par hub-ctrl.c de Niibe Yutaka :
https://www.gniibe.org/development/ac-power-control-by-USB-hub
Hubs USB compatibles
Notez que peu de hubs USB prennent correctement en charge la commutation d'alimentation par port.
Certains ne sont plus fabriqués et peuvent être difficiles à trouver.
Voici la liste des hubs USB compatibles connus :
| Fabricant | Produit | Ports | USB | VID:PID | Sortie | Fin de vie |
|---|
| Acer | BE270U monitor (voir) | 4 | 3.0 | 2109:2811 | 2016 | |
| AmazonBasics | HU3641V1 (problème RPi) | 4 | 3.0 | 2109:2811 | 2013 | |
| AmazonBasics | HU3770V1 (problème RPi) | 7 | 3.0 | 2109:2811 | 2013 | |
| AmazonBasics | HU9003V1EBL, HUC9003V1EBL | 7 | 3.1 | 2109:2817 | 2018 | |
| AmazonBasics | HU9002V1SBL, HU9002V1EBL, HU9002V1ESL, HHU9002V1EZPR01 (note) | 10 | 3.1 | 2109:2817 | 2018 | |
| AmazonBasics | HUC9002V1SBL, HUC9002V1EBL, HUC9002V1ESL | 10 | 3.1 | 2109:2817 | 2018 | |
| AmazonBasics | U3-7HUB (ne fonctionne que pour 1 port de charge) | 7 | 3.0 | 2109:2813 | 2020 | |
| Anker | AK-68ANHUB-BV7A-0004 (note) | 7 | 3.0 |
Ce tableau est loin d'être complet.
Si votre hub fonctionne avec uhubctl, mais n'est pas listé ci-dessus, veuillez le signaler
en ouvrant une nouvelle issue sur https://github.com/mvp/uhubctl/issues,
afin que nous puissions l'ajouter au tableau des hubs pris en charge. Dans votre rapport, veuillez fournir
le modèle exact du produit et ajouter la sortie de uhubctl,
et veuillez tester le support de la coupure VBUS comme décrit ci-dessous dans la FAQ.
Notez qu'un certain nombre de cartes mères modernes ont des hubs racine intégrés qui
prennent en charge cette fonctionnalité - vous n'avez peut-être même pas besoin d'acheter un hub externe.
USB 3.0 duality note
Si vous avez un hub USB 3.0 connecté à un port amont USB 3.0, il sera détecté
comme 2 hubs virtuels indépendants : USB2 et USB3, et vos périphériques USB seront connectés
au hub virtuel USB2 ou USB3 selon leurs capacités et leur vitesse de connexion.
Pour contrôler l'alimentation de ces hubs, il est nécessaire de couper/rétablir l'alimentation sur les deux
hubs virtuels USB2 et USB3 pour que les changements d'alimentation prennent effet. uhubctl essaiera de le faire automatiquement
(à moins que vous ne désactiviez ce comportement avec l'option -e).
Malheureusement, si la plupart des hubs coupent la connexion de données USB, certains peuvent ne pas couper le VBUS du port,
ce qui signifie qu'un téléphone connecté peut continuer à se charger depuis un port dont l'alimentation a été coupée par uhubctl.
Installation
Pour Linux et MacOS, uhubctl est disponible dans les gestionnaires de paquets standard
et peut être installé avec les commandes suivantes :
- MacOS :
brew install uhubctl ou sudo port install uhubctl
- ⚠️ MacOS 26+ nécessite libusb 1.0.30 ou ultérieur !
- 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
Cependant, uhubctl installé depuis le gestionnaire de paquets standard peut ne pas
être la dernière version, voire même accuser un retard important par rapport à la version actuelle.
Si la dernière version publiée de uhubctl
est plus récente que celle proposée par votre gestionnaire de paquets, vous devrez peut-être compiler et installer
à partir des sources comme décrit ci-dessous.
Compilation
Cet utilitaire a été testé en compilation et en fonctionnement sur Linux (Ubuntu/Debian/Raspbian,
Redhat/EPEL/Fedora/CentOS, Arch Linux, Gentoo, openSUSE, Buildroot),
FreeBSD, NetBSD, SunOS et MacOS.
Bien que uhubctl compile sous Windows, la commutation d'alimentation USB ne fonctionne pas sous Windows car libusb
utilise le pilote winusb.sys, qui selon Microsoft ne prend pas en charge
les requêtes de contrôle USB nécessaires.
Cela pourrait être corrigé si libusb commençait à prendre en charge un autre pilote sur Windows.
Notez qu'il est fortement recommandé d'avoir l'utilitaire pkgconf (ou pkg-config) installé
(souvent il est installé par défaut).
Tout d'abord, vous devez installer la bibliothèque libusb-1.0 (la version 1.0.13 ou ultérieure est requise,
1.0.23 ou ultérieure est recommandée) :
- 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, ou sudo port install libusb-devel pkgconf
- FreeBSD :
pkg install gmake pkgconf (libusb est inclus par défaut)
- NetBSD :
sudo pkgin install libusb1 gmake pkgconf
- Windows : à déterminer ?
Pour récupérer les sources de uhubctl et les compiler :
git clone https://github.com/mvp/uhubctl
cd uhubctl
make
Cela devrait générer le binaire uhubctl.
Vous pouvez l'installer dans votre système en tant que /usr/sbin/uhubctl en utilisant :
Notez que sur certains OS (par ex. FreeBSD/NetBSD), vous devez utiliser gmake à la place pour compiler.
Utilisation
⚠️ Sous Linux, utilisez sudo ou configurez les permissions USB comme décrit ci-dessous !
Pour lister tous les hubs pris en charge :
Vous pouvez contrôler l'alimentation d'un ou plusieurs ports USB comme ceci :
Cela signifie opérer sur le hub intelligent par défaut et couper l'alimentation (-a off, ou -a 0)
sur le port 2 (-p 2). Les actions prises en charge sont off/on/cycle/toggle (ou 0/1/2/3).
cycle signifie couper l'alimentation, attendre un délai (configurable avec -d) puis la rétablir.
Les ports peuvent être une liste séparée par des virgules, et peuvent utiliser - pour des plages, par ex. 2, ou , ou , ou .> ⚠️ L'extinction des ports USB intégrés peut couper votre clavier ou votre souris,
soyez donc prudent quant aux ports que vous désactivez !
Si vous avez plus d'un hub USB intelligent connecté, vous devez choisir
le hub spécifique à contrôler à l'aide du paramètre -l (location).
Pour trouver les emplacements des hubs, exécutez simplement uhubctl sans aucun paramètre.
Les emplacements des hubs ressemblent à b-x.y.z, où b est le numéro du bus USB, et x, y, z...
sont les numéros de port pour tous les hubs de la chaîne, en partant du hub racine pour un bus USB donné.
Cette adresse est semi-stable : elle ne change pas si vous débranchez/rebranchez (ou éteignez/allumez)
un périphérique USB sur le même port USB physique (cette méthode est également utilisée dans le noyau Linux).
Permissions USB sous Linux
Sous Linux, vous devez configurer les permissions USB de udev (sinon vous devrez l'exécuter en tant que root avec sudo uhubctl).
À partir du noyau Linux 6.0, il existe une interface standard pour activer ou désactiver les ports du hub USB,
et uhubctl tentera de l'utiliser (au lieu de libusb) pour définir l'état du port.
C'est pourquoi il existe des règles supplémentaires pour les noyaux 6.0+.
Ces règles ne posent aucun problème sur les systèmes exécutant des versions plus anciennes du noyau.
Pour corriger les permissions USB, exécutez d'abord sudo uhubctl et notez tous les vid:pid des hubs que vous devez contrôler.
Ensuite, ajoutez des règles udev comme ci-dessous dans le fichier /etc/udev/rules.d/52-usb.rules
(remplacez 2001 par l'identifiant du fabricant de votre hub, ou supprimez complètement le filtre ATTR{idVendor} pour autoriser l'accès à tout 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\""
Notez que pour les hubs USB3, certains hubs utilisent un identifiant de fabricant différent pour les composants USB2 et USB3 de la même puce,
et les deux doivent disposer des permissions pour que uhubctl fonctionne correctement.
Par exemple, pour un Raspberry Pi 4B, vous devez ajouter ces 2 lignes (ou supprimer le filtre idVendor) :
SUBSYSTEM=="usb", DRIVER=="hub|usb", MODE="0666", ATTR{idVendor}=="2109"
SUBSYSTEM=="usb", DRIVER=="hub|usb", MODE="0666", ATTR{idVendor}=="1d6b"
Si vous ne souhaitez pas utiliser le mode grand ouvert 0666, vous pouvez restreindre l'accès par groupe comme ceci :
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\""
puis ajoutez les utilisateurs autorisés au groupe dialout :
sudo usermod -a -G dialout $USER
Pour que vos modifications des règles udev prennent effet, redémarrez ou exécutez :
sudo udevadm trigger --attr-match=subsystem=usb
Pour votre commodité, une règle udev prête à l'emploi est fournie ici.
FAQ
Qu'est-ce que la commutation d'alimentation par port USB ?
Selon la spécification USB 2.0, les hubs USB peuvent annoncer l'absence de commutation d'alimentation,
une commutation groupée (tous les ports à la fois) ou une commutation par port (individuelle).
Notez que par défaut uhubctl ne détecte que les hubs USB qui prennent en charge la commutation d'alimentation par port
(mais vous pouvez forcer son fonctionnement sur des hubs non pris en charge avec l'option -f).
Vous pouvez savoir quel type de commutation d'alimentation votre matériel prend en charge en utilisant sudo lsusb -v :
Aucune commutation d'alimentation :
wHubCharacteristic 0x000a
No power switching (usb 1.0)
Per-port overcurrent protection
Commutation d'alimentation groupée :
wHubCharacteristic 0x0008
Ganged power switching
Per-port overcurrent protection
Commutation d'alimentation par port :
wHubCharacteristic 0x0009
Per-port power switching
Per-port overcurrent protection
- Exécutez
sudo uhubctl. Si votre hub n'y figure pas, il n'est pas pris en charge.
Vous pouvez également exécuter sudo lsusb -v et rechercher
Per-port power switching - si vous ne voyez pas une telle ligne dans la sortie de lsusb,
le hub n'est pas pris en charge.
- Vérifiez la prise en charge de la coupure de VBUS (tension) : branchez un téléphone, une lampe USB
ou un ventilateur USB sur un port USB de votre hub.
Essayez d'utiliser
uhubctl pour couper l'alimentation de ce port et vérifiez
que le téléphone cesse de se charger, que la lampe USB cesse de briller ou que le ventilateur USB cesse de tourner.
Si le VBUS ne se coupe pas, le fabricant de votre hub n'a pas inclus les circuits
nécessaires pour réellement couper l'alimentation. Un tel hub fonctionnera tout de même
pour couper la connexion de données USB, mais il ne peut pas couper l'alimentation,
et nous ne considérons pas cet appareil comme pris en charge.
- Si les tests ci-dessus ont réussi, veuillez signaler votre hub
en ouvrant un nouveau problème sur https://github.com/mvp/uhubctl/issues,
afin que nous puissions l'ajouter à la liste des appareils pris en charge.
Veuillez ne pas signaler les hubs non pris en charge, à moins qu'il s'agisse d'une révision
matérielle différente d'un modèle déjà répertorié comme pris en charge.
Les périphériques USB ne sont pas supprimés après la coupure de l'alimentation du port sous Linux
Après avoir coupé l'alimentation d'un port USB, udev ne reçoit aucun événement, il conserve donc les fichiers de périphérique.
Cependant, toute tentative d'accès aux fichiers de périphérique entraînera une erreur d'E/S.
Il s'agit d'un problème du noyau Linux, corrigé
depuis uhubctl 2.5.0 pour les systèmes avec un noyau Linux 6.0 ou ultérieur.
Si vous utilisez encore Linux 5.x ou une version antérieure, vous pouvez utiliser cette solution de contournement pour ce problème :
sudo uhubctl -a off -l ${location} -p ${port}
sudo udevadm trigger --action=remove /sys/bus/usb/devices/${location}.${port}/
Le fichier de périphérique sera supprimé par udev, mais le périphérique USB restera visible dans lsusb.
Notez que le chemin /sys/bus/usb/devices/${location}.${port} n'existera que si un périphérique a été détecté sur ce port.
Lorsque vous rallumez l'alimentation, le périphérique devrait se ré-énumérer correctement (pas besoin de rappeler udevadm).
L'alimentation se rallume après quelques secondes sous Linux
Certains pilotes de périphérique du noyau sont surpris par la mise hors tension d'un périphérique USB et tentent automatiquement de le rallumer.
Il s'agit d'un problème du noyau Linux, corrigé
depuis uhubctl 2.5.0 pour les systèmes avec un noyau Linux 6.0 ou ultérieur.
Si vous utilisez encore Linux 5.x ou une version antérieure :
Vous pouvez utiliser l'option -r N, où N est un nombre de 10 à 1000, pour corriger ce problème -
uhubctl essaiera de couper l'alimentation plusieurs fois rapidement, ce qui devrait supprimer ce comportement.
La désactivation de l'autorisation USB du périphérique concerné avant de couper l'alimentation avec uhubctl devrait aider :
echo 0 > sudo tee /sys/bus/usb/devices/${location}.${port}/authorized
Si votre périphérique est un stockage de masse USB, invoquer udisksctl avant d'appeler uhubctl devrait également aider :
sudo udisksctl power-off --block-device /dev/disk/...`
sudo uhubctl -a off ...
Plusieurs hubs 4 ports sont détectés, mais je n'ai qu'un hub 7 ports connecté
De nombreux fabricants de hubs construisent leurs hubs USB à partir de puces USB de base à 4 ports.
Par exemple, pour fabriquer un hub 7 ports, ils connectent en chaîne deux hubs 4 ports - 1 port est perdu pour la connexion en chaîne,
ce qui donne un hub de 4+4-1=7 ports. De même, un hub 10 ports pourrait être construit avec 3 hubs 4 ports
connectés en chaîne, ce qui donne 4+4+4-2=10 ports utilisables.
Notez que vous ne devez jamais tenter de modifier l'état d'alimentation des ports utilisés pour connecter en chaîne les hubs internes.
Cela perturberait les circuits internes du hub et provoquerait un comportement imprévisible.
Le Raspberry Pi coupe l'alimentation sur tous les ports, pas seulement sur celui que j'ai spécifié
C'est une limitation de la conception matérielle du Raspberry Pi.
Pour contourner ce problème, vous pouvez acheter un hub USB externe de la liste prise en charge ci-dessus,
le connecter à n'importe quel port USB du Raspberry Pi et contrôler l'alimentation de ses ports indépendamment.
Il existe également des hubs pris en charge conçus spécifiquement pour le Raspberry Pi, par exemple UUGear MEGA4.
Pour référence, les modèles de Raspberry Pi pris en charge ont la topologie USB interne suivante :
Raspberry Pi B+,2B,3B
-
Hub unique 1-1, ports 2 à 5 groupés, tous contrôlés par le port 2 :
Tenter de contrôler les ports 3,4,5 ne fera rien.
Le port 1 contrôle l'alimentation de l'Ethernet+WiFi.
Raspberry Pi 3B+
-
Hub principal 1-1, les 4 ports sont groupés, tous contrôlés par le port 2 (coupe également les ports du hub secondaire).
Le port 1 connecte le hub 1-1.1 ci-dessous, les ports 2 et 3 sont câblés à l'extérieur, le port 4 n'est pas câblé.
-
Hub secondaire 1-1.1 (connecté en chaîne au hub principal) : 3 ports,
le port 1 est utilisé pour l'Ethernet+WiFi, et les ports 2 et 3 sont câblés à l'extérieur.
Raspberry Pi 4B
⚠️ Si votre firmware VL805 est plus ancien que 00137ad (vérifiez avec sudo rpi-eeprom-update),
vous devez mettre à jour le firmware
pour que la commutation d'alimentation fonctionne sur RPi 4B.
-
Hub USB2 1, 1 port, ne connecte que le hub 1-1 ci-dessous.
-
Hub USB2 1-1, 4 ports groupés, correspondant au hub USB3 2 ci-dessous :
-
Hub USB3 2, 4 ports groupés, correspondant au hub USB2 1-1 ci-dessus :
-
Hub USB2 3, 1 port, contrôleur OTG. La commutation d'alimentation n'est pas prise en charge.
Raspberry Pi 5
Le Raspberry Pi 5 dispose de deux ports USB2 et de deux ports USB3 (4 au total).
Ces ports sont connectés à 4 hubs USB distincts 1,2,3,4 dans une configuration vraiment étrange
(mais selon le système d'exploitation et la révision matérielle, les hubs concernés peuvent être 2,3,4,5).
Si un périphérique USB3 est connecté à une prise bleue, il sera détecté sur le hub USB3 2 ou 4.
Si un périphérique USB2 est connecté à n'importe quelle prise ou qu'un périphérique USB3 est connecté à une prise noire,
il sera détecté sur le hub USB2 1 ou 3.
Quel que soit le type de connexion USB2/USB3, les prises bleues sont toujours le port 1,
et les prises noires sont toujours le port 2.
Chacun des 4 hubs USB intégrés annonce prendre en charge la commutation d'alimentation par port, mais ce n'est pas vrai.
En réalité, sur le Raspberry Pi 5, les 4 ports sont groupés dans un seul ensemble,
bien qu'ils appartiennent à 4 hubs USB logiques différents.
Pour couper l'alimentation VBUS, celle-ci doit être désactivée sur tous les hubs et ports intégrés avec : ```
uhubctl -l 2 -a 0
uhubctl -l 4 -a 0
Pour le réactiver : ```
uhubctl -l 2 -a 1
uhubctl -l 4 -a 1
Notez que l'alimentation VBUS n'est coupée que si tous les ports sont éteints -
activer un seul port réactive l'alimentation VBUS pour les 4 ports.
Projets notables utilisant uhubctl
Droits d'auteur
Copyright (C) 2009-2026 Vadim Mikhailov
Ce fichier peut être distribué selon les termes et conditions de la
GNU General Public License version 2.