Putuskan dan sambungkan kembali port USB melalui cli

17

Saya punya mouse yang akan berhenti bekerja secara acak. Solusinya mudah, cabut dan pasang kembali. Apakah ada cara saya bisa melakukan ini melalui baris perintah? Melakukan melalui baris perintah memiliki beberapa keuntungan.

  1. Tidak merusak konektor.
  2. Lebih cepat.
  3. Menghemat kesulitan merangkak di bawah meja saya.
  4. Paling penting: mencegah saya untuk tidak sengaja mencabut sesuatu yang lain.

Ditambah lagi, saya ingin tahu bagaimana melakukan ini.

OS adalah Debian 8.

Terima kasih!

celana kucing
sumber
1
Bukan pertanyaan yang persis sama, tetapi jawabannya harus berlaku: Bagaimana cara menghubungkan kembali perangkat USB yang terputus secara logis?
Gilles 'SANGAT berhenti menjadi jahat'
Mungkin unix.stackexchange.com/a/166601/117599 adalah apa yang Anda cari.
phk

Jawaban:

13

Simpan yang berikut ke 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;
}

Jalankan perintah berikut di terminal:

  1. Kompilasi program:

    cc usbreset.c -o usbreset
    
  2. Dapatkan ID Bus dan Perangkat dari perangkat USB yang ingin Anda atur ulang:

    lsusb -t 
    
    Bus#  4  
    -Dev#   1 Vendor 0x1d6b Product 0x0001    
    -Dev#   3 Vendor 0x046b Product 0xff10
    
  3. Jadikan program terkompilasi kami dapat dijalankan:

    chmod +x usbreset
    
  4. Jalankan program dengan sudohak istimewa; buat penggantian <Bus>dan <Device>id yang diperlukan seperti yang ditemukan dengan menjalankan lsusbperintah:

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

Sumber program di atas: http://marc.info/?l=linux-usb&m=121459435621262&w=2

Paul
sumber
1
Apakah ini secara efektif mengatur ulang daya pada perangkat dan karenanya akan menyetel ulang sepenuhnya tanpa harus mencabut dan memasangnya kembali?
Jarryd
Ini bekerja seperti pesona.
Wedge Martin
Jika suatu program telah membuka perangkat USB serial (misalnya, / dev / ttyUSB0 disambungkan dari / dev / myserialdevice seperti yang ditentukan dalam /etc/udev/rules.d/mystuff.rules), dan perangkat digantung karena suatu alasan, apakah itu maka perlu untuk meresetnya dengan ioctl () seperti di atas, atau apakah cukup dengan cukup menutup () dan membuka () lagi?
Per Lindberg
1
@Jarryd lihat penjelasan Alan di tautan di atas :Note however, that reset followed by re-enumeration is _not_ the same thing as power-cycle followed by reconnect and re-enumeration.
ckujau
2

Saya telah membuat skrip Python yang menyederhanakan seluruh proses berdasarkan jawaban di sini: /ubuntu/645/how-do-you-reset-a-usb-device-from-the-command-line .

Simpan skrip di bawah ini sebagai reset_usb.py atau tiruan repo ini: https://github.com/mcarans/resetusb/ .

Pemakaian:

python reset_usb.py help: Tunjukkan bantuan ini

sudo python daftar reset_usb.py: Daftar semua perangkat USB

sudo python jalur reset_usb.py / dev / bus / usb / XXX / YYY: Setel ulang perangkat USB menggunakan jalur / dev / bus / usb / XXX / YYY

sudo python reset_usb.py pencarian "istilah pencarian": Cari perangkat USB menggunakan istilah pencarian dalam string pencarian yang dikembalikan oleh daftar dan reset perangkat yang cocok

sudo python reset_usb.py listpci: Daftar semua perangkat PCI USB

sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X: Reset perangkat PCI USB menggunakan path /sys/bus/pci/drivers/.../XXXX:XX: XX.X

sudo python reset_usb.py searchpci "istilah pencarian": Cari perangkat PCI USB menggunakan istilah pencarian dalam string pencarian yang dikembalikan oleh listpci dan reset perangkat yang cocok

#!/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)
mcaran
sumber
0

Anda selalu dapat mengatur ulang tumpukan USB melalui perangkat lunak, dan juga menempatkan perangkat USB ke mode sleep ( hemat daya ), tetapi ini tidak mempengaruhi daya port + 5V, yang selalu menyala.

Tergantung pada hub USB Anda, Anda mungkin atau mungkin tidak dapat benar-benar mematikan (siklus) daya ke port USB fisik.

Hanya hub USB "pintar" yang memungkinkan per-port power cycle. Ini adalah proyek kecil yang memungkinkan Anda mengontrolnya.

Birkensocks
sumber