/* usbreset -- send a USB port reset to a USB device */ /* http://marc.info/?l=linux-usb-users&m=116827193506484&w=2 and needs mounted usbfs filesystem sudo mount -t usbfs none /proc/bus/usb There is a way to suspend a USB device. In order to use it, you must have a kernel with CONFIG_PM_SYSFS_DEPRECATED turned on. To suspend a device, do (as root): echo -n 2 >/sys/bus/usb/devices/.../power/state where the "..." is the ID for your device. To unsuspend, do the same thing but with a "0" instead of the "2" above. Note that this mechanism is slated to be removed from the kernel within the next year. Hopefully some other mechanism will take its place. > To reset a > device? Here's a program to do it. You invoke it as either usbreset /proc/bus/usb/BBB/DDD or usbreset /dev/usbB.D depending on how your system is set up, where BBB and DDD are the bus and device address numbers. Alan Stern */ #include #include #include #include #include #include #include #include #include #include #include #include static char *usbfs = NULL; struct usbentry { int bus_num; int dev_num; int vendor_id; int product_id; char vendor_name[128]; char product_name[128]; }; static char *sysfs_attr(const char *dev, const char *attr) { int fd, len = 0; char path[PATH_MAX]; static char buf[129]; memset(buf, 0, sizeof(buf)); snprintf(path, sizeof(path) - 1, "/sys/bus/usb/devices/%s/%s", dev, attr); if ((fd = open(path, O_RDONLY)) >= 0) { len = read(fd, buf, sizeof(buf) - 1); close(fd); } while (--len > 0 && isspace(buf[len])) buf[len] = 0; return (len >= 0) ? buf : NULL; } static struct usbentry * parse_devlist(DIR *d) { char *attr; struct dirent *e; static struct usbentry dev; do { e = readdir(d); if (!e) return NULL; } while(!isdigit(e->d_name[0]) || strchr(e->d_name, ':')); memset(&dev, 0, sizeof(dev)); if ((attr = sysfs_attr(e->d_name, "busnum")) != NULL) dev.bus_num = strtoul(attr, NULL, 10); if ((attr = sysfs_attr(e->d_name, "devnum")) != NULL) dev.dev_num = strtoul(attr, NULL, 10); if ((attr = sysfs_attr(e->d_name, "idVendor")) != NULL) dev.vendor_id = strtoul(attr, NULL, 16); if ((attr = sysfs_attr(e->d_name, "idProduct")) != NULL) dev.product_id = strtoul(attr, NULL, 16); if ((attr = sysfs_attr(e->d_name, "manufacturer")) != NULL) strcpy(dev.vendor_name, attr); if ((attr = sysfs_attr(e->d_name, "product")) != NULL) strcpy(dev.product_name, attr); if (dev.bus_num && dev.dev_num && dev.vendor_id && dev.product_id) return &dev; return NULL; } static void list_devices(void) { DIR *devs = opendir("/sys/bus/usb/devices"); struct usbentry *dev; if (!devs) return; while ((dev = parse_devlist(devs)) != NULL) { printf(" Number %03d/%03d ID %04x:%04x %s\n", dev->bus_num, dev->dev_num, dev->vendor_id, dev->product_id, dev->product_name); } closedir(devs); } struct usbentry * find_device(int *bus, int *dev, int *vid, int *pid, const char *product) { DIR *devs = opendir("/sys/bus/usb/devices"); struct usbentry *e, *match = NULL; if (!devs) return NULL; while ((e = parse_devlist(devs)) != NULL) { if ((bus && (e->bus_num == *bus) && (e->dev_num == *dev)) || (vid && (e->vendor_id == *vid) && (e->product_id == *pid)) || (product && !strcasecmp(e->product_name, product))) { match = e; break; } } closedir(devs); return match; } static void reset_device(struct usbentry *dev) { int fd; char path[PATH_MAX]; snprintf(path, sizeof(path) - 1, "/dev/bus/usb/%03d/%03d", dev->bus_num, dev->dev_num); printf("Resetting %s ... ", dev->product_name); if ((fd = open(path, O_WRONLY)) > -1) { if (ioctl(fd, USBDEVFS_RESET, 0) < 0) printf("failed [%s]\n", strerror(errno)); else printf("ok\n"); close(fd); } else { printf("can't open [%s]\n", strerror(errno)); } } int main(int argc, char **argv) { int id1, id2; struct usbentry *dev; if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2)) { dev = find_device(&id1, &id2, NULL, NULL, NULL); } else if ((argc == 2) && (sscanf(argv[1], "%4x:%4x", &id1, &id2) == 2)) { dev = find_device(NULL, NULL, &id1, &id2, NULL); } else if ((argc == 2) && strlen(argv[1]) < 128) { dev = find_device(NULL, NULL, NULL, NULL, argv[1]); } else { printf("Usage:\n" " usbreset PPPP:VVVV - reset by product and vendor id\n" " usbreset BBB/DDD - reset by bus and device number\n" " usbreset \"Product\" - reset by product name\n\n" "Devices:\n"); list_devices(); return 1; } if (!dev) { fprintf(stderr, "No such device found\n"); return 1; } reset_device(dev); return 0; }