21 #include "../../SDL_internal.h"
23 #ifdef SDL_HAPTIC_IOKIT
27 #include "../SDL_syshaptic.h"
29 #include "../../joystick/SDL_sysjoystick.h"
30 #include "../../joystick/darwin/SDL_iokitjoystick_c.h"
31 #include "SDL_syshaptic_c.h"
33 #include <IOKit/IOKitLib.h>
34 #include <IOKit/hid/IOHIDKeys.h>
35 #include <IOKit/hid/IOHIDUsageTables.h>
36 #include <ForceFeedback/ForceFeedback.h>
37 #include <ForceFeedback/ForceFeedbackConstants.h>
39 #ifndef IO_OBJECT_NULL
40 #define IO_OBJECT_NULL ((io_service_t)0)
66 FFDeviceObjectReference
device;
74 struct haptic_hweffect
76 FFEffectObjectReference
ref;
77 struct FFEFFECT effect;
83 static void SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect,
int type);
84 static int HIDGetDeviceProduct(io_service_t dev,
char *
name);
88 static int numhaptics = -1;
94 FFStrError(
unsigned int err)
97 case FFERR_DEVICEFULL:
102 case FFERR_DEVICEPAUSED:
103 return "device paused";
104 case FFERR_DEVICERELEASED:
105 return "device released";
106 case FFERR_EFFECTPLAYING:
107 return "effect playing";
108 case FFERR_EFFECTTYPEMISMATCH:
109 return "effect type mismatch";
110 case FFERR_EFFECTTYPENOTSUPPORTED:
111 return "effect type not supported";
113 return "undetermined error";
114 case FFERR_HASEFFECTS:
115 return "device has effects";
116 case FFERR_INCOMPLETEEFFECT:
117 return "incomplete effect";
119 return "internal fault";
120 case FFERR_INVALIDDOWNLOADID:
121 return "invalid download id";
122 case FFERR_INVALIDPARAM:
123 return "invalid parameter";
126 case FFERR_NOINTERFACE:
127 return "interface not supported";
128 case FFERR_NOTDOWNLOADED:
129 return "effect is not downloaded";
130 case FFERR_NOTINITIALIZED:
131 return "object has not been initialized";
132 case FFERR_OUTOFMEMORY:
133 return "out of memory";
134 case FFERR_UNPLUGGED:
135 return "device is unplugged";
136 case FFERR_UNSUPPORTED:
137 return "function call unsupported";
138 case FFERR_UNSUPPORTEDAXIS:
139 return "axis unsupported";
142 return "unknown error";
155 CFDictionaryRef match;
158 if (numhaptics != -1) {
159 return SDL_SetError(
"Haptic subsystem already initialized!");
164 match = IOServiceMatching(kIOHIDDeviceKey);
166 return SDL_SetError(
"Haptic: Failed to get IOServiceMatching.");
170 result = IOServiceGetMatchingServices(kIOMasterPortDefault, match, &iter);
171 if (
result != kIOReturnSuccess) {
172 return SDL_SetError(
"Haptic: Couldn't create a HID object iterator.");
176 if (!IOIteratorIsValid(iter)) {
180 while ((
device = IOIteratorNext(iter)) != IO_OBJECT_NULL) {
185 IOObjectRelease(iter);
197 HapticByDevIndex(
int device_index)
201 if ((device_index < 0) || (device_index >= numhaptics)) {
205 while (device_index > 0) {
218 CFMutableDictionaryRef hidProperties;
222 if (numhaptics == -1) {
227 if (FFIsForceFeedback(
device) != FF_OK) {
234 if (IOObjectIsEqualTo((io_object_t) item->dev,
device)) {
242 return SDL_SetError(
"Could not allocate haptic storage");
259 if ((
result == KERN_SUCCESS) && hidProperties) {
260 refCF = CFDictionaryGetValue(hidProperties,
261 CFSTR(kIOHIDPrimaryUsagePageKey));
263 if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usagePage)) {
266 refCF = CFDictionaryGetValue(hidProperties,
267 CFSTR(kIOHIDPrimaryUsageKey));
269 if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usage)) {
274 CFRelease(hidProperties);
277 if (SDL_hapticlist_tail ==
NULL) {
280 SDL_hapticlist_tail->
next = item;
281 SDL_hapticlist_tail = item;
296 if (numhaptics == -1) {
302 if (IOObjectIsEqualTo((io_object_t) item->dev,
device)) {
311 if (item == SDL_hapticlist_tail) {
312 SDL_hapticlist_tail = prev;
319 IOObjectRelease(item->dev);
336 item = HapticByDevIndex(
index);
344 HIDGetDeviceProduct(io_service_t dev,
char *
name)
346 CFMutableDictionaryRef hidProperties, usbProperties;
347 io_registry_entry_t parent1, parent2;
350 hidProperties = usbProperties = 0;
352 ret = IORegistryEntryCreateCFProperties(dev, &hidProperties,
353 kCFAllocatorDefault, kNilOptions);
354 if ((ret != KERN_SUCCESS) || !hidProperties) {
355 return SDL_SetError(
"Haptic: Unable to create CFProperties.");
362 IORegistryEntryGetParentEntry(dev, kIOServicePlane, &parent1))
364 IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2))
366 IORegistryEntryCreateCFProperties(parent2, &usbProperties,
377 refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey));
379 refCF = CFDictionaryGetValue(usbProperties,
380 CFSTR(
"USB Product Name"));
383 if (!CFStringGetCString(refCF,
name, 256,
384 CFStringGetSystemEncoding())) {
385 return SDL_SetError(
"Haptic: CFStringGetCString error retrieving pDevice->product.");
389 CFRelease(usbProperties);
391 return SDL_SetError(
"Haptic: IORegistryEntryCreateCFProperties failed to create usbProperties.");
395 if (kIOReturnSuccess != IOObjectRelease(parent2)) {
396 SDL_SetError(
"Haptic: IOObjectRelease error with parent2.");
398 if (kIOReturnSuccess != IOObjectRelease(parent1)) {
399 SDL_SetError(
"Haptic: IOObjectRelease error with parent1.");
402 return SDL_SetError(
"Haptic: Error getting registry entries.");
409 #define FF_TEST(ff, s) \
410 if (features.supportedEffects & (ff)) supported |= (s)
415 GetSupportedFeatures(SDL_Haptic *
haptic)
418 FFDeviceObjectReference
device;
419 FFCAPABILITIES features;
420 unsigned int supported;
425 ret = FFDeviceGetForceFeedbackCapabilities(
device, &features);
427 return SDL_SetError(
"Haptic: Unable to get device's supported features.");
433 haptic->neffects = features.storageCapacity;
434 haptic->nplaying = features.playbackCapacity;
452 ret = FFDeviceGetForceFeedbackProperty(
device, FFPROP_FFGAIN,
456 }
else if (ret != FFERR_UNSUPPORTED) {
457 return SDL_SetError(
"Haptic: Unable to get if device supports gain: %s.",
462 ret = FFDeviceGetForceFeedbackProperty(
device, FFPROP_AUTOCENTER,
466 }
else if (ret != FFERR_UNSUPPORTED) {
468 (
"Haptic: Unable to get if device supports autocenter: %s.",
473 haptic->naxes = ((features.numFfAxes) > 3) ? 3 : features.numFfAxes;
481 haptic->supported = supported;
490 SDL_SYS_HapticOpenFromService(SDL_Haptic *
haptic, io_service_t service)
505 ret = FFCreateDevice(service, &
haptic->hwdata->device);
507 SDL_SetError(
"Haptic: Unable to create device from service: %s.",
513 ret2 = GetSupportedFeatures(
haptic);
520 ret = FFDeviceSendForceFeedbackCommand(
haptic->hwdata->device,
523 SDL_SetError(
"Haptic: Unable to reset device: %s.", FFStrError(ret));
526 ret = FFDeviceSendForceFeedbackCommand(
haptic->hwdata->device,
527 FFSFFC_SETACTUATORSON);
550 FFReleaseDevice(
haptic->hwdata->device);
568 item = HapticByDevIndex(
haptic->index);
570 return SDL_SYS_HapticOpenFromService(
haptic, item->dev);
580 int device_index = 0;
584 if ((item->usagePage == kHIDPage_GenericDesktop) &&
585 (item->usage == kHIDUsage_GD_Mouse)) {
601 #ifdef SDL_JOYSTICK_IOKIT
605 if (
joystick->hwdata->ffservice != 0) {
619 #ifdef SDL_JOYSTICK_IOKIT
623 if (IOObjectIsEqualTo((io_object_t) ((
size_t)
haptic->hwdata->device),
638 #ifdef SDL_JOYSTICK_IOKIT
639 int device_index = 0;
646 if (IOObjectIsEqualTo((io_object_t) item->dev,
648 haptic->index = device_index;
654 return SDL_SYS_HapticOpenFromService(
haptic,
joystick->hwdata->ffservice);
675 FFReleaseDevice(
haptic->hwdata->device);
699 IOObjectRelease(item->dev);
705 SDL_hapticlist_tail =
NULL;
715 DWORD dwTriggerButton;
717 dwTriggerButton = FFEB_NOTRIGGER;
720 dwTriggerButton = FFJOFS_BUTTON(
button - 1);
723 return dwTriggerButton;
737 effect->dwFlags |= FFEFF_SPHERICAL;
744 if (rglDir ==
NULL) {
748 effect->rglDirection = rglDir;
752 effect->dwFlags |= FFEFF_POLAR;
753 rglDir[0] = dir->
dir[0];
756 effect->dwFlags |= FFEFF_CARTESIAN;
757 rglDir[0] = dir->
dir[0];
759 rglDir[1] = dir->
dir[1];
762 rglDir[2] = dir->
dir[2];
766 effect->dwFlags |= FFEFF_SPHERICAL;
767 rglDir[0] = dir->
dir[0];
769 rglDir[1] = dir->
dir[1];
772 rglDir[2] = dir->
dir[2];
776 effect->dwFlags |= FFEFF_CARTESIAN;
787 #define CCONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
789 #define CONVERT(x) (((x)*10000) / 0x7FFF)
797 FFCONSTANTFORCE *constant =
NULL;
798 FFPERIODIC *periodic =
NULL;
800 FFRAMPFORCE *ramp =
NULL;
801 FFCUSTOMFORCE *custom =
NULL;
802 FFENVELOPE *envelope =
NULL;
812 dest->dwSize =
sizeof(FFEFFECT);
813 dest->dwSamplePeriod = 0;
814 dest->dwGain = 10000;
815 dest->dwFlags = FFEFF_OBJECTOFFSETS;
819 if (envelope ==
NULL) {
823 dest->lpEnvelope = envelope;
824 envelope->dwSize =
sizeof(FFENVELOPE);
830 dest->cAxes =
haptic->naxes;
832 if (dest->cAxes > 0) {
833 axes =
SDL_malloc(
sizeof(DWORD) * dest->cAxes);
837 axes[0] =
haptic->hwdata->axes[0];
838 if (dest->cAxes > 1) {
839 axes[1] =
haptic->hwdata->axes[1];
841 if (dest->cAxes > 2) {
842 axes[2] =
haptic->hwdata->axes[2];
844 dest->rgdwAxes = axes;
851 hap_constant = &
src->constant;
852 constant =
SDL_malloc(
sizeof(FFCONSTANTFORCE));
853 if (constant ==
NULL) {
856 SDL_memset(constant, 0,
sizeof(FFCONSTANTFORCE));
859 constant->lMagnitude = CONVERT(hap_constant->
level);
860 dest->cbTypeSpecificParams =
sizeof(FFCONSTANTFORCE);
861 dest->lpvTypeSpecificParams = constant;
864 dest->dwDuration = hap_constant->
length * 1000;
865 dest->dwTriggerButton = FFGetTriggerButton(hap_constant->
button);
866 dest->dwTriggerRepeatInterval = hap_constant->
interval;
867 dest->dwStartDelay = hap_constant->
delay * 1000;
870 if (SDL_SYS_SetDirection(dest, &hap_constant->
direction, dest->cAxes)
879 dest->lpEnvelope =
NULL;
881 envelope->dwAttackLevel = CCONVERT(hap_constant->
attack_level);
883 envelope->dwFadeLevel = CCONVERT(hap_constant->
fade_level);
884 envelope->dwFadeTime = hap_constant->
fade_length * 1000;
895 hap_periodic = &
src->periodic;
897 if (periodic ==
NULL) {
904 periodic->lOffset = CONVERT(hap_periodic->
offset);
906 (hap_periodic->
phase + (hap_periodic->
magnitude < 0 ? 18000 : 0)) % 36000;
907 periodic->dwPeriod = hap_periodic->
period * 1000;
908 dest->cbTypeSpecificParams =
sizeof(FFPERIODIC);
909 dest->lpvTypeSpecificParams = periodic;
912 dest->dwDuration = hap_periodic->
length * 1000;
913 dest->dwTriggerButton = FFGetTriggerButton(hap_periodic->
button);
914 dest->dwTriggerRepeatInterval = hap_periodic->
interval;
915 dest->dwStartDelay = hap_periodic->
delay * 1000;
918 if (SDL_SYS_SetDirection(dest, &hap_periodic->
direction, dest->cAxes)
927 dest->lpEnvelope =
NULL;
929 envelope->dwAttackLevel = CCONVERT(hap_periodic->
attack_level);
931 envelope->dwFadeLevel = CCONVERT(hap_periodic->
fade_level);
932 envelope->dwFadeTime = hap_periodic->
fade_length * 1000;
941 hap_condition = &
src->condition;
942 if (dest->cAxes > 0) {
950 for (
i = 0;
i < dest->cAxes;
i++) {
959 CCONVERT(hap_condition->
left_sat[
i] / 2);
964 dest->cbTypeSpecificParams =
sizeof(FFCONDITION) * dest->cAxes;
968 dest->dwDuration = hap_condition->
length * 1000;
969 dest->dwTriggerButton = FFGetTriggerButton(hap_condition->
button);
970 dest->dwTriggerRepeatInterval = hap_condition->
interval;
971 dest->dwStartDelay = hap_condition->
delay * 1000;
974 if (SDL_SYS_SetDirection(dest, &hap_condition->
direction, dest->cAxes)
981 dest->lpEnvelope =
NULL;
986 hap_ramp = &
src->ramp;
994 ramp->lStart = CONVERT(hap_ramp->
start);
995 ramp->lEnd = CONVERT(hap_ramp->
end);
996 dest->cbTypeSpecificParams =
sizeof(FFRAMPFORCE);
997 dest->lpvTypeSpecificParams = ramp;
1000 dest->dwDuration = hap_ramp->
length * 1000;
1001 dest->dwTriggerButton = FFGetTriggerButton(hap_ramp->
button);
1002 dest->dwTriggerRepeatInterval = hap_ramp->
interval;
1003 dest->dwStartDelay = hap_ramp->
delay * 1000;
1006 if (SDL_SYS_SetDirection(dest, &hap_ramp->
direction, dest->cAxes) < 0) {
1013 dest->lpEnvelope =
NULL;
1015 envelope->dwAttackLevel = CCONVERT(hap_ramp->
attack_level);
1017 envelope->dwFadeLevel = CCONVERT(hap_ramp->
fade_level);
1018 envelope->dwFadeTime = hap_ramp->
fade_length * 1000;
1024 hap_custom = &
src->custom;
1026 if (custom ==
NULL) {
1029 SDL_memset(custom, 0,
sizeof(FFCUSTOMFORCE));
1032 custom->cChannels = hap_custom->
channels;
1033 custom->dwSamplePeriod = hap_custom->
period * 1000;
1034 custom->cSamples = hap_custom->
samples;
1035 custom->rglForceData =
1036 SDL_malloc(
sizeof(LONG) * custom->cSamples * custom->cChannels);
1038 custom->rglForceData[
i] = CCONVERT(hap_custom->
data[
i]);
1040 dest->cbTypeSpecificParams =
sizeof(FFCUSTOMFORCE);
1041 dest->lpvTypeSpecificParams = custom;
1044 dest->dwDuration = hap_custom->
length * 1000;
1045 dest->dwTriggerButton = FFGetTriggerButton(hap_custom->
button);
1046 dest->dwTriggerRepeatInterval = hap_custom->
interval;
1047 dest->dwStartDelay = hap_custom->
delay * 1000;
1050 if (SDL_SYS_SetDirection(dest, &hap_custom->
direction, dest->cAxes) <
1059 dest->lpEnvelope =
NULL;
1061 envelope->dwAttackLevel = CCONVERT(hap_custom->
attack_level);
1063 envelope->dwFadeLevel = CCONVERT(hap_custom->
fade_level);
1064 envelope->dwFadeTime = hap_custom->
fade_length * 1000;
1082 SDL_SYS_HapticFreeFFEFFECT(FFEFFECT *
effect,
int type)
1084 FFCUSTOMFORCE *custom;
1092 custom = (FFCUSTOMFORCE *)
effect->lpvTypeSpecificParams;
1094 custom->rglForceData =
NULL;
1112 return kFFEffectType_ConstantForce_ID;
1115 return kFFEffectType_RampForce_ID;
1122 return kFFEffectType_Sine_ID;
1125 return kFFEffectType_Triangle_ID;
1128 return kFFEffectType_SawtoothUp_ID;
1131 return kFFEffectType_SawtoothDown_ID;
1134 return kFFEffectType_Spring_ID;
1137 return kFFEffectType_Damper_ID;
1140 return kFFEffectType_Inertia_ID;
1143 return kFFEffectType_Friction_ID;
1146 return kFFEffectType_CustomForce_ID;
1166 effect->hweffect = (
struct haptic_hweffect *)
1174 type = SDL_SYS_HapticEffectType(
base->type);
1181 goto err_effectdone;
1185 ret = FFDeviceCreateEffect(
haptic->hwdata->device,
type,
1189 SDL_SetError(
"Haptic: Unable to create effect: %s.", FFStrError(ret));
1190 goto err_effectdone;
1196 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect,
base->type);
1213 FFEffectParameterFlag
flags;
1218 if (SDL_SYS_ToFFEFFECT(
haptic, &temp,
data) < 0) {
1224 flags = FFEP_DIRECTION |
1228 FFEP_TRIGGERBUTTON |
1229 FFEP_TRIGGERREPEATINTERVAL | FFEP_TYPESPECIFICPARAMS;
1232 ret = FFEffectSetParameters(effect->
hweffect->ref, &temp,
flags);
1234 SDL_SetError(
"Haptic: Unable to update effect: %s.", FFStrError(ret));
1239 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect,
data->type);
1245 SDL_SYS_HapticFreeFFEFFECT(&temp,
data->type);
1267 ret = FFEffectStart(effect->
hweffect->ref, iter, 0);
1269 return SDL_SetError(
"Haptic: Unable to run the effect: %s.",
1285 ret = FFEffectStop(effect->
hweffect->ref);
1287 return SDL_SetError(
"Haptic: Unable to stop the effect: %s.",
1303 ret = FFDeviceReleaseEffect(
haptic->hwdata->device, effect->
hweffect->ref);
1305 SDL_SetError(
"Haptic: Error removing the effect from the device: %s.",
1308 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect,
1323 FFEffectStatusFlag status;
1325 ret = FFEffectGetEffectStatus(effect->
hweffect->ref, &status);
1327 SDL_SetError(
"Haptic: Unable to get effect status: %s.",
1349 ret = FFDeviceSetForceFeedbackProperty(
haptic->hwdata->device,
1350 FFPROP_FFGAIN, &
val);
1352 return SDL_SetError(
"Haptic: Error setting gain: %s.", FFStrError(ret));
1369 if (autocenter == 0) {
1375 ret = FFDeviceSetForceFeedbackProperty(
haptic->hwdata->device,
1376 FFPROP_AUTOCENTER, &
val);
1378 return SDL_SetError(
"Haptic: Error setting autocenter: %s.",
1394 ret = FFDeviceSendForceFeedbackCommand(
haptic->hwdata->device,
1397 return SDL_SetError(
"Haptic: Error pausing device: %s.", FFStrError(ret));
1412 ret = FFDeviceSendForceFeedbackCommand(
haptic->hwdata->device,
1415 return SDL_SetError(
"Haptic: Error pausing device: %s.", FFStrError(ret));
1430 ret = FFDeviceSendForceFeedbackCommand(
haptic->hwdata->device,
1433 return SDL_SetError(
"Haptic: Error stopping device: %s.", FFStrError(ret));
#define SDL_assert(condition)
#define SDL_OutOfMemory()
The SDL haptic subsystem allows you to control haptic (force feedback) devices.
#define SDL_HAPTIC_INERTIA
Inertia effect supported - uses axes acceleration.
#define SDL_HAPTIC_SPHERICAL
Uses spherical coordinates for the direction.
#define SDL_HAPTIC_AUTOCENTER
Device can set autocenter.
#define SDL_HAPTIC_GAIN
Device can set global gain.
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
#define SDL_HAPTIC_INFINITY
Used to play a device an infinite number of times.
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.
#define SDL_HAPTIC_PAUSE
Device can be paused.
#define SDL_HAPTIC_CUSTOM
Custom effect is supported.
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
#define SDL_HAPTIC_STEERING_AXIS
Use this value to play an effect on the steering wheel axis. This provides better compatibility acros...
#define SDL_HAPTIC_SINE
Sine wave effect supported.
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
#define SDL_HAPTIC_STATUS
Device can be queried for effect status.
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
#define SDL_HAPTIC_TRIANGLE
Triangle wave effect supported.
#define SDL_HAPTIC_RAMP
Ramp effect supported.
#define SDL_HAPTIC_CARTESIAN
Uses cartesian coordinates for the direction.
#define SDL_HAPTIC_SAWTOOTHDOWN
Sawtoothdown wave effect supported.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLuint GLuint GLsizei GLenum type
GLuint const GLchar * name
GLsizeiptr const void GLenum usage
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticPause(SDL_Haptic *haptic)
int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
const char * SDL_SYS_HapticName(int index)
void SDL_SYS_HapticQuit(void)
int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticMouse(void)
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
int SDL_SYS_NumHaptics(void)
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticInit(void)
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
SDL_JoystickDriver SDL_DARWIN_JoystickDriver
SDL_hapticlist_item * SDL_hapticlist
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
int MacHaptic_MaybeRemoveDevice(io_object_t device)
int MacHaptic_MaybeAddDevice(io_object_t device)
static SDL_AudioDeviceID device
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst base
A structure containing a template for a Condition effect.
SDL_HapticDirection direction
A structure containing a template for a Constant effect.
SDL_HapticDirection direction
A structure containing a template for the SDL_HAPTIC_CUSTOM effect.
SDL_HapticDirection direction
Structure that represents a haptic direction.
A structure containing a template for a Periodic effect.
SDL_HapticDirection direction
A structure containing a template for a Ramp effect.
SDL_HapticDirection direction
struct SDL_hapticlist_item * next
struct haptic_hweffect * hweffect
static SDL_Haptic * haptic
static SDL_Joystick * joystick
The generic template for any haptic effect.