diff options
author | Mike Lockwood <lockwood@android.com> | 2010-07-01 11:33:41 -0400 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2010-07-01 11:33:41 -0400 |
commit | 7a96ba436c9a2bacc64e712bdb53bd7accc5c3a9 (patch) | |
tree | c21beaa4015313b25616db50d28c713425d9696d /libusbhost | |
parent | 4272a7ad70721acd68cf9f73c0455bda3102c80f (diff) | |
download | system_core-7a96ba436c9a2bacc64e712bdb53bd7accc5c3a9.zip system_core-7a96ba436c9a2bacc64e712bdb53bd7accc5c3a9.tar.gz system_core-7a96ba436c9a2bacc64e712bdb53bd7accc5c3a9.tar.bz2 |
libusbhost: The client is now responsible for creating the thread that monitors the bus
This is to allow using a thread that is capable of calling through JNI to Java code
to report USB device attached/removed events.
Change-Id: Ia58592607a2c1f4357b31072044f5db5617d7f5b
Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'libusbhost')
-rw-r--r-- | libusbhost/usbhost.c | 96 |
1 files changed, 49 insertions, 47 deletions
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c index 1d83a39..efd3103 100644 --- a/libusbhost/usbhost.c +++ b/libusbhost/usbhost.c @@ -60,9 +60,7 @@ struct usb_host_context { - usb_device_added_cb added_cb; - usb_device_removed_cb removed_cb; - void *client_data; + int fd; }; struct usb_device { @@ -88,73 +86,97 @@ static inline int badname(const char *name) return 0; } -static void find_existing_devices(struct usb_host_context *context) +/* returns true if one of the callbacks indicates we are done */ +static int find_existing_devices(usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + void *client_data) { char busname[32], devname[32]; DIR *busdir , *devdir ; struct dirent *de; + int done = 0; busdir = opendir(USB_FS_DIR); - if(busdir == 0) return; + if(busdir == 0) return 1; - while((de = readdir(busdir)) != 0) { + while ((de = readdir(busdir)) != 0 && !done) { if(badname(de->d_name)) continue; snprintf(busname, sizeof busname, "%s/%s", USB_FS_DIR, de->d_name); devdir = opendir(busname); if(devdir == 0) continue; - while((de = readdir(devdir))) { + while ((de = readdir(devdir)) && !done) { if(badname(de->d_name)) continue; snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name); - context->added_cb(devname, context->client_data); + done = added_cb(devname, client_data); } // end of devdir while closedir(devdir); } //end of busdir while closedir(busdir); + + return done; +} + +struct usb_host_context *usb_host_init() +{ + struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context)); + if (!context) { + fprintf(stderr, "out of memory in usb_host_context\n"); + return NULL; + } + context->fd = inotify_init(); + if (context->fd < 0) { + fprintf(stderr, "inotify_init failed\n"); + free(context); + return NULL; + } + return context; } -static void* device_discovery_thread(void *client_data) +void usb_host_cleanup(struct usb_host_context *context) +{ + close(context->fd); + free(context); +} + +void usb_host_run(struct usb_host_context *context, + usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + void *client_data) { - struct usb_host_context *context = (struct usb_host_context *)client_data; struct inotify_event* event; char event_buf[512]; char path[100]; - int i, fd, ret; + int i, ret, done = 0; int wd, wds[10]; int wd_count = sizeof(wds) / sizeof(wds[0]); D("Created device discovery thread\n"); - fd = inotify_init(); - if (fd < 0) { - fprintf(stderr, "inotify_init failed\n"); - return NULL; - } - /* watch for files added and deleted within USB_FS_DIR */ memset(wds, 0, sizeof(wds)); /* watch the root for new subdirectories */ - wds[0] = inotify_add_watch(fd, USB_FS_DIR, IN_CREATE | IN_DELETE); + wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE); if (wds[0] < 0) { fprintf(stderr, "inotify_add_watch failed\n"); - return NULL; + return; } /* watch existing subdirectories of USB_FS_DIR */ for (i = 1; i < wd_count; i++) { snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i); - ret = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE); + ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); if (ret > 0) wds[i] = ret; } /* check for existing devices first, after we have inotify set up */ - find_existing_devices(context); + done = find_existing_devices(added_cb, removed_cb, client_data); - while (1) { - ret = read(fd, event_buf, sizeof(event_buf)); + while (!done) { + ret = read(context->fd, event_buf, sizeof(event_buf)); if (ret >= (int)sizeof(struct inotify_event)) { event = (struct inotify_event *)event_buf; wd = event->wd; @@ -163,46 +185,26 @@ static void* device_discovery_thread(void *client_data) snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name); D("new subdirectory %s: index: %d\n", path, i); if (i > 0 && i < wd_count) { - ret = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE); + ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); if (ret > 0) wds[i] = ret; } } else { - for (i = 1; i < wd_count; i++) { + for (i = 1; i < wd_count && !done; i++) { if (wd == wds[i]) { snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name); if (event->mask == IN_CREATE) { D("new device %s\n", path); - context->added_cb(path, context->client_data); + done = added_cb(path, client_data); } else if (event->mask == IN_DELETE) { D("gone device %s\n", path); - context->removed_cb(path, context->client_data); + done = removed_cb(path, client_data); } } } } } } - return NULL; -} - -int usb_host_init(usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, void *client_data) -{ - struct usb_host_context *context; - pthread_t tid; - pthread_attr_t attr; - - if (!added_cb || !removed_cb) - return -EINVAL; - - context = calloc(1, sizeof(struct usb_host_context)); - context->added_cb = added_cb; - context->removed_cb = removed_cb; - context->client_data = client_data; - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - return pthread_create(&tid, &attr, device_discovery_thread, context); } struct usb_device *usb_device_open(const char *dev_name) |