OpenWrt – Blame information for rev 4

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