packages: clean up the package folder
[openwrt/openwrt.git] / package / utils / usbreset / src / usbreset.c
diff --git a/package/utils/usbreset/src/usbreset.c b/package/utils/usbreset/src/usbreset.c
new file mode 100644 (file)
index 0000000..087a14c
--- /dev/null
@@ -0,0 +1,253 @@
+/* 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 <sys/ioctl.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 bool find_usbfs(void)
+{
+       FILE *mtab;
+
+       char buf[1024], type[32];
+       static char path[1024];
+
+       if ((mtab = fopen("/proc/mounts", "r")) != NULL)
+       {
+               while (fgets(buf, sizeof(buf), mtab))
+               {
+                       if (sscanf(buf, "%*s %1023s %31s ", path, type) == 2 &&
+                               !strncmp(type, "usbfs", 5))
+                       {
+                               usbfs = path;
+                               break;
+                       }
+               }
+
+               fclose(mtab);
+       }
+
+       return !!usbfs;
+}
+
+static FILE * open_devlist(void)
+{
+       char buf[1024];
+       snprintf(buf, sizeof(buf), "%s/devices", usbfs);
+       return fopen(buf, "r");
+}
+
+static void close_devlist(FILE *devs)
+{
+       fclose(devs);
+}
+
+static struct usbentry * parse_devlist(FILE *devs)
+{
+       char buf[1024];
+       static struct usbentry dev;
+
+       memset(&dev, 0, sizeof(dev));
+
+       while (fgets(buf, sizeof(buf), devs))
+       {
+               buf[strlen(buf)-1] = 0;
+
+               switch (buf[0])
+               {
+               case 'T':
+                       sscanf(buf, "T: Bus=%d Lev=%*d Prnt=%*d Port=%*d Cnt=%*d Dev#=%d",
+                                  &dev.bus_num, &dev.dev_num);
+                       break;
+
+               case 'P':
+                       sscanf(buf, "P: Vendor=%x ProdID=%x",
+                                  &dev.vendor_id, &dev.product_id);
+                       break;
+
+               case 'S':
+                       if (!strncmp(buf, "S:  Manufacturer=", 17))
+                               snprintf(dev.vendor_name, sizeof(dev.vendor_name),
+                                        "%s", buf+17);
+                       else if (!strncmp(buf, "S:  Product=", 12))
+                               snprintf(dev.product_name, sizeof(dev.product_name),
+                                        "%s", buf+12);
+                       break;
+               }
+
+               if (dev.product_name[0])
+                       return &dev;
+       }
+
+       return NULL;
+}
+
+static void list_devices(void)
+{
+       FILE *devs = open_devlist();
+       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);
+       }
+
+       close_devlist(devs);
+}
+
+struct usbentry * find_device(int *bus, int *dev,
+                              int *vid, int *pid,
+                              const char *product)
+{
+       FILE *devs = open_devlist();
+
+       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;
+               }
+       }
+
+       close_devlist(devs);
+
+       return match;
+}
+
+static void reset_device(struct usbentry *dev)
+{
+       int fd;
+       char path[1024];
+
+       snprintf(path, sizeof(path), "%s/%03d/%03d",
+                        usbfs, 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 (!find_usbfs())
+       {
+               fprintf(stderr, "Unable to find usbfs, is it mounted?\n");
+               return 1;
+       }
+
+       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;
+}