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

164

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

Plus précisément, mon appareil est un appareil photo numérique. J'utilise gphoto2, mais dernièrement, des "erreurs de lecture de l'appareil" se produisent, j'aimerais donc essayer de réinitialiser le logiciel de la connexion.

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

cmcginty
la source
Quelle version d'Ubuntu utilisez-vous?
Utilisateur
J'ai essayé les deux solutions de Li Lo et de ssokolow, tout ce que j'obtiens est une permission refusée, si j'utilise le code usbreset ou la ligne de commande "echo 0> ...", j'utilise sudo, mes périphériques usb sont également la propriété de root peut les utiliser sans droits d'administrateur (caméras ..)
1
Si vous obtenez des erreurs de lecture, il est possible que certaines données soient corrompues. Si votre appareil photo utilise une carte mémoire externe (telle que MicroSD), il peut être judicieux de la connecter à l'ordinateur et d'exécuter fsck.
TSJNachos117

Réponses:

118

Enregistrez les éléments suivants sous usbreset.c

/* usbreset -- send a USB port reset to a USB device */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <linux/usbdevice_fs.h>


int main(int argc, char **argv)
{
    const char *filename;
    int fd;
    int rc;

    if (argc != 2) {
        fprintf(stderr, "Usage: usbreset device-filename\n");
        return 1;
    }
    filename = argv[1];

    fd = open(filename, O_WRONLY);
    if (fd < 0) {
        perror("Error opening output file");
        return 1;
    }

    printf("Resetting USB device %s\n", filename);
    rc = ioctl(fd, USBDEVFS_RESET, 0);
    if (rc < 0) {
        perror("Error in ioctl");
        return 1;
    }
    printf("Reset successful\n");

    close(fd);
    return 0;
}

Le exécuter les commandes suivantes dans le terminal:

  1. Compiler le programme:

    $ cc usbreset.c -o usbreset
    
  2. Obtenez les identifiants de bus et de périphérique du périphérique USB que vous souhaitez réinitialiser:

    $ lsusb  
    Bus 002 Device 003: ID 0fe9:9010 DVICO  
    
  3. Rendre notre programme compilé exécutable:

    $ chmod +x usbreset
    
  4. Exécutez le programme avec le privilège sudo; effectuez les substitutions nécessaires <Bus>et les <Device>identifiants trouvés en exécutant la lsusbcommande:

    $ sudo ./usbreset /dev/bus/usb/002/003  
    

Source du programme ci-dessus: http://marc.info/?l=linux-usb&m=121459435621262&w=2

Li Lo
la source
3
Cela fonctionne avec Ubuntu 13.10. L'identifiant de l'appareil peut varier. POUR l'obtenir pour la souris, j'ai enveloppé le code ci-dessus dans quelques commandes shellecho $(lsusb | grep Mouse) mouse=$( lsusb | grep Mouse | perl -nE "/\D+(\d+)\D+(\d+).+/; print qq(\$1/\$2)") sudo /path/to/c-program/usbreset /dev/bus/usb/$mouse
knb
1
mon disque externe semble devenir indétectable (je dois bien reconnecter le câble USB); il s’agit d’un port USB 2.0 connecté à un port PC de bureau USB 3.0; lorsque je lance usbreset /dev/bus/usb/011/001c’est l’un des 2 concentrateurs racine usb 3.0 lsusb, il se trompe: "Erreur dans ioctl: un répertoire", aucune idée? J'ai essayé sur les deux hubs usb 3.0
Aquarius Power
1
Si quelqu'un qui lit ceci a un gel de la souris (usb) après s'être connecté à Ubuntu 16.04 (avec dmesg rempli par "input irq status -75"), je peux confirmer qu'il s'agit de la seule solution qui a fonctionné pour moi. Merci
Agustin Baez
1
@ Aquarius, je reçois aussi la même erreur "Erreur dans ioctl: est un répertoire". Est-ce résolu?
Ransh
1
Voir ma réponse ici askubuntu.com/a/988297/558070 qui utilise la même méthode de réinitialisation que cette réponse mais permet également une liste simplifiée des appareils et la recherche de ceux-ci.
mcarans
58

Je ne me suis jamais trouvé dans votre situation particulière auparavant, alors je ne sais pas si cela suffira, mais la façon la plus simple que j'ai trouvée de réinitialiser un périphérique USB est cette commande: (Aucune application externe nécessaire)

sudo sh -c "echo 0 > /sys/bus/usb/devices/1-4.6/authorized"
sudo sh -c "echo 1 > /sys/bus/usb/devices/1-4.6/authorized"

C’est celui que j’utilise pour réinitialiser mon Kinect car libfreenect ne semble pas avoir d’API pour le remettre en veille. C'est sur ma boîte Gentoo, mais le noyau devrait être suffisamment nouveau pour utiliser la même structure de chemin pour sysfs.

Évidemment, ce n’est pas le cas, 1-4.6mais vous pouvez extraire le chemin de votre périphérique à partir de votre log ( dmesg) (logernel ) ou vous pouvez utiliser quelque chose comme lsusbobtenir les ID du fournisseur et du produit, puis utiliser une commande rapide comme celle-ci pour répertorier le lien entre les chemins d’un fournisseur différent. / paires d'ID de produit:

for X in /sys/bus/usb/devices/*; do 
    echo "$X"
    cat "$X/idVendor" 2>/dev/null 
    cat "$X/idProduct" 2>/dev/null
    echo
done
ssokolow
la source
sh: 1: impossible de créer /sys/bus/usb/devices/1-3.1:1.0/authorized: annuaire inexistant
Nicolas Marchildon
On dirait qu'ils ont changé la disposition du système de fichiers usbfs. Je vais essayer de comprendre quelle est la nouvelle façon de faire les choses sur Ubuntu une fois que je ne suis plus aussi fatigué.
ssokolow
9
Merci a bien travaillé! Peut-être devriez-vous également mentionner d'effectuer un echo 1 > /sys/bus/usb/devices/whatever/authorizedscript dans un script pour réactiver l'appareil dès qu'il a été désactivé. Je l'ai fait à la fois avec ma souris et mon clavier USB et je me suis retrouvé avec un système complètement sourd :)
Avio
1
Il est extrêmement étrange de rétablir automatiquement la valeur 1, car la valeur 0 indique au système que vous ne voulez pas que le périphérique soit "autorisé" et donc inaccessible.
Tim Tisdall
2
Une note pour tous ceux qui essaient de passer à l’ | sudo tee ...approche des /sysécritures privilégiées : Cela tombe mal si vos informations d’identité sudo ne sont pas déjà mises en cache. sudo sh -c "..."fonctionne comme prévu lorsque sudo doit demander un mot de passe.
ssokolow
51

Ceci réinitialisera tous les ports USB1 / 2/3 connectés [1]:

for i in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*; do
  [ -e "$i" ] || continue
  echo "${i##*/}" > "${i%/*}/unbind"
  echo "${i##*/}" > "${i%/*}/bind"
done

Je crois que cela résoudra votre problème. Si vous ne souhaitez pas réinitialiser tous les points de terminaison USB, vous pouvez utiliser l'ID de périphérique approprié à partir de/sys/bus/pci/drivers/ehci_hcd


Remarques: [1]: les *hci_hcdpilotes du noyau contrôlent généralement les ports USB. ohci_hcdet uhci_hcdsont pour les ports USB1.1, ehci_hcdest pour les ports USB2 et xhci_hcdest pour les ports USB3. (voir https://en.wikipedia.org/wiki/Host_controller_interface_(USB,_Firewire) )

Tamás Tapsonyi
la source
croyez-vous que cela peut fonctionner pour réveiller un stockage USB ?
Aquarius Power
2
Bien que j'ai reçu le message suivant: ls: cannot access /sys/bus/pci/drivers/ehci_hcd/: No such file or directoryle problème a été résolu, la souris a immédiatement fonctionné. +1
Attila Fulop
2
@Otheus OHCI et UHCI sont les normes de l'hôte USB 1.1, EHCI est la norme de l'hôte USB 2.0 et XHCI est la norme de l'hôte USB 3.0.
ssokolow
2
C'est une belle solution. Cependant, sur certains noyaux plus tard et d' autres distributions * nix, vous constaterez que vous devez remplacer *hci_hcdavec *hci-pci, comme pilote hci_hcd est déjà compilé dans le noyau.
not2qubit
1
Sur un Banana Pi, il n'y a apparemment pas de bus PCI, je devais utiliser ce qui suit:for i in /sys/bus/usb/drivers/*/*:*; do
Martin Hansen
10

J'avais besoin d'automatiser cela dans un script python. J'ai donc adapté la réponse extrêmement utile de LiLo aux éléments suivants:

#!/usr/bin/env python
import os
import sys
from subprocess import Popen, PIPE
import fcntl
driver = sys.argv[-1]
print "resetting driver:", driver
USBDEVFS_RESET= 21780

try:
    lsusb_out = Popen("lsusb | grep -i %s"%driver, shell=True, bufsize=64, stdin=PIPE, stdout=PIPE, close_fds=True).stdout.read().strip().split()
    bus = lsusb_out[1]
    device = lsusb_out[3][:-1]
    f = open("/dev/bus/usb/%s/%s"%(bus, device), 'w', os.O_WRONLY)
    fcntl.ioctl(f, USBDEVFS_RESET, 0)
except Exception, msg:
    print "failed to reset device:", msg

Dans mon cas, il s’agissait du pilote cp210x (que je pourrais identifier lsmod | grep usbserial), vous pouvez donc enregistrer l’extrait ci-dessus sous le nom reset_usb.py, puis procédez comme suit:

sudo python reset_usb.py cp210x

Cela pourrait également être utile si vous n'avez pas déjà configuré le compilateur ca sur votre système, mais que vous avez le python.

Peter
la source
a travaillé pour moi sur un Raspberry
webo80
1
Quelques mots supplémentaires sur votre solution, s'il vous plaît. Par exemple, quelque chose à propos de la constante USBDEVFS_RESET. Est-ce toujours le même pour tous les systèmes?
not2qubit
@ not2qubit USBDEVFS_RESETest identique pour tous les systèmes. Pour MIPS il est 536892692.
mercredi
Les versions les plus récentes de lsusb semblent avoir besoin de l' -targument (mode arborescence) pour afficher les informations de pilote attendues par ce script, mais le script nécessite ensuite des mises à jour pour analyser les différentes lignes de sortie générées par ce script
Cheetah
Voir ma réponse ici askubuntu.com/a/988297/558070 pour une version nettement améliorée de ce script.
mcarans
8

J'ai créé un script Python qui simplifie l'ensemble du processus en fonction des réponses fournies.

Enregistrez le script ci-dessous sous le nom reset_usb.py ou clonez ce référentiel .

Usage:

python reset_usb.py help  # Show this help
sudo python reset_usb.py list  # List all USB devices
sudo python reset_usb.py path /dev/bus/usb/XXX/YYY  # Reset USB device using path /dev/bus/usb/XXX/YYY
sudo python reset_usb.py search "search terms"  # Search for USB device using the search terms within the search string returned by list and reset matching device
sudo python reset_usb.py listpci  # List all PCI USB devices
sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X  # Reset PCI USB device using path /sys/bus/pci/drivers/.../XXXX:XX:XX.X
sudo python reset_usb.py searchpci "search terms"  # Search for PCI USB device using the search terms within the search string returned by listpci and reset matching device

Scénario:

#!/usr/bin/env python
import os
import sys
from subprocess import Popen, PIPE
import fcntl

instructions = '''
Usage: python reset_usb.py help : Show this help
       sudo python reset_usb.py list : List all USB devices
       sudo python reset_usb.py path /dev/bus/usb/XXX/YYY : Reset USB device using path /dev/bus/usb/XXX/YYY
       sudo python reset_usb.py search "search terms" : Search for USB device using the search terms within the search string returned by list and reset matching device
       sudo python reset_usb.py listpci : List all PCI USB devices
       sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X : Reset PCI USB device using path
       sudo python reset_usb.py searchpci "search terms" : Search for PCI USB device using the search terms within the search string returned by listpci and reset matching device       
       '''


if len(sys.argv) < 2:
    print(instructions)
    sys.exit(0)

option = sys.argv[1].lower()
if 'help' in option:
    print(instructions)
    sys.exit(0)


def create_pci_list():
    pci_usb_list = list()
    try:
        lspci_out = Popen('lspci -Dvmm', shell=True, bufsize=64, stdin=PIPE, stdout=PIPE, close_fds=True).stdout.read().strip().decode('utf-8')
        pci_devices = lspci_out.split('%s%s' % (os.linesep, os.linesep))
        for pci_device in pci_devices:
            device_dict = dict()
            categories = pci_device.split(os.linesep)
            for category in categories:
                key, value = category.split('\t')
                device_dict[key[:-1]] = value.strip()
            if 'USB' not in device_dict['Class']:
                continue
            for root, dirs, files in os.walk('/sys/bus/pci/drivers/'):
                slot = device_dict['Slot']
                if slot in dirs:
                    device_dict['path'] = os.path.join(root, slot)
                    break
            pci_usb_list.append(device_dict)
    except Exception as ex:
        print('Failed to list pci devices! Error: %s' % ex)
        sys.exit(-1)
    return pci_usb_list


def create_usb_list():
    device_list = list()
    try:
        lsusb_out = Popen('lsusb -v', shell=True, bufsize=64, stdin=PIPE, stdout=PIPE, close_fds=True).stdout.read().strip().decode('utf-8')
        usb_devices = lsusb_out.split('%s%s' % (os.linesep, os.linesep))
        for device_categories in usb_devices:
            if not device_categories:
                continue
            categories = device_categories.split(os.linesep)
            device_stuff = categories[0].strip().split()
            bus = device_stuff[1]
            device = device_stuff[3][:-1]
            device_dict = {'bus': bus, 'device': device}
            device_info = ' '.join(device_stuff[6:])
            device_dict['description'] = device_info
            for category in categories:
                if not category:
                    continue
                categoryinfo = category.strip().split()
                if categoryinfo[0] == 'iManufacturer':
                    manufacturer_info = ' '.join(categoryinfo[2:])
                    device_dict['manufacturer'] = manufacturer_info
                if categoryinfo[0] == 'iProduct':
                    device_info = ' '.join(categoryinfo[2:])
                    device_dict['device'] = device_info
            path = '/dev/bus/usb/%s/%s' % (bus, device)
            device_dict['path'] = path

            device_list.append(device_dict)
    except Exception as ex:
        print('Failed to list usb devices! Error: %s' % ex)
        sys.exit(-1)
    return device_list


if 'listpci' in option:
    pci_usb_list = create_pci_list()
    for device in pci_usb_list:
        print('path=%s' % device['path'])
        print('    manufacturer=%s' % device['SVendor'])
        print('    device=%s' % device['SDevice'])
        print('    search string=%s %s' % (device['SVendor'], device['SDevice']))
    sys.exit(0)

if 'list' in option:
    usb_list = create_usb_list()
    for device in usb_list:
        print('path=%s' % device['path'])
        print('    description=%s' % device['description'])
        print('    manufacturer=%s' % device['manufacturer'])
        print('    device=%s' % device['device'])
        print('    search string=%s %s %s' % (device['description'], device['manufacturer'], device['device']))
    sys.exit(0)

if len(sys.argv) < 3:
    print(instructions)
    sys.exit(0)

option2 = sys.argv[2]

print('Resetting device: %s' % option2)


# echo -n "0000:39:00.0" | tee /sys/bus/pci/drivers/xhci_hcd/unbind;echo -n "0000:39:00.0" | tee /sys/bus/pci/drivers/xhci_hcd/bind
def reset_pci_usb_device(dev_path):
    folder, slot = os.path.split(dev_path)
    try:
        fp = open(os.path.join(folder, 'unbind'), 'wt')
        fp.write(slot)
        fp.close()
        fp = open(os.path.join(folder, 'bind'), 'wt')
        fp.write(slot)
        fp.close()
        print('Successfully reset %s' % dev_path)
        sys.exit(0)
    except Exception as ex:
        print('Failed to reset device! Error: %s' % ex)
        sys.exit(-1)


if 'pathpci' in option:
    reset_pci_usb_device(option2)


if 'searchpci' in option:
    pci_usb_list = create_pci_list()
    for device in pci_usb_list:
        text = '%s %s' % (device['SVendor'], device['SDevice'])
        if option2 in text:
            reset_pci_usb_device(device['path'])
    print('Failed to find device!')
    sys.exit(-1)


def reset_usb_device(dev_path):
    USBDEVFS_RESET = 21780
    try:
        f = open(dev_path, 'w', os.O_WRONLY)
        fcntl.ioctl(f, USBDEVFS_RESET, 0)
        print('Successfully reset %s' % dev_path)
        sys.exit(0)
    except Exception as ex:
        print('Failed to reset device! Error: %s' % ex)
        sys.exit(-1)


if 'path' in option:
    reset_usb_device(option2)


if 'search' in option:
    usb_list = create_usb_list()
    for device in usb_list:
        text = '%s %s %s' % (device['description'], device['manufacturer'], device['device'])
        if option2 in text:
            reset_usb_device(device['path'])
    print('Failed to find device!')
    sys.exit(-1)
mcarans
la source
c'est la meilleure réponse à cette question.
Kapad
4

Comme le cas particulier de la question est un problème de communication de gphoto2 avec un appareil photo USB, il existe 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.

Mviereck
la source
3

Le moyen le plus rapide de réinitialiser consiste à réinitialiser le contrôleur USB lui-même. Cela obligera udev à annuler l’enregistrement du périphérique lors de la déconnexion et l’enregistrement est de retour une fois que vous l’activez.

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. Toutefois, si vous utilisez du matériel personnalisé, vous pouvez simplement parcourir les noms de périphériques. Avec cette méthode, vous n'avez pas besoin de connaître le nom du périphérique à l'aide de lsusb. Vous pouvez également intégrer un script automatisé.

chandank
la source
1
Vous devez exécuter ces commandes en tant que root / sudo, et cela ne fonctionnera pas sur tous les systèmes (sur certains, vous devrez le remplacer ehci_hcdpar ehci-pci. Plus d'informations sur cette solution (peut-être d'où vient-elle?): Davidjb.com/blog / 2012/06 /…
Lambart
3

J'utilise une sorte de sledgehammer en rechargeant les modules. Voici mon script usb_reset.sh:

#!/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 de diplay:

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

[Service]
Type=oneshot
ExecStart=/path/to/usb_reset.sh
Ulrich-Lorenz Schlüter
la source
En utilisant l'option listpci de mon script ici: askubuntu.com/a/988297/558070 aidera à identifier le module USB à recharger (par exemple, xhci_pci, ehci_pci).
mcarans
2
Malheureusement sur mon système, ces modules de noyau ne sont pas séparés du noyau, donc cela ne fonctionnera pas:rmmod: ERROR: Module xhci_pci is builtin.
unfa
3

J'ai créé un script python qui réinitialisera un périphérique USB particulier en fonction du numéro de périphérique. Vous pouvez trouver le numéro de périphérique à l'aide 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 de périphérique

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()
Raghu
la source
J'aime cette solution! J'ai apporté quelques modifications au script selon mes goûts: gist.github.com/willstott101/7a455817ec6f4b8d89571ce72bdfd34a
Will S
2

Voici un script qui réinitialisera uniquement un ID de produit / fournisseur 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
cmcginty
la source
1
J'ai trouvé votre script utile. Mais que dois-je faire si le $DIRpériphérique disparaît et que le périphérique n'est pas visible?
Eugen Konkov
1

Est-ce que quelqu'un a commandé un sledgehammer? Ceci est reconstitué à partir de diverses autres réponses ici.

#!/bin/bash

# Root required
if (( UID )); then
        exec sudo "$0" "$@"
fi

cd /sys/bus/pci/drivers

function reinit {(
        local d="$1"
        test -e "$d" || return

        rmmod "$d"

        cd "$d"

        for i in $(ls | grep :); do
                echo "$i" > unbind
        done

        sleep 1

        for i in $(ls | grep :); do
                echo "$i" > bind
        done

        modprobe "$d"

)}

for d in ?hci_???; do
        echo " - $d"
        reinit "$d"
done
Mark K Cowan
la source
Mark, avez-vous trouvé que le déblocage est vraiment nécessaire ou est-ce ici simplement pour être sûr?
Ndemou
Ceci est un sledgehammer, il fait probablement beaucoup de choses inutiles
Mark K Cowan
@MarkKCowan, comment l'utilisez-vous? Quels sont les arguments de commande nécessaires / attendus?
not2qubit
1
@ not2qubit: aucun argument de ligne de commande requis. Le $@proxy dans le sudo est juste une force d'habbit, l'avoir empêchant les bugs si je décide plus tard d'ajouter des arguments (et d'oublier de mettre à jour le proxy sudo).
Mark K Cowan
1
@MarkKCowan Doh! Désolé mon ami! Oh oui de la malédiction! Je ne devrais pas faire de commentaires sur ce site pendant que je suis somnolent. Upvoted!
not2qubit
1

Parfois, je souhaite effectuer cette opération sur un périphérique particulier, identifié par VID (identifiant du fournisseur) et PID (identifiant du produit). C'est un script que j'ai trouvé utile à cette fin, qui utilise la bibliothèque nifty libusb.

Première exécution:

sudo apt-get install libusb-dev

Ensuite, resetDeviceConnection de ce fichier c ++ doit exécuter cette tâche, en réinitialisant une connexion de périphérique identifiée par vid et pid.

#include <libusb-1.0/libusb.h>

int resetDeviceConnection(UINT_16 vid, UINT_16 pid){
    /*Open libusb*/
    int resetStatus = 0;
    libusb_context * context;
    libusb_init(&context);

    libusb_device_handle * dev_handle = libusb_open_device_with_vid_pid(context,vid,pid);
    if (dev_handle == NULL){
      printf("usb resetting unsuccessful! No matching device found, or error encountered!\n");
      resetStatus = 1;
    }
    else{
      /*reset the device, if one was found*/
      resetStatus = libusb_reset_device(dev_handle);
    }
    /*exit libusb*/
    libusb_exit(context);
    return resetStatus;
}

(volé de mon catalogue TIL personnel: https://github.com/Marviel/TIL/blob/master/unix_tools/Reset_specific_USB_Device.md )

Marviel
la source
3
S'il vous plaît pouvez-vous montrer comment ce script est exécuté.
George Udosen
Bien sûr, laissez-moi mettre à jour.
Marviel
1
@Marviel, nous attendons toujours une mise à jour ...
not2qubit
il faut des votes inutiles
Eugen Konkov
1

J'ai fait un script bash simple pour réinitialiser un périphérique USB particulier.

#!/bin/bash
#type lsusb to find "vendor" and "product" ID in terminal
set -euo pipefail
IFS=$'\n\t'

#edit the below two lines of vendor and product values using lsusb result
dev=$(lsusb -t | grep usbdevicename | grep 'If 1' | cut -d' ' -f13|cut -d"," -f1)
#VENDOR=05a3
#PRODUCT=9230
VENDOR=$(lsusb -s $dev | cut -d' ' -f6 | cut -d: -f1)
PRODUCT=$(lsusb -s $dev | cut -d' ' -f6 | cut -d: -f2)

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
Bien
la source
0

Peut-être que cela fonctionne aussi pour une caméra:

Après avoir relancé un USB 3.0disque dur affamé sur un 3.4.42Linux (kernel.org) de mon côté. dmesgOn a dit que les commandes expiraient après 360 secondes (désolé, je ne peux pas copier le journal système ici, pas de réseaux connectés) et que le lecteur a été suspendu complètement. Les processus accédant à l'appareil ont été bloqués dans le noyau, impossible à tuer. NFSaccroché, ZFSaccroché, ddaccroché.

Après cela, tout a encore fonctionné. dmesgdit juste une seule ligne sur le USBpériphérique trouvé.

Je n'ai vraiment aucune idée de ce qui suit fait en détail. Mais cela a fonctionné.

L'exemple de sortie suivant provient de Debian Squeeze avec le 2.6.32-5-686noyau, je pense donc que cela fonctionne pour les versions 2.6 et supérieures:

$ ls -al /dev/sdb
brw-rw---T 1 root floppy 8, 16 Jun  3 20:24 /dev/sdb

$ ls -al /sys/dev/block/8:16/device/rescan
--w------- 1 root root 4096 Jun  6 01:46 /sys/dev/block/8:16/device/rescan

$ echo 1 > /sys/dev/block/8:16/device/rescan

Si cela ne fonctionne pas, quelqu'un d'autre peut peut-être comprendre comment envoyer une réinitialisation réelle à un périphérique.

Tino
la source
0

Essayez ceci, il s’agit d’un débranchement de logiciel (Eject).

Parfois, cela ne fonctionne pas simplement en déconnectant un périphérique pour certains périphériques.

Exemple:

Je souhaite retirer ou éjecter mon "Genius NetScroll 120".

Ensuite, je vérifie d'abord mon périphérique USB connecté

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 03f0:231d Hewlett-Packard 
Bus 001 Device 004: ID 138a:0007 Validity Sensors, Inc. VFS451 Fingerprint Reader
Bus 001 Device 005: ID 04f2:b163 Chicony Electronics Co., Ltd 
Bus 002 Device 009: ID 0458:003a KYE Systems Corp. (Mouse Systems) NetScroll+ Mini Traveler / Genius NetScroll 120  **<----This my Mouse! XDDD**

Ok, j'ai trouvé ma souris, elle a un bus 002, un périphérique 009, idVendor 0458 et idProduct 003a, il s'agit donc d'une information de référence sur la souris.

Ceci est important, le numéro de bus est le chemin du nom de début du périphérique et je vérifierai l'ID du produit et le fournisseur pour s'assurer que le périphérique correct à supprimer.

$ ls /sys/bus/usb/drivers/usb/
1-1/    1-1.1/  1-1.3/  1-1.5/  2-1/    2-1.3/  bind    uevent  unbind  usb1/   usb2/

Faites attention aux dossiers, vérifiez le début avec le dossier numéro 2, je vais vérifier celui-ci car mon bus est 002, et un par un, j'ai vérifié chaque dossier contenant le bon idVendor et idProduct à propos de mes informations de souris.

Dans ce cas, je vais récupérer les informations avec cette commande:

cat /sys/bus/usb/drivers/usb/2-1.3/idVendor
0458
cat /sys/bus/usb/drivers/usb/2-1.3/idProduct
003a

Ok, le chemin /sys/bus/usb/drivers/usb/2-1.3/ correspond à ma souris d’information! XDDD.

Il est temps de retirer l'appareil!

su -c "echo 1 > /sys/bus/usb/drivers/usb/2-1.3/remove"

Rebranchez le périphérique USB et ça marche encore!

utilisateur242078
la source
10
Et si vous ne pouvez pas le brancher à nouveau? (par exemple, c'est un lecteur de carte SD interne)
aleb
0

Si vous connaissez le nom de votre appareil, ce script python fonctionnera:

#!/usr/bin/python
"""
USB Reset

Call as "usbreset.py <device_file_path>"

With device_file_path like "/dev/bus/usb/bus_number/device_number"
"""
import fcntl, sys, os

USBDEVFS_RESET = ord('U') << (4*2) | 20

def main():
    fd = os.open(sys.argv[1], os.O_WRONLY)
    if fd < 0: sys.exit(1)
    fcntl.ioctl(fd, USBDEVFS_RESET, 0)
    os.close(fd)
    sys.exit(0)
# end main

if __name__ == '__main__':
    main()
Argile
la source