Frage Wie setzt du ein USB-Gerät über die Befehlszeile zurück?


Ist es möglich, die Verbindung eines USB-Geräts zurückzusetzen, ohne den PC physisch zu trennen / zu verbinden?

Insbesondere ist mein Gerät eine Digitalkamera. Ich benutze gphoto2, aber in letzter Zeit bekomme ich "Gerät lesen Fehler", also möchte ich versuchen, eine Software-Reset der Verbindung zu tun.

Soweit ich das beurteilen kann, werden keine Kernelmodule für die Kamera geladen. Der einzige, der verwandt ist, ist usbhid.


141
2017-08-01 19:46


Ursprung


Welche Version von Ubuntu benutzt du? - User
Ich habe versucht beide Lösungen von Li Lo und ssokolow, alles, was ich bekomme ist verweigert, nomatter, wenn ich den usbreset-Code oder die Befehlszeile "echo 0> ..." Ich benutze Sudo, auch meine USB-Geräte sind im Besitz von root, aber ich kann sie ohne Administratorrechte (Kameras ..) verwenden
Wenn Sie Lesefehler bekommen, könnten Sie einige Daten beschädigt haben. Wenn Ihre Kamera eine externe Speicherkarte (z. B. MicroSD) verwendet, sollten Sie sie mit dem Computer verbinden und fsck ausführen. - TSJNachos117


Antworten:


Speichern Sie Folgendes als 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;
}

Führen Sie die folgenden Befehle im Terminal aus:

  1. Kompiliere das Programm:

    $ cc usbreset.c -o usbreset
    
  2. Ermitteln Sie die Bus- und Geräte-ID des USB-Geräts, das Sie zurücksetzen möchten:

    $ lsusb  
    Bus 002 Device 003: ID 0fe9:9010 DVICO  
    
  3. Machen Sie unser kompiliertes Programm ausführbar:

    $ chmod +x usbreset
    
  4. Führe das Programm mit der Berechtigung sudo aus; Machen Sie die notwendige Ersetzung für <Bus> und <Device> IDs, die beim Ausführen von lsusb Befehl:

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

Quelle des obigen Programms: http://marc.info/?l=linux-usb&m=121459435621262&w=2


104
2017-08-02 02:27



Ich habe Fehler wie folgt: ./usbreset: Befehl nicht gefunden Dan 11.04 Natty
Ich danke dir sehr! Dies wird mir helfen, mein sterbendes Intellimouse um ein Vielfaches zu bereichern. - Randall Ma
Dies funktioniert mit Ubuntu 13.10. Die Geräte-ID kann variieren. Um es für die Maus zu bekommen, habe ich obigen Code in wenigen Shell-Befehlen eingepackt 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
Wenn jemand, der dies liest, einen (usb) Mouse Freeze hat, nachdem er sich bei Ubuntu 16.04 angemeldet hat (mit dmesg gefüllt mit "input irq status -75"), kann ich bestätigen, dass dies die einzige Lösung ist, die für mich funktioniert hat. Vielen Dank - Agustin Baez
@ Aquarius, bekomme ich auch den gleichen Fehler "Fehler in ioctl: Ist ein Verzeichnis". Ist es gelöst? - ransh


Ich habe mich zuvor noch nicht in Ihren spezifischen Umständen wiedergefunden, also bin ich mir nicht sicher, ob es genug tun wird, aber die einfachste Möglichkeit, ein USB-Gerät zurückzusetzen, ist dieser Befehl: (Keine externen Apps erforderlich)

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"

Das ist die tatsächliche, die ich benutze, um meine Kinect zurückzusetzen, da libfreenect keine API zu haben scheint, um es wieder einzuschalten. Es ist in meiner Gentoo-Box, aber der Kernel sollte neu genug sein, um die gleiche Pfadstruktur für sysfs zu verwenden.

Deines würde natürlich nicht sein 1-4.6 aber Sie können diesen Gerätepfad entweder aus Ihrem Kernel-Protokoll (dmesg) oder Sie können etwas wie lsusb um die Hersteller- und Produkt-IDs zu erhalten und dann einen schnellen Befehl wie folgt zu verwenden, um aufzulisten, wie sich die Pfade auf verschiedene Anbieter- / Produkt-ID-Paare beziehen:

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

47
2017-09-13 06:56



sh: 1: kann nicht erstellt werden /sys/bus/usb/devices/1-3.1:1.0/authorized: Verzeichnis nicht vorhanden - Nicolas Marchildon
Offenbar haben sie das Layout des usbfs-Dateisystems geändert. Ich werde versuchen, herauszufinden, was die neue Art, Dinge zu tun, auf Ubuntu ist, wenn ich nicht so müde bin. - ssokolow
Danke super funktioniert! Vielleicht solltest du auch erwähnen, ein echo 1 > /sys/bus/usb/devices/whatever/authorizedin einem Skript, um das Gerät wieder zu aktivieren, sobald es deaktiviert wurde. Ich habe es sowohl mit meiner Maus als auch mit meiner USB-Tastatur gemacht und ich endete mit einem komplett tauben System :) - Avio
Das letzte Mal, als ich es benutzt habe, würde etwas im System es ein oder zwei Sekunden später auf 1 zurücksetzen, ohne dass ich es manuell machen müsste. - ssokolow
Eine Notiz für jeden, der versucht, auf die | sudo tee ... Annäherung an Privilegierte /sys schreibt: Das bricht schlecht, wenn Sie Ihre sudo-Anmeldeinformationen nicht bereits zwischengespeichert haben. sudo sh -c "..." funktioniert wie erwartet, wenn sudo nach einem Passwort fragen muss. - ssokolow


Dadurch werden alle an USB1 / 2/3 angeschlossenen Ports [1] zurückgesetzt:

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

Ich glaube, das wird dein Problem lösen. Wenn Sie nicht alle USB-Endpunkte zurücksetzen möchten, können Sie die entsprechende Geräte-ID verwenden /sys/bus/pci/drivers/ehci_hcd


Anmerkungen: [1]: die *hci_hcd Kernel-Treiber steuern normalerweise die USB-Ports. ohci_hcd und uhci_hcd sind für USB1.1 Ports, ehci_hcd ist für USB2 Anschlüsse und xhci_hcd ist für USB3-Ports. (sehen https://en.wikipedia.org/wiki/Host_controller_interface_(USB,_Firewire))


37
2018-05-04 11:02



Glaubst du, es könnte funktionieren? Wecken Sie einen USB-Speicher? - Aquarius Power
Obwohl ich die folgende Nachricht erhalten habe: ls: cannot access /sys/bus/pci/drivers/ehci_hcd/: No such file or directory Dies hat das Problem gelöst, die Maus hat sofort mit der Arbeit begonnen. +1 - Attila Fulop
Ist es möglich, eine Überprüfung hinzuzufügen, um installierte USB-Massenspeichergeräte zu überspringen? - eadmaster
@Otheus OHCI und UHCI sind die USB 1.1-Host-Standards, EHCI ist der USB 2.0-Host-Standard und XHCI ist der USB 3.0-Host-Standard. - ssokolow
Dies ist eine schöne Lösung. Bei einigen späteren Kernel und anderen * nix-Distributionen werden Sie jedoch feststellen, dass Sie diese ersetzen müssen *hci_hcd mit *hci-pci, da der hci_hcd-Treiber bereits in den Kernel kompiliert ist. - not2qubit


Ich musste dies in einem Python-Skript automatisieren, also adaptierte ich LiLos extrem hilfreiche Antwort auf Folgendes:

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

In meinem Fall war es der cp210x-Treiber (was ich sagen konnte) lsmod | grep usbserial), sodass Sie das obige Snippet als reset_usb.py speichern und dann Folgendes tun können:

sudo python reset_usb.py cp210x

Dies kann auch hilfreich sein, wenn Sie noch kein C-Compiler-Setup auf Ihrem System installiert haben, aber Sie haben Python.


9
2018-03-02 20:38



arbeitete für mich auf einer Himbeere - webo80
Noch ein paar Worte zu Ihrer Lösung. Zum Beispiel etwas über die Konstante USBDEVFS_RESET. Ist es für alle Systeme immer gleich? - not2qubit
@ Not2qubit USBDEVFS_RESET ist für alle Systeme gleich. Für MIPS ist es 536892692. - yegorich
Neuere Versionen von lsusb scheinen das zu brauchen -t Argument (Baummodus), um die Treiberinformationen anzuzeigen, die dieses Skript erwartet, aber das Skript benötigt dann einige Aktualisierungen, um die verschiedenen Ausgangszeilen zu analysieren, die dieses generiert - Cheetah
Siehe meine Antwort hier askubuntu.com/a/988297/558070 für eine viel verbesserte Version dieses Skripts. - mcarans


Ich benutze eine Art Vorschlaghammer, indem ich die Module neu lade. Das ist mein Skript 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

Und das ist meine Systemd-Servicedatei /usr/lib/systemd/system/usbreset.service, die usb_reset.sh ausführt, nachdem mein diplay-Manager gestartet wurde:

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

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

4
2018-01-09 10:18



Benutze die listpci Option meines Skripts hier: askubuntu.com/a/988297/558070 hilft zu identifizieren, welches USB-Modul neu geladen werden soll (zB xhci_pci, ehci_pci). - mcarans
Leider sind diese Kernelmodule auf meinem System nicht vom Kernel getrennt, so dass dies nicht funktioniert: rmmod: ERROR: Module xhci_pci is builtin. - unfa


Der schnellste Weg zum Zurücksetzen besteht darin, den USB-Controller selbst zurückzusetzen. Wenn Sie dies tun, erzwingt udev die Aufhebung der Registrierung des Geräts beim Trennen der Verbindung, und die Registrierung wird wiederhergestellt, sobald Sie es aktiviert haben.

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

Dies sollte für die meisten PC-Umgebungen funktionieren. Wenn Sie jedoch eine benutzerdefinierte Hardware verwenden, können Sie einfach die Gerätenamen durchlaufen. Mit dieser Methode müssen Sie den Gerätenamen nicht nach lsusb ermitteln. Sie können auch in ein automatisiertes Skript integrieren.


3
2017-11-24 19:34



Sie müssen diese Befehle als root / sudo ausführen, und es wird nicht auf allen Systemen funktionieren (bei einigen müssen Sie ersetzen ehci_hcd mit ehci-pci. Weitere Informationen zu dieser Lösung (vielleicht woher kommt sie?): davidjb.com/blog/2012/06/... - Lambart


Da der Spezialfall der Frage ein Kommunikationsproblem von gphoto2 mit einer Kamera auf USB ist, gibt es in gphoto2 eine Option zum Zurücksetzen der USB-Verbindung:

gphoto2 --reset

Vielleicht gab es diese Option 2010 nicht, als die Frage gestellt wurde.


3
2017-08-31 13:19





Ich habe ein Python-Skript erstellt, das ein bestimmtes USB-Gerät basierend auf der Gerätenummer zurücksetzt. Sie können die Gerätenummer aus dem Befehl lsusb herausfinden.

beispielsweise:

$ lsusb

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

In diesem String ist 004 die Gerätenummer

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

2
2017-09-07 11:42





Hier ist ein Skript, das nur eine übereinstimmende Produkt- / Lieferanten-ID zurücksetzt.

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

2
2018-04-30 03:50



Ich fand dein Skript nützlich. Aber was soll ich tun, wenn die $DIR verschwindet und Gerät ist nicht sichtbar? - Eugen Konkov


Ich habe ein Python-Skript erstellt, das den gesamten Prozess basierend auf Antworten hier vereinfacht.

Speichern Sie das folgende Skript als reset_usb.py oder klonen Sie dieses Repo: https://github.com/mcarans/resetusb/.

Verwendung:

python reset_usb.py help: Zeigt diese Hilfe an

sudo python reset_usb.py Liste: Listet alle USB-Geräte auf

sudo python reset_usb.py pfad / dev / bus / usb / XXX / YYY: USB-Gerät mit dem Pfad / dev / bus / usb / XXX / YYY zurücksetzen

sudo python reset_usb.py Suche "Suchbegriffe": Suchen Sie nach USB-Gerät mit den Suchbegriffen innerhalb der Such-String von der Liste zurückgegeben und passendes Gerät zurücksetzen

sudo python reset_usb.py listpci: Listet alle PCI-USB-Geräte auf

sudo python reset_usb.py pathpci /sys/bus/pci/drivers/.../XXXX:XX:XX.X: Setzen Sie das PCI-USB-Gerät über den Pfad /sys/bus/pci/drivers/.../XXXX:XX zurück: XX.X

sudo python reset_usb.py searchpci "Suchbegriffe": Suchen Sie nach PCI-USB-Geräten mit den Suchbegriffen innerhalb der von listpci zurückgegebenen Suchzeichenfolge und setzen Sie das passende Gerät zurück

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

2
2017-12-21 10:15