Updated Haptic API for SDL 3.0 conventions

Also removed the XInput haptic support since using the haptic API for rumble is no longer supported.
This commit is contained in:
Sam Lantinga
2024-01-17 15:22:35 -08:00
parent 8ca9134115
commit f224af5ac5
35 changed files with 943 additions and 1320 deletions

View File

@@ -24,16 +24,15 @@
#include "SDL_haptic_c.h"
#include "../joystick/SDL_joystick_c.h" /* For SDL_IsJoystickValid */
/* Global for SDL_windowshaptic.c */
#if (defined(SDL_HAPTIC_DINPUT) && SDL_HAPTIC_DINPUT) || (defined(SDL_HAPTIC_XINPUT) && SDL_HAPTIC_XINPUT)
SDL_Haptic *SDL_haptics = NULL;
#else
static SDL_Haptic *SDL_haptics = NULL;
#endif
static char SDL_haptic_magic;
#define CHECK_HAPTIC_MAGIC(haptic, retval) \
if (!haptic || haptic->magic != &SDL_haptic_magic) { \
SDL_InvalidParamError("haptic"); \
return retval; \
}
/*
* Initializes the Haptic devices.
*/
int SDL_InitHaptics(void)
{
int status;
@@ -46,75 +45,82 @@ int SDL_InitHaptics(void)
return status;
}
/*
* Checks to see if the haptic device is valid
*/
static int ValidHaptic(SDL_Haptic *haptic)
static SDL_bool SDL_GetHapticIndex(SDL_HapticID instance_id, int *driver_index)
{
int valid;
SDL_Haptic *hapticlist;
int num_haptics, device_index;
valid = 0;
if (haptic) {
hapticlist = SDL_haptics;
while (hapticlist) {
if (hapticlist == haptic) {
valid = 1;
break;
if (instance_id > 0) {
num_haptics = SDL_SYS_NumHaptics();
for (device_index = 0; device_index < num_haptics; ++device_index) {
SDL_HapticID haptic_id = SDL_SYS_HapticInstanceID(device_index);
if (haptic_id == instance_id) {
*driver_index = device_index;
return SDL_TRUE;
}
hapticlist = hapticlist->next;
}
}
/* Create the error here. */
if (valid == 0) {
SDL_SetError("Haptic: Invalid haptic device identifier");
SDL_SetError("Haptic device %" SDL_PRIu32 " not found", instance_id);
return SDL_FALSE;
}
SDL_HapticID *SDL_GetHaptics(int *count)
{
int device_index;
int haptic_index = 0, num_haptics = 0;
SDL_HapticID *haptics;
num_haptics = SDL_SYS_NumHaptics();
haptics = (SDL_HapticID *)SDL_malloc((num_haptics + 1) * sizeof(*haptics));
if (haptics) {
if (count) {
*count = num_haptics;
}
for (device_index = 0; device_index < num_haptics; ++device_index) {
haptics[haptic_index] = SDL_SYS_HapticInstanceID(device_index);
SDL_assert(haptics[haptic_index] > 0);
++haptic_index;
}
haptics[haptic_index] = 0;
} else {
if (count) {
*count = 0;
}
}
return valid;
return haptics;
}
/*
* Returns the number of available devices.
*/
int SDL_NumHaptics(void)
const char *SDL_GetHapticInstanceName(SDL_HapticID instance_id)
{
return SDL_SYS_NumHaptics();
}
int device_index;
const char *name = NULL;
/*
* Gets the name of a Haptic device by index.
*/
const char *SDL_HapticName(int device_index)
{
if ((device_index < 0) || (device_index >= SDL_NumHaptics())) {
SDL_SetError("Haptic: There are %d haptic devices available",
SDL_NumHaptics());
return NULL;
if (SDL_GetHapticIndex(instance_id, &device_index)) {
name = SDL_SYS_HapticName(device_index);
}
return SDL_SYS_HapticName(device_index);
return name;
}
/*
* Opens a Haptic device.
*/
SDL_Haptic *SDL_HapticOpen(int device_index)
SDL_Haptic *SDL_OpenHaptic(SDL_HapticID instance_id)
{
SDL_Haptic *haptic;
SDL_Haptic *hapticlist;
const char *name;
int device_index = 0;
if ((device_index < 0) || (device_index >= SDL_NumHaptics())) {
SDL_SetError("Haptic: There are %d haptic devices available",
SDL_NumHaptics());
if (!SDL_GetHapticIndex(instance_id, &device_index)) {
return NULL;
}
hapticlist = SDL_haptics;
/* If the haptic is already open, return it
* TODO: Should we create haptic instance IDs like the Joystick API?
/* If the haptic device is already open, return it
* it is important that we have a single haptic device for each instance id
*/
while (hapticlist) {
if (device_index == hapticlist->index) {
if (instance_id == hapticlist->instance_id) {
haptic = hapticlist;
++haptic->ref_count;
return haptic;
@@ -123,20 +129,27 @@ SDL_Haptic *SDL_HapticOpen(int device_index)
}
/* Create the haptic device */
haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic));
haptic = (SDL_Haptic *)SDL_calloc(1, sizeof(*haptic));
if (!haptic) {
return NULL;
}
/* Initialize the haptic device */
SDL_memset(haptic, 0, sizeof(*haptic));
haptic->magic = &SDL_haptic_magic;
haptic->instance_id = instance_id;
haptic->rumble_id = -1;
haptic->index = (Uint8)device_index;
if (SDL_SYS_HapticOpen(haptic) < 0) {
SDL_free(haptic);
return NULL;
}
if (!haptic->name) {
name = SDL_SYS_HapticName(device_index);
if (name) {
haptic->name = SDL_strdup(name);
}
}
/* Add haptic to list */
++haptic->ref_count;
/* Link the haptic in the list */
@@ -145,59 +158,42 @@ SDL_Haptic *SDL_HapticOpen(int device_index)
/* Disable autocenter and set gain to max. */
if (haptic->supported & SDL_HAPTIC_GAIN) {
SDL_HapticSetGain(haptic, 100);
SDL_SetHapticGain(haptic, 100);
}
if (haptic->supported & SDL_HAPTIC_AUTOCENTER) {
SDL_HapticSetAutocenter(haptic, 0);
SDL_SetHapticAutocenter(haptic, 0);
}
return haptic;
}
/*
* Returns 1 if the device has been opened.
*/
int SDL_HapticOpened(int device_index)
SDL_Haptic *SDL_GetHapticFromInstanceID(SDL_HapticID instance_id)
{
int opened;
SDL_Haptic *hapticlist;
SDL_Haptic *haptic;
/* Make sure it's valid. */
if ((device_index < 0) || (device_index >= SDL_NumHaptics())) {
SDL_SetError("Haptic: There are %d haptic devices available",
SDL_NumHaptics());
return 0;
}
opened = 0;
hapticlist = SDL_haptics;
/* TODO Should this use an instance ID? */
while (hapticlist) {
if (hapticlist->index == (Uint8)device_index) {
opened = 1;
for (haptic = SDL_haptics; haptic; haptic = haptic->next) {
if (instance_id == haptic->instance_id) {
break;
}
hapticlist = hapticlist->next;
}
return opened;
return haptic;
}
/*
* Returns the index to a haptic device.
*/
int SDL_HapticIndex(SDL_Haptic *haptic)
SDL_HapticID SDL_GetHapticInstanceID(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, 0);
return haptic->index;
return haptic->instance_id;
}
/*
* Returns SDL_TRUE if mouse is haptic, SDL_FALSE if it isn't.
*/
int SDL_MouseIsHaptic(void)
const char *SDL_GetHapticName(SDL_Haptic *haptic)
{
CHECK_HAPTIC_MAGIC(haptic, 0);
return haptic->name;
}
SDL_bool SDL_IsMouseHaptic(void)
{
if (SDL_SYS_HapticMouse() < 0) {
return SDL_FALSE;
@@ -205,10 +201,7 @@ int SDL_MouseIsHaptic(void)
return SDL_TRUE;
}
/*
* Returns the haptic device if mouse is haptic or NULL elsewise.
*/
SDL_Haptic *SDL_HapticOpenFromMouse(void)
SDL_Haptic *SDL_OpenHapticFromMouse(void)
{
int device_index;
@@ -219,52 +212,33 @@ SDL_Haptic *SDL_HapticOpenFromMouse(void)
return NULL;
}
return SDL_HapticOpen(device_index);
return SDL_OpenHaptic(device_index);
}
/*
* Returns SDL_TRUE if joystick has haptic features.
*/
int SDL_JoystickIsHaptic(SDL_Joystick *joystick)
SDL_bool SDL_IsJoystickHaptic(SDL_Joystick *joystick)
{
int ret;
SDL_bool result = SDL_FALSE;
SDL_LockJoysticks();
{
/* Must be a valid joystick */
if (!SDL_IsJoystickValid(joystick)) {
SDL_UnlockJoysticks();
return -1;
if (SDL_IsJoystickValid(joystick) &&
!SDL_IsGamepad(SDL_GetJoystickInstanceID(joystick))) {
if (SDL_SYS_JoystickIsHaptic(joystick) > 0) {
result = SDL_TRUE;
}
}
ret = SDL_SYS_JoystickIsHaptic(joystick);
}
SDL_UnlockJoysticks();
if (ret > 0) {
return SDL_TRUE;
} else if (ret == 0) {
return SDL_FALSE;
}
return -1;
return result;
}
/*
* Opens a haptic device from a joystick.
*/
SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
SDL_Haptic *SDL_OpenHapticFromJoystick(SDL_Joystick *joystick)
{
SDL_Haptic *haptic;
SDL_Haptic *hapticlist;
/* Make sure there is room. */
if (SDL_NumHaptics() <= 0) {
SDL_SetError("Haptic: There are %d haptic devices available",
SDL_NumHaptics());
return NULL;
}
SDL_LockJoysticks();
{
/* Must be a valid joystick */
@@ -275,7 +249,8 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
}
/* Joystick must be haptic */
if (SDL_SYS_JoystickIsHaptic(joystick) <= 0) {
if (SDL_IsGamepad(SDL_GetJoystickInstanceID(joystick)) ||
SDL_SYS_JoystickIsHaptic(joystick) <= 0) {
SDL_SetError("Haptic: Joystick isn't a haptic device.");
SDL_UnlockJoysticks();
return NULL;
@@ -294,14 +269,15 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
}
/* Create the haptic device */
haptic = (SDL_Haptic *)SDL_malloc(sizeof(*haptic));
haptic = (SDL_Haptic *)SDL_calloc(1, sizeof(*haptic));
if (!haptic) {
SDL_UnlockJoysticks();
return NULL;
}
/* Initialize the haptic device */
SDL_memset(haptic, 0, sizeof(SDL_Haptic));
/* Initialize the haptic device
* This function should fill in the instance ID and name.
*/
haptic->rumble_id = -1;
if (SDL_SYS_HapticOpenFromJoystick(haptic, joystick) < 0) {
SDL_SetError("Haptic: SDL_SYS_HapticOpenFromJoystick failed.");
@@ -309,6 +285,7 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
SDL_UnlockJoysticks();
return NULL;
}
SDL_assert(haptic->instance_id != 0);
}
SDL_UnlockJoysticks();
@@ -321,19 +298,13 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
return haptic;
}
/*
* Closes a SDL_Haptic device.
*/
void SDL_HapticClose(SDL_Haptic *haptic)
void SDL_CloseHaptic(SDL_Haptic *haptic)
{
int i;
SDL_Haptic *hapticlist;
SDL_Haptic *hapticlistprev;
/* Must be valid */
if (!ValidHaptic(haptic)) {
return;
}
CHECK_HAPTIC_MAGIC(haptic,);
/* Check if it's still in use */
if (--haptic->ref_count > 0) {
@@ -343,10 +314,11 @@ void SDL_HapticClose(SDL_Haptic *haptic)
/* Close it, properly removing effects if needed */
for (i = 0; i < haptic->neffects; i++) {
if (haptic->effects[i].hweffect != NULL) {
SDL_HapticDestroyEffect(haptic, i);
SDL_DestroyHapticEffect(haptic, i);
}
}
SDL_SYS_HapticClose(haptic);
haptic->magic = NULL;
/* Remove from the list */
hapticlist = SDL_haptics;
@@ -366,78 +338,51 @@ void SDL_HapticClose(SDL_Haptic *haptic)
hapticlist = hapticlist->next;
}
/* Free */
/* Free the data associated with this device */
SDL_free(haptic->name);
SDL_free(haptic);
}
/*
* Cleans up after the subsystem.
*/
void SDL_QuitHaptics(void)
{
while (SDL_haptics) {
SDL_HapticClose(SDL_haptics);
SDL_CloseHaptic(SDL_haptics);
}
SDL_SYS_HapticQuit();
}
/*
* Returns the number of effects a haptic device has.
*/
int SDL_HapticNumEffects(SDL_Haptic *haptic)
int SDL_GetMaxHapticEffects(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
return haptic->neffects;
}
/*
* Returns the number of effects a haptic device can play.
*/
int SDL_HapticNumEffectsPlaying(SDL_Haptic *haptic)
int SDL_GetMaxHapticEffectsPlaying(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
return haptic->nplaying;
}
/*
* Returns supported effects by the device.
*/
unsigned int SDL_HapticQuery(SDL_Haptic *haptic)
unsigned int SDL_GetHapticFeatures(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return 0; /* same as if no effects were supported */
}
CHECK_HAPTIC_MAGIC(haptic, 0);
return haptic->supported;
}
/*
* Returns the number of axis on the device.
*/
int SDL_HapticNumAxes(SDL_Haptic *haptic)
int SDL_GetNumHapticAxes(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
return haptic->naxes;
}
/*
* Checks to see if the device can support the effect.
*/
int SDL_HapticEffectSupported(SDL_Haptic *haptic, SDL_HapticEffect *effect)
SDL_bool SDL_HapticEffectSupported(SDL_Haptic *haptic, SDL_HapticEffect *effect)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, SDL_FALSE);
if ((haptic->supported & effect->type) != 0) {
return SDL_TRUE;
@@ -445,17 +390,11 @@ int SDL_HapticEffectSupported(SDL_Haptic *haptic, SDL_HapticEffect *effect)
return SDL_FALSE;
}
/*
* Creates a new haptic effect.
*/
int SDL_HapticNewEffect(SDL_Haptic *haptic, SDL_HapticEffect *effect)
int SDL_CreateHapticEffect(SDL_Haptic *haptic, SDL_HapticEffect *effect)
{
int i;
/* Check for device validity. */
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
/* Check to see if effect is supported */
if (SDL_HapticEffectSupported(haptic, effect) == SDL_FALSE) {
@@ -480,9 +419,6 @@ int SDL_HapticNewEffect(SDL_Haptic *haptic, SDL_HapticEffect *effect)
return SDL_SetError("Haptic: Device has no free space left.");
}
/*
* Checks to see if an effect is valid.
*/
static int ValidEffect(SDL_Haptic *haptic, int effect)
{
if ((effect < 0) || (effect >= haptic->neffects)) {
@@ -492,13 +428,11 @@ static int ValidEffect(SDL_Haptic *haptic, int effect)
return 1;
}
/*
* Updates an effect.
*/
int SDL_HapticUpdateEffect(SDL_Haptic *haptic, int effect,
SDL_HapticEffect *data)
int SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effect, SDL_HapticEffect *data)
{
if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!ValidEffect(haptic, effect)) {
return -1;
}
@@ -518,12 +452,11 @@ int SDL_HapticUpdateEffect(SDL_Haptic *haptic, int effect,
return 0;
}
/*
* Runs the haptic effect on the device.
*/
int SDL_HapticRunEffect(SDL_Haptic *haptic, int effect, Uint32 iterations)
int SDL_RunHapticEffect(SDL_Haptic *haptic, int effect, Uint32 iterations)
{
if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!ValidEffect(haptic, effect)) {
return -1;
}
@@ -535,12 +468,11 @@ int SDL_HapticRunEffect(SDL_Haptic *haptic, int effect, Uint32 iterations)
return 0;
}
/*
* Stops the haptic effect on the device.
*/
int SDL_HapticStopEffect(SDL_Haptic *haptic, int effect)
int SDL_StopHapticEffect(SDL_Haptic *haptic, int effect)
{
if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!ValidEffect(haptic, effect)) {
return -1;
}
@@ -552,12 +484,11 @@ int SDL_HapticStopEffect(SDL_Haptic *haptic, int effect)
return 0;
}
/*
* Gets rid of a haptic effect.
*/
void SDL_HapticDestroyEffect(SDL_Haptic *haptic, int effect)
void SDL_DestroyHapticEffect(SDL_Haptic *haptic, int effect)
{
if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
CHECK_HAPTIC_MAGIC(haptic,);
if (!ValidEffect(haptic, effect)) {
return;
}
@@ -569,12 +500,11 @@ void SDL_HapticDestroyEffect(SDL_Haptic *haptic, int effect)
SDL_SYS_HapticDestroyEffect(haptic, &haptic->effects[effect]);
}
/*
* Gets the status of a haptic effect.
*/
int SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect)
int SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int effect)
{
if (!ValidHaptic(haptic) || !ValidEffect(haptic, effect)) {
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!ValidEffect(haptic, effect)) {
return -1;
}
@@ -585,17 +515,12 @@ int SDL_HapticGetEffectStatus(SDL_Haptic *haptic, int effect)
return SDL_SYS_HapticGetEffectStatus(haptic, &haptic->effects[effect]);
}
/*
* Sets the global gain of the device.
*/
int SDL_HapticSetGain(SDL_Haptic *haptic, int gain)
int SDL_SetHapticGain(SDL_Haptic *haptic, int gain)
{
const char *env;
int real_gain, max_gain;
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!(haptic->supported & SDL_HAPTIC_GAIN)) {
return SDL_SetError("Haptic: Device does not support setting gain.");
@@ -630,14 +555,9 @@ int SDL_HapticSetGain(SDL_Haptic *haptic, int gain)
return 0;
}
/*
* Makes the device autocenter, 0 disables.
*/
int SDL_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_SetHapticAutocenter(SDL_Haptic *haptic, int autocenter)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!(haptic->supported & SDL_HAPTIC_AUTOCENTER)) {
return SDL_SetError("Haptic: Device does not support setting autocenter.");
@@ -654,14 +574,9 @@ int SDL_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
return 0;
}
/*
* Pauses the haptic device.
*/
int SDL_HapticPause(SDL_Haptic *haptic)
int SDL_PauseHaptic(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!(haptic->supported & SDL_HAPTIC_PAUSE)) {
return SDL_SetError("Haptic: Device does not support setting pausing.");
@@ -670,14 +585,9 @@ int SDL_HapticPause(SDL_Haptic *haptic)
return SDL_SYS_HapticPause(haptic);
}
/*
* Unpauses the haptic device.
*/
int SDL_HapticUnpause(SDL_Haptic *haptic)
int SDL_ResumeHaptic(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
if (!(haptic->supported & SDL_HAPTIC_PAUSE)) {
return 0; /* Not going to be paused, so we pretend it's unpaused. */
@@ -686,41 +596,26 @@ int SDL_HapticUnpause(SDL_Haptic *haptic)
return SDL_SYS_HapticUnpause(haptic);
}
/*
* Stops all the currently playing effects.
*/
int SDL_HapticStopAll(SDL_Haptic *haptic)
int SDL_StopHapticEffects(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
return SDL_SYS_HapticStopAll(haptic);
}
/*
* Checks to see if rumble is supported.
*/
int SDL_HapticRumbleSupported(SDL_Haptic *haptic)
SDL_bool SDL_HapticRumbleSupported(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, SDL_FALSE);
/* Most things can use SINE, but XInput only has LEFTRIGHT. */
return (haptic->supported & (SDL_HAPTIC_SINE | SDL_HAPTIC_LEFTRIGHT)) != 0;
}
/*
* Initializes the haptic device for simple rumble playback.
*/
int SDL_HapticRumbleInit(SDL_Haptic *haptic)
int SDL_InitHapticRumble(SDL_Haptic *haptic)
{
SDL_HapticEffect *efx = &haptic->rumble_effect;
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
/* Already allocated. */
if (haptic->rumble_id >= 0) {
@@ -745,24 +640,19 @@ int SDL_HapticRumbleInit(SDL_Haptic *haptic)
return SDL_SetError("Device doesn't support rumble");
}
haptic->rumble_id = SDL_HapticNewEffect(haptic, &haptic->rumble_effect);
haptic->rumble_id = SDL_CreateHapticEffect(haptic, &haptic->rumble_effect);
if (haptic->rumble_id >= 0) {
return 0;
}
return -1;
}
/*
* Runs simple rumble on a haptic device
*/
int SDL_HapticRumblePlay(SDL_Haptic *haptic, float strength, Uint32 length)
int SDL_PlayHapticRumble(SDL_Haptic *haptic, float strength, Uint32 length)
{
SDL_HapticEffect *efx;
Sint16 magnitude;
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
if (haptic->rumble_id < 0) {
return SDL_SetError("Haptic: Rumble effect not initialized on haptic device");
@@ -787,25 +677,20 @@ int SDL_HapticRumblePlay(SDL_Haptic *haptic, float strength, Uint32 length)
SDL_assert(0 && "This should have been caught elsewhere");
}
if (SDL_HapticUpdateEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) {
if (SDL_UpdateHapticEffect(haptic, haptic->rumble_id, &haptic->rumble_effect) < 0) {
return -1;
}
return SDL_HapticRunEffect(haptic, haptic->rumble_id, 1);
return SDL_RunHapticEffect(haptic, haptic->rumble_id, 1);
}
/*
* Stops the simple rumble on a haptic device.
*/
int SDL_HapticRumbleStop(SDL_Haptic *haptic)
int SDL_StopHapticRumble(SDL_Haptic *haptic)
{
if (!ValidHaptic(haptic)) {
return -1;
}
CHECK_HAPTIC_MAGIC(haptic, -1);
if (haptic->rumble_id < 0) {
return SDL_SetError("Haptic: Rumble effect not initialized on haptic device");
}
return SDL_HapticStopEffect(haptic, haptic->rumble_id);
return SDL_StopHapticEffect(haptic, haptic->rumble_id);
}

View File

@@ -40,20 +40,23 @@ struct haptic_effect
*/
struct SDL_Haptic
{
Uint8 index; /* Stores index it is attached to */
const void *magic;
struct haptic_effect *effects; /* Allocated effects */
int neffects; /* Maximum amount of effects */
int nplaying; /* Maximum amount of effects to play at the same time */
unsigned int supported; /* Supported effects */
int naxes; /* Number of axes on the device. */
SDL_HapticID instance_id; /* Device instance, monotonically increasing from 0 */
char *name; /* Device name - system dependent */
struct haptic_hwdata *hwdata; /* Driver dependent */
int ref_count; /* Count for multiple opens */
struct haptic_effect *effects; /* Allocated effects */
int neffects; /* Maximum amount of effects */
int nplaying; /* Maximum amount of effects to play at the same time */
unsigned int supported; /* Supported effects */
int naxes; /* Number of axes on the device. */
struct haptic_hwdata *hwdata; /* Driver dependent */
int ref_count; /* Count for multiple opens */
int rumble_id; /* ID of rumble effect for simple rumble API. */
SDL_HapticEffect rumble_effect; /* Rumble effect. */
struct SDL_Haptic *next; /* pointer to next haptic we have allocated */
struct SDL_Haptic *next; /* pointer to next haptic we have allocated */
};
/*
@@ -66,6 +69,11 @@ extern int SDL_SYS_HapticInit(void);
/* Function to return the number of haptic devices plugged in right now */
extern int SDL_SYS_NumHaptics(void);
/*
* Gets the instance ID of the haptic device
*/
extern SDL_HapticID SDL_SYS_HapticInstanceID(int index);
/*
* Gets the device dependent name of the haptic device
*/

View File

@@ -30,6 +30,7 @@
typedef struct SDL_hapticlist_item
{
SDL_HapticID instance_id;
int device_id;
char *name;
SDL_Haptic *haptic;
@@ -66,6 +67,17 @@ static SDL_hapticlist_item *HapticByOrder(int index)
return item;
}
static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)
{
SDL_hapticlist_item *item;
for (item = SDL_hapticlist; item; item = item->next) {
if (instance_id == item->instance_id) {
return item;
}
}
return NULL;
}
static SDL_hapticlist_item *HapticByDevId(int device_id)
{
SDL_hapticlist_item *item;
@@ -78,6 +90,15 @@ static SDL_hapticlist_item *HapticByDevId(int device_id)
return NULL;
}
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
{
SDL_hapticlist_item *item = HapticByOrder(index);
if (item) {
return item->instance_id;
}
return 0;
}
const char *SDL_SYS_HapticName(int index)
{
SDL_hapticlist_item *item = HapticByOrder(index);
@@ -102,20 +123,23 @@ static SDL_hapticlist_item *OpenHaptic(SDL_Haptic *haptic, SDL_hapticlist_item *
haptic->hwdata = (struct haptic_hwdata *)item;
item->haptic = haptic;
haptic->instance_id = item->instance_id;
if (item->name) {
haptic->name = SDL_strdup(item->name);
}
haptic->supported = SDL_HAPTIC_LEFTRIGHT;
haptic->neffects = 1;
haptic->nplaying = haptic->neffects;
haptic->effects = (struct haptic_effect *)SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
haptic->effects = (struct haptic_effect *)SDL_calloc(haptic->neffects, sizeof(struct haptic_effect));
if (!haptic->effects) {
return NULL;
}
SDL_memset(haptic->effects, 0, sizeof(struct haptic_effect) * haptic->neffects);
return item;
}
static SDL_hapticlist_item *OpenHapticByOrder(SDL_Haptic *haptic, int index)
static SDL_hapticlist_item *OpenHapticByInstanceID(SDL_Haptic *haptic, SDL_HapticID instance_id)
{
return OpenHaptic(haptic, HapticByOrder(index));
return OpenHaptic(haptic, HapticByInstanceID(instance_id));
}
static SDL_hapticlist_item *OpenHapticByDevId(SDL_Haptic *haptic, int device_id)
@@ -125,7 +149,7 @@ static SDL_hapticlist_item *OpenHapticByDevId(SDL_Haptic *haptic, int device_id)
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
{
return OpenHapticByOrder(haptic, haptic->index) == NULL ? -1 : 0;
return OpenHapticByInstanceID(haptic, haptic->instance_id) == NULL ? -1 : 0;
}
int SDL_SYS_HapticMouse(void)
@@ -249,6 +273,7 @@ int Android_AddHaptic(int device_id, const char *name)
return -1;
}
item->instance_id = SDL_GetNextObjectID();
item->device_id = device_id;
item->name = SDL_strdup(name);
if (!item->name) {
@@ -275,7 +300,7 @@ int Android_RemoveHaptic(int device_id)
for (item = SDL_hapticlist; item; item = item->next) {
/* found it, remove it. */
if (device_id == item->device_id) {
const int retval = item->haptic ? item->haptic->index : -1;
const int retval = item->haptic ? 0 : -1;
if (prev) {
prev->next = item->next;

View File

@@ -42,6 +42,7 @@
*/
typedef struct SDL_hapticlist_item
{
SDL_HapticID instance_id;
char name[256]; /* Name of the device. */
io_service_t dev; /* Node we use to create the device. */
@@ -201,6 +202,17 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index)
return item;
}
static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)
{
SDL_hapticlist_item *item;
for (item = SDL_hapticlist; item; item = item->next) {
if (instance_id == item->instance_id) {
return item;
}
}
return NULL;
}
int MacHaptic_MaybeAddDevice(io_object_t device)
{
IOReturn result;
@@ -229,6 +241,7 @@ int MacHaptic_MaybeAddDevice(io_object_t device)
if (!item) {
return SDL_SetError("Could not allocate haptic storage");
}
item->instance_id = SDL_GetNextObjectID();
/* retain it as we are going to keep it around a while */
IOObjectRetain(device);
@@ -287,7 +300,7 @@ int MacHaptic_MaybeRemoveDevice(io_object_t device)
for (item = SDL_hapticlist; item; item = item->next) {
/* found it, remove it. */
if (IOObjectIsEqualTo((io_object_t)item->dev, device)) {
const int retval = item->haptic ? item->haptic->index : -1;
const int retval = item->haptic ? 0 : -1;
if (prev) {
prev->next = item->next;
@@ -313,6 +326,16 @@ int MacHaptic_MaybeRemoveDevice(io_object_t device)
return -1;
}
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
{
SDL_hapticlist_item *item;
item = HapticByDevIndex(index);
if (item) {
return item->instance_id;
}
return 0;
}
/*
* Return the name of a haptic device, does not need to be opened.
*/
@@ -320,7 +343,10 @@ const char *SDL_SYS_HapticName(int index)
{
SDL_hapticlist_item *item;
item = HapticByDevIndex(index);
return item->name;
if (item) {
return item->name;
}
return NULL;
}
/*
@@ -535,7 +561,7 @@ creat_err:
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
{
SDL_hapticlist_item *item;
item = HapticByDevIndex(haptic->index);
item = HapticByInstanceID(haptic->instance_id);
return SDL_SYS_HapticOpenFromService(haptic, item->dev);
}
@@ -598,7 +624,6 @@ int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
#ifdef SDL_JOYSTICK_IOKIT
int device_index = 0;
SDL_hapticlist_item *item;
if (joystick->driver != &SDL_DARWIN_JoystickDriver) {
@@ -607,10 +632,13 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
for (item = SDL_hapticlist; item; item = item->next) {
if (IOObjectIsEqualTo((io_object_t)item->dev,
joystick->hwdata->ffservice)) {
haptic->index = device_index;
haptic->instance_id = item->instance_id;
break;
}
++device_index;
}
if (joystick->name) {
haptic->name = SDL_strdup(joystick->name);
}
return SDL_SYS_HapticOpenFromService(haptic, joystick->hwdata->ffservice);

View File

@@ -39,6 +39,12 @@ int SDL_SYS_NumHaptics(void)
return 0;
}
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
{
SDL_SYS_LogicError();
return 0;
}
const char *SDL_SYS_HapticName(int index)
{
SDL_SYS_LogicError();

View File

@@ -49,6 +49,7 @@ static void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
*/
typedef struct SDL_hapticlist_item
{
SDL_HapticID instance_id;
char *fname; /* Dev path name (like /dev/input/event1) */
SDL_Haptic *haptic; /* Associated haptic. */
dev_t dev_num;
@@ -196,6 +197,17 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index)
return item;
}
static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)
{
SDL_hapticlist_item *item;
for (item = SDL_hapticlist; item; item = item->next) {
if (instance_id == item->instance_id) {
return item;
}
}
return NULL;
}
#ifdef SDL_USE_LIBUDEV
static void haptic_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
{
@@ -263,6 +275,7 @@ static int MaybeAddDevice(const char *path)
return -1;
}
item->instance_id = SDL_GetNextObjectID();
item->fname = SDL_strdup(path);
if (!item->fname) {
SDL_free(item);
@@ -299,7 +312,7 @@ static int MaybeRemoveDevice(const char *path)
for (item = SDL_hapticlist; item; item = item->next) {
/* found it, remove it. */
if (SDL_strcmp(path, item->fname) == 0) {
const int retval = item->haptic ? item->haptic->index : -1;
const int retval = item->haptic ? 0 : -1;
if (prev) {
prev->next = item->next;
@@ -326,6 +339,20 @@ static int MaybeRemoveDevice(const char *path)
}
#endif /* SDL_USE_LIBUDEV */
/*
* Return the instance ID of a haptic device, does not need to be opened.
*/
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
{
SDL_hapticlist_item *item;
item = HapticByDevIndex(index);
if (item) {
return item->instance_id;
}
return 0;
}
/*
* Gets the name from a file descriptor.
*/
@@ -348,23 +375,23 @@ const char *SDL_SYS_HapticName(int index)
{
SDL_hapticlist_item *item;
int fd;
const char *name;
const char *name = NULL;
item = HapticByDevIndex(index);
/* Open the haptic device. */
name = NULL;
fd = open(item->fname, O_RDONLY | O_CLOEXEC, 0);
if (item) {
/* Open the haptic device. */
fd = open(item->fname, O_RDONLY | O_CLOEXEC, 0);
if (fd >= 0) {
if (fd >= 0) {
name = SDL_SYS_HapticNameFromFD(fd);
if (!name) {
/* No name found, return device character device */
name = item->fname;
name = SDL_SYS_HapticNameFromFD(fd);
if (!name) {
/* No name found, return device character device */
name = item->fname;
}
close(fd);
}
close(fd);
}
return name;
}
@@ -422,7 +449,7 @@ int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
int ret;
SDL_hapticlist_item *item;
item = HapticByDevIndex(haptic->index);
item = HapticByInstanceID(haptic->instance_id);
/* Open the character device */
fd = open(item->fname, O_RDWR | O_CLOEXEC, 0);
if (fd < 0) {
@@ -516,10 +543,10 @@ int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
#ifdef SDL_JOYSTICK_LINUX
int device_index = 0;
int fd;
int ret;
SDL_hapticlist_item *item;
const char *name;
SDL_AssertJoysticksLocked();
@@ -529,14 +556,9 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
/* Find the joystick in the haptic list. */
for (item = SDL_hapticlist; item; item = item->next) {
if (SDL_strcmp(item->fname, joystick->hwdata->fname) == 0) {
haptic->instance_id = item->instance_id;
break;
}
++device_index;
}
haptic->index = device_index;
if (device_index >= MAX_HAPTICS) {
return SDL_SetError("Haptic: Joystick doesn't have Haptic capabilities");
}
fd = open(joystick->hwdata->fname, O_RDWR | O_CLOEXEC, 0);
@@ -551,6 +573,10 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
haptic->hwdata->fname = SDL_strdup(joystick->hwdata->fname);
name = SDL_SYS_HapticNameFromFD(fd);
if (name) {
haptic->name = SDL_strdup(name);
}
return 0;
#else
return -1;

View File

@@ -139,7 +139,7 @@ int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance)
/* Make sure we don't already have it */
for (item = SDL_hapticlist; item; item = item->next) {
if ((!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0)) {
if (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
return -1; /* Already added */
}
}
@@ -170,6 +170,7 @@ int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance)
return -1;
}
item->instance_id = SDL_GetNextObjectID();
item->name = WIN_StringToUTF8(pdidInstance->tszProductName);
if (!item->name) {
SDL_free(item);
@@ -193,7 +194,7 @@ int SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance)
}
for (item = SDL_hapticlist; item; item = item->next) {
if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
if (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
/* found it, remove it. */
return SDL_SYS_RemoveHapticDevice(prev, item);
}
@@ -298,7 +299,7 @@ static int SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic *haptic, LPDIRECTINPUTDEVI
/* !!! FIXME: opening a haptic device here first will make an attempt to
!!! FIXME: SDL_OpenJoystick() that same device fail later, since we
!!! FIXME: have it open in exclusive mode. But this will allow
!!! FIXME: SDL_OpenJoystick() followed by SDL_HapticOpenFromJoystick()
!!! FIXME: SDL_OpenJoystick() followed by SDL_OpenHapticFromJoystick()
!!! FIXME: to work, and that's probably the common case. Still,
!!! FIXME: ideally, We need to unify the opening code. */
@@ -461,7 +462,6 @@ int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
SDL_hapticlist_item *item;
Uint8 index = 0;
HRESULT ret;
DIDEVICEINSTANCE joy_instance;
@@ -473,11 +473,11 @@ int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick
/* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
for (item = SDL_hapticlist; item; item = item->next) {
if (!item->bXInputHaptic && WIN_IsEqualGUID(&item->instance.guidInstance, &joy_instance.guidInstance)) {
haptic->index = index;
if (WIN_IsEqualGUID(&item->instance.guidInstance, &joy_instance.guidInstance)) {
haptic->instance_id = item->instance_id;
haptic->name = SDL_strdup(item->name);
return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
}
++index;
}
return SDL_SetError("Couldn't find joystick in haptic device list");

View File

@@ -20,7 +20,7 @@
*/
#include "SDL_internal.h"
#if defined(SDL_HAPTIC_DINPUT) || defined(SDL_HAPTIC_XINPUT)
#ifdef SDL_HAPTIC_DINPUT
#include "../SDL_syshaptic.h"
#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
@@ -29,7 +29,6 @@
#include "SDL_windowshaptic_c.h"
#include "SDL_dinputhaptic_c.h"
#include "SDL_xinputhaptic_c.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
@@ -53,9 +52,6 @@ int SDL_SYS_HapticInit(void)
if (SDL_DINPUT_HapticInit() < 0) {
return -1;
}
if (SDL_XINPUT_HapticInit() < 0) {
return -1;
}
/* The joystick subsystem will usually be initialized before haptics,
* so the initial HapticMaybeAddDevice() calls from the joystick
@@ -63,11 +59,7 @@ int SDL_SYS_HapticInit(void)
* invoke those callbacks again here to pick up any joysticks that
* were added prior to haptics initialization. */
for (device = SYS_Joystick; device; device = device->pNext) {
if (device->bXInputDevice) {
SDL_XINPUT_HapticMaybeAddDevice(device->XInputUserId);
} else {
SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice);
}
SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice);
}
return numhaptics;
@@ -90,7 +82,7 @@ int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
{
const int retval = item->haptic ? item->haptic->index : -1;
const int retval = item->haptic ? 0 : -1;
if (prev) {
prev->next = item->next;
} else {
@@ -127,6 +119,26 @@ static SDL_hapticlist_item *HapticByDevIndex(int device_index)
return item;
}
static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)
{
SDL_hapticlist_item *item;
for (item = SDL_hapticlist; item; item = item->next) {
if (instance_id == item->instance_id) {
return item;
}
}
return NULL;
}
SDL_HapticID SDL_SYS_HapticInstanceID(int index)
{
SDL_hapticlist_item *item = HapticByDevIndex(index);
if (item) {
return item->instance_id;
}
return 0;
}
/*
* Return the name of a haptic device, does not need to be opened.
*/
@@ -141,12 +153,8 @@ const char *SDL_SYS_HapticName(int index)
*/
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
{
SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
if (item->bXInputHaptic) {
return SDL_XINPUT_HapticOpen(haptic, item);
} else {
return SDL_DINPUT_HapticOpen(haptic, item);
}
SDL_hapticlist_item *item = HapticByInstanceID(haptic->instance_id);
return SDL_DINPUT_HapticOpen(haptic, item);
}
/*
@@ -177,16 +185,9 @@ int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
return 0;
}
#ifdef SDL_HAPTIC_XINPUT
if (joystick->hwdata->bXInputHaptic) {
return 1;
}
#endif
#ifdef SDL_HAPTIC_DINPUT
if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
return 1;
}
#endif
return 0;
}
@@ -198,13 +199,7 @@ int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
return 0;
}
if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
return 0; /* one is XInput, one is not; not the same device. */
} else if (joystick->hwdata->bXInputHaptic) {
return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
} else {
return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
}
return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
}
/*
@@ -214,11 +209,7 @@ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver);
if (joystick->hwdata->bXInputDevice) {
return SDL_XINPUT_HapticOpenFromJoystick(haptic, joystick);
} else {
return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
}
return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);
}
/*
@@ -234,11 +225,7 @@ void SDL_SYS_HapticClose(SDL_Haptic *haptic)
haptic->neffects = 0;
/* Clean up */
if (haptic->hwdata->bXInputHaptic) {
SDL_XINPUT_HapticClose(haptic);
} else {
SDL_DINPUT_HapticClose(haptic);
}
SDL_DINPUT_HapticClose(haptic);
/* Free */
SDL_free(haptic->hwdata);
@@ -253,17 +240,6 @@ void SDL_SYS_HapticQuit(void)
{
SDL_hapticlist_item *item;
SDL_hapticlist_item *next = NULL;
SDL_Haptic *hapticitem = NULL;
extern SDL_Haptic *SDL_haptics;
for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
/* we _have_ to stop the thread before we free the XInput DLL! */
SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
SDL_WaitThread(hapticitem->hwdata->thread, NULL);
hapticitem->hwdata->thread = NULL;
}
}
for (item = SDL_hapticlist; item; item = next) {
/* Opened and not closed haptics are leaked, this is on purpose.
@@ -274,7 +250,6 @@ void SDL_SYS_HapticQuit(void)
SDL_free(item);
}
SDL_XINPUT_HapticQuit();
SDL_DINPUT_HapticQuit();
numhaptics = 0;
@@ -296,11 +271,7 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect,
return -1;
}
if (haptic->hwdata->bXInputHaptic) {
result = SDL_XINPUT_HapticNewEffect(haptic, effect, base);
} else {
result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
}
result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);
if (result < 0) {
SDL_free(effect->hweffect);
effect->hweffect = NULL;
@@ -311,28 +282,17 @@ int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect,
/*
* Updates an effect.
*/
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic,
struct haptic_effect *effect,
SDL_HapticEffect *data)
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticUpdateEffect(haptic, effect, data);
} else {
return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
}
return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);
}
/*
* Runs an effect.
*/
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect,
Uint32 iterations)
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticRunEffect(haptic, effect, iterations);
} else {
return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
}
return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);
}
/*
@@ -340,11 +300,7 @@ int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect,
*/
int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticStopEffect(haptic, effect);
} else {
return SDL_DINPUT_HapticStopEffect(haptic, effect);
}
return SDL_DINPUT_HapticStopEffect(haptic, effect);
}
/*
@@ -352,11 +308,7 @@ int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
*/
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
{
if (haptic->hwdata->bXInputHaptic) {
SDL_XINPUT_HapticDestroyEffect(haptic, effect);
} else {
SDL_DINPUT_HapticDestroyEffect(haptic, effect);
}
SDL_DINPUT_HapticDestroyEffect(haptic, effect);
SDL_free(effect->hweffect);
effect->hweffect = NULL;
}
@@ -364,14 +316,9 @@ void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effec
/*
* Gets the status of a haptic effect.
*/
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic,
struct haptic_effect *effect)
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticGetEffectStatus(haptic, effect);
} else {
return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
}
return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);
}
/*
@@ -379,11 +326,7 @@ int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic,
*/
int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticSetGain(haptic, gain);
} else {
return SDL_DINPUT_HapticSetGain(haptic, gain);
}
return SDL_DINPUT_HapticSetGain(haptic, gain);
}
/*
@@ -391,11 +334,7 @@ int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
*/
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
} else {
return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
}
return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
}
/*
@@ -403,11 +342,7 @@ int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
*/
int SDL_SYS_HapticPause(SDL_Haptic *haptic)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticPause(haptic);
} else {
return SDL_DINPUT_HapticPause(haptic);
}
return SDL_DINPUT_HapticPause(haptic);
}
/*
@@ -415,11 +350,7 @@ int SDL_SYS_HapticPause(SDL_Haptic *haptic)
*/
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticUnpause(haptic);
} else {
return SDL_DINPUT_HapticUnpause(haptic);
}
return SDL_DINPUT_HapticUnpause(haptic);
}
/*
@@ -427,11 +358,7 @@ int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
*/
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
{
if (haptic->hwdata->bXInputHaptic) {
return SDL_XINPUT_HapticStopAll(haptic);
} else {
return SDL_DINPUT_HapticStopAll(haptic);
}
return SDL_DINPUT_HapticStopAll(haptic);
}
/* Ends C function definitions when using C++ */
@@ -439,4 +366,4 @@ int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
}
#endif
#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
#endif /* SDL_HAPTIC_DINPUT */

View File

@@ -42,8 +42,6 @@ struct haptic_hwdata
#endif
DWORD axes[3]; /* Axes to use. */
SDL_bool is_joystick; /* Device is loaded as joystick. */
Uint8 bXInputHaptic; /* Supports force feedback via XInput. */
Uint8 userid; /* XInput userid index for this joystick */
SDL_Thread *thread;
SDL_Mutex *mutex;
Uint64 stopTicks;
@@ -53,16 +51,11 @@ struct haptic_hwdata
/*
* Haptic system effect data.
*/
#if defined(SDL_HAPTIC_DINPUT) || defined(SDL_HAPTIC_XINPUT)
#ifdef SDL_HAPTIC_DINPUT
struct haptic_hweffect
{
#ifdef SDL_HAPTIC_DINPUT
DIEFFECT effect;
LPDIRECTINPUTEFFECT ref;
#endif
#ifdef SDL_HAPTIC_XINPUT
XINPUT_VIBRATION vibration;
#endif
};
#endif
@@ -71,14 +64,13 @@ struct haptic_hweffect
*/
typedef struct SDL_hapticlist_item
{
SDL_HapticID instance_id;
char *name;
SDL_Haptic *haptic;
#ifdef SDL_HAPTIC_DINPUT
DIDEVICEINSTANCE instance;
DIDEVCAPS capabilities;
#endif
SDL_bool bXInputHaptic; /* Supports force feedback via XInput. */
Uint8 userid; /* XInput userid index for this joystick */
struct SDL_hapticlist_item *next;
} SDL_hapticlist_item;

View File

@@ -1,443 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "../SDL_syshaptic.h"
#ifdef SDL_HAPTIC_XINPUT
#include "SDL_windowshaptic_c.h"
#include "SDL_xinputhaptic_c.h"
#include "../../core/windows/SDL_xinput.h"
#include "../../joystick/windows/SDL_windowsjoystick_c.h"
#include "../../thread/SDL_systhread.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
/*
* Internal stuff.
*/
static SDL_bool loaded_xinput = SDL_FALSE;
int SDL_XINPUT_HapticInit(void)
{
if (SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE)) {
loaded_xinput = (WIN_LoadXInputDLL() == 0);
}
/* If the joystick subsystem is active, it will manage adding XInput haptic devices */
if (loaded_xinput && !SDL_WasInit(SDL_INIT_JOYSTICK)) {
DWORD i;
for (i = 0; i < XUSER_MAX_COUNT; i++) {
SDL_XINPUT_HapticMaybeAddDevice(i);
}
}
return 0;
}
int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid)
{
const Uint8 userid = (Uint8)dwUserid;
SDL_hapticlist_item *item;
XINPUT_VIBRATION state;
if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
return -1;
}
/* Make sure we don't already have it */
for (item = SDL_hapticlist; item; item = item->next) {
if (item->bXInputHaptic && item->userid == userid) {
return -1; /* Already added */
}
}
SDL_zero(state);
if (XINPUTSETSTATE(dwUserid, &state) != ERROR_SUCCESS) {
return -1; /* no force feedback on this device. */
}
item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item));
if (!item) {
return -1;
}
/* !!! FIXME: I'm not bothering to query for a real name right now (can we even?) */
{
char buf[64];
(void)SDL_snprintf(buf, sizeof(buf), "XInput Controller #%d", 1 + userid);
item->name = SDL_strdup(buf);
}
if (!item->name) {
SDL_free(item);
return -1;
}
/* Copy the instance over, useful for creating devices. */
item->bXInputHaptic = SDL_TRUE;
item->userid = userid;
return SDL_SYS_AddHapticDevice(item);
}
int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid)
{
const Uint8 userid = (Uint8)dwUserid;
SDL_hapticlist_item *item;
SDL_hapticlist_item *prev = NULL;
if ((!loaded_xinput) || (dwUserid >= XUSER_MAX_COUNT)) {
return -1;
}
for (item = SDL_hapticlist; item; item = item->next) {
if (item->bXInputHaptic && item->userid == userid) {
/* found it, remove it. */
return SDL_SYS_RemoveHapticDevice(prev, item);
}
prev = item;
}
return -1;
}
/* !!! FIXME: this is a hack, remove this later. */
/* Since XInput doesn't offer a way to vibrate for X time, we hook into
* SDL_PumpEvents() to check if it's time to stop vibrating with some
* frequency.
* In practice, this works for 99% of use cases. But in an ideal world,
* we do this in a separate thread so that:
* - we aren't bound to when the app chooses to pump the event queue.
* - we aren't adding more polling to the event queue
* - we can emulate all the haptic effects correctly (start on a delay,
* mix multiple effects, etc).
*
* Mostly, this is here to get rumbling to work, and all the other features
* are absent in the XInput path for now. :(
*/
static int SDLCALL SDL_RunXInputHaptic(void *arg)
{
struct haptic_hwdata *hwdata = (struct haptic_hwdata *)arg;
while (!SDL_AtomicGet(&hwdata->stopThread)) {
SDL_Delay(50);
SDL_LockMutex(hwdata->mutex);
/* If we're currently running and need to stop... */
if (hwdata->stopTicks) {
if ((hwdata->stopTicks != SDL_HAPTIC_INFINITY) && SDL_GetTicks() >= hwdata->stopTicks) {
XINPUT_VIBRATION vibration = { 0, 0 };
hwdata->stopTicks = 0;
XINPUTSETSTATE(hwdata->userid, &vibration);
}
}
SDL_UnlockMutex(hwdata->mutex);
}
return 0;
}
static int SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 userid)
{
char threadName[32];
XINPUT_VIBRATION vibration = { 0, 0 }; /* stop any current vibration */
XINPUTSETSTATE(userid, &vibration);
haptic->supported = SDL_HAPTIC_LEFTRIGHT;
haptic->neffects = 1;
haptic->nplaying = 1;
/* Prepare effects memory. */
haptic->effects = (struct haptic_effect *)
SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
if (!haptic->effects) {
return -1;
}
/* Clear the memory */
SDL_memset(haptic->effects, 0,
sizeof(struct haptic_effect) * haptic->neffects);
haptic->hwdata = (struct haptic_hwdata *)SDL_calloc(1, sizeof(*haptic->hwdata));
if (!haptic->hwdata) {
SDL_free(haptic->effects);
haptic->effects = NULL;
return -1;
}
haptic->hwdata->bXInputHaptic = 1;
haptic->hwdata->userid = userid;
haptic->hwdata->mutex = SDL_CreateMutex();
if (!haptic->hwdata->mutex) {
SDL_free(haptic->effects);
SDL_free(haptic->hwdata);
haptic->effects = NULL;
return SDL_SetError("Couldn't create XInput haptic mutex");
}
(void)SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%u", userid);
haptic->hwdata->thread = SDL_CreateThreadInternal(SDL_RunXInputHaptic, threadName, 64 * 1024, haptic->hwdata);
if (!haptic->hwdata->thread) {
SDL_DestroyMutex(haptic->hwdata->mutex);
SDL_free(haptic->effects);
SDL_free(haptic->hwdata);
haptic->effects = NULL;
return SDL_SetError("Couldn't create XInput haptic thread");
}
return 0;
}
int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item)
{
return SDL_XINPUT_HapticOpenFromUserIndex(haptic, item->userid);
}
int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
return haptic->hwdata->userid == joystick->hwdata->userid;
}
int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
SDL_hapticlist_item *item;
Uint8 index = 0;
/* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
for (item = SDL_hapticlist; item; item = item->next) {
if (item->bXInputHaptic && item->userid == joystick->hwdata->userid) {
haptic->index = index;
return SDL_XINPUT_HapticOpenFromUserIndex(haptic, joystick->hwdata->userid);
}
++index;
}
return SDL_SetError("Couldn't find joystick in haptic device list");
}
void SDL_XINPUT_HapticClose(SDL_Haptic *haptic)
{
SDL_AtomicSet(&haptic->hwdata->stopThread, 1);
SDL_WaitThread(haptic->hwdata->thread, NULL);
SDL_DestroyMutex(haptic->hwdata->mutex);
}
void SDL_XINPUT_HapticQuit(void)
{
if (loaded_xinput) {
WIN_UnloadXInputDLL();
loaded_xinput = SDL_FALSE;
}
}
int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
{
SDL_assert(base->type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
return SDL_XINPUT_HapticUpdateEffect(haptic, effect, base);
}
int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
{
XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
SDL_assert(data->type == SDL_HAPTIC_LEFTRIGHT);
/* SDL_HapticEffect has max magnitude of 32767, XInput expects 65535 max, so multiply */
vib->wLeftMotorSpeed = data->leftright.large_magnitude * 2;
vib->wRightMotorSpeed = data->leftright.small_magnitude * 2;
SDL_LockMutex(haptic->hwdata->mutex);
if (haptic->hwdata->stopTicks) { /* running right now? Update it. */
XINPUTSETSTATE(haptic->hwdata->userid, vib);
}
SDL_UnlockMutex(haptic->hwdata->mutex);
return 0;
}
int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
{
XINPUT_VIBRATION *vib = &effect->hweffect->vibration;
SDL_assert(effect->effect.type == SDL_HAPTIC_LEFTRIGHT); /* should catch this at higher level */
SDL_LockMutex(haptic->hwdata->mutex);
if (effect->effect.leftright.length == SDL_HAPTIC_INFINITY || iterations == SDL_HAPTIC_INFINITY) {
haptic->hwdata->stopTicks = SDL_HAPTIC_INFINITY;
} else if ((!effect->effect.leftright.length) || (!iterations)) {
/* do nothing. Effect runs for zero milliseconds. */
} else {
haptic->hwdata->stopTicks = SDL_GetTicks() + ((Uint64)effect->effect.leftright.length * iterations);
}
SDL_UnlockMutex(haptic->hwdata->mutex);
return (XINPUTSETSTATE(haptic->hwdata->userid, vib) == ERROR_SUCCESS) ? 0 : -1;
}
int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
{
XINPUT_VIBRATION vibration = { 0, 0 };
SDL_LockMutex(haptic->hwdata->mutex);
haptic->hwdata->stopTicks = 0;
SDL_UnlockMutex(haptic->hwdata->mutex);
return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
}
void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
{
SDL_XINPUT_HapticStopEffect(haptic, effect);
}
int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticPause(SDL_Haptic *haptic)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic)
{
XINPUT_VIBRATION vibration = { 0, 0 };
SDL_LockMutex(haptic->hwdata->mutex);
haptic->hwdata->stopTicks = 0;
SDL_UnlockMutex(haptic->hwdata->mutex);
return (XINPUTSETSTATE(haptic->hwdata->userid, &vibration) == ERROR_SUCCESS) ? 0 : -1;
}
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#else /* !SDL_HAPTIC_XINPUT */
#include "../../core/windows/SDL_windows.h"
typedef struct SDL_hapticlist_item SDL_hapticlist_item;
int SDL_XINPUT_HapticInit(void)
{
return 0;
}
int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item)
{
return SDL_Unsupported();
}
int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
{
return SDL_Unsupported();
}
void SDL_XINPUT_HapticClose(SDL_Haptic *haptic)
{
}
void SDL_XINPUT_HapticQuit(void)
{
}
int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
{
return SDL_Unsupported();
}
void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
{
}
int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticPause(SDL_Haptic *haptic)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic)
{
return SDL_Unsupported();
}
int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic)
{
return SDL_Unsupported();
}
#endif /* SDL_HAPTIC_XINPUT */

View File

@@ -1,53 +0,0 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#include "SDL_windowshaptic_c.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
extern int SDL_XINPUT_HapticInit(void);
extern int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid);
extern int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid);
extern int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item);
extern int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick);
extern int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick);
extern void SDL_XINPUT_HapticClose(SDL_Haptic *haptic);
extern void SDL_XINPUT_HapticQuit(void);
extern int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base);
extern int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data);
extern int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations);
extern int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect);
extern void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect);
extern int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect);
extern int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain);
extern int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter);
extern int SDL_XINPUT_HapticPause(SDL_Haptic *haptic);
extern int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic);
extern int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif