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 <[email protected]> --- 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; _______________________________________________ xorg mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/xorg
