23 #ifdef SDL_HAPTIC_IOKIT
26 #include "../SDL_syshaptic.h"
28 #include "../../joystick/SDL_sysjoystick.h"
29 #include "../../joystick/darwin/SDL_sysjoystick_c.h"
31 #include <IOKit/IOKitLib.h>
32 #include <IOKit/hid/IOHIDKeys.h>
33 #include <IOKit/hid/IOHIDUsageTables.h>
34 #include <ForceFeedback/ForceFeedback.h>
35 #include <ForceFeedback/ForceFeedbackConstants.h>
37 #ifndef IO_OBJECT_NULL
38 #define IO_OBJECT_NULL ((io_service_t)0)
41 #define MAX_HAPTICS 32
57 } SDL_hapticlist[MAX_HAPTICS];
65 FFDeviceObjectReference device;
73 struct haptic_hweffect
75 FFEffectObjectReference
ref;
76 struct FFEFFECT effect;
82 static void SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect,
int type);
83 static int HIDGetDeviceProduct(io_service_t dev,
char *
name);
93 case FFERR_DEVICEFULL:
98 case FFERR_DEVICEPAUSED:
99 return "device paused";
100 case FFERR_DEVICERELEASED:
101 return "device released";
102 case FFERR_EFFECTPLAYING:
103 return "effect playing";
104 case FFERR_EFFECTTYPEMISMATCH:
105 return "effect type mismatch";
106 case FFERR_EFFECTTYPENOTSUPPORTED:
107 return "effect type not supported";
109 return "undetermined error";
110 case FFERR_HASEFFECTS:
111 return "device has effects";
112 case FFERR_INCOMPLETEEFFECT:
113 return "incomplete effect";
115 return "internal fault";
116 case FFERR_INVALIDDOWNLOADID:
117 return "invalid download id";
118 case FFERR_INVALIDPARAM:
119 return "invalid parameter";
122 case FFERR_NOINTERFACE:
123 return "interface not supported";
124 case FFERR_NOTDOWNLOADED:
125 return "effect is not downloaded";
126 case FFERR_NOTINITIALIZED:
127 return "object has not been initialized";
128 case FFERR_OUTOFMEMORY:
129 return "out of memory";
130 case FFERR_UNPLUGGED:
131 return "device is unplugged";
132 case FFERR_UNSUPPORTED:
133 return "function call unsupported";
134 case FFERR_UNSUPPORTEDAXIS:
135 return "axis unsupported";
138 return "unknown error";
152 CFDictionaryRef match;
154 CFMutableDictionaryRef hidProperties;
158 SDL_memset(SDL_hapticlist, 0,
sizeof(SDL_hapticlist));
161 match = IOServiceMatching(kIOHIDDeviceKey);
163 return SDL_SetError(
"Haptic: Failed to get IOServiceMatching.");
167 result = IOServiceGetMatchingServices(kIOMasterPortDefault, match, &iter);
168 if (result != kIOReturnSuccess) {
169 return SDL_SetError(
"Haptic: Couldn't create a HID object iterator.");
173 if (!IOIteratorIsValid(iter)) {
178 while ((device = IOIteratorNext(iter)) != IO_OBJECT_NULL) {
181 if (FFIsForceFeedback(device) == FF_OK) {
184 HIDGetDeviceProduct(device, SDL_hapticlist[numhaptics].
name);
185 SDL_hapticlist[numhaptics].dev = device;
186 SDL_hapticlist[numhaptics].haptic =
NULL;
191 result = IORegistryEntryCreateCFProperties(device,
195 if ((result == KERN_SUCCESS) && hidProperties) {
197 CFDictionaryGetValue(hidProperties,
198 CFSTR(kIOHIDPrimaryUsagePageKey));
200 if (!CFNumberGetValue(refCF, kCFNumberLongType,
201 &SDL_hapticlist[numhaptics].
204 (
"Haptic: Recieving device's usage page.");
206 CFDictionaryGetValue(hidProperties,
207 CFSTR(kIOHIDPrimaryUsageKey));
209 if (!CFNumberGetValue(refCF, kCFNumberLongType,
210 &SDL_hapticlist[numhaptics].
215 CFRelease(hidProperties);
221 IOObjectRelease(device);
225 if (numhaptics >= MAX_HAPTICS)
228 IOObjectRelease(iter);
240 return SDL_hapticlist[
index].name;
247 HIDGetDeviceProduct(io_service_t dev,
char *
name)
249 CFMutableDictionaryRef hidProperties, usbProperties;
250 io_registry_entry_t parent1, parent2;
253 hidProperties = usbProperties = 0;
255 ret = IORegistryEntryCreateCFProperties(dev, &hidProperties,
256 kCFAllocatorDefault, kNilOptions);
257 if ((ret != KERN_SUCCESS) || !hidProperties) {
258 return SDL_SetError(
"Haptic: Unable to create CFProperties.");
265 IORegistryEntryGetParentEntry(dev, kIOServicePlane, &parent1))
267 IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2))
269 IORegistryEntryCreateCFProperties(parent2, &usbProperties,
281 CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey));
284 CFDictionaryGetValue(usbProperties,
285 CFSTR(
"USB Product Name"));
287 if (!CFStringGetCString(refCF, name, 256,
288 CFStringGetSystemEncoding())) {
290 (
"Haptic: CFStringGetCString error retrieving pDevice->product.");
294 CFRelease(usbProperties);
297 (
"Haptic: IORegistryEntryCreateCFProperties failed to create usbProperties.");
301 if (kIOReturnSuccess != IOObjectRelease(parent2)) {
302 SDL_SetError(
"Haptic: IOObjectRelease error with parent2.");
304 if (kIOReturnSuccess != IOObjectRelease(parent1)) {
305 SDL_SetError(
"Haptic: IOObjectRelease error with parent1.");
308 return SDL_SetError(
"Haptic: Error getting registry entries.");
315 #define FF_TEST(ff, s) \
316 if (features.supportedEffects & (ff)) supported |= (s)
324 FFDeviceObjectReference device;
325 FFCAPABILITIES features;
326 unsigned int supported;
329 device = haptic->
hwdata->device;
331 ret = FFDeviceGetForceFeedbackCapabilities(device, &features);
333 return SDL_SetError(
"Haptic: Unable to get device's supported features.");
339 haptic->
neffects = features.storageCapacity;
340 haptic->
nplaying = features.playbackCapacity;
358 ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_FFGAIN,
362 else if (ret != FFERR_UNSUPPORTED) {
363 return SDL_SetError(
"Haptic: Unable to get if device supports gain: %s.",
368 ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_AUTOCENTER,
372 else if (ret != FFERR_UNSUPPORTED) {
374 (
"Haptic: Unable to get if device supports autocenter: %s.",
379 haptic->
naxes = ((features.numFfAxes) > 3) ? 3 : features.numFfAxes;
396 SDL_SYS_HapticOpenFromService(
SDL_Haptic * haptic, io_service_t service)
402 haptic->
hwdata = (
struct haptic_hwdata *)
411 ret = FFCreateDevice(service, &haptic->
hwdata->device);
413 SDL_SetError(
"Haptic: Unable to create device from service: %s.",
419 ret2 = GetSupportedFeatures(haptic);
426 ret = FFDeviceSendForceFeedbackCommand(haptic->
hwdata->device,
429 SDL_SetError(
"Haptic: Unable to reset device: %s.", FFStrError(ret));
432 ret = FFDeviceSendForceFeedbackCommand(haptic->
hwdata->device,
433 FFSFFC_SETACTUATORSON);
456 FFReleaseDevice(haptic->
hwdata->device);
473 return SDL_SYS_HapticOpenFromService(haptic,
474 SDL_hapticlist[haptic->
index].dev);
487 if ((SDL_hapticlist[i].usagePage == kHIDPage_GenericDesktop) &&
488 (SDL_hapticlist[i].
usage == kHIDUsage_GD_Mouse))
514 if (IOObjectIsEqualTo((io_object_t) ((
size_t)haptic->
hwdata->device),
529 if (IOObjectIsEqualTo((io_object_t) SDL_hapticlist[i].dev,
535 if (i >= SDL_numhaptics) {
539 return SDL_SYS_HapticOpenFromService(haptic, joystick->
hwdata->
ffservice);
557 FFReleaseDevice(haptic->
hwdata->device);
579 IOObjectRelease(SDL_hapticlist[i].dev);
588 FFGetTriggerButton(
Uint16 button)
590 DWORD dwTriggerButton;
592 dwTriggerButton = FFEB_NOTRIGGER;
595 dwTriggerButton = FFJOFS_BUTTON(button - 1);
598 return dwTriggerButton;
612 effect->dwFlags |= FFEFF_SPHERICAL;
613 effect->rglDirection =
NULL;
619 if (rglDir ==
NULL) {
623 effect->rglDirection = rglDir;
627 effect->dwFlags |= FFEFF_POLAR;
628 rglDir[0] = dir->
dir[0];
631 effect->dwFlags |= FFEFF_CARTESIAN;
632 rglDir[0] = dir->
dir[0];
634 rglDir[1] = dir->
dir[1];
636 rglDir[2] = dir->
dir[2];
639 effect->dwFlags |= FFEFF_SPHERICAL;
640 rglDir[0] = dir->
dir[0];
642 rglDir[1] = dir->
dir[1];
644 rglDir[2] = dir->
dir[2];
654 #define CCONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
656 #define CONVERT(x) (((x)*10000) / 0x7FFF)
661 SDL_SYS_ToFFEFFECT(
SDL_Haptic * haptic, FFEFFECT * dest,
665 FFCONSTANTFORCE *constant;
666 FFPERIODIC *periodic;
669 FFCUSTOMFORCE *custom;
670 FFENVELOPE *envelope;
680 dest->dwSize =
sizeof(FFEFFECT);
681 dest->dwSamplePeriod = 0;
682 dest->dwGain = 10000;
683 dest->dwFlags = FFEFF_OBJECTOFFSETS;
687 if (envelope ==
NULL) {
691 dest->lpEnvelope = envelope;
692 envelope->dwSize =
sizeof(FFENVELOPE);
695 dest->cAxes = haptic->
naxes;
696 if (dest->cAxes > 0) {
701 axes[0] = haptic->
hwdata->axes[0];
702 if (dest->cAxes > 1) {
703 axes[1] = haptic->
hwdata->axes[1];
705 if (dest->cAxes > 2) {
706 axes[2] = haptic->
hwdata->axes[2];
708 dest->rgdwAxes = axes;
716 constant =
SDL_malloc(
sizeof(FFCONSTANTFORCE));
717 if (constant ==
NULL) {
720 SDL_memset(constant, 0,
sizeof(FFCONSTANTFORCE));
723 constant->lMagnitude = CONVERT(hap_constant->
level);
724 dest->cbTypeSpecificParams =
sizeof(FFCONSTANTFORCE);
725 dest->lpvTypeSpecificParams = constant;
728 dest->dwDuration = hap_constant->
length * 1000;
729 dest->dwTriggerButton = FFGetTriggerButton(hap_constant->
button);
730 dest->dwTriggerRepeatInterval = hap_constant->
interval;
731 dest->dwStartDelay = hap_constant->
delay * 1000;
734 if (SDL_SYS_SetDirection(dest, &hap_constant->
direction, dest->cAxes)
743 dest->lpEnvelope =
NULL;
745 envelope->dwAttackLevel = CCONVERT(hap_constant->
attack_level);
747 envelope->dwFadeLevel = CCONVERT(hap_constant->
fade_level);
748 envelope->dwFadeTime = hap_constant->
fade_length * 1000;
761 if (periodic ==
NULL) {
767 periodic->dwMagnitude = CONVERT(hap_periodic->
magnitude);
768 periodic->lOffset = CONVERT(hap_periodic->
offset);
769 periodic->dwPhase = hap_periodic->
phase;
770 periodic->dwPeriod = hap_periodic->
period * 1000;
771 dest->cbTypeSpecificParams =
sizeof(FFPERIODIC);
772 dest->lpvTypeSpecificParams = periodic;
775 dest->dwDuration = hap_periodic->
length * 1000;
776 dest->dwTriggerButton = FFGetTriggerButton(hap_periodic->
button);
777 dest->dwTriggerRepeatInterval = hap_periodic->
interval;
778 dest->dwStartDelay = hap_periodic->
delay * 1000;
781 if (SDL_SYS_SetDirection(dest, &hap_periodic->
direction, dest->cAxes)
790 dest->lpEnvelope =
NULL;
792 envelope->dwAttackLevel = CCONVERT(hap_periodic->
attack_level);
794 envelope->dwFadeLevel = CCONVERT(hap_periodic->
fade_level);
795 envelope->dwFadeTime = hap_periodic->
fade_length * 1000;
805 condition =
SDL_malloc(
sizeof(FFCONDITION) * dest->cAxes);
806 if (condition ==
NULL) {
809 SDL_memset(condition, 0,
sizeof(FFCONDITION));
812 for (i = 0; i < dest->cAxes; i++) {
813 condition[
i].lOffset = CONVERT(hap_condition->
center[i]);
814 condition[
i].lPositiveCoefficient =
816 condition[
i].lNegativeCoefficient =
818 condition[
i].dwPositiveSaturation =
820 condition[
i].dwNegativeSaturation =
821 CCONVERT(hap_condition->
left_sat[i]);
822 condition[
i].lDeadBand = CCONVERT(hap_condition->
deadband[i]);
824 dest->cbTypeSpecificParams =
sizeof(FFCONDITION) * dest->cAxes;
825 dest->lpvTypeSpecificParams = condition;
828 dest->dwDuration = hap_condition->
length * 1000;
829 dest->dwTriggerButton = FFGetTriggerButton(hap_condition->
button);
830 dest->dwTriggerRepeatInterval = hap_condition->
interval;
831 dest->dwStartDelay = hap_condition->
delay * 1000;
834 if (SDL_SYS_SetDirection(dest, &hap_condition->
direction, dest->cAxes)
841 dest->lpEnvelope =
NULL;
846 hap_ramp = &src->
ramp;
854 ramp->lStart = CONVERT(hap_ramp->
start);
855 ramp->lEnd = CONVERT(hap_ramp->
end);
856 dest->cbTypeSpecificParams =
sizeof(FFRAMPFORCE);
857 dest->lpvTypeSpecificParams = ramp;
860 dest->dwDuration = hap_ramp->
length * 1000;
861 dest->dwTriggerButton = FFGetTriggerButton(hap_ramp->
button);
862 dest->dwTriggerRepeatInterval = hap_ramp->
interval;
863 dest->dwStartDelay = hap_ramp->
delay * 1000;
866 if (SDL_SYS_SetDirection(dest, &hap_ramp->
direction, dest->cAxes) < 0) {
873 dest->lpEnvelope =
NULL;
875 envelope->dwAttackLevel = CCONVERT(hap_ramp->
attack_level);
877 envelope->dwFadeLevel = CCONVERT(hap_ramp->
fade_level);
878 envelope->dwFadeTime = hap_ramp->
fade_length * 1000;
884 hap_custom = &src->
custom;
886 if (custom ==
NULL) {
892 custom->cChannels = hap_custom->
channels;
893 custom->dwSamplePeriod = hap_custom->
period * 1000;
894 custom->cSamples = hap_custom->
samples;
895 custom->rglForceData =
896 SDL_malloc(
sizeof(LONG) * custom->cSamples * custom->cChannels);
898 custom->rglForceData[
i] = CCONVERT(hap_custom->
data[i]);
900 dest->cbTypeSpecificParams =
sizeof(FFCUSTOMFORCE);
901 dest->lpvTypeSpecificParams = custom;
904 dest->dwDuration = hap_custom->
length * 1000;
905 dest->dwTriggerButton = FFGetTriggerButton(hap_custom->
button);
906 dest->dwTriggerRepeatInterval = hap_custom->
interval;
907 dest->dwStartDelay = hap_custom->
delay * 1000;
910 if (SDL_SYS_SetDirection(dest, &hap_custom->
direction, dest->cAxes) <
919 dest->lpEnvelope =
NULL;
921 envelope->dwAttackLevel = CCONVERT(hap_custom->
attack_level);
923 envelope->dwFadeLevel = CCONVERT(hap_custom->
fade_level);
924 envelope->dwFadeTime = hap_custom->
fade_length * 1000;
942 SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect,
int type)
944 FFCUSTOMFORCE *custom;
947 effect->lpEnvelope =
NULL;
949 effect->rgdwAxes =
NULL;
950 if (effect->lpvTypeSpecificParams !=
NULL) {
952 custom = (FFCUSTOMFORCE *) effect->lpvTypeSpecificParams;
954 custom->rglForceData =
NULL;
956 SDL_free(effect->lpvTypeSpecificParams);
957 effect->lpvTypeSpecificParams =
NULL;
960 effect->rglDirection =
NULL;
968 SDL_SYS_HapticEffectType(
Uint16 type)
972 return kFFEffectType_ConstantForce_ID;
975 return kFFEffectType_RampForce_ID;
982 return kFFEffectType_Sine_ID;
985 return kFFEffectType_Triangle_ID;
988 return kFFEffectType_SawtoothUp_ID;
991 return kFFEffectType_SawtoothDown_ID;
994 return kFFEffectType_Spring_ID;
997 return kFFEffectType_Damper_ID;
1000 return kFFEffectType_Inertia_ID;
1003 return kFFEffectType_Friction_ID;
1006 return kFFEffectType_CustomForce_ID;
1026 effect->
hweffect = (
struct haptic_hweffect *)
1034 type = SDL_SYS_HapticEffectType(base->
type);
1040 if (SDL_SYS_ToFFEFFECT(haptic, &effect->
hweffect->effect, base) < 0) {
1041 goto err_effectdone;
1045 ret = FFDeviceCreateEffect(haptic->
hwdata->device, type,
1049 SDL_SetError(
"Haptic: Unable to create effect: %s.", FFStrError(ret));
1050 goto err_effectdone;
1056 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect, base->
type);
1073 FFEffectParameterFlag
flags;
1078 if (SDL_SYS_ToFFEFFECT(haptic, &temp, data) < 0) {
1084 flags = FFEP_DIRECTION |
1088 FFEP_TRIGGERBUTTON |
1089 FFEP_TRIGGERREPEATINTERVAL | FFEP_TYPESPECIFICPARAMS;
1092 ret = FFEffectSetParameters(effect->
hweffect->ref, &temp, flags);
1094 SDL_SetError(
"Haptic: Unable to update effect: %s.", FFStrError(ret));
1099 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect, data->
type);
1105 SDL_SYS_HapticFreeFFEFFECT(&temp, data->
type);
1127 ret = FFEffectStart(effect->
hweffect->ref, iter, 0);
1129 return SDL_SetError(
"Haptic: Unable to run the effect: %s.",
1145 ret = FFEffectStop(effect->
hweffect->ref);
1147 return SDL_SetError(
"Haptic: Unable to stop the effect: %s.",
1164 FFDeviceReleaseEffect(haptic->
hwdata->device, effect->
hweffect->ref);
1166 SDL_SetError(
"Haptic: Error removing the effect from the device: %s.",
1169 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect,
1184 FFEffectStatusFlag status;
1186 ret = FFEffectGetEffectStatus(effect->
hweffect->ref, &status);
1188 SDL_SetError(
"Haptic: Unable to get effect status: %s.",
1210 FFDeviceSetForceFeedbackProperty(haptic->
hwdata->device,
1211 FFPROP_FFGAIN, &val);
1213 return SDL_SetError(
"Haptic: Error setting gain: %s.", FFStrError(ret));
1230 if (autocenter == 0)
1235 ret = FFDeviceSetForceFeedbackProperty(haptic->
hwdata->device,
1236 FFPROP_AUTOCENTER, &val);
1238 return SDL_SetError(
"Haptic: Error setting autocenter: %s.",
1254 ret = FFDeviceSendForceFeedbackCommand(haptic->
hwdata->device,
1257 return SDL_SetError(
"Haptic: Error pausing device: %s.", FFStrError(ret));
1272 ret = FFDeviceSendForceFeedbackCommand(haptic->
hwdata->device,
1275 return SDL_SetError(
"Haptic: Error pausing device: %s.", FFStrError(ret));
1290 ret = FFDeviceSendForceFeedbackCommand(haptic->
hwdata->device,
1293 return SDL_SetError(
"Haptic: Error stopping device: %s.", FFStrError(ret));
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
struct haptic_hwdata * hwdata
Structure that represents a haptic direction.
GLuint const GLfloat * val
struct haptic_effect * effects
#define SDL_HAPTIC_SPHERICAL
Uses spherical coordinates for the direction.
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
#define SDL_HAPTIC_AUTOCENTER
Device can set autocenter.
A structure containing a template for a Periodic effect.
#define SDL_HAPTIC_GAIN
Device can set global gain.
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
#define SDL_HAPTIC_CUSTOM
Custom effect is supported.
#define SDL_HAPTIC_TRIANGLE
Triangle wave effect supported.
SDL_HapticDirection direction
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
int SDL_SYS_HapticMouse(void)
int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
#define SDL_HAPTIC_INERTIA
Inertia effect supported - uses axes acceleration.
DECLSPEC void SDLCALL SDL_free(void *mem)
int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
const char * SDL_SYS_HapticName(int index)
A structure containing a template for a Condition effect.
EGLImageKHR EGLint * name
The SDL Haptic subsystem allows you to control haptic (force feedback) devices.
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
#define SDL_HAPTIC_SINE
Sine wave effect supported.
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
struct joystick_hwdata * hwdata
A structure containing a template for a Constant effect.
#define SDL_HAPTIC_INFINITY
Used to play a device an infinite number of times.
#define SDL_HAPTIC_CARTESIAN
Uses cartesian coordinates for the direction.
uint32_t Uint32
An unsigned 32-bit integer type.
SDL_HapticCondition condition
The generic template for any haptic effect.
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
SDL_HapticConstant constant
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
#define SDL_HAPTIC_PAUSE
Device can be paused.
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
SDL_HapticDirection direction
A structure containing a template for a Ramp effect.
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
#define SDL_OutOfMemory()
int SDL_SYS_HapticInit(void)
void SDL_SYS_HapticQuit(void)
struct haptic_hweffect * hweffect
#define SDL_HAPTIC_STATUS
Device can be queried for effect status.
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
int SDL_SYS_HapticPause(SDL_Haptic *haptic)
DECLSPEC void *SDLCALL SDL_memcpy(void *dst, const void *src, size_t len)
SDL_HapticDirection direction
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
#define SDL_HAPTIC_RAMP
Ramp effect supported.
uint8_t Uint8
An unsigned 8-bit integer type.
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
A structure containing a template for the SDL_HAPTIC_CUSTOM effect.
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
uint16_t Uint16
An unsigned 16-bit integer type.
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
SDL_HapticPeriodic periodic
GLsizeiptr const GLvoid GLenum usage
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
#define SDL_HAPTIC_SAWTOOTHDOWN
Sawtoothdown wave effect supported.
SDL_HapticDirection direction
SDL_HapticDirection direction
int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.