summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZephaniah E. Hull <warp@agamemnon.b5>2007-04-24 06:49:11 -0400
committerZephaniah E. Hull <warp@agamemnon.b5>2007-04-24 06:49:11 -0400
commita0ea7363f51ff6c2bb81006b7220b7daa9ee9221 (patch)
tree6766bbe03cf96f91c7a799612a0bdb6dab033d4a
parent3c4a96fbd851e46830fe82570d04e191bae5e8e3 (diff)
downloadxorg-driver-xf86-input-evdev-a0ea7363f51ff6c2bb81006b7220b7daa9ee9221.tar.gz
Remove all of evdev_brain.c and all callers.
Remove the non-functional 2.4 kernel compiling compatibility. Remove the XInput 1.4+ SendCoreEvents/DontSendCoreEvents define replacements. Remove evdevDriver, some stuff from evdevDevice, all users. NOTE: This WILL BREAK all existing configurations. NOTE: Device read failure segfaults, don't unplug stuff.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/evdev.c228
-rw-r--r--src/evdev.h79
-rw-r--r--src/evdev_brain.c658
4 files changed, 65 insertions, 902 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 4d97d16..5a68288 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,4 +29,4 @@
@DRIVER_NAME@_drv_la_CFLAGS = -Wall
@DRIVER_NAME@_drv_ladir = @inputdir@
-@DRIVER_NAME@_drv_la_SOURCES = evdev.c evdev.h evdev_brain.c evdev_axes.c evdev_btn.c evdev_key.c inotify.h inotify-syscalls.h
+@DRIVER_NAME@_drv_la_SOURCES = evdev.c evdev.h evdev_axes.c evdev_btn.c evdev_key.c inotify.h inotify-syscalls.h
diff --git a/src/evdev.c b/src/evdev.c
index 5455062..63b8eb0 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -67,6 +67,7 @@
#include <xf86Module.h>
#include <mipointer.h>
+#include <xf86_OSlib.h>
#include <xf86_OSproc.h>
@@ -78,6 +79,35 @@
void xf86ActivateDevice(InputInfoPtr pInfo);
+/**
+ * Obtain various information using ioctls on the given socket. This
+ * information is used to determine if a device has axis, buttons or keys.
+ *
+ * @return TRUE on success or FALSE on error.
+ */
+static Bool
+evdevGetBits (int fd, evdevBitsPtr bits)
+{
+#define get_bitmask(fd, which, where) \
+ if (ioctl(fd, EVIOCGBIT(which, sizeof (where)), where) < 0) { \
+ xf86Msg(X_ERROR, "ioctl EVIOCGBIT %s failed: %s\n", #which, strerror(errno)); \
+ return FALSE; \
+ }
+
+ get_bitmask (fd, 0, bits->ev);
+ get_bitmask (fd, EV_KEY, bits->key);
+ get_bitmask (fd, EV_REL, bits->rel);
+ get_bitmask (fd, EV_ABS, bits->abs);
+ get_bitmask (fd, EV_MSC, bits->msc);
+ get_bitmask (fd, EV_LED, bits->led);
+ get_bitmask (fd, EV_SND, bits->snd);
+ get_bitmask (fd, EV_FF, bits->ff);
+
+#undef get_bitmask
+
+ return TRUE;
+}
+
static void
EvdevReadInput(InputInfoPtr pInfo)
{
@@ -94,7 +124,6 @@ EvdevReadInput(InputInfoPtr pInfo)
if (len < 0) {
evdevDevicePtr pEvdev = pInfo->private;
pEvdev->callback(pEvdev->pInfo->dev, DEVICE_OFF);
- pEvdev->seen--;
}
break;
}
@@ -162,13 +191,10 @@ EvdevProc(DeviceIntPtr device, int what)
if (device->public.on)
break;
- if ((pInfo->fd = evdevGetFDForDevice (pEvdev)) == -1) {
+ SYSCALL(pInfo->fd = open (pEvdev->device, O_RDWR | O_NONBLOCK));
+ if (pInfo->fd == -1) {
xf86Msg(X_ERROR, "%s: cannot open input device.\n", pInfo->name);
- if (pEvdev->phys)
- xfree(pEvdev->phys);
- pEvdev->phys = NULL;
-
if (pEvdev->device)
xfree(pEvdev->device);
pEvdev->device = NULL;
@@ -214,8 +240,13 @@ EvdevProc(DeviceIntPtr device, int what)
EvdevKeyOff (device);
}
+#if 0
+ /*
+ * FIXME: Handle device removal properly.
+ */
if (what == DEVICE_CLOSE)
evdevRemoveDevice(pEvdev);
+#endif
device->public.on = FALSE;
break;
@@ -241,12 +272,6 @@ EvdevSwitchMode (ClientPtr client, DeviceIntPtr device, int mode)
else
return !Success;
break;
-#if 0
- case SendCoreEvents:
- case DontSendCoreEvents:
- xf86XInputSetSendCoreEvents (pInfo, (mode == SendCoreEvents));
- break;
-#endif
default:
return !Success;
}
@@ -254,20 +279,29 @@ EvdevSwitchMode (ClientPtr client, DeviceIntPtr device, int mode)
return Success;
}
+/*
static Bool
EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
+*/
+
+InputInfoPtr
+EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
{
InputInfoPtr pInfo;
- char name[512] = {0};
+ evdevDevicePtr device;
- if (!(pInfo = xf86AllocateInput(driver->drv, 0)))
- return 0;
+ if (!(pInfo = xf86AllocateInput(drv, 0)))
+ return NULL;
+
+ device = Xcalloc (sizeof (evdevDeviceRec));
+ if (!device) {
+ pInfo->private = NULL;
+ xf86DeleteInput (pInfo, 0);
+ return NULL;
+ }
/* Initialise the InputInfoRec. */
- strncat (name, driver->dev->identifier, sizeof(name));
- strncat (name, "-", sizeof(name));
- strncat (name, device->phys, sizeof(name));
- pInfo->name = xstrdup(name);
+ pInfo->name = xstrdup(dev->identifier);
pInfo->flags = 0;
pInfo->type_name = "UNKNOWN";
pInfo->device_control = EvdevProc;
@@ -276,29 +310,31 @@ EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
pInfo->motion_history_proc = xf86GetMotionEvents;
#endif
- pInfo->conf_idev = driver->dev;
+ pInfo->conf_idev = dev;
pInfo->private = device;
- device->callback = EvdevProc;
- device->pInfo = pInfo;
+ device->device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
xf86CollectInputOptions(pInfo, NULL, NULL);
xf86ProcessCommonOptions(pInfo, pInfo->options);
- if ((pInfo->fd = evdevGetFDForDevice (device)) == -1) {
+ SYSCALL(pInfo->fd = open (device->device, O_RDWR | O_NONBLOCK));
+ if (pInfo->fd == -1) {
xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
pInfo->private = NULL;
+ xfree(device);
xf86DeleteInput (pInfo, 0);
- return 0;
+ return NULL;
}
if (!evdevGetBits (pInfo->fd, &device->bits)) {
xf86Msg(X_ERROR, "%s: cannot load bits\n", pInfo->name);
pInfo->private = NULL;
close (pInfo->fd);
+ xfree(device);
xf86DeleteInput (pInfo, 0);
- return 0;
+ return NULL;
}
if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
@@ -328,148 +364,12 @@ EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
xf86Msg(X_ERROR, "%s: Don't know how to use device.\n", pInfo->name);
pInfo->private = NULL;
close (pInfo->fd);
+ xfree(device);
xf86DeleteInput (pInfo, 0);
- return 0;
- }
-
- if (driver->configured) {
- xf86ActivateDevice (pInfo);
- pInfo->dev->inited = (ActivateDevice(pInfo->dev) == Success);
- ActivateDevice(pInfo->dev);
- EnableDevice (pInfo->dev);
- }
-
- return 1;
-}
-
-static void
-EvdevParseBits (char *in, unsigned long *out, int len)
-{
- unsigned long v[2];
- int n, i, max_bits = len * BITS_PER_LONG;
-
- n = sscanf (in, "%lu-%lu", &v[0], &v[1]);
- if (!n)
- return;
-
- if (v[0] >= max_bits)
- return;
-
- if (n == 2) {
- if (v[1] >= max_bits)
- v[1] = max_bits - 1;
-
- for (i = v[0]; i <= v[1]; i++)
- set_bit (i, out);
- } else
- set_bit (v[0], out);
-}
-
-static void
-EvdevParseBitOption (char *opt, unsigned long *all, unsigned long *not, unsigned long *any, int len)
-{
- char *cur, *next;
-
- next = opt - 1;
- while (next) {
- cur = next + 1;
- if ((next = strchr(cur, ' ')))
- *next = '\0';
-
- switch (cur[0]) {
- case '+':
- EvdevParseBits (cur + 1, all, len);
- break;
- case '-':
- EvdevParseBits (cur + 1, not, len);
- break;
- case '~':
- EvdevParseBits (cur + 1, any, len);
- break;
- }
- }
-}
-
-/**
- * Called during InitInput().
- * Starts up the evdev brain device if it hasn't started yet and then causes a
- * full rescan of all devices.
- *
- * @param drv The evdev driver module. Copied version of EVDEV.
- * @param dev The device we'd like to initialise.
- *
- * @return NULL on failure or the InputInfoPtr of the new device.
- */
-static InputInfoPtr
-EvdevCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
-{
- evdevDriverPtr pEvdev;
- char *opt, *tmp;
-
- if (!(pEvdev = Xcalloc(sizeof(*pEvdev))))
return NULL;
-
- pEvdev->name = xf86CheckStrOption(dev->commonOptions, "Name", NULL);
- pEvdev->phys = xf86CheckStrOption(dev->commonOptions, "Phys", NULL);
- pEvdev->device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
-
-#define bitoption(field) \
- opt = xf86CheckStrOption(dev->commonOptions, #field "Bits", NULL); \
- if (opt) { \
- tmp = strdup(opt); \
- EvdevParseBitOption (tmp, pEvdev->all_bits.field, \
- pEvdev->not_bits.field, \
- pEvdev->any_bits.field, \
- sizeof(pEvdev->not_bits.field) / sizeof (unsigned long)); \
- free (tmp); \
- }
- bitoption(ev);
- bitoption(key);
- bitoption(rel);
- bitoption(abs);
- bitoption(msc);
- bitoption(led);
- bitoption(snd);
- bitoption(ff);
-#undef bitoption
-
- pEvdev->id.bustype = xf86CheckIntOption(dev->commonOptions, "bustype", 0);
- pEvdev->id.vendor = xf86CheckIntOption(dev->commonOptions, "vendor", 0);
- pEvdev->id.product = xf86CheckIntOption(dev->commonOptions, "product", 0);
- pEvdev->id.version = xf86CheckIntOption(dev->commonOptions, "version", 0);
-
- pEvdev->pass = xf86CheckIntOption(dev->commonOptions, "Pass", 0);
- if (pEvdev->pass > 3)
- pEvdev->pass = 3;
- else if (pEvdev->pass < 0)
- pEvdev->pass = 0;
-
-
- pEvdev->callback = EvdevNew;
-
- pEvdev->dev = dev;
- pEvdev->drv = drv;
-
- if (!evdevStart (drv)) {
- xf86Msg(X_ERROR, "%s: cannot start evdev brain.\n", dev->identifier);
- xfree(pEvdev);
- return NULL;
}
- evdevNewDriver (pEvdev);
-
- if (pEvdev->devices && pEvdev->devices->pInfo)
- return pEvdev->devices->pInfo;
-
- /* In some cases pEvdev->devices is NULL, but on the next
- * evdevRescanDevices the device suddenly appears. If we return NULL here,
- * the server will clean up and the sudden appearance of the device will
- * segfault. We need to remove the driver from the list to avoid this.
- * No. I don't know why it just appears. (whot)
- */
- evdevRemoveDriver(pEvdev);
-
- return NULL;
+ return pInfo;
}
@@ -478,7 +378,7 @@ _X_EXPORT InputDriverRec EVDEV = {
1,
"evdev",
NULL,
- EvdevCorePreInit,
+ EvdevPreInit,
NULL,
NULL,
0
diff --git a/src/evdev.h b/src/evdev.h
index 81abbb6..9aca533 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -90,55 +90,10 @@
#define clear_bit(bit, array) (array[LONG(bit)] &= ~MASK(bit))
#endif
-/* 2.4 compatibility */
-#ifndef EVIOCGSW
-
-#include <sys/time.h>
-#include <sys/ioctl.h>
-
-#define EVIOCGSW(len) _IOC(_IOC_READ, 'E', 0x1b, len) /* get all switch states */
-
-#define EV_SW 0x05
-#endif
-
-#ifndef EVIOCGRAB
-#define EVIOCGRAB _IOW('E', 0x90, int)
-#endif
-
-#ifndef BTN_TASK
-#define BTN_TASK 0x117
-#endif
-
-#ifndef EV_SYN
-#define EV_SYN EV_RST
-#endif
-/* end compat */
#include <X11/extensions/XKB.h>
#include <X11/extensions/XKBstr.h>
-/* XInput 1.4+ compatability. */
-#ifndef SendCoreEvents
-#define SendCoreEvents 59
-#define DontSendCoreEvents 60
-#endif
-
-
-/*
- * Switch events
- */
-
-#define EV_SW_0 0x00
-#define EV_SW_1 0x01
-#define EV_SW_2 0x02
-#define EV_SW_3 0x03
-#define EV_SW_4 0x04
-#define EV_SW_5 0x05
-#define EV_SW_6 0x06
-#define EV_SW_7 0x07
-#define EV_SW_MAX 0x0f
-
-#define EV_BUS_GSC 0x1A
#define EVDEV_MAXBUTTONS 96
@@ -213,52 +168,18 @@ typedef struct _evdevState {
} evdevStateRec, *evdevStatePtr;
typedef struct _evdevDevice {
- const char *name;
- const char *phys;
const char *device;
- int seen;
InputInfoPtr pInfo;
int (*callback)(DeviceIntPtr cb_data, int what);
evdevBitsRec bits;
- struct input_id id;
evdevStateRec state;
struct _evdevDevice *next;
} evdevDeviceRec, *evdevDevicePtr;
-typedef struct _evdevDriver {
- const char *name;
- const char *phys;
- const char *device;
-
- evdevBitsRec all_bits;
- evdevBitsRec not_bits;
- evdevBitsRec any_bits;
-
- struct input_id id;
-
- int pass;
-
- InputDriverPtr drv;
- IDevPtr dev;
- Bool (*callback)(struct _evdevDriver *driver, evdevDevicePtr device);
- evdevDevicePtr devices;
- Bool configured;
-
- struct _evdevDriver *next;
-} evdevDriverRec, *evdevDriverPtr;
-
-int evdevGetFDForDevice (evdevDevicePtr driver);
-Bool evdevStart (InputDriverPtr drv);
-Bool evdevNewDriver (evdevDriverPtr driver);
-Bool evdevGetBits (int fd, evdevBitsPtr bits);
-void evdevRemoveDevice (evdevDevicePtr device);
-void evdevDeleteDevice (evdevDevicePtr device);
-void evdevRemoveDriver (evdevDriverPtr device);
-
int EvdevBtnInit (DeviceIntPtr device);
int EvdevBtnOn (DeviceIntPtr device);
int EvdevBtnOff (DeviceIntPtr device);
diff --git a/src/evdev_brain.c b/src/evdev_brain.c
deleted file mode 100644
index 03506c4..0000000
--- a/src/evdev_brain.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright © 2006 Zephaniah E. Hull
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Soft-
- * ware"), to deal in the Software without restriction, including without
- * limitation the rights to use, copy, modify, merge, publish, distribute,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, provided that the above copyright
- * notice(s) and this permission notice appear in all copies of the Soft-
- * ware and that both the above copyright notice(s) and this permission
- * notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
- * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
- * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
- * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
- * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
- * MANCE OF THIS SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder shall
- * not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization of
- * the copyright holder.
- *
- * Author: Zephaniah E. Hull (warp@aehallh.com)
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "evdev.h"
-
-#include "xf86_OSlib.h"
-
-#include <xf86.h>
-#include <fnmatch.h>
-#include <sys/poll.h>
-
-#include "inotify.h"
-#include "inotify-syscalls.h"
-
-#ifndef SYSCALL
-#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
-#endif
-
-/**
- * Indicate if evdev brain has been started yet.
- */
-static Bool evdev_alive = FALSE;
-/**
- * Pointer to the "evdev brain".
- * Note that this is a list, so evdev_pInfo->next will point to other devices
- * (albeit not evdev ones).
- */
-static InputInfoPtr evdev_pInfo = NULL;
-/**
- * All drivers that are currently active for one or more devices.
- */
-static evdevDriverPtr evdev_drivers = NULL;
-/**
- * Internal sequence numbering. Increased each time we evdevRescanDevices().
- */
-static int evdev_seq;
-static int evdev_inotify;
-
-/**
- * Open the file descriptor for the given device in rw, nonblocking mode.
- *
- * @return The FD on success or -1 otherwise.
- */
-int
-evdevGetFDForDevice (evdevDevicePtr device)
-{
- int fd;
-
- if (!device)
- return -1;
-
-
- if (device->device) {
- SYSCALL(fd = open (device->device, O_RDWR | O_NONBLOCK));
- if (fd == -1)
- xf86Msg(X_ERROR, "%s (%d): Open failed: %s\n", __FILE__, __LINE__, strerror(errno));
- return fd;
- } else
- return -1;
-}
-
-#define device_add(driver,device) do { \
- device->next = driver->devices; \
- driver->devices = device; \
-} while (0)
-
-typedef struct {
- evdevBitsRec bits;
- char name[256];
- char phys[256];
- char dev[256];
- struct input_id id;
-} evdevDevInfoRec, *evdevDevInfoPtr;
-
-static Bool
-MatchAll (unsigned long *dev, unsigned long *match, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- if ((dev[i] & match[i]) != match[i])
- return FALSE;
-
- return TRUE;
-}
-
-static Bool
-MatchNot (unsigned long *dev, unsigned long *match, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- if ((dev[i] & match[i]))
- return FALSE;
-
- return TRUE;
-}
-
-static Bool
-MatchAny (unsigned long *dev, unsigned long *match, int len)
-{
- int i, found = 0;
-
- for (i = 0; i < len; i++)
- if (match[i]) {
- found = 1;
- if ((dev[i] & match[i]))
- return TRUE;
- }
-
- if (found)
- return FALSE;
- else
- return TRUE;
-}
-
-/**
- * Compare various fields of the given driver to the matching fields of the
- * info struct. Fields include but are not limited to name, phys string and
- * device.
- * If this function returns TRUE, the given driver is responsible for the
- * device with the given info.
- *
- * @param driver One of the evdev drivers.
- * @param info Information obtained using ioctls on the device file.
- *
- * @return TRUE on match, FALSE otherwise.
- */
-static Bool
-MatchDriver (evdevDriverPtr driver, evdevDevInfoPtr info)
-{
- if (driver->name && fnmatch(driver->name, info->name, 0))
- return FALSE;
- if (driver->phys && fnmatch(driver->phys, info->phys, 0))
- return FALSE;
- if (driver->device && fnmatch(driver->device, info->dev, 0))
- return FALSE;
-
- if (driver->id.bustype && driver->id.bustype != info->id.bustype)
- return FALSE;
- if (driver->id.vendor && driver->id.vendor != info->id.vendor)
- return FALSE;
- if (driver->id.product && driver->id.product != info->id.product)
- return FALSE;
- if (driver->id.version && driver->id.version != info->id.version)
- return FALSE;
-
-#define match(which) \
- if (!MatchAll(info->bits.which, driver->all_bits.which, \
- sizeof(driver->all_bits.which) / \
- sizeof(driver->all_bits.which[0]))) \
- return FALSE; \
- if (!MatchNot(info->bits.which, driver->not_bits.which, \
- sizeof(driver->not_bits.which) / \
- sizeof(driver->not_bits.which[0]))) \
- return FALSE; \
- if (!MatchAny(info->bits.which, driver->any_bits.which, \
- sizeof(driver->any_bits.which) / \
- sizeof(driver->any_bits.which[0]))) \
- return FALSE;
-
- match(ev)
- match(key)
- match(rel)
- match(abs)
- match(msc)
- match(led)
- match(snd)
- match(ff)
-
-#undef match
-
- return TRUE;
-}
-
-/**
- * Compare various fields of the device with the given info.
- * If this function returns true, the device is identical to the device the
- * information was obtained from.
- *
- * @param device The device using some driver.
- * @param info Information obtained using ioctls on the device file.
- *
- * @return TRUE on match, FALSE otherwise.
- */
-static Bool
-MatchDevice (evdevDevicePtr device, evdevDevInfoPtr info)
-{
- int i, len;
-
- if (device->id.bustype != info->id.bustype)
- return FALSE;
- if (device->id.vendor != info->id.vendor)
- return FALSE;
- if (device->id.product != info->id.product)
- return FALSE;
- if (device->id.version != info->id.version)
- return FALSE;
-
- if (strcmp(device->name, info->name))
- return FALSE;
-
- len = sizeof(info->bits.ev) / sizeof(info->bits.ev[0]);
- for (i = 0; i < len; i++)
- if (device->bits.ev[i] != info->bits.ev[i])
- return FALSE;
-
- return TRUE;
-}
-
-/**
- * Figure out if the device has already been initialised previously. If so,
- * switch it on. If not, create a new device and call it's callback to set it
- * up.
- *
- * @param driver The driver responsible for the device.
- * @param info Information obtained using ioctls on the device file.
- *
- * @return TRUE if device was switched on or newly created. False if driver
- * and info are not matching.
- */
-static Bool
-evdevScanDevice (evdevDriverPtr driver, evdevDevInfoPtr info)
-{
- evdevDevicePtr device;
- int found;
-
- if (!MatchDriver (driver, info))
- return FALSE;
-
- found = 0;
- for (device = driver->devices; device; device = device->next) {
- if (MatchDevice (device, info)) {
- if (device->seen != (evdev_seq - 1)) {
- device->device = xstrdup(info->dev);
- device->phys = xstrdup(info->phys);
- device->callback(device->pInfo->dev, DEVICE_ON);
- }
-
- device->seen = evdev_seq;
-
- return TRUE;
- }
- }
-
- device = Xcalloc (sizeof (evdevDeviceRec));
-
- device->device = xstrdup(info->dev);
- device->name = xstrdup(info->name);
- device->phys = xstrdup(info->phys);
- device->id.bustype = info->id.bustype;
- device->id.vendor = info->id.vendor;
- device->id.product = info->id.product;
- device->id.version = info->id.version;
- device->seen = evdev_seq;
- device_add(driver, device);
- driver->callback(driver, device);
-
- return TRUE;
-}
-
-
-/**
- * Use various ioctls to get information about the given device file.
- * This information is used in evdevScanDevice, MatchDriver and MatchDevice.
- *
- * @param dev The device file to use.
- * @param info The struct to fill with the given info.
- */
-static Bool
-FillDevInfo (char *dev, evdevDevInfoPtr info)
-{
- int fd;
-
- SYSCALL(fd = open (dev, O_RDWR | O_NONBLOCK));
- if (fd == -1)
- return FALSE;
-
- if (ioctl(fd, EVIOCGNAME(sizeof(info->name)), info->name) == -1)
- info->name[0] = '\0';
- if (ioctl(fd, EVIOCGPHYS(sizeof(info->phys)), info->phys) == -1)
- info->phys[0] = '\0';
- if (ioctl(fd, EVIOCGID, &info->id) == -1) {
- close (fd);
- return FALSE;
- }
- if (!evdevGetBits (fd, &info->bits)) {
- close (fd);
- return FALSE;
- }
-
- strncpy (info->dev, dev, sizeof(info->dev));
- close (fd);
-
- return TRUE;
-}
-
-/**
- * Scan all /dev/input/event* devices. If a driver is available for one, try
- * to get a device going on it (either creating a new one or switching it on).
- * After the scan, switch off all devices that didn't get switched on in the
- * previous run through the device files.
- */
-static void
-evdevRescanDevices (InputInfoPtr pInfo)
-{
- char dev[20];
- int i, j, found;
- evdevDriverPtr driver;
- evdevDevicePtr device;
- evdevDevInfoRec info;
-
- evdev_seq++;
- xf86Msg(X_INFO, "%s: Rescanning devices (%d).\n", pInfo->name, evdev_seq);
-
- for (i = 0; i < 32; i++) {
- snprintf(dev, sizeof(dev), "/dev/input/event%d", i);
-
- if (!FillDevInfo (dev, &info))
- continue;
-
- found = 0;
-
- for (j = 0; j <= 3 && !found; j++) {
- for (driver = evdev_drivers; driver && !found; driver = driver->next) {
- if ((driver->pass == j) && (found = evdevScanDevice (driver, &info)))
- break;
- }
- }
- }
-
- for (driver = evdev_drivers; driver; driver = driver->next)
- for (device = driver->devices; device; device = device->next)
- if (device->seen == (evdev_seq - 1)) {
- device->callback(device->pInfo->dev, DEVICE_OFF);
-
- if (device->device)
- xfree(device->device);
- device->device = NULL;
-
- if (device->phys)
- xfree(device->phys);
- device->phys = NULL;
- }
-}
-
-static void
-evdevReadInput (InputInfoPtr 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, flags;
-
- pInfo = pPointer->public.devicePrivate;
-
- switch (what) {
- case DEVICE_INIT:
- pPointer->public.on = FALSE;
- 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.
- */
- 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 ((flags = fcntl(pInfo->fd, F_GETFL)) < 0) {
- xf86Msg(X_ERROR, "%s: Unable to NONBLOCK inotify, using fallback. "
- "(errno: %d)\n", pInfo->name, errno);
- evdev_inotify = 0;
- SYSCALL (close (pInfo->fd));
- pInfo->fd = -1;
- } else if (fcntl(pInfo->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
- xf86Msg(X_ERROR, "%s: Unable to NONBLOCK 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);
- pPointer->public.on = TRUE;
- evdevRescanDevices (pInfo);
- break;
-
- case DEVICE_OFF:
- case DEVICE_CLOSE:
- if (pInfo->fd != -1) {
- RemoveEnabledDevice(pInfo->fd);
- SYSCALL (close (pInfo->fd));
- pInfo->fd = -1;
- }
- pPointer->public.on = FALSE;
- break;
- }
- return Success;
-}
-
-/**
- * Start up the evdev brain device.
- * Without the brain device, evdev won't be of a lot of use, so if this method
- * fails you just shot yourself in the foot.
- *
- * If the evdev brain was already started up, this method returns TRUE.
- *
- * Returns TRUE on success or FALSE otherwise.
- */
-Bool
-evdevStart (InputDriverPtr drv)
-{
- InputInfoRec *pInfo;
-
- if (evdev_alive)
- return TRUE;
-
- if (!(pInfo = xf86AllocateInput(drv, 0)))
- return FALSE;
-
- evdev_alive = TRUE;
-
- pInfo->name = "evdev brain";
- pInfo->type_name = "evdev brain";
- pInfo->device_control = evdevControl;
- pInfo->read_input = evdevReadInput;
- pInfo->fd = -1;
- pInfo->flags = XI86_CONFIGURED | XI86_OPEN_ON_INIT;
-
- evdev_pInfo = pInfo;
- return TRUE;
-}
-
-/**
- * Prepend a new driver to the global driver list and rescan all devices.
- * evdevStart() must be called before.
- *
- * @param driver The new driver to be prepended
- *
- * @return TRUE on success or FALSE if the driver's callback wasn't setup.
- */
-Bool
-evdevNewDriver (evdevDriverPtr driver)
-{
- if (!evdev_alive)
- return FALSE;
- /* FIXME: Make this check valid given all the ways to look. */
-#if 0
- if (!(driver->name || driver->phys || driver->device))
- return FALSE;
-#endif
- if (!driver->callback)
- return FALSE;
-
- driver->next = evdev_drivers;
- evdev_drivers = driver;
-
- evdevRescanDevices (evdev_pInfo);
- driver->configured = TRUE;
- return TRUE;
-}
-
-/**
- * Search all drivers for the given device. If it exists, remove the device.
- * Note that this does not remove the driver, so after calling this function
- * with a valid device, there may be a driver without a device floating
- * around.
- *
- * @param pEvdev The device to remove.
- */
-void
-evdevRemoveDevice (evdevDevicePtr pEvdev)
-{
- evdevDriverPtr driver, prev;
- evdevDevicePtr *device;
-
- prev = evdev_drivers;
-
- for (driver = evdev_drivers; driver; prev = driver, driver = driver->next) {
- for (device = &driver->devices; *device; device = &(*device)->next) {
- if (*device == pEvdev) {
- *device = pEvdev->next;
- pEvdev->next = NULL;
- /* driver without device? get rid of it, otherwise it'll
- * auto-hotplug when a device is plugged in again.
- */
- if (!driver->devices)
- {
- evdevDeleteDevice(pEvdev);
- evdevRemoveDriver(driver);
- }
- return;
- }
- }
- }
-}
-
-/**
- * Obtain various information using ioctls on the given socket. This
- * information is used to determine if a device has axis, buttons or keys.
- *
- * @return TRUE on success or FALSE on error.
- */
-Bool
-evdevGetBits (int fd, evdevBitsPtr bits)
-{
-#define get_bitmask(fd, which, where) \
- if (ioctl(fd, EVIOCGBIT(which, sizeof (where)), where) < 0) { \
- xf86Msg(X_ERROR, "ioctl EVIOCGBIT %s failed: %s\n", #which, strerror(errno)); \
- return FALSE; \
- }
-
- get_bitmask (fd, 0, bits->ev);
- get_bitmask (fd, EV_KEY, bits->key);
- get_bitmask (fd, EV_REL, bits->rel);
- get_bitmask (fd, EV_ABS, bits->abs);
- get_bitmask (fd, EV_MSC, bits->msc);
- get_bitmask (fd, EV_LED, bits->led);
- get_bitmask (fd, EV_SND, bits->snd);
- get_bitmask (fd, EV_FF, bits->ff);
-
-#undef get_bitmask
-
- return TRUE;
-}
-
-/**
- * Free memory associated with device.
- */
-void
-evdevDeleteDevice(evdevDevicePtr pEvdev)
-{
- /* pEvdev->pInp is freed in xf86DeleteInput() when
- * DeleteInputDeviceRequest is called. */
- xfree(pEvdev->name);
- xfree(pEvdev->phys);
- xfree(pEvdev->device);
- xfree(pEvdev);
-}
-
-/**
- * Remove a driver from the list, free memory.
- */
-void evdevRemoveDriver(evdevDriverPtr drv)
-{
- evdevDriverPtr driver, prev;
- evdevDevicePtr device;
-
- if (drv == evdev_drivers)
- evdev_drivers = evdev_drivers->next;
- else
- for (prev = evdev_drivers, driver = prev->next; driver;
- prev = driver, driver = driver->next)
- {
- if (driver == drv)
- {
- prev->next = driver->next;
- }
- }
-
- xfree(drv->name);
- xfree(drv->phys);
- xfree(drv->device);
-
- device = drv->devices;
- while(device)
- {
- evdevDeleteDevice(device);
- device = device->next;
- }
-
- xfree(drv);
-}
-