[PATCH] Fix FOO_MAX off-by-one
Matt Helsley
matt.helsley at gmail.com
Sun Jan 11 18:36:59 PST 2009
In linux/input.h each section's (e.g. ABS) FOO_MAX is the maximum FOO
value. Recent kernels define FOO_CNT as the maximum number of FOO there
will ever be. Hence using FOO_MAX to size the bit vectors representing
the capabilities of an evdev device is off by one.
Define FOO_CNT values for use with Linux kernels which lack them. Use
FOO_CNT whenever we need to know the number of bits needed -- usually to
calculate the number of longs needed.
When iterating over the values FOO_MAX still seems appropriate however
the loop test should include FOO_MAX rather than skip it.
Signed-off-by: Matt Helsley <matt.helsley at gmail.com>
---
src/evdev.c | 24 ++++++++++++------------
src/evdev.h | 28 ++++++++++++++++++++++------
2 files changed, 34 insertions(+), 18 deletions(-)
Index: xf86-input-evdev/src/evdev.c
===================================================================
--- xf86-input-evdev.orig/src/evdev.c
+++ xf86-input-evdev/src/evdev.c
@@ -234,18 +234,18 @@ PostButtonClicks(InputInfoPtr pInfo, int
static void
PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
{
int code = ev->code + MIN_KEYCODE;
- static char warned[KEY_MAX];
+ static char warned[KEY_CNT];
/* Filter all repeated events from device.
We'll do softrepeat in the server */
if (value == 2)
return;
- if (code > 255 && ev->code < KEY_MAX) {
+ if (code > 255 && ev->code <= KEY_MAX) {
if (!warned[ev->code])
xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
pInfo->name, ev->code);
warned[ev->code] = 1;
}
@@ -1221,16 +1221,16 @@ EvdevCacheCompare(InputInfoPtr pInfo, BO
{
EvdevPtr pEvdev = pInfo->private;
int i;
char name[1024] = {0};
- long bitmask[NLONGS(EV_MAX)] = {0};
- long key_bitmask[NLONGS(KEY_MAX)] = {0};
- long rel_bitmask[NLONGS(REL_MAX)] = {0};
- long abs_bitmask[NLONGS(ABS_MAX)] = {0};
- long led_bitmask[NLONGS(LED_MAX)] = {0};
- struct input_absinfo absinfo[ABS_MAX];
+ long bitmask[NLONGS(EV_CNT)] = {0};
+ long key_bitmask[NLONGS(KEY_CNT)] = {0};
+ long rel_bitmask[NLONGS(REL_CNT)] = {0};
+ long abs_bitmask[NLONGS(ABS_CNT)] = {0};
+ long led_bitmask[NLONGS(LED_CNT)] = {0};
+ struct input_absinfo absinfo[ABS_CNT];
if (ioctl(pInfo->fd,
EVIOCGNAME(sizeof(name) - 1), name) < 0) {
xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
goto error;
@@ -1285,11 +1285,11 @@ EvdevCacheCompare(InputInfoPtr pInfo, BO
if (compare && memcmp(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask)))
goto error;
memset(absinfo, 0, sizeof(absinfo));
- for (i = 0; i < ABS_MAX; i++)
+ for (i = ABS_X; i <= ABS_MAX; i++)
{
if (TestBit(i, abs_bitmask))
{
if (ioctl(pInfo->fd, EVIOCGABS(i), &absinfo[i]) < 0) {
xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno));
@@ -1321,13 +1321,13 @@ error:
}
static int
EvdevProbe(InputInfoPtr pInfo)
{
- long key_bitmask[NLONGS(KEY_MAX)] = {0};
- long rel_bitmask[NLONGS(REL_MAX)] = {0};
- long abs_bitmask[NLONGS(ABS_MAX)] = {0};
+ long key_bitmask[NLONGS(KEY_CNT)] = {0};
+ long rel_bitmask[NLONGS(REL_CNT)] = {0};
+ long abs_bitmask[NLONGS(ABS_CNT)] = {0};
int i, has_axes, has_keys, num_buttons, has_scroll;
int kernel24 = 0;
EvdevPtr pEvdev = pInfo->private;
if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
Index: xf86-input-evdev/src/evdev.h
===================================================================
--- xf86-input-evdev.orig/src/evdev.h
+++ xf86-input-evdev/src/evdev.h
@@ -38,10 +38,26 @@
#ifdef XKB
#include <xkbstr.h>
#endif
+#ifndef EV_CNT /* linux 2.4 kernels and earlier lack _CNT defines */
+#define EV_CNT (EV_MAX+1)
+#endif
+#ifndef KEY_CNT
+#define KEY_CNT (KEY_MAX+1)
+#endif
+#ifndef REL_CNT
+#define REL_CNT (REL_MAX+1)
+#endif
+#ifndef ABS_CNT
+#define ABS_CNT (ABS_MAX+1)
+#endif
+#ifndef LED_CNT
+#define LED_CNT (LED_MAX+1)
+#endif
+
#define EVDEV_MAXBUTTONS 32
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
#define HAVE_PROPERTIES 1
#endif
@@ -121,16 +137,16 @@ typedef struct {
int reopen_left; /* number of attempts left to re-open the device */
OsTimerPtr reopen_timer;
/* Cached info from device. */
char name[1024];
- long bitmask[NLONGS(EV_MAX)];
- long key_bitmask[NLONGS(KEY_MAX)];
- long rel_bitmask[NLONGS(REL_MAX)];
- long abs_bitmask[NLONGS(ABS_MAX)];
- long led_bitmask[NLONGS(LED_MAX)];
- struct input_absinfo absinfo[ABS_MAX];
+ long bitmask[NLONGS(EV_CNT)];
+ long key_bitmask[NLONGS(KEY_CNT)];
+ long rel_bitmask[NLONGS(REL_CNT)];
+ long abs_bitmask[NLONGS(ABS_CNT)];
+ long led_bitmask[NLONGS(LED_CNT)];
+ struct input_absinfo absinfo[ABS_CNT];
/* minor/major number */
dev_t min_maj;
} EvdevRec, *EvdevPtr;
More information about the xorg
mailing list