📄 osx.c
字号:
if (NULL == pDevice) return; if (elementType) { // look at types of interest if (elementType != kIOHIDElementTypeCollection) { if (usagePage && usage) // if valid usage and page { switch (usagePage) // only interested in kHIDPage_GenericDesktop and kHIDPage_Button { case kHIDPage_GenericDesktop: { switch (usage) // look at usage to determine function { case kHIDUsage_GD_X: case kHIDUsage_GD_Y: case kHIDUsage_GD_Z: case kHIDUsage_GD_Rx: case kHIDUsage_GD_Ry: case kHIDUsage_GD_Rz: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->axis++; break; case kHIDUsage_GD_Slider: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->sliders++; break; case kHIDUsage_GD_Dial: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->dials++; break; case kHIDUsage_GD_Wheel: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->wheels++; break; case kHIDUsage_GD_Hatswitch: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->hats++; break; default: pElement = (pRecElement) malloc (sizeof (recElement)); break; } } break; case kHIDPage_Button: pElement = (pRecElement) malloc (sizeof (recElement)); if (pElement) pDevice->buttons++; break; default: // just add a generic element pElement = (pRecElement) malloc (sizeof (recElement)); break; } }#if 0 else HIDReportError ("CFNumberGetValue error when getting value for refUsage or refUsagePage.");#endif 0 } else // collection pElement = (pRecElement) malloc (sizeof (recElement)); } else HIDReportError ("CFNumberGetValue error when getting value for refElementType."); if (pElement) // add to list { // this code builds a binary tree based on the collection hierarchy of inherent in the device element layout // it preserves the structure of the lements as collections have children and elements are siblings to each other // clear record bzero(pElement,sizeof(recElement)); // get element info pElement->type = elementType; pElement->usagePage = usagePage; pElement->usage = usage; pElement->depth = 0; // assume root object hid_GetElementInfo (refElement, pElement); // count elements pDevice->totalElements++; switch (pElement->type) { case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: pDevice->inputs++; break; case kIOHIDElementTypeOutput: pDevice->outputs++; break; case kIOHIDElementTypeFeature: pDevice->features++; break; case kIOHIDElementTypeCollection: pDevice->collections++; break; default: HIDReportErrorNum ("Unknown element type : ", pElement->type); } if (NULL == *ppElementCurrent) // if at list head { pDevice->pListElements = pElement; // add current element *ppElementCurrent = pElement; // set current element to element we just added } else // have exsiting structure { if (gAddAsChild) // if the previous element was a collection, let's add this as a child of the previous { // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works while ((*ppElementCurrent)->pChild) // step down tree until free child node found *ppElementCurrent = (*ppElementCurrent)->pChild; (*ppElementCurrent)->pChild = pElement; // insert there pElement->depth = (*ppElementCurrent)->depth + 1; } else // add as sibling { // this iteration should not be needed but there maybe some untested degenerate case which this code will ensure works while ((*ppElementCurrent)->pSibling) // step down tree until free sibling node found *ppElementCurrent = (*ppElementCurrent)->pSibling; (*ppElementCurrent)->pSibling = pElement; // insert there pElement->depth = (*ppElementCurrent)->depth; } pElement->pPrevious = *ppElementCurrent; // point to previous *ppElementCurrent = pElement; // set current to our collection } if (elementType == kIOHIDElementTypeCollection) // if this element is a collection of other elements { gAddAsChild = true; // add next set as children to this element gDepth++; hid_GetCollectionElements ((CFMutableDictionaryRef) refElement, &pElement); // recursively process the collection gDepth--; } gAddAsChild = false; // add next as this elements sibling (when return from a collection or with non-collections) }#if 0 else HIDReportError ("hid_AddElement - no element added.");#endif}static void hid_GetElementsCFArrayHandler (const void * value, void * parameter){ if (CFGetTypeID (value) == CFDictionaryGetTypeID ()) hid_AddElement ((CFTypeRef) value, (pRecElement *) parameter);}// ---------------------------------// handles retrieval of element information from arrays of elements in device IO registry informationstatic void hid_GetElements (CFTypeRef refElementCurrent, pRecElement *ppCurrentElement){ CFTypeID type = CFGetTypeID (refElementCurrent); if (type == CFArrayGetTypeID()) // if element is an array { CFRange range = {0, CFArrayGetCount (refElementCurrent)}; // CountElementsCFArrayHandler called for each array member CFArrayApplyFunction (refElementCurrent, range, hid_GetElementsCFArrayHandler, ppCurrentElement); }}static void hid_TopLevelElementHandler (const void * value, void * parameter){ CFTypeRef refCF = 0; if ((NULL == value) || (NULL == parameter)) return; // (kIOReturnBadArgument) if (CFGetTypeID (value) != CFDictionaryGetTypeID ()) return; // (kIOReturnBadArgument) refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsagePageKey)); if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usagePage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); refCF = CFDictionaryGetValue (value, CFSTR(kIOHIDElementUsageKey)); if (!CFNumberGetValue (refCF, kCFNumberLongType, &((pRecDevice) parameter)->usage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usage.");}static void hid_GetDeviceInfo (io_object_t hidDevice, CFMutableDictionaryRef hidProperties, pRecDevice pDevice){ CFMutableDictionaryRef usbProperties = 0; io_registry_entry_t parent1, parent2; // 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 (hidDevice, 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 transport refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDTransportKey)); if (refCF) { if (!CFStringGetCString (refCF, pDevice->transport, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->transport."); } // get vendorID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVendorIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("idVendor")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->vendorID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->vendorID."); } // get product ID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("idProduct")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->productID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->productID."); } // get product version refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDVersionNumberKey)); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->version)) HIDReportError ("CFNumberGetValue error retrieving pDevice->version."); } // get manufacturer name refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDManufacturerKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Vendor Name")); if (refCF) { if (!CFStringGetCString (refCF, pDevice->manufacturer, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->manufacturer."); } // get product name refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDProductKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("USB Product Name")); if (refCF) { if (!CFStringGetCString (refCF, pDevice->product, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->product."); } // get serial refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDSerialNumberKey)); if (refCF) { if (!CFStringGetCString (refCF, pDevice->serial, 256, CFStringGetSystemEncoding ())) HIDReportError ("CFStringGetCString error retrieving pDevice->serial."); } // get location ID refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDLocationIDKey)); if (!refCF) refCF = CFDictionaryGetValue (usbProperties, CFSTR("locationID")); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->locID)) HIDReportError ("CFNumberGetValue error retrieving pDevice->locID."); } // get usage page and usage refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); if (refCF) { if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usagePage."); refCF = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); if (refCF) if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) HIDReportError ("CFNumberGetValue error retrieving pDevice->usage."); } if (NULL == refCF) // get top level element HID usage page or usage { // use top level element instead CFTypeRef refCFTopElement = 0; refCFTopElement = CFDictionaryGetValue (hidProperties, CFSTR(kIOHIDElementKey)); { // refCFTopElement points to an array of element dictionaries CFRange range = {0, CFArrayGetCount (refCFTopElement)}; CFArrayApplyFunction (refCFTopElement, range, hid_TopLevelElementHandler, NULL); } } } else HIDReportError ("IORegistryEntryCreateCFProperties failed to create usbProperties."); CFRelease (usbProperties); if (kIOReturnSuccess != IOObjectRelease (parent2)) HIDReportError ("IOObjectRelease error with parent2."); if (kIOReturnSuccess != IOObjectRelease (parent1)) HIDReportError ("IOObjectRelease error with parent1."); }}static Boolean hid_MatchElementTypeMask (IOHIDElementType type, HIDElementTypeMask typeMask){ if (typeMask & kHIDElementTypeInput) if ((type == kIOHIDElementTypeInput_Misc) || (type == kIOHIDElementTypeInput_Button) || (type == kIOHIDElementTypeInput_Axis) || (type == kIOHIDElementTypeInput_ScanCodes)) return true; if (typeMask & kHIDElementTypeOutput) if (type == kIOHIDElementTypeOutput) return true; if (typeMask & kHIDElementTypeFeature) if (type == kIOHIDElementTypeFeature) return true; if (typeMask & kHIDElementTypeCollection) if (type == kIOHIDElementTypeCollection) return true; return false;}static pRecElement hid_GetDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask){ // we are asking for this element if (NULL != pElement) { if (hid_MatchElementTypeMask (pElement->type, typeMask)) // if the type match what we are looking for return pElement; // return the element else return HIDGetNextDeviceElement (pElement, typeMask); // else get the next one
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -