Root/package/usbreset/src/usbreset.c

1/* usbreset -- send a USB port reset to a USB device */
2
3/*
4
5http://marc.info/?l=linux-usb-users&m=116827193506484&w=2
6
7and needs mounted usbfs filesystem
8
9    sudo mount -t usbfs none /proc/bus/usb
10
11There is a way to suspend a USB device. In order to use it,
12you must have a kernel with CONFIG_PM_SYSFS_DEPRECATED turned on. To
13suspend a device, do (as root):
14
15    echo -n 2 >/sys/bus/usb/devices/.../power/state
16
17where the "..." is the ID for your device. To unsuspend, do the same
18thing but with a "0" instead of the "2" above.
19
20Note that this mechanism is slated to be removed from the kernel within
21the next year. Hopefully some other mechanism will take its place.
22
23> To reset a
24> device?
25
26Here's a program to do it. You invoke it as either
27
28    usbreset /proc/bus/usb/BBB/DDD
29or
30    usbreset /dev/usbB.D
31
32depending on how your system is set up, where BBB and DDD are the bus and
33device address numbers.
34
35Alan Stern
36
37*/
38
39#include <stdio.h>
40#include <stdbool.h>
41#include <unistd.h>
42#include <fcntl.h>
43#include <errno.h>
44#include <string.h>
45#include <sys/ioctl.h>
46
47#include <linux/usbdevice_fs.h>
48
49
50static char *usbfs = NULL;
51
52struct usbentry {
53    int bus_num;
54    int dev_num;
55    int vendor_id;
56    int product_id;
57    char vendor_name[128];
58    char product_name[128];
59};
60
61
62static bool find_usbfs(void)
63{
64    FILE *mtab;
65
66    char buf[1024], type[32];
67    static char path[1024];
68
69    if ((mtab = fopen("/proc/mounts", "r")) != NULL)
70    {
71        while (fgets(buf, sizeof(buf), mtab))
72        {
73            if (sscanf(buf, "%*s %1023s %31s ", path, type) == 2 &&
74                !strncmp(type, "usbfs", 5))
75            {
76                usbfs = path;
77                break;
78            }
79        }
80
81        fclose(mtab);
82    }
83
84    return !!usbfs;
85}
86
87static FILE * open_devlist(void)
88{
89    char buf[1024];
90    snprintf(buf, sizeof(buf), "%s/devices", usbfs);
91    return fopen(buf, "r");
92}
93
94static void close_devlist(FILE *devs)
95{
96    fclose(devs);
97}
98
99static struct usbentry * parse_devlist(FILE *devs)
100{
101    char buf[1024];
102    static struct usbentry dev;
103
104    memset(&dev, 0, sizeof(dev));
105
106    while (fgets(buf, sizeof(buf), devs))
107    {
108        buf[strlen(buf)-1] = 0;
109
110        switch (buf[0])
111        {
112        case 'T':
113            sscanf(buf, "T: Bus=%d Lev=%*d Prnt=%*d Port=%*d Cnt=%*d Dev#=%d",
114                   &dev.bus_num, &dev.dev_num);
115            break;
116
117        case 'P':
118            sscanf(buf, "P: Vendor=%x ProdID=%x",
119                   &dev.vendor_id, &dev.product_id);
120            break;
121
122        case 'S':
123            if (!strncmp(buf, "S: Manufacturer=", 17))
124                snprintf(dev.vendor_name, sizeof(dev.vendor_name),
125                         "%s", buf+17);
126            else if (!strncmp(buf, "S: Product=", 12))
127                snprintf(dev.product_name, sizeof(dev.product_name),
128                         "%s", buf+12);
129            break;
130        }
131
132        if (dev.product_name[0])
133            return &dev;
134    }
135
136    return NULL;
137}
138
139static void list_devices(void)
140{
141    FILE *devs = open_devlist();
142    struct usbentry *dev;
143
144    if (!devs)
145        return;
146
147    while ((dev = parse_devlist(devs)) != NULL)
148    {
149        printf(" Number %03d/%03d ID %04x:%04x %s\n",
150               dev->bus_num, dev->dev_num,
151               dev->vendor_id, dev->product_id,
152               dev->product_name);
153    }
154
155    close_devlist(devs);
156}
157
158struct usbentry * find_device(int *bus, int *dev,
159                              int *vid, int *pid,
160                              const char *product)
161{
162    FILE *devs = open_devlist();
163
164    struct usbentry *e, *match = NULL;
165
166    if (!devs)
167        return NULL;
168
169    while ((e = parse_devlist(devs)) != NULL)
170    {
171        if ((bus && (e->bus_num == *bus) && (e->dev_num == *dev)) ||
172            (vid && (e->vendor_id == *vid) && (e->product_id == *pid)) ||
173            (product && !strcasecmp(e->product_name, product)))
174        {
175            match = e;
176            break;
177        }
178    }
179
180    close_devlist(devs);
181
182    return match;
183}
184
185static void reset_device(struct usbentry *dev)
186{
187    int fd;
188    char path[1024];
189
190    snprintf(path, sizeof(path), "%s/%03d/%03d",
191             usbfs, dev->bus_num, dev->dev_num);
192
193    printf("Resetting %s ... ", dev->product_name);
194
195    if ((fd = open(path, O_WRONLY)) > -1)
196    {
197        if (ioctl(fd, USBDEVFS_RESET, 0) < 0)
198            printf("failed [%s]\n", strerror(errno));
199        else
200            printf("ok\n");
201
202        close(fd);
203    }
204    else
205    {
206        printf("can't open [%s]\n", strerror(errno));
207    }
208}
209
210
211int main(int argc, char **argv)
212{
213    int id1, id2;
214    struct usbentry *dev;
215
216    if (!find_usbfs())
217    {
218        fprintf(stderr, "Unable to find usbfs, is it mounted?\n");
219        return 1;
220    }
221
222    if ((argc == 2) && (sscanf(argv[1], "%3d/%3d", &id1, &id2) == 2))
223    {
224        dev = find_device(&id1, &id2, NULL, NULL, NULL);
225    }
226    else if ((argc == 2) && (sscanf(argv[1], "%4x:%4x", &id1, &id2) == 2))
227    {
228        dev = find_device(NULL, NULL, &id1, &id2, NULL);
229    }
230    else if ((argc == 2) && strlen(argv[1]) < 128)
231    {
232        dev = find_device(NULL, NULL, NULL, NULL, argv[1]);
233    }
234    else
235    {
236        printf("Usage:\n"
237               " usbreset PPPP:VVVV - reset by product and vendor id\n"
238               " usbreset BBB/DDD - reset by bus and device number\n"
239               " usbreset \"Product\" - reset by product name\n\n"
240               "Devices:\n");
241        list_devices();
242        return 1;
243    }
244
245    if (!dev)
246    {
247        fprintf(stderr, "No such device found\n");
248        return 1;
249    }
250
251    reset_device(dev);
252    return 0;
253}
254

Archive Download this file



interactive