21 #include "../../SDL_internal.h" 23 #ifdef SDL_HAPTIC_IOKIT 28 #include "../SDL_syshaptic.h" 30 #include "../../joystick/SDL_sysjoystick.h" 31 #include "../../joystick/darwin/SDL_sysjoystick_c.h" 32 #include "SDL_syshaptic_c.h" 34 #include <IOKit/IOKitLib.h> 35 #include <IOKit/hid/IOHIDKeys.h> 36 #include <IOKit/hid/IOHIDUsageTables.h> 37 #include <ForceFeedback/ForceFeedback.h> 38 #include <ForceFeedback/ForceFeedbackConstants.h> 40 #ifndef IO_OBJECT_NULL 41 #define IO_OBJECT_NULL ((io_service_t)0) 67 FFDeviceObjectReference
device;
77 FFEffectObjectReference
ref;
78 struct FFEFFECT effect;
84 static void SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect,
int type);
85 static int HIDGetDeviceProduct(io_service_t dev,
char *
name);
89 static int numhaptics = -1;
95 FFStrError(
unsigned int err)
98 case FFERR_DEVICEFULL:
103 case FFERR_DEVICEPAUSED:
104 return "device paused";
105 case FFERR_DEVICERELEASED:
106 return "device released";
107 case FFERR_EFFECTPLAYING:
108 return "effect playing";
109 case FFERR_EFFECTTYPEMISMATCH:
110 return "effect type mismatch";
111 case FFERR_EFFECTTYPENOTSUPPORTED:
112 return "effect type not supported";
114 return "undetermined error";
115 case FFERR_HASEFFECTS:
116 return "device has effects";
117 case FFERR_INCOMPLETEEFFECT:
118 return "incomplete effect";
120 return "internal fault";
121 case FFERR_INVALIDDOWNLOADID:
122 return "invalid download id";
123 case FFERR_INVALIDPARAM:
124 return "invalid parameter";
127 case FFERR_NOINTERFACE:
128 return "interface not supported";
129 case FFERR_NOTDOWNLOADED:
130 return "effect is not downloaded";
131 case FFERR_NOTINITIALIZED:
132 return "object has not been initialized";
133 case FFERR_OUTOFMEMORY:
134 return "out of memory";
135 case FFERR_UNPLUGGED:
136 return "device is unplugged";
137 case FFERR_UNSUPPORTED:
138 return "function call unsupported";
139 case FFERR_UNSUPPORTEDAXIS:
140 return "axis unsupported";
143 return "unknown error";
156 CFDictionaryRef match;
159 if (numhaptics != -1) {
160 return SDL_SetError(
"Haptic subsystem already initialized!");
165 match = IOServiceMatching(kIOHIDDeviceKey);
167 return SDL_SetError(
"Haptic: Failed to get IOServiceMatching.");
171 result = IOServiceGetMatchingServices(kIOMasterPortDefault, match, &iter);
172 if (result != kIOReturnSuccess) {
173 return SDL_SetError(
"Haptic: Couldn't create a HID object iterator.");
177 if (!IOIteratorIsValid(iter)) {
181 while ((device = IOIteratorNext(iter)) != IO_OBJECT_NULL) {
184 IOObjectRelease(device);
186 IOObjectRelease(iter);
198 HapticByDevIndex(
int device_index)
202 if ((device_index < 0) || (device_index >= numhaptics)) {
206 while (device_index > 0) {
219 CFMutableDictionaryRef hidProperties;
223 if (numhaptics == -1) {
228 if (FFIsForceFeedback(device) != FF_OK) {
233 for (item = SDL_hapticlist; item ; item = item->
next)
235 if (IOObjectIsEqualTo((io_object_t) item->dev, device)) {
243 return SDL_SetError(
"Could not allocate haptic storage");
247 IOObjectRetain(device);
250 HIDGetDeviceProduct(device, item->
name);
256 result = IORegistryEntryCreateCFProperties(device,
260 if ((result == KERN_SUCCESS) && hidProperties) {
261 refCF = CFDictionaryGetValue(hidProperties,
262 CFSTR(kIOHIDPrimaryUsagePageKey));
264 if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usagePage)) {
267 refCF = CFDictionaryGetValue(hidProperties,
268 CFSTR(kIOHIDPrimaryUsageKey));
270 if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usage)) {
275 CFRelease(hidProperties);
278 if (SDL_hapticlist_tail ==
NULL) {
279 SDL_hapticlist = SDL_hapticlist_tail = item;
281 SDL_hapticlist_tail->
next = item;
282 SDL_hapticlist_tail = item;
297 if (numhaptics == -1) {
301 for (item = SDL_hapticlist; item !=
NULL; item = item->
next) {
303 if (IOObjectIsEqualTo((io_object_t) item->dev, device)) {
310 SDL_hapticlist = item->
next;
312 if (item == SDL_hapticlist_tail) {
313 SDL_hapticlist_tail = prev;
320 IOObjectRelease(item->dev);
337 item = HapticByDevIndex(index);
345 HIDGetDeviceProduct(io_service_t dev,
char *
name)
347 CFMutableDictionaryRef hidProperties, usbProperties;
348 io_registry_entry_t parent1, parent2;
351 hidProperties = usbProperties = 0;
353 ret = IORegistryEntryCreateCFProperties(dev, &hidProperties,
354 kCFAllocatorDefault, kNilOptions);
355 if ((ret != KERN_SUCCESS) || !hidProperties) {
356 return SDL_SetError(
"Haptic: Unable to create CFProperties.");
363 IORegistryEntryGetParentEntry(dev, kIOServicePlane, &parent1))
365 IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2))
367 IORegistryEntryCreateCFProperties(parent2, &usbProperties,
378 refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey));
380 refCF = CFDictionaryGetValue(usbProperties,
381 CFSTR(
"USB Product Name"));
384 if (!CFStringGetCString(refCF, name, 256,
385 CFStringGetSystemEncoding())) {
386 return SDL_SetError(
"Haptic: CFStringGetCString error retrieving pDevice->product.");
390 CFRelease(usbProperties);
392 return SDL_SetError(
"Haptic: IORegistryEntryCreateCFProperties failed to create usbProperties.");
396 if (kIOReturnSuccess != IOObjectRelease(parent2)) {
397 SDL_SetError(
"Haptic: IOObjectRelease error with parent2.");
399 if (kIOReturnSuccess != IOObjectRelease(parent1)) {
400 SDL_SetError(
"Haptic: IOObjectRelease error with parent1.");
403 return SDL_SetError(
"Haptic: Error getting registry entries.");
410 #define FF_TEST(ff, s) \ 411 if (features.supportedEffects & (ff)) supported |= (s) 416 GetSupportedFeatures(SDL_Haptic *
haptic)
419 FFDeviceObjectReference
device;
420 FFCAPABILITIES features;
421 unsigned int supported;
424 device = haptic->hwdata->device;
426 ret = FFDeviceGetForceFeedbackCapabilities(device, &features);
428 return SDL_SetError(
"Haptic: Unable to get device's supported features.");
434 haptic->neffects = features.storageCapacity;
435 haptic->nplaying = features.playbackCapacity;
453 ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_FFGAIN,
457 }
else if (ret != FFERR_UNSUPPORTED) {
458 return SDL_SetError(
"Haptic: Unable to get if device supports gain: %s.",
463 ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_AUTOCENTER,
467 }
else if (ret != FFERR_UNSUPPORTED) {
469 (
"Haptic: Unable to get if device supports autocenter: %s.",
474 haptic->naxes = ((features.numFfAxes) > 3) ? 3 : features.numFfAxes;
476 SDL_memcpy(haptic->hwdata->axes, features.ffAxes,
477 haptic->naxes *
sizeof(
Uint8));
482 haptic->supported = supported;
491 SDL_SYS_HapticOpenFromService(SDL_Haptic * haptic, io_service_t service)
499 if (haptic->hwdata ==
NULL) {
503 SDL_memset(haptic->hwdata, 0,
sizeof(*haptic->hwdata));
506 ret = FFCreateDevice(service, &haptic->hwdata->device);
508 SDL_SetError(
"Haptic: Unable to create device from service: %s.",
514 ret2 = GetSupportedFeatures(haptic);
521 ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
524 SDL_SetError(
"Haptic: Unable to reset device: %s.", FFStrError(ret));
527 ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
528 FFSFFC_SETACTUATORSON);
539 if (haptic->effects ==
NULL) {
551 FFReleaseDevice(haptic->hwdata->device);
553 if (haptic->hwdata !=
NULL) {
555 haptic->hwdata =
NULL;
569 item = HapticByDevIndex(haptic->index);
571 return SDL_SYS_HapticOpenFromService(haptic, item->dev);
581 int device_index = 0;
584 for (item = SDL_hapticlist; item; item = item->
next) {
585 if ((item->usagePage == kHIDPage_GenericDesktop) &&
586 (item->usage == kHIDUsage_GD_Mouse)) {
602 if (joystick->hwdata->ffservice != 0) {
615 if (IOObjectIsEqualTo((io_object_t) ((
size_t)haptic->hwdata->device),
616 joystick->hwdata->ffservice)) {
629 int device_index = 0;
632 for (item = SDL_hapticlist; item; item = item->
next) {
633 if (IOObjectIsEqualTo((io_object_t) item->dev,
634 joystick->hwdata->ffservice)) {
635 haptic->index = device_index;
641 return SDL_SYS_HapticOpenFromService(haptic, joystick->hwdata->ffservice);
651 if (haptic->hwdata) {
655 haptic->effects =
NULL;
656 haptic->neffects = 0;
659 FFReleaseDevice(haptic->hwdata->device);
663 haptic->hwdata =
NULL;
677 for (item = SDL_hapticlist; item; item =
next) {
683 IOObjectRelease(item->dev);
688 SDL_hapticlist =
NULL;
689 SDL_hapticlist_tail =
NULL;
699 DWORD dwTriggerButton;
701 dwTriggerButton = FFEB_NOTRIGGER;
704 dwTriggerButton = FFJOFS_BUTTON(button - 1);
707 return dwTriggerButton;
721 effect->dwFlags |= FFEFF_SPHERICAL;
722 effect->rglDirection =
NULL;
728 if (rglDir ==
NULL) {
732 effect->rglDirection = rglDir;
736 effect->dwFlags |= FFEFF_POLAR;
737 rglDir[0] = dir->
dir[0];
740 effect->dwFlags |= FFEFF_CARTESIAN;
741 rglDir[0] = dir->
dir[0];
743 rglDir[1] = dir->
dir[1];
746 rglDir[2] = dir->
dir[2];
750 effect->dwFlags |= FFEFF_SPHERICAL;
751 rglDir[0] = dir->
dir[0];
753 rglDir[1] = dir->
dir[1];
756 rglDir[2] = dir->
dir[2];
767 #define CCONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF) 769 #define CONVERT(x) (((x)*10000) / 0x7FFF) 777 FFCONSTANTFORCE *constant =
NULL;
778 FFPERIODIC *periodic =
NULL;
780 FFRAMPFORCE *ramp =
NULL;
781 FFCUSTOMFORCE *custom =
NULL;
782 FFENVELOPE *envelope =
NULL;
792 dest->dwSize =
sizeof(FFEFFECT);
793 dest->dwSamplePeriod = 0;
794 dest->dwGain = 10000;
795 dest->dwFlags = FFEFF_OBJECTOFFSETS;
799 if (envelope ==
NULL) {
803 dest->lpEnvelope = envelope;
804 envelope->dwSize =
sizeof(FFENVELOPE);
807 dest->cAxes = haptic->naxes;
808 if (dest->cAxes > 0) {
809 axes =
SDL_malloc(
sizeof(DWORD) * dest->cAxes);
813 axes[0] = haptic->hwdata->axes[0];
814 if (dest->cAxes > 1) {
815 axes[1] = haptic->hwdata->axes[1];
817 if (dest->cAxes > 2) {
818 axes[2] = haptic->hwdata->axes[2];
820 dest->rgdwAxes = axes;
828 constant =
SDL_malloc(
sizeof(FFCONSTANTFORCE));
829 if (constant ==
NULL) {
832 SDL_memset(constant, 0,
sizeof(FFCONSTANTFORCE));
835 constant->lMagnitude = CONVERT(hap_constant->
level);
836 dest->cbTypeSpecificParams =
sizeof(FFCONSTANTFORCE);
837 dest->lpvTypeSpecificParams = constant;
840 dest->dwDuration = hap_constant->
length * 1000;
841 dest->dwTriggerButton = FFGetTriggerButton(hap_constant->
button);
842 dest->dwTriggerRepeatInterval = hap_constant->
interval;
843 dest->dwStartDelay = hap_constant->
delay * 1000;
846 if (SDL_SYS_SetDirection(dest, &hap_constant->
direction, dest->cAxes)
855 dest->lpEnvelope =
NULL;
857 envelope->dwAttackLevel = CCONVERT(hap_constant->
attack_level);
859 envelope->dwFadeLevel = CCONVERT(hap_constant->
fade_level);
860 envelope->dwFadeTime = hap_constant->
fade_length * 1000;
873 if (periodic ==
NULL) {
880 periodic->lOffset = CONVERT(hap_periodic->
offset);
882 (hap_periodic->
phase + (hap_periodic->
magnitude < 0 ? 18000 : 0)) % 36000;
883 periodic->dwPeriod = hap_periodic->
period * 1000;
884 dest->cbTypeSpecificParams =
sizeof(FFPERIODIC);
885 dest->lpvTypeSpecificParams = periodic;
888 dest->dwDuration = hap_periodic->
length * 1000;
889 dest->dwTriggerButton = FFGetTriggerButton(hap_periodic->
button);
890 dest->dwTriggerRepeatInterval = hap_periodic->
interval;
891 dest->dwStartDelay = hap_periodic->
delay * 1000;
894 if (SDL_SYS_SetDirection(dest, &hap_periodic->
direction, dest->cAxes)
903 dest->lpEnvelope =
NULL;
905 envelope->dwAttackLevel = CCONVERT(hap_periodic->
attack_level);
907 envelope->dwFadeLevel = CCONVERT(hap_periodic->
fade_level);
908 envelope->dwFadeTime = hap_periodic->
fade_length * 1000;
918 if (dest->cAxes > 0) {
919 condition =
SDL_malloc(
sizeof(FFCONDITION) * dest->cAxes);
920 if (condition ==
NULL) {
923 SDL_memset(condition, 0,
sizeof(FFCONDITION));
926 for (i = 0; i < dest->cAxes; i++) {
927 condition[
i].lOffset = CONVERT(hap_condition->
center[i]);
928 condition[
i].lPositiveCoefficient =
930 condition[
i].lNegativeCoefficient =
932 condition[
i].dwPositiveSaturation =
933 CCONVERT(hap_condition->
right_sat[i] / 2);
934 condition[
i].dwNegativeSaturation =
935 CCONVERT(hap_condition->
left_sat[i] / 2);
936 condition[
i].lDeadBand = CCONVERT(hap_condition->
deadband[i] / 2);
940 dest->cbTypeSpecificParams =
sizeof(FFCONDITION) * dest->cAxes;
941 dest->lpvTypeSpecificParams = condition;
944 dest->dwDuration = hap_condition->
length * 1000;
945 dest->dwTriggerButton = FFGetTriggerButton(hap_condition->
button);
946 dest->dwTriggerRepeatInterval = hap_condition->
interval;
947 dest->dwStartDelay = hap_condition->
delay * 1000;
950 if (SDL_SYS_SetDirection(dest, &hap_condition->
direction, dest->cAxes)
957 dest->lpEnvelope =
NULL;
962 hap_ramp = &src->
ramp;
970 ramp->lStart = CONVERT(hap_ramp->
start);
971 ramp->lEnd = CONVERT(hap_ramp->
end);
972 dest->cbTypeSpecificParams =
sizeof(FFRAMPFORCE);
973 dest->lpvTypeSpecificParams = ramp;
976 dest->dwDuration = hap_ramp->
length * 1000;
977 dest->dwTriggerButton = FFGetTriggerButton(hap_ramp->
button);
978 dest->dwTriggerRepeatInterval = hap_ramp->
interval;
979 dest->dwStartDelay = hap_ramp->
delay * 1000;
982 if (SDL_SYS_SetDirection(dest, &hap_ramp->
direction, dest->cAxes) < 0) {
989 dest->lpEnvelope =
NULL;
991 envelope->dwAttackLevel = CCONVERT(hap_ramp->
attack_level);
993 envelope->dwFadeLevel = CCONVERT(hap_ramp->
fade_level);
994 envelope->dwFadeTime = hap_ramp->
fade_length * 1000;
1000 hap_custom = &src->
custom;
1002 if (custom ==
NULL) {
1005 SDL_memset(custom, 0,
sizeof(FFCUSTOMFORCE));
1008 custom->cChannels = hap_custom->
channels;
1009 custom->dwSamplePeriod = hap_custom->
period * 1000;
1010 custom->cSamples = hap_custom->
samples;
1011 custom->rglForceData =
1012 SDL_malloc(
sizeof(LONG) * custom->cSamples * custom->cChannels);
1014 custom->rglForceData[
i] = CCONVERT(hap_custom->
data[i]);
1016 dest->cbTypeSpecificParams =
sizeof(FFCUSTOMFORCE);
1017 dest->lpvTypeSpecificParams = custom;
1020 dest->dwDuration = hap_custom->
length * 1000;
1021 dest->dwTriggerButton = FFGetTriggerButton(hap_custom->
button);
1022 dest->dwTriggerRepeatInterval = hap_custom->
interval;
1023 dest->dwStartDelay = hap_custom->
delay * 1000;
1026 if (SDL_SYS_SetDirection(dest, &hap_custom->
direction, dest->cAxes) <
1035 dest->lpEnvelope =
NULL;
1037 envelope->dwAttackLevel = CCONVERT(hap_custom->
attack_level);
1039 envelope->dwFadeLevel = CCONVERT(hap_custom->
fade_level);
1040 envelope->dwFadeTime = hap_custom->
fade_length * 1000;
1058 SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect,
int type)
1060 FFCUSTOMFORCE *custom;
1063 effect->lpEnvelope =
NULL;
1065 effect->rgdwAxes =
NULL;
1066 if (effect->lpvTypeSpecificParams !=
NULL) {
1068 custom = (FFCUSTOMFORCE *) effect->lpvTypeSpecificParams;
1070 custom->rglForceData =
NULL;
1072 SDL_free(effect->lpvTypeSpecificParams);
1073 effect->lpvTypeSpecificParams =
NULL;
1076 effect->rglDirection =
NULL;
1084 SDL_SYS_HapticEffectType(
Uint16 type)
1088 return kFFEffectType_ConstantForce_ID;
1091 return kFFEffectType_RampForce_ID;
1098 return kFFEffectType_Sine_ID;
1101 return kFFEffectType_Triangle_ID;
1104 return kFFEffectType_SawtoothUp_ID;
1107 return kFFEffectType_SawtoothDown_ID;
1110 return kFFEffectType_Spring_ID;
1113 return kFFEffectType_Damper_ID;
1116 return kFFEffectType_Inertia_ID;
1119 return kFFEffectType_Friction_ID;
1122 return kFFEffectType_CustomForce_ID;
1150 type = SDL_SYS_HapticEffectType(base->
type);
1156 if (SDL_SYS_ToFFEFFECT(haptic, &effect->
hweffect->effect, base) < 0) {
1157 goto err_effectdone;
1161 ret = FFDeviceCreateEffect(haptic->hwdata->device, type,
1165 SDL_SetError(
"Haptic: Unable to create effect: %s.", FFStrError(ret));
1166 goto err_effectdone;
1172 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect, base->
type);
1189 FFEffectParameterFlag
flags;
1194 if (SDL_SYS_ToFFEFFECT(haptic, &temp, data) < 0) {
1200 flags = FFEP_DIRECTION |
1204 FFEP_TRIGGERBUTTON |
1205 FFEP_TRIGGERREPEATINTERVAL | FFEP_TYPESPECIFICPARAMS;
1208 ret = FFEffectSetParameters(effect->
hweffect->ref, &temp, flags);
1210 SDL_SetError(
"Haptic: Unable to update effect: %s.", FFStrError(ret));
1215 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect, data->
type);
1221 SDL_SYS_HapticFreeFFEFFECT(&temp, data->
type);
1243 ret = FFEffectStart(effect->
hweffect->ref, iter, 0);
1245 return SDL_SetError(
"Haptic: Unable to run the effect: %s.",
1261 ret = FFEffectStop(effect->
hweffect->ref);
1263 return SDL_SetError(
"Haptic: Unable to stop the effect: %s.",
1279 ret = FFDeviceReleaseEffect(haptic->hwdata->device, effect->
hweffect->ref);
1281 SDL_SetError(
"Haptic: Error removing the effect from the device: %s.",
1284 SDL_SYS_HapticFreeFFEFFECT(&effect->
hweffect->effect,
1299 FFEffectStatusFlag status;
1301 ret = FFEffectGetEffectStatus(effect->
hweffect->ref, &status);
1303 SDL_SetError(
"Haptic: Unable to get effect status: %s.",
1325 ret = FFDeviceSetForceFeedbackProperty(haptic->hwdata->device,
1326 FFPROP_FFGAIN, &val);
1328 return SDL_SetError(
"Haptic: Error setting gain: %s.", FFStrError(ret));
1345 if (autocenter == 0) {
1351 ret = FFDeviceSetForceFeedbackProperty(haptic->hwdata->device,
1352 FFPROP_AUTOCENTER, &val);
1354 return SDL_SetError(
"Haptic: Error setting autocenter: %s.",
1370 ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
1373 return SDL_SetError(
"Haptic: Error pausing device: %s.", FFStrError(ret));
1388 ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
1391 return SDL_SetError(
"Haptic: Error pausing device: %s.", FFStrError(ret));
1406 ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
1409 return SDL_SetError(
"Haptic: Error stopping device: %s.", FFStrError(ret));
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
Structure that represents a haptic direction.
#define SDL_HAPTIC_SPHERICAL
Uses spherical coordinates for the direction.
#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.
#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.
int MacHaptic_MaybeRemoveDevice(io_object_t device)
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.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
The SDL haptic subsystem allows you to control haptic (force feedback) devices.
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
int SDL_SYS_NumHaptics(void)
#define SDL_HAPTIC_SINE
Sine wave effect supported.
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
GLuint const GLchar * name
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.
SDL_hapticlist_item * SDL_hapticlist
static SDL_AudioDeviceID device
struct SDL_hapticlist_item * next
SDL_HapticCondition condition
GLsizeiptr const void GLenum usage
The generic template for any haptic effect.
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
SDL_HapticConstant constant
#define SDL_HAPTIC_PAUSE
Device can be paused.
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)
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)
#define SDL_assert(condition)
#define SDL_OutOfMemory()
int SDL_SYS_HapticInit(void)
void SDL_SYS_HapticQuit(void)
int MacHaptic_MaybeAddDevice(io_object_t device)
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)
SDL_HapticDirection direction
#define SDL_HAPTIC_RAMP
Ramp effect supported.
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
GLuint GLuint GLsizei GLenum type
A structure containing a template for the SDL_HAPTIC_CUSTOM effect.
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
#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
#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.