packages: clean up the package folder
[openwrt/staging/yousong.git] / package / utils / usbreset / src / usbreset.c
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 <sys/ioctl.h>
46
47 #include <linux/usbdevice_fs.h>
48
49
50 static char *usbfs = NULL;
51
52 struct 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
62 static 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
87 static FILE * open_devlist(void)
88 {
89 char buf[1024];
90 snprintf(buf, sizeof(buf), "%s/devices", usbfs);
91 return fopen(buf, "r");
92 }
93
94 static void close_devlist(FILE *devs)
95 {
96 fclose(devs);
97 }
98
99 static 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
139 static 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
158 struct 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
185 static 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
211 int 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 }