blob: 3604a42ade6f814b910727552a8bdaa42aba4ce1 [file] [log] [blame]
Mike Lockwood30ff2c72010-05-09 16:23:47 -04001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <string.h>
21
22#include <sys/ioctl.h>
23#include <sys/types.h>
24#include <sys/time.h>
25#include <sys/inotify.h>
26#include <dirent.h>
27#include <fcntl.h>
28#include <errno.h>
29#include <ctype.h>
30#include <pthread.h>
31
32#include <linux/usbdevice_fs.h>
33#include <linux/version.h>
34#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
35#include <linux/usb/ch9.h>
36#else
37#include <linux/usb_ch9.h>
38#endif
39#include <asm/byteorder.h>
40
41#include "usbhost/usbhost.h"
42
43#define USB_FS_DIR "/dev/bus/usb"
44
45#if 0
46#define D printf
47#else
48#define D(...)
49#endif
50
51struct usb_device {
52 char dev_name[64];
53 unsigned char desc[256];
54 int desc_length;
55 int fd;
56 int writeable;
57};
58
59struct usb_endpoint
60{
61 struct usb_device *dev;
62 struct usb_endpoint_descriptor desc;
63 struct usbdevfs_urb urb;
64};
65
66static usb_device_added_cb s_added_cb;
67static usb_device_removed_cb s_removed_cb;
68
69static inline int badname(const char *name)
70{
71 while(*name) {
72 if(!isdigit(*name++)) return 1;
73 }
74 return 0;
75}
76
77static void find_existing_devices()
78{
79 char busname[32], devname[32];
80 DIR *busdir , *devdir ;
81 struct dirent *de;
82
83 busdir = opendir(USB_FS_DIR);
84 if(busdir == 0) return;
85
86 while((de = readdir(busdir)) != 0) {
87 if(badname(de->d_name)) continue;
88
89 snprintf(busname, sizeof busname, "%s/%s", USB_FS_DIR, de->d_name);
90 devdir = opendir(busname);
91 if(devdir == 0) continue;
92
93 while((de = readdir(devdir))) {
94 if(badname(de->d_name)) continue;
95
96 snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
97 s_added_cb(devname);
98 } // end of devdir while
99 closedir(devdir);
100 } //end of busdir while
101 closedir(busdir);
102}
103
104static void* device_discovery_thread(void* unused)
105{
106 struct inotify_event* event;
107 char event_buf[512];
108 char path[100];
109 int i, fd, ret;
110 int wd, wds[10];
111 int wd_count = sizeof(wds) / sizeof(wds[0]);
112
113 D("Created device discovery thread\n");
114
115 fd = inotify_init();
116 if (fd < 0) {
117 fprintf(stderr, "inotify_init failed\n");
118 return NULL;
119 }
120
121 /* watch for files added and deleted within USB_FS_DIR */
122 memset(wds, 0, sizeof(wds));
123 /* watch the root for new subdirectories */
124 wds[0] = inotify_add_watch(fd, USB_FS_DIR, IN_CREATE | IN_DELETE);
125 if (wds[0] < 0) {
126 fprintf(stderr, "inotify_add_watch failed\n");
127 return NULL;
128 }
129
130 /* watch existing subdirectories of USB_FS_DIR */
131 for (i = 1; i < wd_count; i++) {
132 snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i);
133 ret = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE);
134 if (ret > 0)
135 wds[i] = ret;
136 }
137
138 /* check for existing devices first, after we have inotify set up */
139 if (s_added_cb)
140 find_existing_devices();
141
142 while (1) {
143 ret = read(fd, event_buf, sizeof(event_buf));
144 if (ret >= (int)sizeof(struct inotify_event)) {
145 event = (struct inotify_event *)event_buf;
146 wd = event->wd;
147 if (wd == wds[0]) {
148 i = atoi(event->name);
149 snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name);
150 D("new subdirectory %s: index: %d\n", path, i);
151 if (i > 0 && i < wd_count) {
152 ret = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE);
153 if (ret > 0)
154 wds[i] = ret;
155 }
156 } else {
157 for (i = 1; i < wd_count; i++) {
158 if (wd == wds[i]) {
159 snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name);
160 if (event->mask == IN_CREATE) {
161 D("new device %s\n", path);
162 if (s_added_cb)
163 s_added_cb(path);
164 } else if (event->mask == IN_DELETE) {
165 D("gone device %s\n", path);
166 if (s_removed_cb)
167 s_removed_cb(path);
168 }
169 }
170 }
171 }
172 }
173 }
174 return NULL;
175}
176
177int usb_host_init(usb_device_added_cb added_cb, usb_device_removed_cb removed_cb)
178{
179 pthread_t tid;
180
181 s_added_cb = added_cb;
182 s_removed_cb = removed_cb;
183
184 if (added_cb || removed_cb) {
185 pthread_attr_t attr;
186
187 pthread_attr_init(&attr);
188 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
189 return pthread_create(&tid, &attr, device_discovery_thread, NULL);
190 }
191 else
192 return 0;
193}
194
195struct usb_device *usb_device_open(const char *dev_name)
196{
197 struct usb_device *device = calloc(1, sizeof(struct usb_device));
198 int fd, length, did_retry = 0;
199
200 strcpy(device->dev_name, dev_name);
201 device->writeable = 1;
202
203retry:
204 fd = open(dev_name, O_RDWR);
205 if (fd < 0) {
206 /* if we fail, see if have read-only access */
207 fd = open(dev_name, O_RDONLY);
208 if (fd < 0 && errno == EACCES && !did_retry) {
209 /* work around race condition between inotify and permissions management */
210 sleep(1);
211 did_retry = 1;
212 goto retry;
213 }
214
215 if (fd < 0) goto fail;
216 device->writeable = 0;
217 D("[ usb open read-only %s fd = %d]\n", dev_name, fd);
218 }
219
220 length = read(fd, device->desc, sizeof(device->desc));
221 if (length < 0)
222 goto fail;
223
224 device->fd = fd;
225 device->desc_length = length;
226 return device;
227fail:
228 close(fd);
229 free(device);
230 return NULL;
231}
232
233void usb_device_close(struct usb_device *device)
234{
235 close(device->fd);
236 free(device);
237}
238
239const char* usb_device_get_name(struct usb_device *device)
240{
241 return device->dev_name;
242}
243
244uint16_t usb_device_get_vendor_id(struct usb_device *device)
245{
246 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
247 return __le16_to_cpu(desc->idVendor);
248}
249
250uint16_t usb_device_get_product_id(struct usb_device *device)
251{
252 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
253 return __le16_to_cpu(desc->idProduct);
254}
255
256char* usb_device_get_string(struct usb_device *device, int id)
257{
258 char string[256];
259 struct usbdevfs_ctrltransfer ctrl;
260 __u16 buffer[128];
261 __u16 languages[128];
262 int i, result;
263 int languageCount = 0;
264
265 string[0] = 0;
266
267 // reading the string requires read/write permission
268 if (!device->writeable) {
269 int fd = open(device->dev_name, O_RDWR);
270 if (fd > 0) {
271 close(device->fd);
272 device->fd = fd;
273 device->writeable = 1;
274 } else {
275 return NULL;
276 }
277 }
278
279 memset(languages, 0, sizeof(languages));
280 memset(&ctrl, 0, sizeof(ctrl));
281
282 // read list of supported languages
283 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
284 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
285 ctrl.wValue = (USB_DT_STRING << 8) | 0;
286 ctrl.wIndex = 0;
287 ctrl.wLength = sizeof(languages);
288 ctrl.data = languages;
289
290 result = ioctl(device->fd, USBDEVFS_CONTROL, &ctrl);
291 if (result > 0)
292 languageCount = (result - 2) / 2;
293
294 for (i = 1; i <= languageCount; i++) {
295 memset(buffer, 0, sizeof(buffer));
296 memset(&ctrl, 0, sizeof(ctrl));
297
298 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
299 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
300 ctrl.wValue = (USB_DT_STRING << 8) | id;
301 ctrl.wIndex = languages[i];
302 ctrl.wLength = sizeof(buffer);
303 ctrl.data = buffer;
304
305 result = ioctl(device->fd, USBDEVFS_CONTROL, &ctrl);
306 if (result > 0) {
307 int i;
308 // skip first word, and copy the rest to the string, changing shorts to bytes.
309 result /= 2;
310 for (i = 1; i < result; i++)
311 string[i - 1] = buffer[i];
312 string[i - 1] = 0;
313 return strdup(string);
314 }
315 }
316
317 return NULL;
318}
319
320char* usb_device_get_manufacturer_name(struct usb_device *device)
321{
322 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
323
324 if (desc->iManufacturer)
325 return usb_device_get_string(device, desc->iManufacturer);
326 else
327 return NULL;
328}
329
330char* usb_device_get_product_name(struct usb_device *device)
331{
332 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
333
334 if (desc->iProduct)
335 return usb_device_get_string(device, desc->iProduct);
336 else
337 return NULL;
338}
339
340char* usb_device_get_serial(struct usb_device *device)
341{
342 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
343
344 if (desc->iSerialNumber)
345 return usb_device_get_string(device, desc->iSerialNumber);
346 else
347 return NULL;
348}
349
350int usb_device_is_writeable(struct usb_device *device)
351{
352 return device->writeable;
353}
354
355void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter)
356{
357 iter->config = device->desc;
358 iter->config_end = device->desc + device->desc_length;
359 iter->curr_desc = device->desc;
360}
361
362struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter)
363{
364 struct usb_descriptor_header* next;
365 if (iter->curr_desc >= iter->config_end)
366 return NULL;
367 next = (struct usb_descriptor_header*)iter->curr_desc;
368 iter->curr_desc += next->bLength;
369 return next;
370}
371
372int usb_device_claim_interface(struct usb_device *device, unsigned int interface)
373{
374 return ioctl(device->fd, USBDEVFS_CLAIMINTERFACE, &interface);
375}
376
377int usb_device_release_interface(struct usb_device *device, unsigned int interface)
378{
379 return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface);
380}
381
382struct usb_endpoint *usb_endpoint_open(struct usb_device *dev,
383 const struct usb_endpoint_descriptor *desc)
384{
385 struct usb_endpoint *ep = calloc(1, sizeof(struct usb_endpoint));
386 memcpy(&ep->desc, desc, sizeof(ep->desc));
387 ep->dev = dev;
388 return ep;
389}
390
391void usb_endpoint_close(struct usb_endpoint *ep)
392{
393 // cancel IO here?
394 free(ep);
395}
396
397int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len)
398{
399 struct usbdevfs_urb *urb = &ep->urb;
400 int res;
401
402 D("usb_endpoint_queue\n");
403 memset(urb, 0, sizeof(*urb));
404 urb->type = USBDEVFS_URB_TYPE_BULK;
405 urb->endpoint = ep->desc.bEndpointAddress;
406 urb->status = -1;
407 urb->buffer = data;
408 urb->buffer_length = len;
409
410 do {
411 res = ioctl(ep->dev->fd, USBDEVFS_SUBMITURB, urb);
412 } while((res < 0) && (errno == EINTR));
413
414 return res;
415}
416
417int usb_endpoint_wait(struct usb_device *dev, int *out_ep_num)
418{
419 struct usbdevfs_urb *out = NULL;
420 int res;
421
422 while (1) {
423 res = ioctl(dev->fd, USBDEVFS_REAPURB, &out);
424 D("USBDEVFS_REAPURB returned %d\n", res);
425 if (res < 0) {
426 if(errno == EINTR) {
427 continue;
428 }
429 D("[ reap urb - error ]\n");
430 *out_ep_num = -1;
431 } else {
432 D("[ urb @%p status = %d, actual = %d ]\n",
433 out, out->status, out->actual_length);
434 res = out->actual_length;
435 *out_ep_num = out->endpoint;
436 }
437 break;
438 }
439 return res;
440}
441
442int usb_endpoint_cancel(struct usb_endpoint *ep)
443{
444 return ioctl(ep->dev->fd, USBDEVFS_DISCARDURB, &ep->urb);
445}
446
Mike Lockwood5e567cb2010-05-12 08:53:49 -0400447struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep)
448{
449 return ep->dev;
450}
451
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400452int usb_endpoint_number(struct usb_endpoint *ep)
453{
454 return ep->desc.bEndpointAddress;
455}
456
457int usb_endpoint_max_packet(struct usb_endpoint *ep)
458{
459 return __le16_to_cpu(ep->desc.wMaxPacketSize);
460}
461