Fixed bug 3021 - HapticOpenFromJoystick() problems
authorSam Lantinga <slouken@libsdl.org>
Tue, 04 Oct 2016 03:50:28 -0700
changeset 10463ac6a748250f4
parent 10462 197d526cd22d
child 10464 ec4945e3e49f
Fixed bug 3021 - HapticOpenFromJoystick() problems

Joe Thompson

With Direct Input device (MOMO Steering Wheel w/FF)
with SDL 2.0.3,
SDL_HapticOpenFromJoystick() would fail. (Can't set exclusive mode)
Now with 2.0.4 rc1,
SDL_HapticOpenFromJoystick() succeeds but the the returned SDL_Haptic* cannot be used. Calls to SDL_HapticNewEffect() fail with "Haptic error Unable to create effect"

If SDL_HapticOpen() is used instead of HapticOpenFromJoystick(), the device is usable. Calls to HapticNewEffect() succeed with the exact same parameters as the previous failing call.

I have attached a proposed patch for this issue.

When using SDL_HapticOpenFromJoystick(), the original code did not (re)enumerate the axes. This returned a new haptic device with 0 axes. Later, when a new effect is created, SDL_SYS_SetDirection() would set the flags to include DIEFF_SPHERICAL, regardless of what the caller actually set. (see Line 566 in SDL_dinputhaptic.c). This would cause the SDL_HapticNewEffect() to fail (or interpret the coordinates incorreclty.)

The patch moves the call to IDirectInputDevice8_EnumObjects() outside of the if() block so that the axes are (re)enumerated for the new haptic device.

Note: For steering wheels it is common for the joystick to have multiple axes (ie steering, throttle, brake), but the haptic portion of the joystick usually only applies to steering.
src/haptic/windows/SDL_dinputhaptic.c
     1.1 --- a/src/haptic/windows/SDL_dinputhaptic.c	Tue Oct 04 03:42:42 2016 -0700
     1.2 +++ b/src/haptic/windows/SDL_dinputhaptic.c	Tue Oct 04 03:50:28 2016 -0700
     1.3 @@ -331,14 +331,6 @@
     1.4              goto acquire_err;
     1.5          }
     1.6  
     1.7 -        /* Get number of axes. */
     1.8 -        ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
     1.9 -                                              DI_DeviceObjectCallback,
    1.10 -                                              haptic, DIDFT_AXIS);
    1.11 -        if (FAILED(ret)) {
    1.12 -            DI_SetError("Getting device axes", ret);
    1.13 -            goto acquire_err;
    1.14 -        }
    1.15  
    1.16          /* Acquire the device. */
    1.17          ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
    1.18 @@ -348,6 +340,15 @@
    1.19          }
    1.20      }
    1.21  
    1.22 +    /* Get number of axes. */
    1.23 +    ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
    1.24 +                                          DI_DeviceObjectCallback,
    1.25 +                                          haptic, DIDFT_AXIS);
    1.26 +    if (FAILED(ret)) {
    1.27 +        DI_SetError("Getting device axes", ret);
    1.28 +        goto acquire_err;
    1.29 +    }
    1.30 +
    1.31      /* Reset all actuators - just in case. */
    1.32      ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
    1.33                                                         DISFFC_RESET);