usbhost.c revision 5e567cb34b5e54467f501fc9703db82ca6639ff3
1/*
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
447struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep)
448{
449    return ep->dev;
450}
451
452int 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
462