Desconecte y vuelva a conectar el puerto USB a través de cli

17

Tengo un mouse que dejará de funcionar al azar. La solución es fácil, desenchufa y vuelve a enchufar. ¿Hay alguna forma de que pueda hacer esto a través de la línea de comando? Hacerlo a través de la línea de comando tiene algunas ventajas.

  1. No desgasta el conector.
  2. Más rápido.
  3. Me ahorra la molestia de gatear debajo de mi escritorio.
  4. Lo más importante: me impide desconectar accidentalmente otra cosa.

Además, tengo curiosidad por saber cómo hacer esto.

El sistema operativo es Debian 8.

¡Gracias!

pantalones de gato
fuente
1
No es exactamente la misma pregunta, pero las respuestas deberían ser aplicables: ¿Cómo volver a conectar un dispositivo USB desconectado lógicamente?
Gilles 'SO- deja de ser malvado'
Quizás unix.stackexchange.com/a/166601/117599 es lo que estás buscando.
phk

Respuestas:

13

Guarde lo siguiente en 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;
}

El ejecutar los siguientes comandos en la terminal:

  1. Compila el programa:

    cc usbreset.c -o usbreset
    
  2. Obtenga la identificación de bus y dispositivo del dispositivo USB que desea restablecer:

    lsusb -t 
    
    Bus#  4  
    -Dev#   1 Vendor 0x1d6b Product 0x0001    
    -Dev#   3 Vendor 0x046b Product 0xff10
    
  3. Haga que nuestro programa compilado sea ejecutable:

    chmod +x usbreset
    
  4. Ejecute el programa con sudoprivilegio; realice la sustitución necesaria para <Bus>y los <Device>identificadores que se encuentran ejecutando el lsusbcomando:

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

Fuente del programa anterior: http://marc.info/?l=linux-usb&m=121459435621262&w=2

Pablo
fuente
1
¿Esto restablece efectivamente la alimentación del dispositivo y, por lo tanto, lo restablecería por completo sin tener que desenchufarlo y volver a enchufarlo?
Jarryd
Esto funcionó a las mil maravillas.
Wedge Martin el
Si un programa ha abierto un dispositivo USB en serie (por ejemplo, / dev / ttyUSB0 enlazado desde / dev / myserialdevice como se especifica en /etc/udev/rules.d/mystuff.rules), y el dispositivo se cuelga por alguna razón, ¿es así? entonces es necesario restablecerlo con un ioctl () como se indicó anteriormente, o ¿es suficiente simplemente cerrarlo () y abrirlo () nuevamente?
Según Lindberg el
1
@Jarryd ve la explicación de Alan en el enlace de arriba :Note however, that reset followed by re-enumeration is _not_ the same thing as power-cycle followed by reconnect and re-enumeration.
ckujau
2

Creé un script de Python que simplifica todo el proceso basado en las respuestas aquí: /ubuntu/645/how-do-you-reset-a-usb-device-from-the-command-line .

Guarde el script a continuación como reset_usb.py o clone este repositorio: https://github.com/mcarans/resetusb/ .

Uso:

python reset_usb.py help: muestra esta ayuda

sudo python reset_usb.py list: Lista todos los dispositivos USB

sudo python reset_usb.py ruta / dev / bus / usb / XXX / YYY: Restablece el dispositivo USB usando la ruta / dev / bus / usb / XXX / YYY

sudo python reset_usb.py buscar "términos de búsqueda": busque un dispositivo USB utilizando los términos de búsqueda dentro de la cadena de búsqueda devuelta por la lista y restablezca el dispositivo coincidente

sudo python reset_usb.py listpci: Lista todos los dispositivos USB PCI

sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X: restablezca el dispositivo USB PCI utilizando la ruta /sys/bus/pci/drivers/.../XXXX:XX: XX.X

sudo python reset_usb.py searchpci "términos de búsqueda": busque un dispositivo USB PCI utilizando los términos de búsqueda dentro de la cadena de búsqueda devuelta por listpci y restablezca el dispositivo coincidente

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

Siempre puede restablecer la pila USB a través del software y también poner los dispositivos USB en modo de suspensión ( ahorro de energía ), pero esto no afecta la alimentación del puerto + 5V, que siempre está encendida.

Dependiendo de su concentrador USB, es posible que pueda o no apagar o apagar la alimentación de un puerto USB físico.

Solo los concentradores USB "inteligentes" permiten el ciclo de alimentación por puerto. Aquí hay un pequeño proyecto que le permite controlarlos.

Birkensocks
fuente