Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a306ced1 authored by Ziv Hendel's avatar Ziv Hendel Committed by Benoit Goby
Browse files

libusbhost: It's no longer assumed that "bus/usb" exists once "bus" was created

On some devices there is a slight delay between the creation of "/dev/bus"
and "/dev/bus/usb". Previously, the code assumed that both are created in the
same time which caused "watch_existing_subdirs" to fail and libusbhost to stop
working until the device is rebooted. The fix will setup an inotify event on the
creation of the "bus/usb" so it will not be missed once it's created.

Change-Id: I17f06dd167e61573307425e48898e12ebc954093
parent 18860c52
Loading
Loading
Loading
Loading
+16 −3
Original line number Original line Diff line number Diff line
@@ -51,7 +51,8 @@
#include "usbhost/usbhost.h"
#include "usbhost/usbhost.h"


#define DEV_DIR             "/dev"
#define DEV_DIR             "/dev"
#define USB_FS_DIR          DEV_DIR "/bus/usb"
#define DEV_BUS_DIR         DEV_DIR "/bus"
#define USB_FS_DIR          DEV_BUS_DIR "/usb"
#define USB_FS_ID_SCANNER   USB_FS_DIR "/%d/%d"
#define USB_FS_ID_SCANNER   USB_FS_DIR "/%d/%d"
#define USB_FS_ID_FORMAT    USB_FS_DIR "/%03d/%03d"
#define USB_FS_ID_FORMAT    USB_FS_DIR "/%03d/%03d"


@@ -68,6 +69,7 @@ struct usb_host_context {
    void                        *data;
    void                        *data;
    int                         wds[MAX_USBFS_WD_COUNT];
    int                         wds[MAX_USBFS_WD_COUNT];
    int                         wdd;
    int                         wdd;
    int                         wddbus;
};
};


struct usb_device {
struct usb_device {
@@ -195,6 +197,7 @@ int usb_host_load(struct usb_host_context *context,
    D("Created device discovery thread\n");
    D("Created device discovery thread\n");


    /* watch for files added and deleted within USB_FS_DIR */
    /* watch for files added and deleted within USB_FS_DIR */
    context->wddbus = -1;
    for (i = 0; i < MAX_USBFS_WD_COUNT; i++)
    for (i = 0; i < MAX_USBFS_WD_COUNT; i++)
        context->wds[i] = -1;
        context->wds[i] = -1;


@@ -228,15 +231,25 @@ int usb_host_read_event(struct usb_host_context *context)


    ret = read(context->fd, event_buf, sizeof(event_buf));
    ret = read(context->fd, event_buf, sizeof(event_buf));
    if (ret >= (int)sizeof(struct inotify_event)) {
    if (ret >= (int)sizeof(struct inotify_event)) {
        while (offset < ret) {
        while (offset < ret && !done) {
            event = (struct inotify_event*)&event_buf[offset];
            event = (struct inotify_event*)&event_buf[offset];
            done = 0;
            done = 0;
            wd = event->wd;
            wd = event->wd;
            if (wd == context->wdd) {
            if (wd == context->wdd) {
                if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
                if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
                    context->wddbus = inotify_add_watch(context->fd, DEV_BUS_DIR, IN_CREATE | IN_DELETE);
                    if (context->wddbus < 0) {
                        done = 1;
                    } else {
                        watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
                        done = find_existing_devices(context->cb_added, context->data);
                    }
                }
            } else if (wd == context->wddbus) {
                if ((event->mask & IN_CREATE) && !strcmp(event->name, "usb")) {
                    watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
                    watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
                    done = find_existing_devices(context->cb_added, context->data);
                    done = find_existing_devices(context->cb_added, context->data);
                } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) {
                } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "usb")) {
                    for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
                    for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
                        if (context->wds[i] >= 0) {
                        if (context->wds[i] >= 0) {
                            inotify_rm_watch(context->fd, context->wds[i]);
                            inotify_rm_watch(context->fd, context->wds[i]);