linux evdev: detect the button base instead of hardcoding 256

Some old USB devices report themselves as joysticks, which prompts linux
to start their button number from BN_JOYSTICK (0x120) instead of BN_MISC
(0x100). Spacenavd previously assumed the later and subtracted 256 from
button numbers, which causes an offset of 32 to all button events on the
Magellan SpaceMouse USB. This fix adds a bnbase field to the device
structure, which is detected and set automatically in the button
counting loop.
pull/65/head
John Tsiombikas 2022-08-26 17:16:59 +03:00
rodzic b6351158fa
commit 919a86f6b5
2 zmienionych plików z 11 dodań i 2 usunięć

Wyświetl plik

@ -36,6 +36,7 @@ struct device {
unsigned int flags;
int num_axes, num_buttons;
int bnbase; /* button base (reported number of first button) */
int *minval, *maxval; /* input value range (default: -500, 500) */
int *fuzz; /* noise threshold */

Wyświetl plik

@ -127,6 +127,7 @@ int open_dev_usb(struct device *dev)
}
/* get number of buttons */
dev->bnbase = -1;
dev->num_buttons = 0;
if(ioctl(dev->fd, EVIOCGBIT(EV_KEY, sizeof evtype_mask), evtype_mask) != -1) {
for(i=0; i<KEY_CNT; i++) {
@ -134,6 +135,9 @@ int open_dev_usb(struct device *dev)
int bit = i % 8;
if(evtype_mask[idx] & (1 << bit)) {
if(dev->bnbase < 0) {
dev->bnbase = idx * 8 + bit;
}
dev->num_buttons++;
}
}
@ -141,6 +145,10 @@ int open_dev_usb(struct device *dev)
logmsg(LOG_DEBUG, "EVIOCGBIT(EV_KEY) ioctl failed: %s\n", strerror(errno));
}
if(dev->bnbase == -1) {
dev->bnbase = 0;
}
/* sanity check, problematic devices appear to report 256 buttons, if that's
* not the case, this is probably a mistake.
*/
@ -177,7 +185,7 @@ int open_dev_usb(struct device *dev)
dev->num_buttons = 2;
} else {
if(verbose) {
logmsg(LOG_INFO, " Number of buttons: %d\n", dev->num_buttons);
logmsg(LOG_INFO, " Number of buttons: %d (evdev offset: %d)\n", dev->num_buttons, dev->bnbase);
}
}
@ -312,7 +320,7 @@ static int read_evdev(struct device *dev, struct dev_input *inp)
return -1;
}
} else {
inp->idx = iev.code - BTN_0;
inp->idx = iev.code - dev->bnbase;
}
inp->val = iev.value;
/*logmsg(LOG_DEBUG, "EV_KEY c:%d (%d) v:%d\n", iev.code, inp->idx, iev.value);*/