usbreset.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /* usbreset -- send a USB port reset to a USB device */
  2. /*
  3. http://marc.info/?l=linux-usb-users&m=116827193506484&w=2
  4. and needs mounted usbfs filesystem
  5. sudo mount -t usbfs none /proc/bus/usb
  6. There is a way to suspend a USB device. In order to use it,
  7. you must have a kernel with CONFIG_PM_SYSFS_DEPRECATED turned on. To
  8. suspend a device, do (as root):
  9. echo -n 2 >/sys/bus/usb/devices/.../power/state
  10. where the "..." is the ID for your device. To unsuspend, do the same
  11. thing but with a "0" instead of the "2" above.
  12. Note that this mechanism is slated to be removed from the kernel within
  13. the next year. Hopefully some other mechanism will take its place.
  14. > To reset a
  15. > device?
  16. Here's a program to do it. You invoke it as either
  17. usbreset /proc/bus/usb/BBB/DDD
  18. or
  19. usbreset /dev/usbB.D
  20. depending on how your system is set up, where BBB and DDD are the bus and
  21. device address numbers.
  22. Alan Stern
  23. */
  24. #include <stdio.h>
  25. #include <stdbool.h>
  26. #include <unistd.h>
  27. #include <fcntl.h>
  28. #include <errno.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31. #include <limits.h>
  32. #include <dirent.h>
  33. #include <sys/ioctl.h>
  34. #include <sys/types.h>
  35. #include <linux/usbdevice_fs.h>
  36. static char *usbfs = NULL;
  37. struct usbentry {
  38. int bus_num;
  39. int dev_num;
  40. int vendor_id;
  41. int product_id;
  42. char vendor_name[128];
  43. char product_name[128];
  44. };
  45. static char *sysfs_attr(const char *dev, const char *attr)
  46. {
  47. int fd, len = 0;
  48. char path[PATH_MAX];
  49. static char buf[129];
  50. memset(buf, 0, sizeof(buf));
  51. snprintf(path, sizeof(path) - 1, "/sys/bus/usb/devices/%s/%s", dev, attr);
  52. if ((fd = open(path, O_RDONLY)) >= 0)
  53. {
  54. len = read(fd, buf, sizeof(buf) - 1);
  55. close(fd);
  56. }
  57. while (--len > 0 && isspace(buf[len]))
  58. buf[len] = 0;
  59. return (len >= 0) ? buf : NULL;
  60. }
  61. static struct usbentry * parse_devlist(DIR *d)
  62. {
  63. char *attr;
  64. struct dirent *e;
  65. static struct usbentry dev;
  66. do {
  67. e = readdir(d);
  68. if (!e)
  69. return NULL;
  70. }
  71. while(!isdigit(e->d_name[0]) || strchr(e->d_name, ':'));
  72. memset(&dev, 0, sizeof(dev));
  73. if ((attr = sysfs_attr(e->d_name, "busnum")) != NULL)
  74. dev.bus_num = strtoul(attr, NULL, 10);
  75. if ((attr = sysfs_attr(e->d_name, "devnum")) != NULL)
  76. dev.dev_num = strtoul(attr, NULL, 10);
  77. if ((attr = sysfs_attr(e->d_name, "idVendor")) != NULL)
  78. dev.vendor_id = strtoul(attr, NULL, 16);
  79. if ((attr = sysfs_attr(e->d_name, "idProduct")) != NULL)
  80. dev.product_id = strtoul(attr, NULL, 16);
  81. if ((attr = sysfs_attr(e->d_name, "manufacturer")) != NULL)
  82. strcpy(dev.vendor_name, attr);
  83. if ((attr = sysfs_attr(e->d_name, "product")) != NULL)
  84. strcpy(dev.product_name, attr);
  85. if (dev.bus_num && dev.dev_num && dev.vendor_id && dev.product_id)
  86. return &dev;
  87. return NULL;
  88. }
  89. static void list_devices(void)
  90. {
  91. DIR *devs = opendir("/sys/bus/usb/devices");
  92. struct usbentry *dev;
  93. if (!devs)
  94. return;
  95. while ((dev = parse_devlist(devs)) != NULL)
  96. {
  97. printf(" Number %03d/%03d ID %04x:%04x %s\n",
  98. dev->bus_num, dev->dev_num,
  99. dev->vendor_id, dev->product_id,
  100. dev->product_name);
  101. }
  102. closedir(devs);
  103. }
  104. struct usbentry * find_device(int *bus, int *dev,
  105. int *vid, int *pid,
  106. const char *product)
  107. {
  108. DIR *devs = opendir("/sys/bus/usb/devices");
  109. struct usbentry *e, *match = NULL;
  110. if (!devs)
  111. return NULL;
  112. while ((e = parse_devlist(devs)) != NULL)
  113. {
  114. if ((bus && (e->bus_num == *bus) && (e->dev_num == *dev)) ||
  115. (vid && (e->vendor_id == *vid) && (e->product_id == *pid)) ||
  116. (product && !strcasecmp(e->product_name, product)))
  117. {
  118. match = e;
  119. break;
  120. }
  121. }
  122. closedir(devs);
  123. return match;
  124. }
  125. static void reset_device(struct usbentry *dev)
  126. {
  127. int fd;
  128. char path[PATH_MAX];
  129. snprintf(path, sizeof(path) - 1, "/dev/bus/usb/%03d/%03d",
  130. dev->bus_num, dev->dev_num);
  131. printf("Resetting %s ... ", dev->product_name);
  132. if ((fd = open(path, O_WRONLY)) > -1)
  133. {
  134. if (ioctl(fd, USBDEVFS_RESET, 0) < 0)
  135. printf("failed [%s]\n", strerror(errno));
  136. else
  137. printf("ok\n");
  138. close(fd);
  139. }
  140. else
  141. {
  142. printf("can't open [%s]\n", strerror(errno));
  143. }
  144. }
  145. int main(int argc, char **argv)
  146. {
  147. int id1, id2;
  148. struct usbentry *dev;
  149. if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
  150. {
  151. dev = find_device(&id1, &id2, NULL, NULL, NULL);
  152. }
  153. else if ((argc == 2) && (sscanf(argv[1], "%4x:%4x", &id1, &id2) == 2))
  154. {
  155. dev = find_device(NULL, NULL, &id1, &id2, NULL);
  156. }
  157. else if ((argc == 2) && strlen(argv[1]) < 128)
  158. {
  159. dev = find_device(NULL, NULL, NULL, NULL, argv[1]);
  160. }
  161. else
  162. {
  163. printf("Usage:\n"
  164. " usbreset PPPP:VVVV - reset by product and vendor id\n"
  165. " usbreset BBB/DDD - reset by bus and device number\n"
  166. " usbreset \"Product\" - reset by product name\n\n"
  167. "Devices:\n");
  168. list_devices();
  169. return 1;
  170. }
  171. if (!dev)
  172. {
  173. fprintf(stderr, "No such device found\n");
  174. return 1;
  175. }
  176. reset_device(dev);
  177. return 0;
  178. }