Come si ripristina un dispositivo USB dalla riga di comando?

143

È possibile ripristinare la connessione di un dispositivo USB, senza disconnettersi / connettersi fisicamente dal PC?

In particolare, il mio dispositivo è una fotocamera digitale. Sto utilizzando gphoto2 , ma ultimamente ricevo "errori di lettura del dispositivo", quindi mi piacerebbe provare a eseguire un ripristino software della connessione.

Da quello che posso dire, non ci sono moduli del kernel caricati per la fotocamera. L'unico che sembra correlato è usbhid .

    
posta cmcginty 01.08.2010 - 21:46

16 risposte

107

Salva quanto segue come 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;
}

Esegui i seguenti comandi nel terminale:

  1. Compila il programma:

    $ cc usbreset.c -o usbreset
    
  2. Ottieni l'ID bus e dispositivo del dispositivo USB che desideri ripristinare:

    $ lsusb  
    Bus 002 Device 003: ID 0fe9:9010 DVICO  
    
  3. Rendi eseguibile il nostro programma compilato:

    $ chmod +x usbreset
    
  4. Esegui il programma con privilegio sudo; rendere necessaria la sostituzione per <Bus> e <Device> id come trovato eseguendo il comando lsusb :

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

Fonte del programma di cui sopra: link

    
risposta data Li Lo 02.08.2010 - 04:27
49

Non mi sono mai trovato nelle tue circostanze specifiche prima, quindi non sono sicuro che farà abbastanza, ma il modo più semplice che ho trovato per resettare un dispositivo USB è questo comando: (Non sono necessarie app esterne )

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"

Questo è quello che uso per ripristinare il mio Kinect poiché libfreenect sembra non avere API per rimetterlo in stato di stop. È nella mia scatola di Gentoo, ma il kernel dovrebbe essere abbastanza nuovo da usare la stessa struttura di percorso per sysfs.

Il tuo ovviamente non sarebbe 1-4.6 ma puoi estrarre il percorso del dispositivo dal log del tuo kernel ( dmesg ) oppure puoi usare qualcosa come lsusb per ottenere il fornitore e gli ID prodotto e quindi usare un veloce comando come questo per elencare in che modo i percorsi si riferiscono a coppie di produttori / ID di prodotto diversi:

for X in /sys/bus/usb/devices/*; do 
    echo "$X"
    cat "$X/idVendor" 2>/dev/null 
    cat "$X/idProduct" 2>/dev/null
    echo
done
    
risposta data ssokolow 13.09.2011 - 08:56
40

Questo ripristinerà tutte le porte USB1 / 2/3 collegate [1]:

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

Credo che questo risolva il tuo problema. Se non si desidera ripristinare tutti gli endpoint USB, è possibile utilizzare l'ID dispositivo appropriato da /sys/bus/pci/drivers/ehci_hcd

Note: [1]: i driver del kernel *hci_hcd in genere controllano le porte USB. ohci_hcd e uhci_hcd sono per porte USB1.1, ehci_hcd per porte USB2 e xhci_hcd per porte USB3. (vedi link )

    
risposta data Tamás Tapsonyi 04.05.2013 - 13:02
9

Avevo bisogno di automatizzarlo in uno script python, quindi ho adattato la risposta estremamente utile di LiLo a quanto segue:

#!/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

Nel mio caso era il driver cp210x (che potrei dire da lsmod | grep usbserial ), quindi puoi salvare lo snippet sopra riportato come reset_usb.py e poi fare questo:

sudo python reset_usb.py cp210x

Questo potrebbe anche essere utile se non hai già una configurazione del compilatore c sul tuo sistema, ma hai python.

    
risposta data Peter 02.03.2015 - 21:38
4

Sto usando un po 'di mazza ricaricando i moduli. Questo è il mio 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

E questo è il mio file di servizio systemd /usr/lib/systemd/system/usbreset.service che esegue usb_reset.sh dopo che il gestore di diplay è stato avviato:

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

[Service]
Type=oneshot
ExecStart=/path/to/usb_reset.sh
    
risposta data Ulrich-Lorenz Schlüter 09.01.2016 - 11:18
4

Poiché il caso speciale della domanda è un problema di comunicazione di gphoto2 con una fotocamera su USB, c'è un'opzione in gphoto2 per reimpostare la sua connessione USB:

gphoto2 --reset

Forse questa opzione non esisteva nel 2010 quando la domanda è stata posta.

    
risposta data mviereck 31.08.2016 - 15:19
3

Il modo più rapido per reimpostare sarà ripristinare il controller USB stesso. Così facendo imporrà a udev di annullare la registrazione del dispositivo in caso di disconnessione, e la registrazione tornerà dopo averla abilitata.

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

Questo dovrebbe funzionare per la maggior parte dell'ambiente PC. Tuttavia, se si utilizza un hardware personalizzato, è possibile semplicemente scorrere i nomi dei dispositivi. Con questo metodo non è necessario trovare il nome del dispositivo da lsusb. Puoi incorporare anche in uno script automatico.

    
risposta data chandank 24.11.2014 - 20:34
2

Ho creato uno script python che resetterà un particolare dispositivo USB in base al numero del dispositivo. È possibile trovare il numero del dispositivo dal comando lsusb.

ad esempio:

$ lsusb

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

In questa stringa 004 è il numero del dispositivo

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()
    
risposta data Raghu 07.09.2016 - 13:42
2

Ecco uno script che reimposterà solo un ID prodotto / fornitore corrispondente.

#!/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
    
risposta data cmcginty 30.04.2017 - 05:50
2

Ho creato uno script Python che semplifica l'intero processo in base alle risposte qui.

Salva lo script di seguito come reset_usb.py o clona questo repository: link .

Uso:

python reset_usb.py help: mostra questo aiuto

sudo python elenco reset_usb.py: elenca tutti i dispositivi USB

sudo python reset_usb.py percorso / dev / bus / usb / XXX / YYY: resetta il dispositivo USB usando il percorso / dev / bus / usb / XXX / YYY

sudo python reset_usb.py cerca "termini di ricerca": cerca il dispositivo USB utilizzando i termini di ricerca all'interno della stringa di ricerca restituita dall'elenco e ripristina il dispositivo corrispondente

sudo python reset_usb.py listpci: elenca tutti i dispositivi USB PCI

sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X: Ripristina dispositivo USB PCI usando il percorso /sys/bus/pci/drivers/.../XXXX : XX: XX, X

sudo python reset_usb.py searchpci "termini di ricerca": cerca il dispositivo PCI USB utilizzando i termini di ricerca all'interno della stringa di ricerca restituita da listpci e ripristina il dispositivo corrispondente

#!/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)
    
risposta data mcarans 21.12.2017 - 11:15
1

Qualcuno ha ordinato un martello? Questo è messo insieme da varie altre risposte qui.

#!/bin/bash

# Root required
if (( UID )); then
        exec sudo "$0" "[email protected]"
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
    
risposta data Mark K Cowan 28.06.2016 - 16:08
1

A volte voglio eseguire questa operazione su un particolare dispositivo, come identificato da VID (ID venditore) e PID (id prodotto). Questo è uno script che ho trovato utile per questo scopo, che utilizza la libreria nifty libusb.

Prima esecuzione:

sudo apt-get install libusb-dev

Quindi, questo resetDeviceConnection del file c ++ dovrebbe eseguire questa operazione, di reimpostare una connessione di dispositivo come identificata da vid e 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;
}

(rubato dal mio catalogo TIL personale: link )

    
risposta data Marviel 29.12.2016 - 14:53
0

Forse funziona anche per una fotocamera:

In seguito ha rianimato un HDD con% co_de affamato su un USB 3.0 (kernel.org) Linux dalla mia parte. 3.4.42 detto, che stava scadendo i comandi dopo 360s (mi dispiace, non posso copiare il syslog qui, non le reti connesse) e l'unità si è bloccata completamente. I processi che accedono al dispositivo sono stati bloccati nel kernel, non eseguibili. dmesg sospeso, NFS sospeso, ZFS bloccato.

Dopo aver fatto ciò, tutto ha funzionato di nuovo. dd ha detto solo una riga relativa al dispositivo dmesg trovato.

Non ho davvero idea di cosa segua nei dettagli. Ma ha funzionato.

Il seguente esempio di output proviene da Debian Squeeze con USB kernel, quindi penso che funzioni per 2.6 e sopra:

$ 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

Se questo non funziona, forse qualcun altro può capire come inviare un vero reset a un dispositivo.

    
risposta data Tino 06.06.2013 - 02:08
0

Prova questo, è un software scollegato (Espelli).

A volte non funziona semplicemente disconnettendo il dispositivo per alcuni dispositivi.

Esempio:

Voglio rimuovere o espellere il mio "Genius NetScroll 120".

Quindi prima controlla il dispositivo USB collegato

$ 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, ho trovato il mio mouse, ha un Bus 002, Dispositivo 009, idVendor 0458 e idProduct 003a, quindi questa è un'informazione del dispositivo di riferimento sul mouse.

Questo è importante, il numero di bus è il percorso iniziale del nome del dispositivo e controllerò l'ID del prodotto e il fornitore per garantire il dispositivo corretto da rimuovere.

$ 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/

Prestare attenzione alle cartelle, controllare l'inizio con il numero di cartella 2, lo controllerò perché il mio Bus è 002, e uno per uno ho controllato ogni cartella contenente l'idVendor e idProduct corretti sulle informazioni del mio mouse.

In questo caso, recupererò le informazioni con questo comando:

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

Ok, il percorso /sys/bus/usb/drivers/usb/2-1.3/ corrisponde al mio mouse di informazioni! XDDD.

È ora di rimuovere il dispositivo!

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

Ricollega il dispositivo USB e funziona di nuovo!

    
risposta data user242078 31.01.2014 - 12:15
0

Se conosci il nome del tuo dispositivo, questo script python funzionerà:

#!/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()
    
risposta data Clay 04.08.2017 - 16:35
-3

Forse questa guida ti può aiutare:

Se sei infastidito dal bug che non ti permette di montare dispositivi USB su Ubuntu Lucid Lynx, il problema è causato dal modulo floppy. Disabilita con:

sudo modprobe -r floppy

Dopo un riavvio, il modulo verrà ricaricato.

    
risposta data User 01.08.2010 - 22:16

Leggi altre domande sui tag