Turn off rumble on drivers which don't respect the replay.length value
authorSam Lantinga <slouken@libsdl.org>
Thu, 23 Jan 2020 12:53:39 -0800
changeset 13442d885f6cfea3b
parent 13441 96fb90f42bb5
child 13443 93fcc499b16f
Turn off rumble on drivers which don't respect the replay.length value
src/joystick/linux/SDL_sysjoystick.c
src/joystick/linux/SDL_sysjoystick_c.h
     1.1 --- a/src/joystick/linux/SDL_sysjoystick.c	Thu Jan 23 01:03:23 2020 -0800
     1.2 +++ b/src/joystick/linux/SDL_sysjoystick.c	Thu Jan 23 12:53:39 2020 -0800
     1.3 @@ -803,16 +803,30 @@
     1.4      return (0);
     1.5  }
     1.6  
     1.7 +#define MAX_KERNEL_RUMBLE_DURATION_MS  0xFFFF
     1.8 +
     1.9  static int
    1.10  LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
    1.11  {
    1.12      struct input_event event;
    1.13  
    1.14 +    if (duration_ms > MAX_KERNEL_RUMBLE_DURATION_MS) {
    1.15 +        duration_ms = MAX_KERNEL_RUMBLE_DURATION_MS;
    1.16 +    }
    1.17 +    if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
    1.18 +        joystick->hwdata->effect_expiration = SDL_GetTicks() + duration_ms;
    1.19 +        if (!joystick->hwdata->effect_expiration) {
    1.20 +            joystick->hwdata->effect_expiration = 1;
    1.21 +        }
    1.22 +    } else {
    1.23 +        joystick->hwdata->effect_expiration = 0;
    1.24 +    }
    1.25 +
    1.26      if (joystick->hwdata->ff_rumble) {
    1.27          struct ff_effect *effect = &joystick->hwdata->effect;
    1.28  
    1.29          effect->type = FF_RUMBLE;
    1.30 -        effect->replay.length = SDL_min(duration_ms, 32767);
    1.31 +        effect->replay.length = duration_ms;
    1.32          effect->u.rumble.strong_magnitude = low_frequency_rumble;
    1.33          effect->u.rumble.weak_magnitude = high_frequency_rumble;
    1.34      } else if (joystick->hwdata->ff_sine) {
    1.35 @@ -821,7 +835,7 @@
    1.36          struct ff_effect *effect = &joystick->hwdata->effect;
    1.37  
    1.38          effect->type = FF_PERIODIC;
    1.39 -        effect->replay.length = SDL_min(duration_ms, 32767);
    1.40 +        effect->replay.length = duration_ms;
    1.41          effect->u.periodic.waveform = FF_SINE;
    1.42          effect->u.periodic.magnitude = magnitude;
    1.43      } else {
    1.44 @@ -1038,6 +1052,13 @@
    1.45              SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
    1.46          }
    1.47      }
    1.48 +
    1.49 +    if (joystick->hwdata->effect_expiration) {
    1.50 +        Uint32 now = SDL_GetTicks();
    1.51 +        if (SDL_TICKS_PASSED(now, joystick->hwdata->effect_expiration)) {
    1.52 +            LINUX_JoystickRumble(joystick, 0, 0, 0);
    1.53 +        }
    1.54 +    }
    1.55  }
    1.56  
    1.57  /* Function to close a joystick after use */
    1.58 @@ -1045,6 +1066,9 @@
    1.59  LINUX_JoystickClose(SDL_Joystick * joystick)
    1.60  {
    1.61      if (joystick->hwdata) {
    1.62 +        if (joystick->hwdata->effect_expiration) {
    1.63 +            LINUX_JoystickRumble(joystick, 0, 0, 0);
    1.64 +        }
    1.65          if (joystick->hwdata->effect.id >= 0) {
    1.66              ioctl(joystick->hwdata->fd, EVIOCRMFF, joystick->hwdata->effect.id);
    1.67              joystick->hwdata->effect.id = -1;
     2.1 --- a/src/joystick/linux/SDL_sysjoystick_c.h	Thu Jan 23 01:03:23 2020 -0800
     2.2 +++ b/src/joystick/linux/SDL_sysjoystick_c.h	Thu Jan 23 12:53:39 2020 -0800
     2.3 @@ -37,6 +37,7 @@
     2.4      SDL_bool ff_rumble;
     2.5      SDL_bool ff_sine;
     2.6      struct ff_effect effect;
     2.7 +    Uint32 effect_expiration;
     2.8  
     2.9      /* The current Linux joystick driver maps hats to two axes */
    2.10      struct hwdata_hat