Skip to content

Commit 32b6590

Browse files
committed
Add support for new EV_BTN event in linux joystick
Adds support for new EV_BTN event that'll be used in place of EV_KEY for joysticks and maybe gamepads. This event doesn't require any mapping as it simply passes through button number as the code (starting from 1 just like HID) and it's value. It was needed to cleanly support joysticks and simracing/simflight hardware that defines more than 80 buttons. Some HW used hacks in the drivers that assigned random usages found lower than TRIGGER_HAPPPY range.
1 parent 504041a commit 32b6590

File tree

3 files changed

+56
-14
lines changed

3 files changed

+56
-14
lines changed

src/core/linux/SDL_evdev_capabilities.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#ifndef KEY_ALS_TOGGLE
3636
#define KEY_ALS_TOGGLE 0x230
3737
#endif
38+
#ifndef EV_BTN
39+
#define EV_BTN 0x06
40+
#endif
3841

3942
extern int
4043
SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)],
@@ -58,6 +61,11 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA
5861
int devclass = 0;
5962
unsigned long keyboard_mask;
6063

64+
// Only Joysticks (and maybe gamepads) have generic buttons
65+
if (test_bit(EV_BTN, bitmask_ev)) {
66+
return SDL_UDEV_DEVICE_JOYSTICK;
67+
}
68+
6169
// If the kernel specifically says it's an accelerometer, believe it
6270
if (test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props)) {
6371
return SDL_UDEV_DEVICE_ACCELEROMETER;

src/joystick/linux/SDL_sysjoystick.c

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@
5757
#ifndef SYN_DROPPED
5858
#define SYN_DROPPED 3
5959
#endif
60+
#ifndef EV_BTN
61+
#define EV_BTN 0x06
62+
#define EVIOCGBTNCNT 0
63+
#endif
6064
#ifndef BTN_NORTH
6165
#define BTN_NORTH 0x133
6266
#endif
@@ -1225,6 +1229,7 @@ static bool GuessIfAxesAreDigitalHat(struct input_absinfo *absinfo_x, struct inp
12251229
static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor)
12261230
{
12271231
int i, t;
1232+
unsigned long evbit[NBITS(EV_MAX)] = { 0 };
12281233
unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
12291234
unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
12301235
unsigned long relbit[NBITS(REL_MAX)] = { 0 };
@@ -1238,27 +1243,40 @@ static void ConfigJoystick(SDL_Joystick *joystick, int fd, int fd_sensor)
12381243
// See if this device uses the new unified event API
12391244
if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
12401245
(ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
1241-
(ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
1246+
(ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0) &&
1247+
(ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) >= 0) ) {
12421248

12431249
// Get the number of buttons, axes, and other thingamajigs
1244-
for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
1245-
if (test_bit(i, keybit)) {
1250+
if (test_bit(EV_BTN, evbit)) {
1251+
unsigned int button_count;
1252+
if(ioctl(fd, EVIOCGBTNCNT, &button_count) == 0) {
1253+
joystick->hwdata->ev_btn = true;
1254+
joystick->nbuttons = button_count;
12461255
#ifdef DEBUG_INPUT_EVENTS
1247-
SDL_Log("Joystick has button: 0x%x", i);
1256+
SDL_Log("Joystick has %u buttons", button_count);
12481257
#endif
1249-
joystick->hwdata->key_map[i] = joystick->nbuttons;
1250-
joystick->hwdata->has_key[i] = true;
1251-
++joystick->nbuttons;
12521258
}
12531259
}
1254-
for (i = 0; i < BTN_JOYSTICK; ++i) {
1255-
if (test_bit(i, keybit)) {
1260+
if (!joystick->hwdata->ev_btn) {
1261+
for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
1262+
if (test_bit(i, keybit)) {
12561263
#ifdef DEBUG_INPUT_EVENTS
1257-
SDL_Log("Joystick has button: 0x%x", i);
1264+
SDL_Log("Joystick has button: 0x%x", i);
12581265
#endif
1259-
joystick->hwdata->key_map[i] = joystick->nbuttons;
1260-
joystick->hwdata->has_key[i] = true;
1261-
++joystick->nbuttons;
1266+
joystick->hwdata->key_map[i] = joystick->nbuttons;
1267+
joystick->hwdata->has_key[i] = true;
1268+
++joystick->nbuttons;
1269+
}
1270+
}
1271+
for (i = 0; i < BTN_JOYSTICK; ++i) {
1272+
if (test_bit(i, keybit)) {
1273+
#ifdef DEBUG_INPUT_EVENTS
1274+
SDL_Log("Joystick has button: 0x%x", i);
1275+
#endif
1276+
joystick->hwdata->key_map[i] = joystick->nbuttons;
1277+
joystick->hwdata->has_key[i] = true;
1278+
++joystick->nbuttons;
1279+
}
12621280
}
12631281
}
12641282
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
@@ -1860,7 +1878,8 @@ static void PollAllValues(Uint64 timestamp, SDL_Joystick *joystick)
18601878

18611879
// Poll all buttons
18621880
SDL_zeroa(keyinfo);
1863-
if (ioctl(joystick->hwdata->fd, EVIOCGKEY(sizeof(keyinfo)), keyinfo) >= 0) {
1881+
if (ioctl(joystick->hwdata->fd, EVIOCGKEY(sizeof(keyinfo)), keyinfo) >= 0 &&
1882+
!joystick->hwdata->ev_btn) {
18641883
for (i = 0; i < KEY_MAX; i++) {
18651884
if (joystick->hwdata->has_key[i]) {
18661885
bool down = test_bit(i, keyinfo);
@@ -1963,7 +1982,18 @@ static void HandleInputEvents(SDL_Joystick *joystick)
19631982
}
19641983

19651984
switch (event->type) {
1985+
case EV_BTN:
1986+
if (!joystick->hwdata->ev_btn)
1987+
break;
1988+
#ifdef DEBUG_INPUT_EVENTS
1989+
SDL_Log("Button %u %s", code, event->value ? "PRESSED" : "RELEASED");
1990+
#endif
1991+
SDL_SendJoystickButton(SDL_EVDEV_GetEventTimestamp(event), joystick,
1992+
code - 1, (event->value != 0));
1993+
break;
19661994
case EV_KEY:
1995+
if (joystick->hwdata->ev_btn)
1996+
break;
19671997
#ifdef DEBUG_INPUT_EVENTS
19681998
SDL_Log("Key 0x%.2x %s", code, event->value ? "PRESSED" : "RELEASED");
19691999
#endif
@@ -2061,6 +2091,7 @@ static void HandleInputEvents(SDL_Joystick *joystick)
20612091
}
20622092

20632093
switch (event->type) {
2094+
case EV_BTN:
20642095
case EV_KEY:
20652096
SDL_assert(0);
20662097
break;

src/joystick/linux/SDL_sysjoystick_c.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ struct joystick_hwdata
6363
bool has_accelerometer;
6464
bool has_gyro;
6565

66+
// Use EV_BTN instead of EV_KEY
67+
bool ev_btn;
68+
6669
// Support for the classic joystick interface
6770
bool classic;
6871
Uint16 *key_pam;

0 commit comments

Comments
 (0)