Jak zresetować urządzenie USB z wiersza poleceń?

164

Czy można zresetować połączenie urządzenia USB bez fizycznego odłączania / podłączania od komputera?

W szczególności moje urządzenie to aparat cyfrowy. Używam gphoto2, ale ostatnio dostaję „błędy odczytu urządzenia”, więc chciałbym spróbować zresetować oprogramowanie połączenia.

Z tego, co mogę powiedzieć, nie ma modułów jądra ładowanych do kamery. Jedyny, który wygląda na spokrewniony, to usbhid.

cmcginty
źródło
Z jakiej wersji Ubuntu korzystasz?
Użytkownik
wypróbowałem oba rozwiązania Li Lo i ssokolow, wszystko, co dostaję, to odmowa zgody, nomatter, jeśli użyję kodu usbreset lub wiersza poleceń „echo 0> ...” używam sudo, również moje urządzenia USB są własnością root, ale ja mogą z nich korzystać bez uprawnień administratora (kamery ..)
1
Jeśli otrzymujesz błędy odczytu, możesz mieć uszkodzenie danych. Jeśli twój aparat używa zewnętrznej karty pamięci (takiej jak MicroSD), rozsądnie jest podłączyć ją do komputera i uruchomić fsck.
TSJNachos117

Odpowiedzi:

118

Zapisz następujące jako 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;
}

Uruchom następujące polecenia w terminalu:

  1. Skompiluj program:

    $ cc usbreset.c -o usbreset
    
  2. Uzyskaj identyfikator magistrali i urządzenia urządzenia USB, które chcesz zresetować:

    $ lsusb  
    Bus 002 Device 003: ID 0fe9:9010 DVICO  
    
  3. Spraw, aby nasz skompilowany program był wykonywalny:

    $ chmod +x usbreset
    
  4. Uruchom program z uprawnieniami sudo; dokonaj niezbędnych podstawień <Bus>i <Device>identyfikatorów zgodnie z lsusbpoleceniem:

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

Źródło powyższego programu: http://marc.info/?l=linux-usb&m=121459435621262&w=2

Li Lo
źródło
3
Działa to z Ubuntu 13.10. Identyfikator urządzenia może się różnić. Aby pobrać go dla myszy, 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
zawarłem
1
mój dysk zewnętrzny wydaje się niewykrywalny (muszę ponownie podłączyć kabel USB); jest to usb2.0 podłączony do portu komputera stacjonarnego usb3.0; kiedy uruchamiam usbreset /dev/bus/usb/011/001jeden z 2 głównych hubów USB 3.0 w lsusb, pojawia się błąd: „Błąd w ioctl: czy katalog”, jakieś idee? Próbowałem na obu hubach USB 3.0
Aquarius Power
1
Jeśli ktoś, kto to czyta, ma zawieszenie myszy (usb) po zalogowaniu się na Ubuntu 16.04 (z dmesg wypełnionym „input irq status -75”), mogę potwierdzić, że to jedyne rozwiązanie, które działało dla mnie. Dziękuję
Agustin Baez
1
@ Aquarius, pojawia się również ten sam błąd „Błąd w ioctl: jest katalogiem”. Czy to jest rozwiązane?
ransh
1
Zobacz moją odpowiedź tutaj askubuntu.com/a/988297/558070, która korzysta z tej samej metody resetowania co ta odpowiedź, ale umożliwia także uproszczone wyświetlanie i wyszukiwanie urządzeń.
mcarans
58

Nie znalazłem się wcześniej w konkretnych okolicznościach, więc nie jestem pewien, czy to wystarczy, ale najprostszym sposobem na zresetowanie urządzenia USB jest to polecenie: (Nie są wymagane żadne aplikacje zewnętrzne)

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"

Właśnie tego używam do resetowania Kinect, ponieważ libfreenect wydaje się nie mieć API do przywracania go do stanu uśpienia. Jest na moim pudełku Gentoo, ale jądro powinno być wystarczająco nowe, aby używać tej samej struktury ścieżki dla sysfs.

Oczywiście, że nie, 1-4.6ale możesz albo pobrać tę ścieżkę urządzenia z dziennika jądra ( dmesg), albo użyć czegoś takiego, lsusbaby uzyskać identyfikatory dostawcy i produktu, a następnie użyć szybkiego polecenia, aby wyświetlić relacje między ścieżkami do różnych dostawców / pary identyfikatora produktu:

for X in /sys/bus/usb/devices/*; do 
    echo "$X"
    cat "$X/idVendor" 2>/dev/null 
    cat "$X/idProduct" 2>/dev/null
    echo
done
ssokolow
źródło
sh: 1: nie można utworzyć /sys/bus/usb/devices/1-3.1:1.0/authorized: Katalog nie istnieje
Nicolas Marchildon
Wygląda na to, że zmienili układ systemu plików usbfs. Spróbuję dowiedzieć się, jaki jest nowy sposób robienia rzeczy na Ubuntu, kiedy nie będę tak śpiący.
ssokolow
9
Dziękuję, że pracowałeś świetnie! Być może powinieneś także wspomnieć o wykonaniu echo 1 > /sys/bus/usb/devices/whatever/authorizedskryptu w celu ponownego włączenia urządzenia, gdy tylko zostanie wyłączone. Zrobiłem to zarówno na mojej myszy, jak i na klawiaturze USB i skończyłem z całkowicie głuchym systemem :)
Avio
1
To bardzo dziwne, jeśli automatycznie ponownie ustawia wartość na 1, ponieważ ustawienie na 0 mówi systemowi, że nie chcesz, aby urządzenie było „autoryzowane”, a zatem niedostępne.
Tim Tisdall
2
Uwaga dla każdego, kto próbuje przejść do | sudo tee ...podejścia do uprzywilejowanego /syspisze: To psuje się źle, jeśli nie masz jeszcze buforowanych poświadczeń sudo. sudo sh -c "..."działa zgodnie z oczekiwaniami, gdy sudo musi poprosić o hasło.
ssokolow
51

Spowoduje to zresetowanie wszystkich podłączonych portów 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

Wierzę, że to rozwiąże twój problem. Jeśli nie chcesz resetować wszystkich punktów końcowych USB, możesz użyć odpowiedniego identyfikatora urządzenia z/sys/bus/pci/drivers/ehci_hcd


Uwagi: [1]: *hci_hcdsterowniki jądra zwykle kontrolują porty USB. ohci_hcdi uhci_hcdsą dla portów USB 1.1, ehci_hcdsą dla portów USB2 i xhci_hcddla portów USB3. (patrz https://en.wikipedia.org/wiki/Host_controller_interface_(USB,_Firewire) )

Tamás Tapsonyi
źródło
Czy uważasz, że może to działać, aby obudzić pamięć USB ?
Aquarius Power
2
Mimo że otrzymałem następujący komunikat: ls: cannot access /sys/bus/pci/drivers/ehci_hcd/: No such file or directoryto rozwiązało problem, mysz natychmiast zaczęła działać. +1
Attila Fulop
2
@Otheus OHCI i UHCI to standardy hosta USB 1.1, EHCI to standard hosta USB 2.0, a XHCI to standard hosta USB 3.0.
ssokolow
2
To jest piękne rozwiązanie. Jednakże, w niektórych późniejszych Jądra i innych dystrybucjach * nix, okaże się, że trzeba zastąpić *hci_hcdz *hci-pci, jak kierowca hci_hcd jest już skompilowany do jądra.
not2qubit
1
Na Banana Pi najwyraźniej nie ma magistrali PCI, musiałem użyć następujących opcji:for i in /sys/bus/usb/drivers/*/*:*; do
Martin Hansen
10

Musiałem zautomatyzować to w skrypcie python, więc dostosowałem niezwykle pomocną odpowiedź LiLo na następujące:

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

W moim przypadku był to sterownik cp210x (o którym mogłem powiedzieć lsmod | grep usbserial), więc możesz zapisać powyższy fragment jako reset_usb.py, a następnie zrobić to:

sudo python reset_usb.py cp210x

Może to być również pomocne, jeśli nie masz jeszcze konfiguracji kompilatora ac w swoim systemie, ale masz python.

Piotr
źródło
pracował dla mnie na Raspberry
webo80
1
Poproszę jeszcze kilka słów na temat twojego rozwiązania. Na przykład coś o stałej USBDEVFS_RESET. Czy zawsze jest tak samo dla wszystkich systemów?
not2qubit
@ not2qubit USBDEVFS_RESETjest taki sam dla wszystkich systemów. W przypadku MIPS jest to 536892692.
yegorich
Nowsze wersje lsusb wydają się potrzebować -targumentu (tryb drzewa), aby wyświetlić informacje o sterowniku, których oczekuje ten skrypt, ale skrypt potrzebuje następnie aktualizacji, aby przeanalizować różne generowane linie wyjściowe
Cheetah
Zobacz moją odpowiedź tutaj askubuntu.com/a/988297/558070, aby uzyskać znacznie ulepszoną wersję tego skryptu.
mcarans
8

Stworzyłem skrypt w języku Python, który upraszcza cały proces na podstawie odpowiedzi tutaj.

Zapisz poniższy skrypt jako reset_usb.py lub sklonuj to repozytorium .

Stosowanie:

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

Scenariusz:

#!/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)
Marcarans
źródło
to najlepsza odpowiedź na to pytanie.
kapad
4

Ponieważ szczególnym przypadkiem tego pytania jest problem z komunikacją gphoto2 z aparatem na USB, w gphoto2 istnieje możliwość zresetowania połączenia USB:

gphoto2 --reset

Być może ta opcja nie istniała w 2010 r., Kiedy zadano pytanie.

mviereck
źródło
3

Najszybszym sposobem na zresetowanie będzie zresetowanie samego kontrolera USB. Spowoduje to wymuszenie udev do wyrejestrowania urządzenia po rozłączeniu, a rejestracja powróci po włączeniu.

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

Powinno to działać w większości środowisk komputerowych. Jeśli jednak używasz niestandardowego sprzętu, możesz po prostu iterować nazwy urządzeń. Dzięki tej metodzie nie musisz szukać nazwy urządzenia przez lsusb. Możesz również włączyć do skryptu automatycznego.

chandank
źródło
1
Musisz uruchomić te polecenia jako root / sudo, i to nie będzie działać na wszystkich systemach (w niektórych przypadkach będziesz musiał zastąpić ehci_hcdje ehci-pci. Więcej informacji na temat tego rozwiązania (być może skąd pochodzi?): Davidjb.com/blog / 2012/06 /…
Lambart
3

Używam swego rodzaju młota, ponownie ładując moduły. To jest mój skrypt 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

A to jest mój plik usługi systemd /usr/lib/systemd/system/usbreset.service, który uruchamia usb_reset.sh po uruchomieniu mojego menedżera diplay:

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

[Service]
Type=oneshot
ExecStart=/path/to/usb_reset.sh
Ulrich-Lorenz Schlüter
źródło
Użycie opcji listpci mojego skryptu tutaj: askubuntu.com/a/988297/558070 pomoże zidentyfikować moduł USB do ponownego załadowania (np. Xhci_pci, ehci_pci).
mcarans
2
Niestety w moim systemie te moduły jądra nie są oddzielne od jądra, więc to nie zadziała:rmmod: ERROR: Module xhci_pci is builtin.
unfa
3

Stworzyłem skrypt Pythona, który zresetuje określone urządzenie USB na podstawie numeru urządzenia. Możesz znaleźć numer urządzenia z polecenia lsusb.

na przykład:

$ lsusb

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

W tym ciągu 004 jest numerem urządzenia

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()
Raghu
źródło
Podoba mi się to rozwiązanie! Zrobiłem kilka poprawek w skrypcie według własnych upodobań: gist.github.com/willstott101/7a455817ec6f4b8d89571ce72bdfd34a
Czy
2

Oto skrypt, który resetuje tylko pasujący identyfikator produktu / dostawcy.

#!/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
cmcginty
źródło
1
Odkryłem, że twój skrypt jest przydatny. Ale co powinienem zrobić, jeśli $DIRzniknie, a urządzenie nie będzie widoczne?
Eugen Konkov
1

Czy ktoś zamówił młot? Jest to zestawione z różnych innych odpowiedzi tutaj.

#!/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 K Cowan
źródło
Mark, czy odkryłeś, że rozpięcie jest naprawdę konieczne, czy też jest tu po prostu po bezpiecznej stronie?
ndemou
To młot kowalski, prawdopodobnie robi wiele niepotrzebnych rzeczy
Mark K Cowan
@MarkKCowan, jak z niego korzystać? Jakie są wymagane / oczekiwane argumenty polecenia?
not2qubit
1
@ not2qubit: Nie są wymagane argumenty wiersza polecenia. $@W proxy sudo jest tylko siła habbit mając zapobiega błędy gdybym później zdecydować, aby dodać argumenty (i zapomnij zaktualizować proxy sudo).
Mark K Cowan
1
@MarkKCowan Doh! Przepraszam kolego! O tak, przekleństwo! Nie powinienem komentować tej witryny, gdy jestem śpiący. Pozytywne!
not2qubit
1

Czasami chcę wykonać tę operację na określonym urządzeniu, określonym przez VID (identyfikator dostawcy) i PID (identyfikator produktu). Jest to skrypt, który uznałem za przydatny w tym celu, który wykorzystuje zręczną bibliotekę libusb.

Pierwszy bieg:

sudo apt-get install libusb-dev

Następnie resetDeviceConnection tego pliku c ++ powinien wykonać to zadanie polegające na zresetowaniu połączenia urządzenia określonego przez vid i 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;
}

(skradziony z mojego osobistego katalogu TIL: https://github.com/Marviel/TIL/blob/master/unix_tools/Reset_specific_USB_Device.md )

Marviel
źródło
3
Proszę pokazać, jak działa ten skrypt .
George Udosen
Jasne, pozwól mi zaktualizować.
Marviel,
1
@Marviel, wciąż czekamy na aktualizację ...
not2qubit
wymaga głosowania jako bezużyteczne
Eugen Konkov
1

Zrobiłem prosty skrypt bash do zresetowania konkretnego urządzenia 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
Thoht
źródło
0

Być może działa to również w przypadku aparatu:

Po przywróceniu głodującego USB 3.0dysku twardego na 3.4.42Linux (kernel.org) po mojej stronie. dmesgpowiedział, że upłynął limit czasu poleceń po 360s (przepraszam, nie mogę skopiować syslog tutaj, nie podłączonych sieci) i dysk został całkowicie zawieszony. Procesy uzyskiwania dostępu do urządzenia zostały zablokowane w jądrze, niemożliwe do zabicia. NFSzawieszony, ZFSzawieszony, ddzawieszony.

Po wykonaniu tej czynności wszystko znów działało. dmesgpowiedział tylko jeden wiersz o USBznalezionym urządzeniu.

Naprawdę nie mam pojęcia, co szczegółowo robi poniższe. Ale zadziałało.

Poniższy przykładowy wynik pochodzi z Debian Squeeze z 2.6.32-5-686jądrem, więc myślę, że działa dla wersji 2.6 i nowszych:

$ 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

Jeśli to nie zadziała, być może ktoś inny może wymyślić, jak wysłać prawdziwy reset do urządzenia.

Tino
źródło
0

Wypróbuj to, to oprogramowanie odłączyć (Eject).

Czasami nie działa po prostu odznacz urządzenie dla niektórych urządzeń.

Przykład:

Chcę usunąć lub wysunąć mój „Genius NetScroll 120”.

Następnie najpierw sprawdź podłączone urządzenie 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**

Ok, znalazłem moją mysz, ma ona magistralę 002, urządzenie 009, idVendor 0458 i idProduct 003a, więc jest to informacja o urządzeniu referencyjnym na temat myszy.

Jest to ważne, ponieważ numer magistrali jest początkową ścieżką nazwy urządzenia i sprawdzę identyfikator produktu i dostawcę, aby upewnić się, że urządzenie ma zostać usunięte.

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

Zwróć uwagę na foldery, sprawdź początek z folderem nr 2, sprawdzę ten, ponieważ moja magistrala to 002, i jeden po drugim sprawdzam każdy folder zawierający poprawny idVendor i idProduct na temat moich informacji o myszy.

W takim przypadku odzyskam informacje za pomocą tego polecenia:

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

Ok, ścieżka /sys/bus/usb/drivers/usb/2-1.3/ pasuje do mojej myszy informacyjnej! XDDD.

Czas usunąć urządzenie!

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

Podłącz ponownie urządzenie USB i znów działa!

użytkownik242078
źródło
10
Co jeśli nie możesz go ponownie podłączyć? (na przykład jest to wewnętrzny czytnik kart
sd
0

Jeśli znasz nazwę swojego urządzenia, ten skrypt w języku Python będzie działał:

#!/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()
Glina
źródło