From 749b83b63582f6aacc0413bc3e0c8eb2db189fe3 Mon Sep 17 00:00:00 2001 From: Edgar Simo Date: Sat, 19 Jul 2008 17:05:30 +0000 Subject: [PATCH] Support for SDL_HapticName in darwin. Fixed memleak. --- src/haptic/darwin/SDL_syshaptic.c | 74 ++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/src/haptic/darwin/SDL_syshaptic.c b/src/haptic/darwin/SDL_syshaptic.c index dc47e3c01..f1991b93f 100644 --- a/src/haptic/darwin/SDL_syshaptic.c +++ b/src/haptic/darwin/SDL_syshaptic.c @@ -43,6 +43,7 @@ */ static struct { + char name[256]; io_service_t dev; SDL_Haptic *haptic; } SDL_hapticlist[MAX_HAPTICS]; @@ -69,7 +70,8 @@ struct haptic_hweffect /* * 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 @@ SDL_SYS_HapticInit(void) 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 @@ SDL_SYS_HapticInit(void) /* 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 @@ SDL_SYS_HapticInit(void) 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; }