Skip to content
Browse files

libusbhost: Fix USB device discovery on boot

On some devices, /dev/bus/usb does not exist on boot, it is only created
when the otg port is in host mode. Use inotify to detect when /dev/bus/usb
is created and then start watching subdirectories.

Change-Id: Ic1472a5ea7a7118cdbb560cc7071ade9bcee753a
  • Loading branch information...
1 parent 6cc883c commit f4de078388242fff9b68c04b122e8a095cab9b0e @benoitgoby benoitgoby committed Aug 1, 2012
Showing with 43 additions and 15 deletions.
  1. +43 −15 libusbhost/usbhost.c
View
58 libusbhost/usbhost.c
@@ -49,7 +49,8 @@
#include "usbhost/usbhost.h"
-#define USB_FS_DIR "/dev/bus/usb"
+#define DEV_DIR "/dev"
+#define USB_FS_DIR "/dev/bus/usb"
#define USB_FS_ID_SCANNER "/dev/bus/usb/%d/%d"
#define USB_FS_ID_FORMAT "/dev/bus/usb/%03d/%03d"
@@ -110,7 +111,7 @@ static int find_existing_devices(usb_device_added_cb added_cb,
int done = 0;
busdir = opendir(USB_FS_DIR);
- if(busdir == 0) return 1;
+ if(busdir == 0) return 0;
while ((de = readdir(busdir)) != 0 && !done) {
if(badname(de->d_name)) continue;
@@ -124,6 +125,25 @@ static int find_existing_devices(usb_device_added_cb added_cb,
return done;
}
+static void watch_existing_subdirs(struct usb_host_context *context,
+ int *wds, int wd_count)
+{
+ char path[100];
+ int i, ret;
+
+ wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE);
+ if (wds[0] < 0)
+ 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(context->fd, path, IN_CREATE | IN_DELETE);
+ if (ret >= 0)
+ wds[i] = ret;
+ }
+}
+
struct usb_host_context *usb_host_init()
{
struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context));
@@ -156,29 +176,25 @@ void usb_host_run(struct usb_host_context *context,
char event_buf[512];
char path[100];
int i, ret, done = 0;
- int wd, wds[10];
+ int wd, wdd, wds[10];
int wd_count = sizeof(wds) / sizeof(wds[0]);
D("Created device discovery thread\n");
/* watch for files added and deleted within USB_FS_DIR */
- memset(wds, 0, sizeof(wds));
+ for (i = 0; i < wd_count; i++)
+ wds[i] = -1;
+
/* watch the root for new subdirectories */
- wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE);
- if (wds[0] < 0) {
+ wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE);
+ if (wdd < 0) {
fprintf(stderr, "inotify_add_watch failed\n");
if (discovery_done_cb)
discovery_done_cb(client_data);
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(context->fd, path, IN_CREATE | IN_DELETE);
- if (ret > 0)
- wds[i] = ret;
- }
+ watch_existing_subdirs(context, wds, wd_count);
/* check for existing devices first, after we have inotify set up */
done = find_existing_devices(added_cb, client_data);
@@ -190,7 +206,19 @@ void usb_host_run(struct usb_host_context *context,
if (ret >= (int)sizeof(struct inotify_event)) {
event = (struct inotify_event *)event_buf;
wd = event->wd;
- if (wd == wds[0]) {
+ if (wd == wdd) {
+ if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
+ watch_existing_subdirs(context, wds, wd_count);
+ done = find_existing_devices(added_cb, client_data);
+ } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
+ for (i = 0; i < wd_count; i++) {
+ if (wds[i] >= 0) {
+ inotify_rm_watch(context->fd, wds[i]);
+ wds[i] = -1;
+ }
+ }
+ }
+ } else if (wd == wds[0]) {
i = atoi(event->name);
snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name);
D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
@@ -199,7 +227,7 @@ void usb_host_run(struct usb_host_context *context,
if (event->mask & IN_CREATE) {
ret = inotify_add_watch(context->fd, path,
IN_CREATE | IN_DELETE);
- if (ret > 0)
+ if (ret >= 0)
wds[i] = ret;
done = find_existing_devices_bus(path, added_cb,
client_data);

0 comments on commit f4de078

Please sign in to comment.
Something went wrong with that request. Please try again.