217 votes

Comment réinitialiser un périphérique USB à partir de la ligne de commande ?

Est-il possible de réinitialiser la connexion d'un périphérique USB, sans le déconnecter/le connecter physiquement au PC ?

Plus précisément, mon appareil est un appareil photo numérique. J'utilise gphoto2 mais dernièrement, je reçois des "erreurs de lecture du périphérique", alors j'aimerais essayer de réinitialiser la connexion par logiciel.

D'après ce que je peux dire, aucun module du noyau n'est chargé pour la caméra. Le seul qui semble lié est usbhid .

6voto

chandank Points 299

La façon la plus rapide de réinitialiser sera de réinitialiser le contrôleur USB lui-même. Cela obligera udev à désenregistrer le périphérique à la déconnexion, et à le réenregistrer une fois que vous l'aurez activé.

echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci_hcd/unbind
echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci_hcd/unbind
echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci_hcd/bind
echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci_hcd/bind

Cela devrait fonctionner pour la plupart des environnements PC. Cependant, si vous utilisez un matériel personnalisé, vous pouvez simplement itérer à travers les noms de périphériques. Avec cette méthode, vous n'avez pas besoin de trouver le nom du périphérique par lsusb. Vous pouvez également incorporer dans un script automatisé.

5voto

J'utilise une sorte de marteau-pilon en rechargeant les modules. C'est mon usb_reset.sh script :

#!/bin/bash

# USB drivers
rmmod xhci_pci
rmmod ehci_pci

# uncomment if you have firewire
#rmmod ohci_pci

modprobe xhci_pci
modprobe ehci_pci

# uncomment if you have firewire
#modprobe ohci_pci

Et voici mon fichier de service systemd /usr/lib/systemd/system/usbreset.service qui exécute usb_reset.sh après le démarrage de mon gestionnaire d'affichage :

[Unit]
Description=usbreset Service
After=gdm.service
Wants=gdm.service

[Service]
Type=oneshot
ExecStart=/path/to/usb_reset.sh

5voto

mviereck Points 209

Comme le cas particulier de la question est un problème de communication de gphoto2 avec un appareil photo sur USB, il y a une option dans gphoto2 pour réinitialiser sa connexion USB :

gphoto2 --reset

Peut-être que cette option n'existait pas en 2010 lorsque la question a été posée.

5voto

thelsdj Points 3344

Voici script qui ne réinitialisera qu'un ID produit/vendeur correspondant.

#!/bin/bash

set -euo pipefail
IFS=$'\n\t'

VENDOR="045e"
PRODUCT="0719"

for DIR in $(find /sys/bus/usb/devices/ -maxdepth 1 -type l); do
  if [[ -f $DIR/idVendor && -f $DIR/idProduct &&
        $(cat $DIR/idVendor) == $VENDOR && $(cat $DIR/idProduct) == $PRODUCT ]]; then
    echo 0 > $DIR/authorized
    sleep 0.5
    echo 1 > $DIR/authorized
  fi
done

4voto

Raghu Points 41

J'ai fait un script Python qui va réinitialiser un périphérique USB particulier en fonction du numéro du périphérique. Vous pouvez trouver le numéro du périphérique à partir de la commande lsusb.

par exemple :

$ lsusb

Bus 002 Device 004: ID 046d:c312 Logitech, Inc. DeLuxe 250 Keyboard

Dans cette chaîne, 004 est le numéro du dispositif

import os
import argparse
import subprocess

path='/sys/bus/usb/devices/'

def runbash(cmd):
    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    out = p.stdout.read().strip()
    return out

def reset_device(dev_num):
    sub_dirs = []
    for root, dirs, files in os.walk(path):
            for name in dirs:
                    sub_dirs.append(os.path.join(root, name))

    dev_found = 0
    for sub_dir in sub_dirs:
            if True == os.path.isfile(sub_dir+'/devnum'):
                    fd = open(sub_dir+'/devnum','r')
                    line = fd.readline()
                    if int(dev_num) == int(line):
                            print ('Your device is at: '+sub_dir)
                            dev_found = 1
                            break

                    fd.close()

    if dev_found == 1:
            reset_file = sub_dir+'/authorized'
            runbash('echo 0 > '+reset_file) 
            runbash('echo 1 > '+reset_file) 
            print ('Device reset successful')

    else:
            print ("No such device")

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--devnum', dest='devnum')
    args = parser.parse_args()

    if args.devnum is None:
            print('Usage:usb_reset.py -d <device_number> \nThe device    number can be obtained from lsusb command result')
            return

    reset_device(args.devnum)

if __name__=='__main__':
    main()

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X