web-dev-qa-db-fra.com

Linux USB: allumer et éteindre?

Comment puis-je activer et désactiver par programme l'alimentation d'un port USB particulier sous Linux? Une telle chose est-elle possible? Les réponses Mac ont également été appréciées!

J'essayais d'obtenir un BOC (ne prétendez pas que vous n'essayiez pas d'en obtenir un aussi!) Et je me suis retrouvé avec un de ceux-ci, et j'aimerais en avoir une certaine utilisation en le connectant à notre moniteur de serveur.

59
Mark Harrison

Digs par les signets

http://blog.andrew.net.au/2009/01/01#usb_power_control

On dirait que vous devez le connecter à un hub et contrôler son alimentation. Aucun des concentrateurs racine que j'ai vus ne semble capable de prendre en charge le contrôle de l'alimentation.

7
Savant Degrees

Il existe une entrée système pour cela dans Linux. De Documentation/usb/power-management.txt :

niveau d'énergie

This file contains one of three words: "on", "auto",
or "suspend".  You can write those words to the file
to change the device's setting.

"on" means that the device should be resumed and
autosuspend is not allowed.  (Of course, system
suspends are still allowed.)

"auto" is the normal state in which the kernel is
allowed to autosuspend and autoresume the device.

"suspend" means that the device should remain
suspended, and autoresume is not allowed.  (But remote
wakeup may still be allowed, since it is controlled
separately by the power/wakeup attribute.)

Quelque chose comme: echo on > /sys/bus/usb/devices/usb5/power/level

Vous devrez peut-être également jouer avec le paramètre autosuspend. Sans dire au noyau d'arrêter d'essayer, il peut suspendre le port automatiquement.

Bonne chance!

24
mixonic

L'interaction usbfs semble avoir changé plusieurs fois depuis la réponse à cette question. Voici donc comment allumer le port du concentrateur sous Ubuntu Oneiric Ocelot à partir d’un shell Bash.

Recherchez le bus et le numéro d'appareil:

Sudo lsusb -v|less

Localisez le périphérique dans la hiérarchie des ports bus/hub à l'aide du bus et du numéro de périphérique:

Sudo lsusb -t|less

La syntaxe semble être "bus-port.port.port.port.port ..." Par exemple, ma souris est connectée à un hub externe qui se connecte au hub de mon ordinateur qui se connecte en interne à un hub racine:

/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=hub, Driver=hub/6p, 480M
        |__ Port 1: Dev 3, If 0, Class=hub, Driver=hub/3p, 480M
            |__ Port 1: Dev 6, If 0, Class=HID, Driver=usbhid, 1.5M

Donc, '2-1.1.1' dans le cas ci-dessus. Enfin, redémarrez l’alimentation du port:

echo '2-1.1.1'|Sudo tee /sys/bus/usb/drivers/usb/unbind
sleep 1
echo '2-1.1.1'|Sudo tee /sys/bus/usb/drivers/usb/bind

Je n'ai pas branché un analyseur de protocole pour savoir ce qui se passe réellement dans le bus, mais je sais que la lumière de la souris s'éteint lorsque je le dissocie. J'imagine qu'une couche inférieure interagit avec le contrôleur hôte EHCI pour éteindre le port. Ceci est particulièrement utile pour les périphériques intégrés, tels que les webcams UVC, qui ne semblent jamais fonctionner correctement et qui nécessiteraient sinon un redémarrage du système pour se réinitialiser.

Voir aussi la commande udevadm.

15

Vous pouvez utiliser uhubctl -, un utilitaire de ligne de commande pour contrôler l’alimentation USB par port pour les concentrateurs USB compatibles.

Il ne fonctionne que sur les concentrateurs prenant en charge la commutation d'alimentation par port, mais notez que de nombreuses cartes mères modernes possèdent des concentrateurs USB prenant en charge cette fonctionnalité. En outre, la dernière version d’uhubctl prend en charge les concentrateurs USB 3.0. La bonne nouvelle est que bon nombre de nouveaux concentrateurs USB 3.0 prennent en charge cette fonctionnalité.

Compiler:

git clone https://github.com/mvp/uhubctl
cd uhubctl
make

Pour lister le statut de tous les hubs et ports pouvant être contrôlés par uhubctl:

uhubctl

Pour mettre le port 5 du concentrateur compatible unique hors tension:

uhubctl -a 0 -p 5

Pour mettre sous tension tous les ports de tous les concentrateurs compatibles:

uhubctl -a 1

Pour éteindre puis rallumer:

uhubctl -a 2 -p 5

Lire plus ici .

Divulgation - Je suis l'auteur de uhubctl.

5
mvp

Voici un exemple avec une souris sans fil USB Logitech sous Linux.

Lisez le paragraphe correspondant de "/ proc/bus/usb/devices" en fonction de vos périphériques "Vendor" (id du fournisseur) et "ProdID" (id du produit) Ou "Fabricant" et "Produit" (toutes ces valeurs sont constantes par appareil).

cat /proc/bus/usb/devices

(premier paragraphe avec appareil allumé, deuxième avec le même appareil éteint mais toujours branché)

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  4 Spd=1.5 MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=046d ProdID=c50e Rev=25.10
S:  Manufacturer=Logitech
S:  Product=USB RECEIVER
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 70mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=usbhid
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=10ms

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  4 Spd=1.5 MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=046d ProdID=c50e Rev=25.10
S:  Manufacturer=Logitech
S:  Product=USB RECEIVER
C:  #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 70mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=10ms

Vous avez besoin de deux variables ici . Elles sont situées dans la ligne "T:" (première ligne du paragraphe) . Ces variables sont: Bus (Bus = 01 dans cet exemple) Cnt (Cnt = 01 dans cet exemple)

Vous devrez ajouter "1" (une arithmétique) à "Cnt" pour obtenir le rang Rank = Cnt + 1 (il s'agit d'une fonction mathématique, Rank = 2 dans cet exemple)

Donc, le périphérique que vous recherchez est la chaîne suivante: Rang de bus (ce n'est pas une fonction mathématique, c'est une chaîne, 1-2 dans cet exemple)

Notez également la ligne "C:" . Elle contient des informations sur la puissance (courant) de l'appareil . S'il y a un astérisque dans "C: " (comme dans notre premier exemple), alors le périphérique est alimenté . Si ce n'est pas le cas ("C:"), il est "plus ou moins" éteint, ce qui signifie qu'il y a toujours un très faible courant lorsqu'un périphérique est branché, sinon nous ne pourrions pas tout lire. cette info.

Remarquez enfin la ligne "I:" . Si le champ "I: *" contient un astérisque (comme dans notre premier exemple), il y a entrée, de ou vers le périphérique, je ne suis pas sûr, peut-être les deux ..___ Le dernier champ de ligne contient le pilote utilisé ("usbhid" dans notre premier exemple)

Nous sommes prêts à allumer l'alimentation de notre appareil:

éteindre

echo -n "Bus-Rank" > /sys/bus/usb/drivers/usb/unbind
echo -n "1-2" > /sys/bus/usb/drivers/usb/unbind (in our example)

allumer

echo -n "Bus-Rank" > /sys/bus/usb/drivers/usb/bind
echo -n "1-2" > /sys/bus/usb/drivers/usb/bind (in our example)

Ce qui suit est un simple script bash "USBMS" (USB Mouse Switch) qui contrôle la puissance du périphérique dans notre exemple ci-dessus . Il n’est pas très dynamique et utilise les constantes "Product" et "Manufacturer" pour localiser le Paragraphe correspondant de "/proc/bus/usb/devices"Vous devez utiliser le" Vendeur "(identifiant du fournisseur) et le" ProdID "(identifiant du produit) à la place . Il vérifie également l'état d'alimentation du périphérique. Exécuter en tant que superutilisateur.

Commande: action ./USBMS

paramètre: action = "off" ou "0" pour mettre hors tension - action = "on" ou "1" pour mettre sous tension (sans les guillemets)

#!/bin/bash

     USBmouseProduct="USB RECEIVER"
USBmouseManufacturer="Logitech"

              signal=$1

nr3=$(awk '/Product='"$USBmouseProduct"'/ {print NR}' /proc/bus/usb/devices)
nr3=$(expr $nr3 + 0)
nr2=$(awk '/Manufacturer='"$USBmouseManufacturer"'/ {print NR}' /proc/bus/usb/devices)
nr2=$(expr $nr2 + 0)
nr1=$(expr $nr2 - 3)
nr4=$(expr $nr3 + 1)
nrdiff=$(expr $nr3 - $nr2)

[ $nr3 != 0 -a $nr2 != 0 -a $nrdiff = 1 ] && (
                                                 usbmbus0=$(awk 'NR=='$nr1' {print $2}' /proc/bus/usb/devices | awk -F= '{print $2}')
                                                  usbmbus=$(expr $usbmbus0 + 0)
                                                  usbmdev=$(awk 'NR=='$nr1' {print $8}' /proc/bus/usb/devices)
                                                 usbmrank=$(awk 'NR=='$nr1' {print $5}' /proc/bus/usb/devices | awk -F= '{print $2}')
                                                 usbmrank=$(expr $usbmrank + 1)
                                               usbmbusrank="$usbmbus""-""$usbmrank"
                                                usbmpower=$(awk 'NR=='$nr4' {if ( $1=="C:" ) {print 0}; if ( $1=="C:*" ) {print 1}}' /proc/bus/usb/devices)

                                               case $signal in
                                                              off|0)
                                                                    [ $usbmpower = 1 ] && echo -n "$usbmbusrank" > /sys/bus/usb/drivers/usb/unbind
                                                                    ;;
                                                               on|1)
                                                                    [ $usbmpower = 0 ] && echo -n "$usbmbusrank" > /sys/bus/usb/drivers/usb/bind
                                                                    ;;
                                               esac
                                             )
4
RVF16

@Kristian Généralement, vous ne trouverez pas de publicité contrôlée par un port contrôlé par logiciel, car les utilisateurs ne devraient pas être conscients de cette couche. Je ne pense pas que les cas d’utilisation qui en découlent soient nombreux, mis à part le fait de forcer les périphériques mal alimentés par le bus à un état connu, et le traitement de périphériques muets comme des périphériques de poste utilisant uniquement l’USB pour le pouvoir. Le dispositif de Mark appartient peut-être à cette dernière catégorie. C'est un mécanisme brut, de dernier recours.

Comme je l’ai mentionné, je n’ai pas examiné les détails d’implémentation du piratage non corrélé et je l’ai seulement essayé sur le contrôleur hôte EHCI intégré à ma carte mère, un contrôleur hôte USB amélioré de la famille de chipsets Intel Corporation série 6/C200 rev 05). " Je suppose que ce contrôleur hôte a le bit PPC de HCSPARAMS, indiquant le contrôle logiciel des commutateurs d'alimentation de port, conformément aux spécifications EHCI.

Si vous vous connectez à un concentrateur externe, "un concentrateur indique s'il prend ou non en charge la commutation d'alimentation en définissant le champ Mode de commutation d'alimentation logique dans wHubCharacteristics", conformément à la spécification USB 2.0. Je ne me souviens pas si les tests de conformité assurent cette fonctionnalité ou non, mais s'ils le font, il vous suffira de trouver un concentrateur portant le logo USB 2.0. Je suppose que le piratage enverrait une demande de fonctionnalité de port définie, mais il est possible que le cycle ne se limite pas au port cible. Encore une fois, selon les spécifications USB 2.0, "un concentrateur avec des commutateurs d'alimentation peut alimenter tous les ports en groupe/groupe, individuellement, ou avoir un nombre arbitraire de groupes d'un ou de plusieurs ports". Je ne suis pas sûr s'il existe un outil de ligne de commande de Nice pour obtenir wHubCharacteristics.

En bref, il n’existe pas, à ma connaissance, de solution générique pour traiter ce problème. Cependant, il est possible d'interroger un hub interne ou externe pour déterminer son niveau de support, puis, s'il est supporté, l'utiliser. C'est juste une question de combien de temps vous voulez passer ainsi.

3
Stephen Niedzielski

Sous OS X, vous pouvez accéder à un périphérique USB à partir de l'espace utilisateur et demander sa suspension.

Vous trouverez un exemple général dans/ Guide de l’interface de périphérique USB . Vous devrez utiliser la méthode IOUSBDeviceInterface182 (ou supérieure) USBDeviceSuspend .

Remarque: les concentrateurs et les ports de contrôleur peuvent avoir des blocs d'alimentation groupés, ce qui signifie qu'un même commutateur est partagé par plusieurs ports. Si tel est le cas et que votre appareil appartient au même groupe qu'un autre appareil actif, il ne sera pas mis hors tension.

2
Hasturkun

niveau d'énergie

"on" signifie que le périphérique doit être repris et qu'autosuspend n'est pas autorisé (bien sûr, les suspensions du système sont toujours autorisées).

"auto" est l'état normal dans lequel le noyau est autorisé à autosuspend et autoresume le périphérique.

"suspendre" signifie que le périphérique doit rester suspendu, et la reprise automatique n'est pas autorisée. (Mais le réveil à distance peut toujours être autorisé, Puisqu'il est contrôlé séparément par l'attribut power/wakeup.)

Étape 1:j'ai donc, usb1, usb2, usb3, usb4 ....

$ cat /sys/bus/usb/devices/usb*/power/level
auto
auto
auto
auto

Étape 2:comment saurais-je lequel est lequel? ( 

# echo "on" | tee /sys/bus/usb/devices/usb*/power/level
# cat /sys/bus/usb/devices/usb*/power/level
on
on
on
on

Optional 1:au cas où le lsusb apparaît et doit en trouver un spécifique

#!/bin/bash
usb="046d:082d" # Find ME, Replace the ID 

cam=$(lsusb | awk "/$usb/ {print $6}")
echo $cam
if [ ! -z "$cam" -a "$cam" != " " ]; then
  for X in /sys/bus/usb/devices/*;
  do
    a=$(cat "$X/idVendor" 2>/dev/null)
    b=$(cat "$X/idProduct" 2>/dev/null)
    c="$a:$b"
    if [ ! -z "$c" -a "$c" != " " ] && [ "$c" == "$usb" ]; then
      d=$(echo $X | sed "s/\/sys\/bus\/usb\/devices\///g")
      echo "[FOUND] $d"

      #Sudo sh -c "echo on > /sys/bus/usb/devices/$d/authorized"
      sleep 2
      #Sudo sh -c "echo on > /sys/bus/usb/devices/$d/authorized"
      lsusb
      break

    fi
  done;
fi

Facultatif 2:si aucun fichier n'est trouvé - le redémarrage ne parvient pas à redémarrer, utilisez le relais Arduino via udp.

#!/bin/bash

file="/var/www/html/video/now.jpeg"

function age() {
   local filename=$1
   local changed=`stat -c %Y "$filename"`
   local now=`date +%s`
   local elapsed
   let elapsed=now-changed
   echo $elapsed
}

while true
do
  target="/dev/video99"
  foundon="none"
  warn="[WARNING]:"
  ok="[OK]:"
  for i in 0 1 2 3 4
  do
    tmp="/dev/video$i"
    if [ -e $tmp ]; then
      foundon="/dev/video$i"
    #else
    #  echo "no $i"
    fi
  done

  b="none"
  if [ "$foundon" = "$b" ]; then
    echo "$warn No camera is found - inform reboot or arduino boot"

  else
    echo "$ok ln -s $foundon $target"

    ### Camera is available but something is not correct so ###
    file_age=$(age "$file")
    echo The age of $file is $file_age seconds.

    if [[ ! -f $file ]]; then
      echo "file is not found. Kernel sucks for 500mA USB's"
    else
      echo "found file: $file_age"
      if [[ $file_age -gt 240 ]]; then
        echo "$warn greater then 240 seconds"

      else
        echo "$ok - less then 240 seconds"

      fi
    fi
  fi

ls /dev/video*
sleep 5

done

Relais Arduino: 

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD};
IPAddress ip(10,109,4,166);
byte gateway[]= {10,109, 0, 1};
byte subnet[]= {255, 255, 248,0};

unsigned int localPort = 8888;

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char  ReplyBuffer[] = "ackv1";
EthernetUDP Udp;
int led1 = 2;
int led2 = 3;

void setup() {
  Ethernet.begin(mac,ip);
  //Ethernet.begin(mac, ip, '8.8.8.8', gateway, subnet);
  Udp.begin(localPort);

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);

  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
}

void loop() {
  int packetSize = Udp.parsePacket();
  if(packetSize) {
    delay(1000);
    digitalWrite(led1, HIGH);    // turn the LED off by making the voltage LOW
    delay(3000);
    digitalWrite(led1, LOW);   // turn the LED on (HIGH is the voltage level)

    delay(1000);
    digitalWrite(led2, HIGH);    // turn the LED off by making the voltage LOW
    delay(3000);
    digitalWrite(led2, LOW);   // turn the LED on (HIGH is the voltage level)


    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}
2
YumYumYum

Je serais plus enclin à couper le fil et à le raccorder à un port série avec un type de relais simple exécutant l'une des fiches de réception reçues. Ensuite, vous pouvez simplement tirer la ligne vers le bas (signalez que je suis prêt à recevoir) dans le fichier de port série chaque fois qu'il y a un problème. Quand c'est fait, il suffit de signaler 'je suis plein'

D'après ce que je comprends de ces choses, elles consomment beaucoup de courant jusqu'à ce qu'elles chargent complètement le condensateur, puis les relâchent en même temps pour faire clignoter l'ampoule. Je ne peux pas imaginer qu'une telle décharge soudaine soit bénéfique pour les circuits de l'ordinateur. vous aurez peut-être besoin de certaines interruptions de courant de diode pour empêcher tout retour dans le port série.

Chaque fois que mon réveil sonne, l'ordinateur s'arrête!

1
Ape-inago

Un quelques concentrateurs USB peut activer ou désactiver leurs ports, comme expliqué dans le lien. Je n'ai pas encore trouvé de carte mère avec des ports USB pouvant être activée ou désactivée.

1
ptonelli

Vous utilisez simplement "echo" en tant que root, essayez:

echo suspend | Sudo tee /sys/bus/usb/devices/usb3/power/level
0
Adaś

N'achetez pas un hub intelligent coûteux juste pour allumer et éteindre des gadgets USB.
Tout ce dont vous avez besoin est un microcontrôleur.

Arduino Nano ™ ATmega328 *1enter image description here

Le Nano est un ordinateur 8 bits à 16 MHz avec 2K RAM et 32K de stockage flash.
Il a 22 broches programmables (8 analogiques et 14 numériques).
Il peut lire/écrire USB et est alimenté par son port microUSB 5.0V (jusqu’à 12.0V externe).

// USB Blinker
// Blink LED while receiving USB stream
//
// For Arduino Nano™

int LED = 13;

// setup() is run once at powerup or when reset button is pressed
//
void setup() {
        pinMode(LED, OUTPUT);   // Configure pin D13 as output 
        Serial.begin(9600);     // Open 9600bps USB stream
}

// loop() runs forever at 16Mhz, blinking the LED at 1Hz when receiving USB data.
// 
void loop() { 
        if (Serial.available() > 0) {           // When stream is buffering
                digitalWrite(LED, HIGH);        //   turn on LED 
                delay(500);                     //   wait half second
                digitalWrite(LED, LOW);         //   turn off LED
                delay(500);                     //   wait half second
                while (Serial.available() > 0)  //   drain the buffer
                        Serial.read();         
         }
}


De minuscules valises sont disponibles (également des imprimables gratuits 3d ).

C4Labs Zebra Black Ice Case
6

* Utilisez uniquement les produits Arduino Nano ™ authentiques. Attention aux contrefaçons .

MISE À JOUR: Des microcontrôleurs ATtiny et sans fil miniaturisés sont également disponibles.

0
Dominic Cerisano