Is het mogelijk om de aansluiting van een USB-apparaat te resetten, zonder het apparaat fysiek los te koppelen van de PC?
Om precies te zijn, mijn apparaat is een digitale camera. Ik'gebruik gphoto2
, maar de laatste tijd krijg ik "device read errors", dus ik'zou willen proberen om een software-reset van de verbinding uit te voeren.
Voor zover ik kan zien, worden er geen kernel modules geladen voor de camera. De enige die er mee te maken lijkt te hebben is usbhid
.
Sla het volgende op 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;
}
Voer de volgende commando's uit in terminal:
Compileer het programma:
$ cc usbreset.c -o usbreset
Vraag de Bus en Device ID op van het USB-apparaat dat je wilt resetten:
$ lsusb
Bus 002 Apparaat 003: ID 0fe9:9010 DVICO
Maak ons gecompileerde programma uitvoerbaar:
$ chmod +x usbreset
Voer het programma uit met sudo privilege; maak de nodige vervanging voor <Bus>
en <Device>
ids zoals gevonden door het uitvoeren van het lsusb
commando:
$ sudo ./usbreset /dev/bus/usb/002/003
Bron van bovenstaand programma: http://marc.info/?l=linux-usb&m=121459435621262&w=2
Ik heb mezelf nog niet eerder in uw specifieke omstandigheden bevonden, dus ik'ben niet zeker of het genoeg zal doen, maar de eenvoudigste manier die ik'heb gevonden om een USB-apparaat te resetten is dit commando: (Geen externe apps nodig)
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"
Dat's de eigenlijke die ik gebruik om mijn Kinect te resetten sinds libfreenect geen API schijnt te hebben om het terug in slaap te brengen. Het staat op mijn Gentoo box, maar de kernel zou nieuw genoeg moeten zijn om dezelfde padstructuur voor sysfs te gebruiken.
De jouwe zou duidelijk niet 1-4.6
zijn, maar je kunt ofwel dat apparaatpad uit je kernel log halen (dmesg
) of je kunt iets als lsusb
gebruiken om de leverancier en product ID's te krijgen en dan een snel commando als dit gebruiken om te zien hoe de paden zich verhouden tot verschillende leverancier/product ID paren:
for X in /sys/bus/usb/devices/*; do
echo "$X"
cat "$X/idVendor" 2>/dev/null
cat "$X/idProduct" 2>/dev/null
echo
done
Dit zal alle aangesloten USB1/2/3 poorten[1] resetten:
for i in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*; do
[ -e "$i" ] || continue
echo "${i##*/}" > "${i%/*}/unbind"
echo "${i##*/}" > "${i%/*}/bind"
done
Ik denk dat dit uw probleem zal oplossen. Als u niet alle USB-eindpunten wilt resetten, kunt u het juiste apparaat-ID uit /sys/bus/pci/drivers/ehci_hcd
gebruiken
Opmerkingen:
[1]: de *hci_hcd
kernel drivers besturen meestal de USB poorten. ohci_hcd
en uhci_hcd
zijn voor USB1.1 poorten, ehci_hcd
is voor USB2 poorten en xhci_hcd
is voor USB3 poorten. (zie https://en.wikipedia.org/wiki/Host_controller_interface_(USB,_Firewire))