Index: xf86-input-evdev/src/evdev_brain.c =================================================================== RCS file: /cvs/xorg/driver/xf86-input-evdev/src/evdev_brain.c,v retrieving revision 1.4 diff -u -r1.4 evdev_brain.c --- xf86-input-evdev/src/evdev_brain.c 16 Mar 2006 13:09:19 -0000 1.4 +++ xf86-input-evdev/src/evdev_brain.c 31 Mar 2006 18:47:34 -0000 @@ -37,6 +37,8 @@ #include "xf86_OSlib.h" #include "evdev.h" +#include "inotify.h" +#include "inotify-syscalls.h" #include #include @@ -45,6 +47,9 @@ #define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) #endif +#define INOTIFY_EVENT_SIZE (sizeof (struct inotify_event)) +#define INOTIFY_BUF_LEN (1024 * (INOTIFY_EVENT_SIZE + 16)) + static Bool evdev_alive = FALSE; static InputInfoPtr evdev_pInfo = NULL; static evdevDriverPtr evdev_drivers = NULL; @@ -292,8 +297,7 @@ } } - if (!found) - close (info.fd); + close (info.fd); } for (driver = evdev_drivers; driver; driver = driver->next) @@ -315,16 +319,35 @@ evdevReadInput (InputInfoPtr pInfo) { /* - * XXX: Freezing the server for a moment is not really friendly. - * But we need to wait until udev has actually created the device. + * Check that it was an "event" file */ - usleep (500000); - evdevRescanDevices (pInfo); + int i = 0, y = 0, len = 0; + struct inotify_event *event; + char buf[INOTIFY_BUF_LEN]; + + len = read (pInfo->fd, buf, INOTIFY_BUF_LEN); + while (i < len) { + event = (struct inotify_event *) &buf[i]; + if (event->len && ! strncmp(event->name, "event", 5)) { + if (event->mask & IN_DELETE) { + xf86Msg(X_INFO, "file deleted: %s\n", event->name); + } else if (event->mask & IN_CREATE) { + xf86Msg(X_INFO, "file created: %s\n", event->name); + } + y = 1; + break; + } + i += INOTIFY_EVENT_SIZE + event->len; + } + if (y) + evdevRescanDevices (pInfo); } static int evdevControl(DeviceIntPtr pPointer, int what) { + int wd; + InputInfoPtr pInfo; pInfo = pPointer->public.devicePrivate; @@ -335,17 +358,20 @@ break; case DEVICE_ON: - /* - * XXX: We do /proc/bus/usb/devices instead of /proc/bus/input/devices - * because the only hotplug input devices at the moment are USB... - * And because the latter is useless to poll/select against. - * FIXME: Get a patch in the kernel which fixes the latter. - */ - pInfo->fd = open ("/proc/bus/usb/devices", O_RDONLY); - if (pInfo->fd == -1) { - xf86Msg(X_ERROR, "%s: cannot open /proc/bus/usb/devices.\n", pInfo->name); - return BadRequest; - } + /* + * Use the kernel's inotify to detect changes in /dev/input + */ + pInfo->fd = inotify_init (); + if (pInfo->fd == -1) { + xf86Msg(X_ERROR, "%s: cannot initialize inotify.\n", pInfo->name); + return BadRequest; + } + wd = inotify_add_watch (pInfo->fd, "/dev/input/", IN_CREATE | IN_DELETE); + if (wd < 0) { + xf86Msg(X_ERROR, "%s: cannot initialize inotify watcher.\n", pInfo->name); + return BadRequest; + } + xf86FlushInput(pInfo->fd); AddEnabledDevice(pInfo->fd); pPointer->public.on = TRUE;