123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /* 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 <stdio.h>
- #include <stdbool.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <string.h>
- #include <ctype.h>
- #include <limits.h>
- #include <dirent.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <linux/usbdevice_fs.h>
- 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;
- }
|