summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--configure.ac2
-rw-r--r--src/evdev.c5
-rw-r--r--src/evdev_brain.c65
-rw-r--r--src/inotify-syscalls.h61
-rw-r--r--src/inotify.h60
6 files changed, 195 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 069dd9d..e47d892 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 */