📄 osx.c
字号:
{ pRecElement pCurrentElement = NULL; // create device interface result = HIDCreateOpenDeviceInterface (hidDevice, pDevice); if (kIOReturnSuccess != result) HIDReportErrorNum ("HIDCreateOpenDeviceInterface failed.", result); hid_GetDeviceInfo (hidDevice, hidProperties, pDevice); // hidDevice used to find parents in registry tree // set current device for use in getting elements gCurrentGetDevice = pDevice; // Add all elements hid_GetCollectionElements (hidProperties, &pCurrentElement); gCurrentGetDevice = NULL; CFRelease (hidProperties); } else HIDReportErrorNum ("IORegistryEntryCreateCFProperties error when creating deviceProperties.", result); } else HIDReportError ("malloc error when allocating pRecDevice."); return pDevice;}#if USE_NOTIFICATIONS//================================================================================================//// hid_DeviceNotification//// This routine will get called whenever any kIOGeneralInterest notification happens. We are// interested in the kIOMessageServiceIsTerminated message so that's what we look for. Other// messages are defined in IOMessage.h.////================================================================================================//static void hid_DeviceNotification( void *refCon, io_service_t service, natural_t messageType, void *messageArgument ){ pRecDevice pDevice = (pRecDevice) refCon; if (messageType == kIOMessageServiceIsTerminated) { //printf("Device 0x%08x \"%s\"removed.\n", service, pDevice->product); // ryan added this. if (pDevice->disconnect == DISCONNECT_CONNECTED) pDevice->disconnect = DISCONNECT_TELLUSER; // Free the data we're no longer using now that the device is going away // ryan commented this out. //hid_DisposeDevice (pDevice); }}#elsestatic void hid_RemovalCallbackFunction(void * target, IOReturn result, void * refcon, void * sender){ // ryan commented this out. //hid_DisposeDevice ((pRecDevice) target); // ryan added this. pRecDevice = (pRecDevice) target; if (pDevice->disconnect == DISCONNECT_CONNECTED) pDevice->disconnect = DISCONNECT_TELLUSER;}#endif USE_NOTIFICATIONSstatic void hid_AddDevices (void *refCon, io_iterator_t iterator){ // NOTE: refcon passed in is used to point to the device list head pRecDevice* pListDeviceHead = (pRecDevice*) refCon; IOReturn result = kIOReturnSuccess; io_object_t ioHIDDeviceObject = 0; while ((ioHIDDeviceObject = IOIteratorNext (iterator)) != 0) { pRecDevice* pNewDeviceAt = NULL; pRecDevice pNewDevice = hid_BuildDevice (ioHIDDeviceObject); if (pNewDevice) {#if 0 // set true for verbose output printf("\nhid_AddDevices: pNewDevice = {t: \"%s\", v: %ld, p: %ld, v: %ld, m: \"%s\", " \ "p: \"%s\", l: %ld, u: %4.4lX:%4.4lX, #e: %ld, #f: %ld, #i: %ld, #o: %ld, " \ "#c: %ld, #a: %ld, #b: %ld, #h: %ld, #s: %ld, #d: %ld, #w: %ld}.", pNewDevice->transport, pNewDevice->vendorID, pNewDevice->productID, pNewDevice->version, pNewDevice->manufacturer, pNewDevice->product, pNewDevice->locID, pNewDevice->usagePage, pNewDevice->usage, pNewDevice->totalElements, pNewDevice->features, pNewDevice->inputs, pNewDevice->outputs, pNewDevice->collections, pNewDevice->axis, pNewDevice->buttons, pNewDevice->hats, pNewDevice->sliders, pNewDevice->dials, pNewDevice->wheels ); fflush(stdout);#elif 0 // otherwise output brief description printf("\nhid_AddDevices: pNewDevice = {m: \"%s\" p: \"%s\", vid: %ld, pid: %ld, loc: %8.8lX, usage: %4.4lX:%4.4lX}.", pNewDevice->manufacturer, pNewDevice->product, pNewDevice->vendorID, pNewDevice->productID, pNewDevice->locID, pNewDevice->usagePage, pNewDevice->usage ); fflush(stdout);#endif pNewDeviceAt = hid_AddDevice (pListDeviceHead, pNewDevice); }#if USE_NOTIFICATIONS // Register for an interest notification of this device being removed. Use a reference to our // private data as the refCon which will be passed to the notification callback. result = IOServiceAddInterestNotification( gNotifyPort, // notifyPort ioHIDDeviceObject, // service kIOGeneralInterest, // interestType hid_DeviceNotification, // callback pNewDevice, // refCon (io_object_t*) &pNewDevice->notification); // notification if (KERN_SUCCESS != result) HIDReportErrorNum ("hid_AddDevices: IOServiceAddInterestNotification error: x0%8.8lX.", result);#else result = (*(IOHIDDeviceInterface**)pNewDevice->interface)->setRemovalCallback (pNewDevice->interface, hid_RemovalCallbackFunction,pNewDeviceAt,0);#endif USE_NOTIFICATIONS // release the device object, it is no longer needed result = IOObjectRelease (ioHIDDeviceObject); if (KERN_SUCCESS != result) HIDReportErrorNum ("hid_AddDevices: IOObjectRelease error with ioHIDDeviceObject.", result); }}static Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage){ IOReturn result = kIOReturnSuccess; mach_port_t masterPort = 0; if (NULL != gpDeviceList) HIDReleaseDeviceList (); result = IOMasterPort (bootstrap_port, &masterPort); if (kIOReturnSuccess != result) HIDReportErrorNum ("IOMasterPort error with bootstrap_port.", result); else { CFMutableDictionaryRef hidMatchDictionary = NULL; // Set up matching dictionary to search the I/O Registry for HID devices we are interested in. Dictionary reference is NULL if error. { CFNumberRef refUsage = NULL, refUsagePage = NULL; // Set up a matching dictionary to search I/O Registry by class name for all HID class devices. hidMatchDictionary = IOServiceMatching (kIOHIDDeviceKey); if (NULL != hidMatchDictionary) { if (usagePage) { // Add key for device type (joystick, in this case) to refine the matching dictionary. refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usagePage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); CFRelease (refUsagePage); if (usage) { refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberLongType, &usage); CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); CFRelease (refUsage); } } CFRetain(hidMatchDictionary); } else HIDReportError ("Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); }#if USE_NOTIFICATIONS // Create a notification port and add its run loop event source to our run loop // This is how async notifications get set up. { CFRunLoopSourceRef runLoopSource; gNotifyPort = IONotificationPortCreate(masterPort); runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); gRunLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); // Now set up a notification to be called when a device is first matched by I/O Kit. result = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType hidMatchDictionary, // matching hid_AddDevices, // callback &gpDeviceList, // refCon &gAddedIter // notification ); // call it now to add all existing devices hid_AddDevices(&gpDeviceList,gAddedIter); return true; }#else { io_iterator_t hidObjectIterator = NULL; // Now search I/O Registry for matching devices. result = IOServiceGetMatchingServices (masterPort, hidMatchDictionary, &hidObjectIterator); if (kIOReturnSuccess != result) HIDReportErrorNum ("Failed to create IO object iterator, error:", result); else if (NULL == hidObjectIterator) // likely no HID devices which matched selection criteria are connected HIDReportError ("Warning: Could not find any matching devices, thus iterator creation failed."); if (NULL != hidObjectIterator) { hid_AddDevices(&gpDeviceList,hidObjectIterator); result = IOObjectRelease (hidObjectIterator); // release the iterator if (kIOReturnSuccess != result) HIDReportErrorNum ("IOObjectRelease error with hidObjectIterator.", result); gNumDevices = hid_CountCurrentDevices (); return true; } }#endif USE_NOTIFICATIONS // IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. hidMatchDictionary = NULL; } return false;}// ---------------------------------// release list built by above function// MUST be called prior to application exit to properly release devices// if not called (or app crashes) devices can be recovered by pluging into different location in USB chainstatic void HIDReleaseDeviceList (void){ while (NULL != gpDeviceList) gpDeviceList = hid_DisposeDevice (gpDeviceList); // dispose current device return next device will set gpDeviceList to NULL gNumDevices = 0;}// ---------------------------------// get the first device in the device list// returns NULL if no list existsstatic pRecDevice HIDGetFirstDevice (void){ return gpDeviceList;}// ---------------------------------// get next device in list given current device as parameter// returns NULL if end of liststatic pRecDevice HIDGetNextDevice (pRecDevice pDevice){ if (NULL != pDevice) return pDevice->pNext; else return NULL;}// ---------------------------------// get the first element of device passed in as parameter// returns NULL if no list exists or device does not exists or is NULLstatic pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask){ if (HIDIsValidDevice(pDevice)) { if (hid_MatchElementTypeMask (pDevice->pListElements->type, typeMask)) // ensure first type matches return pDevice->pListElements; else return HIDGetNextDeviceElement (pDevice->pListElements, typeMask); } else return NULL;}// ---------------------------------// get next element of given device in list given current element as parameter// will walk down each collection then to next element or collection (depthwise traverse)// returns NULL if end of list// uses mask of HIDElementTypeMask to restrict element found// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionalitystatic pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask){ // should only have elements passed in (though someone could mix calls and pass us a collection) // collection means return the next child or sibling (in that order) // element means returnt he next sibling (as elements can't have children if (NULL != pElement) { if (pElement->pChild) { if (pElement->type != kIOHIDElementTypeCollection) HIDReportError ("Malformed element list: found child of element."); else return hid_GetDeviceElement (pElement->pChild, typeMask); // return the child of this element } else if (pElement->pSibling) { return hid_GetDeviceElement (pElement->pSibling, typeMask); //return the sibling of this element } else // at end back up correctly { pRecElement pPreviousElement = NULL; // malformed device ending in collection if (pElement->type == kIOHIDElementTypeCollection) HIDReportError ("Malformed device: found collection at end of element chain."); // walk back up tree to element prior to first collection ecountered and take next element while (NULL != pElement->pPrevious) { pPreviousElement = pElement; pElement = pElement->pPrevious; // look at previous element // if we have a collection and the previous element is the branch element (should have both a colection and next element attached to it) // if we found a collection, which we are not at the sibling level that actually does have siblings if (((pElement->type == kIOHIDElementTypeCollection) && (pPreviousElement != pElement->pSibling) && pElement->pSibling) || // or if we are at the top (NULL == pElement->pPrevious)) // at top of tree break; } if (NULL == pElement->pPrevious) return NULL; // got to top of list with only a collection as the first element // now we must have been down the child route so go down the sibling route
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -