diff src/haptic/darwin/SDL_syshaptic.c @ 2537:8d92ec01f92f gsoc2008_force_feedback

Support for SDL_HapticName in darwin. Fixed memleak.
author Edgar Simo <bobbens@gmail.com>
date Sat, 19 Jul 2008 17:05:30 +0000
parents f0ed8471497d
children 1f9c20580ab4
line wrap: on
line diff
--- a/src/haptic/darwin/SDL_syshaptic.c	Sat Jul 19 16:06:43 2008 +0000
+++ b/src/haptic/darwin/SDL_syshaptic.c	Sat Jul 19 17:05:30 2008 +0000
@@ -43,6 +43,7 @@
  */
 static struct
 {
+   char name[256];
    io_service_t dev;
    SDL_Haptic *haptic;
 } SDL_hapticlist[MAX_HAPTICS];
@@ -69,7 +70,8 @@
 /*
  * Prototypes.
  */
-static void SDL_SYS_HapticFreeFFEFFECT( FFEFFECT * effect, int type );
+static void SDL_SYS_HapticFreeFFEFFECT(FFEFFECT * effect, int type);
+static int HIDGetDeviceProduct(io_service_t dev, char * name);
 
 
 /*
@@ -84,6 +86,9 @@
    CFDictionaryRef match;
    io_service_t device;
 
+   /* Clear all the memory. */
+   SDL_memset(SDL_hapticlist, 0, sizeof(SDL_hapticlist));
+
    /* Get HID devices. */
    match = IOServiceMatching(kIOHIDDeviceKey);
    if (match == NULL) {
@@ -104,10 +109,14 @@
 
       /* Check for force feedback. */
       if (FFIsForceFeedback(device) == FF_OK) {
+         HIDGetDeviceProduct(device, SDL_hapticlist[numhaptics].name);
          SDL_hapticlist[numhaptics].dev = device;
          SDL_hapticlist[numhaptics].haptic = NULL;
          numhaptics++;
       }
+      else { /* Free the unused device. */
+         IOObjectRelease(device);
+      }
 
       /* Reached haptic limit. */
       if (numhaptics >= MAX_HAPTICS)
@@ -125,7 +134,68 @@
 const char *
 SDL_SYS_HapticName(int index)
 {
-   return NULL;
+   return SDL_hapticlist[index].name;
+}
+
+/*
+ * Gets the device's product name.
+ */
+static int
+HIDGetDeviceProduct(io_service_t dev, char *name)
+{
+   CFMutableDictionaryRef hidProperties, usbProperties;
+   io_registry_entry_t parent1, parent2;
+
+   hidProperties = usbProperties = 0;
+
+   /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also
+    * get dictionary for usb properties: step up two levels and get CF dictionary for USB properties
+    */
+   if ((KERN_SUCCESS ==
+            IORegistryEntryGetParentEntry(dev, kIOServicePlane, &parent1))
+         && (KERN_SUCCESS ==
+            IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2))
+         && (KERN_SUCCESS ==
+            IORegistryEntryCreateCFProperties(parent2, &usbProperties,
+               kCFAllocatorDefault,
+               kNilOptions))) {
+      if (usbProperties) {
+         CFTypeRef refCF = 0;
+         /* get device info
+          * try hid dictionary first, if fail then go to usb dictionary
+          */
+
+
+         /* Get product name */
+         refCF =
+            CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey));
+         if (!refCF)
+            refCF =
+               CFDictionaryGetValue(usbProperties, CFSTR("USB Product Name"));
+         if (refCF) {
+            if (!CFStringGetCString(refCF, name, 256,
+                                    CFStringGetSystemEncoding())) {
+               SDL_SetError("CFStringGetCString error retrieving pDevice->product.");
+               return -1;
+            }
+         }
+
+         CFRelease(usbProperties);
+      }
+      else {
+         SDL_SetError("IORegistryEntryCreateCFProperties failed to create usbProperties.");
+         return -1;
+      }
+
+      /* Release stuff. */
+      if (kIOReturnSuccess != IOObjectRelease(parent2)) {
+         SDL_SetError("IOObjectRelease error with parent2.");
+      }
+      if (kIOReturnSuccess != IOObjectRelease(parent1))  {
+         SDL_SetError("IOObjectRelease error with parent1.");
+      }
+   }
+   return 0;
 }