Είναι δυνατή η επαναφορά της σύνδεσης μιας συσκευής USB χωρίς φυσική αποσύνδεση/σύνδεση από τον υπολογιστή;
Συγκεκριμένα, η συσκευή μου είναι μια ψηφιακή φωτογραφική μηχανή. Χρησιμοποιώ το gphoto2
, αλλά τελευταία λαμβάνω "σφάλματα ανάγνωσης συσκευής", οπότε θα ήθελα να προσπαθήσω να κάνω μια επαναφορά της σύνδεσης μέσω λογισμικού.
Από ό,τι μπορώ να καταλάβω, δεν φορτώνονται μονάδες πυρήνα για την κάμερα. Το μόνο που φαίνεται να σχετίζεται με το θέμα είναι το usbhid
.
Αποθηκεύστε τα ακόλουθα ως 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;
}
Εκτελέστε τις ακόλουθες εντολές στο τερματικό:
Μεταγλωττίσετε το πρόγραμμα:
$ cc usbreset.c -o usbreset
Λάβετε το Bus και το Device ID της συσκευής USB που θέλετε να επαναφέρετε:
$ lsusb
Δίαυλος 002 Συσκευή 003: ID 0fe9:9010 DVICO
Κάντε το μεταγλωττισμένο πρόγραμμά μας εκτελέσιμο:
$ chmod +x usbreset
Εκτελέστε το πρόγραμμα με το προνόμιο sudo, κάντε την απαραίτητη αντικατάσταση για τα ids <Bus>
και <Device>
όπως βρέθηκαν με την εκτέλεση της εντολής lsusb
:
$ sudo ./usbreset /dev/bus/usb/002/003
Πηγή του παραπάνω προγράμματος: http://marc.info/?l=linux-usb&m=121459435621262&w=2
Δεν έχω βρεθεί στη δική σας περίπτωση, οπότε δεν είμαι σίγουρος αν θα είναι αρκετό, αλλά ο απλούστερος τρόπος που έχω βρει για να επαναφέρετε μια συσκευή 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
για να πάρετε τα IDs του προμηθευτή και του προϊόντος και στη συνέχεια να χρησιμοποιήσετε μια γρήγορη εντολή όπως αυτή για να καταγράψετε πώς τα μονοπάτια σχετίζονται με διαφορετικά ζεύγη IDs προμηθευτή/προϊόντος:
for X in /sys/bus/usb/devices/*; do
echo "$X"
cat "$X/idVendor" 2>/dev/null
cat "$X/idProduct" 2>/dev/null
echo
done
Αυτό θα επαναφέρει όλες τις συνδεδεμένες θύρες 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))