Làm thế nào để bạn thiết lập lại một thiết bị USB từ dòng lệnh?


164

Có thể thiết lập lại kết nối của thiết bị USB mà không cần ngắt kết nối / kết nối vật lý với PC không?

Cụ thể, thiết bị của tôi là một máy ảnh kỹ thuật số. Tôi đang sử dụng gphoto2, nhưng gần đây tôi gặp "lỗi đọc thiết bị", vì vậy tôi muốn thử thiết lập lại phần mềm kết nối.

Từ những gì tôi có thể nói, không có mô-đun hạt nhân nào được tải cho máy ảnh. Người duy nhất có vẻ liên quan là usbhid.


Bạn đang sử dụng phiên bản Ubuntu nào?
Người dùng

Tôi đã thử cả hai giải pháp của Li Lo và ssokolow, tất cả những gì tôi nhận được là sự cho phép, từ chối nếu tôi sử dụng mã usbreset hoặc dòng lệnh "echo 0> ..." tôi sử dụng sudo, cũng là thiết bị usb của tôi được sở hữu bởi root nhưng tôi có thể sử dụng chúng mà không có quyền quản trị (máy ảnh ..)

1
Nếu bạn đang nhận được lỗi đọc, bạn có thể có một số lỗi dữ liệu. Nếu máy ảnh của bạn sử dụng thẻ nhớ ngoài (như MicroSD), có thể là khôn ngoan khi kết nối nó với máy tính và chạy fsck.
TSJNachos117

Câu trả lời:


118

Lưu lại như sau 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;
}

Việc chạy các lệnh sau trong terminal:

  1. Biên dịch chương trình:

    $ cc usbreset.c -o usbreset
    
  2. Nhận Bus và ID thiết bị của thiết bị USB bạn muốn đặt lại:

    $ lsusb  
    Bus 002 Device 003: ID 0fe9:9010 DVICO  
    
  3. Làm cho chương trình biên dịch của chúng tôi thực thi:

    $ chmod +x usbreset
    
  4. Thực hiện chương trình với đặc quyền sudo; thực hiện thay thế cần thiết cho <Bus><Device>id như được tìm thấy bằng cách chạy lsusblệnh:

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

Nguồn của chương trình trên: http://marc.info/?l=linux-usb&m=121459435621262&w=2


3
Điều này hoạt động với Ubuntu 13.10. ID thiết bị có thể thay đổi. Để lấy nó cho chuột, tôi đã gói mã ở trên trong vài lệnh shellecho $(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 22/12/13

1
ổ đĩa ngoài của tôi dường như không thể phát hiện được (tôi phải kết nối lại cáp usb); nó là một USB2.0 được kết nối trên cổng máy tính để bàn usb3.0; Khi tôi chạy usbreset /dev/bus/usb/011/001đó là một trong 2 trung tâm gốc của USB 3.0 lsusb, nó báo lỗi: "Lỗi trong ioctl: Là một thư mục", có ideia nào không? Tôi đã thử trên cả hai trung tâm usb 3.0
Aquarius Power

1
Nếu bất cứ ai đọc cái này bị đóng băng (usb) sau khi đăng nhập vào Ubuntu 16.04 (với dmesg được điền bởi "input irq status -75"), tôi có thể xác nhận rằng đây là giải pháp duy nhất phù hợp với tôi. Cảm ơn bạn
Agustin Baez

1
@ Bảo Bình, tôi cũng nhận được lỗi tương tự "Lỗi trong ioctl: Là một thư mục". Được giải quyết chưa?
tiền chuộc

1
Xem câu trả lời của tôi ở đây Askubfox.com/a/988297/558070 sử dụng cùng một phương pháp đặt lại như câu trả lời này nhưng cũng cho phép liệt kê đơn giản và tìm kiếm thiết bị.
mcarans

58

Trước đây tôi chưa thấy mình trong hoàn cảnh cụ thể của bạn, vì vậy tôi không chắc liệu nó có đủ không, nhưng cách đơn giản nhất tôi tìm thấy để đặt lại thiết bị USB là lệnh này: (Không cần ứng dụng bên ngoài)

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"

Đó là cái thực tế tôi sử dụng để đặt lại Kinect của mình vì libfreenect dường như không có API để đưa nó trở lại trạng thái ngủ. Nó nằm trong hộp Gentoo của tôi, nhưng kernel phải đủ mới để sử dụng cùng cấu trúc đường dẫn cho sysfs.

Rõ ràng là bạn sẽ không 1-4.6nhưng bạn có thể kéo đường dẫn thiết bị đó khỏi nhật ký kernel ( dmesg) hoặc bạn có thể sử dụng một cái gì đó như lsusbđể lấy ID nhà cung cấp và sản phẩm và sau đó sử dụng một lệnh nhanh như thế này để liệt kê cách các đường dẫn liên quan đến nhà cung cấp khác / cặp ID sản phẩm:

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: không thể tạo /sys/bus/usb/devices/1-3.1:1.0/authorized: Directory nonexistent
Nicolas Marchildon

Có vẻ như họ đã thay đổi bố cục của hệ thống tập tin usbfs. Tôi sẽ cố gắng tìm ra cách thức mới để làm mọi thứ trên Ubuntu một khi tôi không buồn ngủ quá.
ssokolow

9
Cảm ơn bạn đã làm việc tuyệt vời! Có lẽ bạn cũng nên đề cập đến để thực hiện một echo 1 > /sys/bus/usb/devices/whatever/authorizedtập lệnh bên trong để kích hoạt lại thiết bị ngay khi nó bị vô hiệu hóa. Tôi đã làm điều đó trên cả bàn phím chuột và usb và tôi đã kết thúc với một hệ thống hoàn toàn điếc :)
Avio

1
Thật kỳ lạ nếu nó tự động đặt lại giá trị thành 1 khi đặt nó thành 0 đang nói với hệ thống mà bạn không muốn thiết bị được "ủy quyền" và do đó không thể truy cập được.
Tim Tonomall

2
Một lưu ý cho bất cứ ai cố gắng chuyển sang | sudo tee ...cách tiếp cận /sysviết đặc quyền : Điều đó sẽ phá vỡ nếu bạn chưa có thông tin đăng nhập sudo của mình. sudo sh -c "..."hoạt động như mong đợi khi sudo cần nhắc mật khẩu.
ssokolow

51

Điều này sẽ thiết lập lại tất cả các cổng USB1 / 2/3 đính kèm [1]:

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

Tôi tin rằng điều này sẽ giải quyết vấn đề của bạn. Nếu bạn không muốn đặt lại tất cả các điểm cuối USB, bạn có thể sử dụng ID thiết bị phù hợp từ/sys/bus/pci/drivers/ehci_hcd


Lưu ý: [1]: *hci_hcdtrình điều khiển hạt nhân thường điều khiển các cổng USB. ohci_hcduhci_hcddành cho cổng USB1.1, ehci_hcddành cho cổng USB2 và xhci_hcddành cho cổng USB3. (xem https://en.wikipedia.org/wiki/host_controll_interface_(USB,_Firewire) )


Bạn có tin rằng nó có thể hoạt động để đánh thức một bộ lưu trữ usb ?
Sức mạnh Bảo Bình

2
Mặc dù tôi đã nhận được thông báo sau: ls: cannot access /sys/bus/pci/drivers/ehci_hcd/: No such file or directoryđiều này đã giải quyết được vấn đề, chuột đã bắt đầu hoạt động ngay lập tức. +1
Attila Fulop

2
@Otheus OHCI và UHCI là các tiêu chuẩn máy chủ USB 1.1, EHCI là tiêu chuẩn máy chủ USB 2.0 và XHCI là tiêu chuẩn máy chủ USB 3.0.
ssokolow

2
Đây là một giải pháp đẹp. Tuy nhiên, trên một số Kernels sau này và các bản phân phối * nix khác, bạn sẽ thấy rằng bạn cần thay thế *hci_hcdbằng *hci-pci, vì trình điều khiển hci_hcd đã được biên dịch vào Kernel.
not2qubit

1
Trên Banana Pi, rõ ràng không có xe buýt PCI, tôi đã phải sử dụng như sau:for i in /sys/bus/usb/drivers/*/*:*; do
Martin Hansen

10

Tôi cần tự động hóa điều này trong một kịch bản python, vì vậy tôi đã điều chỉnh câu trả lời cực kỳ hữu ích của LiLo sau đây:

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

Trong trường hợp của tôi, đó là trình điều khiển cp210x (mà tôi có thể biết từ đó lsmod | grep usbserial), vì vậy bạn có thể lưu đoạn mã trên dưới dạng reset_usb.py và sau đó thực hiện việc này:

sudo python reset_usb.py cp210x

Điều này cũng có thể hữu ích nếu bạn chưa có thiết lập trình biên dịch ac trên hệ thống của mình, nhưng bạn có python.


làm việc cho tôi trên Raspberry
webo80

1
Xin hãy nói thêm vài lời về giải pháp của bạn. Ví dụ, một cái gì đó về hằng số USBDEVFS_RESET. Có phải nó luôn giống nhau cho tất cả các hệ thống?
not2qubit

@ not2qubit USBDEVFS_RESETlà giống nhau cho tất cả các hệ thống. Đối với MIPS, đó là 536892692.
yegorich

Các phiên bản mới hơn của lsusb dường như cần -tđối số (chế độ cây) để hiển thị thông tin trình điều khiển mà tập lệnh này đang mong đợi, nhưng tập lệnh sau đó cần một số cập nhật để phân tích các dòng đầu ra khác nhau mà nó tạo ra
Cheetah

Xem câu trả lời của tôi ở đây Askubfox.com/a/988297/558070 để biết phiên bản cải tiến của tập lệnh này.
mcarans

8

Tôi đã tạo một tập lệnh Python đơn giản hóa toàn bộ quá trình dựa trên các câu trả lời ở đây.

Lưu tập lệnh bên dưới dưới dạng reset_usb.py hoặc sao chép repo này .

Sử dụng:

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

Kịch bản:

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

đây là câu trả lời tốt nhất cho câu hỏi này
kapad

4

Vì trường hợp đặc biệt của câu hỏi là sự cố giao tiếp của gphoto2 với camera trên USB, có một tùy chọn trong gphoto2 để đặt lại kết nối USB của nó:

gphoto2 --reset

Có lẽ tùy chọn này đã không tồn tại vào năm 2010 khi câu hỏi được hỏi.


3

Cách nhanh nhất để thiết lập lại sẽ là tự thiết lập lại bộ điều khiển USB. Làm như vậy sẽ buộc udev hủy đăng ký thiết bị khi ngắt kết nối và đăng ký trở lại sau khi bạn bật thiết bị.

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

Điều này sẽ làm việc cho hầu hết các môi trường PC. Tuy nhiên, nếu bạn đang sử dụng một số phần cứng tùy chỉnh, bạn có thể chỉ cần lặp qua tên thiết bị. Với phương pháp này, bạn không cần phải tìm ra tên thiết bị theo lsusb. Bạn có thể kết hợp trong một kịch bản tự động là tốt.


1
Bạn cần chạy các lệnh này dưới dạng root / sudo và nó sẽ không hoạt động trên tất cả các hệ thống (trên một số, bạn sẽ cần phải thay thế ehci_hcdbằng ehci-pci. Thông tin thêm về giải pháp này (có lẽ nó đến từ đâu?): Davidjb.com/blog /
2012/06

3

Tôi đang sử dụng loại búa tạ bằng cách tải lại các mô-đun. Đây là tập lệnh usb_reset.sh của tôi:

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

Và đây là tệp dịch vụ systemd của tôi /usr/lib/systemd/system/usbreset.service chạy usb_reset.sh sau khi trình quản lý bằng tốt nghiệp của tôi bắt đầu:

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

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

Sử dụng tùy chọn listpci của tập lệnh của tôi ở đây: askubfox.com/a/988297/558070 sẽ giúp xác định mô-đun USB nào để tải lại (ví dụ: xhci_pci, ehci_pci).
mcarans

2
Đáng tiếc là trên hệ thống của tôi những mô-đun hạt nhân không tách rời thành hạt nhân, vì vậy đây sẽ không làm việc:rmmod: ERROR: Module xhci_pci is builtin.
unfa

3

Tôi đã tạo một tập lệnh python sẽ thiết lập lại một thiết bị USB cụ thể dựa trên số thiết bị. Bạn có thể tìm ra số thiết bị từ lệnh lsusb.

ví dụ:

$ lsusb

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

Trong chuỗi này 004 là số thiết bị

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

Tôi thích giải pháp này! Tôi đã thực hiện một vài điều chỉnh cho kịch bản theo sở thích của riêng mình: gist.github.com/willstott101/7a455817ec6f4b8d89571ce72bdfd34a
Will S

2

Đây là tập lệnh sẽ chỉ đặt lại ID sản phẩm / nhà cung cấp phù hợp.

#!/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
Tôi thấy kịch bản của bạn là hữu ích. Nhưng tôi nên làm gì nếu $DIRbiến mất và thiết bị không nhìn thấy được?
Eugen Konkov

1

Có ai đó đặt mua một chiếc búa tạ? Điều này được chắp ghép từ nhiều câu trả lời khác nhau ở đây.

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

Mark, bạn có thấy rằng việc bỏ ràng buộc là thực sự cần thiết hay nó ở đây chỉ để ở bên an toàn?
ndemou

Đây là một chiếc búa tạ, nó có thể làm rất nhiều thứ không cần thiết
Mark K Cowan

@MarkKCowan, bạn sử dụng nó như thế nào? Các đối số lệnh cần thiết / dự kiến ​​là gì?
not2qubit

1
@ not2qubit: Không yêu cầu đối số dòng lệnh. Các $@trong proxy sudo chỉ là một lực lượng của habbit, có nó ngăn chặn lỗi nếu sau, tôi quyết định thêm lập luận (và quên cập nhật proxy sudo).
Mark K Cowan

1
@MarkKCowan Doh! Xin lỗi bạn đời! Ồ vâng lời nguyền! Tôi không nên bình luận trên trang web này trong khi buồn ngủ. Nâng cao!
not2qubit

1

Đôi khi tôi muốn thực hiện thao tác này trên một thiết bị cụ thể, như được xác định bởi VID (id nhà cung cấp) và PID (id sản phẩm). Đây là một kịch bản tôi thấy hữu ích cho mục đích này, sử dụng thư viện libusb tiện lợi.

Lần chạy đầu tiên:

sudo apt-get install libusb-dev

Sau đó, resetDeviceConnection của tệp c ++ này sẽ thực hiện tác vụ này, đặt lại kết nối thiết bị như được xác định bởi vid và 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;
}

(bị đánh cắp từ danh mục TIL cá nhân của tôi: https://github.com/Marviel/TIL/blob/master/unix_tools/Reset_specific_USB_Device.md )


3
Xin vui lòng cho biết kịch bản này được chạy như thế nào .
George Udosen

Chắc chắn, hãy để tôi cập nhật.
Marviel

1
@Marviel, chúng tôi vẫn đang chờ cập nhật ...
not2qubit

cần downvote là vô dụng
Eugen Konkov

1

tôi đã tạo một tập lệnh bash đơn giản để thiết lập lại thiết bị USB cụ thể.

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

Có lẽ điều này cũng làm việc cho một máy ảnh:

Sau khi hồi sinh một USB 3.0ổ cứng bị bỏ đói trên 3.4.42Linux (kernel.org) về phía tôi. dmesgnói rằng đó là thời gian ra lệnh sau 360 giây (xin lỗi, tôi không thể sao chép nhật ký hệ thống ở đây, không kết nối mạng) và ổ đĩa bị treo hoàn toàn. Các quy trình truy cập thiết bị đã bị chặn trong kernel, không thể thực hiện được. NFShung, ZFShung, ddhung.

Sau khi làm điều này, mọi thứ hoạt động trở lại. dmesgchỉ nói một dòng về USBthiết bị được tìm thấy.

Tôi thực sự không có ý tưởng gì sau đây làm chi tiết. Nhưng nó đã làm việc.

Kết quả ví dụ sau đây là từ Debian Squeeze với 2.6.32-5-686kernel, vì vậy tôi nghĩ rằng nó hoạt động cho 2.6 trở lên:

$ 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

Nếu điều này không hoạt động, có lẽ ai đó khác có thể tìm ra cách gửi thiết lập lại thực sự cho thiết bị.


0

Hãy thử điều này, đó là một phần mềm rút phích cắm (Eject).

Đôi khi không hoạt động đơn giản là hủy kết nối thiết bị cho một số thiết bị.

Thí dụ:

Tôi muốn xóa hoặc đẩy "Genius NetScroll 120" của tôi.

Sau đó, tôi đầu tiên Kiểm tra thiết bị usb đính kèm của tôi

$ 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, tôi đã tìm thấy con chuột của mình, nó có Bus 002, Thiết bị 009, idVendor 0458 và idSản phẩm 003a, vì vậy đây là thông tin thiết bị tham khảo về chuột.

Điều này rất quan trọng, số Bus là đường dẫn tên bắt đầu đến thiết bị và tôi sẽ kiểm tra Id sản phẩm và Nhà cung cấp để đảm bảo xóa đúng thiết bị.

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

Chú ý vào các thư mục, kiểm tra bắt đầu với thư mục số 2, tôi sẽ kiểm tra cái này vì Bus của tôi là 002 và từng cái một tôi đã kiểm tra từng thư mục chứa idVendor chính xác và idSản phẩm về thông tin chuột của tôi.

Trong trường hợp này, tôi sẽ lấy thông tin bằng lệnh này:

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

Ok, đường dẫn /sys/bus/usb/drivers/usb/2-1.3/ khớp với chuột thông tin của tôi! XDDĐ.

Đã đến lúc tháo thiết bị!

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

Cắm lại thiết bị usb và nó hoạt động trở lại!


10
Điều gì nếu bạn không thể cắm lại? (ví dụ: đó là trình đọc sdcard nội bộ)
aleb

0

Nếu bạn biết tên thiết bị của mình, tập lệnh python này sẽ hoạt động:

#!/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()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.