OpenWrt – Blame information for rev 1
?pathlinks?
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 | } |