Scollegare e ricollegare la porta USB tramite cli


17

Ho un mouse che smetterà di funzionare in modo casuale. La soluzione è semplice, scollegare e ricollegare. C'è un modo in cui posso farlo tramite la riga di comando? Fare tramite riga di comando ha alcuni vantaggi.

  1. Non consuma il connettore.
  2. Più veloce.
  3. Mi salva il problema di strisciare sotto la mia scrivania.
  4. Più importante: mi impedisce di scollegare accidentalmente qualcos'altro.

Inoltre sono curioso di sapere come farlo.

Il sistema operativo è Debian 8.

Grazie!


1
Non esattamente la stessa domanda, ma le risposte dovrebbero essere applicabili: come riconnettere un dispositivo USB logicamente disconnesso?
Gilles 'SO- smetti di essere malvagio'

Forse unix.stackexchange.com/a/166601/117599 è quello che stai cercando.
phk,

Risposte:


13

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

Eseguono 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 -t 
    
    Bus#  4  
    -Dev#   1 Vendor 0x1d6b Product 0x0001    
    -Dev#   3 Vendor 0x046b Product 0xff10
    
  3. Rendi eseguibile il nostro programma compilato:

    chmod +x usbreset
    
  4. Eseguire il programma con sudoprivilegio; effettuare la sostituzione necessaria per <Bus>e <Device>id come trovato eseguendo il lsusbcomando:

    sudo ./usbreset /dev/bus/usb/004/003
    
    Resetting USB device /dev/bus/usb/004/003
    
    Reset successful
    

Fonte del programma precedente: http://marc.info/?l=linux-usb&m=121459435621262&w=2


1
Questo ripristina efficacemente l'alimentazione del dispositivo e quindi ripristinerebbe completamente senza dover scollegare e ricollegare?
Jarryd,

Questo ha funzionato come un fascino.
Wedge Martin,

Se un programma ha aperto un dispositivo USB seriale (diciamo, / dev / ttyUSB0 collegato simbolicamente da / dev / myserialdevice come specificato in /etc/udev/rules.d/mystuff.rules) e il dispositivo si blocca per qualche motivo, vero? quindi è necessario ripristinarlo con un ioctl () come sopra, o è sufficiente semplicemente chiuderlo () e aprirlo () di nuovo?
Per Lindberg,

1
@Jarryd vedi la spiegazione di Alan nel link sopra :Note however, that reset followed by re-enumeration is _not_ the same thing as power-cycle followed by reconnect and re-enumeration.
ckujau,

2

Ho creato uno script Python che semplifica l'intero processo in base alle risposte qui: /ubuntu/645/how-do-you-reset-a-usb-device-from-the-command-line .

Salvare lo script qui sotto come reset_usb.py o clonare questo repository: https://github.com/mcarans/resetusb/ .

Uso:

python reset_usb.py aiuto: mostra questo aiuto

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

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

sudo python reset_usb.py cerca "termini di ricerca": cerca un dispositivo USB usando 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 il dispositivo PCI USB utilizzando path /sys/bus/pci/drivers/.../XXXX:XX: XX.X

sudo python reset_usb.py searchpci "termini di ricerca": cerca un dispositivo PCI USB usando i termini di ricerca all'interno della stringa di ricerca restituita da listpci e reimposta 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)

0

Puoi sempre ripristinare lo stack USB tramite software e anche mettere i dispositivi USB in modalità di sospensione ( risparmio energetico ), ma ciò non influisce sull'alimentazione della porta + 5V, che è sempre attiva.

A seconda dell'hub USB, è possibile o meno essere in grado di spegnere (spegnere) l'alimentazione a una porta USB fisica.

Solo gli hub USB "intelligenti" consentono il ciclo di alimentazione per porta. Ecco un piccolo progetto che ti consente di controllarli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.