Replaced SDL_HAPTIC_SQUARE with SDL_HAPTIC_LEFTRIGHT.
authorRyan C. Gordon <icculus@icculus.org>
Sat, 10 Aug 2013 13:38:09 -0400
changeset 76215caa5fb3deb6
parent 7620 c99a31e02b7a
child 7622 d758150805de
Replaced SDL_HAPTIC_SQUARE with SDL_HAPTIC_LEFTRIGHT.

We needed a bit, so we're hoping no one needs this effect, especially when
it's fairly close to SDL_HAPTIC_SINE, we hope.

SDL_HAPTIC_LEFTRIGHT maps to XInput's functionality, so this removes the SINE
code for the XInput driver to keep things clean.

This also makes the simplified Rumble API use SDL_HAPTIC_LEFTRIGHT if
SDL_HAPTIC_SINE isn't available, to keep XInput working.

When we break the ABI, and can extend the supported capabilities field from
a Uint16, we'll add SDL_HAPTIC_SQUARE back in.

This patch is based on work by Ethan Lee.
include/SDL_haptic.h
src/haptic/SDL_haptic.c
src/haptic/darwin/SDL_syshaptic.c
src/haptic/linux/SDL_syshaptic.c
src/haptic/windows/SDL_syshaptic.c
test/testhaptic.c
     1.1 --- a/include/SDL_haptic.h	Sat Aug 10 13:20:45 2013 -0400
     1.2 +++ b/include/SDL_haptic.h	Sat Aug 10 13:38:09 2013 -0400
     1.3 @@ -166,13 +166,18 @@
     1.4  #define SDL_HAPTIC_SINE       (1<<1)
     1.5  
     1.6  /**
     1.7 - *  \brief Square wave effect supported.
     1.8 + *  \brief Left/Right effect supported.
     1.9   *
    1.10 - *  Periodic haptic effect that simulates square waves.
    1.11 + *  Haptic effect for direct control over high/low frequency motors.
    1.12   *
    1.13 - *  \sa SDL_HapticPeriodic
    1.14 + *  \sa SDL_HapticLeftRight
    1.15 + * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
    1.16 + *          we ran out of bits, and this is important for XInput devices.
    1.17   */
    1.18 -#define SDL_HAPTIC_SQUARE     (1<<2)
    1.19 +#define SDL_HAPTIC_LEFTRIGHT     (1<<2)
    1.20 +
    1.21 +/* !!! FIXME: put this back when we have more bits in 2.1 */
    1.22 +/*#define SDL_HAPTIC_SQUARE     (1<<2)*/
    1.23  
    1.24  /**
    1.25   *  \brief Triangle wave effect supported.
    1.26 @@ -646,6 +651,31 @@
    1.27  } SDL_HapticRamp;
    1.28  
    1.29  /**
    1.30 + * \brief A structure containing a template for a Left/Right effect.
    1.31 + *
    1.32 + * This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect.
    1.33 + *
    1.34 + * The Left/Right effect is used to explicitly control the large and small
    1.35 + * motors, commonly found in modern game controllers. One motor is high
    1.36 + * frequency, the other is low frequency.
    1.37 + *
    1.38 + * \sa SDL_HAPTIC_LEFTRIGHT
    1.39 + * \sa SDL_HapticEffect
    1.40 + */
    1.41 +typedef struct SDL_HapticLeftRight
    1.42 +{
    1.43 +    /* Header */
    1.44 +    Uint16 type;            /**< ::SDL_HAPTIC_LEFTRIGHT */
    1.45 +
    1.46 +    /* Replay */
    1.47 +    Uint32 length;          /**< Duration of the effect. */
    1.48 +
    1.49 +    /* Rumble */
    1.50 +    Uint16 large_magnitude; /**< Control of the large controller motor. */
    1.51 +    Uint16 small_magnitude; /**< Control of the small controller motor. */
    1.52 +} SDL_HapticLeftRight;
    1.53 +
    1.54 +/**
    1.55   *  \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect.
    1.56   *
    1.57   *  A custom force feedback effect is much like a periodic effect, where the
    1.58 @@ -751,6 +781,7 @@
    1.59   *  \sa SDL_HapticPeriodic
    1.60   *  \sa SDL_HapticCondition
    1.61   *  \sa SDL_HapticRamp
    1.62 + *  \sa SDL_HapticLeftRight
    1.63   *  \sa SDL_HapticCustom
    1.64   */
    1.65  typedef union SDL_HapticEffect
    1.66 @@ -761,6 +792,7 @@
    1.67      SDL_HapticPeriodic periodic;    /**< Periodic effect. */
    1.68      SDL_HapticCondition condition;  /**< Condition effect. */
    1.69      SDL_HapticRamp ramp;            /**< Ramp effect. */
    1.70 +    SDL_HapticLeftRight leftright;  /**< Left/Right effect. */
    1.71      SDL_HapticCustom custom;        /**< Custom effect. */
    1.72  } SDL_HapticEffect;
    1.73  
    1.74 @@ -1182,8 +1214,6 @@
    1.75   */
    1.76  extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic);
    1.77  
    1.78 -
    1.79 -
    1.80  /* Ends C function definitions when using C++ */
    1.81  #ifdef __cplusplus
    1.82  }
     2.1 --- a/src/haptic/SDL_haptic.c	Sat Aug 10 13:20:45 2013 -0400
     2.2 +++ b/src/haptic/SDL_haptic.c	Sat Aug 10 13:38:09 2013 -0400
     2.3 @@ -23,7 +23,7 @@
     2.4  #include "SDL_syshaptic.h"
     2.5  #include "SDL_haptic_c.h"
     2.6  #include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */
     2.7 -
     2.8 +#include "SDL_assert.h"
     2.9  
    2.10  Uint8 SDL_numhaptics = 0;
    2.11  SDL_Haptic **SDL_haptics = NULL;
    2.12 @@ -723,32 +723,18 @@
    2.13      return SDL_SYS_HapticStopAll(haptic);
    2.14  }
    2.15  
    2.16 -static void
    2.17 -SDL_HapticRumbleCreate(SDL_HapticEffect * efx)
    2.18 -{
    2.19 -   SDL_memset(efx, 0, sizeof(SDL_HapticEffect));
    2.20 -   efx->type = SDL_HAPTIC_SINE;
    2.21 -   efx->periodic.period = 1000;
    2.22 -   efx->periodic.magnitude = 0x4000;
    2.23 -   efx->periodic.length = 5000;
    2.24 -   efx->periodic.attack_length = 0;
    2.25 -   efx->periodic.fade_length = 0;
    2.26 -}
    2.27 -
    2.28  /*
    2.29   * Checks to see if rumble is supported.
    2.30   */
    2.31  int
    2.32  SDL_HapticRumbleSupported(SDL_Haptic * haptic)
    2.33  {
    2.34 -    SDL_HapticEffect efx;
    2.35 -
    2.36      if (!ValidHaptic(haptic)) {
    2.37          return -1;
    2.38      }
    2.39  
    2.40 -    SDL_HapticRumbleCreate(&efx);
    2.41 -    return SDL_HapticEffectSupported(haptic, &efx);
    2.42 +    /* Most things can use SINE, but XInput only has LEFTRIGHT. */
    2.43 +    return ((haptic->supported & (SDL_HAPTIC_SINE|SDL_HAPTIC_LEFTRIGHT)) != 0);
    2.44  }
    2.45  
    2.46  /*
    2.47 @@ -757,6 +743,8 @@
    2.48  int
    2.49  SDL_HapticRumbleInit(SDL_Haptic * haptic)
    2.50  {
    2.51 +    SDL_HapticEffect *efx = &haptic->rumble_effect;
    2.52 +
    2.53      if (!ValidHaptic(haptic)) {
    2.54          return -1;
    2.55      }
    2.56 @@ -766,8 +754,23 @@
    2.57          return 0;
    2.58      }
    2.59  
    2.60 -    /* Copy over. */
    2.61 -    SDL_HapticRumbleCreate(&haptic->rumble_effect);
    2.62 +    SDL_zerop(efx);
    2.63 +    if (haptic->supported & SDL_HAPTIC_SINE) {
    2.64 +        efx->type = SDL_HAPTIC_SINE;
    2.65 +        efx->periodic.period = 1000;
    2.66 +        efx->periodic.magnitude = 0x4000;
    2.67 +        efx->periodic.length = 5000;
    2.68 +        efx->periodic.attack_length = 0;
    2.69 +        efx->periodic.fade_length = 0;
    2.70 +    } else if (haptic->supported & SDL_HAPTIC_LEFTRIGHT) {  /* XInput? */
    2.71 +        efx->type = SDL_HAPTIC_LEFTRIGHT;
    2.72 +        efx->leftright.length = 5000;
    2.73 +        efx->leftright.large_magnitude = 0x4000;
    2.74 +        efx->leftright.small_magnitude = 0x4000;
    2.75 +    } else {
    2.76 +        return SDL_SetError("Device doesn't support rumble");
    2.77 +    }
    2.78 +
    2.79      haptic->rumble_id = SDL_HapticNewEffect(haptic, &haptic->rumble_effect);
    2.80      if (haptic->rumble_id >= 0) {
    2.81          return 0;
    2.82 @@ -781,7 +784,8 @@
    2.83  int
    2.84  SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length)
    2.85  {
    2.86 -    SDL_HapticPeriodic *efx;
    2.87 +    SDL_HapticEffect *efx;
    2.88 +    Sint16 magnitude;
    2.89  
    2.90      if (!ValidHaptic(haptic)) {
    2.91          return -1;
    2.92 @@ -794,15 +798,22 @@
    2.93      /* Clamp strength. */
    2.94      if (strength > 1.0f) {
    2.95          strength = 1.0f;
    2.96 -    }
    2.97 -    else if (strength < 0.0f) {
    2.98 +    } else if (strength < 0.0f) {
    2.99          strength = 0.0f;
   2.100      }
   2.101 +    magnitude = (Sint16)(32767.0f*strength);
   2.102  
   2.103 -    /* New effect. */
   2.104 -    efx = &haptic->rumble_effect.periodic;
   2.105 -    efx->magnitude = (Sint16)(32767.0f*strength);
   2.106 -    efx->length = length;
   2.107 +    efx = &haptic->rumble_effect;
   2.108 +    if (efx->type == SDL_HAPTIC_SINE) {
   2.109 +        efx->periodic.magnitude = magnitude;
   2.110 +        efx->periodic.length = length;
   2.111 +    } else if (efx->type == SDL_HAPTIC_LEFTRIGHT) {
   2.112 +        efx->leftright.small_magnitude = efx->leftright.large_magnitude = magnitude;
   2.113 +        efx->leftright.length = length;
   2.114 +    } else {
   2.115 +        SDL_assert(0 && "This should have been caught elsewhere");
   2.116 +    }
   2.117 +
   2.118      if (SDL_HapticUpdateEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) {
   2.119          return -1;
   2.120      }
   2.121 @@ -827,4 +838,3 @@
   2.122      return SDL_HapticStopEffect(haptic, haptic->rumble_id);
   2.123  }
   2.124  
   2.125 -
     3.1 --- a/src/haptic/darwin/SDL_syshaptic.c	Sat Aug 10 13:20:45 2013 -0400
     3.2 +++ b/src/haptic/darwin/SDL_syshaptic.c	Sat Aug 10 13:38:09 2013 -0400
     3.3 @@ -342,7 +342,8 @@
     3.4      /* Test for effects. */
     3.5      FF_TEST(FFCAP_ET_CONSTANTFORCE, SDL_HAPTIC_CONSTANT);
     3.6      FF_TEST(FFCAP_ET_RAMPFORCE, SDL_HAPTIC_RAMP);
     3.7 -    FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE);
     3.8 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
     3.9 +    /*FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE);*/
    3.10      FF_TEST(FFCAP_ET_SINE, SDL_HAPTIC_SINE);
    3.11      FF_TEST(FFCAP_ET_TRIANGLE, SDL_HAPTIC_TRIANGLE);
    3.12      FF_TEST(FFCAP_ET_SAWTOOTHUP, SDL_HAPTIC_SAWTOOTHUP);
    3.13 @@ -750,7 +751,8 @@
    3.14          break;
    3.15  
    3.16      case SDL_HAPTIC_SINE:
    3.17 -    case SDL_HAPTIC_SQUARE:
    3.18 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
    3.19 +    /*case SDL_HAPTIC_SQUARE:*/
    3.20      case SDL_HAPTIC_TRIANGLE:
    3.21      case SDL_HAPTIC_SAWTOOTHUP:
    3.22      case SDL_HAPTIC_SAWTOOTHDOWN:
    3.23 @@ -978,8 +980,9 @@
    3.24      case SDL_HAPTIC_RAMP:
    3.25          return kFFEffectType_RampForce_ID;
    3.26  
    3.27 -    case SDL_HAPTIC_SQUARE:
    3.28 -        return kFFEffectType_Square_ID;
    3.29 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
    3.30 +    /*case SDL_HAPTIC_SQUARE:
    3.31 +        return kFFEffectType_Square_ID;*/
    3.32  
    3.33      case SDL_HAPTIC_SINE:
    3.34          return kFFEffectType_Sine_ID;
     4.1 --- a/src/haptic/linux/SDL_syshaptic.c	Sat Aug 10 13:20:45 2013 -0400
     4.2 +++ b/src/haptic/linux/SDL_syshaptic.c	Sat Aug 10 13:38:09 2013 -0400
     4.3 @@ -99,7 +99,8 @@
     4.4      /* Convert supported features to SDL_HAPTIC platform-neutral features. */
     4.5      EV_TEST(FF_CONSTANT, SDL_HAPTIC_CONSTANT);
     4.6      EV_TEST(FF_SINE, SDL_HAPTIC_SINE);
     4.7 -    EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE);
     4.8 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
     4.9 +    /*EV_TEST(FF_SQUARE, SDL_HAPTIC_SQUARE);*/
    4.10      EV_TEST(FF_TRIANGLE, SDL_HAPTIC_TRIANGLE);
    4.11      EV_TEST(FF_SAW_UP, SDL_HAPTIC_SAWTOOTHUP);
    4.12      EV_TEST(FF_SAW_DOWN, SDL_HAPTIC_SAWTOOTHDOWN);
    4.13 @@ -111,6 +112,7 @@
    4.14      EV_TEST(FF_CUSTOM, SDL_HAPTIC_CUSTOM);
    4.15      EV_TEST(FF_GAIN, SDL_HAPTIC_GAIN);
    4.16      EV_TEST(FF_AUTOCENTER, SDL_HAPTIC_AUTOCENTER);
    4.17 +    EV_TEST(FF_RUMBLE, SDL_HAPTIC_LEFTRIGHT);
    4.18  
    4.19      /* Return what it supports. */
    4.20      return ret;
    4.21 @@ -559,6 +561,7 @@
    4.22      SDL_HapticPeriodic *periodic;
    4.23      SDL_HapticCondition *condition;
    4.24      SDL_HapticRamp *ramp;
    4.25 +    SDL_HapticLeftRight *leftright;
    4.26  
    4.27      /* Clear up */
    4.28      SDL_memset(dest, 0, sizeof(struct ff_effect));
    4.29 @@ -596,7 +599,8 @@
    4.30          break;
    4.31  
    4.32      case SDL_HAPTIC_SINE:
    4.33 -    case SDL_HAPTIC_SQUARE:
    4.34 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
    4.35 +    /*case SDL_HAPTIC_SQUARE:*/
    4.36      case SDL_HAPTIC_TRIANGLE:
    4.37      case SDL_HAPTIC_SAWTOOTHUP:
    4.38      case SDL_HAPTIC_SAWTOOTHDOWN:
    4.39 @@ -620,8 +624,9 @@
    4.40          /* Periodic */
    4.41          if (periodic->type == SDL_HAPTIC_SINE)
    4.42              dest->u.periodic.waveform = FF_SINE;
    4.43 -        else if (periodic->type == SDL_HAPTIC_SQUARE)
    4.44 -            dest->u.periodic.waveform = FF_SQUARE;
    4.45 +        /* !!! FIXME: put this back when we have more bits in 2.1 */
    4.46 +        /*else if (periodic->type == SDL_HAPTIC_SQUARE)
    4.47 +            dest->u.periodic.waveform = FF_SQUARE;*/
    4.48          else if (periodic->type == SDL_HAPTIC_TRIANGLE)
    4.49              dest->u.periodic.waveform = FF_TRIANGLE;
    4.50          else if (periodic->type == SDL_HAPTIC_SAWTOOTHUP)
    4.51 @@ -725,6 +730,27 @@
    4.52  
    4.53          break;
    4.54  
    4.55 +    case SDL_HAPTIC_LEFTRIGHT:
    4.56 +        leftright = &src->leftright;
    4.57 +
    4.58 +        /* Header */
    4.59 +        dest->type = FF_RUMBLE;
    4.60 +        dest->direction = 0;
    4.61 +
    4.62 +        /* Replay */
    4.63 +        dest->replay.length = (leftright->length == SDL_HAPTIC_INFINITY) ?
    4.64 +            0 : CLAMP(leftright->length);
    4.65 +
    4.66 +        /* Trigger */
    4.67 +        dest->trigger.button = 0;
    4.68 +        dest->trigger.interval = 0;
    4.69 +
    4.70 +        /* Rumble */
    4.71 +        dest->u.rumble.strong_magnitude = leftright->large_magnitude;
    4.72 +        dest->u.rumble.weak_magnitude = leftright->small_magnitude;
    4.73 +
    4.74 +	break;
    4.75 +
    4.76  
    4.77      default:
    4.78          return SDL_SetError("Haptic: Unknown effect type.");
     5.1 --- a/src/haptic/windows/SDL_syshaptic.c	Sat Aug 10 13:20:45 2013 -0400
     5.2 +++ b/src/haptic/windows/SDL_syshaptic.c	Sat Aug 10 13:38:09 2013 -0400
     5.3 @@ -303,7 +303,8 @@
     5.4      EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
     5.5      EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
     5.6      EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
     5.7 -    EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE);
     5.8 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
     5.9 +    /*EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE);*/
    5.10      EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
    5.11      EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
    5.12      EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
    5.13 @@ -389,8 +390,7 @@
    5.14      XINPUT_VIBRATION vibration = { 0, 0 };  /* stop any current vibration */
    5.15      XINPUTSETSTATE(userid, &vibration);
    5.16  
    5.17 -    /* !!! FIXME: we can probably do more than SINE if we figure out how to set up the left and right motors properly. */
    5.18 -    haptic->supported = SDL_HAPTIC_SINE;
    5.19 +    haptic->supported = SDL_HAPTIC_LEFTRIGHT;
    5.20  
    5.21      haptic->neffects = 1;
    5.22      haptic->nplaying = 1;
    5.23 @@ -935,7 +935,8 @@
    5.24          break;
    5.25  
    5.26      case SDL_HAPTIC_SINE:
    5.27 -    case SDL_HAPTIC_SQUARE:
    5.28 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
    5.29 +    /*case SDL_HAPTIC_SQUARE:*/
    5.30      case SDL_HAPTIC_TRIANGLE:
    5.31      case SDL_HAPTIC_SAWTOOTHUP:
    5.32      case SDL_HAPTIC_SAWTOOTHDOWN:
    5.33 @@ -1163,8 +1164,9 @@
    5.34      case SDL_HAPTIC_RAMP:
    5.35          return &GUID_RampForce;
    5.36  
    5.37 -    case SDL_HAPTIC_SQUARE:
    5.38 -        return &GUID_Square;
    5.39 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
    5.40 +    /*case SDL_HAPTIC_SQUARE:
    5.41 +        return &GUID_Square;*/
    5.42  
    5.43      case SDL_HAPTIC_SINE:
    5.44          return &GUID_Sine;
    5.45 @@ -1210,7 +1212,7 @@
    5.46      HRESULT ret;
    5.47      REFGUID type = SDL_SYS_HapticEffectType(base);
    5.48  
    5.49 -    if (type == NULL) {
    5.50 +    if ((type == NULL) && (!haptic->hwdata->bXInputHaptic)) {
    5.51          goto err_hweffect;
    5.52      }
    5.53  
    5.54 @@ -1225,7 +1227,7 @@
    5.55      SDL_zerop(effect->hweffect);
    5.56  
    5.57      if (haptic->hwdata->bXInputHaptic) {
    5.58 -        SDL_assert(base->type == SDL_HAPTIC_SINE);  /* should catch this at higher level */
    5.59 +        SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
    5.60          return SDL_SYS_HapticUpdateEffect(haptic, effect, base);
    5.61      }
    5.62  
    5.63 @@ -1269,20 +1271,14 @@
    5.64      DIEFFECT temp;
    5.65  
    5.66      if (haptic->hwdata->bXInputHaptic) {
    5.67 -        /* !!! FIXME: this isn't close to right. We only support "sine" effects,
    5.68 -         * !!! FIXME:  we ignore most of the parameters, and we probably get
    5.69 -         * !!! FIXME:  the ones we don't ignore wrong, too.
    5.70 -         * !!! FIXME: if I had a better understanding of how the two motors
    5.71 -         * !!! FIXME:  could be used in unison, perhaps I could implement other
    5.72 -         * !!! FIXME:  effect types?
    5.73 -         */
    5.74          /* From MSDN:
    5.75              "Note that the right motor is the high-frequency motor, the left
    5.76               motor is the low-frequency motor. They do not always need to be
    5.77               set to the same amount, as they provide different effects." */
    5.78          XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
    5.79 -        SDL_assert(data->type == SDL_HAPTIC_SINE);
    5.80 -        vib->wLeftMotorSpeed = vib->wRightMotorSpeed = data->periodic.magnitude * 2;
    5.81 +        SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT);
    5.82 +        vib->wLeftMotorSpeed = data->leftright.large_magnitude;
    5.83 +        vib->wRightMotorSpeed = data->leftright.small_magnitude;
    5.84          return 0;
    5.85      }
    5.86  
    5.87 @@ -1333,9 +1329,9 @@
    5.88  
    5.89      if (haptic->hwdata->bXInputHaptic) {
    5.90          XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
    5.91 -        SDL_assert(effect->effect.type == SDL_HAPTIC_SINE);  /* should catch this at higher level */
    5.92 +        SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT);  /* should catch this at higher level */
    5.93          SDL_LockMutex(haptic->hwdata->mutex);
    5.94 -        haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.periodic.length * iterations);
    5.95 +        haptic->hwdata->stopTicks = SDL_GetTicks() + (effect->effect.leftright.length * iterations);
    5.96          SDL_UnlockMutex(haptic->hwdata->mutex);
    5.97          return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
    5.98      }
     6.1 --- a/test/testhaptic.c	Sat Aug 10 13:20:45 2013 -0400
     6.2 +++ b/test/testhaptic.c	Sat Aug 10 13:38:09 2013 -0400
     6.3 @@ -213,6 +213,22 @@
     6.4          nefx++;
     6.5      }
     6.6  
     6.7 +    /* First we'll try a SINE effect. */
     6.8 +    if (supported & SDL_HAPTIC_LEFTRIGHT) {
     6.9 +        printf("   effect %d: Left/Right\n", nefx);
    6.10 +        efx[nefx].type = SDL_HAPTIC_LEFTRIGHT;
    6.11 +        efx[nefx].leftright.length = 5000;
    6.12 +        efx[nefx].leftright.large_magnitude = 0x3000;
    6.13 +        efx[nefx].leftright.small_magnitude = 0xFFFF;
    6.14 +        id[nefx] = SDL_HapticNewEffect(haptic, &efx[nefx]);
    6.15 +        if (id[nefx] < 0) {
    6.16 +            printf("UPLOADING EFFECT ERROR: %s\n", SDL_GetError());
    6.17 +            abort_execution();
    6.18 +        }
    6.19 +        nefx++;
    6.20 +    }
    6.21 +
    6.22 +
    6.23      printf
    6.24          ("\nNow playing effects for 5 seconds each with 1 second delay between\n");
    6.25      for (i = 0; i < nefx; i++) {
    6.26 @@ -260,8 +276,9 @@
    6.27          printf("      constant\n");
    6.28      if (supported & SDL_HAPTIC_SINE)
    6.29          printf("      sine\n");
    6.30 -    if (supported & SDL_HAPTIC_SQUARE)
    6.31 -        printf("      square\n");
    6.32 +    /* !!! FIXME: put this back when we have more bits in 2.1 */
    6.33 +    /*if (supported & SDL_HAPTIC_SQUARE)
    6.34 +        printf("      square\n");*/
    6.35      if (supported & SDL_HAPTIC_TRIANGLE)
    6.36          printf("      triangle\n");
    6.37      if (supported & SDL_HAPTIC_SAWTOOTHUP)
    6.38 @@ -280,6 +297,8 @@
    6.39          printf("      intertia\n");
    6.40      if (supported & SDL_HAPTIC_CUSTOM)
    6.41          printf("      custom\n");
    6.42 +    if (supported & SDL_HAPTIC_LEFTRIGHT)
    6.43 +        printf("      left/right\n");
    6.44      printf("   Supported capabilities:\n");
    6.45      if (supported & SDL_HAPTIC_GAIN)
    6.46          printf("      gain\n");