aboutsummaryrefslogtreecommitdiff
path: root/src/evdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/evdev.c')
-rw-r--r--src/evdev.c133
1 files changed, 111 insertions, 22 deletions
diff --git a/src/evdev.c b/src/evdev.c
index 701fd03..fa5a1d9 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -62,7 +62,6 @@
#include <X11/extensions/XIproto.h>
#include <string.h>
-#include <errno.h>
/* The libc wrapper just blows... linux/input.h must be included
* before xf86_ansic.h and xf86_libc.h so we avoid defining ioctl
@@ -141,16 +140,19 @@ EvdevProc(DeviceIntPtr device, int what)
InputInfoPtr pInfo = device->public.devicePrivate;
evdevDevicePtr pEvdev = pInfo->private;
+ if (!pEvdev->device)
+ return BadRequest;
+
switch (what)
{
case DEVICE_INIT:
- if (pEvdev->state.abs_axes)
+ if (pEvdev->state.abs)
EvdevAbsInit (device);
- if (pEvdev->state.rel_axes)
+ if (pEvdev->state.rel)
EvdevRelInit (device);
- if (pEvdev->state.buttons)
+ if (pEvdev->state.btn)
EvdevBtnInit (device);
- if (pEvdev->state.keys)
+ if (pEvdev->state.key)
EvdevKeyInit (device);
xf86Msg(X_INFO, "%s: Init\n", pInfo->name);
break;
@@ -184,13 +186,13 @@ EvdevProc(DeviceIntPtr device, int what)
device->public.on = TRUE;
- if (pEvdev->state.abs_axes)
+ if (pEvdev->state.abs)
EvdevAbsOn (device);
- if (pEvdev->state.rel_axes)
+ if (pEvdev->state.rel)
EvdevRelOn (device);
- if (pEvdev->state.buttons)
+ if (pEvdev->state.btn)
EvdevBtnOn (device);
- if (pEvdev->state.keys)
+ if (pEvdev->state.key)
EvdevKeyOn (device);
break;
@@ -205,13 +207,13 @@ EvdevProc(DeviceIntPtr device, int what)
xf86RemoveSIGIOHandler (pInfo->fd);
close (pInfo->fd);
- if (pEvdev->state.abs_axes)
+ if (pEvdev->state.abs)
EvdevAbsOff (device);
- if (pEvdev->state.rel_axes)
+ if (pEvdev->state.rel)
EvdevRelOff (device);
- if (pEvdev->state.buttons)
+ if (pEvdev->state.btn)
EvdevBtnOff (device);
- if (pEvdev->state.keys)
+ if (pEvdev->state.key)
EvdevKeyOff (device);
}
@@ -233,7 +235,7 @@ EvdevSwitchMode (ClientPtr client, DeviceIntPtr device, int mode)
{
case Absolute:
case Relative:
- if (state->abs_axes)
+ if (state->abs)
state->mode = mode;
else
return !Success;
@@ -286,6 +288,14 @@ EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
return 0;
}
+ if (!evdevGetBits (pInfo->fd, &device->bits)) {
+ xf86Msg(X_ERROR, "%s: cannot load bits\n", pInfo->name);
+ pInfo->private = NULL;
+ close (pInfo->fd);
+ xf86DeleteInput (pInfo, 0);
+ return 0;
+ }
+
if (ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
xf86Msg(X_INFO, "%s: Unable to grab device (%s). Cowardly refusing to check use as keyboard.\n", pInfo->name, strerror(errno));
device->state.can_grab = 0;
@@ -294,6 +304,7 @@ EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
ioctl(pInfo->fd, EVIOCGRAB, (void *)0);
}
+
/* XXX: Note, the order of these is important. */
EvdevAbsNew (pInfo);
EvdevRelNew (pInfo);
@@ -308,6 +319,7 @@ EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
if (!(pInfo->flags & XI86_CONFIGURED)) {
xf86Msg(X_ERROR, "%s: Don't know how to use device.\n", pInfo->name);
pInfo->private = NULL;
+ close (pInfo->fd);
xf86DeleteInput (pInfo, 0);
return 0;
}
@@ -322,10 +334,59 @@ EvdevNew(evdevDriverPtr driver, evdevDevicePtr device)
return 1;
}
+static void
+EvdevParseBits (char *in, 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, long *all, long *not, 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;
+ }
+ }
+}
+
static InputInfoPtr
EvdevCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
{
evdevDriverPtr pEvdev;
+ char *opt, *tmp;
if (!(pEvdev = Xcalloc(sizeof(*pEvdev))))
return NULL;
@@ -333,20 +394,48 @@ EvdevCorePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
pEvdev->name = xf86CheckStrOption(dev->commonOptions, "Name", NULL);
pEvdev->phys = xf86CheckStrOption(dev->commonOptions, "Phys", NULL);
pEvdev->device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
- xf86Msg(X_ERROR, "%s: name: %s, phys: %s, device: %s.\n", dev->identifier,
- pEvdev->name, pEvdev->phys, pEvdev->device);
+
+#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 (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;
+
+
+ xf86Msg(X_CONFIG, "%s: name: %s, phys: %s, device: %s, pass: %d.\n",
+ dev->identifier, pEvdev->name, pEvdev->phys, pEvdev->device,
+ pEvdev->pass);
pEvdev->callback = EvdevNew;
pEvdev->dev = dev;
pEvdev->drv = drv;
- if (!pEvdev->name && !pEvdev->phys && !pEvdev->device) {
- xf86Msg(X_ERROR, "%s: No device identifiers specified.\n", dev->identifier);
- xfree(pEvdev);
- return NULL;
- }
-
if (!evdevStart (drv)) {
xf86Msg(X_ERROR, "%s: cannot start evdev brain.\n", dev->identifier);
xfree(pEvdev);