"Fossies" - the Fresh Open Source Software Archive

Member "usbutils-014/usbreset.c" (22 Feb 2021, 4089 Bytes) of package /linux/misc/usbutils-014.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "usbreset.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 013_vs_014.

    1 // SPDX-License-Identifier: GPL-2.0-only
    2 /* usbreset -- send a USB port reset to a USB device */
    3 /* Copyright (c) 2009-2016 Alan Stern */
    4 /* To build:  gcc -o usbreset usbreset.c */
    5 
    6 #include <stdint.h>
    7 #include <stdio.h>
    8 #include <stdbool.h>
    9 #include <stdlib.h>
   10 #include <unistd.h>
   11 #include <fcntl.h>
   12 #include <errno.h>
   13 #include <string.h>
   14 #include <ctype.h>
   15 #include <limits.h>
   16 #include <dirent.h>
   17 #include <sys/ioctl.h>
   18 
   19 #include <linux/usbdevice_fs.h>
   20 
   21 
   22 /* static char *usbfs = NULL; */
   23 
   24 struct usbentry {
   25     int bus_num;
   26     int dev_num;
   27     int vendor_id;
   28     int product_id;
   29     char vendor_name[128];
   30     char product_name[128];
   31 };
   32 
   33 static char *sysfs_attr(const char *dev, const char *attr)
   34 {
   35     int fd, len = 0;
   36     char path[PATH_MAX];
   37     static char buf[129];
   38 
   39     memset(buf, 0, sizeof(buf));
   40     snprintf(path, sizeof(path) - 1, "/sys/bus/usb/devices/%s/%s", dev, attr);
   41 
   42     fd = open(path, O_RDONLY);
   43     if (fd >= 0) {
   44         len = read(fd, buf, sizeof(buf) - 1);
   45         close(fd);
   46     }
   47 
   48     while (--len > 0 && isspace(buf[len]))
   49         buf[len] = 0;
   50 
   51     return (len >= 0) ? buf : NULL;
   52 }
   53 
   54 static struct usbentry *parse_devlist(DIR *d)
   55 {
   56     char *attr;
   57     struct dirent *e;
   58     static struct usbentry dev;
   59 
   60     do {
   61         e = readdir(d);
   62 
   63         if (!e)
   64             return NULL;
   65     } while (!isdigit(e->d_name[0]) || strchr(e->d_name, ':'));
   66 
   67     memset(&dev, 0, sizeof(dev));
   68 
   69     attr = sysfs_attr(e->d_name, "busnum");
   70     if (attr)
   71         dev.bus_num = strtoul(attr, NULL, 10);
   72 
   73     attr = sysfs_attr(e->d_name, "devnum");
   74     if (attr)
   75         dev.dev_num = strtoul(attr, NULL, 10);
   76 
   77     attr = sysfs_attr(e->d_name, "idVendor");
   78     if (attr)
   79         dev.vendor_id = strtoul(attr, NULL, 16);
   80 
   81     attr = sysfs_attr(e->d_name, "idProduct");
   82     if (attr)
   83         dev.product_id = strtoul(attr, NULL, 16);
   84 
   85     attr = sysfs_attr(e->d_name, "manufacturer");
   86     if (attr)
   87         strcpy(dev.vendor_name, attr);
   88 
   89     attr = sysfs_attr(e->d_name, "product");
   90     if (attr)
   91         strcpy(dev.product_name, attr);
   92 
   93     if (dev.bus_num && dev.dev_num && dev.vendor_id && dev.product_id)
   94         return &dev;
   95 
   96     return NULL;
   97 }
   98 
   99 static void list_devices(void)
  100 {
  101     DIR *devs = opendir("/sys/bus/usb/devices");
  102     struct usbentry *dev;
  103 
  104     if (!devs)
  105         return;
  106 
  107     while ((dev = parse_devlist(devs)) != NULL)
  108         printf("  Number %03d/%03d  ID %04x:%04x  %s\n",
  109                dev->bus_num, dev->dev_num,
  110                dev->vendor_id, dev->product_id,
  111                dev->product_name);
  112 
  113     closedir(devs);
  114 }
  115 
  116 static struct usbentry *find_device(int *bus, int *dev, int *vid, int *pid,
  117                     const char *product)
  118 {
  119     DIR *devs = opendir("/sys/bus/usb/devices");
  120 
  121     struct usbentry *e, *match = NULL;
  122 
  123     if (!devs)
  124         return NULL;
  125 
  126     while ((e = parse_devlist(devs)) != NULL)
  127         if ((bus && (e->bus_num == *bus) && (e->dev_num == *dev)) ||
  128             (vid && (e->vendor_id == *vid) && (e->product_id == *pid)) ||
  129             (product && !strcasecmp(e->product_name, product))) {
  130             match = e;
  131             break;
  132         }
  133 
  134     closedir(devs);
  135 
  136     return match;
  137 }
  138 
  139 static void reset_device(struct usbentry *dev)
  140 {
  141     int fd;
  142     char path[PATH_MAX];
  143 
  144     snprintf(path, sizeof(path) - 1, "/dev/bus/usb/%03d/%03d",
  145         dev->bus_num, dev->dev_num);
  146 
  147     printf("Resetting %s ... ", dev->product_name);
  148 
  149     fd = open(path, O_WRONLY);
  150     if (fd  > -1) {
  151         if (ioctl(fd, USBDEVFS_RESET, 0) < 0)
  152             printf("failed [%s]\n", strerror(errno));
  153         else
  154             printf("ok\n");
  155 
  156         close(fd);
  157     } else {
  158         printf("can't open [%s]\n", strerror(errno));
  159     }
  160 }
  161 
  162 
  163 int main(int argc, char **argv)
  164 {
  165     int id1, id2;
  166     struct usbentry *dev;
  167 
  168     if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
  169         dev = find_device(&id1, &id2, NULL, NULL, NULL);
  170     else if ((argc == 2) && (sscanf(argv[1], "%4x:%4x", &id1, &id2) == 2))
  171         dev = find_device(NULL, NULL, &id1, &id2, NULL);
  172     else if ((argc == 2) && strlen(argv[1]) < 128)
  173         dev = find_device(NULL, NULL, NULL, NULL, argv[1]);
  174     else {
  175         printf("Usage:\n"
  176                "  usbreset PPPP:VVVV - reset by product and vendor id\n"
  177                "  usbreset BBB/DDD   - reset by bus and device number\n"
  178                "  usbreset \"Product\" - reset by product name\n\n"
  179                "Devices:\n");
  180         list_devices();
  181         return 1;
  182     }
  183 
  184     if (!dev) {
  185         fprintf(stderr, "No such device found\n");
  186         return 1;
  187     }
  188 
  189     reset_device(dev);
  190     return 0;
  191 }