Як скинути USB-пристрій з командного рядка?


164

Чи можливо скинути підключення USB-пристрою, не фізично відключаючи / підключаючись до ПК?

Зокрема, мій пристрій - це цифровий фотоапарат. Я використовую gphoto2, але останнім часом я отримую "помилки читання пристрою", тому я хотів би спробувати зробити програмне відновлення з'єднання.

Як я можу сказати, для камери не завантажуються модулі ядра. Єдине, що виглядає пов'язаним - це usbhid.


Яку версію Ubuntu ви використовуєте?
Користувач

Я спробував обидва рішення від Li Lo та ssokolow, все, що я отримую, заборонений у дозволі, номаттер, якщо я використовую код 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. Отримайте ідентифікатор шини та пристрою 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. Ідентифікатор пристрою може змінюватись. Щоб отримати його для миші, я загорнув вище код в декілька команд оболонки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 у lsusb, він помиляється: "Помилка в ioctl: це каталог", будь-яка ідея? Я спробував на обох концентраторах USB 3.0
Power Aquarius

1
Якщо хтось, хто читає це, має (usb) мишу заморожувати після входу в Ubuntu 16.04 (з dmesg, заповненим "вхідним статусом irq -75"), я можу підтвердити, що це єдине рішення, яке працювало для мене. Дякую
Агустін Беез

1
@ Водолій, я також отримую ту ж помилку "Помилка ioctl: Є каталог". Чи вирішено?
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: Каталог відсутній
Nicolas Marchildon

Схоже, вони змінили макет файлової системи usbfs. Я спробую розібратися, який новий спосіб робити речі на Ubuntu, коли я не такий сонний.
ssokolow

9
Дякую, що ви працювали чудово! Можливо, вам слід також згадати про виконання echo 1 > /sys/bus/usb/devices/whatever/authorizedвсередині сценарію, щоб повторно включити пристрій, як тільки він був відключений. Я робив це як на миші, так і на клавіатурі usb, і я закінчив повністю глуху систему :)
Avio

1
Це надзвичайно дивно, якщо воно автоматично встановлює значення на 1, оскільки його встановлюють на 0, це говорить системі, що ви не хочете, щоб пристрій був "авторизованим" і тому був недоступний.
Тім Тісдалл

2
Примітка для всіх, хто намагається перейти на | sudo tee ...підхід до привілейованих, /sysпише: Це погано руйнується, якщо у вас ще немає кешованих даних про судо. 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, ви можете використовувати відповідний ідентифікатор пристрою/sys/bus/pci/drivers/ehci_hcd


Примітки: [1]: *hci_hcdдрайвери ядра зазвичай керують портами USB. ohci_hcdі uhci_hcdпризначені для портів USB1.1, ehci_hcdдля портів USB2 і 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
Аттіла Фулоп

2
@Otheus OHCI і UHCI - хост стандарту USB 1.1, EHCI - хост-стандарт USB 2.0, а XHCI - стандарт хоста USB 3.0.
ssokolow

2
Це прекрасне рішення. Однак, на деяких пізніших ядрах і інших * NIX дистрибутивах, ви виявите , що вам необхідно замінити *hci_hcdз *hci-pci, як водій hci_hcd вже скомпільовано в ядро.
not2qubit

1
На Banana Pi, очевидно, немає шини PCI, я повинен був використовувати наступне:for i in /sys/bus/usb/drivers/*/*:*; do
Мартін Хансен

10

Мені потрібно було автоматизувати це за допомогою сценарію python, тому я адаптував надзвичайно корисну відповідь 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

Це також може бути корисним, якщо у вас ще не встановлено компілятор змінного струму у вашій системі, але у вас є python.


працював для мене на малиновому
webo80

1
Ще кілька слів щодо вашого рішення, будь ласка. Наприклад, щось про постійне USBDEVFS_RESET. Чи завжди це однаково для всіх систем?
not2qubit

@ not2qubit USBDEVFS_RESETоднаковий для всіх систем. Для MIPS це 536892692.
Єгорич

Новіші версії lsusb, здається, потребують -tаргументу (режим дерева), щоб показати інформацію про драйверів, що очікує цей скрипт, але сценарій потребує деяких оновлень, щоб проаналізувати різні вихідні рядки, які це генерує
Гепард,

Дивіться мою відповідь тут askubuntu.com/a/988297/558070 для значно покращеної версії цього сценарію.
мкаран

8

Я створив сценарій Python, який спрощує весь процес на основі відповідей тут.

Збережіть сценарій нижче як reset_usb.py або клонуйте це репо .

Використання:

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)

це найкраща відповідь на це питання.
капад

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
Вам потрібно запустити ці команди , як корінь / Судо, і він не буде працювати на всіх системах (на деяких, вам необхідно замінити ehci_hcdз ehci-pciДетальніше про це рішення (можливо , звідки він взявся).? Davidjb.com/blog /
2012/06

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

І це мій системний файл служби /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.
недобре

3

Я створив сценарій python, який буде скинути певний 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
Буде 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зникає і пристрій не видно?
Євген Конков

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

Це кувалда, вона, мабуть, робить багато зайвих речей
Марк К Коуан

@MarkKCowan, як ти ним користуєшся? Які аргументи команд потрібні / очікувані?
not2qubit

1
@ not2qubit: аргументи командного рядка не потрібні. $@У SUDO проксі просто сила Habbit, маючи це запобігає помилки , якщо пізніше я вирішив додати аргументи (і забудьте оновити SUDO проксі).
Mark K Cowan

1
@MarkKCowan До! Вибачте, товариш! О так прокляття! Мені не слід коментувати цей сайт, коли я спляча. Оголошено!
not2qubit

1

Іноді я хочу виконати цю операцію на певному пристрої, як ідентифіковано VID (ідентифікатор постачальника) та PID (ідентифікатор продукту). Цей сценарій, який я знайшов корисним для цієї мети, використовує чудову бібліотеку libusb.

Перший запуск:

sudo apt-get install libusb-dev

Тоді цей c ++ файл resetDeviceConnection повинен виконати це завдання - скинути з’єднання пристрою, як ідентифікували 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
Покажіть, будь ласка, як працює цей сценарій .
Джордж Удосен

Звичайно, дозвольте мені оновити.
Marviel

1
@Marviel, ми все ще чекаємо оновлення ...
not2qubit

потребує скоромовки як марної
Євген

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.0жорсткий диск на 3.4.42(kernel.org) Linux. dmesgсказав, що він випереджав команди після 360-х років (вибачте, я не можу скопіювати сюди syslog, не підключені мережі) і накопичувач повністю висів. Процеси доступу до пристрою були заблоковані в ядрі. NFSповісити, ZFSповісити, ddповісити.

Після цього все знову працювало. dmesgрозповів лише один рядок про USBзнайдений пристрій.

Я дійсно не маю уявлення, що далі робить детально. Але це спрацювало.

Наступний приклад виводиться з Debian Squeeze з 2.6.32-5-686ядром, тому я думаю, що він працює для 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

Спробуйте це, відключіть програмне забезпечення (Eject).

Інколи не працює просто відв’язати пристрій для деяких пристроїв.

Приклад:

Я хочу видалити або вийняти мій "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, я перевірю цю, тому що моя шина 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

0

Якщо ви знаєте ім'я свого пристрою, цей сценарій python буде працювати:

#!/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()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.