คุณจะรีเซ็ตอุปกรณ์ USB จากบรรทัดคำสั่งได้อย่างไร


164

เป็นไปได้ไหมที่จะรีเซ็ตการเชื่อมต่อของอุปกรณ์ USB โดยไม่ต้องทำการยกเลิกการเชื่อมต่อ / เชื่อมต่อทางกายภาพจาก PC?

โดยเฉพาะอุปกรณ์ของฉันเป็นกล้องดิจิตอล ฉันใช้gphoto2แต่เมื่อเร็ว ๆ นี้ฉันได้รับ "ข้อผิดพลาดในการอ่านอุปกรณ์" ดังนั้นฉันจึงต้องการลองทำการรีเซ็ตซอฟต์แวร์ของการเชื่อมต่อ

จากสิ่งที่ฉันสามารถบอกได้ไม่มีโมดูลเคอร์เนลที่ถูกโหลดสำหรับกล้อง usbhidเพียงคนเดียวที่มีลักษณะที่เกี่ยวข้อง


คุณใช้ Ubuntu รุ่นไหน
ผู้ใช้

ฉันพยายามแก้ปัญหาทั้งสองโดย Li Lo และ ssokolow ทั้งหมดที่ฉันได้รับคือการอนุญาตปฏิเสธ, nomatter ถ้าฉันใช้รหัส usbreset หรือบรรทัดคำสั่ง "echo 0> ... " ฉันใช้ sudo, อุปกรณ์ usb ของฉันเป็นเจ้าของโดย root แต่ฉัน สามารถใช้งานได้โดยไม่มีสิทธิ์ผู้ดูแลระบบ (กล้อง .. )

1
หากคุณได้รับข้อผิดพลาดการอ่านคุณอาจมีข้อมูลเสียหาย หากกล้องของคุณใช้การ์ดหน่วยความจำภายนอก (เช่น MicroSD) คุณอาจต้องเชื่อมต่อกับคอมพิวเตอร์และเรียกใช้ fsck
TSJNachos117

คำตอบ:


118

บันทึกต่อไปนี้เป็น 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;
}

รันคำสั่งต่อไปนี้ในเทอร์มินัล:

  1. รวบรวมโปรแกรม:

    $ cc usbreset.c -o usbreset
    
  2. รับ Bus และ ID อุปกรณ์ของอุปกรณ์ USB ที่คุณต้องการรีเซ็ต:

    $ lsusb  
    Bus 002 Device 003: ID 0fe9:9010 DVICO  
    
  3. ทำให้โปรแกรมที่คอมไพล์ของเราสามารถทำงานได้:

    $ chmod +x usbreset
    
  4. ดำเนินการโปรแกรมด้วยสิทธิ์ sudo; ทำการทดแทนที่จำเป็นสำหรับ<Bus>และ<Device>รหัสที่พบโดยการเรียกใช้lsusbคำสั่ง:

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

แหล่งที่มาของโปรแกรมข้างต้น: http://marc.info/?l=linux-usb&m=121459435621262&w=2


3
ใช้งานได้กับ Ubuntu 13.10 ID อุปกรณ์อาจแตกต่างกัน ที่จะได้รับมันสำหรับเมาส์ฉันได้ห่อโค้ดข้างต้นในคำสั่งเชลล์ไม่กี่คำสั่งecho $(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
ดูเหมือนว่าไดรฟ์ภายนอกของฉันจะตรวจไม่พบ (ฉันต้องเชื่อมต่อสายเคเบิล USB อีกครั้งอย่างหนัก); มันเป็น usb2.0 ที่เชื่อมต่อกับพอร์ตพีซีเดสก์ทอป usb3.0; เมื่อฉันเรียกใช้usbreset /dev/bus/usb/011/001นั่นเป็นหนึ่งใน 2 usb 3.0 root hubs at lsusbมันมีข้อผิดพลาด: "Error in ioctl: เป็นไดเร็กตอรี่", ideia ใด ๆ ? ฉันลองทั้งฮับ usb 3.0
Aquarius Power

1
หากใครที่อ่านข้อความนี้มี (usb) เมาส์ค้างหลังจากเข้าสู่ระบบบน Ubuntu 16.04 (ด้วย dmesg ที่เต็มไปด้วย "input irq status -75"), ฉันสามารถยืนยันได้ว่านี่เป็นทางออกเดียวที่เหมาะกับฉัน ขอบคุณ
Agustin Baez

1
@ Aquarius ฉันยังได้รับข้อผิดพลาดเดียวกัน "Error in ioctl: Is a directory" แก้ไขหรือไม่
ransh

1
ดูคำตอบของฉันที่นี่askubuntu.com/a/988297/558070ที่ใช้วิธีการรีเซ็ตแบบเดียวกันกับคำตอบนี้ แต่ยังอนุญาตให้แสดงรายการและค้นหาอุปกรณ์ได้ง่ายขึ้น
mcarans

58

ฉันไม่ได้พบตัวเองในสถานการณ์ที่เฉพาะเจาะจงของคุณมาก่อนดังนั้นฉันไม่แน่ใจว่ามันจะเพียงพอหรือไม่ แต่วิธีที่ง่ายที่สุดที่ฉันพบในการรีเซ็ตอุปกรณ์ USB คือคำสั่งนี้: (ไม่จำเป็นต้องใช้แอพภายนอก)

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"

นั่นคืออันที่จริงที่ฉันใช้เพื่อรีเซ็ต Kinect ของฉันเนื่องจาก libfreenect ดูเหมือนว่าจะไม่มี API สำหรับทำให้มันกลับสู่โหมดสลีป มันอยู่ในกล่อง Gentoo ของฉัน แต่เคอร์เนลควรใหม่พอที่จะใช้โครงสร้างพา ธ เดียวกันสำหรับ sysfs

เห็นได้ชัดว่าไม่ใช่ของ1-4.6คุณ แต่คุณสามารถดึงพา ธ อุปกรณ์นั้นจากเคอร์เนลบันทึกของคุณ ( dmesg) หรือคุณสามารถใช้บางสิ่งบางอย่างเช่นlsusbเพื่อรับผู้ขายและรหัสผลิตภัณฑ์จากนั้นใช้คำสั่งด่วนเช่นนี้เพื่อแสดงเส้นทางที่สัมพันธ์กับผู้ขายรายอื่น / คู่รหัสผลิตภัณฑ์:

for X in /sys/bus/usb/devices/*; do 
    echo "$X"
    cat "$X/idVendor" 2>/dev/null 
    cat "$X/idProduct" 2>/dev/null
    echo
done

sh: 1: ไม่สามารถสร้าง /sys/bus/usb/devices/1-3.1:1.0/authorized: Directory nonexistent
Nicolas Marchildon

ดูเหมือนว่าพวกเขาได้เปลี่ยนเค้าโครงของระบบไฟล์ usbfs ฉันจะลองคิดดูว่าวิธีการทำสิ่งใหม่ ๆ บน Ubuntu คืออะไรเมื่อฉันไม่ง่วง
ssokolow

9
ขอบคุณที่ใช้งานได้ดี! บางทีคุณควรพูดถึงเพื่อดำเนินการecho 1 > /sys/bus/usb/devices/whatever/authorizedภายในสคริปต์เพื่อเปิดใช้งานอุปกรณ์ทันทีที่ถูกปิดใช้งาน ฉันไม่ได้ทั้งบนแป้นพิมพ์เมาส์และ USB ของฉันและฉันจบลงด้วยระบบหูหนวกสมบูรณ์ :)
Avio

1
มันแปลกมากหากตั้งค่าเป็น 1 โดยอัตโนมัติเมื่อตั้งค่าเป็น 0 จะเป็นการบอกระบบว่าคุณไม่ต้องการให้อุปกรณ์นั้น "อนุญาต" และไม่สามารถเข้าถึงได้
Tim Tisdall

2
หมายเหตุสำหรับผู้ที่พยายามเปลี่ยนไปใช้| sudo tee ...วิธีการ/sysเขียนที่มีสิทธิพิเศษ: นั่นจะไม่ดีถ้าคุณยังไม่มีแคชข้อมูลประจำตัว sudo sudo sh -c "..."ทำงานตามที่คาดไว้เมื่อ sudo ต้องการให้ใส่รหัสผ่าน
ssokolow

51

นี่จะเป็นการรีเซ็ตพอร์ต USB1 / 2/3 ที่ต่อทั้งหมด [1]:

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

ฉันเชื่อว่านี่จะช่วยแก้ปัญหาของคุณได้ หากคุณไม่ต้องการรีเซ็ตจุดปลาย USB ทั้งหมดคุณสามารถใช้ ID อุปกรณ์ที่เหมาะสมได้/sys/bus/pci/drivers/ehci_hcd


หมายเหตุ: [1]: *hci_hcdโดยทั่วไปเคอร์เนลไดรเวอร์จะควบคุมพอร์ต USB ohci_hcdและuhci_hcdสำหรับพอร์ต USB1.1 สำหรับพอร์ตehci_hcdUSB2 และxhci_hcdสำหรับพอร์ต USB3 (ดูhttps://en.wikipedia.org/wiki/Host_controller_interface_(USB,_Firewire) )


คุณเชื่อว่าอาจใช้การปลุกที่จัดเก็บข้อมูล usb ได้หรือไม่
กุมภ์กำลัง

2
แม้ว่าฉันจะได้รับข้อความต่อไปนี้: ls: cannot access /sys/bus/pci/drivers/ehci_hcd/: No such file or directoryสิ่งนี้สามารถแก้ไขปัญหาได้ แต่เมาส์ก็เริ่มทำงานได้ทันที +1
Attila Fulop

2
@Ousus OHCI และ UHCI เป็นมาตรฐานโฮสต์ USB 1.1, EHCI เป็นโฮสต์มาตรฐาน USB 2.0 และ XHCI เป็นโฮสต์มาตรฐาน USB 3.0
ssokolow

2
นี่เป็นทางออกที่สวยงาม อย่างไรก็ตามใน Kernels และดิสทริบิวชัน * nix อื่น ๆ คุณจะพบว่าคุณจำเป็นต้องแทนที่*hci_hcdด้วย*hci-pciเนื่องจากไดรเวอร์ hci_hcd ได้ถูกคอมไพล์แล้วในเคอร์เนล
not2qubit

1
บน Banana Pi เห็นได้ชัดว่าไม่มีรถบัส PCI ฉันต้องใช้สิ่งต่อไปนี้:for i in /sys/bus/usb/drivers/*/*:*; do
Martin Hansen

10

ฉันต้องการทำให้เป็นแบบอัตโนมัติในสคริปต์ไพ ธ อนดังนั้นฉันจึงปรับคำตอบที่เป็นประโยชน์อย่างมากของ LiLo ให้กับสิ่งต่อไปนี้:

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

ในกรณีของฉันมันเป็นไดรเวอร์ cp210x (ซึ่งฉันสามารถบอกได้lsmod | grep usbserial) ดังนั้นคุณสามารถบันทึกข้อมูลโค้ดด้านบนเป็น reset_usb.py จากนั้นทำสิ่งนี้:

sudo python reset_usb.py cp210x

สิ่งนี้อาจเป็นประโยชน์หากคุณยังไม่มีการตั้งค่าคอมไพเลอร์ ac ในระบบของคุณ แต่คุณมีไพ ธ อน


ทำงานให้ฉันใน Raspberry
webo80

1
โปรดพูดอีกสองสามคำเกี่ยวกับโซลูชันของคุณ USBDEVFS_RESETยกตัวอย่างเช่นบางสิ่งบางอย่างเกี่ยวกับการคง มันเหมือนกันสำหรับทุกระบบหรือไม่
not2qubit

@ not2qubit USBDEVFS_RESETเหมือนกันสำหรับทุกระบบ สำหรับ MIPS คือ 536892692
yegorich

lsusb รุ่นใหม่ดูเหมือนจะต้องการ-tอาร์กิวเมนต์ (โหมดต้นไม้) เพื่อแสดงข้อมูลไดรเวอร์ที่สคริปต์นี้คาดหวัง แต่สคริปต์นั้นต้องการการอัปเดตบางอย่างเพื่อแยกวิเคราะห์บรรทัดเอาต์พุตต่าง ๆ ที่สร้างขึ้นนี้
Cheetah

ดูคำตอบของฉันที่นี่askubuntu.com/a/988297/558070สำหรับเวอร์ชันที่ปรับปรุงใหม่ของสคริปต์นี้
mcarans

8

ฉันสร้างสคริปต์ Python ที่ทำให้กระบวนการทั้งหมดง่ายขึ้นโดยอิงจากคำตอบที่นี่

บันทึกสคริปต์ด้านล่างนี้เป็น reset_usb.py หรือคัดลอกrepoนี้

การใช้งาน:

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

สคริปต์:

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

นี่คือคำตอบที่ดีที่สุดสำหรับคำถามนี้
kapad

4

เนื่องจากกรณีพิเศษของคำถามคือปัญหาการสื่อสารของ gphoto2 ที่มีกล้องใน USB จึงมีตัวเลือกใน gphoto2 เพื่อรีเซ็ตการเชื่อมต่อ USB:

gphoto2 --reset

อาจจะไม่มีตัวเลือกนี้ในปี 2010 เมื่อถามคำถาม


3

วิธีที่เร็วที่สุดในการรีเซ็ตจะเป็นการรีเซ็ตตัวควบคุม USB เอง การทำเช่นนั้นจะบังคับใช้ udev เพื่อยกเลิกการลงทะเบียนอุปกรณ์ในการตัดการเชื่อมต่อและการลงทะเบียนจะกลับมาอีกครั้งเมื่อคุณเปิดใช้งาน

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

สิ่งนี้น่าจะเหมาะกับสภาพแวดล้อมพีซีส่วนใหญ่ อย่างไรก็ตามหากคุณใช้ฮาร์ดแวร์ที่กำหนดเองคุณสามารถทำซ้ำได้ตามชื่ออุปกรณ์ ด้วยวิธีนี้คุณไม่จำเป็นต้องค้นหาชื่ออุปกรณ์โดย lsusb คุณสามารถรวมเป็นสคริปต์อัตโนมัติได้เช่นกัน


1
คุณจำเป็นต้องเรียกใช้คำสั่งเหล่านี้ในฐานะรูท / sudo และจะไม่สามารถใช้ได้กับทุกระบบ (ในบางระบบคุณจะต้องแทนที่ehci_hcdด้วยehci-pciข้อมูลเพิ่มเติมเกี่ยวกับโซลูชันนี้ (อาจมาจากที่ไหน?): davidjb.com/blog / 2012/06 / …
Lambart

3

ฉันใช้ค้อนขนาดใหญ่ชนิดโดยการโหลดโมดูล นี่คือสคริปต์ 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

และนี่คือไฟล์บริการ systemd ของฉัน /usr/lib/systemd/system/usbreset.service ซึ่งเรียกใช้ usb_reset.sh หลังจากที่ผู้จัดการนักการทูตของฉันเริ่มต้น:

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

[Service]
Type=oneshot
ExecStart=/path/to/usb_reset.sh

การใช้ตัวเลือก listpci ของสคริปต์ของฉันที่นี่: askubuntu.com/a/988297/558070จะช่วยระบุโมดูล USB ที่จะโหลดซ้ำ (เช่น. xhci_pci, ehci_pci)
mcarans

2
น่าเสียดายที่ในระบบของฉันโมดูลเคอร์เนลเหล่านี้ไม่ได้แยกจากกันในรูปแบบเคอร์เนลดังนั้นสิ่งนี้จะไม่ทำงาน:rmmod: ERROR: Module xhci_pci is builtin.
unfa

3

ฉันสร้างสคริปต์ไพ ธ อนซึ่งจะรีเซ็ตอุปกรณ์ USB เฉพาะตามหมายเลขอุปกรณ์ คุณสามารถค้นหาหมายเลขอุปกรณ์จากคำสั่ง lsusb

ตัวอย่างเช่น:

$ lsusb

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

ในสายนี้ 004 คือหมายเลขอุปกรณ์

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()

ฉันชอบวิธีนี้! ฉันได้ปรับแต่งสคริปต์ให้กับรสนิยมของตัวเอง: gist.github.com/willstott101/7a455817ec6f4b8d89571ce72bdfd34a
Will S

2

นี่คือสคริปต์ที่จะรีเซ็ตรหัสผลิตภัณฑ์ / ผู้จำหน่ายที่ตรงกันเท่านั้น

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

1
ฉันพบว่าสคริปต์ของคุณมีประโยชน์ แต่ฉันควรทำอย่างไรหาก$DIRมองไม่เห็นอุปกรณ์หายไป?
Eugen Konkov

1

มีใครบางคนสั่งค้อนขนาดใหญ่? นี่คือการรวมกันจากคำตอบอื่น ๆ อีกมากมายที่นี่

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

ทำเครื่องหมายคุณได้พบว่าการผูกไม่จำเป็นจริงๆหรือเป็นที่นี่เพียงเพื่อความปลอดภัยหรือไม่
ndemou

นี่เป็นค้อนขนาดใหญ่มันอาจทำสิ่งที่ไม่จำเป็นมากมาย
Mark K Cowan

@ MarkKCowan คุณจะใช้มันอย่างไร? อะไรคือข้อโต้แย้งคำสั่งที่จำเป็น / คาดหวัง?
not2qubit

1
@ not2qubit: ไม่จำเป็นต้องมีอาร์กิวเมนต์บรรทัดคำสั่ง $@ในหนังสือมอบฉันทะ sudo เป็นเพียงแรง habbit, มีข้อบกพร่องที่จะป้องกันไม่ให้ถ้าผมตัดสินใจในภายหลังว่าจะเพิ่มการขัดแย้ง (และลืมที่จะปรับปรุงพร็อกซี่ sudo) ที่
Mark K Cowan

1
@ MarkKCowan Doh! ขออภัยเพื่อน! โอ้ใช่คำสาป! ฉันไม่ควรแสดงความคิดเห็นในเว็บไซต์นี้ในขณะที่ง่วงนอน upvoted!
not2qubit

1

บางครั้งฉันต้องการดำเนินการนี้กับอุปกรณ์เฉพาะอย่างตามที่ระบุโดย VID (รหัสผู้ขาย) และ PID (รหัสผลิตภัณฑ์) นี่คือสคริปต์ที่ฉันพบว่ามีประโยชน์สำหรับวัตถุประสงค์นี้ซึ่งใช้ไลบรารี libusb ที่ดี

วิ่งครั้งแรก:

sudo apt-get install libusb-dev

จากนั้นรีเซ็ต cDeviceConnection ของไฟล์ c ++ นี้ควรทำงานนี้โดยการรีเซ็ตการเชื่อมต่ออุปกรณ์ตามที่ระบุโดย vid และ 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;
}

(ถูกขโมยจากแคตตาล็อก TIL ส่วนตัวของฉัน: https://github.com/Marviel/TIL/blob/master/unix_tools/Reset_specific_USB_Device.md )


3
กรุณาคุณสามารถแสดงวิธีการเรียกใช้สคริปต์นี้
George Udosen

แน่นอนให้ฉันอัปเดต
Marviel

1
@Marviel เรายังคงรอการอัปเดต ...
Not2qubit

ต้องการ downvote อย่างไร้ประโยชน์
Eugen Konkov

1

ฉันสร้างสคริปต์ทุบตีง่ายๆสำหรับรีเซ็ตอุปกรณ์ USB โดยเฉพาะ

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

0

บางทีนี่อาจใช้งานได้กับกล้องเช่นกัน:

หลังจากฟื้นสภาพUSB 3.0HDD ที่หิวโหยบน3.4.42Linux (kernel.org) แล้ว dmesgบอกว่ามันเป็นคำสั่งหมดเวลาหลังจาก 360s (ขออภัยฉันไม่สามารถคัดลอก syslog ที่นี่ไม่ได้เชื่อมต่อเครือข่าย) และไดรฟ์แขวนอย่างสมบูรณ์ กระบวนการเข้าถึงอุปกรณ์นั้นถูกบล็อกในเคอร์เนลซึ่งไม่สามารถฆ่าได้ NFSแขวน, ZFSแขวน, ddแขวน

หลังจากทำเช่นนี้ทุกอย่างทำงานได้อีกครั้ง dmesgบอกเพียงบรรทัดเดียวเกี่ยวกับUSBอุปกรณ์ที่พบ

ฉันไม่รู้จริงๆว่ารายละเอียดต่อไปนี้เป็นอย่างไร แต่มันได้ผล

ตัวอย่างผลลัพธ์ต่อไปนี้มาจาก Debian Squeeze with 2.6.32-5-686kernel ดังนั้นฉันคิดว่ามันใช้งานได้ตั้งแต่ 2.6 ขึ้นไป:

$ 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

หากวิธีนี้ใช้ไม่ได้ผลอาจมีคนอื่นรู้วิธีส่งการรีเซ็ตจริงไปยังอุปกรณ์


0

ลองสิ่งนี้เป็นการถอดปลั๊กซอฟต์แวร์ (นำออก)

บางครั้งไม่ทำงานเพียงแค่ผูกอุปกรณ์สำหรับอุปกรณ์บางอย่าง

ตัวอย่าง:

ฉันต้องการลบหรือเปิด "Genius NetScroll 120" ของฉัน

จากนั้นฉันก่อนตรวจสอบอุปกรณ์ usb ที่ต่ออยู่ของฉัน

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

ตกลงฉันพบเมาส์แล้วมันมีบัส 002, อุปกรณ์ 009, idVendor 0458 และ idProduct 003a ดังนั้นนี่คือข้อมูลอุปกรณ์อ้างอิงเกี่ยวกับเมาส์

นี่เป็นสิ่งสำคัญหมายเลขรถบัสเป็นชื่อพา ธ เริ่มต้นไปยังอุปกรณ์และฉันจะตรวจสอบหมายเลขผลิตภัณฑ์และผู้ขายเพื่อให้แน่ใจว่าอุปกรณ์ที่ถูกต้องที่จะลบ

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

ให้ความสนใจกับโฟลเดอร์ตรวจสอบจุดเริ่มต้นด้วยหมายเลขโฟลเดอร์ 2 ฉันจะตรวจสอบอันนี้เพราะ Bus ของฉันคือ 002 และหนึ่งต่อหนึ่งฉันได้ตรวจสอบแต่ละโฟลเดอร์ที่มี idVendor ที่ถูกต้องและ idProduct เกี่ยวกับข้อมูลเมาส์ของฉัน

ในกรณีนี้ฉันจะดึงข้อมูลด้วยคำสั่งนี้:

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

ตกลงเส้นทาง /sys/bus/usb/drivers/usb/2-1.3/ ตรงกับเมาส์ข้อมูลของฉัน! XDDD

ได้เวลาลบอุปกรณ์แล้ว!

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

เสียบอุปกรณ์ usb อีกครั้งและใช้งานได้อีกครั้ง!


10
ถ้าคุณไม่สามารถเสียบมันอีกครั้ง (ตัวอย่างเช่นเป็นเครื่องอ่าน sdcard ภายใน)
aleb

0

หากคุณรู้ชื่ออุปกรณ์สคริปต์ไพ ธ อนนี้จะใช้งานได้:

#!/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()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.