diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/evdev.c | 5 | ||||
-rw-r--r-- | src/evdev_brain.c | 65 | ||||
-rw-r--r-- | src/inotify-syscalls.h | 61 | ||||
-rw-r--r-- | src/inotify.h | 60 |
6 files changed, 195 insertions, 12 deletions
@@ -1,5 +1,19 @@ 2006-04-08 Zephaniah E. Hull <warp@aehallh.com> + * configure.ac: + Dropped the xorg-xserver 1.0.99.901 requirement. + (Things were tweaked to mostly work for older servers again.) + * src/evdev.c: (EvdevReadInput): + Close the device properly on read errer. + * src/evdev_brain.c: (evdevReadInput), (evdevControl): + Minimal inotify support, not ideal yet, but... + * src/inotify-syscalls.h: + Minimal inotify support, not ideal yet, but... + * src/inotify.h: + Minimal inotify support, not ideal yet, but... + +2006-04-08 Zephaniah E. Hull <warp@aehallh.com> + * src/Makefile.am: Remove evdev_abs.c and evdev_rel.c. Added evdev_axes.c. diff --git a/configure.ac b/configure.ac index dee75a2..c476853 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,7 @@ XORG_DRIVER_CHECK_EXT(XKB, kbproto) XORG_DRIVER_CHECK_EXT(XINPUT, inputproto) # Checks for pkg-config packages -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.99.901] xproto $REQUIRED_MODULES) +PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES) sdkdir=$(pkg-config --variable=sdkdir xorg-server) CFLAGS="$CFLAGS $XORG_CFLAGS "' -I$(top_srcdir)/src' diff --git a/src/evdev.c b/src/evdev.c index 7179c04..94ff353 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -93,6 +93,11 @@ EvdevReadInput(InputInfoPtr pInfo) * event, so len != sizeof ev is an error. */ xf86Msg(X_ERROR, "Read error: %s (%d, %d != %ld)\n", strerror(errno), errno, len, sizeof (ev)); + if (len < 0) { + evdevDevicePtr pEvdev = pInfo->private; + pEvdev->callback(pEvdev->pInfo->dev, DEVICE_OFF); + pEvdev->seen--; + } break; } diff --git a/src/evdev_brain.c b/src/evdev_brain.c index 92f003c..c4b6fd1 100644 --- a/src/evdev_brain.c +++ b/src/evdev_brain.c @@ -40,6 +40,9 @@ #include <xf86.h> #include <fnmatch.h> +#include "inotify.h" +#include "inotify-syscalls.h" + #ifndef SYSCALL #define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) #endif @@ -48,6 +51,7 @@ static Bool evdev_alive = FALSE; static InputInfoPtr evdev_pInfo = NULL; static evdevDriverPtr evdev_drivers = NULL; static int evdev_seq; +static int evdev_inotify; int evdevGetFDForDevice (evdevDevicePtr device) @@ -309,18 +313,41 @@ evdevRescanDevices (InputInfoPtr pInfo) static void 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. - */ - usleep (500000); - evdevRescanDevices (pInfo); + int scan = 0, i, len; + char buf[4096]; + struct inotify_event *event; + + if (evdev_inotify) { + while ((len = read (pInfo->fd, buf, sizeof(buf))) >= 0) { + for (i = 0; i < len; i += sizeof (struct inotify_event) + event->len) { + event = (struct inotify_event *) &buf[i]; + if (!event->len) + continue; + if (event->mask & IN_ISDIR) + continue; + if (strncmp("event", event->name, 5)) + continue; + scan = 1; + } + } + + if (scan) + evdevRescanDevices (pInfo); + } else { + /* + * XXX: Freezing the server for a moment is not really friendly. + * But we need to wait until udev has actually created the device. + */ + usleep (500000); + evdevRescanDevices (pInfo); + } } static int evdevControl(DeviceIntPtr pPointer, int what) { InputInfoPtr pInfo; + int i; pInfo = pPointer->public.devicePrivate; @@ -336,10 +363,26 @@ evdevControl(DeviceIntPtr pPointer, int what) * 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; + evdev_inotify = 1; + SYSCALL(pInfo->fd = inotify_init()); + if (pInfo->fd < 0) { + xf86Msg(X_ERROR, "%s: Unable to initialize inotify, using fallback. (errno: %d)\n", pInfo->name, errno); + evdev_inotify = 0; + } + SYSCALL (i = inotify_add_watch (pInfo->fd, "/dev/input/", IN_CREATE | IN_DELETE)); + if (i < 0) { + xf86Msg(X_ERROR, "%s: Unable to initialize inotify, using fallback. (errno: %d)\n", pInfo->name, errno); + evdev_inotify = 0; + SYSCALL (close (pInfo->fd)); + pInfo->fd = -1; + } + + if (!evdev_inotify) { + SYSCALL (pInfo->fd = open ("/proc/bus/usb/devices", O_RDONLY)); + if (pInfo->fd < 0) { + xf86Msg(X_ERROR, "%s: cannot open /proc/bus/usb/devices.\n", pInfo->name); + return BadRequest; + } } xf86FlushInput(pInfo->fd); AddEnabledDevice(pInfo->fd); @@ -351,7 +394,7 @@ evdevControl(DeviceIntPtr pPointer, int what) case DEVICE_CLOSE: if (pInfo->fd != -1) { RemoveEnabledDevice(pInfo->fd); - close (pInfo->fd); + SYSCALL (close (pInfo->fd)); pInfo->fd = -1; } pPointer->public.on = FALSE; diff --git a/src/inotify-syscalls.h b/src/inotify-syscalls.h new file mode 100644 index 0000000..1431d46 --- /dev/null +++ b/src/inotify-syscalls.h @@ -0,0 +1,61 @@ +#ifndef _LINUX_INOTIFY_SYSCALLS_H +#define _LINUX_INOTIFY_SYSCALLS_H + +#include <sys/syscall.h> + +#if defined(__i386__) +# define __NR_inotify_init 291 +# define __NR_inotify_add_watch 292 +# define __NR_inotify_rm_watch 293 +#elif defined(__x86_64__) +# define __NR_inotify_init 253 +# define __NR_inotify_add_watch 254 +# define __NR_inotify_rm_watch 255 +#elif defined(__powerpc__) || defined(__powerpc64__) +# define __NR_inotify_init 275 +# define __NR_inotify_add_watch 276 +# define __NR_inotify_rm_watch 277 +#elif defined (__ia64__) +# define __NR_inotify_init 1277 +# define __NR_inotify_add_watch 1278 +# define __NR_inotify_rm_watch 1279 +#elif defined (__s390__) +# define __NR_inotify_init 284 +# define __NR_inotify_add_watch 285 +# define __NR_inotify_rm_watch 286 +#elif defined (__alpha__) +# define __NR_inotify_init 444 +# define __NR_inotify_add_watch 445 +# define __NR_inotify_rm_watch 446 +#elif defined (__sparc__) || defined (__sparc64__) +# define __NR_inotify_init 151 +# define __NR_inotify_add_watch 152 +# define __NR_inotify_rm_watch 156 +#elif defined (__arm__) +# define __NR_inotify_init 316 +# define __NR_inotify_add_watch 317 +# define __NR_inotify_rm_watch 318 +#elif defined (__sh__) +# define __NR_inotify_init 290 +# define __NR_inotify_add_watch 291 +# define __NR_inotify_rm_watch 292 +#else +# error "Unsupported architecture!" +#endif + +static inline int inotify_init (void) +{ + return syscall (__NR_inotify_init); +} + +static inline int inotify_add_watch (int fd, const char *name, __u32 mask) +{ + return syscall (__NR_inotify_add_watch, fd, name, mask); +} + +static inline int inotify_rm_watch (int fd, __u32 wd) +{ + return syscall (__NR_inotify_rm_watch, fd, wd); +} + +#endif /* _LINUX_INOTIFY_SYSCALLS_H */ diff --git a/src/inotify.h b/src/inotify.h new file mode 100644 index 0000000..20d419a --- /dev/null +++ b/src/inotify.h @@ -0,0 +1,60 @@ +/* + * Inode based directory notification for Linux + * + * Copyright (C) 2005 John McCutchan + */ + +#ifndef _LINUX_INOTIFY_H +#define _LINUX_INOTIFY_H + +#include <linux/types.h> + +/* + * struct inotify_event - structure read from the inotify device for each event + * + * When you are watching a directory, you will receive the filename for events + * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd. + */ +struct inotify_event { + __s32 wd; /* watch descriptor */ + __u32 mask; /* watch mask */ + __u32 cookie; /* cookie to synchronize two events */ + __u32 len; /* length (including nulls) of name */ + char name[0]; /* stub for possible name */ +}; + +/* the following are legal, implemented events that user-space can watch for */ +#define IN_ACCESS 0x00000001 /* File was accessed */ +#define IN_MODIFY 0x00000002 /* File was modified */ +#define IN_ATTRIB 0x00000004 /* Metadata changed */ +#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */ +#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ +#define IN_OPEN 0x00000020 /* File was opened */ +#define IN_MOVED_FROM 0x00000040 /* File was moved from X */ +#define IN_MOVED_TO 0x00000080 /* File was moved to Y */ +#define IN_CREATE 0x00000100 /* Subfile was created */ +#define IN_DELETE 0x00000200 /* Subfile was deleted */ +#define IN_DELETE_SELF 0x00000400 /* Self was deleted */ + +/* the following are legal events. they are sent as needed to any watch */ +#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */ +#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */ +#define IN_IGNORED 0x00008000 /* File was ignored */ + +/* helper events */ +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */ +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */ + +/* special flags */ +#define IN_ISDIR 0x40000000 /* event occurred against dir */ +#define IN_ONESHOT 0x80000000 /* only send event once */ + +/* + * All of the events - we build the list by hand so that we can add flags in + * the future and not break backward compatibility. Apps will get only the + * events that they originally wanted. Be sure to add new events here! + */ +#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \ + IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \ + IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF) +#endif /* _LINUX_INOTIFY_H */ |