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 */ if (hid_init() < 0) return NULL; /* give the IOHIDManager a chance to update itself */ process_pending_events(); 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", (void*)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; }
static int find_osx_devices(void) { IOReturn tIOReturn; CFMutableDictionaryRef result; CFSetRef devset; CFArrayRef matching; gIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, 0L ); tIOReturn = IOHIDManagerOpen( gIOHIDManagerRef, 0L); if ( kIOReturnSuccess != tIOReturn ) { ERR("Couldn't open IOHIDManager.\n"); return 0; } matching = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks ); /* build matching dictionary */ result = creates_osx_device_match(kHIDUsage_GD_Joystick); if (!result) { CFRelease(matching); return 0; } CFArrayAppendValue( ( CFMutableArrayRef )matching, result ); result = creates_osx_device_match(kHIDUsage_GD_GamePad); if (!result) { CFRelease(matching); return 0; } CFArrayAppendValue( ( CFMutableArrayRef )matching, result ); IOHIDManagerSetDeviceMatchingMultiple( gIOHIDManagerRef, matching); devset = IOHIDManagerCopyDevices( gIOHIDManagerRef ); if (devset) { CFIndex countDevices, countCollections, idx; CFArrayRef gDevices = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); CFSetApplyFunction(devset, CFSetApplierFunctionCopyToCFArray, (void*)gDevices); CFRelease( devset); countDevices = CFArrayGetCount(gDevices); gCollections = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); if (!gCollections) return 0; countCollections = 0; for (idx = 0; idx < countDevices; idx++) { CFIndex tTop; IOHIDDeviceRef tDevice; tDevice = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDevices, idx); tTop = find_top_level(tDevice, gCollections); countCollections += tTop; } CFRelease(gDevices); TRACE("found %i device(s), %i collection(s)\n",(int)countDevices,(int)countCollections); return (int)countCollections; } 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
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 */ if (hid_init() < 0) return NULL; /* give the IOHIDManager a chance to update itself */ process_pending_events(); /* 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; }
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; }
/************************************************************************** * 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 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; }
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 */ if (!hid_mgr) init_hid_manager(); 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]; CFIndex max_input_report_len; free(device_array); CFRelease(device_set); dev->device_handle = os_dev; /* Create the buffers for receiving data */ max_input_report_len = (CFIndex) get_max_report_length(os_dev); dev->input_report_buf = calloc(max_input_report_len, sizeof(uint8_t)); /* Create the Run Loop Mode for this device. printing the reference seems to work. */ sprintf(str, "%p", os_dev); dev->run_loop_mode = CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); /* Attach the device to a Run Loop */ IOHIDDeviceScheduleWithRunLoop(os_dev, CFRunLoopGetCurrent(), dev->run_loop_mode); IOHIDDeviceRegisterInputReportCallback( os_dev, dev->input_report_buf, max_input_report_len, &hid_report_callback, dev); pthread_mutex_init(&dev->mutex, NULL); return dev; } else { goto return_error; } } } return_error: free(device_array); CFRelease(device_set); free(dev); return NULL; }
struct hid_device_info HID_API_EXPORT *hid_enumerate(uint16_t vendor_id, uint16_t 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 */ if (!hid_mgr) init_hid_manager(); /* 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++) { uint16_t dev_vid; uint16_t dev_pid; #define BUF_LEN 256 wchar_t buf[BUF_LEN]; char cbuf[BUF_LEN]; IOHIDDeviceRef dev = device_array[i]; 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; /* 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; } } free(device_array); CFRelease(device_set); return root; }
CFSetRef HIDJoystickManager::copyJoysticks() { CFSetRef devices = IOHIDManagerCopyDevices(m_manager); return devices; }
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); // 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; } // 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; }