Sample Code
OSX Driver and Kext Samples/ HID_Dumper/ HID_Dumper/ HID_Dumper/ HID Utilities/ HID_Name_Lookup.c/
// File: HID_Name_Lookup.c // Abstract: HID Name Lookup Utilities. // Version: 2.0 // // Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple // Inc. ("Apple") in consideration of your agreement to the following // terms, and your use, installation, modification or redistribution of // this Apple software constitutes acceptance of these terms. If you do // not agree with these terms, please do not use, install, modify or // redistribute this Apple software. // // In consideration of your agreement to abide by the following terms, and // subject to these terms, Apple grants you a personal, non-exclusive // license, under Apple's copyrights in this original Apple software (the // "Apple Software"), to use, reproduce, modify and redistribute the Apple // Software, with or without modifications, in source and/or binary forms; // provided that if you redistribute the Apple Software in its entirety and // without modifications, you must retain this notice and the following // text and disclaimers in all such redistributions of the Apple Software. // Neither the name, trademarks, service marks or logos of Apple Inc. may // be used to endorse or promote products derived from the Apple Software // without specific prior written permission from Apple. Except as // expressly stated in this notice, no other rights or licenses, express or // implied, are granted by Apple herein, including but not limited to any // patent rights that may be infringed by your derivative works or by other // works in which the Apple Software may be incorporated. // // The Apple Software is provided by Apple on an "AS IS" basis. APPLE // MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION // THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND // OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. // // IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, // MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED // AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), // STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // Copyright (C) 2013 Apple Inc. All Rights Reserved. // // ***************************************************** #pragma mark - includes & imports // ***************************************************** #include "HID_Utilities_External.h" // ***************************************************** #pragma mark - typedefs, enums, defines, etc. // ***************************************************** #define FAKE_MISSING_NAMES 0 // for debugging; returns the vendor, product & cookie (or usage info) as numbers. #define VERBOSE_ELEMENT_NAMES 0 // set true to include vender & product names in element names (useful for debugging) #define kNameKeyCFStringRef CFSTR("Name") // ***************************************************** #pragma mark - local (static) function prototypes // ***************************************************** #if false // currently unused static SInt32 hu_SaveToXMLFile(CFPropertyListRef inCFPRef, CFURLRef inCFURLRef); static SInt32 hu_XMLSave(CFPropertyListRef inCFPropertyListRef, CFStringRef inResourceName, CFStringRef inResourceExtension); #endif // if 0 static CFPropertyListRef hu_LoadFromXMLFile(CFURLRef inCFURLRef); static CFPropertyListRef hu_XMLLoad(CFStringRef inResourceName, CFStringRef inResourceExtension); static Boolean hu_XMLSearchForElementNameByCookie(long inVendorID, long inProductID, IOHIDElementCookie inCookie, char * outCStr); static Boolean hu_XMLSearchForElementNameByUsage(long inVendorID, long inProductID, long inUsagePage, long inUsage, char * outCStr); static Boolean hu_XMLSearchForVendorNameByVendorID(long inVendorID, char * outCStr); static Boolean hu_XMLSearchForProductNameByVendorProductID(long inVendorID, long inProductID, char * outCStr); #if false // currently unused static Boolean hu_AddVendorProductToCFDict(CFMutableDictionaryRef inCFMutableDictionaryRef, long inVendorID, CFStringRef inVendorCFStringRef, long inProductID, CFStringRef inProductCFStringRef); static Boolean hu_AddDeviceElementToUsageXML(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef); #endif // if 0 // ***************************************************** #pragma mark - exported globals // ***************************************************** #pragma mark - local (static) globals // ***************************************************** static CFPropertyListRef gCookieCFPropertyListRef = NULL; static CFPropertyListRef gUsageCFPropertyListRef = NULL; // ***************************************************** #pragma mark - exported function implementations // ***************************************************** /************************************************************************* * * HIDGetVendorNameFromVendorID(inVendorID, inProductID, inCookie, outCStrName) * * Purpose: Uses an devices vendor ID to generate a name for it. * * Notes: Now uses XML files to store dictionary of names * * Inputs: inVendorID - the elements vendor ID * outCStrName - address where result will be returned * Returns: Boolean - if successful */ Boolean HIDGetVendorNameFromVendorID(long inVendorID, char * outCStrName) { Boolean result = false; *outCStrName = 0; // clear name if ( hu_XMLSearchForVendorNameByVendorID(inVendorID, outCStrName) ) { return (true); } #if FAKE_MISSING_NAMES sprintf(outCStrName, "#{ V: %ld}#", inVendorID); result = true; #endif // FAKE_MISSING_NAMES return (result); } // HIDGetVendorNameFromVendorID /************************************************************************* * * HIDGetProductNameFromVendorProductID(inVendorID, inProductID, outCStrName) * * Purpose: Uses an elements vendor, product & usage info to generate a name for it. * * Notes: Now uses XML files to store dictionary of names * * Inputs: inVendorID - the elements vendor ID * inProductID - the elements product ID * inUsagePage - the elements usage page * inUsage - the elements usage * outCStrName - address where result will be returned * Returns: Boolean - if successful */ Boolean HIDGetProductNameFromVendorProductID(long inVendorID, long inProductID, char * outCStrName) { Boolean result = false; *outCStrName = 0; // clear name if ( hu_XMLSearchForProductNameByVendorProductID(inVendorID, inProductID, outCStrName) ) { return (true); } #if FAKE_MISSING_NAMES sprintf(outCStrName, "#{ V: %ld, P: %ld, U: %ld: %ld}#", inVendorID, inProductID, inUsagePage, inUsage); result = true; #endif // FAKE_MISSING_NAMES return (result); } // HIDGetProductNameFromVendorProductID /************************************************************************* * * HIDGetElementNameFromVendorProductCookie(inVendorID, inProductID, inCookie, outCStrName) * * Purpose: Uses an elements vendor, product & cookie to generate a name for it. * * Notes: Now uses XML files to store dictionary of names * * Inputs: inVendorID - the elements vendor ID * inProductID - the elements product ID * inCookie - the elements cookie * outCStrName - address where result will be returned * Returns: Boolean - if successful */ Boolean HIDGetElementNameFromVendorProductCookie(int inVendorID, int inProductID, IOHIDElementCookie inCookie, char * outCStrName) { Boolean result = false; *outCStrName = 0; // clear name // Look in the XML file first if ( hu_XMLSearchForElementNameByCookie(inVendorID, inProductID, inCookie, outCStrName) ) { return (true); } #if FAKE_MISSING_NAMES sprintf(outCStrName, "#{ V: %ld, P: %ld, C: %ld}#", inVendorID, inProductID, inCookie); #else // if FAKE_MISSING_NAMES result = false; #endif // FAKE_MISSING_NAMES return (result); } // HIDGetElementNameFromVendorProductCookie /************************************************************************* * * HIDGetElementNameFromVendorProductUsage(inVendorID, inProductID, inUsagePage, inUsage, outCStrName) * * Purpose: Uses an elements vendor, product & usage info to generate a name for it. * * Notes: Now uses XML files to store dictionary of names * * Inputs: inVendorID - the elements vendor ID * inProductID - the elements product ID * inUsagePage - the elements usage page * inUsage - the elements usage * outCStrName - address where result will be returned * Returns: Boolean - if successful */ Boolean HIDGetElementNameFromVendorProductUsage(long inVendorID, long inProductID, long inUsagePage, long inUsage, char * outCStrName) { Boolean result = false; *outCStrName = 0; // clear name if ( hu_XMLSearchForElementNameByUsage(inVendorID, inProductID, inUsagePage, inUsage, outCStrName) ) { return (true); } #if FAKE_MISSING_NAMES sprintf(outCStrName, "#{ V: %ld, P: %ld, U: %ld: %ld}#", inVendorID, inProductID, inUsagePage, inUsage); result = true; #endif // FAKE_MISSING_NAMES return (result); } // HIDGetElementNameFromVendorProductUsage #if false // currently unused /************************************************************************* * * HIDAddDeviceToXML(inDevice) * * Purpose: Adds a devices info to the HID_device_usage_strings.plist(XML) file * * Inputs: inDevice - the device * Returns: Boolean - if successful */ static Boolean HIDAddDeviceToXML(IOHIDDeviceRef inIOHIDDeviceRef) { Boolean result = false; if ( HIDIsValidDevice(inIOHIDDeviceRef) ) { CFStringRef vendorCFStringRef = IOHIDDevice_GetManufacturer(inIOHIDDeviceRef); CFStringRef productCFStringRef = IOHIDDevice_GetProduct(inIOHIDDeviceRef); if (vendorCFStringRef && productCFStringRef) { #if false // don't update the cookie xml file gCookieCFPropertyListRef = hu_XMLLoad(CFSTR("HID_cookie_strings"), CFSTR("plist") ); if (gCookieCFPropertyListRef) { CFMutableDictionaryRef tCFMutableDictionaryRef = CFDictionaryCreateMutableCopy( kCFAllocatorDefault, 0, gCookieCFPropertyListRef); if (tCFMutableDictionaryRef) { if ( hu_AddVendorProductToCFDict(tCFMutableDictionaryRef, vendorID, vendorCFStringRef, productID, productCFStringRef) ) { hu_XMLSave( tCFMutableDictionaryRef, CFSTR("HID_cookie_strings"), CFSTR("plist") ); result = true; } CFRelease(tCFMutableDictionaryRef); } } #endif // if 0 if (gUsageCFPropertyListRef) { CFRelease(gUsageCFPropertyListRef); } gUsageCFPropertyListRef = hu_XMLLoad(CFSTR("HID_device_usage_strings"), CFSTR("plist") ); if (gUsageCFPropertyListRef) { CFMutableDictionaryRef tCFMutableDictionaryRef = CFDictionaryCreateMutableCopy( kCFAllocatorDefault, 0, gUsageCFPropertyListRef); if (tCFMutableDictionaryRef) { long vendorID = IOHIDDevice_GetVendorID(inIOHIDDeviceRef); long productID = IOHIDDevice_GetProductID(inIOHIDDeviceRef); if ( hu_AddVendorProductToCFDict(tCFMutableDictionaryRef, vendorID, vendorCFStringRef, productID, productCFStringRef) ) { hu_XMLSave( tCFMutableDictionaryRef,CFSTR("HID_device_usage_strings"), CFSTR("plist") ); result = true; } CFRelease(tCFMutableDictionaryRef); } } } } return (result); } // HIDAddDeviceToXML /************************************************************************* * * HIDAddDeviceElementToXML(inDevice, inElement) * * Purpose: Adds a devices info to the HID_device_usage_strings.plist(XML) file * * Inputs: inDevice - the device * inElement - the element * * Returns: Boolean - if successful */ Boolean HIDAddDeviceElementToXML(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef) { Boolean result = false; if ( HIDIsValidElement(inIOHIDElementRef) ) { if ( HIDAddDeviceToXML(inIOHIDDeviceRef) ) { result = true; } if ( hu_AddDeviceElementToUsageXML(inIOHIDDeviceRef, inIOHIDElementRef) ) { result = true; } } return (result); } // HIDAddDeviceElementToXML #endif // if 0 /************************************************************************* * * HIDGetTypeName(inIOHIDElementType, outCStrName) * * Purpose: return a C string for a given element type(see IOHIDKeys.h) * Notes: returns "Unknown Type" for invalid types * * Inputs: inIOHIDElementType - type element type * outCStrName - address where to store element type string * * Returns: outCStrName - the element type string */ void HIDGetTypeName(IOHIDElementType inIOHIDElementType, char * outCStrName) { switch (inIOHIDElementType) { case kIOHIDElementTypeInput_Misc: { sprintf(outCStrName, "Miscellaneous Input"); break; } case kIOHIDElementTypeInput_Button: { sprintf(outCStrName, "Button Input"); break; } case kIOHIDElementTypeInput_Axis: { sprintf(outCStrName, "Axis Input"); break; } case kIOHIDElementTypeInput_ScanCodes: { sprintf(outCStrName, "Scan Code Input"); break; } case kIOHIDElementTypeOutput: { sprintf(outCStrName, "Output"); break; } case kIOHIDElementTypeFeature: { sprintf(outCStrName, "Feature"); break; } case kIOHIDElementTypeCollection: { sprintf(outCStrName, "Collection"); break; } default: { sprintf(outCStrName, "Unknown Type"); break; } } // switch } // HIDGetTypeName // ************************************************************************* // // HIDCopyUsagePageName(inUsagePage) // // Purpose: return a CFStringRef string for a given usage page (see IOUSBHIDParser.h) // // Notes: returns usage page in CFString form for unknown values // // Inputs: inUsagePage - the usage page // // Returns: CFStringRef - the resultant string // CFStringRef HIDCopyUsagePageName(long inUsagePage) { static CFPropertyListRef tCFPropertyListRef = NULL; CFStringRef result = NULL; if (!tCFPropertyListRef) { tCFPropertyListRef = hu_XMLLoad(CFSTR("HID_usage_strings"), CFSTR("plist") ); } if (tCFPropertyListRef) { if ( CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef) ) { CFStringRef pageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), inUsagePage); if (pageKeyCFStringRef) { CFDictionaryRef pageCFDictionaryRef; if ( CFDictionaryGetValueIfPresent(tCFPropertyListRef, pageKeyCFStringRef, (const void * *) &pageCFDictionaryRef) ) { CFStringRef pageCFStringRef; if ( CFDictionaryGetValueIfPresent(pageCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &pageCFStringRef) ) { result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), pageCFStringRef); } #if FAKE_MISSING_NAMES else { // no name data for this page key (so we use the key) result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("#%@"), pageKeyCFStringRef); } } else { // no name data for this page key (so we use the key) result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("#%@"), pageKeyCFStringRef); #endif // if FAKE_MISSING_NAMES } CFRelease(pageKeyCFStringRef); } } // CFRelease(tCFPropertyListRef); // Leak this! // tCFPropertyListRef = NULL; } return (result); } // HIDCopyUsagePageName // ************************************************************************* // // HIDCopyUsageName(inUsagePage, inUsage) // // Purpose: return a CFStringRef string for a given usage page & usage(see IOUSBHIDParser.h) // // Notes: returns usage page and usage values in CFString form for unknown values // // Inputs: inUsagePage - the usage page // inUsage - the usage // // Returns: CFStringRef - the resultant string // CFStringRef HIDCopyUsageName(long inUsagePage, long inUsage) { static CFPropertyListRef tCFPropertyListRef = NULL; CFStringRef result = NULL; if (!tCFPropertyListRef) { tCFPropertyListRef = hu_XMLLoad(CFSTR("HID_usage_strings"), CFSTR("plist") ); } if (tCFPropertyListRef) { if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef) ) { CFStringRef pageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), inUsagePage); if (pageKeyCFStringRef) { CFDictionaryRef pageCFDictionaryRef; if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, pageKeyCFStringRef, (const void * *) &pageCFDictionaryRef) ) { CFStringRef pageCFStringRef; if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &pageCFStringRef) ) { CFStringRef usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), inUsage); if (usageKeyCFStringRef) { CFStringRef usageCFStringRef; if ( CFDictionaryGetValueIfPresent(pageCFDictionaryRef, usageKeyCFStringRef, (const void * *) &usageCFStringRef) ) { result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@"), pageCFStringRef, usageCFStringRef); } #if FAKE_MISSING_NAMES else { result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ #%@"), pageCFStringRef, usageKeyCFStringRef); } #endif // if FAKE_MISSING_NAMES CFRelease(usageKeyCFStringRef); } } else { // no name data for this page } } else { // no data for this page } CFRelease(pageKeyCFStringRef); } } // CFRelease(tCFPropertyListRef); // Leak this! // tCFPropertyListRef = NULL; } return (result); } // HIDCopyUsageName // ***************************************************** #pragma mark - local (static) function implementations // ***************************************************** #if false // currently unused /************************************************************************* * * hu_SaveToXMLFile(inCFPRef, inCFURLRef) * * Purpose: save a property list into an XML file * * Inputs: inCFPRef - the data * inCFURLRef - URL for the file * * Returns: SInt32 - error code (if any) */ static SInt32 hu_SaveToXMLFile(CFPropertyListRef inCFPRef, CFURLRef inCFURLRef) { CFDataRef xmlCFDataRef; SInt32 error = coreFoundationUnknownErr; // Convert the property list into XML data. xmlCFDataRef = CFPropertyListCreateXMLData(kCFAllocatorDefault, inCFPRef); if (xmlCFDataRef) { // Write the XML data to the file. (void) CFURLWriteDataAndPropertiesToResource(inCFURLRef, xmlCFDataRef, NULL, &error); // Release the XML data CFRelease(xmlCFDataRef); } return (error); } // hu_SaveToXMLFile #endif // if 0 /************************************************************************* * * hu_LoadFromXMLFile(inCFURLRef) * * Purpose: load a property list from an XML file * * Inputs: inCFURLRef - URL for the file * * Returns: CFPropertyListRef - the data */ static CFPropertyListRef hu_LoadFromXMLFile(CFURLRef inCFURLRef) { CFDataRef xmlCFDataRef; CFPropertyListRef myCFPropertyListRef = NULL; // Read the XML file. SInt32 error; if ( CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, inCFURLRef, &xmlCFDataRef, NULL, NULL, &error) ) { CFStringRef errorString; // Reconstitute the dictionary using the XML data. myCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, xmlCFDataRef, kCFPropertyListImmutable, &errorString); // Release the XML data CFRelease(xmlCFDataRef); } return (myCFPropertyListRef); } // hu_LoadFromXMLFile #if false // currently unused /************************************************************************* * * hu_XMLSave(inCFPropertyListRef, inResourceName, inResourceExtension) * * Purpose: save a CFPropertyListRef into a resource(XML) file * * Inputs: inCFPropertyListRef - the data * inResourceName - name of the resource file * inResourceExtension - extension of the resource file * * Returns: SInt32 - error code (if any) */ static SInt32 hu_XMLSave(CFPropertyListRef inCFPropertyListRef, CFStringRef inResourceName, CFStringRef inResourceExtension) { CFURLRef resFileCFURLRef; SInt32 error = -1; // check the main (application) bundle resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), inResourceName, inResourceExtension, NULL); if (!resFileCFURLRef) { // check this specific (HID_Utilities framework) bundle CFBundleRef tCFBundleRef = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.HID_Utilities") ); if (tCFBundleRef) { resFileCFURLRef = CFBundleCopyResourceURL(tCFBundleRef, inResourceName, inResourceExtension, NULL); } } if (!resFileCFURLRef) { // check bundles already loaded or otherwise known to the current process CFArrayRef tCFArrayRef = CFBundleGetAllBundles(); CFIndex idx, cnt = CFArrayGetCount(tCFArrayRef); for (idx = 0; idx < cnt; idx++) { CFBundleRef tCFBundleRef = (CFBundleRef) CFArrayGetValueAtIndex(tCFArrayRef, idx); if (tCFBundleRef) { resFileCFURLRef = CFBundleCopyResourceURL(tCFBundleRef, inResourceName, inResourceExtension, NULL); if (resFileCFURLRef) { break; } } } } if (resFileCFURLRef) { error = hu_SaveToXMLFile(inCFPropertyListRef, resFileCFURLRef); CFRelease(resFileCFURLRef); } return (error); } // hu_XMLSave #endif // if 0 /************************************************************************* * * hu_XMLLoad(inResourceName, inResourceExtension) * * Purpose: Load a resource(XML) file into a CFPropertyListRef * * Inputs: inResourceName - name of the resource file * inResourceExtension - extension of the resource file * * Returns: CFPropertyListRef - the data */ static CFPropertyListRef hu_XMLLoad(CFStringRef inResourceName, CFStringRef inResourceExtension) { CFURLRef resFileCFURLRef; CFPropertyListRef tCFPropertyListRef = NULL; // check the main (application) bundle resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), inResourceName, inResourceExtension, NULL); if (!resFileCFURLRef) { // check this specific (HID_Utilities framework) bundle CFBundleRef tCFBundleRef = CFBundleGetBundleWithIdentifier( CFSTR("com.apple.HID_Utilities") ); if (tCFBundleRef) { resFileCFURLRef = CFBundleCopyResourceURL(tCFBundleRef, inResourceName, inResourceExtension, NULL); } } if (!resFileCFURLRef) { // check bundles already loaded or otherwise known to the current process CFArrayRef tCFArrayRef = CFBundleGetAllBundles(); CFIndex idx, cnt = CFArrayGetCount(tCFArrayRef); for (idx = 0; idx < cnt; idx++) { CFBundleRef tCFBundleRef = (CFBundleRef) CFArrayGetValueAtIndex(tCFArrayRef, idx); if (tCFBundleRef) { resFileCFURLRef = CFBundleCopyResourceURL(tCFBundleRef, inResourceName, inResourceExtension, NULL); if (resFileCFURLRef) { break; } } } } if (resFileCFURLRef) { tCFPropertyListRef = hu_LoadFromXMLFile(resFileCFURLRef); CFRelease(resFileCFURLRef); } return (tCFPropertyListRef); } // hu_XMLLoad /************************************************************************* * * hu_XMLSearchForVendorNameByVendorID(inVendorID, outCStr) * * Purpose: Find a vendor string in the <HID_device_usage_strings.plist> resource (XML) file * * Inputs: inVendorID - the elements vendor ID * inProductID - the elements product ID * outCStr - address where result will be returned * * Returns: Boolean - if successful */ static Boolean hu_XMLSearchForVendorNameByVendorID(long inVendorID, char * outCStr) { Boolean results = false; if (!gUsageCFPropertyListRef) { gUsageCFPropertyListRef = hu_XMLLoad(CFSTR("HID_device_usage_strings"), CFSTR("plist") ); } if (gUsageCFPropertyListRef) { if ( CFDictionaryGetTypeID() == CFGetTypeID(gUsageCFPropertyListRef) ) { CFDictionaryRef vendorCFDictionaryRef; CFStringRef vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inVendorID); if (vendorKeyCFStringRef) { if ( CFDictionaryGetValueIfPresent(gUsageCFPropertyListRef, vendorKeyCFStringRef, (const void * *) &vendorCFDictionaryRef) ) { CFStringRef vendorCFStringRef = NULL; if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &vendorCFStringRef) && vendorCFStringRef) { // CFShow(vendorCFStringRef); results = CFStringGetCString(vendorCFStringRef, outCStr, CFStringGetLength( vendorCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingUTF8); } } CFRelease(vendorKeyCFStringRef); } } // ++ CFRelease(gUsageCFPropertyListRef); // Leak this ! } return (results); } // hu_XMLSearchForVendorNameByVendorID /************************************************************************* * * hu_XMLSearchForProductNameByVendorProductID(inVendorID, inProductID, outCStr) * * Purpose: Find an product string in the <HID_device_usage_strings.plist> resource (XML) file * * Inputs: inVendorID - the elements vendor ID * inProductID - the elements product ID * outCStr - address where result will be returned * * Returns: Boolean - if successful */ static Boolean hu_XMLSearchForProductNameByVendorProductID(long inVendorID, long inProductID, char * outCStr) { Boolean results = false; if (!gUsageCFPropertyListRef) { gUsageCFPropertyListRef = hu_XMLLoad(CFSTR("HID_device_usage_strings"), CFSTR("plist") ); } if (gUsageCFPropertyListRef) { if ( CFDictionaryGetTypeID() == CFGetTypeID(gUsageCFPropertyListRef) ) { // first we make our vendor ID key CFStringRef vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inVendorID); if (vendorKeyCFStringRef) { // and use it to look up our vendor dictionary CFDictionaryRef vendorCFDictionaryRef; if ( CFDictionaryGetValueIfPresent(gUsageCFPropertyListRef, vendorKeyCFStringRef, (const void * *) &vendorCFDictionaryRef) ) { // pull our vendor name our of that dictionary CFStringRef vendorCFStringRef = NULL; if ( CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &vendorCFStringRef) ) { #if FAKE_MISSING_NAMES CFRetain(vendorCFStringRef); // so we can CFRelease it later } else { vendorCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("V: %@"), vendorKeyCFStringRef); #endif // if FAKE_MISSING_NAMES } // now we make our product ID key CFStringRef productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inProductID); if (productKeyCFStringRef) { // and use that key to look up our product dictionary in the vendor dictionary CFDictionaryRef productCFDictionaryRef; if ( CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void * *) &productCFDictionaryRef) ) { // pull our product name our of the product dictionary CFStringRef productCFStringRef = NULL; if ( CFDictionaryGetValueIfPresent(productCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &productCFStringRef) ) { #if FAKE_MISSING_NAMES CFRetain(productCFStringRef); // so we can CFRelease it later } else { productCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("P: %@"), kNameKeyCFStringRef); #endif // if FAKE_MISSING_NAMES } CFStringRef fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@"), vendorCFStringRef, productCFStringRef); if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString(fullCFStringRef, outCStr, CFStringGetLength( fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingUTF8); CFRelease(fullCFStringRef); } #if FAKE_MISSING_NAMES if (productCFStringRef) { CFRelease(productCFStringRef); } #endif // if FAKE_MISSING_NAMES } CFRelease(productKeyCFStringRef); } #if FAKE_MISSING_NAMES if (vendorCFStringRef) { CFRelease(vendorCFStringRef); } #endif // if FAKE_MISSING_NAMES } CFRelease(vendorKeyCFStringRef); } } // ++ CFRelease(gUsageCFPropertyListRef); // Leak this ! } return (results); } // hu_XMLSearchForProductNameByVendorProductID /************************************************************************* * * hu_XMLSearchForElementNameByCookie(inVendorID, inProductID, inCookie, outCStr) * * Purpose: Find an element string in the <HID_cookie_strings.plist> resource(XML) file * * Inputs: inVendorID - the elements vendor ID * inProductID - the elements product ID * inCookie - the elements cookie * outCStr - address where result will be returned * * Returns: Boolean - if successful */ static Boolean hu_XMLSearchForElementNameByCookie(long inVendorID, long inProductID, IOHIDElementCookie inCookie, char * outCStr) { Boolean results = false; if (!gCookieCFPropertyListRef) { gCookieCFPropertyListRef = hu_XMLLoad(CFSTR("HID_cookie_strings"), CFSTR("plist") ); } if (gCookieCFPropertyListRef) { if ( CFDictionaryGetTypeID() == CFGetTypeID(gCookieCFPropertyListRef) ) { CFStringRef vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inVendorID); if (vendorKeyCFStringRef) { CFDictionaryRef vendorCFDictionaryRef; if ( CFDictionaryGetValueIfPresent(gCookieCFPropertyListRef, vendorKeyCFStringRef, (const void * *) &vendorCFDictionaryRef) ) { CFDictionaryRef productCFDictionaryRef; CFStringRef productKeyCFStringRef; CFStringRef vendorCFStringRef; if ( CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &vendorCFStringRef) ) { // CFShow(vendorCFStringRef); } productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inProductID); if ( CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void * *) &productCFDictionaryRef) ) { CFStringRef fullCFStringRef = NULL; CFStringRef cookieKeyCFStringRef; CFStringRef productCFStringRef; CFStringRef cookieCFStringRef; if ( CFDictionaryGetValueIfPresent(productCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &productCFStringRef) ) { // CFShow(productCFStringRef); } cookieKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), (uint32_t) inCookie); if ( CFDictionaryGetValueIfPresent(productCFDictionaryRef, cookieKeyCFStringRef, (const void * *) &cookieCFStringRef) ) { #if VERBOSE_ELEMENT_NAMES fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), vendorCFStringRef, productCFStringRef, cookieCFStringRef); #else // if VERBOSE_ELEMENT_NAMES fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), cookieCFStringRef); #endif // VERBOSE_ELEMENT_NAMES // CFShow(cookieCFStringRef); } #if FAKE_MISSING_NAMES else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ # %@"), vendorCFStringRef, productCFStringRef, cookieKeyCFStringRef); } #endif // FAKE_MISSING_NAMES if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString(fullCFStringRef, outCStr, CFStringGetLength( fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingUTF8); CFRelease(fullCFStringRef); } CFRelease(cookieKeyCFStringRef); } CFRelease(productKeyCFStringRef); } CFRelease(vendorKeyCFStringRef); } } // ++ CFRelease(gCookieCFPropertyListRef); // Leak this ! } return (results); } // hu_XMLSearchForElementNameByCookie /************************************************************************* * * hu_XMLSearchForElementNameByUsage(inVendorID, inProductID, inUsagePage, inUsage, outCStr) * * Purpose: Find an element string in the <HID_device_usage_strings.plist> resource(XML) file * * Inputs: inVendorID - the elements vendor ID * inProductID - the elements product ID * inUsagePage - the elements usage page * inUsage - the elements usage * outCStr - address where result will be returned * * Returns: Boolean - if successful */ static Boolean hu_XMLSearchForElementNameByUsage(long inVendorID, long inProductID, long inUsagePage, long inUsage, char * outCStr) { Boolean results = false; if (!gUsageCFPropertyListRef) { gUsageCFPropertyListRef = hu_XMLLoad(CFSTR("HID_device_usage_strings"), CFSTR("plist") ); } if (gUsageCFPropertyListRef) { if ( CFDictionaryGetTypeID() == CFGetTypeID(gUsageCFPropertyListRef) ) { CFStringRef vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inVendorID); if (vendorKeyCFStringRef) { CFDictionaryRef vendorCFDictionaryRef; if ( CFDictionaryGetValueIfPresent(gUsageCFPropertyListRef, vendorKeyCFStringRef, (const void * *) &vendorCFDictionaryRef) ) { CFStringRef vendorCFStringRef = NULL; if ( CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &vendorCFStringRef) ) { vendorCFStringRef = CFStringCreateCopy(kCFAllocatorDefault, vendorCFStringRef); } else { vendorCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("v: %ld"), inVendorID); // CFShow(vendorCFStringRef); } CFStringRef productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inProductID); CFDictionaryRef productCFDictionaryRef; if ( CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void * *) &productCFDictionaryRef) ) { CFStringRef fullCFStringRef = NULL; CFStringRef productCFStringRef; if ( CFDictionaryGetValueIfPresent(productCFDictionaryRef, kNameKeyCFStringRef, (const void * *) &productCFStringRef) ) { // CFShow(productCFStringRef); } CFStringRef usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld:%ld"), inUsagePage, inUsage); CFStringRef usageCFStringRef; if ( CFDictionaryGetValueIfPresent(productCFDictionaryRef, usageKeyCFStringRef, (const void * *) &usageCFStringRef) ) { #if VERBOSE_ELEMENT_NAMES fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"), vendorCFStringRef, productCFStringRef, usageCFStringRef); #else // if VERBOSE_ELEMENT_NAMES fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), usageCFStringRef); #endif // VERBOSE_ELEMENT_NAMES // CFShow(usageCFStringRef); } #if FAKE_MISSING_NAMES else { fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ # %@"), vendorCFStringRef, productCFStringRef, usageKeyCFStringRef); } #endif // FAKE_MISSING_NAMES if (fullCFStringRef) { // CFShow(fullCFStringRef); results = CFStringGetCString(fullCFStringRef, outCStr, CFStringGetLength( fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingUTF8); CFRelease(fullCFStringRef); } CFRelease(usageKeyCFStringRef); } if (vendorCFStringRef) { CFRelease(vendorCFStringRef); } CFRelease(productKeyCFStringRef); } CFRelease(vendorKeyCFStringRef); } } // ++ CFRelease(gUsageCFPropertyListRef); // Leak this ! } return (results); } // hu_XMLSearchForElementNameByUsage #if false // currently unused /************************************************************************* * * hu_AddVendorProductToCFDict(inCFMutableDictionaryRef, inVendorID, inVendorCFStringRef, inProductID, inProductCFStringRef) * * Purpose: add a vendor & product to a dictionary * * Inputs: inCFMutableDictionaryRef - the dictionary * inVendorID - the elements vendor ID * inProductID - the elements product ID * inProductCFStringRef - the string to be added * * Returns: Boolean - if successful */ static Boolean hu_AddVendorProductToCFDict(CFMutableDictionaryRef inCFMutableDictionaryRef, long inVendorID, CFStringRef inVendorCFStringRef, long inProductID, CFStringRef inProductCFStringRef) { Boolean results = false; if ( inCFMutableDictionaryRef && ( CFDictionaryGetTypeID() == CFGetTypeID(inCFMutableDictionaryRef) ) ) { CFMutableDictionaryRef vendorCFMutableDictionaryRef; CFStringRef vendorKeyCFStringRef; CFMutableDictionaryRef productCFMutableDictionaryRef; CFStringRef productKeyCFStringRef; // if the vendor dictionary doesn't exist vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inVendorID); if ( CFDictionaryGetValueIfPresent(inCFMutableDictionaryRef, vendorKeyCFStringRef, (const void * *) &vendorCFMutableDictionaryRef) ) { // copy it. vendorCFMutableDictionaryRef = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, vendorCFMutableDictionaryRef); } else { // ...otherwise... // create it. vendorCFMutableDictionaryRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); results = true; } // if the vendor name key doesn't exist if ( !CFDictionaryContainsKey(vendorCFMutableDictionaryRef, kNameKeyCFStringRef) ) { // create it. CFDictionaryAddValue(vendorCFMutableDictionaryRef, kNameKeyCFStringRef, inVendorCFStringRef); results = true; } // if the product key exists in the vendor dictionary productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), inProductID); if ( CFDictionaryGetValueIfPresent(vendorCFMutableDictionaryRef, productKeyCFStringRef, (const void * *) &productCFMutableDictionaryRef) ) { // copy it. productCFMutableDictionaryRef = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, productCFMutableDictionaryRef); } else { // ...otherwise... // create it. productCFMutableDictionaryRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); results = true; } // if the product name key doesn't exist if ( !CFDictionaryContainsKey(productCFMutableDictionaryRef, kNameKeyCFStringRef) ) { // create it. CFDictionaryAddValue(productCFMutableDictionaryRef, kNameKeyCFStringRef, inProductCFStringRef); results = true; } if (vendorCFMutableDictionaryRef) { if (productCFMutableDictionaryRef) { if (results) { CFDictionarySetValue(vendorCFMutableDictionaryRef, productKeyCFStringRef, productCFMutableDictionaryRef); } CFRelease(productCFMutableDictionaryRef); } if (results) { CFDictionarySetValue(inCFMutableDictionaryRef, vendorKeyCFStringRef, vendorCFMutableDictionaryRef); } CFRelease(vendorCFMutableDictionaryRef); } if (productKeyCFStringRef) { CFRelease(productKeyCFStringRef); } if (vendorKeyCFStringRef) { CFRelease(vendorKeyCFStringRef); } } return (results); } // hu_AddVendorProductToCFDict /************************************************************************* * * hu_AddDeviceElementToUsageXML(inDevice, inElement) * * Purpose: add a device and it's elements to our usage(XML) file * * Inputs: inDevice - the device * inElement - the element * * Returns: Boolean - if successful */ static Boolean hu_AddDeviceElementToUsageXML(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef) { Boolean results = false; if (gUsageCFPropertyListRef) { CFRelease(gUsageCFPropertyListRef); } gUsageCFPropertyListRef = hu_XMLLoad(CFSTR("HID_device_usage_strings"), CFSTR("plist") ); if (gUsageCFPropertyListRef) { CFMutableDictionaryRef tCFMutableDictionaryRef = CFDictionaryCreateMutableCopy( kCFAllocatorDefault, 0, gUsageCFPropertyListRef); if (tCFMutableDictionaryRef) { CFMutableDictionaryRef vendorCFMutableDictionaryRef; CFMutableDictionaryRef productCFMutableDictionaryRef; CFStringRef productKeyCFStringRef; CFStringRef usageKeyCFStringRef; // if the vendor dictionary exists... long vendorID = IOHIDDevice_GetVendorID(inIOHIDDeviceRef); CFStringRef vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), vendorID); if (vendorKeyCFStringRef) { if ( CFDictionaryGetValueIfPresent(tCFMutableDictionaryRef, vendorKeyCFStringRef, (const void * *) &vendorCFMutableDictionaryRef) ) { // ...copy it... vendorCFMutableDictionaryRef = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, vendorCFMutableDictionaryRef); } else { // ...otherwise... // ...create it. vendorCFMutableDictionaryRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); results = true; } // if the vendor name key doesn't exist... if ( !CFDictionaryContainsKey(vendorCFMutableDictionaryRef, kNameKeyCFStringRef) ) { CFStringRef manCFStringRef = IOHIDDevice_GetManufacturer(inIOHIDDeviceRef); // ...create it. CFDictionaryAddValue(vendorCFMutableDictionaryRef, kNameKeyCFStringRef, manCFStringRef); results = true; } // if the product key exists in the vendor dictionary... long productID = IOHIDDevice_GetProductID(inIOHIDDeviceRef); productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), productID); if ( CFDictionaryGetValueIfPresent(vendorCFMutableDictionaryRef, productKeyCFStringRef, (const void * *) &productCFMutableDictionaryRef) ) { // ...copy it... productCFMutableDictionaryRef = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, productCFMutableDictionaryRef); } else { // ...otherwise... // ...create it. productCFMutableDictionaryRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); results = true; } // if the product name key doesn't exist... if ( !CFDictionaryContainsKey(productCFMutableDictionaryRef, kNameKeyCFStringRef) ) { CFStringRef productCFStringRef = IOHIDDevice_GetProduct(inIOHIDDeviceRef); // ...create it. CFDictionaryAddValue(productCFMutableDictionaryRef, kNameKeyCFStringRef, productCFStringRef); results = true; } // if the usage key doesn't exist in the product dictionary... uint32_t usagePage = IOHIDElementGetUsagePage(inIOHIDElementRef); uint32_t usage = IOHIDElementGetUsagePage(inIOHIDElementRef); usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld:%ld"), usagePage, usage); if (usageKeyCFStringRef) { if ( !CFDictionaryContainsKey(productCFMutableDictionaryRef, usageKeyCFStringRef) ) { // find it's generic name CFStringRef usageCFStringRef = HIDCopyUsageName(usagePage, usage); if (usageCFStringRef) { // and add that. CFDictionaryAddValue(productCFMutableDictionaryRef, usageKeyCFStringRef, usageCFStringRef); results = true; CFRelease(usageCFStringRef); } } CFRelease(usageKeyCFStringRef); } if (vendorCFMutableDictionaryRef) { if (productCFMutableDictionaryRef) { if (results) { CFDictionarySetValue(vendorCFMutableDictionaryRef, productKeyCFStringRef, productCFMutableDictionaryRef); } CFRelease(productCFMutableDictionaryRef); } if (results) { CFDictionarySetValue(tCFMutableDictionaryRef, vendorKeyCFStringRef, vendorCFMutableDictionaryRef); } CFRelease(vendorCFMutableDictionaryRef); } CFRelease(vendorKeyCFStringRef); } if (productKeyCFStringRef) { CFRelease(productKeyCFStringRef); } if (results) { hu_XMLSave( tCFMutableDictionaryRef, CFSTR("HID_device_usage_strings"), CFSTR("plist") ); } CFRelease(tCFMutableDictionaryRef); } } return (results); } // hu_AddDeviceElementToUsageXML #endif // if 0
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials