/* * Checks to see if the haptic device and joystick and in reality the same. */ int SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick) { if (IOObjectIsEqualTo((io_object_t) ((size_t)haptic->hwdata->device), joystick->hwdata->ffservice)) return 1; return 0; }
/* * Opens a SDL_Haptic from a SDL_Joystick. */ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick) { int device_index = 0; SDL_hapticlist_item *item; for (item = SDL_hapticlist; item; item = item->next) { if (IOObjectIsEqualTo((io_object_t) item->dev, joystick->hwdata->ffservice)) { haptic->index = device_index; break; } ++device_index; } return SDL_SYS_HapticOpenFromService(haptic, joystick->hwdata->ffservice); }
/* * Opens a SDL_Haptic from a SDL_Joystick. */ int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick) { int i; for (i=0; i<SDL_numhaptics; i++) { if (IOObjectIsEqualTo((io_object_t) SDL_hapticlist[i].dev, joystick->hwdata->ffservice)) { haptic->index = i; break; } } if (i >= SDL_numhaptics) { return -1; } return SDL_SYS_HapticOpenFromService(haptic, joystick->hwdata->ffservice); }
int MacHaptic_MaybeRemoveDevice( io_object_t device ) { SDL_hapticlist_item *item; SDL_hapticlist_item *prev = NULL; if (numhaptics == -1) { return -1; /* not initialized. ignore this. */ } for (item = SDL_hapticlist; item != NULL; item = item->next) { /* found it, remove it. */ if (IOObjectIsEqualTo((io_object_t) item->dev, device)) { const int retval = item->haptic ? item->haptic->index : -1; if (prev != NULL) { prev->next = item->next; } else { SDL_assert(SDL_hapticlist == item); SDL_hapticlist = item->next; } if (item == SDL_hapticlist_tail) { SDL_hapticlist_tail = prev; } /* Need to decrement the haptic count */ --numhaptics; /* !!! TODO: Send a haptic remove event? */ IOObjectRelease(item->dev); SDL_free(item); return retval; } prev = item; } return -1; }
int MacHaptic_MaybeAddDevice( io_object_t device ) { IOReturn result; CFMutableDictionaryRef hidProperties; CFTypeRef refCF; SDL_hapticlist_item *item; if (numhaptics == -1) { return -1; /* not initialized. We'll pick these up on enumeration if we init later. */ } /* Check for force feedback. */ if (FFIsForceFeedback(device) != FF_OK) { return -1; } /* Make sure we don't already have it */ for (item = SDL_hapticlist; item ; item = item->next) { if (IOObjectIsEqualTo((io_object_t) item->dev, device)) { /* Already added */ return -1; } } item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); if (item == NULL) { return SDL_SetError("Could not allocate haptic storage"); } /* retain it as we are going to keep it around a while */ IOObjectRetain(device); /* Set basic device data. */ HIDGetDeviceProduct(device, item->name); item->dev = device; /* Set usage pages. */ hidProperties = 0; refCF = 0; result = IORegistryEntryCreateCFProperties(device, &hidProperties, kCFAllocatorDefault, kNilOptions); if ((result == KERN_SUCCESS) && hidProperties) { refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); if (refCF) { if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usagePage)) { SDL_SetError("Haptic: Receiving device's usage page."); } refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); if (refCF) { if (!CFNumberGetValue(refCF, kCFNumberLongType, &item->usage)) { SDL_SetError("Haptic: Receiving device's usage."); } } } CFRelease(hidProperties); } if (SDL_hapticlist_tail == NULL) { SDL_hapticlist = SDL_hapticlist_tail = item; } else { SDL_hapticlist_tail->next = item; SDL_hapticlist_tail = item; } /* Device has been added. */ ++numhaptics; return numhaptics; }
// first look up the media object, then create a // custom matching dictionary that should be persistent // from boot to boot int addMatchingInfoForBSDName(BLContextPtr context, mach_port_t masterPort, CFMutableDictionaryRef dict, const char *bsdName, bool shortForm) { io_service_t media = IO_OBJECT_NULL, checkMedia = IO_OBJECT_NULL; CFStringRef uuid = NULL; CFMutableDictionaryRef propDict = NULL; kern_return_t kret; CFStringRef lastBSDName = NULL; lastBSDName = CFStringCreateWithCString(kCFAllocatorDefault, bsdName, kCFStringEncodingUTF8); propDict = IOBSDNameMatching(masterPort, 0, bsdName); CFDictionarySetValue(propDict, CFSTR(kIOProviderClassKey), CFSTR(kIOMediaClass)); media = IOServiceGetMatchingService(masterPort, propDict); propDict = NULL; if(media == IO_OBJECT_NULL) { contextprintf(context, kBLLogLevelError, "Could not find object for %s\n", bsdName); CFRelease(lastBSDName); return 1; } uuid = IORegistryEntryCreateCFProperty(media, CFSTR(kIOMediaUUIDKey), kCFAllocatorDefault, 0); if(uuid == NULL) { CFUUIDRef fsuuid = NULL; CFStringRef fsuuidstr = NULL; io_string_t path; #if USE_DISKARBITRATION DASessionRef session = NULL; DADiskRef dadisk = NULL; contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have a partition %s\n", bsdName, kIOMediaUUIDKey); session = DASessionCreate(kCFAllocatorDefault); if(session) { dadisk = DADiskCreateFromIOMedia(kCFAllocatorDefault, session, media); if(dadisk) { CFDictionaryRef descrip = DADiskCopyDescription(dadisk); if(descrip) { fsuuid = CFDictionaryGetValue(descrip, kDADiskDescriptionVolumeUUIDKey); if(fsuuid) CFRetain(fsuuid); CFRelease(descrip); } CFRelease(dadisk); } CFRelease(session); } #endif // USE_DISKARBITRATION if(fsuuid) { char fsuuidCString[64]; fsuuidstr = CFUUIDCreateString(kCFAllocatorDefault, fsuuid); CFStringGetCString(fsuuidstr,fsuuidCString,sizeof(fsuuidCString),kCFStringEncodingUTF8); contextprintf(context, kBLLogLevelVerbose, "DADiskRef %s has Volume UUID %s\n", bsdName, fsuuidCString); CFRelease(fsuuid); } else { contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have a Volume UUID\n", bsdName); } // we have a volume UUID, but our primary matching mechanism will be the device path kret = IORegistryEntryGetPath(media, kIODeviceTreePlane,path); if(kret) { contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have device tree path\n", bsdName); propDict = IOServiceMatching(kIOMediaClass); CFDictionaryAddValue(propDict, CFSTR(kIOBSDNameKey), lastBSDName); // add UUID as hint if(fsuuidstr) CFDictionaryAddValue(dict, CFSTR("BLVolumeUUID"), fsuuidstr); } else { CFStringRef blpath = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); contextprintf(context, kBLLogLevelVerbose, "IOMedia %s has path %s\n", bsdName, path); propDict = IOServiceMatching(kIOMediaClass); CFDictionaryAddValue(propDict, CFSTR(kIOPathMatchKey), blpath); CFRelease(blpath); // add UUID as hint if(fsuuidstr) CFDictionaryAddValue(dict, CFSTR("BLVolumeUUID"), fsuuidstr); CFDictionaryAddValue(dict, CFSTR("BLLastBSDName"), lastBSDName); } if(fsuuidstr) { CFRelease(fsuuidstr); } } else { CFMutableDictionaryRef propMatch; contextprintf(context, kBLLogLevelVerbose, "IOMedia %s has UUID %s\n", bsdName, BLGetCStringDescription(uuid)); propMatch = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(propMatch, CFSTR(kIOMediaUUIDKey), uuid); propDict = IOServiceMatching(kIOMediaClass); CFDictionaryAddValue(propDict, CFSTR(kIOPropertyMatchKey), propMatch); CFRelease(propMatch); // add a hint to the top-level dict CFDictionaryAddValue(dict, CFSTR("BLLastBSDName"), lastBSDName); CFRelease(uuid); } // verify the dictionary matches CFRetain(propDict); // consumed below checkMedia = IOServiceGetMatchingService(masterPort, propDict); if(IO_OBJECT_NULL == checkMedia || !IOObjectIsEqualTo(media, checkMedia)) { contextprintf(context, kBLLogLevelVerbose, "Inconsistent registry entries for %s\n", bsdName); if(IO_OBJECT_NULL != checkMedia) IOObjectRelease(checkMedia); IOObjectRelease(media); CFRelease(lastBSDName); CFRelease(propDict); return 2; } IOObjectRelease(checkMedia); IOObjectRelease(media); CFDictionaryAddValue(dict, CFSTR("IOMatch"), propDict); CFRelease(lastBSDName); CFRelease(propDict); if(shortForm) { CFDictionaryAddValue(dict, CFSTR("IOEFIShortForm"), kCFBooleanTrue); } return 0; }