CFMutableSetRef CFSetCreateMutableCopy (CFAllocatorRef allocator, CFIndex capacity, CFSetRef set) { if (CF_IS_OBJC (_kCFSetTypeID, set)) { CFMutableSetRef result; const CFIndex count = CFSetGetCount (set); void **values = (void **) CFAllocatorAllocate (allocator, sizeof (void *) * count, 0); CFIndex i; CFSetGetValues (set, (const void **) values); result = CFSetCreateMutable (allocator, count, &kCFTypeSetCallBacks); for (i = 0; i < count; i++) GSHashTableAddValue ((GSHashTableRef) result, values[i], values[i]); CFAllocatorDeallocate (allocator, (void *) values); return result; } return (CFMutableSetRef) GSHashTableCreateMutableCopy (allocator, (GSHashTableRef) set, capacity); }
CFSetRef CFSetCreateCopy(CFAllocatorRef allocator, CFSetRef set) { CFSetRef result; const CFSetCallBacks *cb; CFIndex numValues = CFSetGetCount(set); const void **list, *buffer[256]; list = (numValues <= 256) ? buffer : CFAllocatorAllocate(allocator, numValues * sizeof(void *), 0); if (list != buffer && __CFOASafe) __CFSetLastAllocationEventName(list, "CFSet (temp)"); CFSetGetValues(set, list); cb = CF_IS_OBJC(__kCFSetTypeID, set) ? &kCFTypeSetCallBacks : __CFSetGetCallBacks(set); result = CFSetCreate(allocator, list, numValues, cb); if (list != buffer) CFAllocatorDeallocate(allocator, list); return result; }
bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) { if (!initializeManager()) { return false; } CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager); CFIndex deviceCount = CFSetGetCount(deviceSet); // Allocate a block of memory and read the set into it. IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount); CFSetGetValues(deviceSet, (const void **) devices); // Iterate over devices. for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { IOHIDDeviceRef hidDev = devices[deviceIndex]; if (!hidDev) { continue; } HIDDeviceDesc devDesc; if (getPath(hidDev, &(devDesc.Path)) && initVendorProductVersion(hidDev, &devDesc) && enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) && initUsage(hidDev, &devDesc)) { initStrings(hidDev, &devDesc); initSerialNumber(hidDev, &devDesc); // Construct minimal device that the visitor callback can get feature reports from. OSX::HIDDevice device(this, hidDev); enumVisitor->Visit(device, devDesc); } } OVR_FREE(devices); CFRelease(deviceSet); return true; }
IOHIDDeviceRef FindDevice(IOHIDManagerRef manager, long vendorId, long productId) { IOHIDDeviceRef theDevice = NULL; // setup dictionary CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable( kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFNumberRef cfVendorId = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongType, &vendorId); CFStringRef cfVendorSt = CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDVendorIDKey, kCFStringEncodingUTF8); CFDictionaryAddValue(dictionary, cfVendorSt, cfVendorId); CFRelease(cfVendorId); CFRelease(cfVendorSt); CFNumberRef cfProductId = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongType, &productId); CFStringRef cfProductSt = CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDProductIDKey, kCFStringEncodingUTF8); CFDictionaryAddValue(dictionary, cfProductSt, cfProductId); CFRelease(cfProductId); CFRelease(cfProductSt); // look for devices matching criteria IOHIDManagerSetDeviceMatching(manager, dictionary); CFSetRef foundDevices = IOHIDManagerCopyDevices(manager); CFIndex foundCount = foundDevices ? CFSetGetCount(foundDevices) : 0; // what the API does not say is that it could be null if(foundCount > 0) { CFTypeRef* array = new CFTypeRef[foundCount]; // array of IOHIDDeviceRef CFSetGetValues(foundDevices, array); // get first matching device theDevice = (IOHIDDeviceRef)array[0]; CFRetain(theDevice); delete [] array; } if(foundDevices) { CFRelease(foundDevices); } CFRelease(dictionary); return theDevice; }
CFMutableSetRef CFSetCreateMutableCopy(CFAllocatorRef allocator, CFIndex capacity, CFSetRef set) { CFMutableSetRef result; const CFSetCallBacks *cb; CFIndex idx, numValues = CFSetGetCount(set); const void **list, *buffer[256]; CFAssert3(0 == capacity || numValues <= capacity, __kCFLogAssertion, "%s(): for fixed-mutable sets, capacity (%d) must be greater than or equal to initial number of values (%d)", __PRETTY_FUNCTION__, capacity, numValues); list = (numValues <= 256) ? buffer : CFAllocatorAllocate(allocator, numValues * sizeof(void *), 0); if (list != buffer && __CFOASafe) __CFSetLastAllocationEventName(list, "CFSet (temp)"); CFSetGetValues(set, list); cb = CF_IS_OBJC(__kCFSetTypeID, set) ? &kCFTypeSetCallBacks : __CFSetGetCallBacks(set); result = CFSetCreateMutable(allocator, capacity, cb); if (0 == capacity) _CFSetSetCapacity(result, numValues); for (idx = 0; idx < numValues; idx++) { CFSetAddValue(result, list[idx]); } if (list != buffer) CFAllocatorDeallocate(allocator, list); return result; }
void CFSetApplyFunction (CFSetRef set, CFSetApplierFunction applier, void *context) { // TODO: could be made more efficient by providing a specialized // implementation for the CF_IS_OBJC case const CFIndex count = CFSetGetCount (set); void **values = (void **) CFAllocatorAllocate (NULL, sizeof (void *) * count, 0); CFIndex i; CFSetGetValues (set, (const void **) values); for (i = 0; i < count; i++) { applier (values[i], context); } CFAllocatorDeallocate (NULL, (void *) values); }
static IOHIDDeviceRef* getDevRef(OSX_HID_REF *hid, CFIndex *deviceCount) { CFSetRef deviceCFSetRef; IOHIDDeviceRef *dev_refs=NULL; *deviceCount = 0; yEnterCriticalSection(&hid->hidMCS); deviceCFSetRef = IOHIDManagerCopyDevices(hid->manager); yLeaveCriticalSection(&hid->hidMCS); if (deviceCFSetRef!= NULL) { // how many devices in the set? *deviceCount = CFSetGetCount( deviceCFSetRef ); dev_refs = yMalloc( sizeof(IOHIDDeviceRef) * (u32)*deviceCount ); // now extract the device ref's from the set CFSetGetValues( deviceCFSetRef, (const void **) dev_refs ); } return dev_refs; }
void setAllKeyboards(LedState changes[]) { IOHIDManagerRef manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); if (!manager) { fprintf(stderr, "Failed to create IOHID manager.\n"); return; } CFDictionaryRef keyboard = getKeyboardDictionary(); if (!keyboard) { fprintf(stderr, "Failed to get dictionary usage page for kHIDUsage_GD_Keyboard.\n"); return; } IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone); IOHIDManagerSetDeviceMatching(manager, keyboard); CFSetRef devices = IOHIDManagerCopyDevices(manager); if (devices) { CFIndex deviceCount = CFSetGetCount(devices); if (deviceCount == 0) { fprintf(stderr, "Could not find any keyboard devices.\n"); } else { // Loop through all keyboards attempting to get or display led state IOHIDDeviceRef *deviceRefs = malloc(sizeof(IOHIDDeviceRef) * deviceCount); if (deviceRefs) { CFSetGetValues(devices, (const void **) deviceRefs); for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) if (isKeyboardDevice(deviceRefs[deviceIndex])) setKeyboard(deviceRefs[deviceIndex], keyboard, changes); free(deviceRefs); } } CFRelease(devices); } CFRelease(keyboard); }
CFSetRef CFSetCreateCopy (CFAllocatorRef allocator, CFSetRef set) { if (CF_IS_OBJC (_kCFSetTypeID, set)) { CFSetRef result; const CFIndex count = CFSetGetCount (set); void **values = (void **) CFAllocatorAllocate (allocator, sizeof (void *) * count, 0); CFSetGetValues (set, (const void **) values); result = CFSetCreate (allocator, (const void **) values, count, &kCFTypeSetCallBacks); CFAllocatorDeallocate (allocator, (void *) values); return result; } return (CFSetRef) GSHashTableCreateCopy (allocator, (GSHashTableRef) set); }
int main(void) { IOHIDManagerRef mgr; int i; mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); IOHIDManagerSetDeviceMatching(mgr, NULL); IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); CFSetRef device_set = IOHIDManagerCopyDevices(mgr); if (device_set==NULL) { return 0; } CFIndex num_devices = CFSetGetCount(device_set); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); CFSetGetValues(device_set, (const void **) device_array); for (i = 0; i < num_devices; i++) { IOHIDDeviceRef dev = device_array[i]; printf("Device: %p\n", dev); printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev)); wchar_t serial[256], buf[256]; char cbuf[256]; get_serial_number(dev, serial, 256); printf(" Serial: %ls\n", serial); printf(" Loc: %ld\n", get_location_id(dev)); get_transport(dev, buf, 256); printf(" Trans: %ls\n", buf); make_path(dev, cbuf, 256); printf(" Path: %s\n", cbuf); } return 0; }
CFArrayRef CFLocaleCopyAvailableLocaleIdentifiers(void) { int32_t locale, localeCount = uloc_countAvailable(); CFMutableSetRef working = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeSetCallBacks); for (locale = 0; locale < localeCount; ++locale) { const char *localeID = uloc_getAvailable(locale); CFStringRef string1 = CFStringCreateWithCString(kCFAllocatorSystemDefault, localeID, kCFStringEncodingASCII); CFStringRef string2 = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorSystemDefault, string1); CFSetAddValue(working, string1); // do not include canonicalized version as IntlFormats cannot cope with that in its popup CFRelease(string1); CFRelease(string2); } CFIndex cnt = CFSetGetCount(working); #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_LINUX || (DEPLOYMENT_TARGET_WINDOWS && __GNUC__) STACK_BUFFER_DECL(const void *, buffer, cnt); #else const void* buffer[BUFFER_SIZE]; #endif CFSetGetValues(working, buffer); CFArrayRef result = CFArrayCreate(kCFAllocatorSystemDefault, buffer, cnt, &kCFTypeArrayCallBacks); CFRelease(working); return result; }
bool JoystickImpl::open(unsigned int index) { m_index = index; Location deviceLoc = m_locationIDs[index]; // The device we need to load // Get all devices CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); if (devices == NULL) return false; // Get a usable copy of the joysticks devices. CFIndex joysticksCount = CFSetGetCount(devices); CFTypeRef devicesArray[joysticksCount]; CFSetGetValues(devices, devicesArray); // Get the desired joystick. IOHIDDeviceRef self = 0; for (CFIndex i(0); i < joysticksCount; ++i) { IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i]; if (deviceLoc == HIDInputManager::getLocationID(d)) { self = d; break; // We found it so we stop looping. } } if (self == 0) { // This shouldn't happen! CFRelease(devices); return false; } m_identification.name = getDeviceString(self, CFSTR(kIOHIDProductKey), m_index); m_identification.vendorId = getDeviceUint(self, CFSTR(kIOHIDVendorIDKey), m_index); m_identification.productId = getDeviceUint(self, CFSTR(kIOHIDProductIDKey), m_index); // Get a list of all elements attached to the device. CFArrayRef elements = IOHIDDeviceCopyMatchingElements(self, NULL, kIOHIDOptionsTypeNone); if (elements == NULL) { CFRelease(devices); return false; } // How many elements are there? CFIndex elementsCount = CFArrayGetCount(elements); if (elementsCount == 0) { // What is a joystick with no element? CFRelease(elements); CFRelease(devices); return false; } // Go through all connected elements. for (int i = 0; i < elementsCount; ++i) { IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); switch (IOHIDElementGetType(element)) { case kIOHIDElementTypeInput_Misc: switch (IOHIDElementGetUsage(element)) { case kHIDUsage_GD_X: m_axis[Joystick::X] = element; break; case kHIDUsage_GD_Y: m_axis[Joystick::Y] = element; break; case kHIDUsage_GD_Z: m_axis[Joystick::Z] = element; break; case kHIDUsage_GD_Rx: m_axis[Joystick::U] = element; break; case kHIDUsage_GD_Ry: m_axis[Joystick::V] = element; break; case kHIDUsage_GD_Rz: m_axis[Joystick::R] = element; break; // kHIDUsage_GD_Vx, kHIDUsage_GD_Vy, kHIDUsage_GD_Vz are ignored. } break; case kIOHIDElementTypeInput_Button: if (m_buttons.size() < Joystick::ButtonCount) // If we have free slot... m_buttons.push_back(element); // ...we add this element to the list // Else: too many buttons. We ignore this one. break; default: // Make compiler happy break; } } // Ensure that the buttons will be indexed in the same order as their // HID Usage (assigned by manufacturer and/or a driver). std::sort(m_buttons.begin(), m_buttons.end(), JoystickButtonSortPredicate); // Note: Joy::AxisPovX/Y are not supported (yet). // Maybe kIOHIDElementTypeInput_Axis is the corresponding type but I can't test. // Retain all these objects for personal use for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) CFRetain(*it); for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it) CFRetain(it->second); // Note: we didn't retain element in the switch because we might have multiple // Axis X (for example) and we want to keep only the last one. So to prevent // leaking we retain objects 'only' now. CFRelease(devices); CFRelease(elements); return true; }
//int main( int argc, const char * argv[] ) int manipulate_led( int which_led, int led_value ) { #pragma unused ( argc, argv ) IOHIDDeviceRef * tIOHIDDeviceRefs = nil; // create a IO HID Manager reference IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone ); require( tIOHIDManagerRef, Oops ); // Create a device matching dictionary CFDictionaryRef matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( TRUE, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ); require( matchingCFDictRef, Oops ); // set the HID device matching dictionary IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef ); if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } // Now open the IO HID Manager reference IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone ); require_noerr( tIOReturn, Oops ); // and copy out its devices CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef ); require( deviceCFSetRef, Oops ); // how many devices in the set? CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef ); // allocate a block of memory to extact the device ref's from the set into tIOHIDDeviceRefs = malloc( sizeof( IOHIDDeviceRef ) * deviceCount ); if (!tIOHIDDeviceRefs) { CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; goto Oops; } // now extract the device ref's from the set CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs ); CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; // before we get into the device loop we'll setup our element matching dictionary matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( FALSE, kHIDPage_LEDs, 0 ); require( matchingCFDictRef, Oops ); int pass; // do 256 passes //for ( pass = 0; pass < 256; pass++ ) { Boolean delayFlag = FALSE; // if we find an LED element we'll set this to TRUE //printf( "pass = %d.\n", pass ); for ( deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++ ) { // if this isn't a keyboard device... if ( !IOHIDDeviceConformsTo( tIOHIDDeviceRefs[deviceIndex], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ) ) { continue; // ...skip it } //printf( " device = %p.\n", tIOHIDDeviceRefs[deviceIndex] ); // copy all the elements CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRefs[deviceIndex], matchingCFDictRef, kIOHIDOptionsTypeNone ); require( elementCFArrayRef, next_device ); // for each device on the system these values are divided by the value ranges of all LED elements found // for example, if the first four LED element have a range of 0-1 then the four least significant bits of // this value will be sent to these first four LED elements, etc. int device_value = pass; // iterate over all the elements CFIndex elementIndex, elementCount = CFArrayGetCount( elementCFArrayRef ); for ( elementIndex = 0; elementIndex < elementCount; elementIndex++ ) { IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, elementIndex ); require( tIOHIDElementRef, next_element ); uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef ); // if this isn't an LED element... if ( kHIDPage_LEDs != usagePage ) { continue; // ...skip it } uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef ); IOHIDElementType tIOHIDElementType = IOHIDElementGetType( tIOHIDElementRef ); //printf( " element = %p (page: %d, usage: %d, type: %d ).\n", // tIOHIDElementRef, usagePage, usage, tIOHIDElementType ); // get the logical mix/max for this LED element CFIndex minCFIndex = IOHIDElementGetLogicalMin( tIOHIDElementRef ); CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef ); // calculate the range CFIndex modCFIndex = maxCFIndex - minCFIndex + 1; // compute the value for this LED element //CFIndex tCFIndex = minCFIndex + ( device_value % modCFIndex ); CFIndex tCFIndex = led_value; device_value /= modCFIndex; //printf( " value = 0x%08lX.\n", tCFIndex ); uint64_t timestamp = 0; // create the IO HID Value to be sent to this LED element IOHIDValueRef tIOHIDValueRef = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, tIOHIDElementRef, timestamp, tCFIndex ); if ( tIOHIDValueRef ) { // now set it on the device tIOReturn = IOHIDDeviceSetValue( tIOHIDDeviceRefs[deviceIndex], tIOHIDElementRef, tIOHIDValueRef ); CFRelease( tIOHIDValueRef ); require_noerr( tIOReturn, next_element ); delayFlag = TRUE; // set this TRUE so we'll delay before changing our LED values again } next_element: ; continue; } CFRelease( elementCFArrayRef ); next_device: ; continue; } // if we found an LED we'll delay before continuing //if ( delayFlag ) { // usleep( 500000 ); // sleep one half second //} // if the mouse is down… //if (GetCurrentButtonState()) { // break; // abort pass loop //} //} // next pass if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } Oops: ; if ( tIOHIDDeviceRefs ) { free(tIOHIDDeviceRefs); } if ( tIOHIDManagerRef ) { CFRelease( tIOHIDManagerRef ); } return 0; } /* main */
int main( int argc, const char * argv[] ) { Boolean initialized = FALSE; if (( argc != 4 ) && ( argc != 5 )) { printf ( "usage: Dream Cheeky Notifier R G B [A]\n\tRGB values should be 0-31. A is an optional parameter on whether to do the LED activation sequence. Anything larger than 0 is YES, default is 0 (activate).\n\n"); exit ( -1 ); } char r = (int)strtol ( argv[1], NULL, 10 ); char g = (int)strtol ( argv[2], NULL, 10 ); char b = (int)strtol ( argv[3], NULL, 10 ); if ( argc == 5 ) { initialized = TRUE; } if ((r < 0) || (r > 31) || (g < 0) || (g > 31) || (b < 0) || (b > 31)) { printf("RGB values must be within 0-31."); exit -1; } // create a IO HID Manager reference IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone ); // Create a device matching dictionary CFDictionaryRef matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( TRUE, kHIDPage_GenericDesktop, 0x10 ); // set the HID device matching dictionary IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef ); if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } // Now open the IO HID Manager reference IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone ); // and copy out its devices CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef ); // how many devices in the set? CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef ); // allocate a block of memory to extact the device ref's from the set into IOHIDDeviceRef * tIOHIDDeviceRefs = malloc( sizeof( IOHIDDeviceRef ) * deviceCount ); // now extract the device ref's from the set CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs ); // before we get into the device loop we'll setup our element matching dictionary (Note: we don't do element matching anymore) matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( FALSE, 0, 0 ); for ( deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++ ) { // if this isn't the notifier device... TODO: let's detect via vendor/product ids instead long vendor_id = 0; IOHIDDevice_GetLongProperty(tIOHIDDeviceRefs[deviceIndex], CFSTR(kIOHIDVendorIDKey), &vendor_id); long product_id = 0; IOHIDDevice_GetLongProperty(tIOHIDDeviceRefs[deviceIndex], CFSTR(kIOHIDProductIDKey), &product_id); if ((vendor_id != 0x1D34 ) || (product_id != 0x0004 )) { printf(" skipping device %p.\n", tIOHIDDeviceRefs[deviceIndex] ); continue; // ...skip it } printf( " device = %p.\n", tIOHIDDeviceRefs[deviceIndex] ); unsigned char report[8]; if (initialized == FALSE) { report[0] = 0x1F; // turn on LEDs report[1] = 0x02; report[2] = 0x00; report[3] = 0x5F; report[4] = 0x00; report[5] = 0x00; report[6] = 0x1A; report[7] = 0x03; // Note: We don't use the returned value here, so the compiler might throw a warning. IOReturn tIOReturn = IOHIDDeviceSetReport( tIOHIDDeviceRefs[deviceIndex], // IOHIDDeviceRef for the HID device kIOHIDReportTypeInput, // IOHIDReportType for the report (input, output, feature) 0, // CFIndex for the report ID report, // address of report buffer 8); // length of the report initialized = TRUE; } report[0] = r; // set brightness on LEDs to r, g, & b report[1] = g; report[2] = b; report[3] = 0x00; report[4] = 0x00; report[5] = 0x00; report[6] = 0x1A; report[7] = 0x05; tIOReturn = IOHIDDeviceSetReport( tIOHIDDeviceRefs[deviceIndex], // IOHIDDeviceRef for the HID device kIOHIDReportTypeInput, // IOHIDReportType for the report (input, output, feature) 0, // CFIndex for the report ID report, // address of report buffer 8); // length of the report next_device: ; continue; } if ( tIOHIDManagerRef ) { CFRelease( tIOHIDManagerRef ); } if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } Oops: ; return -1; } /* main */
bool HIDDevice::openDevice() { // Have to iterate through devices again to generate paths. CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager->HIDManager); CFIndex deviceCount = CFSetGetCount(deviceSet); // Allocate a block of memory and read the set into it. IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount); CFSetGetValues(deviceSet, (const void **) devices); // Iterate over devices. IOHIDDeviceRef device = NULL; for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { IOHIDDeviceRef tmpDevice = devices[deviceIndex]; if (!tmpDevice) { continue; } String path; if (!HIDManager->getPath(tmpDevice, &path)) { continue; } if (path == DevDesc.Path) { device = tmpDevice; break; } } OVR_FREE(devices); if (!device) { CFRelease(deviceSet); return false; } // Attempt to open device. if (IOHIDDeviceOpen(device, kIOHIDOptionsTypeSeizeDevice) != kIOReturnSuccess) { CFRelease(deviceSet); return false; } // Retain the device before we release the set. CFRetain(device); CFRelease(deviceSet); Device = device; if (!initInfo()) { IOHIDDeviceClose(Device, kIOHIDOptionsTypeSeizeDevice); CFRelease(Device); Device = NULL; return false; } // Setup the Run Loop and callbacks. IOHIDDeviceScheduleWithRunLoop(Device, HIDManager->getRunLoop(), kCFRunLoopDefaultMode); IOHIDDeviceRegisterInputReportCallback(Device, ReadBuffer, ReadBufferSize, staticHIDReportCallback, this); IOHIDDeviceRegisterRemovalCallback(Device, staticDeviceRemovedCallback, this); return true; }
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; CFIndex num_devices; int i; /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) return NULL; /* give the IOHIDManager a chance to update itself */ process_pending_events(); /* Get a list of the Devices */ IOHIDManagerSetDeviceMatching(hid_mgr, NULL); CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); /* Convert the list into a C array so we can iterate easily. */ num_devices = CFSetGetCount(device_set); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); CFSetGetValues(device_set, (const void **) device_array); /* Iterate over each device, making an entry for it. */ for (i = 0; i < num_devices; i++) { unsigned short dev_vid; unsigned short dev_pid; #define BUF_LEN 256 wchar_t buf[BUF_LEN]; IOHIDDeviceRef dev = device_array[i]; if (!dev) { continue; } dev_vid = get_vendor_id(dev); dev_pid = get_product_id(dev); /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 || vendor_id == dev_vid) && (product_id == 0x0 || product_id == dev_pid)) { struct hid_device_info *tmp; io_object_t iokit_dev; kern_return_t res; io_string_t path; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Get the Usage Page and Usage for this device. */ cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); /* Fill out the record */ cur_dev->next = NULL; /* Fill in the path (IOService plane) */ iokit_dev = hidapi_IOHIDDeviceGetService(dev); res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path); if (res == KERN_SUCCESS) cur_dev->path = strdup(path); else cur_dev->path = strdup(""); /* Serial Number */ get_serial_number(dev, buf, BUF_LEN); cur_dev->serial_number = dup_wcs(buf); /* Manufacturer and Product strings */ get_manufacturer_string(dev, buf, BUF_LEN); cur_dev->manufacturer_string = dup_wcs(buf); get_product_string(dev, buf, BUF_LEN); cur_dev->product_string = dup_wcs(buf); /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Release Number */ cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); /* Interface Number (Unsupported on Mac)*/ cur_dev->interface_number = -1; } } free(device_array); CFRelease(device_set); return root; }
int yUSBGetInterfaces(yInterfaceSt **ifaces,int *nbifaceDetect,char *errmsg) { int nbifaceAlloc; int deviceIndex; CFSetRef deviceCFSetRef; CFIndex deviceCount; IOHIDDeviceRef *dev_refs; // allocate buffer for detected interfaces *nbifaceDetect = 0; nbifaceAlloc = 8; *ifaces =yMalloc(nbifaceAlloc * sizeof(yInterfaceSt)); memset(*ifaces, 0 ,nbifaceAlloc * sizeof(yInterfaceSt)); yEnterCriticalSection(&yContext->hidMCS); deviceCFSetRef = IOHIDManagerCopyDevices( yContext->hidM ); yLeaveCriticalSection(&yContext->hidMCS); if(deviceCFSetRef== NULL){ //no device found return 0; } // how many devices in the set? deviceCount = CFSetGetCount( deviceCFSetRef ); HALLOG("%ld usb interfaces detected\n",deviceCount); dev_refs = yMalloc( sizeof(IOHIDDeviceRef) * (u32)deviceCount ); // now extract the device ref's from the set CFSetGetValues( deviceCFSetRef, (const void **) dev_refs ); for(deviceIndex=0 ; deviceIndex < deviceCount ;deviceIndex++){ u16 vendorid; u16 deviceid; IOHIDDeviceRef dev = dev_refs[deviceIndex]; yInterfaceSt *iface; vendorid = get_int_property(dev,CFSTR(kIOHIDVendorIDKey)); deviceid = get_int_property(dev,CFSTR(kIOHIDProductIDKey)); //ensure the buffer of detected interface is big enought if(*nbifaceDetect == nbifaceAlloc){ yInterfaceSt *tmp; tmp = (yInterfaceSt*) yMalloc(nbifaceAlloc*2 * sizeof(yInterfaceSt)); memset(tmp,0,nbifaceAlloc*2 * sizeof(yInterfaceSt)); yMemcpy(tmp,*ifaces, nbifaceAlloc * sizeof(yInterfaceSt) ); yFree(*ifaces); *ifaces = tmp; nbifaceAlloc *=2; } iface = *ifaces + *nbifaceDetect; iface->devref = dev; iface->vendorid = vendorid; iface->deviceid = deviceid; get_txt_property(dev,iface->serial,YOCTO_SERIAL_LEN*2, CFSTR(kIOHIDSerialNumberKey)); HALLOG("work on interface %d (%x:%x:%s)\n",deviceIndex,vendorid,deviceid,iface->serial); (*nbifaceDetect)++; } CFRelease(deviceCFSetRef); yFree(dev_refs); return YAPI_SUCCESS; }
bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor) { if (!initializeManager()) { return false; } CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager); if (!deviceSet) return false; CFIndex deviceCount = CFSetGetCount(deviceSet); // Allocate a block of memory and read the set into it. IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount); CFSetGetValues(deviceSet, (const void **) devices); // Iterate over devices. for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { IOHIDDeviceRef hidDev = devices[deviceIndex]; if (!hidDev) { continue; } HIDDeviceDesc devDesc; if (getPath(hidDev, &(devDesc.Path)) && initVendorProductVersion(hidDev, &devDesc) && enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) && initUsage(hidDev, &devDesc)) { initStrings(hidDev, &devDesc); initSerialNumber(hidDev, &devDesc); // Look for the device to check if it is already opened. Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc, true); // if device exists and it is opened then most likely the CreateHIDFile // will fail; therefore, we just set Enumerated to 'true' and continue. if (existingDevice && existingDevice->pDevice) { existingDevice->Enumerated = true; continue; } // open the device temporarily for startup communication if (IOHIDDeviceOpen(hidDev, kIOHIDOptionsTypeSeizeDevice) == kIOReturnSuccess) { // Construct minimal device that the visitor callback can get feature reports from. OSX::HIDDevice device(this, hidDev); enumVisitor->Visit(device, devDesc); IOHIDDeviceClose(hidDev, kIOHIDOptionsTypeSeizeDevice); } } } OVR_FREE(devices); CFRelease(deviceSet); return true; }
/************************************************************************** * find_osx_devices */ static int find_osx_devices(void) { IOHIDManagerRef hid_manager; int usages[] = { kHIDUsage_GD_Joystick, kHIDUsage_GD_GamePad }; int i; CFDictionaryRef matching_dicts[sizeof(usages) / sizeof(usages[0])]; CFArrayRef matching; CFSetRef devset; TRACE("()\n"); hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, 0L); if (IOHIDManagerOpen(hid_manager, 0) != kIOReturnSuccess) { ERR("Couldn't open IOHIDManager.\n"); CFRelease(hid_manager); return 0; } for (i = 0; i < sizeof(matching_dicts) / sizeof(matching_dicts[0]); i++) { matching_dicts[i] = create_osx_device_match(usages[i]); if (!matching_dicts[i]) { while (i > 0) CFRelease(matching_dicts[--i]); goto fail; } } matching = CFArrayCreate(NULL, (const void**)matching_dicts, sizeof(matching_dicts) / sizeof(matching_dicts[0]), &kCFTypeArrayCallBacks); for (i = 0; i < sizeof(matching_dicts) / sizeof(matching_dicts[0]); i++) CFRelease(matching_dicts[i]); IOHIDManagerSetDeviceMatchingMultiple(hid_manager, matching); CFRelease(matching); devset = IOHIDManagerCopyDevices(hid_manager); if (devset) { CFIndex num_devices, num_main_elements; const void** refs; CFArrayRef devices; num_devices = CFSetGetCount(devset); refs = HeapAlloc(GetProcessHeap(), 0, num_devices * sizeof(*refs)); if (!refs) { CFRelease(devset); goto fail; } CFSetGetValues(devset, refs); devices = CFArrayCreate(NULL, refs, num_devices, &kCFTypeArrayCallBacks); HeapFree(GetProcessHeap(), 0, refs); CFRelease(devset); if (!devices) goto fail; device_main_elements = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); if (!device_main_elements) { CFRelease(devices); goto fail; } num_main_elements = 0; for (i = 0; i < num_devices; i++) { IOHIDDeviceRef hid_device = (IOHIDDeviceRef)CFArrayGetValueAtIndex(devices, i); TRACE("hid_device %s\n", debugstr_device(hid_device)); num_main_elements += find_top_level(hid_device, device_main_elements); } CFRelease(devices); TRACE("found %i device(s), %i collection(s)\n",(int)num_devices,(int)num_main_elements); return (int)num_main_elements; } fail: IOHIDManagerClose(hid_manager, 0); CFRelease(hid_manager); return 0; }
// ---------------------------------------------------- int main(int argc, const char * argv[]) { #pragma unused ( argc, argv ) IOHIDManagerRef tIOHIDManagerRef = NULL; CFSetRef deviceCFSetRef = NULL; IOHIDDeviceRef *tIOHIDDeviceRefs = nil; do { tIOHIDManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); if (!tIOHIDManagerRef) { break; } IOHIDManagerSetDeviceMatching(tIOHIDManagerRef, NULL); IOReturn tIOReturn = IOHIDManagerOpen(tIOHIDManagerRef, kIOHIDOptionsTypeNone); if (noErr != tIOReturn) { break; } deviceCFSetRef = IOHIDManagerCopyDevices(tIOHIDManagerRef); if (!deviceCFSetRef) { break; } CFIndex deviceIndex, deviceCount = CFSetGetCount(deviceCFSetRef); tIOHIDDeviceRefs = malloc(sizeof(IOHIDDeviceRef) * deviceCount); if (!tIOHIDDeviceRefs) { break; } CFSetGetValues(deviceCFSetRef, (const void **)tIOHIDDeviceRefs); CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; for (deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++) { if (!tIOHIDDeviceRefs[deviceIndex]) { continue; } HIDDumpDeviceInfo(tIOHIDDeviceRefs[deviceIndex]); #if true // and copy all the elements CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRefs[deviceIndex], NULL /* matchingCFDictRef */, kIOHIDOptionsTypeNone); if (elementCFArrayRef) { // iterate over all the elements CFIndex elementIndex, elementCount = CFArrayGetCount(elementCFArrayRef); for (elementIndex = 0; elementIndex < elementCount; elementIndex++) { IOHIDElementRef tIOHIDElementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(elementCFArrayRef, elementIndex); if (tIOHIDElementRef) { HIDDumpElementInfo(tIOHIDElementRef); } } CFRelease(elementCFArrayRef); } #endif } } while (false); if (tIOHIDDeviceRefs) { free(tIOHIDDeviceRefs); } if (deviceCFSetRef) { CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; } if (tIOHIDManagerRef) { CFRelease(tIOHIDManagerRef); } return (0); } // main
bool JoystickImpl::open(unsigned int index) { m_index = index; m_hat = NULL; Location deviceLoc = m_locationIDs[index]; // The device we need to load // Get all devices CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); if (devices == NULL) return false; // Get a usable copy of the joysticks devices. CFIndex joysticksCount = CFSetGetCount(devices); CFTypeRef devicesArray[joysticksCount]; CFSetGetValues(devices, devicesArray); // Get the desired joystick. IOHIDDeviceRef self = 0; for (CFIndex i(0); self == 0 && i < joysticksCount; ++i) { IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i]; if (deviceLoc == HIDInputManager::getLocationID(d)) self = d; } if (self == 0) { CFRelease(devices); return false; } m_identification.name = getDeviceString(self, CFSTR(kIOHIDProductKey), m_index); m_identification.vendorId = getDeviceUint(self, CFSTR(kIOHIDVendorIDKey), m_index); m_identification.productId = getDeviceUint(self, CFSTR(kIOHIDProductIDKey), m_index); // Get a list of all elements attached to the device. CFArrayRef elements = IOHIDDeviceCopyMatchingElements(self, NULL, kIOHIDOptionsTypeNone); if (elements == NULL) { CFRelease(devices); return false; } // Go through all connected elements. CFIndex elementsCount = CFArrayGetCount(elements); for (int i = 0; i < elementsCount; ++i) { IOHIDElementRef element = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i); switch (IOHIDElementGetUsagePage(element)) { case kHIDPage_GenericDesktop: switch (IOHIDElementGetUsage(element)) { case kHIDUsage_GD_X: m_axis[Joystick::X] = element; break; case kHIDUsage_GD_Y: m_axis[Joystick::Y] = element; break; case kHIDUsage_GD_Z: m_axis[Joystick::Z] = element; break; case kHIDUsage_GD_Rx: m_axis[Joystick::U] = element; break; case kHIDUsage_GD_Ry: m_axis[Joystick::V] = element; break; case kHIDUsage_GD_Rz: m_axis[Joystick::R] = element; break; case kHIDUsage_GD_Hatswitch: // From §4.3 MiscellaneousControls of HUT v1.12: // // > Hat Switch: // > A typical example is four switches that are capable of generating // > information about four possible directions in which the knob can be // > tilted. Intermediate positions can also be decoded if the hardware // > allows two switches to be reported simultaneously. // // We assume this model here as well. Hence, with 4 switches and intermediate // positions we have 8 values (0-7) plus the "null" state (8). { CFIndex min = IOHIDElementGetLogicalMin(element); CFIndex max = IOHIDElementGetLogicalMax(element); if (min != 0 || max != 7) { sf::err() << std::hex << "Joystick (vendor/product id: 0x" << m_identification.vendorId << "/0x" << m_identification.productId << std::dec << ") range is an unexpected one: [" << min << ", " << max << "]" << std::endl; } else { m_hat = element; } } break; case kHIDUsage_GD_GamePad: // We assume a game pad is an application collection, meaning it doesn't hold // any values per say. They kind of "emit" the joystick's usages. // See §3.4.3 Usage Types (Collection) of HUT v1.12 if (IOHIDElementGetCollectionType(element) != kIOHIDElementCollectionTypeApplication) { sf::err() << std::hex << "Gamepage (vendor/product id: 0x" << m_identification.vendorId << "/0x" << m_identification.productId << ") is not an CA but a 0x" << IOHIDElementGetCollectionType(element) << std::dec << std::endl; } break; default: #ifdef SFML_DEBUG sf::err() << "Unexpected usage for element of Page Generic Desktop: 0x" << std::hex << IOHIDElementGetUsage(element) << std::dec << std::endl; #endif break; } break; case kHIDPage_Button: if (m_buttons.size() < Joystick::ButtonCount) // If we have free slot... m_buttons.push_back(element); // ...we add this element to the list // Else: too many buttons. We ignore this one. break; default: /* No other page is expected because of the mask applied by the HID manager. */ break; } } // Ensure that the buttons will be indexed in the same order as their // HID Usage (assigned by manufacturer and/or a driver). std::sort(m_buttons.begin(), m_buttons.end(), JoystickButtonSortPredicate); // Retain all these objects for personal use for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it) CFRetain(*it); for (AxisMap::iterator it(m_axis.begin()); it != m_axis.end(); ++it) CFRetain(it->second); if (m_hat != NULL) CFRetain(m_hat); // Note: we didn't retain element in the switch because we might have multiple // Axis X (for example) and we want to keep only the last one. To prevent // leaking we retain objects 'only' now. CFRelease(devices); CFRelease(elements); return true; }
bool JoystickImpl::isConnected(unsigned int index) { bool state = false; // Is the index-th joystick connected? // First, let's check if the device was previously detected: if (m_locationIDs[index] != 0) { state = true; } else { // Otherwise, let's check if it is now connected // i.e., m_locationIDs[index] == 0 // if there is more connected joystick to the HID manager than // opened joystick devices then we find the new one. unsigned int openedCount = 0; for (unsigned int i(0); i < sf::Joystick::Count; ++i) { if (m_locationIDs[i] != 0) openedCount++; } unsigned int connectedCount = HIDJoystickManager::getInstance().getJoystickCount(); if (connectedCount > openedCount) { // Get all devices CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); if (devices != NULL) { CFIndex size = CFSetGetCount(devices); if (size > 0) { CFTypeRef array[size]; // array of IOHIDDeviceRef CFSetGetValues(devices, array); // If there exists a device d s.t. there is no j s.t. // m_locationIDs[j] == d's location then we have a new device. for (CFIndex didx(0); didx < size; ++didx) { IOHIDDeviceRef d = (IOHIDDeviceRef)array[didx]; Location dloc = HIDInputManager::getLocationID(d); bool foundJ = false; for (unsigned int j(0); j < Joystick::Count; ++j) { if (m_locationIDs[j] == dloc) { foundJ = true; break; // no need to loop again } } if (!foundJ) { // This is a new device // We set it up for Open(..) m_locationIDs[index] = dloc; state = true; break; // We stop looking for a new device } } } CFRelease(devices); } } } return state; }
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct hid_device_info *root = NULL; // return object struct hid_device_info *cur_dev = NULL; CFIndex num_devices; int i; setlocale(LC_ALL,""); /* Set up the HID Manager if it hasn't been done */ hid_init(); /* Get a list of the Devices */ CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); /* Convert the list into a C array so we can iterate easily. */ num_devices = CFSetGetCount(device_set); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); CFSetGetValues(device_set, (const void **) device_array); /* Iterate over each device, making an entry for it. */ for (i = 0; i < num_devices; i++) { unsigned short dev_vid; unsigned short dev_pid; #define BUF_LEN 256 wchar_t buf[BUF_LEN]; char cbuf[BUF_LEN]; IOHIDDeviceRef dev = device_array[i]; if (!dev) { continue; } dev_vid = get_vendor_id(dev); dev_pid = get_product_id(dev); /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 && product_id == 0x0) || (vendor_id == dev_vid && product_id == dev_pid)) { struct hid_device_info *tmp; size_t len; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; // Get the Usage Page and Usage for this device. cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); /* Fill out the record */ cur_dev->next = NULL; len = make_path(dev, cbuf, sizeof(cbuf)); cur_dev->path = strdup(cbuf); /* Serial Number */ get_serial_number(dev, buf, BUF_LEN); cur_dev->serial_number = dup_wcs(buf); /* Manufacturer and Product strings */ get_manufacturer_string(dev, buf, BUF_LEN); cur_dev->manufacturer_string = dup_wcs(buf); get_product_string(dev, buf, BUF_LEN); cur_dev->product_string = dup_wcs(buf); /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Release Number */ cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); /* Interface Number (Unsupported on Mac)*/ cur_dev->interface_number = -1; } } free(device_array); CFRelease(device_set); return root; }
hid_device * HID_API_EXPORT hid_open_path(const char *path) { int i; hid_device *dev = NULL; CFIndex num_devices; dev = new_hid_device(); /* Set up the HID Manager if it hasn't been done */ hid_init(); CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); num_devices = CFSetGetCount(device_set); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); CFSetGetValues(device_set, (const void **) device_array); for (i = 0; i < num_devices; i++) { char cbuf[BUF_LEN]; size_t len; IOHIDDeviceRef os_dev = device_array[i]; len = make_path(os_dev, cbuf, sizeof(cbuf)); if (!strcmp(cbuf, path)) { // Matched Paths. Open this Device. IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone); if (ret == kIOReturnSuccess) { char str[32]; free(device_array); CFRelease(device_set); dev->device_handle = os_dev; /* Create the buffers for receiving data */ dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev); dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); /* Create the Run Loop Mode for this device. printing the reference seems to work. */ sprintf(str, "HIDAPI_%p", os_dev); dev->run_loop_mode = CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); /* Attach the device to a Run Loop */ IOHIDDeviceRegisterInputReportCallback( os_dev, dev->input_report_buf, dev->max_input_report_len, &hid_report_callback, dev); IOHIDManagerRegisterDeviceRemovalCallback(hid_mgr, hid_device_removal_callback, NULL); /* Start the read thread */ pthread_create(&dev->thread, NULL, read_thread, dev); /* Wait here for the read thread to be initialized. */ pthread_barrier_wait(&dev->barrier); return dev; } else { goto return_error; } } } return_error: free(device_array); CFRelease(device_set); free_hid_device(dev); return NULL; }
JoystickState JoystickImpl::update() { static const JoystickState disconnectedState; // return this if joystick was disconnected JoystickState state; // otherwise return that state.connected = true; // Note: free up is done in close() which is called, if required, // by the joystick manager. So we don't release buttons nor axes here. // First, let's determine if the joystick is still connected Location selfLoc = m_locationIDs[m_index]; // Get all devices CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks(); if (devices == NULL) return disconnectedState; // Get a usable copy of the joysticks devices. CFIndex joysticksCount = CFSetGetCount(devices); CFTypeRef devicesArray[joysticksCount]; CFSetGetValues(devices, devicesArray); // Search for it bool found = false; for (CFIndex i(0); i < joysticksCount; ++i) { IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i]; if (selfLoc == HIDInputManager::getLocationID(d)) { found = true; break; // Stop looping } } // Release unused stuff CFRelease(devices); // If not found we consider it disconnected if (!found) return disconnectedState; // Update buttons' state unsigned int i = 0; for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it, ++i) { IOHIDValueRef value = 0; IOHIDDeviceGetValue(IOHIDElementGetDevice(*it), *it, &value); // Check for plug out. if (!value) { // No value? Hum... Seems like the joystick is gone return disconnectedState; } // 1 means pressed, others mean released state.buttons[i] = IOHIDValueGetIntegerValue(value) == 1; } // Update axes' state for (AxisMap::iterator it = m_axis.begin(); it != m_axis.end(); ++it) { IOHIDValueRef value = 0; IOHIDDeviceGetValue(IOHIDElementGetDevice(it->second), it->second, &value); // Check for plug out. if (!value) { // No value? Hum... Seems like the joystick is gone return disconnectedState; } // We want to bind [physicalMin,physicalMax] to [-100=min,100=max]. // // General formula to bind [a,b] to [c,d] with a linear progression: // // f: [a, b] -> [c, d] // x |-> (x-a)(d-c)/(b-a)+c // // This method might not be very accurate (the "0 position" can be // slightly shift with some device) but we don't care because most // of devices are so sensitive that this is not relevant. double physicalMax = IOHIDElementGetPhysicalMax(it->second); double physicalMin = IOHIDElementGetPhysicalMin(it->second); double scaledMin = -100; double scaledMax = 100; double physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical); float scaledValue = (((physicalValue - physicalMin) * (scaledMax - scaledMin)) / (physicalMax - physicalMin)) + scaledMin; state.axes[it->first] = scaledValue; } return state; }