From 620127d5b97c67f6c7f35e42f9e190278fd64e19 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 11 Feb 2013 16:45:24 -0800 Subject: [PATCH] Fix for dropped joystick events contributed by Simon In my system SDL2 is dropping a chunk of joystick events, which result in a 'stuck brake/accelerator' whilst playing a racing simulator. This basically means SDL2 is unsuitable for use at this point... The patch below detects this situation and forces a re-read of all attached joystick axis - thus resync to the correct/current pedal positions. --- src/joystick/linux/SDL_sysjoystick.c | 57 ++++++++++++++++++++++++++ src/joystick/linux/SDL_sysjoystick_c.h | 4 ++ 2 files changed, 61 insertions(+) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 4ef9bfba2..74e3c1aa9 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -763,6 +763,9 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) /* Get the number of buttons and axes on the joystick */ ConfigJoystick(joystick, fd); + // mark joystick as fresh and ready + joystick->hwdata->fresh = 1; + return (0); } @@ -833,6 +836,44 @@ AxisCorrect(SDL_Joystick * joystick, int which, int value) return value; } +static __inline__ void +PollAllValues(SDL_Joystick * joystick) +{ + struct input_absinfo absinfo; + int a, b = 0; + + // Poll all axis + for (a = ABS_X; b < ABS_MAX; a++) { + switch (a) { + case ABS_HAT0X: + case ABS_HAT0Y: + case ABS_HAT1X: + case ABS_HAT1Y: + case ABS_HAT2X: + case ABS_HAT2Y: + case ABS_HAT3X: + case ABS_HAT3Y: + // ingore hats + break; + default: + if (joystick->hwdata->abs_correct[b].used) { + if (ioctl(joystick->hwdata->fd, EVIOCGABS(a), &absinfo) >= 0) { + absinfo.value = AxisCorrect(joystick, b, absinfo.value); + +#ifdef DEBUG_INPUT_EVENTS + printf("Joystick : Re-read Axis %d (%d) val= %d\n", + joystick->hwdata->abs_map[b], a, absinfo.value); +#endif + SDL_PrivateJoystickAxis(joystick, + joystick->hwdata->abs_map[b], + absinfo.value); + } + } + b++; + } + } +} + static __inline__ void HandleInputEvents(SDL_Joystick * joystick) { @@ -840,6 +881,11 @@ HandleInputEvents(SDL_Joystick * joystick) int i, len; int code; + if (joystick->hwdata->fresh) { + PollAllValues(joystick); + joystick->hwdata->fresh = 0; + } + while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) { len /= sizeof(events[0]); for (i = 0; i < len; ++i) { @@ -890,6 +936,17 @@ HandleInputEvents(SDL_Joystick * joystick) break; } break; + case EV_SYN: + switch (code) { + case SYN_DROPPED : +#ifdef DEBUG_INPUT_EVENTS + printf("Event SYN_DROPPED dectected\n"); +#endif + PollAllValues(joystick); + break; + default: + break; + } default: break; } diff --git a/src/joystick/linux/SDL_sysjoystick_c.h b/src/joystick/linux/SDL_sysjoystick_c.h index cf34c851f..cf45c1e08 100644 --- a/src/joystick/linux/SDL_sysjoystick_c.h +++ b/src/joystick/linux/SDL_sysjoystick_c.h @@ -50,4 +50,8 @@ struct joystick_hwdata int used; int coef[3]; } abs_correct[ABS_MAX]; + + int fresh; }; + +/* vi: set ts=4 sw=4 expandtab: */