diff options
author | Zephaniah E. Hull <warp@agamemnon.b5> | 2007-04-24 06:49:11 -0400 |
---|---|---|
committer | Zephaniah E. Hull <warp@agamemnon.b5> | 2007-04-24 06:49:11 -0400 |
commit | a0ea7363f51ff6c2bb81006b7220b7daa9ee9221 (patch) | |
tree | 6766bbe03cf96f91c7a799612a0bdb6dab033d4a /src | |
parent | Updated configure to 1.2.0, no changes yet. (diff) | |
download | xf86-input-evdev-a0ea7363f51ff6c2bb81006b7220b7daa9ee9221.tar.gz xf86-input-evdev-a0ea7363f51ff6c2bb81006b7220b7daa9ee9221.tar.bz2 xf86-input-evdev-a0ea7363f51ff6c2bb81006b7220b7daa9ee9221.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/evdev.c | 228 | ||||
-rw-r--r-- | src/evdev.h | 79 | ||||
-rw-r--r-- | src/evdev_brain.c | 658 |
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); -} - |