zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_syshaptic.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "SDL_config.h"
22 
23 #ifdef SDL_HAPTIC_IOKIT
24 
25 #include "SDL_haptic.h"
26 #include "../SDL_syshaptic.h"
27 #include "SDL_joystick.h"
28 #include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
29 #include "../../joystick/darwin/SDL_sysjoystick_c.h" /* For joystick hwdata */
30 
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>
36 
37 #ifndef IO_OBJECT_NULL
38 #define IO_OBJECT_NULL ((io_service_t)0)
39 #endif
40 
41 #define MAX_HAPTICS 32
42 
43 
44 /*
45  * List of available haptic devices.
46  */
47 static struct
48 {
49  char name[256]; /* Name of the device. */
50 
51  io_service_t dev; /* Node we use to create the device. */
52  SDL_Haptic *haptic; /* Haptic currently associated with it. */
53 
54  /* Usage pages for determining if it's a mouse or not. */
55  long usage;
56  long usagePage;
57 } SDL_hapticlist[MAX_HAPTICS];
58 
59 
60 /*
61  * Haptic system hardware data.
62  */
63 struct haptic_hwdata
64 {
65  FFDeviceObjectReference device; /* Hardware device. */
66  UInt8 axes[3];
67 };
68 
69 
70 /*
71  * Haptic system effect data.
72  */
73 struct haptic_hweffect
74 {
75  FFEffectObjectReference ref; /* Reference. */
76  struct FFEFFECT effect; /* Hardware effect. */
77 };
78 
79 /*
80  * Prototypes.
81  */
82 static void SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect, int type);
83 static int HIDGetDeviceProduct(io_service_t dev, char *name);
84 
85 
86 /*
87  * Like strerror but for force feedback errors.
88  */
89 static const char *
90 FFStrError(HRESULT err)
91 {
92  switch (err) {
93  case FFERR_DEVICEFULL:
94  return "device full";
95  /* This should be valid, but for some reason isn't defined... */
96  /* case FFERR_DEVICENOTREG:
97  return "device not registered"; */
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";
108  case FFERR_GENERIC:
109  return "undetermined error";
110  case FFERR_HASEFFECTS:
111  return "device has effects";
112  case FFERR_INCOMPLETEEFFECT:
113  return "incomplete effect";
114  case FFERR_INTERNAL:
115  return "internal fault";
116  case FFERR_INVALIDDOWNLOADID:
117  return "invalid download id";
118  case FFERR_INVALIDPARAM:
119  return "invalid parameter";
120  case FFERR_MOREDATA:
121  return "more data";
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";
136 
137  default:
138  return "unknown error";
139  }
140 }
141 
142 
143 /*
144  * Initializes the haptic subsystem.
145  */
146 int
147 SDL_SYS_HapticInit(void)
148 {
149  int numhaptics;
150  IOReturn result;
151  io_iterator_t iter;
152  CFDictionaryRef match;
153  io_service_t device;
154  CFMutableDictionaryRef hidProperties;
155  CFTypeRef refCF;
156 
157  /* Clear all the memory. */
158  SDL_memset(SDL_hapticlist, 0, sizeof(SDL_hapticlist));
159 
160  /* Get HID devices. */
161  match = IOServiceMatching(kIOHIDDeviceKey);
162  if (match == NULL) {
163  return SDL_SetError("Haptic: Failed to get IOServiceMatching.");
164  }
165 
166  /* Now search I/O Registry for matching devices. */
167  result = IOServiceGetMatchingServices(kIOMasterPortDefault, match, &iter);
168  if (result != kIOReturnSuccess) {
169  return SDL_SetError("Haptic: Couldn't create a HID object iterator.");
170  }
171  /* IOServiceGetMatchingServices consumes dictionary. */
172 
173  if (!IOIteratorIsValid(iter)) { /* No iterator. */
174  return 0;
175  }
176 
177  numhaptics = 0;
178  while ((device = IOIteratorNext(iter)) != IO_OBJECT_NULL) {
179 
180  /* Check for force feedback. */
181  if (FFIsForceFeedback(device) == FF_OK) {
182 
183  /* Set basic device data. */
184  HIDGetDeviceProduct(device, SDL_hapticlist[numhaptics].name);
185  SDL_hapticlist[numhaptics].dev = device;
186  SDL_hapticlist[numhaptics].haptic = NULL;
187 
188  /* Set usage pages. */
189  hidProperties = 0;
190  refCF = 0;
191  result = IORegistryEntryCreateCFProperties(device,
192  &hidProperties,
193  kCFAllocatorDefault,
194  kNilOptions);
195  if ((result == KERN_SUCCESS) && hidProperties) {
196  refCF =
197  CFDictionaryGetValue(hidProperties,
198  CFSTR(kIOHIDPrimaryUsagePageKey));
199  if (refCF) {
200  if (!CFNumberGetValue(refCF, kCFNumberLongType,
201  &SDL_hapticlist[numhaptics].
202  usagePage))
204  ("Haptic: Recieving device's usage page.");
205  refCF =
206  CFDictionaryGetValue(hidProperties,
207  CFSTR(kIOHIDPrimaryUsageKey));
208  if (refCF) {
209  if (!CFNumberGetValue(refCF, kCFNumberLongType,
210  &SDL_hapticlist[numhaptics].
211  usage))
212  SDL_SetError("Haptic: Recieving device's usage.");
213  }
214  }
215  CFRelease(hidProperties);
216  }
217 
218  /* Device has been added. */
219  numhaptics++;
220  } else { /* Free the unused device. */
221  IOObjectRelease(device);
222  }
223 
224  /* Reached haptic limit. */
225  if (numhaptics >= MAX_HAPTICS)
226  break;
227  }
228  IOObjectRelease(iter);
229 
230  return numhaptics;
231 }
232 
233 
234 /*
235  * Return the name of a haptic device, does not need to be opened.
236  */
237 const char *
239 {
240  return SDL_hapticlist[index].name;
241 }
242 
243 /*
244  * Gets the device's product name.
245  */
246 static int
247 HIDGetDeviceProduct(io_service_t dev, char *name)
248 {
249  CFMutableDictionaryRef hidProperties, usbProperties;
250  io_registry_entry_t parent1, parent2;
251  kern_return_t ret;
252 
253  hidProperties = usbProperties = 0;
254 
255  ret = IORegistryEntryCreateCFProperties(dev, &hidProperties,
256  kCFAllocatorDefault, kNilOptions);
257  if ((ret != KERN_SUCCESS) || !hidProperties) {
258  return SDL_SetError("Haptic: Unable to create CFProperties.");
259  }
260 
261  /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also
262  * get dictionary for USB properties: step up two levels and get CF dictionary for USB properties
263  */
264  if ((KERN_SUCCESS ==
265  IORegistryEntryGetParentEntry(dev, kIOServicePlane, &parent1))
266  && (KERN_SUCCESS ==
267  IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2))
268  && (KERN_SUCCESS ==
269  IORegistryEntryCreateCFProperties(parent2, &usbProperties,
270  kCFAllocatorDefault,
271  kNilOptions))) {
272  if (usbProperties) {
273  CFTypeRef refCF = 0;
274  /* get device info
275  * try hid dictionary first, if fail then go to USB dictionary
276  */
277 
278 
279  /* Get product name */
280  refCF =
281  CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey));
282  if (!refCF)
283  refCF =
284  CFDictionaryGetValue(usbProperties,
285  CFSTR("USB Product Name"));
286  if (refCF) {
287  if (!CFStringGetCString(refCF, name, 256,
288  CFStringGetSystemEncoding())) {
289  return SDL_SetError
290  ("Haptic: CFStringGetCString error retrieving pDevice->product.");
291  }
292  }
293 
294  CFRelease(usbProperties);
295  } else {
296  return SDL_SetError
297  ("Haptic: IORegistryEntryCreateCFProperties failed to create usbProperties.");
298  }
299 
300  /* Release stuff. */
301  if (kIOReturnSuccess != IOObjectRelease(parent2)) {
302  SDL_SetError("Haptic: IOObjectRelease error with parent2.");
303  }
304  if (kIOReturnSuccess != IOObjectRelease(parent1)) {
305  SDL_SetError("Haptic: IOObjectRelease error with parent1.");
306  }
307  } else {
308  return SDL_SetError("Haptic: Error getting registry entries.");
309  }
310 
311  return 0;
312 }
313 
314 
315 #define FF_TEST(ff, s) \
316 if (features.supportedEffects & (ff)) supported |= (s)
317 /*
318  * Gets supported features.
319  */
320 static unsigned int
321 GetSupportedFeatures(SDL_Haptic * haptic)
322 {
323  HRESULT ret;
324  FFDeviceObjectReference device;
325  FFCAPABILITIES features;
326  unsigned int supported;
327  Uint32 val;
328 
329  device = haptic->hwdata->device;
330 
331  ret = FFDeviceGetForceFeedbackCapabilities(device, &features);
332  if (ret != FF_OK) {
333  return SDL_SetError("Haptic: Unable to get device's supported features.");
334  }
335 
336  supported = 0;
337 
338  /* Get maximum effects. */
339  haptic->neffects = features.storageCapacity;
340  haptic->nplaying = features.playbackCapacity;
341 
342  /* Test for effects. */
343  FF_TEST(FFCAP_ET_CONSTANTFORCE, SDL_HAPTIC_CONSTANT);
344  FF_TEST(FFCAP_ET_RAMPFORCE, SDL_HAPTIC_RAMP);
345  /* !!! FIXME: put this back when we have more bits in 2.1 */
346  /* FF_TEST(FFCAP_ET_SQUARE, SDL_HAPTIC_SQUARE); */
347  FF_TEST(FFCAP_ET_SINE, SDL_HAPTIC_SINE);
348  FF_TEST(FFCAP_ET_TRIANGLE, SDL_HAPTIC_TRIANGLE);
349  FF_TEST(FFCAP_ET_SAWTOOTHUP, SDL_HAPTIC_SAWTOOTHUP);
350  FF_TEST(FFCAP_ET_SAWTOOTHDOWN, SDL_HAPTIC_SAWTOOTHDOWN);
351  FF_TEST(FFCAP_ET_SPRING, SDL_HAPTIC_SPRING);
352  FF_TEST(FFCAP_ET_DAMPER, SDL_HAPTIC_DAMPER);
353  FF_TEST(FFCAP_ET_INERTIA, SDL_HAPTIC_INERTIA);
354  FF_TEST(FFCAP_ET_FRICTION, SDL_HAPTIC_FRICTION);
355  FF_TEST(FFCAP_ET_CUSTOMFORCE, SDL_HAPTIC_CUSTOM);
356 
357  /* Check if supports gain. */
358  ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_FFGAIN,
359  &val, sizeof(val));
360  if (ret == FF_OK)
361  supported |= SDL_HAPTIC_GAIN;
362  else if (ret != FFERR_UNSUPPORTED) {
363  return SDL_SetError("Haptic: Unable to get if device supports gain: %s.",
364  FFStrError(ret));
365  }
366 
367  /* Checks if supports autocenter. */
368  ret = FFDeviceGetForceFeedbackProperty(device, FFPROP_AUTOCENTER,
369  &val, sizeof(val));
370  if (ret == FF_OK)
371  supported |= SDL_HAPTIC_AUTOCENTER;
372  else if (ret != FFERR_UNSUPPORTED) {
373  return SDL_SetError
374  ("Haptic: Unable to get if device supports autocenter: %s.",
375  FFStrError(ret));
376  }
377 
378  /* Check for axes, we have an artificial limit on axes */
379  haptic->naxes = ((features.numFfAxes) > 3) ? 3 : features.numFfAxes;
380  /* Actually store the axes we want to use */
381  SDL_memcpy(haptic->hwdata->axes, features.ffAxes,
382  haptic->naxes * sizeof(Uint8));
383 
384  /* Always supported features. */
385  supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
386 
387  haptic->supported = supported;
388  return 0;;
389 }
390 
391 
392 /*
393  * Opens the haptic device from the file descriptor.
394  */
395 static int
396 SDL_SYS_HapticOpenFromService(SDL_Haptic * haptic, io_service_t service)
397 {
398  HRESULT ret;
399  int ret2;
400 
401  /* Allocate the hwdata */
402  haptic->hwdata = (struct haptic_hwdata *)
403  SDL_malloc(sizeof(*haptic->hwdata));
404  if (haptic->hwdata == NULL) {
405  SDL_OutOfMemory();
406  goto creat_err;
407  }
408  SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
409 
410  /* Open the device */
411  ret = FFCreateDevice(service, &haptic->hwdata->device);
412  if (ret != FF_OK) {
413  SDL_SetError("Haptic: Unable to create device from service: %s.",
414  FFStrError(ret));
415  goto creat_err;
416  }
417 
418  /* Get supported features. */
419  ret2 = GetSupportedFeatures(haptic);
420  if (ret2 < 0) {
421  goto open_err;
422  }
423 
424 
425  /* Reset and then enable actuators. */
426  ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
427  FFSFFC_RESET);
428  if (ret != FF_OK) {
429  SDL_SetError("Haptic: Unable to reset device: %s.", FFStrError(ret));
430  goto open_err;
431  }
432  ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
433  FFSFFC_SETACTUATORSON);
434  if (ret != FF_OK) {
435  SDL_SetError("Haptic: Unable to enable actuators: %s.",
436  FFStrError(ret));
437  goto open_err;
438  }
439 
440 
441  /* Allocate effects memory. */
442  haptic->effects = (struct haptic_effect *)
443  SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
444  if (haptic->effects == NULL) {
445  SDL_OutOfMemory();
446  goto open_err;
447  }
448  /* Clear the memory */
449  SDL_memset(haptic->effects, 0,
450  sizeof(struct haptic_effect) * haptic->neffects);
451 
452  return 0;
453 
454  /* Error handling */
455  open_err:
456  FFReleaseDevice(haptic->hwdata->device);
457  creat_err:
458  if (haptic->hwdata != NULL) {
459  free(haptic->hwdata);
460  haptic->hwdata = NULL;
461  }
462  return -1;
463 
464 }
465 
466 
467 /*
468  * Opens a haptic device for usage.
469  */
470 int
472 {
473  return SDL_SYS_HapticOpenFromService(haptic,
474  SDL_hapticlist[haptic->index].dev);
475 }
476 
477 
478 /*
479  * Opens a haptic device from first mouse it finds for usage.
480  */
481 int
483 {
484  int i;
485 
486  for (i = 0; i < SDL_numhaptics; i++) {
487  if ((SDL_hapticlist[i].usagePage == kHIDPage_GenericDesktop) &&
488  (SDL_hapticlist[i].usage == kHIDUsage_GD_Mouse))
489  return i;
490  }
491 
492  return -1;
493 }
494 
495 
496 /*
497  * Checks to see if a joystick has haptic features.
498  */
499 int
501 {
502  if (joystick->hwdata->ffservice != 0)
503  return SDL_TRUE;
504  return SDL_FALSE;
505 }
506 
507 
508 /*
509  * Checks to see if the haptic device and joystick are in reality the same.
510  */
511 int
513 {
514  if (IOObjectIsEqualTo((io_object_t) ((size_t)haptic->hwdata->device),
515  joystick->hwdata->ffservice))
516  return 1;
517  return 0;
518 }
519 
520 
521 /*
522  * Opens a SDL_Haptic from a SDL_Joystick.
523  */
524 int
526 {
527  int i;
528  for (i=0; i<SDL_numhaptics; i++) {
529  if (IOObjectIsEqualTo((io_object_t) SDL_hapticlist[i].dev,
530  joystick->hwdata->ffservice)) {
531  haptic->index = i;
532  break;
533  }
534  }
535  if (i >= SDL_numhaptics) {
536  return -1;
537  }
538 
539  return SDL_SYS_HapticOpenFromService(haptic, joystick->hwdata->ffservice);
540 }
541 
542 
543 /*
544  * Closes the haptic device.
545  */
546 void
548 {
549  if (haptic->hwdata) {
550 
551  /* Free Effects. */
552  SDL_free(haptic->effects);
553  haptic->effects = NULL;
554  haptic->neffects = 0;
555 
556  /* Clean up */
557  FFReleaseDevice(haptic->hwdata->device);
558 
559  /* Free */
560  SDL_free(haptic->hwdata);
561  haptic->hwdata = NULL;
562  }
563 }
564 
565 
566 /*
567  * Clean up after system specific haptic stuff
568  */
569 void
570 SDL_SYS_HapticQuit(void)
571 {
572  int i;
573 
574  for (i = 0; i < SDL_numhaptics; i++) {
575  /* Opened and not closed haptics are leaked, this is on purpose.
576  * Close your haptic devices after usage. */
577 
578  /* Free the io_service_t */
579  IOObjectRelease(SDL_hapticlist[i].dev);
580  }
581 }
582 
583 
584 /*
585  * Converts an SDL trigger button to an FFEFFECT trigger button.
586  */
587 static DWORD
588 FFGetTriggerButton(Uint16 button)
589 {
590  DWORD dwTriggerButton;
591 
592  dwTriggerButton = FFEB_NOTRIGGER;
593 
594  if (button != 0) {
595  dwTriggerButton = FFJOFS_BUTTON(button - 1);
596  }
597 
598  return dwTriggerButton;
599 }
600 
601 
602 /*
603  * Sets the direction.
604  */
605 static int
606 SDL_SYS_SetDirection(FFEFFECT * effect, SDL_HapticDirection * dir, int naxes)
607 {
608  LONG *rglDir;
609 
610  /* Handle no axes a part. */
611  if (naxes == 0) {
612  effect->dwFlags |= FFEFF_SPHERICAL; /* Set as default. */
613  effect->rglDirection = NULL;
614  return 0;
615  }
616 
617  /* Has axes. */
618  rglDir = SDL_malloc(sizeof(LONG) * naxes);
619  if (rglDir == NULL) {
620  return SDL_OutOfMemory();
621  }
622  SDL_memset(rglDir, 0, sizeof(LONG) * naxes);
623  effect->rglDirection = rglDir;
624 
625  switch (dir->type) {
626  case SDL_HAPTIC_POLAR:
627  effect->dwFlags |= FFEFF_POLAR;
628  rglDir[0] = dir->dir[0];
629  return 0;
631  effect->dwFlags |= FFEFF_CARTESIAN;
632  rglDir[0] = dir->dir[0];
633  if (naxes > 1)
634  rglDir[1] = dir->dir[1];
635  if (naxes > 2)
636  rglDir[2] = dir->dir[2];
637  return 0;
639  effect->dwFlags |= FFEFF_SPHERICAL;
640  rglDir[0] = dir->dir[0];
641  if (naxes > 1)
642  rglDir[1] = dir->dir[1];
643  if (naxes > 2)
644  rglDir[2] = dir->dir[2];
645  return 0;
646 
647  default:
648  return SDL_SetError("Haptic: Unknown direction type.");
649  }
650 }
651 
652 
653 /* Clamps and converts. */
654 #define CCONVERT(x) (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
655 /* Just converts. */
656 #define CONVERT(x) (((x)*10000) / 0x7FFF)
657 /*
658  * Creates the FFEFFECT from a SDL_HapticEffect.
659  */
660 static int
661 SDL_SYS_ToFFEFFECT(SDL_Haptic * haptic, FFEFFECT * dest,
663 {
664  int i;
665  FFCONSTANTFORCE *constant;
666  FFPERIODIC *periodic;
667  FFCONDITION *condition; /* Actually an array of conditions - one per axis. */
668  FFRAMPFORCE *ramp;
669  FFCUSTOMFORCE *custom;
670  FFENVELOPE *envelope;
671  SDL_HapticConstant *hap_constant;
672  SDL_HapticPeriodic *hap_periodic;
673  SDL_HapticCondition *hap_condition;
674  SDL_HapticRamp *hap_ramp;
675  SDL_HapticCustom *hap_custom;
676  DWORD *axes;
677 
678  /* Set global stuff. */
679  SDL_memset(dest, 0, sizeof(FFEFFECT));
680  dest->dwSize = sizeof(FFEFFECT); /* Set the structure size. */
681  dest->dwSamplePeriod = 0; /* Not used by us. */
682  dest->dwGain = 10000; /* Gain is set globally, not locally. */
683  dest->dwFlags = FFEFF_OBJECTOFFSETS; /* Seems obligatory. */
684 
685  /* Envelope. */
686  envelope = SDL_malloc(sizeof(FFENVELOPE));
687  if (envelope == NULL) {
688  return SDL_OutOfMemory();
689  }
690  SDL_memset(envelope, 0, sizeof(FFENVELOPE));
691  dest->lpEnvelope = envelope;
692  envelope->dwSize = sizeof(FFENVELOPE); /* Always should be this. */
693 
694  /* Axes. */
695  dest->cAxes = haptic->naxes;
696  if (dest->cAxes > 0) {
697  axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
698  if (axes == NULL) {
699  return SDL_OutOfMemory();
700  }
701  axes[0] = haptic->hwdata->axes[0]; /* Always at least one axis. */
702  if (dest->cAxes > 1) {
703  axes[1] = haptic->hwdata->axes[1];
704  }
705  if (dest->cAxes > 2) {
706  axes[2] = haptic->hwdata->axes[2];
707  }
708  dest->rgdwAxes = axes;
709  }
710 
711 
712  /* The big type handling switch, even bigger then Linux's version. */
713  switch (src->type) {
714  case SDL_HAPTIC_CONSTANT:
715  hap_constant = &src->constant;
716  constant = SDL_malloc(sizeof(FFCONSTANTFORCE));
717  if (constant == NULL) {
718  return SDL_OutOfMemory();
719  }
720  SDL_memset(constant, 0, sizeof(FFCONSTANTFORCE));
721 
722  /* Specifics */
723  constant->lMagnitude = CONVERT(hap_constant->level);
724  dest->cbTypeSpecificParams = sizeof(FFCONSTANTFORCE);
725  dest->lpvTypeSpecificParams = constant;
726 
727  /* Generics */
728  dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
729  dest->dwTriggerButton = FFGetTriggerButton(hap_constant->button);
730  dest->dwTriggerRepeatInterval = hap_constant->interval;
731  dest->dwStartDelay = hap_constant->delay * 1000; /* In microseconds. */
732 
733  /* Direction. */
734  if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes)
735  < 0) {
736  return -1;
737  }
738 
739  /* Envelope */
740  if ((hap_constant->attack_length == 0)
741  && (hap_constant->fade_length == 0)) {
742  SDL_free(envelope);
743  dest->lpEnvelope = NULL;
744  } else {
745  envelope->dwAttackLevel = CCONVERT(hap_constant->attack_level);
746  envelope->dwAttackTime = hap_constant->attack_length * 1000;
747  envelope->dwFadeLevel = CCONVERT(hap_constant->fade_level);
748  envelope->dwFadeTime = hap_constant->fade_length * 1000;
749  }
750 
751  break;
752 
753  case SDL_HAPTIC_SINE:
754  /* !!! FIXME: put this back when we have more bits in 2.1 */
755  /* case SDL_HAPTIC_SQUARE: */
756  case SDL_HAPTIC_TRIANGLE:
759  hap_periodic = &src->periodic;
760  periodic = SDL_malloc(sizeof(FFPERIODIC));
761  if (periodic == NULL) {
762  return SDL_OutOfMemory();
763  }
764  SDL_memset(periodic, 0, sizeof(FFPERIODIC));
765 
766  /* Specifics */
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;
773 
774  /* Generics */
775  dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
776  dest->dwTriggerButton = FFGetTriggerButton(hap_periodic->button);
777  dest->dwTriggerRepeatInterval = hap_periodic->interval;
778  dest->dwStartDelay = hap_periodic->delay * 1000; /* In microseconds. */
779 
780  /* Direction. */
781  if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes)
782  < 0) {
783  return -1;
784  }
785 
786  /* Envelope */
787  if ((hap_periodic->attack_length == 0)
788  && (hap_periodic->fade_length == 0)) {
789  SDL_free(envelope);
790  dest->lpEnvelope = NULL;
791  } else {
792  envelope->dwAttackLevel = CCONVERT(hap_periodic->attack_level);
793  envelope->dwAttackTime = hap_periodic->attack_length * 1000;
794  envelope->dwFadeLevel = CCONVERT(hap_periodic->fade_level);
795  envelope->dwFadeTime = hap_periodic->fade_length * 1000;
796  }
797 
798  break;
799 
800  case SDL_HAPTIC_SPRING:
801  case SDL_HAPTIC_DAMPER:
802  case SDL_HAPTIC_INERTIA:
803  case SDL_HAPTIC_FRICTION:
804  hap_condition = &src->condition;
805  condition = SDL_malloc(sizeof(FFCONDITION) * dest->cAxes);
806  if (condition == NULL) {
807  return SDL_OutOfMemory();
808  }
809  SDL_memset(condition, 0, sizeof(FFCONDITION));
810 
811  /* Specifics */
812  for (i = 0; i < dest->cAxes; i++) {
813  condition[i].lOffset = CONVERT(hap_condition->center[i]);
814  condition[i].lPositiveCoefficient =
815  CONVERT(hap_condition->right_coeff[i]);
816  condition[i].lNegativeCoefficient =
817  CONVERT(hap_condition->left_coeff[i]);
818  condition[i].dwPositiveSaturation =
819  CCONVERT(hap_condition->right_sat[i]);
820  condition[i].dwNegativeSaturation =
821  CCONVERT(hap_condition->left_sat[i]);
822  condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i]);
823  }
824  dest->cbTypeSpecificParams = sizeof(FFCONDITION) * dest->cAxes;
825  dest->lpvTypeSpecificParams = condition;
826 
827  /* Generics */
828  dest->dwDuration = hap_condition->length * 1000; /* In microseconds. */
829  dest->dwTriggerButton = FFGetTriggerButton(hap_condition->button);
830  dest->dwTriggerRepeatInterval = hap_condition->interval;
831  dest->dwStartDelay = hap_condition->delay * 1000; /* In microseconds. */
832 
833  /* Direction. */
834  if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes)
835  < 0) {
836  return -1;
837  }
838 
839  /* Envelope - Not actually supported by most CONDITION implementations. */
840  SDL_free(dest->lpEnvelope);
841  dest->lpEnvelope = NULL;
842 
843  break;
844 
845  case SDL_HAPTIC_RAMP:
846  hap_ramp = &src->ramp;
847  ramp = SDL_malloc(sizeof(FFRAMPFORCE));
848  if (ramp == NULL) {
849  return SDL_OutOfMemory();
850  }
851  SDL_memset(ramp, 0, sizeof(FFRAMPFORCE));
852 
853  /* Specifics */
854  ramp->lStart = CONVERT(hap_ramp->start);
855  ramp->lEnd = CONVERT(hap_ramp->end);
856  dest->cbTypeSpecificParams = sizeof(FFRAMPFORCE);
857  dest->lpvTypeSpecificParams = ramp;
858 
859  /* Generics */
860  dest->dwDuration = hap_ramp->length * 1000; /* In microseconds. */
861  dest->dwTriggerButton = FFGetTriggerButton(hap_ramp->button);
862  dest->dwTriggerRepeatInterval = hap_ramp->interval;
863  dest->dwStartDelay = hap_ramp->delay * 1000; /* In microseconds. */
864 
865  /* Direction. */
866  if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) {
867  return -1;
868  }
869 
870  /* Envelope */
871  if ((hap_ramp->attack_length == 0) && (hap_ramp->fade_length == 0)) {
872  SDL_free(envelope);
873  dest->lpEnvelope = NULL;
874  } else {
875  envelope->dwAttackLevel = CCONVERT(hap_ramp->attack_level);
876  envelope->dwAttackTime = hap_ramp->attack_length * 1000;
877  envelope->dwFadeLevel = CCONVERT(hap_ramp->fade_level);
878  envelope->dwFadeTime = hap_ramp->fade_length * 1000;
879  }
880 
881  break;
882 
883  case SDL_HAPTIC_CUSTOM:
884  hap_custom = &src->custom;
885  custom = SDL_malloc(sizeof(FFCUSTOMFORCE));
886  if (custom == NULL) {
887  return SDL_OutOfMemory();
888  }
889  SDL_memset(custom, 0, sizeof(FFCUSTOMFORCE));
890 
891  /* Specifics */
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);
897  for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) { /* Copy data. */
898  custom->rglForceData[i] = CCONVERT(hap_custom->data[i]);
899  }
900  dest->cbTypeSpecificParams = sizeof(FFCUSTOMFORCE);
901  dest->lpvTypeSpecificParams = custom;
902 
903  /* Generics */
904  dest->dwDuration = hap_custom->length * 1000; /* In microseconds. */
905  dest->dwTriggerButton = FFGetTriggerButton(hap_custom->button);
906  dest->dwTriggerRepeatInterval = hap_custom->interval;
907  dest->dwStartDelay = hap_custom->delay * 1000; /* In microseconds. */
908 
909  /* Direction. */
910  if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) <
911  0) {
912  return -1;
913  }
914 
915  /* Envelope */
916  if ((hap_custom->attack_length == 0)
917  && (hap_custom->fade_length == 0)) {
918  SDL_free(envelope);
919  dest->lpEnvelope = NULL;
920  } else {
921  envelope->dwAttackLevel = CCONVERT(hap_custom->attack_level);
922  envelope->dwAttackTime = hap_custom->attack_length * 1000;
923  envelope->dwFadeLevel = CCONVERT(hap_custom->fade_level);
924  envelope->dwFadeTime = hap_custom->fade_length * 1000;
925  }
926 
927  break;
928 
929 
930  default:
931  return SDL_SetError("Haptic: Unknown effect type.");
932  }
933 
934  return 0;
935 }
936 
937 
938 /*
939  * Frees an FFEFFECT allocated by SDL_SYS_ToFFEFFECT.
940  */
941 static void
942 SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect, int type)
943 {
944  FFCUSTOMFORCE *custom;
945 
946  SDL_free(effect->lpEnvelope);
947  effect->lpEnvelope = NULL;
948  SDL_free(effect->rgdwAxes);
949  effect->rgdwAxes = NULL;
950  if (effect->lpvTypeSpecificParams != NULL) {
951  if (type == SDL_HAPTIC_CUSTOM) { /* Must free the custom data. */
952  custom = (FFCUSTOMFORCE *) effect->lpvTypeSpecificParams;
953  SDL_free(custom->rglForceData);
954  custom->rglForceData = NULL;
955  }
956  SDL_free(effect->lpvTypeSpecificParams);
957  effect->lpvTypeSpecificParams = NULL;
958  }
959  SDL_free(effect->rglDirection);
960  effect->rglDirection = NULL;
961 }
962 
963 
964 /*
965  * Gets the effect type from the generic SDL haptic effect wrapper.
966  */
967 CFUUIDRef
968 SDL_SYS_HapticEffectType(Uint16 type)
969 {
970  switch (type) {
971  case SDL_HAPTIC_CONSTANT:
972  return kFFEffectType_ConstantForce_ID;
973 
974  case SDL_HAPTIC_RAMP:
975  return kFFEffectType_RampForce_ID;
976 
977  /* !!! FIXME: put this back when we have more bits in 2.1 */
978  /* case SDL_HAPTIC_SQUARE:
979  return kFFEffectType_Square_ID; */
980 
981  case SDL_HAPTIC_SINE:
982  return kFFEffectType_Sine_ID;
983 
984  case SDL_HAPTIC_TRIANGLE:
985  return kFFEffectType_Triangle_ID;
986 
988  return kFFEffectType_SawtoothUp_ID;
989 
991  return kFFEffectType_SawtoothDown_ID;
992 
993  case SDL_HAPTIC_SPRING:
994  return kFFEffectType_Spring_ID;
995 
996  case SDL_HAPTIC_DAMPER:
997  return kFFEffectType_Damper_ID;
998 
999  case SDL_HAPTIC_INERTIA:
1000  return kFFEffectType_Inertia_ID;
1001 
1002  case SDL_HAPTIC_FRICTION:
1003  return kFFEffectType_Friction_ID;
1004 
1005  case SDL_HAPTIC_CUSTOM:
1006  return kFFEffectType_CustomForce_ID;
1007 
1008  default:
1009  SDL_SetError("Haptic: Unknown effect type.");
1010  return NULL;
1011  }
1012 }
1013 
1014 
1015 /*
1016  * Creates a new haptic effect.
1017  */
1018 int
1019 SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
1020  SDL_HapticEffect * base)
1021 {
1022  HRESULT ret;
1023  CFUUIDRef type;
1024 
1025  /* Alloc the effect. */
1026  effect->hweffect = (struct haptic_hweffect *)
1027  SDL_malloc(sizeof(struct haptic_hweffect));
1028  if (effect->hweffect == NULL) {
1029  SDL_OutOfMemory();
1030  goto err_hweffect;
1031  }
1032 
1033  /* Get the type. */
1034  type = SDL_SYS_HapticEffectType(base->type);
1035  if (type == NULL) {
1036  goto err_hweffect;
1037  }
1038 
1039  /* Get the effect. */
1040  if (SDL_SYS_ToFFEFFECT(haptic, &effect->hweffect->effect, base) < 0) {
1041  goto err_effectdone;
1042  }
1043 
1044  /* Create the actual effect. */
1045  ret = FFDeviceCreateEffect(haptic->hwdata->device, type,
1046  &effect->hweffect->effect,
1047  &effect->hweffect->ref);
1048  if (ret != FF_OK) {
1049  SDL_SetError("Haptic: Unable to create effect: %s.", FFStrError(ret));
1050  goto err_effectdone;
1051  }
1052 
1053  return 0;
1054 
1055  err_effectdone:
1056  SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect, base->type);
1057  err_hweffect:
1058  SDL_free(effect->hweffect);
1059  effect->hweffect = NULL;
1060  return -1;
1061 }
1062 
1063 
1064 /*
1065  * Updates an effect.
1066  */
1067 int
1069  struct haptic_effect *effect,
1071 {
1072  HRESULT ret;
1073  FFEffectParameterFlag flags;
1074  FFEFFECT temp;
1075 
1076  /* Get the effect. */
1077  SDL_memset(&temp, 0, sizeof(FFEFFECT));
1078  if (SDL_SYS_ToFFEFFECT(haptic, &temp, data) < 0) {
1079  goto err_update;
1080  }
1081 
1082  /* Set the flags. Might be worthwhile to diff temp with loaded effect and
1083  * only change those parameters. */
1084  flags = FFEP_DIRECTION |
1085  FFEP_DURATION |
1086  FFEP_ENVELOPE |
1087  FFEP_STARTDELAY |
1088  FFEP_TRIGGERBUTTON |
1089  FFEP_TRIGGERREPEATINTERVAL | FFEP_TYPESPECIFICPARAMS;
1090 
1091  /* Create the actual effect. */
1092  ret = FFEffectSetParameters(effect->hweffect->ref, &temp, flags);
1093  if (ret != FF_OK) {
1094  SDL_SetError("Haptic: Unable to update effect: %s.", FFStrError(ret));
1095  goto err_update;
1096  }
1097 
1098  /* Copy it over. */
1099  SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect, data->type);
1100  SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(FFEFFECT));
1101 
1102  return 0;
1103 
1104  err_update:
1105  SDL_SYS_HapticFreeFFEFFECT(&temp, data->type);
1106  return -1;
1107 }
1108 
1109 
1110 /*
1111  * Runs an effect.
1112  */
1113 int
1114 SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
1115  Uint32 iterations)
1116 {
1117  HRESULT ret;
1118  Uint32 iter;
1119 
1120  /* Check if it's infinite. */
1121  if (iterations == SDL_HAPTIC_INFINITY) {
1122  iter = FF_INFINITE;
1123  } else
1124  iter = iterations;
1125 
1126  /* Run the effect. */
1127  ret = FFEffectStart(effect->hweffect->ref, iter, 0);
1128  if (ret != FF_OK) {
1129  return SDL_SetError("Haptic: Unable to run the effect: %s.",
1130  FFStrError(ret));
1131  }
1132 
1133  return 0;
1134 }
1135 
1136 
1137 /*
1138  * Stops an effect.
1139  */
1140 int
1141 SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1142 {
1143  HRESULT ret;
1144 
1145  ret = FFEffectStop(effect->hweffect->ref);
1146  if (ret != FF_OK) {
1147  return SDL_SetError("Haptic: Unable to stop the effect: %s.",
1148  FFStrError(ret));
1149  }
1150 
1151  return 0;
1152 }
1153 
1154 
1155 /*
1156  * Frees the effect.
1157  */
1158 void
1159 SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
1160 {
1161  HRESULT ret;
1162 
1163  ret =
1164  FFDeviceReleaseEffect(haptic->hwdata->device, effect->hweffect->ref);
1165  if (ret != FF_OK) {
1166  SDL_SetError("Haptic: Error removing the effect from the device: %s.",
1167  FFStrError(ret));
1168  }
1169  SDL_SYS_HapticFreeFFEFFECT(&effect->hweffect->effect,
1170  effect->effect.type);
1171  SDL_free(effect->hweffect);
1172  effect->hweffect = NULL;
1173 }
1174 
1175 
1176 /*
1177  * Gets the status of a haptic effect.
1178  */
1179 int
1181  struct haptic_effect *effect)
1182 {
1183  HRESULT ret;
1184  FFEffectStatusFlag status;
1185 
1186  ret = FFEffectGetEffectStatus(effect->hweffect->ref, &status);
1187  if (ret != FF_OK) {
1188  SDL_SetError("Haptic: Unable to get effect status: %s.",
1189  FFStrError(ret));
1190  return -1;
1191  }
1192 
1193  if (status == 0)
1194  return SDL_FALSE;
1195  return SDL_TRUE; /* Assume it's playing or emulated. */
1196 }
1197 
1198 
1199 /*
1200  * Sets the gain.
1201  */
1202 int
1203 SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
1204 {
1205  HRESULT ret;
1206  Uint32 val;
1207 
1208  val = gain * 100; /* Mac OS X uses 0 to 10,000 */
1209  ret =
1210  FFDeviceSetForceFeedbackProperty(haptic->hwdata->device,
1211  FFPROP_FFGAIN, &val);
1212  if (ret != FF_OK) {
1213  return SDL_SetError("Haptic: Error setting gain: %s.", FFStrError(ret));
1214  }
1215 
1216  return 0;
1217 }
1218 
1219 
1220 /*
1221  * Sets the autocentering.
1222  */
1223 int
1224 SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
1225 {
1226  HRESULT ret;
1227  Uint32 val;
1228 
1229  /* Mac OS X only has 0 (off) and 1 (on) */
1230  if (autocenter == 0)
1231  val = 0;
1232  else
1233  val = 1;
1234 
1235  ret = FFDeviceSetForceFeedbackProperty(haptic->hwdata->device,
1236  FFPROP_AUTOCENTER, &val);
1237  if (ret != FF_OK) {
1238  return SDL_SetError("Haptic: Error setting autocenter: %s.",
1239  FFStrError(ret));
1240  }
1241 
1242  return 0;
1243 }
1244 
1245 
1246 /*
1247  * Pauses the device.
1248  */
1249 int
1251 {
1252  HRESULT ret;
1253 
1254  ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
1255  FFSFFC_PAUSE);
1256  if (ret != FF_OK) {
1257  return SDL_SetError("Haptic: Error pausing device: %s.", FFStrError(ret));
1258  }
1259 
1260  return 0;
1261 }
1262 
1263 
1264 /*
1265  * Unpauses the device.
1266  */
1267 int
1269 {
1270  HRESULT ret;
1271 
1272  ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
1273  FFSFFC_CONTINUE);
1274  if (ret != FF_OK) {
1275  return SDL_SetError("Haptic: Error pausing device: %s.", FFStrError(ret));
1276  }
1277 
1278  return 0;
1279 }
1280 
1281 
1282 /*
1283  * Stops all currently playing effects.
1284  */
1285 int
1287 {
1288  HRESULT ret;
1289 
1290  ret = FFDeviceSendForceFeedbackCommand(haptic->hwdata->device,
1291  FFSFFC_STOPALL);
1292  if (ret != FF_OK) {
1293  return SDL_SetError("Haptic: Error stopping device: %s.", FFStrError(ret));
1294  }
1295 
1296  return 0;
1297 }
1298 
1299 
1300 #endif /* SDL_HAPTIC_IOKIT */
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
struct haptic_hwdata * hwdata
Definition: SDL_syshaptic.h:52
Uint16 deadband[3]
Definition: SDL_haptic.h:611
Structure that represents a haptic direction.
Definition: SDL_haptic.h:439
GLenum condition
Definition: gl2ext.h:1403
GLuint const GLfloat * val
Definition: glew.h:2715
struct haptic_effect * effects
Definition: SDL_syshaptic.h:46
#define SDL_HAPTIC_SPHERICAL
Uses spherical coordinates for the direction.
Definition: SDL_haptic.h:329
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
#define SDL_HAPTIC_AUTOCENTER
Device can set autocenter.
Definition: SDL_haptic.h:285
A structure containing a template for a Periodic effect.
Definition: SDL_haptic.h:538
#define NULL
Definition: ftobjs.h:61
#define SDL_HAPTIC_GAIN
Device can set global gain.
Definition: SDL_haptic.h:276
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
#define SDL_HAPTIC_CUSTOM
Custom effect is supported.
Definition: SDL_haptic.h:263
#define SDL_HAPTIC_TRIANGLE
Triangle wave effect supported.
Definition: SDL_haptic.h:189
SDL_HapticDirection direction
Definition: SDL_haptic.h:596
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
SDL_HapticCustom custom
Definition: SDL_haptic.h:796
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.
Definition: SDL_haptic.h:246
SDL_EventEntry * free
Definition: SDL_events.c:80
DECLSPEC void SDLCALL SDL_free(void *mem)
Uint16 fade_level
Definition: SDL_haptic.h:650
SDL_HapticRamp ramp
Definition: SDL_haptic.h:794
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.
Definition: SDL_haptic.h:591
EGLImageKHR EGLint * name
Definition: eglext.h:284
The SDL Haptic subsystem allows you to control haptic (force feedback) devices.
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
Sint16 left_coeff[3]
Definition: SDL_haptic.h:610
Uint16 right_sat[3]
Definition: SDL_haptic.h:607
Uint16 fade_length
Definition: SDL_haptic.h:714
Sint16 right_coeff[3]
Definition: SDL_haptic.h:609
#define SDL_HAPTIC_SINE
Sine wave effect supported.
Definition: SDL_haptic.h:166
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
struct joystick_hwdata * hwdata
ret
Definition: glew_str_glx.c:2
A structure containing a template for a Constant effect.
Definition: SDL_haptic.h:457
Uint8 SDL_numhaptics
Definition: SDL_haptic.c:28
#define SDL_HAPTIC_INFINITY
Used to play a device an infinite number of times.
Definition: SDL_haptic.h:344
Uint16 interval
Definition: SDL_haptic.h:640
#define SDL_HAPTIC_CARTESIAN
Uses cartesian coordinates for the direction.
Definition: SDL_haptic.h:322
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:145
unsigned int supported
Definition: SDL_syshaptic.h:49
SDL_HapticCondition condition
Definition: SDL_haptic.h:793
io_service_t ffservice
GLuint64EXT * result
Definition: glew.h:12708
The generic template for any haptic effect.
Definition: SDL_haptic.h:787
#define SDL_HAPTIC_CONSTANT
Constant effect supported.
Definition: SDL_haptic.h:157
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
#define SDL_HAPTIC_POLAR
Uses polar coordinates for the direction.
Definition: SDL_haptic.h:315
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
SDL_HapticConstant constant
Definition: SDL_haptic.h:791
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
#define SDL_HAPTIC_PAUSE
Device can be paused.
Definition: SDL_haptic.h:302
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
GLuint index
Definition: glew.h:1800
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
SDL_HapticDirection direction
Definition: SDL_haptic.h:632
A structure containing a template for a Ramp effect.
Definition: SDL_haptic.h:628
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
Uint16 attack_length
Definition: SDL_haptic.h:647
Uint16 fade_length
Definition: SDL_haptic.h:649
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_HapticEffect effect
Definition: SDL_syshaptic.h:35
int SDL_SYS_HapticInit(void)
void SDL_SYS_HapticQuit(void)
struct haptic_hweffect * hweffect
Definition: SDL_syshaptic.h:36
#define SDL_HAPTIC_STATUS
Device can be queried for effect status.
Definition: SDL_haptic.h:294
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)
Definition: SDL_string.c:293
SDL_HapticDirection direction
Definition: SDL_haptic.h:544
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
Uint16 attack_level
Definition: SDL_haptic.h:713
#define SDL_HAPTIC_RAMP
Ramp effect supported.
Definition: SDL_haptic.h:216
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
#define SDL_HAPTIC_SPRING
Spring effect supported - uses axes position.
Definition: SDL_haptic.h:226
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
A structure containing a template for the SDL_HAPTIC_CUSTOM effect.
Definition: SDL_haptic.h:691
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:137
GLclampf ref
Definition: gl2ext.h:1455
#define SDL_HAPTIC_SAWTOOTHUP
Sawtoothup wave effect supported.
Definition: SDL_haptic.h:198
int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
GLenum src
Definition: glew.h:2396
int i
Definition: pngrutil.c:1377
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
SDL_HapticPeriodic periodic
Definition: SDL_haptic.h:792
Uint16 attack_level
Definition: SDL_haptic.h:648
Uint16 attack_length
Definition: SDL_haptic.h:712
GLsizeiptr const GLvoid GLenum usage
Definition: glew.h:1667
#define SDL_HAPTIC_FRICTION
Friction effect supported - uses axes movement.
Definition: SDL_haptic.h:256
#define SDL_HAPTIC_SAWTOOTHDOWN
Sawtoothdown wave effect supported.
Definition: SDL_haptic.h:207
SDL_HapticDirection direction
Definition: SDL_haptic.h:461
SDL_HapticDirection direction
Definition: SDL_haptic.h:695
int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
#define SDL_HAPTIC_DAMPER
Damper effect supported - uses axes velocity.
Definition: SDL_haptic.h:236
Uint16 left_sat[3]
Definition: SDL_haptic.h:608