aboutsummaryrefslogtreecommitdiff
path: root/HID_Utilities_Source
diff options
context:
space:
mode:
authorHans-Christoph Steiner <eighthave@users.sourceforge.net>2010-01-28 00:37:54 +0000
committerHans-Christoph Steiner <eighthave@users.sourceforge.net>2010-01-28 00:37:54 +0000
commit6b2aa4a4a7816d604ee63c974131c03fed9a4b7c (patch)
treef2e8041327aba32123e3c45acf746a523943d188 /HID_Utilities_Source
parentd97ac3564e559040da3b87635352da0cea75ab5e (diff)
first working version of hidio+HIDUtilities build on Mac OS X using autotools, still needs work
svn path=/trunk/externals/io/hidio/; revision=13107
Diffstat (limited to 'HID_Utilities_Source')
-rw-r--r--HID_Utilities_Source/HIDLib.h46
-rw-r--r--HID_Utilities_Source/HID_APIs.h150
-rw-r--r--HID_Utilities_Source/HID_CFM.c213
-rw-r--r--HID_Utilities_Source/HID_Config_Utilities.c425
-rw-r--r--HID_Utilities_Source/HID_Config_Utilities.h92
-rw-r--r--HID_Utilities_Source/HID_Error_Handler.c104
-rw-r--r--HID_Utilities_Source/HID_Error_Handler.h74
-rw-r--r--HID_Utilities_Source/HID_Name_Lookup.c347
-rw-r--r--HID_Utilities_Source/HID_Name_Lookup.h87
-rw-r--r--HID_Utilities_Source/HID_Queue_Utilities.c635
-rw-r--r--HID_Utilities_Source/HID_Queue_Utilities.h114
-rw-r--r--HID_Utilities_Source/HID_Transaction_Utilities.c316
-rw-r--r--HID_Utilities_Source/HID_Transaction_Utilities.h106
-rw-r--r--HID_Utilities_Source/HID_Utilities.c2198
-rw-r--r--HID_Utilities_Source/HID_Utilities.h256
-rw-r--r--HID_Utilities_Source/HID_Utilities_CFM.h74
-rw-r--r--HID_Utilities_Source/HID_Utilities_External.h509
-rw-r--r--HID_Utilities_Source/HID_Utilities_Internal.h54
-rw-r--r--HID_Utilities_Source/IOHIDPowerUsage.h280
-rw-r--r--HID_Utilities_Source/ImmrHIDUtilAddOn.c95
-rw-r--r--HID_Utilities_Source/ImmrHIDUtilAddOn.h13
-rw-r--r--HID_Utilities_Source/Makefile.am29
-rw-r--r--HID_Utilities_Source/PID.h1
23 files changed, 6218 insertions, 0 deletions
diff --git a/HID_Utilities_Source/HIDLib.h b/HID_Utilities_Source/HIDLib.h
new file mode 100644
index 0000000..6123009
--- /dev/null
+++ b/HID_Utilities_Source/HIDLib.h
@@ -0,0 +1,46 @@
+/*
+ File: HIDLib.h
+
+ Contains: Include file to define kBuildingLibrary constant (only include when building libraries)
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#define kBuildingLibrary 1 \ No newline at end of file
diff --git a/HID_Utilities_Source/HID_APIs.h b/HID_Utilities_Source/HID_APIs.h
new file mode 100644
index 0000000..d281340
--- /dev/null
+++ b/HID_Utilities_Source/HID_APIs.h
@@ -0,0 +1,150 @@
+
+/*
+ File: HID_APIs.h
+
+ Contains: Definition of the HID Utilities exported API's
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+// ----------------------------------------------------------------
+// The DO_API micro takes four parameters:
+// #define DO_API(r,n,p,a)
+// r - what the API Returns
+// n - the Name of the API
+// p - the Parameters to the API
+// a - the Arguments passed by the API
+//
+// DO_APIr is used when an API returns a value.
+// DO_API is used when an API doesn't return a value.
+//
+// For example:
+//
+// if you have a routine that doesn't return a value:
+//
+// void MyFunction(const UInt32 pSelector, void* pPtr);
+//
+// It's macro would look like this:
+//
+// DO_API(
+// void, // this is what the function returns
+// MyFunction, // this is its Name
+// (const UInt32 pSelector, void* pPtr), // these are its parameters
+// (pSelector, pPtr)) // and these are just the arguments (no type info)
+//
+// If it returns a value like this
+//
+// OSStatus MyFunction2(const UInt32 pSelector, void* pPtr);
+//
+// It's macro would look like this:
+//
+// DO_APIr(
+// OSStatus, // this is what the function returns
+// MyFunction2, // this is its Name
+// (const UInt32 pSelector, void* pPtr), // these are its parameters
+// (pSelector, pPtr)) // and these are just the arguments (no type info)
+//
+
+#ifndef DO_API // if this isn't definedÉ
+ #define DO_API // É then don't do anything.
+#endif
+
+#ifndef DO_APIr // if this isn't definedÉ
+ #define DO_APIr DO_API // É then do the same as DO_API
+#endif
+
+DO_APIr(Boolean, HIDBuildDeviceList, (UInt32 usagePage, UInt32 usage), (usagePage, usage))
+DO_APIr(Boolean, HIDFindActionDeviceAndElement, (const pRecDevice pSearchDevice, const pRecElement pSearchElement,pRecDevice *ppFoundDevice, pRecElement *ppFoundElement), (pSearchDevice, pSearchElement,ppFoundDevice, ppFoundElement))
+DO_APIr(Boolean, HIDFindDevice, (const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice), (pSearchDevice, ppFoundDevice))
+DO_APIr(Boolean, HIDFindSubElement, (const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement), (pStartElement, pSearchElement, ppFoundElement))
+DO_APIr(Boolean, HIDGetElementNameFromVendorProductCookie, (const long vendorID, const long productID, const long cookie, char * pName), (vendorID, productID, cookie, pName))
+DO_APIr(Boolean, HIDGetElementNameFromVendorProductUsage, (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName), (vendorID, productID, pUsagePage, pUsage, pName))
+DO_APIr(Boolean, HIDHaveDeviceList, (void), ())
+DO_APIr(Boolean, HIDIsValidDevice, (const pRecDevice pSearchDevice), (pSearchDevice))
+DO_APIr(Boolean, HIDIsValidElement, (const pRecDevice pSearchDevice, const pRecElement pSearchElement), (pSearchDevice, pSearchElement))
+DO_APIr(Boolean, HIDRestoreElementPref, (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement), (keyCFStringRef, appCFStringRef, ppDevice, ppElement))
+DO_APIr(Boolean, HIDSaveElementPref, (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement), (keyCFStringRef, appCFStringRef, pDevice, pElement))
+DO_APIr(Boolean, HIDTransactionHasElement, (pRecDevice pDevice, pRecElement pElement), (pDevice, pElement))
+DO_APIr(HIDElementTypeMask, HIDConvertElementTypeToMask, (const long type), (type))
+DO_APIr(int, HIDPrintElement, (const pRecElement pElement), (pElement))
+DO_APIr(long, HIDGetElementValue, (pRecDevice pDevice, pRecElement pElement), (pDevice, pElement))
+//DO_APIr(long, HIDGetReport, (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, unsigned long* reportBufferSize), (pDevice,reportType, reportID, reportBuffer, reportBufferSize))
+DO_APIr(long, HIDRestoreElementConfig, (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement), (fileRef, ppDevice, ppElement))
+DO_APIr(long, HIDSetElementValue, (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent), (pDevice, pElement,pIOHIDEvent))
+DO_APIr(long, HIDSetQueueCallback, (pRecDevice pDevice, IOHIDCallbackFunction callback,void* callbackTarget, void* callbackRefcon), (pDevice, callback,callbackTarget, callbackRefcon))
+//DO_APIr(long, HIDSetReport, (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, const unsigned long reportBufferSize),(pDevice,reportType, reportID, reportBuffer, reportBufferSize))
+DO_APIr(pRecDevice, HIDGetFirstDevice, (void), ())
+DO_APIr(pRecDevice, HIDGetNextDevice, (pRecDevice pDevice), (pDevice))
+DO_APIr(pRecElement, HIDGetFirstDeviceElement, (pRecDevice pDevice, HIDElementTypeMask typeMask), (pDevice, typeMask))
+DO_APIr(pRecElement, HIDGetNextDeviceElement, (pRecElement pElement, HIDElementTypeMask typeMask), (pElement, typeMask))
+DO_APIr(pRecElement, HIDGetPreviousDeviceElement, (pRecElement pElement, HIDElementTypeMask typeMask), (pElement, typeMask))
+DO_APIr(SInt32, HIDCalibrateValue, (SInt32 value, pRecElement pElement), (value, pElement))
+DO_APIr(SInt32, HIDScaleValue, (SInt32 value, pRecElement pElement), (value, pElement))
+DO_APIr(UInt32, HIDCountDeviceElements, (pRecDevice pDevice, HIDElementTypeMask typeMask), (pDevice, typeMask))
+DO_APIr(UInt32, HIDCountDevices, (void), ())
+DO_APIr(unsigned char, HIDConfigureAction, (pRecDevice * ppDevice, pRecElement * ppElement, float timeout), (ppDevice, ppElement, timeout))
+DO_APIr(unsigned char, HIDGetEvent, (pRecDevice pDevice, void * pHIDEvent), (pDevice, pHIDEvent))
+DO_APIr(unsigned long, HIDQueueElement, (pRecDevice pDevice, pRecElement pElement), (pDevice, pElement))
+DO_APIr(unsigned long, HIDCloseReleaseInterface, (pRecDevice pDevice), (pDevice))
+DO_APIr(unsigned long, HIDCreateOpenDeviceInterface, (UInt32 hidDevice, pRecDevice pDevice), (hidDevice, pDevice))
+DO_APIr(unsigned long, HIDDequeueDevice, (pRecDevice pDevice), (pDevice))
+DO_APIr(unsigned long, HIDDequeueElement, (pRecDevice pDevice, pRecElement pElement), (pDevice, pElement))
+DO_APIr(unsigned long, HIDQueueDevice, (pRecDevice pDevice), (pDevice))
+DO_APIr(unsigned long, HIDReleaseAllDeviceQueues, (void), ())
+
+DO_APIr(unsigned long, HIDTransactionAddElement, (pRecDevice pDevice, pRecElement pElement), (pDevice, pElement))
+DO_APIr(unsigned long, HIDTransactionClear, (pRecDevice pDevice), (pDevice))
+DO_APIr(unsigned long, HIDTransactionCommit, (pRecDevice pDevice), (pDevice))
+DO_APIr(unsigned long, HIDTransactionGetElementDefault, (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent), (pDevice, pElement,pValueEvent))
+DO_APIr(unsigned long, HIDTransactionGetElementValue, (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent), (pDevice, pElement,pValueEvent))
+DO_APIr(unsigned long, HIDTransactionRemoveElement, (pRecDevice pDevice, pRecElement pElement), (pDevice, pElement))
+DO_APIr(unsigned long, HIDTransactionSetElementDefault, (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent), (pDevice, pElement,pValueEvent))
+DO_APIr(unsigned long, HIDTransactionSetElementValue, (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent), (pDevice, pElement,pValueEvent))
+
+DO_API(void, HIDGetTypeName, (IOHIDElementType theType, char * cstrName), (theType, cstrName))
+DO_API(void, HIDGetUsageName, (long valueUsagePage, long valueUsage, char * cstrName), (valueUsagePage, valueUsage, cstrName))
+DO_API(void, HIDReleaseDeviceList, (void), ())
+DO_API(void, HIDSaveElementConfig, (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie), (fileRef, pDevice, pElement, actionCookie))
+
+DO_APIr(io_object_t, AllocateHIDObjectFromRecDevice,(pRecDevice pDevice),(pDevice))
+DO_APIr(Boolean, FreeHIDObject,(io_object_t hidDevice), (hidDevice))
+
+#undef DO_API
+#undef DO_APIr
+
diff --git a/HID_Utilities_Source/HID_CFM.c b/HID_Utilities_Source/HID_CFM.c
new file mode 100644
index 0000000..ab00e0b
--- /dev/null
+++ b/HID_Utilities_Source/HID_CFM.c
@@ -0,0 +1,213 @@
+/*
+ File: HID_CFM.c
+
+ Contains: Implementation of the CFM interfaces to the HID Utilities bundle
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+ *
+ */
+
+// Note: All the HID API's are defined externally in the file "HID_APIs.h".
+// How they are used in this file is defined via one or two macros:
+//
+// The DO_API micro takes four parameters:
+// #define DO_API(r,n,p,a)
+// r - what the API Returns
+// n - the Name of the API
+// p - the Parameters to the API
+// a - the Arguments passed by the API
+//
+// DO_APIr is used when an API returns a value.
+// DO_API is used when an API doesn't return a value.
+//
+// For example:
+//
+// if you have a routine that doesn't return a value:
+//
+// void MyFunction(const UInt32 pSelector, void* pPtr);
+//
+// It's macro would look like this:
+//
+// DO_API(
+// void, // this is what the function returns
+// MyFunction, // this is its Name
+// (const UInt32 pSelector, void* pPtr), // these are its parameters
+// (pSelector, pPtr)) // and these are just the arguments (no type info)
+//
+// If it returns a value like this
+//
+// OSStatus MyFunction2(const UInt32 pSelector, void* pPtr);
+//
+// It's macro would look like this:
+//
+// DO_APIr(
+// OSStatus, // this is what the function returns
+// MyFunction2, // this is its Name
+// (const UInt32 pSelector, void* pPtr), // these are its parameters
+// (pSelector, pPtr)) // and these are just the arguments (no type info)
+//
+// ==================================
+// includes
+// ==================================
+#include "HID_Utilities_CFM.h"
+
+typedef OSStatus HRESULT;
+typedef UInt32 IOByteCount;
+typedef unsigned int io_service_t;
+typedef unsigned int io_object_t;
+#define S_OK ((HRESULT)0x00000000L)
+
+// ==================================
+// define a ProcPtr type for each API
+#define DO_API(r,n,p,a) typedef r (*fp##n##Type)##p;
+#include "HID_APIs.h"
+
+// ==================================
+// declare storage for each API's function pointers
+#define DO_API(r,n,p,a) static fp##n##Type fp##n = NULL;
+#include "HID_APIs.h"
+
+// ==================================
+// globals
+// ==================================
+CFURLRef gBundleURL = NULL;
+CFBundleRef gBundle = NULL;
+
+// ==================================
+// setup the CFM to MachO (HID) connection
+// ==================================
+OSStatus SetupHIDCFM (void)
+{
+ Boolean didLoad = false; // Flag that indicates the status returned when attempting to load a bundle's executable code.
+ CFBundleRef refMainBundle = NULL;
+ CFURLRef refMainBundleURL = NULL, refPathBundleURL = NULL;
+
+ // See the Core Foundation URL Services chapter for details.
+ // get app bundle (even for a CFM app!)
+ refMainBundle = CFBundleGetMainBundle();
+ if (!refMainBundle)
+ {
+ DebugStr ("\pCould open main bundle");
+ return paramErr;
+ }
+
+ // create a URL to the app bundle
+ refMainBundleURL = CFBundleCopyBundleURL (refMainBundle);
+ if (!refMainBundleURL)
+ {
+ DebugStr ("\pCould not copy main bundle URL");
+ return paramErr;
+ }
+#if 0 // This should only be true if the app is bundled
+ // create a URL that points to the app's directory
+ refPathBundleURL = CFURLCreateCopyDeletingLastPathComponent (kCFAllocatorDefault, refMainBundleURL);
+ if (!refPathBundleURL)
+ {
+ DebugStr ("\pCould not create new parent URL deleting last path component");
+ if (refMainBundleURL != NULL)
+ CFRelease (refMainBundleURL);
+ return paramErr;
+ }
+#else
+ refPathBundleURL = refMainBundleURL;
+ refMainBundleURL = NULL;
+#endif
+
+ // create a URL to the HID library bundle
+ gBundleURL = CFURLCreateCopyAppendingPathComponent (kCFAllocatorDefault, refPathBundleURL, CFSTR("HID.bundle"), true);
+ // release created URLs
+ if (refMainBundleURL != NULL)
+ CFRelease (refMainBundleURL);
+ if (refPathBundleURL != NULL)
+ CFRelease (refPathBundleURL);
+ // did we actaully get a bundle URL
+ if (!gBundleURL)
+ {
+ DebugStr ("\pCould not create HID bundle URL");
+ return paramErr;
+ }
+ // get the actual bundle for the HID library
+ gBundle = CFBundleCreate (kCFAllocatorDefault, gBundleURL);
+ if (!gBundle)
+ {
+ DebugStr ("\pCould not create HID MachO library bundle");
+ CFShow(gBundleURL);
+ return paramErr;
+ }
+
+ if (!CFBundleLoadExecutable (gBundle)) // If the code was successfully loaded, look for our function.
+ {
+ DebugStr ("\pCould not load MachO executable");
+ return paramErr;
+ }
+
+ // Now that the code is loaded, search for the functions we want by name.
+ // for each API, look up it's function pointer and store it the local ProcPtr.
+
+#define DO_API(r,n,p,a) fp##n = (fp##n##Type) CFBundleGetFunctionPointerForName (gBundle, CFSTR(#n));;
+#include "HID_APIs.h"
+
+ return noErr;
+}
+// ==================================
+// tear down the CFM to MachO (HID) connection
+// ==================================
+void TearDownHIDCFM (void)
+{
+ // disassociate function pointers (assign null to each one)
+#define DO_API(r,n,p,a) fp##n = NULL;
+#include "HID_APIs.h"
+
+ if (gBundle != NULL)
+ {
+ CFBundleUnloadExecutable (gBundle); // Unload the bundle's executable code.
+ if (gBundleURL != NULL)
+ CFRelease (gBundleURL);
+ CFRelease (gBundle);
+ }
+}
+
+// Now for each API declare a (CFM) routine that calls thru the local ProcPtr to the MachO glue.
+// Note: we use two different macros here: with & without a return value.
+
+#define DO_API(r,n,p,a) void n##p { (*fp##n)##a;}
+#define DO_APIr(r,n,p,a) r n##p { return (r) (*fp##n)##a;}
+#include "HID_APIs.h"
+// ==================================
diff --git a/HID_Utilities_Source/HID_Config_Utilities.c b/HID_Utilities_Source/HID_Config_Utilities.c
new file mode 100644
index 0000000..a8e97b2
--- /dev/null
+++ b/HID_Utilities_Source/HID_Config_Utilities.c
@@ -0,0 +1,425 @@
+/*
+ File: HID_Config_Utilities.c
+
+ Contains: Implementation of the HID configuration utilities for the HID utilities.
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+
+*/
+
+#include <stdlib.h> // malloc
+#include <time.h> // clock
+
+#include <IOKit/hid/IOHIDUsageTables.h>
+
+#include "HID_Utilities_Internal.h"
+#include "HID_Utilities_External.h"
+
+// ---------------------------------
+// polls all devices and elements for a change greater than kPercentMove. Times out after given time
+// returns 1 and pointer to device and element if found
+// returns 0 and NULL for both parameters if not found
+
+unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout)
+{
+ long numDevices, maxElements = 0;
+ long * saveValueArray;
+ pRecDevice pDevice = NULL;
+ pRecElement pElement = NULL;
+ short deviceNum = 0;
+ unsigned char found = 0, done = 0;
+ clock_t start = clock (), end;
+
+ if (!HIDHaveDeviceList ()) // if we do not have a device list
+ if (0 == HIDBuildDeviceList (kHIDPage_GenericDesktop, 0)) // if we could not build another list (use generic page)
+ return 0; // return 0
+
+ // build list of device and elements to save current values
+ numDevices = HIDCountDevices ();
+ pDevice = HIDGetFirstDevice ();
+ while (pDevice)
+ {
+ long numElements = HIDCountDeviceElements (pDevice, kHIDElementTypeInput);
+ if (numElements > maxElements)
+ maxElements = numElements;
+ pDevice = HIDGetNextDevice (pDevice);
+ }
+ saveValueArray = (long *) malloc (sizeof (long) * numDevices * maxElements); // 2D array to save values
+ bzero(saveValueArray,sizeof (long) * numDevices * maxElements); // clear array
+
+ // store current values
+ deviceNum = 0;
+ pDevice = HIDGetFirstDevice ();
+ while (pDevice)
+ {
+ short elementNum = 0;
+ pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput);
+ while (pElement)
+ {
+ *(saveValueArray + (deviceNum * maxElements) + elementNum) = HIDGetElementValue (pDevice, pElement);
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput);
+ elementNum++;
+ }
+ pDevice = HIDGetNextDevice (pDevice);
+ deviceNum++;
+ }
+
+ // poll all devices and elements, compare current value to save +/- kPercentMove
+ while ((!found) && (!done))
+ {
+ double secs;
+ // are we done?
+ end = clock();
+ secs = (double)(end - start) / CLOCKS_PER_SEC;
+ if (secs > timeout)
+ done = 1;
+ deviceNum = 0;
+ pDevice = HIDGetFirstDevice ();
+ while (pDevice)
+ {
+ short elementNum = 0;
+ pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput);
+ while (pElement)
+ {
+ // ignore force feedback devices AND arrays
+ if ((kHIDPage_PID != pElement->usagePage) && (-1 != pElement->usage))
+ {
+ long initialValue = *(saveValueArray + (deviceNum * maxElements) + elementNum);
+ long value = HIDGetElementValue (pDevice, pElement);
+ long delta = (float)(pElement->max - pElement->min) * kPercentMove * 0.01;
+
+ if (((initialValue + delta) < value) || ((initialValue - delta) > value))
+ {
+ found = 1;
+ break;
+ }
+ }
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput);
+ elementNum++;
+ }
+ if (found)
+ break;
+ pDevice = HIDGetNextDevice (pDevice);
+ deviceNum++;
+ }
+ }
+
+ // return device and element moved
+ if (found)
+ {
+ *ppDevice = pDevice;
+ *ppElement = pElement;
+ return 1;
+ }
+ else
+ {
+ *ppDevice = NULL;
+ *ppElement = NULL;
+ return 0;
+ }
+}
+
+// ---------------------------------
+// takes input records, save required info
+// assume file is open and at correct position.
+// will always write to file (if file exists) size of recSaveHID, even if device and or element is bad
+
+void HIDSaveElementConfig (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie)
+{
+ recSaveHID saveRec;
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ // clear rec
+ bzero(&saveRec,sizeof(recSaveHID));
+
+ saveRec.actionCookie = actionCookie;
+
+ // must save
+ // actionCookie
+ // Device: serial,vendorID, productID, location, usagePage, usage
+ // Element: cookie, usagePage, usage,
+ // need to add serial number when I have a test case
+
+ saveRec.vendorID = pDevice->vendorID;
+ saveRec.productID = pDevice->productID;
+ saveRec.locID = pDevice->locID;
+ saveRec.usage = pDevice->usage;
+ saveRec.usagePage = pDevice->usagePage;
+
+ saveRec.usagePageE = pElement->usagePage;
+ saveRec.usageE = pElement->usage;
+ saveRec.cookie = pElement->cookie;
+
+ // write to file
+ if (fileRef)
+ fwrite ((void *)&saveRec, sizeof (recSaveHID), 1, fileRef);
+ }
+}
+
+// ---------------------------------
+// take file, read one record (assume file position is correct and file is open)
+// search for matching device
+// return pDevice, pElement and cookie for action
+
+long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement)
+{
+ // Device: serial,vendorID, productID, location, usagePage, usage
+ // Element: cookie, usagePage, usage,
+
+ pRecDevice pDevice, pFoundDevice = NULL;
+ pRecElement pElement, pFoundElement = NULL;
+
+ recSaveHID restoreRec;
+
+ fread ((void *) &restoreRec, 1, sizeof (recSaveHID), fileRef);
+
+ // compare to current device list for matches
+ // look for device
+ if (restoreRec.locID && restoreRec.vendorID && restoreRec.productID)
+ { // look for specific device type plug in to same port
+ pDevice = HIDGetFirstDevice ();
+ while (pDevice)
+ {
+ if ((restoreRec.locID == pDevice->locID) &&
+ (restoreRec.vendorID == pDevice->vendorID) &&
+ (restoreRec.productID == pDevice->productID))
+ pFoundDevice = pDevice;
+ if (pFoundDevice)
+ break;
+ pDevice = HIDGetNextDevice (pDevice);
+ }
+ if (pFoundDevice)
+ {
+ pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if (restoreRec.cookie == pElement->cookie)
+ pFoundElement = pElement;
+ if (pFoundElement)
+ break;
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ // if no cookie match (should NOT occur) match on usage
+ pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if ((restoreRec.usageE == pElement->usage) &&
+ (restoreRec.usagePageE == pElement->usagePage))
+ pFoundElement = pElement;
+ if (pFoundElement)
+ break;
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ }
+ }
+ // if we have not found a match, look at just vendor and product
+ if ((NULL == pFoundDevice) &&
+ (restoreRec.vendorID && restoreRec.productID))
+ {
+ pDevice = HIDGetFirstDevice ();
+ while (pDevice)
+ {
+ if ((restoreRec.vendorID == pDevice->vendorID) &&
+ (restoreRec.productID == pDevice->productID))
+ pFoundDevice = pDevice;
+ if (pFoundDevice)
+ break;
+ pDevice = HIDGetNextDevice (pDevice);
+ }
+ // match elements by cookie since same device type
+ if (pFoundDevice)
+ {
+ pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if (restoreRec.cookie == pElement->cookie)
+ pFoundElement = pElement;
+ if (pFoundElement)
+ break;
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ // if no cookie match (should NOT occur) match on usage
+ pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if ((restoreRec.usageE == pElement->usage) &&
+ (restoreRec.usagePageE == pElement->usagePage))
+ pFoundElement = pElement;
+ if (pFoundElement)
+ break;
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ }
+ }
+ // if we have not found a match look for just same type of device
+ if ((NULL == pFoundDevice) && (restoreRec.usage && restoreRec.usagePage))
+ {
+ pDevice = HIDGetFirstDevice ();
+ while (pDevice)
+ {
+ if ((restoreRec.usage == pDevice->usage) && (restoreRec.usagePage == pDevice->usagePage))
+ pFoundDevice = pDevice;
+ if (pFoundDevice)
+ break;
+ pDevice = HIDGetNextDevice (pDevice);
+ }
+ // match elements by type
+ if (pFoundDevice)
+ {
+ pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if ((restoreRec.usageE == pElement->usage) &&
+ (restoreRec.usagePageE == pElement->usagePage))
+ pFoundElement = pElement;
+ if (pFoundElement)
+ break;
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ }
+ }
+ // if still not found just get first device
+ if (NULL == pFoundDevice)
+ {
+ pFoundDevice = HIDGetFirstDevice ();
+ // match elements by type
+ if (pFoundDevice)
+ {
+ pElement = HIDGetFirstDeviceElement (pFoundDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if ((restoreRec.usageE == pElement->usage) &&
+ (restoreRec.usagePageE == pElement->usagePage))
+ pFoundElement = pElement;
+ if (pFoundElement)
+ break;
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ }
+ }
+ if ((NULL == pFoundDevice) || (NULL == pFoundElement))
+ {
+ // no HID device
+ *ppDevice = NULL;
+ *ppElement = NULL;
+ return restoreRec.actionCookie;
+ }
+ else
+ {
+ // no HID device
+ *ppDevice = pFoundDevice;
+ *ppElement = pFoundElement;
+ return restoreRec.actionCookie;
+ }
+
+}
+
+// ---------------------------------
+// Find the specified preference in the specified application
+// search for matching device and element
+// return pDevice, pElement that matches
+
+Boolean HIDRestoreElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement)
+{
+ Boolean found = false;
+
+ if ((NULL != keyCFStringRef) && (NULL != appCFStringRef) && (NULL != ppDevice) && (NULL != ppElement))
+ {
+ CFPropertyListRef prefCFPropertyListRef = CFPreferencesCopyAppValue(keyCFStringRef, appCFStringRef);
+
+ if (NULL != prefCFPropertyListRef)
+ {
+ if (CFStringGetTypeID() == CFGetTypeID(prefCFPropertyListRef))
+ {
+ char buffer[256];
+
+ if (CFStringGetCString((CFStringRef) prefCFPropertyListRef, buffer, sizeof(buffer), kCFStringEncodingASCII))
+ {
+ recDevice searchDevice;
+ recElement searchElement;
+ int count = sscanf(buffer, "d:{v:%ld, p:%ld, l:%ld, p:%ld, u:%ld}, e:{t:%ld, p:%ld, u:%ld, c:%ld}",
+ &searchDevice.vendorID, &searchDevice.productID, &searchDevice.locID, &searchDevice.usagePage, &searchDevice.usage,
+ &searchElement.type, &searchElement.usagePage, &searchElement.usage, (long*) &searchElement.cookie);
+
+ if (9 == count) // if we found all nine parametersÉ
+ { // and can find a device & element that matches theseÉ
+ if (HIDFindActionDeviceAndElement(&searchDevice, &searchElement,ppDevice, ppElement))
+ {
+ found = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ // We found the entry with this key but it's the wrong type; delete it.
+ CFPreferencesSetAppValue(keyCFStringRef, NULL, appCFStringRef);
+ (void) CFPreferencesAppSynchronize(appCFStringRef);
+ }
+ CFRelease(prefCFPropertyListRef);
+ }
+ }
+ return found;
+}
+
+// ---------------------------------
+// Save the device & element values into the specified key in the specified applications preferences
+
+Boolean HIDSaveElementPref (const CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement)
+{
+ Boolean success = false;
+
+ if ((NULL != keyCFStringRef) && (NULL != appCFStringRef) && HIDIsValidElement(pDevice,pElement))
+ {
+ CFStringRef prefCFStringRef =
+ CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("d:{v:%ld, p:%ld, l:%ld, p:%ld, u:%ld}, e:{t:%ld, p:%ld, u:%ld, c:%ld}"),
+ pDevice->vendorID, pDevice->productID, pDevice->locID, pDevice->usagePage, pDevice->usage,
+ pElement->type, pElement->usagePage, pElement->usage, pElement->cookie);
+
+ if (NULL != prefCFStringRef)
+ {
+ CFPreferencesSetAppValue(keyCFStringRef, prefCFStringRef, kCFPreferencesCurrentApplication);
+ CFRelease(prefCFStringRef);
+ success = true;
+ }
+ }
+ return success;
+}
diff --git a/HID_Utilities_Source/HID_Config_Utilities.h b/HID_Utilities_Source/HID_Config_Utilities.h
new file mode 100644
index 0000000..1ab7215
--- /dev/null
+++ b/HID_Utilities_Source/HID_Config_Utilities.h
@@ -0,0 +1,92 @@
+/*
+ File: HID_Config_Utilities.h
+
+ Contains: Definition of the interfaces to <HID_Config_Utilities.c>
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+
+*/
+
+#ifndef _HID_Config_Utilities_h_
+#define _HID_Config_Utilities_h_
+
+#include <stdio.h>
+
+#include "HID_Utilities.h"
+
+enum
+{
+ kPercentMove = 10 // precent of overall range a element must move to register
+};
+
+struct recSaveHID
+{
+ long actionCookie;
+ // device
+ // need to add serial number when I have a test case
+ long vendorID;
+ long productID;
+ long locID;
+ long usage;
+ long usagePage;
+ // elements
+ long usagePageE;
+ long usageE;
+ void * cookie;
+};
+typedef struct recSaveHID recSaveHID;
+typedef recSaveHID * pRecSaveHID;
+
+// polls all devices and elements for a change greater than kPercentMove. Times out after given time
+// returns true and pointer to device and element if found
+// returns false and NULL for both parameters if not found
+extern unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout);
+
+// take input records, save required info
+// assume file is open and at correct position.
+extern void HIDSaveElementConfig (FILE * fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie);
+
+// take file, read one record (assume file position is correct and file is open)
+// search for matching device
+// return pDevice, pElement and cookie for action
+extern long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement);
+
+#endif
+
diff --git a/HID_Utilities_Source/HID_Error_Handler.c b/HID_Utilities_Source/HID_Error_Handler.c
new file mode 100644
index 0000000..2985fce
--- /dev/null
+++ b/HID_Utilities_Source/HID_Error_Handler.c
@@ -0,0 +1,104 @@
+/*
+ File: Error Handler.c
+
+ Contains: Implementation of the HID utility error handlers for the HID Utilities
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+#if !defined (kBuildingLibrary)
+ #define kVerboseErrors
+
+// system includes ----------------------------------------------------------
+
+ #ifdef kVerboseErrors
+ #include <Carbon/Carbon.h>
+ #endif
+#endif // not kBuildingLibrary
+
+#include <stdio.h>
+
+// project includes ---------------------------------------------------------
+
+#include "HID_Utilities_Internal.h"
+
+// globals (internal/private) -----------------------------------------------
+
+// prototypes (internal/private) --------------------------------------------
+
+// functions (internal/private) ---------------------------------------------
+
+#pragma mark -
+// -------------------------------------
+
+// central error reporting
+
+void HIDReportErrorNum (char * strError, long numError)
+{
+ char errMsgCStr [256];
+
+ sprintf (errMsgCStr, "%s #%ld (0x%lx)", strError, numError, numError);
+
+ // out as debug string
+#ifdef kVerboseErrors
+ {
+ Str255 strErr = "\p";
+ CopyCStringToPascal (errMsgCStr, strErr);
+ DebugStr (strErr);
+ }
+#endif // kVerboseErrors
+}
+
+// -------------------------------------
+
+void HIDReportError (char * strError)
+{
+ char errMsgCStr [256];
+
+ sprintf (errMsgCStr, "%s", strError);
+
+ // out as debug string
+#ifdef kVerboseErrors
+ {
+ Str255 strErr = "\p";
+ CopyCStringToPascal (errMsgCStr, strErr);
+ DebugStr (strErr);
+ }
+#endif // kVerboseErrors
+}
diff --git a/HID_Utilities_Source/HID_Error_Handler.h b/HID_Utilities_Source/HID_Error_Handler.h
new file mode 100644
index 0000000..a672182
--- /dev/null
+++ b/HID_Utilities_Source/HID_Error_Handler.h
@@ -0,0 +1,74 @@
+/*
+ File: HID_Error_Handler.h
+
+ Contains: Definition of the interfaces to <HID_Error_Handler.c>
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+
+*/
+
+// Usage notes:
+
+// include control --------------------------------------------------
+
+#ifndef Error_Handler_h
+#define Error_Handler_h
+
+// includes ---------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// structures (public) -----------------------------------------------
+
+// public function declarations -------------------------------------
+
+// Error reporter, can be set to report however the application desires
+extern void HIDReportError (char * strError);
+
+// Error with numeric code reporter, can be set to report however the application desires
+extern void HIDReportErrorNum (char * strError, long numError);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // Error_Handler_h \ No newline at end of file
diff --git a/HID_Utilities_Source/HID_Name_Lookup.c b/HID_Utilities_Source/HID_Name_Lookup.c
new file mode 100644
index 0000000..717909d
--- /dev/null
+++ b/HID_Utilities_Source/HID_Name_Lookup.c
@@ -0,0 +1,347 @@
+/*
+ File: HID_Name_Lookup.c
+
+ Contains: Implementation of the HID device name lookup functions for the HID utilites.
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#include "HID_Utilities_Internal.h"
+#include "HID_Name_Lookup.h"
+
+#define FAKE_IT 1 // set true for debugging; returns the vendor, product & cookie (or usage info) as numbers.
+
+// ---------------------------------
+// Load the element strings from the given resource (XML) file into a CFPropertyListRef
+static CFPropertyListRef xml_load(const CFStringRef pResourceName,const CFStringRef pResourceExtension)
+{
+ CFPropertyListRef tCFPropertyListRef = NULL;
+ CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), pResourceName, pResourceExtension, NULL);
+
+ if (NULL != resFileCFURLRef)
+ {
+ CFDataRef resCFDataRef;
+
+ if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil))
+ {
+ if (NULL != resCFDataRef)
+ {
+ CFStringRef errorString;
+
+ tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString);
+ if (NULL == tCFPropertyListRef)
+ CFShow(errorString);
+ CFRelease(resCFDataRef);
+ }
+ }
+ CFRelease(resFileCFURLRef);
+ }
+ return tCFPropertyListRef;
+}
+
+// ---------------------------------
+// Find an element string in the <HID_cookie_strings.plist> resource (XML) file
+static Boolean xml_search_cookie(const long pVendorID, const long pProductID, const long pCookie, char* pCstr)
+{
+ static CFPropertyListRef tCFPropertyListRef = NULL;
+ Boolean results = false;
+
+ if (NULL == tCFPropertyListRef)
+ tCFPropertyListRef = xml_load(CFSTR("HID_cookie_strings"), CFSTR("plist"));
+ if (NULL != tCFPropertyListRef)
+ {
+ if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef))
+ {
+ CFDictionaryRef vendorCFDictionaryRef;
+ CFStringRef vendorKeyCFStringRef;
+ vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID);
+
+ if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef))
+ {
+ CFDictionaryRef productCFDictionaryRef;
+ CFStringRef productKeyCFStringRef;
+ CFStringRef vendorCFStringRef;
+
+ if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef))
+ {
+ //CFShow(vendorCFStringRef);
+ }
+ productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID);
+
+ if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef))
+ {
+ CFStringRef fullCFStringRef = NULL;
+ CFStringRef cookieKeyCFStringRef;
+ CFStringRef productCFStringRef;
+ CFStringRef cookieCFStringRef;
+
+ if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef))
+ {
+ //CFShow(productCFStringRef);
+ }
+ cookieKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pCookie);
+
+ if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, cookieKeyCFStringRef, (const void**) &cookieCFStringRef))
+ {
+ fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"),
+ vendorCFStringRef, productCFStringRef, cookieCFStringRef);
+ // CFShow(cookieCFStringRef);
+ }
+#if FAKE_IT
+ else
+ {
+ fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"),
+ vendorCFStringRef, productCFStringRef, cookieKeyCFStringRef);
+ }
+#endif
+ if (fullCFStringRef)
+ {
+ // CFShow(fullCFStringRef);
+ results = CFStringGetCString(
+ fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman);
+ CFRelease(fullCFStringRef);
+ }
+ CFRelease(cookieKeyCFStringRef);
+ }
+ CFRelease(productKeyCFStringRef);
+ }
+ CFRelease(vendorKeyCFStringRef);
+ }
+ //++CFRelease(tCFPropertyListRef); // Leak this!
+ }
+ return results;
+}
+
+// ---------------------------------
+// Find an element string in the <HID_device_usage_strings.plist> resource (XML) file
+static Boolean xml_search_usage(const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char* pCstr)
+{
+ static CFPropertyListRef tCFPropertyListRef = NULL;
+ Boolean results = false;
+
+ if (NULL == tCFPropertyListRef)
+ tCFPropertyListRef = xml_load(CFSTR("HID_device_usage_strings"), CFSTR("plist"));
+ if (NULL != tCFPropertyListRef)
+ {
+ if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef))
+ {
+ CFDictionaryRef vendorCFDictionaryRef;
+ CFStringRef vendorKeyCFStringRef;
+ vendorKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pVendorID);
+
+ if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, vendorKeyCFStringRef, (const void**) &vendorCFDictionaryRef))
+ {
+ CFDictionaryRef productCFDictionaryRef;
+ CFStringRef productKeyCFStringRef;
+ CFStringRef vendorCFStringRef;
+
+ if (!CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, CFSTR("Name"), (const void**) &vendorCFStringRef))
+ {
+ vendorCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("v: %ld"), pVendorID);
+ //CFShow(vendorCFStringRef);
+ }
+ productKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), pProductID);
+
+ if (CFDictionaryGetValueIfPresent(vendorCFDictionaryRef, productKeyCFStringRef, (const void**) &productCFDictionaryRef))
+ {
+ CFStringRef fullCFStringRef = NULL;
+ CFStringRef usageKeyCFStringRef;
+ CFStringRef productCFStringRef;
+ CFStringRef usageCFStringRef;
+
+ if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, CFSTR("Name"), (const void**) &productCFStringRef))
+ {
+ //CFShow(productCFStringRef);
+ }
+ usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld:%ld"), pUsagePage, pUsage);
+
+ if (CFDictionaryGetValueIfPresent(productCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef))
+ {
+ fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ %@"),
+ vendorCFStringRef, productCFStringRef, usageCFStringRef);
+ // CFShow(usageCFStringRef);
+ }
+#if FAKE_IT
+ else
+ {
+ fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@ #%@"),
+ vendorCFStringRef, productCFStringRef, usageKeyCFStringRef);
+ }
+#endif
+ if (fullCFStringRef)
+ {
+ // CFShow(fullCFStringRef);
+ results = CFStringGetCString(
+ fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman);
+ CFRelease(fullCFStringRef);
+ }
+ CFRelease(usageKeyCFStringRef);
+ }
+ CFRelease(productKeyCFStringRef);
+ }
+ CFRelease(vendorKeyCFStringRef);
+ }
+ //++CFRelease(tCFPropertyListRef); // Leak this!
+ }
+ return results;
+}
+
+// ---------------------------------
+// set name from vendor id/product id look up
+Boolean HIDGetElementNameFromVendorProductCookie (const long pVendorID, const long pProductID, const long pCookie, char * pName)
+{
+ Boolean result = false;
+ *pName = 0; // clear name
+
+ if (xml_search_cookie(pVendorID, pProductID, pCookie, pName))
+ return true;
+
+ switch (pVendorID) {
+ case kMacally:
+ switch (pProductID) {
+ case kiShock:
+ result = true;
+ switch (pCookie) {
+ case 3: sprintf(pName, "D-Pad Up"); break;
+ case 4: sprintf(pName, "D-Pad Down"); break;
+ case 5: sprintf(pName, "D-Pad Left"); break;
+ case 6: sprintf(pName, "D-Pad Right"); break;
+ case 7: sprintf(pName, "Up Button"); break;
+ case 8: sprintf(pName, "Right Button"); break;
+ case 9: sprintf(pName, "Down Button"); break;
+ case 10: sprintf(pName, "Left Button"); break;
+ case 11: sprintf(pName, "C Button"); break;
+ case 12: sprintf(pName, "B Button [Select]"); break;
+ case 13: sprintf(pName, "A Button [Start]"); break;
+ case 14: sprintf(pName, "F Button"); break;
+ case 15: sprintf(pName, "R1 Trigger"); break;
+ case 16: sprintf(pName, "R2 Trigger"); break;
+ case 17: sprintf(pName, "L1 Trigger"); break;
+ case 18: sprintf(pName, "L2 Trigger"); break;
+ case 19: sprintf(pName, "Left Stick Button"); break;
+ case 20: sprintf(pName, "Right Stick Button"); break;
+ case 21: sprintf(pName, "D Button"); break;
+ case 22: sprintf(pName, "E Button"); break;
+ case 23: sprintf(pName, "Left Stick X-Axis"); break;
+ case 24: sprintf(pName, "Left Stick Y-Axis"); break;
+ case 25: sprintf(pName, "Right Stick X-Axis"); break;
+ case 26: sprintf(pName, "Right Stick Y-Axis"); break;
+ default:
+#if FAKE_IT
+ sprintf(pName, "#{V:Macally, P:iShock, C:%ld}#", pCookie);
+#else
+ result = false;
+#endif FAKE_IT
+ break;
+ }
+ break;
+ default:
+#if FAKE_IT
+ sprintf(pName, "#{V:Macally, P:%ld, C:%ld}#", pProductID, pCookie); break;
+#else
+ result = false;
+#endif FAKE_IT
+ break;
+ }
+ break;
+ case kMacsense:
+ switch (pProductID) {
+ case kFunPadF107:
+ result = true;
+ switch (pCookie) {
+ case 3: sprintf(pName, "Button 1"); break;
+ case 4: sprintf(pName, "Button 2"); break;
+ case 5: sprintf(pName, "Button 3"); break;
+ case 6: sprintf(pName, "Button 4"); break;
+ case 7: sprintf(pName, "L1 Trigger"); break;
+ case 8: sprintf(pName, "R1 Trigger"); break;
+ case 9: sprintf(pName, "L2 Trigger"); break;
+ case 10: sprintf(pName, "R2 Trigger"); break;
+ case 11: sprintf(pName, "Right Stick X-Axis"); break;
+ case 12: sprintf(pName, "Right Stick Y-Axis"); break;
+ case 13: sprintf(pName, "Left Stick X-Axis"); break;
+ case 14: sprintf(pName, "Left Stick Y-Axis"); break;
+ case 15: sprintf(pName, "Hat Switch"); break;
+ default:
+#if FAKE_IT
+ sprintf(pName, "#{V:Macsense, P:FunPad F-107, C:%ld}#", pCookie);
+#else
+ result = false;
+#endif FAKE_IT
+ break;
+ }
+ default:
+#if FAKE_IT
+ sprintf(pName, "#{V:Macsense, P:%ld, C:%ld}#", pProductID, pCookie);
+#else
+ result = false;
+#endif FAKE_IT
+ break;
+ }
+ break;
+ default:
+#if FAKE_IT
+ sprintf(pName, "#{V:%ld, P:%ld, C:%ld}#", pVendorID, pProductID, pCookie);
+#else
+ result = false;
+#endif FAKE_IT
+ break;
+ }
+ return result;
+}
+
+
+// ---------------------------------
+// set name from vendor id/product id & usage look up
+Boolean HIDGetElementNameFromVendorProductUsage (const long pVendorID, const long pProductID, const long pUsagePage, const long pUsage, char * pName)
+{
+ Boolean result = false;
+ *pName = 0; // clear name
+
+ if (xml_search_usage(pVendorID, pProductID, pUsagePage, pUsage, pName))
+ return true;
+
+#if FAKE_IT
+ sprintf(pName, "#{V:%ld, P:%ld, U:%ld:%ld}#", pVendorID, pProductID, pUsagePage, pUsage);
+ result = true;
+#endif
+
+ return result;
+}
diff --git a/HID_Utilities_Source/HID_Name_Lookup.h b/HID_Utilities_Source/HID_Name_Lookup.h
new file mode 100644
index 0000000..5615172
--- /dev/null
+++ b/HID_Utilities_Source/HID_Name_Lookup.h
@@ -0,0 +1,87 @@
+/*
+ File: HID_Name_Lookup.h
+
+ Contains: Definition of the HID device name lookup functions for the HID utilites.
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#ifndef _HID_Name_Lookup_h_
+#define _HID_Name_Lookup_h_
+
+#include "HID_Utilities.h"
+
+// ==================================
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ==================================
+// Note: Now that as the device data has now been moved into external .XML files these
+// constansts should no longer be used. They will eventually be eliminated from this header.
+
+#define kMicrosoft 1118
+#define kSideWinderFFB2 27
+
+#define kLogitech 1133
+#define kWingManStrikeForce3D 49797
+
+#define kMacally 8738
+#define kiShock 16400
+#define kiShockIIFFB 16416
+
+#define kMacsense 1635
+#define kFunPadF107 38916
+// ==================================
+
+// set name from vendor id/product id look up (using cookies)
+extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName);
+
+// set name from vendor id/product id look up (using usage page & usage)
+extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName);
+// ==================================
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HID_Name_Lookup_h_
+
diff --git a/HID_Utilities_Source/HID_Queue_Utilities.c b/HID_Utilities_Source/HID_Queue_Utilities.c
new file mode 100644
index 0000000..70af952
--- /dev/null
+++ b/HID_Utilities_Source/HID_Queue_Utilities.c
@@ -0,0 +1,635 @@
+/*
+ File: HID_Queue_Utilities.c
+
+ Contains: Implementation of the HID queue functions for the HID utilites.
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+//#include <IOKit/hid/IOHIDDevice.h>
+
+#include "HID_Utilities_Internal.h"
+#include "HID_Utilities_External.h"
+
+// ==================================
+// compiler directives
+// ==================================
+#define USE_ASYNC_EVENTS TRUE
+#define REPORT_ERRORS FALSE
+// ==================================
+#if REPORT_ERRORS
+#define HIDREPORTERRORNUM(s,n) HIDReportErrorNum(s,n)
+#define HIDREPORTERROR(s) HIDReportError(s)
+#else
+#define HIDREPORTERRORNUM(s,n) do {} while (false)
+#define HIDREPORTERROR(s) do {} while (false)
+#endif
+// ==================================
+// private functions
+// ==================================
+
+// creates a queue for a device
+
+static IOReturn hid_CreateQueue (pRecDevice pDevice)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (NULL == pDevice->queue) // do we already have a queue
+ {
+ if (NULL != pDevice->interface)
+ {
+ pDevice->queue = (void *) (*(IOHIDDeviceInterface**) pDevice->interface)->allocQueue (pDevice->interface); // alloc queue
+ if (pDevice->queue)
+ {
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->create (pDevice->queue, 0, kDeviceQueueSize); // create actual queue
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("hid_CreateQueue - Failed to create queue via create", result);
+ }
+ else
+ {
+ HIDREPORTERROR ("hid_CreateQueue - Failed to alloc IOHIDQueueInterface ** via allocQueue");
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ else
+ HIDREPORTERRORNUM ("hid_CreateQueue - Device inteface does not exist for queue creation", result);
+ }
+ }
+ else
+ HIDREPORTERRORNUM ("hid_CreateQueue - Invalid Device", result);
+ return result;
+}
+
+// ---------------------------------
+// returns true if queue is empty false otherwise
+// error if no device, empty if no queue
+
+static unsigned char hid_IsDeviceQueueEmpty (pRecDevice pDevice)
+{
+ if (HIDIsValidDevice(pDevice)) // need valid device
+ {
+ if (pDevice->queue) // and queue
+ {
+ pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie))
+ return false;
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ }
+ else
+ HIDREPORTERROR ("hid_IsDeviceQueueEmpty - no queue.");
+ }
+ else
+ HIDREPORTERROR ("hid_IsDeviceQueueEmpty - Invalid device.");
+ return true;
+}
+
+// ---------------------------------
+// disposes and releases queue, sets queue to NULL,.
+// Note: will have no effect if device or queue do not exist
+
+static IOReturn hid_DisposeReleaseQueue (pRecDevice pDevice)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidDevice(pDevice)) // need valid device
+ {
+ if (pDevice->queue) // and queue
+ {
+ // stop queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to stop queue.", result);
+ // dispose of queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->dispose (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to dipose queue.", result);
+ // release the queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->Release (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("hid_DisposeReleaseQueue - Failed to release queue.", result);
+
+ pDevice->queue = NULL;
+ }
+ else
+ HIDREPORTERROR ("hid_DisposeReleaseQueue - no queue.");
+ }
+ else
+ HIDREPORTERROR ("hid_DisposeReleaseQueue - Invalid device.");
+ return result;
+}
+
+// ==================================
+// public functions
+
+// ---------------------------------
+// queues specific element, performing any device queue set up required
+// queue is started and ready to return events on exit from this function
+
+unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (NULL == pDevice->interface) // must have interface
+ {
+ HIDREPORTERROR ("HIDQueueElement - Device does not have interface.");
+ return kIOReturnError;
+ }
+ if (NULL == pDevice->queue) // if no queue create queue
+ result = hid_CreateQueue (pDevice);
+ if ((kIOReturnSuccess != result) || (NULL == pDevice->queue))
+ {
+ HIDREPORTERRORNUM ("HIDQueueElement - problem creating queue.", result);
+ if (kIOReturnSuccess != result)
+ return result;
+ else
+ return kIOReturnError;
+ }
+
+ // stop queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERROR ("HIDQueueElement - Failed to stop queue.");
+
+ // queue element
+ if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie))
+ {
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERROR ("HIDQueueElement - Failed to add Element to queue.");
+ }
+
+ // restart queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERROR ("HIDQueueElement - Failed to start queue.");
+ }
+ else
+ {
+ HIDREPORTERROR ("HIDQueueElement - Invalid Device and/or element.");
+ return kIOReturnBadArgument;
+ }
+
+ return result;
+}
+
+// ---------------------------------
+// adds all elements to queue, performing any device queue set up required
+// queue is started and ready to return events on exit from this function
+
+unsigned long HIDQueueDevice (pRecDevice pDevice)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+ pRecElement pElement;
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ // error checking
+ if (NULL == pDevice)
+ {
+ HIDREPORTERROR ("HIDQueueDevice - Device does not exist.");
+ return kIOReturnBadArgument;
+ }
+ if (NULL == pDevice->interface) // must have interface
+ {
+ HIDREPORTERROR ("HIDQueueDevice - Device does not have interface.");
+ return kIOReturnError;
+ }
+ if (NULL == pDevice->queue) // if no queue create queue
+ result = hid_CreateQueue (pDevice);
+ if ((kIOReturnSuccess != result) || (NULL == pDevice->queue))
+ {
+ HIDREPORTERRORNUM ("HIDQueueDevice - problem creating queue.", result);
+ if (kIOReturnSuccess != result)
+ return result;
+ else
+ return kIOReturnError;
+ }
+
+ // stop queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDQueueDevice - Failed to stop queue.", result);
+
+ // queue element
+ //¥ pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO);
+ pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeInput | kHIDElementTypeFeature);
+
+ while (pElement)
+ {
+ if (!(*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie))
+ {
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->addElement (pDevice->queue, pElement->cookie, 0);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDQueueDevice - Failed to add element to queue.", result);
+ }
+ //¥ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeInput | kHIDElementTypeFeature);
+ }
+
+ // start queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDQueueDevice - Failed to start queue.", result);
+
+ }
+ else
+ HIDREPORTERROR ("HIDQueueDevice - Invalid device.");
+
+ return result;
+}
+
+// ---------------------------------
+// removes element for queue, if last element in queue will release queue and closes device interface
+
+unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (!pDevice || !pElement)
+ result = kIOReturnBadArgument;
+ else
+ {
+ if ((pDevice->interface) && (pDevice->queue))
+ {
+ // stop queue
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->stop (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDDequeueElement - Failed to stop queue.", result);
+
+ if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie)) // if has element then remove
+ {
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDDequeueElement - Failed to add element to queue", result);
+ }
+
+ if (hid_IsDeviceQueueEmpty (pDevice)) // release device queue and close interface if queue empty
+ {
+ result = hid_DisposeReleaseQueue (pDevice);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDDequeueElement - Failed to dispose and release queue.", result);
+ }
+ else // not empty so restart queue
+ {
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->start (pDevice->queue);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDDequeueElement - Failed to start queue.", result);
+ }
+ }
+ else
+ {
+ HIDREPORTERROR ("HIDDequeueElement - No device inteface or queue.");
+ return kIOReturnError;
+ }
+ }
+ }
+ else
+ HIDREPORTERROR ("HIDDequeueElement - Invalid device.");
+
+ return result;
+}
+
+// ---------------------------------
+// completely removes all elements from queue and releases queue and closes device interface
+// does not release device interfaces, application must call HIDReleaseDeviceList on exit
+
+unsigned long HIDDequeueDevice (pRecDevice pDevice)
+{
+ IOReturn result = kIOReturnSuccess;
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if ((pDevice->interface) && (pDevice->queue))
+ {
+ // iterate through elements and if queued, remove
+ pRecElement pElement = HIDGetFirstDeviceElement (pDevice, kHIDElementTypeIO);
+ while (pElement)
+ {
+ if ((*(IOHIDQueueInterface**) pDevice->queue)->hasElement (pDevice->queue, pElement->cookie))
+ {
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->removeElement (pDevice->queue, pElement->cookie);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDDequeueDevice - Failed to remove element from queue.", result);
+ }
+ pElement = HIDGetNextDeviceElement (pElement, kHIDElementTypeIO);
+ }
+ }
+ // ensure queue is disposed and released
+ // interface will be closed and released on call to HIDReleaseDeviceList
+ result = hid_DisposeReleaseQueue (pDevice);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("removeElement - Failed to dispose and release queue.", result);
+#if USE_ASYNC_EVENTS
+ else if (NULL != pDevice->queueRunLoopSource)
+ {
+ if (CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode))
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode);
+ CFRelease(pDevice->queueRunLoopSource);
+ pDevice->queueRunLoopSource = NULL;
+ }
+#endif USE_ASYNC_EVENTS
+ }
+ else
+ {
+ HIDREPORTERROR ("HIDDequeueDevice - Invalid device.");
+ result = kIOReturnBadArgument;
+ }
+ return result;
+}
+
+// ---------------------------------
+// releases all device queues for quit or rebuild (must be called)
+// does not release device interfaces, application must call HIDReleaseDeviceList on exit
+
+unsigned long HIDReleaseAllDeviceQueues (void)
+{
+ IOReturn result = kIOReturnBadArgument;
+ pRecDevice pDevice = HIDGetFirstDevice ();
+
+ while (pDevice)
+ {
+ result = HIDDequeueDevice (pDevice);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDReleaseAllDeviceQueues - Could not dequeue device.", result);
+ pDevice = HIDGetNextDevice (pDevice);
+ }
+ return result;
+}
+
+// ---------------------------------
+// Closes and releases interface to device, should be done prior to exting application
+// Note: will have no affect if device or interface do not exist
+// application will "own" the device if interface is not closed
+// (device may have to be plug and re-plugged in different location to get it working again without a restart)
+
+unsigned long HIDCloseReleaseInterface (pRecDevice pDevice)
+{
+ IOReturn result = kIOReturnSuccess;
+
+ if (HIDIsValidDevice(pDevice) && (NULL != pDevice->interface))
+ {
+ // close the interface
+ result = (*(IOHIDDeviceInterface**) pDevice->interface)->close (pDevice->interface);
+ if (kIOReturnNotOpen == result)
+ {
+ // do nothing as device was not opened, thus can't be closed
+ }
+ else if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to close IOHIDDeviceInterface.", result);
+ //release the interface
+ result = (*(IOHIDDeviceInterface**) pDevice->interface)->Release (pDevice->interface);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDCloseReleaseInterface - Failed to release interface.", result);
+ pDevice->interface = NULL;
+ }
+ return result;
+}
+
+// ---------------------------------
+// Get the next event in the queue for a device
+// elements or entire device should be queued prior to calling this with HIDQueueElement or HIDQueueDevice
+// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise
+// Note: kIOReturnUnderrun returned from getNextEvent indicates an empty queue not an error condition
+// Note: application should pass in a pointer to a IOHIDEventStruct cast to a void (for CFM compatibility)
+
+unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent)
+{
+ IOReturn result = kIOReturnBadArgument;
+ AbsoluteTime zeroTime = {0,0};
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (pDevice->queue)
+ {
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->getNextEvent (pDevice->queue, (IOHIDEventStruct *)pHIDEvent, zeroTime, 0);
+ if (kIOReturnUnderrun == result)
+ return false; // no events in queue not an error per say
+ else if (kIOReturnSuccess != result) // actual error versus just an empty queue
+ HIDREPORTERRORNUM ("HIDGetEvent - Could not get HID event via getNextEvent.", result);
+ else
+ return true;
+ }
+ else
+ HIDREPORTERROR ("HIDGetEvent - queue does not exist.");
+ }
+ else
+ HIDREPORTERROR ("HIDGetEvent - invalid device.");
+
+ return false; // did not get event
+}
+
+// ---------------------------------
+// returns current value for element, polling element
+// will return 0 on error conditions which should be accounted for by application
+
+long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement)
+{
+ IOReturn result = kIOReturnBadArgument;
+ IOHIDEventStruct hidEvent;
+
+ hidEvent.value = 0;
+ hidEvent.longValueSize = 0;
+ hidEvent.longValue = nil;
+
+ if (HIDIsValidElement(pDevice, pElement))
+ {
+ if (NULL != pDevice->interface)
+ {
+ // ++ NOTE: If the element type is feature then use queryElementValue instead of getElementValue
+ if (kIOHIDElementTypeFeature == pElement->type)
+ {
+ result = (*(IOHIDDeviceInterface**) pDevice->interface)->queryElementValue (pDevice->interface, pElement->cookie, &hidEvent,0,NULL,NULL,NULL);
+ if (kIOReturnUnsupported == result) // unless it's unsuported.
+ goto try_getElementValue;
+ else if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via queryElementValue.", result);
+ }
+ else if (pElement->type <= kIOHIDElementTypeInput_ScanCodes)
+ {
+try_getElementValue:
+ result = (*(IOHIDDeviceInterface**) pDevice->interface)->getElementValue (pDevice->interface, pElement->cookie, &hidEvent);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDGetElementValue - Could not get HID element value via getElementValue.", result);
+ }
+ // on 10.0.x this returns the incorrect result for negative ranges, so fix it!!!
+ // this is not required on Mac OS X 10.1+
+ if ((pElement->min < 0) && (hidEvent.value > pElement->max)) // assume range problem
+ hidEvent.value = hidEvent.value + pElement->min - pElement->max - 1;
+ }
+ else
+ HIDREPORTERROR ("HIDGetElementValue - no interface for device.");
+ }
+ else
+ HIDREPORTERROR ("HIDGetElementValue - invalid device and/or element.");
+
+ // record min and max for auto scale and auto ...
+/*
+ if (hidEvent.value < pElement->calMin)
+ pElement->calMin = hidEvent.value;
+ if (hidEvent.value > pElement->calMax)
+ pElement->calMax = hidEvent.value;
+*/
+
+ // auto user scale
+ return hidEvent.value;
+}
+
+// ---------------------------------
+// Set an elements value
+// NOTE: This should only be used when a single element of a report needs to be sent.
+// If multiple elements are to be send then transactions should be used.
+
+long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent)
+{
+ IOHIDEventStruct* pMyIOHIDEvent = (IOHIDEventStruct*) pIOHIDEvent;
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidElement(pDevice, pElement))
+ {
+ if (NULL != pDevice->interface)
+ {
+ result = (*(IOHIDDeviceInterface**) pDevice->interface)->setElementValue (pDevice->interface, pElement->cookie, pMyIOHIDEvent, -1, nil, nil, nil);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDSetElementValue - Could not set HID element value via setElementValue.", result);
+ }
+ else
+ HIDREPORTERROR ("HIDSetElementValue - no interface for device.");
+ }
+ else
+ HIDREPORTERROR ("HIDSetElementValue - invalid device and/or element.");
+
+ return result;
+}
+
+// ---------------------------------
+// Set a callback to be called when a queue goes from empty to non-empty
+/*
+long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidDevice(pDevice))
+ {
+#if USE_ASYNC_EVENTS
+ // if we don't have a queue runloop sourceÉ
+ if (NULL == pDevice->queueRunLoopSource)
+ {
+ // then create one
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->createAsyncEventSource((void *) pDevice->queue,
+ (CFRunLoopSourceRef*) &pDevice->queueRunLoopSource);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDSetQueueCallback - Failed to createAsyncEventSource error: ", result);
+ }
+ // if we have one nowÉ
+ if (NULL != pDevice->queueRunLoopSource)
+ {
+ // and it's not already attached to our runloopÉ
+ if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode))
+ // then attach it now.
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), pDevice->queueRunLoopSource, kCFRunLoopDefaultMode);
+ }
+
+ // now install our callback
+ result = (*(IOHIDQueueInterface**) pDevice->queue)->setEventCallout(pDevice->queue, callback, pDevice, pDevice);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDSetQueueCallback - Could not set HID queue callback via setEventCallout.", result);
+#endif USE_ASYNC_EVENTS
+ }
+ else
+ HIDREPORTERROR ("HIDSetQueueCallback - invalid device and/or element.");
+ return result;
+}
+*/
+#if 1
+// ---------------------------------
+// Get a report from a device
+long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (NULL != pDevice->interface)
+ {
+ result = (*(IOHIDDeviceInterface**) pDevice->interface)->getReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDGetReport - Could not getReport, error: ", result);
+ }
+ else
+ HIDREPORTERROR ("HIDGetReport - no interface for device.");
+ }
+ else
+ HIDREPORTERROR ("HIDGetReport - invalid device.");
+
+ return result;
+}
+
+// ---------------------------------
+// Send a report to a device
+long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize)
+{
+ IOReturn result = kIOReturnError; // assume failure (pessimist!)
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (NULL != pDevice->interface)
+ {
+ result = (*(IOHIDDeviceInterface**) pDevice->interface)->setReport (pDevice->interface, reportType, reportID, reportBuffer, reportBufferSize, -1, nil, nil, nil);
+ if (kIOReturnSuccess != result)
+ HIDREPORTERRORNUM ("HIDGetReport - Could not setReport; error: ", result);
+ }
+ else
+ HIDREPORTERROR ("HIDGetReport - no interface for device.");
+ }
+ else
+ HIDREPORTERROR ("HIDGetReport - invalid device.");
+
+ return result;
+}
+#endif \ No newline at end of file
diff --git a/HID_Utilities_Source/HID_Queue_Utilities.h b/HID_Utilities_Source/HID_Queue_Utilities.h
new file mode 100644
index 0000000..e9b0501
--- /dev/null
+++ b/HID_Utilities_Source/HID_Queue_Utilities.h
@@ -0,0 +1,114 @@
+/*
+ File: HID_Queue_Utilities.h
+
+ Contains: Definition of the HID queue functions for the HID utilites.
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#ifndef _HID_Queue_Utilities_h_
+#define _HID_Queue_Utilities_h_
+
+#include "HID_Utilities.h"
+
+// ==================================
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ==================================
+
+enum
+{
+ kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible
+ // but should account for the maximum possible events in the queue
+ // USB updates will likely occur at 100 Hz so one must account for this rate of
+ // if states change quickly (updates are only posted on state changes)
+};
+
+// ==================================
+// queues specific element, performing any device queue set up required
+extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement);
+
+// adds all elements to queue, performing any device queue set up required
+extern unsigned long HIDQueueDevice (pRecDevice pDevice);
+
+// removes element for queue, if last element in queue will release queue and device
+extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement);
+
+// completely removes all elements from queue and releases queue and device
+extern unsigned long HIDDequeueDevice (pRecDevice pDevice);
+
+// releases all device queues for quit or rebuild (must be called)
+extern unsigned long HIDReleaseAllDeviceQueues (void);
+
+// releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList)
+extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice);
+
+// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise
+// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
+extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent);
+
+// returns current value for element, creating device interface as required, polling element
+extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement);
+
+// Set an elements value
+// NOTE: This should only be used when a single element report needs to be sent.
+// If multiple elements reports are to be send then transactions should be used.
+extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pIOHIDEvent);
+
+// Set a callback to be called when a queue goes from empty to non-empty
+extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback);
+
+#if 0
+// Get a report from a device
+extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, UInt32* reportBufferSize);
+
+// Send a report to a device
+extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const UInt32 reportID, void* reportBuffer, const UInt32 reportBufferSize);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HID_Queue_Utilities_h_
+
diff --git a/HID_Utilities_Source/HID_Transaction_Utilities.c b/HID_Utilities_Source/HID_Transaction_Utilities.c
new file mode 100644
index 0000000..c9012f1
--- /dev/null
+++ b/HID_Utilities_Source/HID_Transaction_Utilities.c
@@ -0,0 +1,316 @@
+/*
+ File: HID_Transaction_Utilities.h
+
+ Contains: Definitions of the HID queue functions for the HID utilites.
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#include <CoreServices/CoreServices.h>
+
+#include "HID_Utilities_Internal.h"
+#include "HID_Utilities_External.h"
+
+// ==================================
+// private functions
+
+// creates a transaction for a device, allocates and creates the transaction interface if required
+
+static IOReturn hid_CreateTransaction(pRecDevice pDevice)
+{
+ IOReturn result = kIOReturnSuccess;
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (NULL == pDevice->transaction) // if we don't already have a transactionÉ
+ {
+ if (NULL != pDevice->interface) // and we do have an interfaceÉ
+ {
+ pDevice->transaction = (void *) (*(IOHIDDeviceInterface**) pDevice->interface)->allocOutputTransaction (pDevice->interface); // alloc Transaction
+ if (pDevice->transaction) // if it was successfulÉ
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->create (pDevice->transaction); // create actual transaction
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nFailed to create transaction via create: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nhid_CreateTransaction failed to allocOutputTransaction");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ else
+ HIDReportErrorNum ("\nhid_CreateTransaction failed: Device inteface does not exist.", result);
+ }
+ }
+ return result;
+}
+
+// ==================================
+// public functions
+// ---------------------------------
+// add an element to a Transaction
+unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->addElement (pDevice->transaction,pElement->cookie); // add element
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionAddElement failed to add Element: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionAddElement failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ return result;
+}
+
+// removes an element from a Transaction
+unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->removeElement (pDevice->transaction,pElement->cookie); // remove element
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionRemoveElement failed to remove Element: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionRemoveElement failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+
+ return result;
+}
+
+// return true if this transaction contains this element
+Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement)
+{
+ Boolean result = false;
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ (void) hid_CreateTransaction(pDevice);
+
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->hasElement (pDevice->transaction,pElement->cookie); // remove element
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionHasElement failed: no transaction interface");
+ }
+ }
+ return result;
+}
+
+/* This changes the default value of an element, when the values of the */
+/* elements are cleared, on clear or commit, they are reset to the */
+/* default value */
+/* This call can be made on elements that are not in the transaction, but */
+/* has undefined behavior if made on elements not in the transaction */
+/* which are later added to the transaction. */
+/* In other words, an element should be added before its default is */
+/* set, for well defined behavior. */
+unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->setElementDefault (pDevice->transaction,pElement->cookie, pValueEvent);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionSetElementDefault failed to set Element Default: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionSetElementDefault failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+
+ return result;
+}
+
+/* Get the current setting of an element's default value */
+unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->getElementDefault (pDevice->transaction,pElement->cookie, pValueEvent);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionGetElementDefault failed to get Element Default: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionGetElementDefault failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ return result;
+}
+
+/* Add a change to the transaction, by setting an element value */
+/* The change is not actually made until it is commited */
+/* The element must be part of the transaction or this call will fail */
+unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->setElementValue (pDevice->transaction,pElement->cookie, pValueEvent);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionSetElementValue failed to set Element Default: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionSetElementValue failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ return result;
+}
+
+/* Get the current setting of an element value */
+unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidElement(pDevice,pElement))
+ {
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->getElementValue (pDevice->transaction,pElement->cookie, pValueEvent);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionGetElementValue failed to get Element Default: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionGetElementValue failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ return result;
+}
+
+/* Commit the transaction, or clear all the changes and start over */
+unsigned long HIDTransactionCommit(pRecDevice pDevice)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (pDevice->transaction)
+ {
+#if 0000
+ // NOTE: this code is to workaround a bug where if you commit transactions
+ // too fast then some of the reports get dropped.
+ // (fixed in 10.2.1)
+ static AbsoluteTime nextTime = {0,0}; // first time this should be no delay
+
+ if (nextTime.hi || nextTime.lo)
+ MPDelayUntil(&nextTime);
+#endif
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->commit (pDevice->transaction,-1,NULL,NULL,NULL);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionCommit failed to commit: error = %ld.", result);
+#if 0000
+ nextTime = AddDurationToAbsolute(20 * kDurationMillisecond,UpTime());
+#endif
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionCommit failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ return result;
+}
+
+/* Clear all the changes and start over */
+unsigned long HIDTransactionClear(pRecDevice pDevice)
+{
+ IOReturn result = hid_CreateTransaction(pDevice);
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (pDevice->transaction)
+ {
+ result = (*(IOHIDOutputTransactionInterface**) pDevice->transaction)->clear (pDevice->transaction);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("\nHIDTransactionClear failed to get Element Default: error = %ld.", result);
+ }
+ else
+ {
+ HIDReportError ("\nHIDTransactionClear failed: no transaction interface");
+ if (!result)
+ result = kIOReturnError; // synthesis error
+ }
+ }
+ return result;
+}
diff --git a/HID_Utilities_Source/HID_Transaction_Utilities.h b/HID_Utilities_Source/HID_Transaction_Utilities.h
new file mode 100644
index 0000000..4822ddb
--- /dev/null
+++ b/HID_Utilities_Source/HID_Transaction_Utilities.h
@@ -0,0 +1,106 @@
+/*
+ File: HID_Transaction_Utilities.h
+
+ Contains: Implementation of the HID queue functions for the HID utilites.
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#ifndef _HID_Transaction_Utilities_h_
+#define _HID_Transaction_Utilities_h_
+
+#include "HID_Utilities.h"
+
+// ==================================
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ==================================
+// Create and open an transaction interface to device, required prior to extracting values or building Transactions
+extern unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement);
+
+// removes an element from a Transaction
+extern unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement);
+
+// return true if this transaction contains this element
+extern Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement);
+
+/* This changes the default value of an element, when the values of the */
+/* elements are cleared, on clear or commit, they are reset to the */
+/* default value */
+/* This call can be made on elements that are not in the transaction, but */
+/* has undefined behavior if made on elements not in the transaction */
+/* which are later added to the transaction. */
+/* In other words, an element should be added before its default is */
+/* set, for well defined behavior. */
+extern unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Get the current setting of an element's default value */
+extern unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Add a change to the transaction, by setting an element value */
+/* The change is not actually made until it is commited */
+/* The element must be part of the transaction or this call will fail */
+extern unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Get the current setting of an element value */
+extern unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Commit the transaction, or clear all the changes and start over */
+/* timoutMS is the timeout in milliseconds, a zero timeout will cause */
+/* this call to be non-blocking (returning queue empty) if there */
+/* is a NULL callback, and blocking forever until the queue is */
+/* non-empty if their is a valid callback */
+/* callback, if non-NULL is a callback to be called when data is */
+/* inserted to the queue */
+/* callbackTarget and callbackRefcon are passed to the callback */
+extern unsigned long HIDTransactionCommit(pRecDevice pDevice);
+
+/* Clear all the changes and start over */
+extern unsigned long HIDTransactionClear(pRecDevice pDevice);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HID_Transaction_Utilities_h_
+
diff --git a/HID_Utilities_Source/HID_Utilities.c b/HID_Utilities_Source/HID_Utilities.c
new file mode 100644
index 0000000..b7b22c5
--- /dev/null
+++ b/HID_Utilities_Source/HID_Utilities.c
@@ -0,0 +1,2198 @@
+/*
+ File: HID_Utilities.c
+
+ Contains: Implementation of HID Utilities
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#include "HID_Utilities_Internal.h"
+#include "HID_Utilities_External.h"
+
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOMessage.h>
+#include <IOKit/hid/IOHIDUsageTables.h>
+
+//================================================================================================
+#define USE_NOTIFICATIONS 1
+//================================================================================================
+// local (static) functions
+//================================================================================================
+static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection);
+static pRecDevice hid_DisposeDevice (pRecDevice ppDevice);
+//================================================================================================
+// globals
+//================================================================================================
+#if USE_NOTIFICATIONS
+static IONotificationPortRef gNotifyPort;
+static io_iterator_t gAddedIter;
+static CFRunLoopRef gRunLoop;
+#endif USE_NOTIFICATIONS
+
+// for element retrieval
+static pRecDevice gCurrentGetDevice = NULL;
+static Boolean gAddAsChild = false;
+static int gDepth = false;
+
+static pRecDevice gpDeviceList = NULL;
+static UInt32 gNumDevices = 0;
+
+#pragma mark private functions
+// ==================================
+// private functions
+
+static UInt32 hid_CountCurrentDevices (void);
+
+// extracts actual specific element information from each element CF dictionary entry
+static void hid_GetElementInfo (CFTypeRef refElement, pRecElement pElement)
+{
+ long number;
+ CFTypeRef refType;
+ // type, usagePage, usage already stored
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementCookieKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->cookie = (IOHIDElementCookie) number;
+ else
+ pElement->cookie = (IOHIDElementCookie) 0;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMinKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->min = number;
+ else
+ pElement->min = 0;
+
+// pElement->calMax = pElement->min;
+ pElement->userMin = kDefaultUserMin;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementMaxKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->max = number;
+ else
+ pElement->max = 0;
+
+// pElement->calMin = pElement->max;
+ pElement->userMax = kDefaultUserMax;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->scaledMin = number;
+ else
+ pElement->scaledMin = 0;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->scaledMax = number;
+ else
+ pElement->scaledMax = 0;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->size = number;
+ else
+ pElement->size = 0;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey));
+ if (refType)
+ pElement->relative = CFBooleanGetValue (refType);
+ else
+ pElement->relative = 0;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey));
+ if (refType)
+ pElement->wrapping = CFBooleanGetValue (refType);
+ else
+ pElement->wrapping = false;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey));
+ if (refType)
+ pElement->nonLinear = CFBooleanGetValue (refType);
+ else
+ pElement->wrapping = false;
+
+#ifdef kIOHIDElementHasPreferredStateKey
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferredStateKey));
+#else // Mac OS X 10.0 has spelling error
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey));
+#endif
+ if (refType)
+ pElement->preferredState = CFBooleanGetValue (refType);
+ else
+ pElement->preferredState = false;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey));
+ if (refType)
+ pElement->nullState = CFBooleanGetValue (refType);
+ else
+ pElement->nullState = false;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->units = number;
+ else
+ pElement->units = 0;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUnitExponentKey));
+ if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number))
+ pElement->unitExp = number;
+ else
+ pElement->unitExp = 0;
+
+ refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementNameKey));
+ if (refType)
+ if (!CFStringGetCString (refType, pElement->name, 256, CFStringGetSystemEncoding ()))
+ HIDReportError ("CFStringGetCString error retrieving pElement->name.");
+ if (!*pElement->name)
+ {
+ // set name from vendor id, product id & usage info look up
+ if (!HIDGetElementNameFromVendorProductUsage (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, pElement->usagePage, pElement->usage, pElement->name))
+ {
+ // set name from vendor id/product id look up
+ HIDGetElementNameFromVendorProductCookie (gCurrentGetDevice->vendorID, gCurrentGetDevice->productID, (long) pElement->cookie, pElement->name);
+ if (!*pElement->name) { // if no name
+ HIDGetUsageName (pElement->usagePage, pElement->usage, pElement->name);
+ if (!*pElement->name) // if not usage
+ sprintf (pElement->name, "Element");
+ }
+ }
+ }
+}
+
+// ---------------------------------
+// examines CF dictionary vlaue in device element hierarchy to determine if it is element of interest or a collection of more elements
+// if element of interest allocate storage, add to list and retrieve element specific info
+// if collection then pass on to deconstruction collection into additional individual elements
+
+static void hid_AddElement (CFTypeRef refElement, pRecElement * ppElementCurrent)
+{
+ pRecDevice pDevice = gCurrentGetDevice;
+ pRecElement pElement = NULL;
+ long elementType, usagePage, usage;
+ CFTypeRef refElementType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementTypeKey));
+ CFTypeRef refUsagePage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsagePageKey));
+ CFTypeRef refUsage = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementUsageKey));
+
+ if (refElementType)
+ CFNumberGetValue (refElementType, kCFNumberLongType, &elementType);
+ if (refUsagePage)
+ CFNumberGetValue (refUsagePage, kCFNumberLongType, &usagePage);
+ if (refUsage)
+ CFNumberGetValue (refUsage, kCFNumberLongType, &usage);
+
+ 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
+}
+
+// ---------------------------------
+// collects information from each array member in device element list (each array memeber = element)
+
+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 information
+
+static 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);
+ }
+}
+
+// ---------------------------------
+// handles extracting element information from element collection CF types
+// used from top level element decoding and hierarchy deconstruction to flatten device element list
+
+static void hid_GetCollectionElements (CFMutableDictionaryRef deviceProperties, pRecElement *ppCurrentCollection)
+{
+ CFTypeRef refElementTop = CFDictionaryGetValue (deviceProperties, CFSTR(kIOHIDElementKey));
+ if (refElementTop)
+ hid_GetElements (refElementTop, ppCurrentCollection);
+ else
+ HIDReportError ("hid_GetCollectionElements: CFDictionaryGetValue error when creating CFTypeRef for kIOHIDElementKey.");
+}
+
+// ---------------------------------
+// use top level element usage page and usage to discern device usage page and usage setting appropriate values in device record
+
+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.");
+}
+
+// ---------------------------------
+// extracts device info from CF dictionary records in IO registry
+
+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.");
+ }
+}
+
+// ---------------------------------
+// adds device to linked list of devices passed in (handles NULL lists properly)
+// (returns where you just stored it)
+static pRecDevice* hid_AddDevice (pRecDevice *ppListDeviceHead, pRecDevice pNewDevice)
+{
+ pRecDevice* result = NULL;
+
+ if (NULL == *ppListDeviceHead)
+ result = ppListDeviceHead;
+ else
+ {
+ pRecDevice pDevicePrevious = NULL, pDevice = *ppListDeviceHead;
+ while (pDevice)
+ {
+ pDevicePrevious = pDevice;
+ pDevice = pDevicePrevious->pNext;
+ }
+ result = &pDevicePrevious->pNext;
+ }
+ pNewDevice->pNext = NULL;
+
+ *result = pNewDevice;
+
+ return result;
+}
+
+// ---------------------------------
+// given a IO device object build a flat device record including device info and elements
+
+static pRecDevice hid_BuildDevice (io_object_t hidDevice)
+{
+ pRecDevice pDevice = (pRecDevice) malloc (sizeof (recDevice));
+
+ if (NULL != pDevice)
+ {
+ // get dictionary for HID properties
+ CFMutableDictionaryRef hidProperties = 0;
+ kern_return_t result = IORegistryEntryCreateCFProperties (hidDevice, &hidProperties, kCFAllocatorDefault, kNilOptions);
+
+ // clear record
+ bzero(pDevice, sizeof(recDevice));
+
+ if ((result == KERN_SUCCESS) && (NULL != hidProperties))
+ {
+ 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);
+
+ // Free the data we're no longer using now that the device is going away
+ hid_DisposeDevice (pDevice);
+ }
+}
+#else
+
+static void hid_RemovalCallbackFunction(void * target, IOReturn result, void * refcon, void * sender)
+{
+ hid_DisposeDevice ((pRecDevice) target);
+}
+
+#endif USE_NOTIFICATIONS
+
+//================================================================================================
+//
+// hid_AddDevices
+//
+// This routine is the callback for our IOServiceAddMatchingNotification. When we get called
+// we will look at all the devices that were added and we will:
+//
+// 1. Create some private data to relate to each device.
+// 2. Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device,
+// using the refCon field to store a pointer to our data. When we get called with
+// this interest notification, we can grab the refCon and access our private data.
+//
+//================================================================================================
+//
+// ---------------------------------
+// given a IO device iterator, iterate it and add all its devices
+
+static 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 = NULL;
+
+ while (ioHIDDeviceObject = IOIteratorNext (iterator))
+ {
+ 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);
+ }
+}
+
+// ---------------------------------
+// disposes of the element list associated with a device and the memory associated with the list
+// uses depthwise recursion to dispose both collections and elements.
+
+static void hid_DisposeDeviceElements (pRecElement pElement)
+{
+ if (pElement)
+ {
+ if (pElement->pChild)
+ hid_DisposeDeviceElements (pElement->pChild);
+ if (pElement->pSibling)
+ hid_DisposeDeviceElements (pElement->pSibling);
+ free (pElement);
+ }
+}
+
+// ---------------------------------
+// disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL
+// all your device no longer belong to us... (i.e., you do not 'own' the device anymore)
+
+static pRecDevice hid_DisposeDevice (pRecDevice pDevice)
+{
+ kern_return_t result = KERN_SUCCESS;
+ pRecDevice pDeviceNext = NULL;
+
+ if (HIDIsValidDevice(pDevice))
+ {
+ // save next device prior to disposing of this device
+ pDeviceNext = pDevice->pNext;
+
+ result = HIDDequeueDevice (pDevice);
+#if 0
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("hid_DisposeDevice: HIDDequeueDevice error: 0x%8.8X.", result);
+#endif 1
+
+ hid_DisposeDeviceElements (pDevice->pListElements);
+ pDevice->pListElements = NULL;
+
+ result = HIDCloseReleaseInterface (pDevice); // function sanity checks interface value (now application does not own device)
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("hid_DisposeDevice: HIDCloseReleaseInterface error: 0x%8.8X.", result);
+
+#if USE_NOTIFICATIONS
+ if (pDevice->interface)
+ {
+ // replace (*pDevice->interface)->Release(pDevice->interface);
+ result = IODestroyPlugInInterface (pDevice->interface);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("hid_DisposeDevice: IODestroyPlugInInterface error: 0x%8.8X.", result);
+ }
+
+ if (pDevice->notification)
+ {
+ result = IOObjectRelease((io_object_t) pDevice->notification);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("hid_DisposeDevice: IOObjectRelease error: 0x%8.8X.", result);
+ }
+#endif USE_NOTIFICATIONS
+
+ // remove this device from the device list
+ if (gpDeviceList == pDevice) // head of list?
+ gpDeviceList = pDeviceNext;
+ else
+ {
+ pRecDevice pDeviceTemp = pDeviceNext = gpDeviceList; // we're going to return this if we don't find ourselfs in the list
+ while (pDeviceTemp)
+ {
+ if (pDeviceTemp->pNext == pDevice) // found us!
+ {
+ // take us out of linked list
+ pDeviceTemp->pNext = pDeviceNext = pDevice->pNext;
+ break;
+ }
+ pDeviceTemp = pDeviceTemp->pNext;
+ }
+ }
+ free (pDevice);
+ }
+
+ // update device count
+ gNumDevices = hid_CountCurrentDevices ();
+
+ return pDeviceNext;
+}
+
+// ---------------------------------
+// count number of devices in global device list (gpDeviceList)
+static UInt32 hid_CountCurrentDevices (void)
+{
+ pRecDevice pDevice = gpDeviceList;
+ UInt32 devices = 0;
+ while (pDevice)
+ {
+ devices++;
+ pDevice = pDevice->pNext;
+ }
+ return devices;
+}
+
+// ---------------------------------
+// matches type masks passed in to actual element types (which are not set up to be used as a mask
+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
+ }
+ return NULL;
+}
+
+#define FAKE_IT 0 // set true for debugging; returns the usage & usage page as numbers
+
+// ---------------------------------
+// Load the usage strings from the <HID_usage_strings.plist> resource (XML) file into a CFPropertyListRef
+static CFPropertyListRef xml_load_usage_strings(void)
+{
+ CFPropertyListRef tCFPropertyListRef = NULL;
+ CFURLRef resFileCFURLRef = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("HID_usage_strings"), CFSTR("plist"), NULL);
+
+ if (NULL != resFileCFURLRef)
+ {
+ CFDataRef resCFDataRef;
+
+ if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, resFileCFURLRef, &resCFDataRef, nil, nil, nil))
+ {
+ if (NULL != resCFDataRef)
+ {
+ CFStringRef errorString;
+
+ tCFPropertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resCFDataRef, kCFPropertyListImmutable, &errorString);
+ if (NULL == tCFPropertyListRef)
+ CFShow(errorString);
+ CFRelease(resCFDataRef);
+ }
+ }
+ CFRelease(resFileCFURLRef);
+ }
+ return tCFPropertyListRef;
+}
+
+// ---------------------------------
+// Find a usage string in the <HID_usage_strings.plist> resource (XML) file
+
+static Boolean xml_GetUsageName(const long valueUsagePage, const long valueUsage, char* pCstr)
+{
+ static CFPropertyListRef tCFPropertyListRef = NULL;
+ Boolean results = false;
+
+ if (NULL == tCFPropertyListRef)
+ tCFPropertyListRef = xml_load_usage_strings();
+ if (NULL != tCFPropertyListRef)
+ {
+ if (CFDictionaryGetTypeID() == CFGetTypeID(tCFPropertyListRef))
+ {
+ CFDictionaryRef pageCFDictionaryRef;
+ CFStringRef pageKeyCFStringRef;
+ pageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsagePage);
+
+ if (CFDictionaryGetValueIfPresent(tCFPropertyListRef, pageKeyCFStringRef, (const void**) &pageCFDictionaryRef))
+ {
+ CFStringRef pageCFStringRef;
+
+ if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, CFSTR("Name"), (const void**) &pageCFStringRef))
+ {
+ //CFShow(pageCFStringRef);
+ }
+
+ {
+ CFStringRef fullCFStringRef = NULL;
+ CFStringRef usageKeyCFStringRef;
+ CFStringRef usageCFStringRef;
+
+ usageKeyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%4.4lX"), valueUsage);
+
+ if (CFDictionaryGetValueIfPresent(pageCFDictionaryRef, usageKeyCFStringRef, (const void**) &usageCFStringRef))
+ {
+ fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@"),
+ pageCFStringRef, usageCFStringRef);
+ // CFShow(usageCFStringRef);
+ }
+#if FAKE_IT
+ else
+ {
+ fullCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ #%@"),
+ pageCFStringRef, usageKeyCFStringRef);
+ }
+#endif
+ if (fullCFStringRef)
+ {
+ // CFShow(fullCFStringRef);
+ results = CFStringGetCString(
+ fullCFStringRef, pCstr, CFStringGetLength(fullCFStringRef) * sizeof(UniChar) + 1, kCFStringEncodingMacRoman);
+ CFRelease(fullCFStringRef);
+ }
+ CFRelease(usageKeyCFStringRef);
+ }
+ }
+ CFRelease(pageKeyCFStringRef);
+ }
+ //++CFRelease(tCFPropertyListRef); // Leak this!
+ }
+ return results;
+}
+
+#pragma mark public functions
+// =================================
+// public functions
+
+// ---------------------------------
+// Create and open an interface to device, required prior to extracting values or building queues
+// Note: appliction now owns the device and must close and release it prior to exiting
+
+unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice)
+{
+ IOReturn result = kIOReturnSuccess;
+ HRESULT plugInResult = S_OK;
+ SInt32 score = 0;
+ IOCFPlugInInterface ** ppPlugInInterface = NULL;
+
+ if (NULL == pDevice->interface)
+ {
+ result = IOCreatePlugInInterfaceForService (hidDevice, kIOHIDDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID, &ppPlugInInterface, &score);
+ if (kIOReturnSuccess == result)
+ {
+ // Call a method of the intermediate plug-in to create the device interface
+ plugInResult = (*ppPlugInInterface)->QueryInterface (ppPlugInInterface,
+ CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID), (void *) &(pDevice->interface));
+ if (S_OK != plugInResult)
+ HIDReportErrorNum ("CouldnÕt query HID class device interface from plugInInterface", plugInResult);
+ IODestroyPlugInInterface (ppPlugInInterface); // replace (*ppPlugInInterface)->Release (ppPlugInInterface)
+ }
+ else
+ HIDReportErrorNum ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", result);
+ }
+ if (NULL != pDevice->interface)
+ {
+ result = (*(IOHIDDeviceInterface**)pDevice->interface)->open (pDevice->interface, 0);
+ if (kIOReturnSuccess != result)
+ HIDReportErrorNum ("Failed to open pDevice->interface via open.", result);
+ }
+ return result;
+}
+
+// ---------------------------------
+// builds list of device with elements (allocates memory and captures devices)
+// list is allcoated internally within HID Utilites and can be accessed via accessor functions
+// structures within list are considered flat and user accessable, but not user modifiable
+// can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list)
+// returns true if succesful
+
+Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage)
+{
+ IOReturn result = kIOReturnSuccess;
+ mach_port_t masterPort = NULL;
+
+ 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);
+ }
+#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 chain
+
+void HIDReleaseDeviceList (void)
+{
+ while (NULL != gpDeviceList)
+ gpDeviceList = hid_DisposeDevice (gpDeviceList); // dispose current device return next device will set gpDeviceList to NULL
+ gNumDevices = 0;
+}
+
+// ---------------------------------
+// does a device list exist
+
+Boolean HIDHaveDeviceList (void)
+{
+ if (NULL != gpDeviceList)
+ return true;
+ return false;
+}
+
+// ---------------------------------
+// how many HID devices have been found
+// returns 0 if no device list exist
+
+UInt32 HIDCountDevices (void)
+{
+ gNumDevices = hid_CountCurrentDevices ();
+
+ return gNumDevices;
+}
+
+// ---------------------------------
+// how many elements does a specific device have
+// returns 0 if device is invlaid or NULL
+
+UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask)
+{
+ long count = 0;
+ if (HIDIsValidDevice(pDevice))
+ {
+ if (typeMask & kHIDElementTypeInput)
+ count += pDevice->inputs;
+ if (typeMask & kHIDElementTypeOutput)
+ count += pDevice->outputs;
+ if (typeMask & kHIDElementTypeFeature)
+ count += pDevice->features;
+ if (typeMask & kHIDElementTypeCollection)
+ count += pDevice->collections;
+ }
+ return count;
+}
+
+// ---------------------------------
+// get the first device in the device list
+// returns NULL if no list exists
+
+pRecDevice HIDGetFirstDevice (void)
+{
+ return gpDeviceList;
+}
+
+// ---------------------------------
+// get next device in list given current device as parameter
+// returns NULL if end of list
+
+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 NULL
+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 functionality
+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
+ pElement = pElement->pSibling; // element of interest
+ return hid_GetDeviceElement (pElement, typeMask); // otherwise return this element
+ }
+ }
+ return NULL;
+}
+
+// ---------------------------------
+// get previous element of given device in list given current element as parameter
+// this wlaks directly up the tree to the top element and does not search at each level
+// returns NULL if beginning of list
+// uses mask of HIDElementTypeMask to restrict element found
+// use kHIDElementTypeIO to get non-collection elements
+pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask)
+{
+ pRecElement pPreviousElement = pElement->pPrevious;
+ // walk back up tree to element prior
+ while (pPreviousElement && !hid_MatchElementTypeMask (pPreviousElement->type, typeMask))
+ {
+ pElement = pPreviousElement; // look at previous element
+ pPreviousElement = pElement->pPrevious;
+ }
+ return pPreviousElement; // return this element
+}
+
+// ---------------------------------
+// returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h)
+// returns "Unknown Type" for invalid types
+
+void HIDGetTypeName (IOHIDElementType theType, char * cstrName)
+{
+ switch (theType)
+ {
+ case kIOHIDElementTypeInput_Misc:
+ sprintf(cstrName, "Miscellaneous Input");
+ break;
+ case kIOHIDElementTypeInput_Button:
+ sprintf(cstrName, "Button Input");
+ break;
+ case kIOHIDElementTypeInput_Axis:
+ sprintf(cstrName, "Axis Input");
+ break;
+ case kIOHIDElementTypeInput_ScanCodes:
+ sprintf(cstrName, "Scan Code Input");
+ break;
+ case kIOHIDElementTypeOutput:
+ sprintf(cstrName, "Output");
+ break;
+ case kIOHIDElementTypeFeature:
+ sprintf(cstrName, "Feature");
+ break;
+ case kIOHIDElementTypeCollection:
+ sprintf(cstrName, "Collection");
+ break;
+ default:
+ sprintf(cstrName, "Unknown Type");
+ break;
+ }
+}
+
+// ---------------------------------
+// returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h)
+// returns usage page and usage values in string form for unknown values
+
+void HIDGetUsageName (const long valueUsagePage, const long valueUsage, char * cstrName)
+{
+ if (xml_GetUsageName(valueUsagePage, valueUsage, cstrName))
+ return;
+
+ switch (valueUsagePage)
+ {
+ case kHIDPage_Undefined:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Undefined Page, Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_GenericDesktop:
+ switch (valueUsage)
+ {
+ case kHIDUsage_GD_Pointer: sprintf (cstrName, "Pointer"); break;
+ case kHIDUsage_GD_Mouse: sprintf (cstrName, "Mouse"); break;
+ case kHIDUsage_GD_Joystick: sprintf (cstrName, "Joystick"); break;
+ case kHIDUsage_GD_GamePad: sprintf (cstrName, "GamePad"); break;
+ case kHIDUsage_GD_Keyboard: sprintf (cstrName, "Keyboard"); break;
+ case kHIDUsage_GD_Keypad: sprintf (cstrName, "Keypad"); break;
+ case kHIDUsage_GD_MultiAxisController: sprintf (cstrName, "Multi-Axis Controller"); break;
+
+ case kHIDUsage_GD_X: sprintf (cstrName, "X-Axis"); break;
+ case kHIDUsage_GD_Y: sprintf (cstrName, "Y-Axis"); break;
+ case kHIDUsage_GD_Z: sprintf (cstrName, "Z-Axis"); break;
+ case kHIDUsage_GD_Rx: sprintf (cstrName, "X-Rotation"); break;
+ case kHIDUsage_GD_Ry: sprintf (cstrName, "Y-Rotation"); break;
+ case kHIDUsage_GD_Rz: sprintf (cstrName, "Z-Rotation"); break;
+ case kHIDUsage_GD_Slider: sprintf (cstrName, "Slider"); break;
+ case kHIDUsage_GD_Dial: sprintf (cstrName, "Dial"); break;
+ case kHIDUsage_GD_Wheel: sprintf (cstrName, "Wheel"); break;
+ case kHIDUsage_GD_Hatswitch: sprintf (cstrName, "Hatswitch"); break;
+ case kHIDUsage_GD_CountedBuffer: sprintf (cstrName, "Counted Buffer"); break;
+ case kHIDUsage_GD_ByteCount: sprintf (cstrName, "Byte Count"); break;
+ case kHIDUsage_GD_MotionWakeup: sprintf (cstrName, "Motion Wakeup"); break;
+ case kHIDUsage_GD_Start: sprintf (cstrName, "Start"); break;
+ case kHIDUsage_GD_Select: sprintf (cstrName, "Select"); break;
+
+ case kHIDUsage_GD_Vx: sprintf (cstrName, "X-Velocity"); break;
+ case kHIDUsage_GD_Vy: sprintf (cstrName, "Y-Velocity"); break;
+ case kHIDUsage_GD_Vz: sprintf (cstrName, "Z-Velocity"); break;
+ case kHIDUsage_GD_Vbrx: sprintf (cstrName, "X-Rotation Velocity"); break;
+ case kHIDUsage_GD_Vbry: sprintf (cstrName, "Y-Rotation Velocity"); break;
+ case kHIDUsage_GD_Vbrz: sprintf (cstrName, "Z-Rotation Velocity"); break;
+ case kHIDUsage_GD_Vno: sprintf (cstrName, "Vno"); break;
+
+ case kHIDUsage_GD_SystemControl: sprintf (cstrName, "System Control"); break;
+ case kHIDUsage_GD_SystemPowerDown: sprintf (cstrName, "System Power Down"); break;
+ case kHIDUsage_GD_SystemSleep: sprintf (cstrName, "System Sleep"); break;
+ case kHIDUsage_GD_SystemWakeUp: sprintf (cstrName, "System Wake Up"); break;
+ case kHIDUsage_GD_SystemContextMenu: sprintf (cstrName, "System Context Menu"); break;
+ case kHIDUsage_GD_SystemMainMenu: sprintf (cstrName, "System Main Menu"); break;
+ case kHIDUsage_GD_SystemAppMenu: sprintf (cstrName, "System App Menu"); break;
+ case kHIDUsage_GD_SystemMenuHelp: sprintf (cstrName, "System Menu Help"); break;
+ case kHIDUsage_GD_SystemMenuExit: sprintf (cstrName, "System Menu Exit"); break;
+ case kHIDUsage_GD_SystemMenu: sprintf (cstrName, "System Menu"); break;
+ case kHIDUsage_GD_SystemMenuRight: sprintf (cstrName, "System Menu Right"); break;
+ case kHIDUsage_GD_SystemMenuLeft: sprintf (cstrName, "System Menu Left"); break;
+ case kHIDUsage_GD_SystemMenuUp: sprintf (cstrName, "System Menu Up"); break;
+ case kHIDUsage_GD_SystemMenuDown: sprintf (cstrName, "System Menu Down"); break;
+
+ case kHIDUsage_GD_DPadUp: sprintf (cstrName, "DPad Up"); break;
+ case kHIDUsage_GD_DPadDown: sprintf (cstrName, "DPad Down"); break;
+ case kHIDUsage_GD_DPadRight: sprintf (cstrName, "DPad Right"); break;
+ case kHIDUsage_GD_DPadLeft: sprintf (cstrName, "DPad Left"); break;
+
+ case kHIDUsage_GD_Reserved: sprintf (cstrName, "Reserved"); break;
+
+ default: sprintf (cstrName, "Generic Desktop Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Simulation:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Simulation Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_VR:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "VR Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Sport:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Sport Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Game:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Game Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_KeyboardOrKeypad:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Keyboard Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_LEDs:
+ switch (valueUsage)
+ {
+ // some LED usages
+ case kHIDUsage_LED_IndicatorRed: sprintf (cstrName, "Red LED"); break;
+ case kHIDUsage_LED_IndicatorGreen: sprintf (cstrName, "Green LED"); break;
+ case kHIDUsage_LED_IndicatorAmber: sprintf (cstrName, "Amber LED"); break;
+ case kHIDUsage_LED_GenericIndicator: sprintf (cstrName, "Generic LED"); break;
+ case kHIDUsage_LED_SystemSuspend: sprintf (cstrName, "System Suspend LED"); break;
+ case kHIDUsage_LED_ExternalPowerConnected: sprintf (cstrName, "External Power LED"); break;
+ default: sprintf (cstrName, "LED Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Button:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Button #%ld", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Ordinal:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Ordinal Instance %lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Telephony:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Telephony Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Consumer:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Consumer Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Digitizer:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Digitizer Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_PID:
+ if (((valueUsage >= 0x02) && (valueUsage <= 0x1F)) || ((valueUsage >= 0x29) && (valueUsage <= 0x2F)) ||
+ ((valueUsage >= 0x35) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x44) && (valueUsage <= 0x4F)) ||
+ (valueUsage == 0x8A) || (valueUsage == 0x93) || ((valueUsage >= 0x9D) && (valueUsage <= 0x9E)) ||
+ ((valueUsage >= 0xA1) && (valueUsage <= 0xA3)) || ((valueUsage >= 0xAD) && (valueUsage <= 0xFFFF)))
+ sprintf (cstrName, "PID Reserved");
+ else
+ switch (valueUsage)
+ {
+ case 0x00: sprintf (cstrName, "PID Undefined Usage"); break;
+ case kHIDUsage_PID_PhysicalInterfaceDevice: sprintf (cstrName, "Physical Interface Device"); break;
+ case kHIDUsage_PID_Normal: sprintf (cstrName, "Normal Force"); break;
+
+ case kHIDUsage_PID_SetEffectReport: sprintf (cstrName, "Set Effect Report"); break;
+ case kHIDUsage_PID_EffectBlockIndex: sprintf (cstrName, "Effect Block Index"); break;
+ case kHIDUsage_PID_ParamBlockOffset: sprintf (cstrName, "Parameter Block Offset"); break;
+ case kHIDUsage_PID_ROM_Flag: sprintf (cstrName, "ROM Flag"); break;
+
+ case kHIDUsage_PID_EffectType: sprintf (cstrName, "Effect Type"); break;
+ case kHIDUsage_PID_ET_ConstantForce: sprintf (cstrName, "Effect Type Constant Force"); break;
+ case kHIDUsage_PID_ET_Ramp: sprintf (cstrName, "Effect Type Ramp"); break;
+ case kHIDUsage_PID_ET_CustomForceData: sprintf (cstrName, "Effect Type Custom Force Data"); break;
+ case kHIDUsage_PID_ET_Square: sprintf (cstrName, "Effect Type Square"); break;
+ case kHIDUsage_PID_ET_Sine: sprintf (cstrName, "Effect Type Sine"); break;
+ case kHIDUsage_PID_ET_Triangle: sprintf (cstrName, "Effect Type Triangle"); break;
+ case kHIDUsage_PID_ET_SawtoothUp: sprintf (cstrName, "Effect Type Sawtooth Up"); break;
+ case kHIDUsage_PID_ET_SawtoothDown: sprintf (cstrName, "Effect Type Sawtooth Down"); break;
+ case kHIDUsage_PID_ET_Spring: sprintf (cstrName, "Effect Type Spring"); break;
+ case kHIDUsage_PID_ET_Damper: sprintf (cstrName, "Effect Type Damper"); break;
+ case kHIDUsage_PID_ET_Inertia: sprintf (cstrName, "Effect Type Inertia"); break;
+ case kHIDUsage_PID_ET_Friction: sprintf (cstrName, "Effect Type Friction"); break;
+ case kHIDUsage_PID_Duration: sprintf (cstrName, "Effect Duration"); break;
+ case kHIDUsage_PID_SamplePeriod: sprintf (cstrName, "Effect Sample Period"); break;
+ case kHIDUsage_PID_Gain: sprintf (cstrName, "Effect Gain"); break;
+ case kHIDUsage_PID_TriggerButton: sprintf (cstrName, "Effect Trigger Button"); break;
+ case kHIDUsage_PID_TriggerRepeatInterval: sprintf (cstrName, "Effect Trigger Repeat Interval"); break;
+
+ case kHIDUsage_PID_AxesEnable: sprintf (cstrName, "Axis Enable"); break;
+ case kHIDUsage_PID_DirectionEnable: sprintf (cstrName, "Direction Enable"); break;
+
+ case kHIDUsage_PID_Direction: sprintf (cstrName, "Direction"); break;
+
+ case kHIDUsage_PID_TypeSpecificBlockOffset: sprintf (cstrName, "Type Specific Block Offset"); break;
+
+ case kHIDUsage_PID_BlockType: sprintf (cstrName, "Block Type"); break;
+
+ case kHIDUsage_PID_SetEnvelopeReport: sprintf (cstrName, "Set Envelope Report"); break;
+ case kHIDUsage_PID_AttackLevel: sprintf (cstrName, "Envelope Attack Level"); break;
+ case kHIDUsage_PID_AttackTime: sprintf (cstrName, "Envelope Attack Time"); break;
+ case kHIDUsage_PID_FadeLevel: sprintf (cstrName, "Envelope Fade Level"); break;
+ case kHIDUsage_PID_FadeTime: sprintf (cstrName, "Envelope Fade Time"); break;
+
+ case kHIDUsage_PID_SetConditionReport: sprintf (cstrName, "Set Condition Report"); break;
+ case kHIDUsage_PID_CP_Offset: sprintf (cstrName, "Condition CP Offset"); break;
+ case kHIDUsage_PID_PositiveCoefficient: sprintf (cstrName, "Condition Positive Coefficient"); break;
+ case kHIDUsage_PID_NegativeCoefficient: sprintf (cstrName, "Condition Negative Coefficient"); break;
+ case kHIDUsage_PID_PositiveSaturation: sprintf (cstrName, "Condition Positive Saturation"); break;
+ case kHIDUsage_PID_NegativeSaturation: sprintf (cstrName, "Condition Negative Saturation"); break;
+ case kHIDUsage_PID_DeadBand: sprintf (cstrName, "Condition Dead Band"); break;
+
+ case kHIDUsage_PID_DownloadForceSample: sprintf (cstrName, "Download Force Sample"); break;
+ case kHIDUsage_PID_IsochCustomForceEnable: sprintf (cstrName, "Isoch Custom Force Enable"); break;
+
+ case kHIDUsage_PID_CustomForceDataReport: sprintf (cstrName, "Custom Force Data Report"); break;
+ case kHIDUsage_PID_CustomForceData: sprintf (cstrName, "Custom Force Data"); break;
+
+ case kHIDUsage_PID_CustomForceVendorDefinedData: sprintf (cstrName, "Custom Force Vendor Defined Data"); break;
+ case kHIDUsage_PID_SetCustomForceReport: sprintf (cstrName, "Set Custom Force Report"); break;
+ case kHIDUsage_PID_CustomForceDataOffset: sprintf (cstrName, "Custom Force Data Offset"); break;
+ case kHIDUsage_PID_SampleCount: sprintf (cstrName, "Custom Force Sample Count"); break;
+
+ case kHIDUsage_PID_SetPeriodicReport: sprintf (cstrName, "Set Periodic Report"); break;
+ case kHIDUsage_PID_Offset: sprintf (cstrName, "Periodic Offset"); break;
+ case kHIDUsage_PID_Magnitude: sprintf (cstrName, "Periodic Magnitude"); break;
+ case kHIDUsage_PID_Phase: sprintf (cstrName, "Periodic Phase"); break;
+ case kHIDUsage_PID_Period: sprintf (cstrName, "Periodic Period"); break;
+
+ case kHIDUsage_PID_SetConstantForceReport: sprintf (cstrName, "Set Constant Force Report"); break;
+
+ case kHIDUsage_PID_SetRampForceReport: sprintf (cstrName, "Set Ramp Force Report"); break;
+ case kHIDUsage_PID_RampStart: sprintf (cstrName, "Ramp Start"); break;
+ case kHIDUsage_PID_RampEnd: sprintf (cstrName, "Ramp End"); break;
+
+ case kHIDUsage_PID_EffectOperationReport: sprintf (cstrName, "Effect Operation Report"); break;
+
+ case kHIDUsage_PID_EffectOperation: sprintf (cstrName, "Effect Operation"); break;
+ case kHIDUsage_PID_OpEffectStart: sprintf (cstrName, "Op Effect Start"); break;
+ case kHIDUsage_PID_OpEffectStartSolo: sprintf (cstrName, "Op Effect Start Solo"); break;
+ case kHIDUsage_PID_OpEffectStop: sprintf (cstrName, "Op Effect Stop"); break;
+ case kHIDUsage_PID_LoopCount: sprintf (cstrName, "Op Effect Loop Count"); break;
+
+ case kHIDUsage_PID_DeviceGainReport: sprintf (cstrName, "Device Gain Report"); break;
+ case kHIDUsage_PID_DeviceGain: sprintf (cstrName, "Device Gain"); break;
+
+ case kHIDUsage_PID_PoolReport: sprintf (cstrName, "PID Pool Report"); break;
+ case kHIDUsage_PID_RAM_PoolSize: sprintf (cstrName, "RAM Pool Size"); break;
+ case kHIDUsage_PID_ROM_PoolSize: sprintf (cstrName, "ROM Pool Size"); break;
+ case kHIDUsage_PID_ROM_EffectBlockCount: sprintf (cstrName, "ROM Effect Block Count"); break;
+ case kHIDUsage_PID_SimultaneousEffectsMax: sprintf (cstrName, "Simultaneous Effects Max"); break;
+ case kHIDUsage_PID_PoolAlignment: sprintf (cstrName, "Pool Alignment"); break;
+
+ case kHIDUsage_PID_PoolMoveReport: sprintf (cstrName, "PID Pool Move Report"); break;
+ case kHIDUsage_PID_MoveSource: sprintf (cstrName, "Move Source"); break;
+ case kHIDUsage_PID_MoveDestination: sprintf (cstrName, "Move Destination"); break;
+ case kHIDUsage_PID_MoveLength: sprintf (cstrName, "Move Length"); break;
+
+ case kHIDUsage_PID_BlockLoadReport: sprintf (cstrName, "PID Block Load Report"); break;
+
+ case kHIDUsage_PID_BlockLoadStatus: sprintf (cstrName, "Block Load Status"); break;
+ case kHIDUsage_PID_BlockLoadSuccess: sprintf (cstrName, "Block Load Success"); break;
+ case kHIDUsage_PID_BlockLoadFull: sprintf (cstrName, "Block Load Full"); break;
+ case kHIDUsage_PID_BlockLoadError: sprintf (cstrName, "Block Load Error"); break;
+ case kHIDUsage_PID_BlockHandle: sprintf (cstrName, "Block Handle"); break;
+
+ case kHIDUsage_PID_BlockFreeReport: sprintf (cstrName, "PID Block Free Report"); break;
+
+ case kHIDUsage_PID_TypeSpecificBlockHandle: sprintf (cstrName, "Type Specific Block Handle"); break;
+
+ case kHIDUsage_PID_StateReport: sprintf (cstrName, "PID State Report"); break;
+ case kHIDUsage_PID_EffectPlaying: sprintf (cstrName, "Effect Playing"); break;
+
+ case kHIDUsage_PID_DeviceControlReport: sprintf (cstrName, "PID Device Control Report"); break;
+
+ case kHIDUsage_PID_DeviceControl: sprintf (cstrName, "PID Device Control"); break;
+ case kHIDUsage_PID_DC_EnableActuators: sprintf (cstrName, "Device Control Enable Actuators"); break;
+ case kHIDUsage_PID_DC_DisableActuators: sprintf (cstrName, "Device Control Disable Actuators"); break;
+ case kHIDUsage_PID_DC_StopAllEffects: sprintf (cstrName, "Device Control Stop All Effects"); break;
+ case kHIDUsage_PID_DC_DeviceReset: sprintf (cstrName, "Device Control Reset"); break;
+ case kHIDUsage_PID_DC_DevicePause: sprintf (cstrName, "Device Control Pause"); break;
+ case kHIDUsage_PID_DC_DeviceContinue: sprintf (cstrName, "Device Control Continue"); break;
+ case kHIDUsage_PID_DevicePaused: sprintf (cstrName, "Device Paused"); break;
+ case kHIDUsage_PID_ActuatorsEnabled: sprintf (cstrName, "Actuators Enabled"); break;
+ case kHIDUsage_PID_SafetySwitch: sprintf (cstrName, "Safety Switch"); break;
+ case kHIDUsage_PID_ActuatorOverrideSwitch: sprintf (cstrName, "Actuator Override Switch"); break;
+ case kHIDUsage_PID_ActuatorPower: sprintf (cstrName, "Actuator Power"); break;
+ case kHIDUsage_PID_StartDelay: sprintf (cstrName, "Start Delay"); break;
+
+ case kHIDUsage_PID_ParameterBlockSize: sprintf (cstrName, "Parameter Block Size"); break;
+ case kHIDUsage_PID_DeviceManagedPool: sprintf (cstrName, "Device Managed Pool"); break;
+ case kHIDUsage_PID_SharedParameterBlocks: sprintf (cstrName, "Shared Parameter Blocks"); break;
+
+ case kHIDUsage_PID_CreateNewEffectReport: sprintf (cstrName, "Create New Effect Report"); break;
+ case kHIDUsage_PID_RAM_PoolAvailable: sprintf (cstrName, "RAM Pool Available"); break;
+ default: sprintf (cstrName, "PID Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Unicode:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Unicode Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_PowerDevice:
+ if (((valueUsage >= 0x06) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x26) && (valueUsage <= 0x2F)) ||
+ ((valueUsage >= 0x39) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x48) && (valueUsage <= 0x4F)) ||
+ ((valueUsage >= 0x58) && (valueUsage <= 0x5F)) || (valueUsage == 0x6A) ||
+ ((valueUsage >= 0x74) && (valueUsage <= 0xFC)))
+ sprintf (cstrName, "Power Device Reserved");
+ else
+ switch (valueUsage)
+ {
+ case kHIDUsage_PD_Undefined: sprintf (cstrName, "Power Device Undefined Usage"); break;
+ case kHIDUsage_PD_iName: sprintf (cstrName, "Power Device Name Index"); break;
+ case kHIDUsage_PD_PresentStatus: sprintf (cstrName, "Power Device Present Status"); break;
+ case kHIDUsage_PD_ChangedStatus: sprintf (cstrName, "Power Device Changed Status"); break;
+ case kHIDUsage_PD_UPS: sprintf (cstrName, "Uninterruptible Power Supply"); break;
+ case kHIDUsage_PD_PowerSupply: sprintf (cstrName, "Power Supply"); break;
+
+ case kHIDUsage_PD_BatterySystem: sprintf (cstrName, "Battery System Power Module"); break;
+ case kHIDUsage_PD_BatterySystemID: sprintf (cstrName, "Battery System ID"); break;
+ case kHIDUsage_PD_Battery: sprintf (cstrName, "Battery"); break;
+ case kHIDUsage_PD_BatteryID: sprintf (cstrName, "Battery ID"); break;
+ case kHIDUsage_PD_Charger: sprintf (cstrName, "Charger"); break;
+ case kHIDUsage_PD_ChargerID: sprintf (cstrName, "Charger ID"); break;
+ case kHIDUsage_PD_PowerConverter: sprintf (cstrName, "Power Converter Power Module"); break;
+ case kHIDUsage_PD_PowerConverterID: sprintf (cstrName, "Power Converter ID"); break;
+ case kHIDUsage_PD_OutletSystem: sprintf (cstrName, "Outlet System power module"); break;
+ case kHIDUsage_PD_OutletSystemID: sprintf (cstrName, "Outlet System ID"); break;
+ case kHIDUsage_PD_Input: sprintf (cstrName, "Power Device Input"); break;
+ case kHIDUsage_PD_InputID: sprintf (cstrName, "Power Device Input ID"); break;
+ case kHIDUsage_PD_Output: sprintf (cstrName, "Power Device Output"); break;
+ case kHIDUsage_PD_OutputID: sprintf (cstrName, "Power Device Output ID"); break;
+ case kHIDUsage_PD_Flow: sprintf (cstrName, "Power Device Flow"); break;
+ case kHIDUsage_PD_FlowID: sprintf (cstrName, "Power Device Flow ID"); break;
+ case kHIDUsage_PD_Outlet: sprintf (cstrName, "Power Device Outlet"); break;
+ case kHIDUsage_PD_OutletID: sprintf (cstrName, "Power Device Outlet ID"); break;
+ case kHIDUsage_PD_Gang: sprintf (cstrName, "Power Device Gang"); break;
+ case kHIDUsage_PD_GangID: sprintf (cstrName, "Power Device Gang ID"); break;
+ case kHIDUsage_PD_PowerSummary: sprintf (cstrName, "Power Device Power Summary"); break;
+ case kHIDUsage_PD_PowerSummaryID: sprintf (cstrName, "Power Device Power Summary ID"); break;
+
+ case kHIDUsage_PD_Voltage: sprintf (cstrName, "Power Device Voltage"); break;
+ case kHIDUsage_PD_Current: sprintf (cstrName, "Power Device Current"); break;
+ case kHIDUsage_PD_Frequency: sprintf (cstrName, "Power Device Frequency"); break;
+ case kHIDUsage_PD_ApparentPower: sprintf (cstrName, "Power Device Apparent Power"); break;
+ case kHIDUsage_PD_ActivePower: sprintf (cstrName, "Power Device RMS Power"); break;
+ case kHIDUsage_PD_PercentLoad: sprintf (cstrName, "Power Device Percent Load"); break;
+ case kHIDUsage_PD_Temperature: sprintf (cstrName, "Power Device Temperature"); break;
+ case kHIDUsage_PD_Humidity: sprintf (cstrName, "Power Device Humidity"); break;
+ case kHIDUsage_PD_BadCount: sprintf (cstrName, "Power Device Bad Condition Count"); break;
+
+ case kHIDUsage_PD_ConfigVoltage: sprintf (cstrName, "Power Device Nominal Voltage"); break;
+ case kHIDUsage_PD_ConfigCurrent: sprintf (cstrName, "Power Device Nominal Current"); break;
+ case kHIDUsage_PD_ConfigFrequency: sprintf (cstrName, "Power Device Nominal Frequency"); break;
+ case kHIDUsage_PD_ConfigApparentPower: sprintf (cstrName, "Power Device Nominal Apparent Power"); break;
+ case kHIDUsage_PD_ConfigActivePower: sprintf (cstrName, "Power Device Nominal RMS Power"); break;
+ case kHIDUsage_PD_ConfigPercentLoad: sprintf (cstrName, "Power Device Nominal Percent Load"); break;
+ case kHIDUsage_PD_ConfigTemperature: sprintf (cstrName, "Power Device Nominal Temperature"); break;
+
+ case kHIDUsage_PD_ConfigHumidity: sprintf (cstrName, "Power Device Nominal Humidity"); break;
+ case kHIDUsage_PD_SwitchOnControl: sprintf (cstrName, "Power Device Switch On Control"); break;
+ case kHIDUsage_PD_SwitchOffControl: sprintf (cstrName, "Power Device Switch Off Control"); break;
+ case kHIDUsage_PD_ToggleControl: sprintf (cstrName, "Power Device Toogle Sequence Control"); break;
+ case kHIDUsage_PD_LowVoltageTransfer: sprintf (cstrName, "Power Device Min Transfer Voltage"); break;
+ case kHIDUsage_PD_HighVoltageTransfer: sprintf (cstrName, "Power Device Max Transfer Voltage"); break;
+ case kHIDUsage_PD_DelayBeforeReboot: sprintf (cstrName, "Power Device Delay Before Reboot"); break;
+ case kHIDUsage_PD_DelayBeforeStartup: sprintf (cstrName, "Power Device Delay Before Startup"); break;
+ case kHIDUsage_PD_DelayBeforeShutdown: sprintf (cstrName, "Power Device Delay Before Shutdown"); break;
+ case kHIDUsage_PD_Test: sprintf (cstrName, "Power Device Test Request/Result"); break;
+ case kHIDUsage_PD_ModuleReset: sprintf (cstrName, "Power Device Reset Request/Result"); break;
+ case kHIDUsage_PD_AudibleAlarmControl: sprintf (cstrName, "Power Device Audible Alarm Control"); break;
+
+ case kHIDUsage_PD_Present: sprintf (cstrName, "Power Device Present"); break;
+ case kHIDUsage_PD_Good: sprintf (cstrName, "Power Device Good"); break;
+ case kHIDUsage_PD_InternalFailure: sprintf (cstrName, "Power Device Internal Failure"); break;
+ case kHIDUsage_PD_VoltageOutOfRange: sprintf (cstrName, "Power Device Voltage Out Of Range"); break;
+ case kHIDUsage_PD_FrequencyOutOfRange: sprintf (cstrName, "Power Device Frequency Out Of Range"); break;
+ case kHIDUsage_PD_Overload: sprintf (cstrName, "Power Device Overload"); break;
+ case kHIDUsage_PD_OverCharged: sprintf (cstrName, "Power Device Over Charged"); break;
+ case kHIDUsage_PD_OverTemperature: sprintf (cstrName, "Power Device Over Temperature"); break;
+ case kHIDUsage_PD_ShutdownRequested: sprintf (cstrName, "Power Device Shutdown Requested"); break;
+
+ case kHIDUsage_PD_ShutdownImminent: sprintf (cstrName, "Power Device Shutdown Imminent"); break;
+ case kHIDUsage_PD_SwitchOnOff: sprintf (cstrName, "Power Device On/Off Switch Status"); break;
+ case kHIDUsage_PD_Switchable: sprintf (cstrName, "Power Device Switchable"); break;
+ case kHIDUsage_PD_Used: sprintf (cstrName, "Power Device Used"); break;
+ case kHIDUsage_PD_Boost: sprintf (cstrName, "Power Device Boosted"); break;
+ case kHIDUsage_PD_Buck: sprintf (cstrName, "Power Device Bucked"); break;
+ case kHIDUsage_PD_Initialized: sprintf (cstrName, "Power Device Initialized"); break;
+ case kHIDUsage_PD_Tested: sprintf (cstrName, "Power Device Tested"); break;
+ case kHIDUsage_PD_AwaitingPower: sprintf (cstrName, "Power Device Awaiting Power"); break;
+ case kHIDUsage_PD_CommunicationLost: sprintf (cstrName, "Power Device Communication Lost"); break;
+
+ case kHIDUsage_PD_iManufacturer: sprintf (cstrName, "Power Device Manufacturer String Index"); break;
+ case kHIDUsage_PD_iProduct: sprintf (cstrName, "Power Device Product String Index"); break;
+ case kHIDUsage_PD_iserialNumber: sprintf (cstrName, "Power Device Serial Number String Index"); break;
+ default: sprintf (cstrName, "Power Device Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_BatterySystem:
+ if (((valueUsage >= 0x0A) && (valueUsage <= 0x0F)) || ((valueUsage >= 0x1E) && (valueUsage <= 0x27)) ||
+ ((valueUsage >= 0x30) && (valueUsage <= 0x3F)) || ((valueUsage >= 0x4C) && (valueUsage <= 0x5F)) ||
+ ((valueUsage >= 0x6C) && (valueUsage <= 0x7F)) || ((valueUsage >= 0x90) && (valueUsage <= 0xBF)) ||
+ ((valueUsage >= 0xC3) && (valueUsage <= 0xCF)) || ((valueUsage >= 0xDD) && (valueUsage <= 0xEF)) ||
+ ((valueUsage >= 0xF2) && (valueUsage <= 0xFF)))
+ sprintf (cstrName, "Power Device Reserved");
+ else
+ switch (valueUsage)
+ {
+ case kHIDUsage_BS_Undefined: sprintf (cstrName, "Battery System Undefined"); break;
+ case kHIDUsage_BS_SMBBatteryMode: sprintf (cstrName, "SMB Mode"); break;
+ case kHIDUsage_BS_SMBBatteryStatus: sprintf (cstrName, "SMB Status"); break;
+ case kHIDUsage_BS_SMBAlarmWarning: sprintf (cstrName, "SMB Alarm Warning"); break;
+ case kHIDUsage_BS_SMBChargerMode: sprintf (cstrName, "SMB Charger Mode"); break;
+ case kHIDUsage_BS_SMBChargerStatus: sprintf (cstrName, "SMB Charger Status"); break;
+ case kHIDUsage_BS_SMBChargerSpecInfo: sprintf (cstrName, "SMB Charger Extended Status"); break;
+ case kHIDUsage_BS_SMBSelectorState: sprintf (cstrName, "SMB Selector State"); break;
+ case kHIDUsage_BS_SMBSelectorPresets: sprintf (cstrName, "SMB Selector Presets"); break;
+ case kHIDUsage_BS_SMBSelectorInfo: sprintf (cstrName, "SMB Selector Info"); break;
+ case kHIDUsage_BS_OptionalMfgFunction1: sprintf (cstrName, "Battery System Optional SMB Mfg Function 1"); break;
+ case kHIDUsage_BS_OptionalMfgFunction2: sprintf (cstrName, "Battery System Optional SMB Mfg Function 2"); break;
+ case kHIDUsage_BS_OptionalMfgFunction3: sprintf (cstrName, "Battery System Optional SMB Mfg Function 3"); break;
+ case kHIDUsage_BS_OptionalMfgFunction4: sprintf (cstrName, "Battery System Optional SMB Mfg Function 4"); break;
+ case kHIDUsage_BS_OptionalMfgFunction5: sprintf (cstrName, "Battery System Optional SMB Mfg Function 5"); break;
+ case kHIDUsage_BS_ConnectionToSMBus: sprintf (cstrName, "Battery System Connection To System Management Bus"); break;
+ case kHIDUsage_BS_OutputConnection: sprintf (cstrName, "Battery System Output Connection Status"); break;
+ case kHIDUsage_BS_ChargerConnection: sprintf (cstrName, "Battery System Charger Connection"); break;
+ case kHIDUsage_BS_BatteryInsertion: sprintf (cstrName, "Battery System Battery Insertion"); break;
+ case kHIDUsage_BS_Usenext: sprintf (cstrName, "Battery System Use Next"); break;
+ case kHIDUsage_BS_OKToUse: sprintf (cstrName, "Battery System OK To Use"); break;
+ case kHIDUsage_BS_BatterySupported: sprintf (cstrName, "Battery System Battery Supported"); break;
+ case kHIDUsage_BS_SelectorRevision: sprintf (cstrName, "Battery System Selector Revision"); break;
+ case kHIDUsage_BS_ChargingIndicator: sprintf (cstrName, "Battery System Charging Indicator"); break;
+ case kHIDUsage_BS_ManufacturerAccess: sprintf (cstrName, "Battery System Manufacturer Access"); break;
+ case kHIDUsage_BS_RemainingCapacityLimit: sprintf (cstrName, "Battery System Remaining Capacity Limit"); break;
+ case kHIDUsage_BS_RemainingTimeLimit: sprintf (cstrName, "Battery System Remaining Time Limit"); break;
+ case kHIDUsage_BS_AtRate: sprintf (cstrName, "Battery System At Rate..."); break;
+ case kHIDUsage_BS_CapacityMode: sprintf (cstrName, "Battery System Capacity Mode"); break;
+ case kHIDUsage_BS_BroadcastToCharger: sprintf (cstrName, "Battery System Broadcast To Charger"); break;
+ case kHIDUsage_BS_PrimaryBattery: sprintf (cstrName, "Battery System Primary Battery"); break;
+ case kHIDUsage_BS_ChargeController: sprintf (cstrName, "Battery System Charge Controller"); break;
+ case kHIDUsage_BS_TerminateCharge: sprintf (cstrName, "Battery System Terminate Charge"); break;
+ case kHIDUsage_BS_TerminateDischarge: sprintf (cstrName, "Battery System Terminate Discharge"); break;
+ case kHIDUsage_BS_BelowRemainingCapacityLimit: sprintf (cstrName, "Battery System Below Remaining Capacity Limit"); break;
+ case kHIDUsage_BS_RemainingTimeLimitExpired: sprintf (cstrName, "Battery System Remaining Time Limit Expired"); break;
+ case kHIDUsage_BS_Charging: sprintf (cstrName, "Battery System Charging"); break;
+ case kHIDUsage_BS_Discharging: sprintf (cstrName, "Battery System Discharging"); break;
+ case kHIDUsage_BS_FullyCharged: sprintf (cstrName, "Battery System Fully Charged"); break;
+ case kHIDUsage_BS_FullyDischarged: sprintf (cstrName, "Battery System Fully Discharged"); break;
+ case kHIDUsage_BS_ConditioningFlag: sprintf (cstrName, "Battery System Conditioning Flag"); break;
+ case kHIDUsage_BS_AtRateOK: sprintf (cstrName, "Battery System At Rate OK"); break;
+ case kHIDUsage_BS_SMBErrorCode: sprintf (cstrName, "Battery System SMB Error Code"); break;
+ case kHIDUsage_BS_NeedReplacement: sprintf (cstrName, "Battery System Need Replacement"); break;
+ case kHIDUsage_BS_AtRateTimeToFull: sprintf (cstrName, "Battery System At Rate Time To Full"); break;
+ case kHIDUsage_BS_AtRateTimeToEmpty: sprintf (cstrName, "Battery System At Rate Time To Empty"); break;
+ case kHIDUsage_BS_AverageCurrent: sprintf (cstrName, "Battery System Average Current"); break;
+ case kHIDUsage_BS_Maxerror: sprintf (cstrName, "Battery System Max Error"); break;
+ case kHIDUsage_BS_RelativeStateOfCharge: sprintf (cstrName, "Battery System Relative State Of Charge"); break;
+ case kHIDUsage_BS_AbsoluteStateOfCharge: sprintf (cstrName, "Battery System Absolute State Of Charge"); break;
+ case kHIDUsage_BS_RemainingCapacity: sprintf (cstrName, "Battery System Remaining Capacity"); break;
+ case kHIDUsage_BS_FullChargeCapacity: sprintf (cstrName, "Battery System Full Charge Capacity"); break;
+ case kHIDUsage_BS_RunTimeToEmpty: sprintf (cstrName, "Battery System Run Time To Empty"); break;
+ case kHIDUsage_BS_AverageTimeToEmpty: sprintf (cstrName, "Battery System Average Time To Empty"); break;
+ case kHIDUsage_BS_AverageTimeToFull: sprintf (cstrName, "Battery System Average Time To Full"); break;
+ case kHIDUsage_BS_CycleCount: sprintf (cstrName, "Battery System Cycle Count"); break;
+ case kHIDUsage_BS_BattPackModelLevel: sprintf (cstrName, "Battery System Batt Pack Model Level"); break;
+ case kHIDUsage_BS_InternalChargeController: sprintf (cstrName, "Battery System Internal Charge Controller"); break;
+ case kHIDUsage_BS_PrimaryBatterySupport: sprintf (cstrName, "Battery System Primary Battery Support"); break;
+ case kHIDUsage_BS_DesignCapacity: sprintf (cstrName, "Battery System Design Capacity"); break;
+ case kHIDUsage_BS_SpecificationInfo: sprintf (cstrName, "Battery System Specification Info"); break;
+ case kHIDUsage_BS_ManufacturerDate: sprintf (cstrName, "Battery System Manufacturer Date"); break;
+ case kHIDUsage_BS_SerialNumber: sprintf (cstrName, "Battery System Serial Number"); break;
+ case kHIDUsage_BS_iManufacturerName: sprintf (cstrName, "Battery System Manufacturer Name Index"); break;
+ case kHIDUsage_BS_iDevicename: sprintf (cstrName, "Battery System Device Name Index"); break;
+ case kHIDUsage_BS_iDeviceChemistry: sprintf (cstrName, "Battery System Device Chemistry Index"); break;
+ case kHIDUsage_BS_ManufacturerData: sprintf (cstrName, "Battery System Manufacturer Data"); break;
+ case kHIDUsage_BS_Rechargable: sprintf (cstrName, "Battery System Rechargable"); break;
+ case kHIDUsage_BS_WarningCapacityLimit: sprintf (cstrName, "Battery System Warning Capacity Limit"); break;
+ case kHIDUsage_BS_CapacityGranularity1: sprintf (cstrName, "Battery System Capacity Granularity 1"); break;
+ case kHIDUsage_BS_CapacityGranularity2: sprintf (cstrName, "Battery System Capacity Granularity 2"); break;
+ case kHIDUsage_BS_iOEMInformation: sprintf (cstrName, "Battery System OEM Information Index"); break;
+ case kHIDUsage_BS_InhibitCharge: sprintf (cstrName, "Battery System Inhibit Charge"); break;
+ case kHIDUsage_BS_EnablePolling: sprintf (cstrName, "Battery System Enable Polling"); break;
+ case kHIDUsage_BS_ResetToZero: sprintf (cstrName, "Battery System Reset To Zero"); break;
+ case kHIDUsage_BS_ACPresent: sprintf (cstrName, "Battery System AC Present"); break;
+ case kHIDUsage_BS_BatteryPresent: sprintf (cstrName, "Battery System Battery Present"); break;
+ case kHIDUsage_BS_PowerFail: sprintf (cstrName, "Battery System Power Fail"); break;
+ case kHIDUsage_BS_AlarmInhibited: sprintf (cstrName, "Battery System Alarm Inhibited"); break;
+ case kHIDUsage_BS_ThermistorUnderRange: sprintf (cstrName, "Battery System Thermistor Under Range"); break;
+ case kHIDUsage_BS_ThermistorHot: sprintf (cstrName, "Battery System Thermistor Hot"); break;
+ case kHIDUsage_BS_ThermistorCold: sprintf (cstrName, "Battery System Thermistor Cold"); break;
+ case kHIDUsage_BS_ThermistorOverRange: sprintf (cstrName, "Battery System Thermistor Over Range"); break;
+ case kHIDUsage_BS_VoltageOutOfRange: sprintf (cstrName, "Battery System Voltage Out Of Range"); break;
+ case kHIDUsage_BS_CurrentOutOfRange: sprintf (cstrName, "Battery System Current Out Of Range"); break;
+ case kHIDUsage_BS_CurrentNotRegulated: sprintf (cstrName, "Battery System Current Not Regulated"); break;
+ case kHIDUsage_BS_VoltageNotRegulated: sprintf (cstrName, "Battery System Voltage Not Regulated"); break;
+ case kHIDUsage_BS_MasterMode: sprintf (cstrName, "Battery System Master Mode"); break;
+ case kHIDUsage_BS_ChargerSelectorSupport: sprintf (cstrName, "Battery System Charger Support Selector"); break;
+ case kHIDUsage_BS_ChargerSpec: sprintf (cstrName, "attery System Charger Specification"); break;
+ case kHIDUsage_BS_Level2: sprintf (cstrName, "Battery System Charger Level 2"); break;
+ case kHIDUsage_BS_Level3: sprintf (cstrName, "Battery System Charger Level 3"); break;
+ default: sprintf (cstrName, "Battery System Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_AlphanumericDisplay:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Alphanumeric Display Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_BarCodeScanner:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Bar Code Scanner Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Scale:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Scale Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_CameraControl:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Camera Control Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ case kHIDPage_Arcade:
+ switch (valueUsage)
+ {
+ default: sprintf (cstrName, "Arcade Usage 0x%lx", valueUsage); break;
+ }
+ break;
+ default:
+ if (valueUsagePage > kHIDPage_VendorDefinedStart)
+ sprintf (cstrName, "Vendor Defined Usage 0x%lx", valueUsage);
+ else
+ sprintf (cstrName, "Page: 0x%lx, Usage: 0x%lx", valueUsagePage, valueUsage);
+ break;
+ }
+}
+
+// ---------------------------------
+// returns calibrated value given raw value passed in
+// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values
+/*
+SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement)
+{
+ if (NULL != pElement)
+ {
+ float deviceScale = pElement->max - pElement->min;
+ float readScale = pElement->calMax - pElement->calMin;
+ if (readScale == 0)
+ return value; // no scaling as
+ else
+ return ((value - pElement->calMin) * deviceScale / readScale) + pElement->min;
+ }
+ else
+ return 0; // bad element passed in
+}
+*/
+// ---------------------------------
+// returns scaled value given raw value passed in
+// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values
+
+SInt32 HIDScaleValue (SInt32 value, pRecElement pElement)
+{
+ float deviceScale = pElement->userMax - pElement->userMin;
+ float readScale = pElement->max - pElement->min;
+ if (readScale == 0)
+ return value;
+ else
+ return (value - pElement->min) * deviceScale / readScale + pElement->userMin;
+}
+
+// ---------------------------------
+// convert an element type to a mask
+HIDElementTypeMask HIDConvertElementTypeToMask (const long type)
+{
+ HIDElementTypeMask result = kHIDElementTypeAll;
+
+ switch (type)
+ {
+ case kIOHIDElementTypeInput_Misc:
+ case kIOHIDElementTypeInput_Button:
+ case kIOHIDElementTypeInput_Axis:
+ case kIOHIDElementTypeInput_ScanCodes:
+ result = kHIDElementTypeInput;
+ break;
+ case kIOHIDElementTypeOutput:
+ result = kHIDElementTypeOutput;
+ break;
+ case kIOHIDElementTypeFeature:
+ result = kHIDElementTypeFeature;
+ break;
+ case kIOHIDElementTypeCollection:
+ result = kHIDElementTypeCollection;
+ break;
+ default:
+ result = kHIDElementTypeAll;
+ break;
+ }
+ return result;
+}
+
+Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice)
+{
+ pRecDevice pDevice, pBestDevice = NULL;
+ long bestScore = 0;
+
+ // iterate over all devices
+ pDevice = HIDGetFirstDevice();
+ while (pDevice)
+ {
+ long deviceScore = 1;
+
+ if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID))
+ {
+ deviceScore += 10;
+ if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID))
+ deviceScore += 8;
+ }
+
+ if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) &&
+ (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage)))
+ deviceScore += 9;
+
+ if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID))
+ deviceScore += 5;
+
+ if (deviceScore > bestScore)
+ {
+ pBestDevice = pDevice;
+ bestScore = deviceScore;
+#if 0 // set true to output scoring informaton
+ printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score);
+ HIDPrintElement(pBestElement);
+#endif
+ }
+ pDevice = HIDGetNextDevice(pDevice);
+ }
+
+ if (NULL != pBestDevice)
+ {
+ *ppFoundDevice = pBestDevice;
+#if 0 // set true to output scoring informaton
+ printf("\n-HIDFindDevice(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore);
+ HIDPrintElement(pBestElement);
+ printf("\n");
+#endif
+ return true;
+ }
+ else
+ return false;
+}
+
+// ---------------------------------
+// find the device and element for this action
+// Device: serial, vendorID, productID, location, usagePage, usage
+// Element: cookie, usagePage, usage,
+
+Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement,
+ pRecDevice *ppFoundDevice, pRecElement *ppFoundElement)
+{
+ pRecDevice pDevice, pBestDevice = NULL;
+ pRecElement pElement, pBestElement = NULL;
+ HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type);
+ long bestScore = 0;
+
+ // iterate over all devices
+ pDevice = HIDGetFirstDevice();
+ while (pDevice)
+ {
+ long deviceScore = 1;
+
+ if (pSearchDevice->vendorID && (pSearchDevice->vendorID == pDevice->vendorID))
+ {
+ deviceScore += 10;
+ if (pSearchDevice->productID && (pSearchDevice->productID == pDevice->productID))
+ deviceScore += 8;
+ }
+ if ((pSearchDevice->usagePage && (pSearchDevice->usagePage == pDevice->usagePage)) &&
+ (pSearchDevice->usage && (pSearchDevice->usage == pDevice->usage)))
+ deviceScore += 9;
+
+ if (pSearchDevice->locID && (pSearchDevice->locID == pDevice->locID))
+ deviceScore += 5;
+
+ // iterate over all elements of this device
+ pElement = HIDGetFirstDeviceElement(pDevice, hidMask);
+ while (pElement)
+ {
+ long score = deviceScore;
+
+ if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) &&
+ (pSearchElement->usage && (pSearchElement->usage == pElement->usage)))
+ {
+ score += 5;
+
+ if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie))
+ score += 4;
+ }
+ else
+ score = 0;
+#if 0 // set true to output scoring informaton
+ if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here
+ {
+ printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score);
+ HIDPrintElement(pElement);
+ }
+#endif
+ if (score > bestScore)
+ {
+ pBestDevice = pDevice;
+ pBestElement = pElement;
+ bestScore = score;
+#if 0 // set true to output scoring informaton
+ printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score);
+ HIDPrintElement(pBestElement);
+#endif
+ }
+ pElement = HIDGetNextDeviceElement(pElement, hidMask);
+ }
+ pDevice = HIDGetNextDevice(pDevice);
+ }
+
+ if ((NULL != pBestDevice) || (NULL != pBestElement))
+ {
+ *ppFoundDevice = pBestDevice;
+ *ppFoundElement = pBestElement;
+#if 0 // set true to output scoring informaton
+ printf("\n-HIDFindActionDeviceAndElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore);
+ HIDPrintElement(pBestElement);
+ printf("\n");
+#endif
+ return true;
+ }
+ else
+ return false;
+}
+
+// ---------------------------------
+// find the device and element for this action
+// Device: serial, vendorID, productID, location, usagePage, usage
+// Element: cookie, usagePage, usage,
+
+Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement)
+{
+ pRecElement pElement, pBestElement = NULL;
+ HIDElementTypeMask hidMask = HIDConvertElementTypeToMask (pSearchElement->type);
+ long bestScore = 0;
+
+ if ((NULL == pStartElement) || (NULL == pSearchElement) || (NULL == ppFoundElement))
+ return false;
+
+ // iterate over all children of this element
+ pElement = pStartElement->pChild;
+
+ while (pElement)
+ {
+ long score = 0;
+#if 0 // set true to output searching informaton
+ printf("\n-HIDFindSubElement, search = {t:%.2lX, u:%.4lX:%.4lX}, match = {t:%.2lX, u:%.4lX:%.4lX, s:\"%s\"}",
+ pSearchElement->type, pSearchElement->usagePage, pSearchElement->usage,
+ pElement->type, pElement->usagePage, pElement->usage, pElement->name);
+ fflush(stdout);
+#endif
+ if ((pSearchElement->usagePage && (pSearchElement->usagePage == pElement->usagePage)) && (pSearchElement->usage && (pSearchElement->usage == pElement->usage)))
+ {
+ score += 4;
+ if (pSearchElement->cookie && (pSearchElement->cookie == pElement->cookie))
+ score += 5;
+ }
+#if 0 // set true to output searching informaton
+ if (kHIDPage_KeyboardOrKeypad != pElement->usagePage) // skip keyboards here
+ {
+ printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score);
+ HIDPrintElement(pElement);
+ }
+#endif
+
+ if (score > bestScore)
+ {
+ pBestElement = pElement;
+ bestScore = score;
+#if 0 // set true to output searching informaton
+ printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, better score: %ld.",pSearchElement->usagePage, pSearchElement->usage, score);
+ HIDPrintElement(pBestElement);
+#endif
+ }
+ pElement = HIDGetNextDeviceElement(pElement, hidMask);
+ }
+#if 0 // set true to output searching informaton
+ if (pBestElement)
+ {
+ printf("\n-HIDFindSubElement(%ld:%ld)-I-Debug, best score: %ld.",pSearchElement->usagePage, pSearchElement->usage, bestScore);
+ HIDPrintElement(pBestElement);
+ printf("\n");
+ }
+#endif
+
+ *ppFoundElement = pBestElement;
+ return (NULL != pBestElement);
+}
+
+// print out all of an elements information
+int HIDPrintElement(const pRecElement pElement)
+{
+ int results;
+ int count;
+
+ printf("\n");
+
+ if (gDepth != pElement->depth)
+ printf("%d",gDepth);
+ for (count = 0;count < pElement->depth;count++)
+ printf(" | ");
+
+#if 0 // this is verbose
+ results =
+ printf("-HIDPrintElement = {name: \"%s\", t: 0x%.2lX, u:%ld:%ld, c: %ld, min/max: %ld/%ld, scaled: %ld/%ld, size: %ld, rel: %s, wrap: %s, nonLinear: %s, preferred: %s, nullState: %s, units: %ld, exp: %ld, cal: %ld/%ld, user: %ld/%ld, depth: %ld}.",
+ pElement->name, // name of element (c string)
+ pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h
+ pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage
+ pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage
+ (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change
+ pElement->min, // reported min value possible
+ pElement->max, // reported max value possible
+ pElement->scaledMin, // reported scaled min value possible
+ pElement->scaledMax, // reported scaled max value possible
+ pElement->size, // size in bits of data return from element
+ pElement->relative ? "YES" : "NO", // are reports relative to last report (deltas)
+ pElement->wrapping ? "YES" : "NO", // does element wrap around (one value higher than max is min)
+ pElement->nonLinear ? "YES" : "NO", // are the values reported non-linear relative to element movement
+ pElement->preferredState ? "YES" : "NO",// does element have a preferred state (such as a button)
+ pElement->nullState ? "YES" : "NO", // does element have null state
+ pElement->units, // units value is reported in (not used very often)
+ pElement->unitExp, // exponent for units (also not used very often)
+ pElement->calMin, // min returned value (for calibrate call)
+ pElement->calMax, // max returned value
+ pElement->userMin, // user set min to scale to (for scale call)
+ pElement->userMax, // user set max
+ pElement->depth
+ );
+#else // this is brief
+ results =
+ printf("-HIDPrintElement = {t: 0x%lX, u:%ld:%ld, c: %ld, name: \"%s\", d: %ld}.",
+ pElement->type, // the type defined by IOHIDElementType in IOHIDKeys.h
+ pElement->usagePage, // usage page from IOUSBHIDParser.h which defines general usage
+ pElement->usage, // usage within above page from IOUSBHIDParser.h which defines specific usage
+ (long) pElement->cookie, // unique value (within device of specific vendorID and productID) which identifies element, will NOT change
+ pElement->name, // name of element (c string)
+ pElement->depth
+ );
+#endif
+ fflush(stdout);
+ return results;
+}
+
+// return true if this is a valid device pointer
+Boolean HIDIsValidDevice(const pRecDevice pSearchDevice)
+{
+ pRecDevice pDevice = gpDeviceList;
+
+ while (pDevice)
+ {
+ if (pDevice == pSearchDevice)
+ return true;
+ pDevice = pDevice->pNext;
+ }
+ return false;
+}
+
+// return true if this is a valid element pointer for this device
+Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement)
+{
+ if (HIDIsValidDevice(pSearchDevice))
+ {
+ pRecElement pRecElementTemp = HIDGetFirstDeviceElement(pSearchDevice,kHIDElementTypeAll);
+ while (pRecElementTemp)
+ {
+ if (pRecElementTemp == pSearchElement)
+ return true;
+ pRecElementTemp = HIDGetNextDeviceElement(pRecElementTemp,kHIDElementTypeAll);
+ }
+ }
+ return false;
+}
diff --git a/HID_Utilities_Source/HID_Utilities.h b/HID_Utilities_Source/HID_Utilities.h
new file mode 100644
index 0000000..e8565ce
--- /dev/null
+++ b/HID_Utilities_Source/HID_Utilities.h
@@ -0,0 +1,256 @@
+/*
+ File: HID_Utilities.h
+
+ Contains: External interface for HID Utilities
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#ifndef _HID_Utilities_h_
+#define _HID_Utilities_h_
+
+#include <Carbon/Carbon.h>
+
+#include <IOKit/IOTypes.h>
+// 10.0.x
+//#include <IOKit/IOUSBHIDParser.h>
+// 10.1.x
+#include <IOKit/hid/IOHIDUsageTables.h>
+
+#include <IOKit/hid/IOHIDLib.h>
+
+// ==================================
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ==================================
+
+enum
+{
+ kDefaultUserMin = 0, // default user min and max used for scaling
+ kDefaultUserMax = 255,
+};
+
+typedef enum HIDElementTypeMask
+{
+ kHIDElementTypeInput = 1 << 1,
+ kHIDElementTypeOutput = 1 << 2,
+ kHIDElementTypeFeature = 1 << 3,
+ kHIDElementTypeCollection = 1 << 4,
+ kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature,
+ kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection
+}HIDElementTypeMask;
+
+struct recElement
+{
+ IOHIDElementType type; // the type defined by IOHIDElementType in IOHIDKeys.h
+ long usagePage; // usage page from IOUSBHIDParser.h which defines general usage
+ long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage
+ IOHIDElementCookie cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change
+ long min; // reported min value possible
+ long max; // reported max value possible
+ long scaledMin; // reported scaled min value possible
+ long scaledMax; // reported scaled max value possible
+ long size; // size in bits of data return from element
+ Boolean relative; // are reports relative to last report (deltas)
+ Boolean wrapping; // does element wrap around (one value higher than max is min)
+ Boolean nonLinear; // are the values reported non-linear relative to element movement
+ Boolean preferredState; // does element have a preferred state (such as a button)
+ Boolean nullState; // does element have null state
+ long units; // units value is reported in (not used very often)
+ long unitExp; // exponent for units (also not used very often)
+ Str255 name; // name of element (not used often)
+
+// runtime variables
+ long minReport; // min returned value
+ long maxReport; // max returned value (calibrate call)
+ long userMin; // user set value to scale to (scale call)
+ long userMax;
+
+ struct recElement * pPrevious; // previous element (NULL at list head)
+ struct recElement * pChild; // next child (only of collections)
+ struct recElement * pSibling; // next sibling (for elements and collections)
+
+};
+typedef struct recElement recElement;
+typedef recElement* pRecElement;
+
+struct recDevice
+{
+ IOHIDDeviceInterface ** interface; // interface to device, NULL = no interface
+ IOHIDQueueInterface ** queue; // device queue, NULL = no queue
+ CFRunLoopSourceRef queueRunLoopSource; // device queue run loop source, NULL == no source
+ IOHIDOutputTransactionInterface ** transaction; // output transaction interface, NULL == no transaction
+ io_object_t notification; // notifications
+ Str255 transport; // device transport
+ long vendorID; // id for device vendor, unique across all devices
+ long productID; // id for particular product, unique across all of a vendors devices
+ long version; // version of product
+ Str255 manufacturer; // name of manufacturer
+ Str255 product; // name of product
+ Str255 serial; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often)
+ long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine
+ long usage; // usage page from IOUSBHID Parser.h which defines general usage
+ long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage
+ long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device)
+ long features; // number of elements of type kIOHIDElementTypeFeature
+ long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes
+ long outputs; // number of elements of type kIOHIDElementTypeOutput
+ long collections; // number of elements of type kIOHIDElementTypeCollection
+ long axis; // number of axis (calculated, not reported by device)
+ long buttons; // number of buttons (calculated, not reported by device)
+ long hats; // number of hat switches (calculated, not reported by device)
+ long sliders; // number of sliders (calculated, not reported by device)
+ long dials; // number of dials (calculated, not reported by device)
+ long wheels; // number of wheels (calculated, not reported by device)
+ recElement* pListElements; // head of linked list of elements
+ struct recDevice* pNext; // next device
+};
+typedef struct recDevice recDevice;
+typedef recDevice* pRecDevice;
+
+// ==================================
+// Create and open an interface to device, required prior to extracting values or building queues
+// Note: appliction now owns the device and must close and release it prior to exiting
+extern IOReturn HIDCreateOpenDeviceInterface (io_object_t hidDevice, pRecDevice pDevice);
+
+// builds list of device with elements (allocates memory and captures devices)
+// list is allcoated internally within HID Utilites and can be accessed via accessor functions
+// structures within list are considered flat and user accessable, butnot user modifiable
+// can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list)
+extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage);
+
+// 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 chain
+extern void HIDReleaseDeviceList (void);
+
+// does a device list exist
+extern Boolean HIDHaveDeviceList (void);
+
+// how many HID devices have been found
+// returns 0 if no device list exist
+extern UInt32 HIDCountDevices (void);
+
+// how many elements does a specific device have
+// returns 0 if device is invalid or NULL
+// uses mask of HIDElementTypeMask to restrict element found
+// use kHIDElementTypeIO to get non-collection elements
+extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask);
+
+// get the first device in the device list
+// returns NULL if no list exists
+extern pRecDevice HIDGetFirstDevice (void);
+
+// get next device in list given current device as parameter
+// returns NULL if end of list
+extern pRecDevice HIDGetNextDevice (pRecDevice pDevice);
+
+// get the first element of device passed in as parameter
+// returns NULL if no list exists or device does not exists or is NULL
+// uses mask of HIDElementTypeMask to restrict element found
+// use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality
+extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask);
+
+// 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 functionality
+extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask);
+
+// get previous element of given device in list given current element as parameter
+// this wlaks directly up the tree to the top element and does not search at each level
+// returns NULL if beginning of list
+// uses mask of HIDElementTypeMask to restrict element found
+// use kHIDElementTypeIO to get non-collection elements
+extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask);
+
+// returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h)
+// returns empty string for invlid types
+extern void HIDGetTypeName (IOHIDElementType type, char * cstrName);
+
+// returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h)
+// returns usage page and usage values in string form for unknown values
+extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName);
+
+// returns calibrated value given raw value passed in
+// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values
+extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement);
+
+// returns scaled value given raw value passed in
+// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values
+extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement);
+
+// ---------------------------------
+// convert an element type to a mask
+extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type);
+
+// find this device
+extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice);
+
+// find the device and element for this action
+// Device: serial, vendorID, productID, location, usagePage, usage
+// Element: cookie, usagePage, usage,
+extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement,
+ pRecDevice *ppFoundDevice, pRecElement *ppFoundElement);
+
+// find the device and element for this action
+// Device: serial, vendorID, productID, location, usagePage, usage
+// Element: cookie, usagePage, usage,
+
+extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement);
+
+// print out all of an elements information
+extern int HIDPrintElement(const pRecElement pElement);
+
+// return true if this is a valid device pointer
+extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice);
+
+// return true if this is a valid element pointer for this device
+extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HID_Utilities_h_
diff --git a/HID_Utilities_Source/HID_Utilities_CFM.h b/HID_Utilities_Source/HID_Utilities_CFM.h
new file mode 100644
index 0000000..305916a
--- /dev/null
+++ b/HID_Utilities_Source/HID_Utilities_CFM.h
@@ -0,0 +1,74 @@
+/*
+ File: HID_Utilities_CFM.h
+
+ Contains: External interface for HID Utilities, can be used with either library or source
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+ *
+*/
+
+#ifndef _HID_Utilities_CFM_h_
+#define _HID_Utilities_CFM_h_
+
+// ==================================
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ==================================
+
+//includes
+
+#include "HID_Utilities_External.h"
+
+// ==================================
+
+// sets up CFM function pointers. Required to be called prior using an HID Utility function from CFM
+OSStatus SetupHIDCFM (void);
+
+// should be called prior to shut down to properly close te bundles
+void TearDownHIDCFM (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _HID_Utilities_External_h_
diff --git a/HID_Utilities_Source/HID_Utilities_External.h b/HID_Utilities_Source/HID_Utilities_External.h
new file mode 100644
index 0000000..62a52ec
--- /dev/null
+++ b/HID_Utilities_Source/HID_Utilities_External.h
@@ -0,0 +1,509 @@
+/*
+ File: HID_Utilities_External.h
+
+ Contains: Definition of the HID Utilities exported functions
+ External interface for HID Utilities, can be used with either library or source
+ Check notes below for usage. Some type casting is required so library is framework and carbon free
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+ *
+*/
+
+#ifndef _HID_Utilities_External_h_
+#define _HID_Utilities_External_h_
+// ==================================
+#if PRAGMA_ONCE
+#pragma once
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if PRAGMA_IMPORT
+#pragma import on
+#endif
+
+#pragma options align=mac68k
+// ==================================
+//includes
+
+#if TARGET_RT_MAC_CFM
+// from IOHIDKeys.h (IOKit)
+// this can't be included since the orginal file has framework includes
+// developers may need to add definitions here
+enum IOHIDElementType
+{
+ kIOHIDElementTypeInput_Misc = 1,
+ kIOHIDElementTypeInput_Button = 2,
+ kIOHIDElementTypeInput_Axis = 3,
+ kIOHIDElementTypeInput_ScanCodes = 4,
+ kIOHIDElementTypeOutput = 129,
+ kIOHIDElementTypeFeature = 257,
+ kIOHIDElementTypeCollection = 513
+};
+typedef enum IOHIDElementType IOHIDElementType;
+
+enum IOHIDReportType
+{
+ kIOHIDReportTypeInput = 0,
+ kIOHIDReportTypeOutput,
+ kIOHIDReportTypeFeature,
+ kIOHIDReportTypeCount
+};
+typedef enum IOHIDReportType IOHIDReportType;
+typedef void (*IOHIDCallbackFunction)(void * target, unsigned long result, void* refcon, void * sender);
+typedef void* IOHIDEventStruct;
+#else
+ #include <IOKit/hid/IOHIDLib.h>
+#endif TARGET_RT_MAC_CFM
+
+#if 0
+#include <IOKit/hid/IOHIDUsageTables.h>
+
+#include "PID.h" // NOTE: These are now in <IOKit/hid/IOHIDUsageTables.h>
+#include "IOHIDPowerUsage.h" // NOTE: These are now in <IOKit/hid/IOHIDUsageTables.h>
+#endif
+
+#include <stdio.h>
+
+// ==================================
+// Device and Element Interfaces
+
+typedef enum HIDElementTypeMask
+{
+ kHIDElementTypeInput = 1 << 1,
+ kHIDElementTypeOutput = 1 << 2,
+ kHIDElementTypeFeature = 1 << 3,
+ kHIDElementTypeCollection = 1 << 4,
+ kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature,
+ kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection
+}HIDElementTypeMask;
+
+struct recElement
+{
+ unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h
+ long usagePage; // usage page from IOUSBHIDParser.h which defines general usage
+ long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage
+ void * cookie; // unique value (within device of specific vendorID and productID) which identifies element, will NOT change
+ long min; // reported min value possible
+ long max; // reported max value possible
+ long scaledMin; // reported scaled min value possible
+ long scaledMax; // reported scaled max value possible
+ long size; // size in bits of data return from element
+ unsigned char relative; // are reports relative to last report (deltas)
+ unsigned char wrapping; // does element wrap around (one value higher than max is min)
+ unsigned char nonLinear; // are the values reported non-linear relative to element movement
+ unsigned char preferredState; // does element have a preferred state (such as a button)
+ unsigned char nullState; // does element have null state
+ long units; // units value is reported in (not used very often)
+ long unitExp; // exponent for units (also not used very often)
+ char name[256]; // name of element (c string)
+
+// runtime variables
+ long initialCenter; // center value at start up
+ unsigned char hasCenter; // whether or not to use center for calibration
+ long minReport; // min returned value
+ long maxReport; // max returned value (calibrate call)
+ long userMin; // user set value to scale to (scale call)
+ long userMax;
+
+ struct recElement * pPrevious; // previous element (NULL at list head)
+ struct recElement * pChild; // next child (only of collections)
+ struct recElement * pSibling; // next sibling (for elements and collections)
+
+ long depth;
+};
+typedef struct recElement recElement;
+typedef recElement* pRecElement;
+
+struct recDevice
+{
+ void * interface; // interface to device, NULL = no interface
+ void * queue; // device queue, NULL = no queue
+ void * queueRunLoopSource; // device queue run loop source, NULL == no source
+ void * transaction; // output transaction interface, NULL == no interface
+ void * notification; // notifications
+ char transport[256]; // device transport (c string)
+ long vendorID; // id for device vendor, unique across all devices
+ long productID; // id for particular product, unique across all of a vendors devices
+ long version; // version of product
+ char manufacturer[256]; // name of manufacturer
+ char product[256]; // name of product
+ char serial[256]; // serial number of specific product, can be assumed unique across specific product or specific vendor (not used often)
+ long locID; // long representing location in USB (or other I/O) chain which device is pluged into, can identify specific device on machine
+ long usage; // usage page from IOUSBHID Parser.h which defines general usage
+ long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage
+ long totalElements; // number of total elements (should be total of all elements on device including collections) (calculated, not reported by device)
+ long features; // number of elements of type kIOHIDElementTypeFeature
+ long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes
+ long outputs; // number of elements of type kIOHIDElementTypeOutput
+ long collections; // number of elements of type kIOHIDElementTypeCollection
+ long axis; // number of axis (calculated, not reported by device)
+ long buttons; // number of buttons (calculated, not reported by device)
+ long hats; // number of hat switches (calculated, not reported by device)
+ long sliders; // number of sliders (calculated, not reported by device)
+ long dials; // number of dials (calculated, not reported by device)
+ long wheels; // number of wheels (calculated, not reported by device)
+ recElement* pListElements; // head of linked list of elements
+ struct recDevice* pNext; // next device
+};
+typedef struct recDevice recDevice;
+typedef recDevice* pRecDevice;
+
+// ==================================
+// HID Utilities interface
+// ==================================
+// Create and open an interface to device, required prior to extracting values or building queues
+// Note: appliction now owns the device and must close and release it prior to exiting
+extern unsigned long HIDCreateOpenDeviceInterface (UInt32 hidDevice, pRecDevice pDevice);
+
+// builds list of device with elements (allocates memory and captures devices)
+// list is allcoated internally within HID Utilites and can be accessed via accessor functions
+// structures within list are considered flat and user accessable, butnot user modifiable
+// can be called again to rebuild list to account for new devices (will do the right thing in case of disposing existing list)
+// usagePage, usage are each a numDeviceTypes sized array of matching usage and usage pages
+// returns true if succesful
+
+extern Boolean HIDBuildMultiDeviceList (UInt32 *pUsagePage, UInt32 *pUsage, UInt32 numDeviceTypes);
+
+// same as above but this uses a single usagePage and usage
+
+extern Boolean HIDBuildDeviceList (UInt32 usagePage, UInt32 usage);
+
+// updates the current device list for any new/removed devices
+// if this is called before HIDBuildDeviceList the it functions like HIDBuildMultiDeviceList
+// usagePage, usage are each a numDeviceTypes sized array of matching usage and usage pages
+// returns true if successful which means if any device were added or removed (the device config changed)
+
+extern Boolean HIDUpdateDeviceList (UInt32 *pUsagePage, UInt32 *pUsage, UInt32 numDeviceTypes);
+
+// 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 chain
+extern void HIDReleaseDeviceList (void);
+
+// does a device list exist
+extern Boolean HIDHaveDeviceList (void);
+
+// how many HID devices have been found
+// returns 0 if no device list exist
+extern UInt32 HIDCountDevices (void);
+
+// how many elements does a specific device have
+// returns 0 if device is invalid or NULL
+// uses mask of HIDElementTypeMask to restrict element found
+// use kHIDElementTypeIO to get non-collection elements
+extern UInt32 HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask);
+
+// get the first device in the device list
+// returns NULL if no list exists
+extern pRecDevice HIDGetFirstDevice (void);
+
+// get next device in list given current device as parameter
+// returns NULL if end of list
+extern pRecDevice HIDGetNextDevice (pRecDevice pDevice);
+
+// get the first element of device passed in as parameter
+// returns NULL if no list exists or device does not exists or is NULL
+// uses mask of HIDElementTypeMask to restrict element found
+// use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality
+extern pRecElement HIDGetFirstDeviceElement (pRecDevice pDevice, HIDElementTypeMask typeMask);
+
+// 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 functionality
+extern pRecElement HIDGetNextDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask);
+
+// get previous element of given device in list given current element as parameter
+// this walks directly up the tree to the top element and does not search at each level
+// returns NULL if beginning of list
+// uses mask of HIDElementTypeMask to restrict element found
+// use kHIDElementTypeIO to get non-collection elements
+extern pRecElement HIDGetPreviousDeviceElement (pRecElement pElement, HIDElementTypeMask typeMask);
+
+// ==================================
+// Name Lookup Interfaces
+
+// returns C string type name given a type enumeration passed in as parameter (see IOHIDKeys.h)
+// returns empty string for invlid types
+extern void HIDGetTypeName (IOHIDElementType theType, char * cstrName);
+
+// set name from vendor id/product id look up (using cookies)
+extern Boolean HIDGetElementNameFromVendorProductCookie (const long vendorID, const long productID, const long cookie, char * pName);
+
+// set name from vendor id/product id look up (using usage page & usage)
+extern Boolean HIDGetElementNameFromVendorProductUsage (const long vendorID, const long productID, const long pUsagePage, const long pUsage, char * pName);
+
+// returns C string usage given usage page and usage passed in as parameters (see IOUSBHIDParser.h)
+// returns usage page and usage values in string form for unknown values
+extern void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName);
+
+// ---------------------------------
+// convert an element type to a mask
+extern HIDElementTypeMask HIDConvertElementTypeToMask (const long type);
+
+// find this device
+extern Boolean HIDFindDevice(const pRecDevice pSearchDevice, pRecDevice *ppFoundDevice);
+
+// find the device and element for this action
+// Device: serial, vendorID, productID, location, usagePage, usage
+// Element: cookie, usagePage, usage,
+extern Boolean HIDFindActionDeviceAndElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement,
+ pRecDevice *ppFoundDevice, pRecElement *ppFoundElement);
+
+// find the device and element for this action
+// Device: serial, vendorID, productID, location, usagePage, usage
+// Element: cookie, usagePage, usage,
+
+extern Boolean HIDFindSubElement(const pRecElement pStartElement, const pRecElement pSearchElement, pRecElement *ppFoundElement);
+
+// print out all of an elements information
+extern int HIDPrintElement(const pRecElement pElement);
+
+// return true if this is a valid device pointer
+extern Boolean HIDIsValidDevice(const pRecDevice pSearchDevice);
+
+// return true if this is a valid element pointer for this device
+extern Boolean HIDIsValidElement(const pRecDevice pSearchDevice, const pRecElement pSearchElement);
+
+// ==================================
+// Element Event Queue and Value Interfaces
+
+enum
+{
+ kDefaultUserMin = 0, // default user min and max used for scaling
+ kDefaultUserMax = 255
+};
+
+enum
+{
+ kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible
+ // but should account for the maximum possible events in the queue
+ // USB updates will likely occur at 100 Hz so one must account for this rate of
+ // if states change quickly (updates are only posted on state changes)
+};
+
+// ==================================
+// queues specific element, performing any device queue set up required
+extern unsigned long HIDQueueElement (pRecDevice pDevice, pRecElement pElement);
+
+// adds all elements to queue, performing any device queue set up required
+extern unsigned long HIDQueueDevice (pRecDevice pDevice);
+
+// removes element for queue, if last element in queue will release queue and device
+extern unsigned long HIDDequeueElement (pRecDevice pDevice, pRecElement pElement);
+
+// completely removes all elements from queue and releases queue and device
+extern unsigned long HIDDequeueDevice (pRecDevice pDevice);
+
+// releases all device queues for quit or rebuild (must be called)
+extern unsigned long HIDReleaseAllDeviceQueues (void);
+
+// releases interface to device, should be done prior to exiting application (called from HIDReleaseDeviceList)
+extern unsigned long HIDCloseReleaseInterface (pRecDevice pDevice);
+
+// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise
+// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
+extern unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent);
+
+// returns current value for element, creating device interface as required, polling element
+extern long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement);
+
+// Set an elements value
+// NOTE: This should only be used when a single element report needs to be sent.
+// If multiple elements reports are to be send then transactions should be used.
+// pIOHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
+extern long HIDSetElementValue (pRecDevice pDevice, pRecElement pElement,void* pIOHIDEvent);
+
+// Set a callback to be called when a queue goes from empty to non-empty
+extern long HIDSetQueueCallback (pRecDevice pDevice, IOHIDCallbackFunction callback,void* callbackTarget, void* callbackRefcon);
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+// Get a report from a device
+extern long HIDGetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, unsigned long* reportBufferSize);
+
+// Send a report to a device
+extern long HIDSetReport (pRecDevice pDevice,const IOHIDReportType reportType, const unsigned long reportID, void* reportBuffer, const unsigned long reportBufferSize);
+#endif MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
+
+// ==================================
+// HUD utilities interfaces
+
+// returns calibrated value given raw value passed in
+// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values
+extern SInt32 HIDCalibrateValue (SInt32 value, pRecElement pElement);
+
+// returns scaled value given raw value passed in
+// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values
+extern SInt32 HIDScaleValue (SInt32 value, pRecElement pElement);
+
+// ==================================
+// Conguration and Save Interfaces
+
+enum
+{
+ kPercentMove = 10 // precent of overall range a element must move to register
+};
+
+typedef struct recSaveHID
+{
+ long actionCookie;
+ // device
+ // need to add serial number when I have a test case
+ long vendorID;
+ long productID;
+ long locID;
+ long usage;
+ long usagePage;
+ // elements
+ long usagePageE;
+ long usageE;
+ void * cookie;
+}recSaveHID,*pRecSaveHID;
+
+// polls all devices and elements for a change greater than kPercentMove. Times out after given time
+// returns true and pointer to device and element if found
+// returns false and NULL for both parameters if not found
+extern unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout);
+
+// -- These are routines to use if the applcation wants HID Utilities to do the file handling --
+// Note: the FILE* is a MachO posix FILE and will not work with the MW MSL FILE* type.
+
+// take input records, save required info
+// assume file is open and at correct position.
+extern void HIDSaveElementConfig (FILE* fileRef, pRecDevice pDevice, pRecElement pElement, long actionCookie);
+
+// take file, read one record (assume file position is correct and file is open)
+// search for matching device
+// return pDevice, pElement and cookie for action
+extern long HIDRestoreElementConfig (FILE* fileRef, pRecDevice * ppDevice, pRecElement * ppElement);
+
+// -- These routines use the CFPreferences API's.
+
+// Save the device & element values into the specified key in the specified applications preferences
+extern Boolean HIDSaveElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice pDevice, pRecElement pElement);
+
+// Find the specified preference in the specified application
+// search for matching device and element
+// return pDevice, pElement that matches
+
+extern Boolean HIDRestoreElementPref (CFStringRef keyCFStringRef, CFStringRef appCFStringRef, pRecDevice * ppDevice, pRecElement * ppElement);
+
+// -- These are routines to use if the client wants to use their own file handling --
+
+// Set up a config record for saving
+// takes an input records, returns record user can save as they want
+// Note: the save rec must be pre-allocated by the calling app and will be filled out
+extern void HIDSetElementConfig (pRecSaveHID pConfigRec, pRecDevice pDevice, pRecElement pElement, long actionCookie);
+
+// Get matching element from config record
+// takes a pre-allocated and filled out config record
+// search for matching device
+// return pDevice, pElement and cookie for action
+extern long HIDGetElementConfig (pRecSaveHID pConfigRec, pRecDevice * ppDevice, pRecElement * ppElement);
+
+// ==================================
+// Output Transaction interface
+
+// Create and open an transaction interface to device, required prior to extracting values or building Transactions
+extern unsigned long HIDTransactionAddElement(pRecDevice pDevice, pRecElement pElement);
+
+// removes an element from a Transaction
+extern unsigned long HIDTransactionRemoveElement(pRecDevice pDevice, pRecElement pElement);
+
+// return true if this transaction contains this element
+extern Boolean HIDTransactionHasElement(pRecDevice pDevice, pRecElement pElement);
+
+/* This changes the default value of an element, when the values of the */
+/* elements are cleared, on clear or commit, they are reset to the */
+/* default value */
+/* This call can be made on elements that are not in the transaction, but */
+/* has undefined behavior if made on elements not in the transaction */
+/* which are later added to the transaction. */
+/* In other words, an element should be added before its default is */
+/* set, for well defined behavior. */
+// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
+extern unsigned long HIDTransactionSetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Get the current setting of an element's default value */
+// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
+extern unsigned long HIDTransactionGetElementDefault(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Add a change to the transaction, by setting an element value */
+/* The change is not actually made until it is commited */
+/* The element must be part of the transaction or this call will fail */
+// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
+extern unsigned long HIDTransactionSetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Get the current setting of an element value */
+// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
+extern unsigned long HIDTransactionGetElementValue(pRecDevice pDevice, pRecElement pElement,IOHIDEventStruct* pValueEvent);
+
+/* Commit the transaction, or clear all the changes and start over */
+/* timoutMS is the timeout in milliseconds, a zero timeout will cause */
+/* this call to be non-blocking (returning queue empty) if there */
+/* is a NULL callback, and blocking forever until the queue is */
+/* non-empty if their is a valid callback */
+/* callback, if non-NULL is a callback to be called when data is */
+/* inserted to the queue */
+/* callbackTarget and callbackRefcon are passed to the callback */
+extern unsigned long HIDTransactionCommit(pRecDevice pDevice);
+
+/* Clear all the changes and start over */
+extern unsigned long HIDTransactionClear(pRecDevice pDevice);
+
+// ==================================
+#pragma options align=reset
+
+#ifdef PRAGMA_IMPORT_OFF
+#pragma import off
+#elif PRAGMA_IMPORT
+#pragma import reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+// ==================================
+
+#endif // _HID_Utilities_External_h_
diff --git a/HID_Utilities_Source/HID_Utilities_Internal.h b/HID_Utilities_Source/HID_Utilities_Internal.h
new file mode 100644
index 0000000..3e1eac2
--- /dev/null
+++ b/HID_Utilities_Source/HID_Utilities_Internal.h
@@ -0,0 +1,54 @@
+/*
+ File: HID_Utilities_Internal.h
+
+ Contains: Definition of HID Utilities internal functions
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#ifndef _HID_Utilities_Internal_h_
+#define _HID_Utilities_Internal_h_
+
+// Moved into specific "HID_xxx.h" files.
+
+#include "HID_Error_Handler.h"
+
+#endif // _HID_Utilities_Internal_h_
+
diff --git a/HID_Utilities_Source/IOHIDPowerUsage.h b/HID_Utilities_Source/IOHIDPowerUsage.h
new file mode 100644
index 0000000..27c440f
--- /dev/null
+++ b/HID_Utilities_Source/IOHIDPowerUsage.h
@@ -0,0 +1,280 @@
+/*
+ File: IOHIDPowerUsage.h
+
+ Contains: Definition of the HID power usage constants (NOTE: Moved into <IOKit/hid/IOHIDUsageTables.h>)
+
+ DRI: George Warner
+
+ Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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.
+*/
+
+#ifndef __IOHIDPowerUsage__
+#define __IOHIDPowerUsage__
+
+#ifndef __MACTYPES__
+//#include <MacTypes.h>
+#endif
+
+#ifndef __MACERRORS__
+//#include <MacErrors.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+enum
+{
+ kHIDPage_PowerDevice = 0x84, /* Power Device Page */
+ kHIDPage_BatterySystem = 0x85, /* Battery System Page */
+
+ /* Usage Types:
+ CA- Application Collection
+ CL- logical Collection
+ CP- Pyiscal Collection
+ DF- Dynamic Flag
+ DV- Dynamic Value
+ SF- Static Flag
+ SV- Static Value
+
+ Usgae Implementations:
+ I- Input
+ O- Output
+ F- Feature
+ */
+
+ /* Power Device Page (0x84) */
+ /* This section provides detailed descriptions of the usages employed by Power Devices. */
+ kHIDUsage_PD_Undefined = 0x00, /* Power Device Undefined Usage */
+ kHIDUsage_PD_iName = 0x01, /* CL- Power Device Name Index */
+ kHIDUsage_PD_PresentStatus = 0x02, /* CL- Power Device Present Status */
+ kHIDUsage_PD_ChangedStatus = 0x03, /* CA- Power Device Changed Status */
+ kHIDUsage_PD_UPS = 0x04, /* CA- Uninterruptible Power Supply */
+ kHIDUsage_PD_PowerSupply = 0x05, /* CA- Power Supply */
+ /* Reserved 0x06 - 0x0F */
+ kHIDUsage_PD_BatterySystem = 0x10, /* CP- Battery System power module */
+ kHIDUsage_PD_BatterySystemID = 0x11, /* SV IF- Battery System ID */
+ kHIDUsage_PD_Battery = 0x12, /* CP- Battery */
+ kHIDUsage_PD_BatteryID = 0x13, /* SV IF- Battery ID */
+ kHIDUsage_PD_Charger = 0x14, /* CP- Charger */
+ kHIDUsage_PD_ChargerID = 0x15, /* SV IF- Charger ID */
+ kHIDUsage_PD_PowerConverter = 0x16, /* CP- Power Converter power module */
+ kHIDUsage_PD_PowerConverterID = 0x17, /* SV IF- Power Converter ID */
+ kHIDUsage_PD_OutletSystem = 0x18, /* CP- Outlet System power module */
+ kHIDUsage_PD_OutletSystemID = 0x19, /* SV IF-Outlet System ID */
+ kHIDUsage_PD_Input = 0x1A, /* CP- Power Device Input */
+ kHIDUsage_PD_InputID = 0x1B, /* SV IF- Power Device Input ID */
+ kHIDUsage_PD_Output = 0x1C, /* CP- Power Device Output */
+ kHIDUsage_PD_OutputID = 0x1D, /* SV IF- Power Device Output ID */
+ kHIDUsage_PD_Flow = 0x1E, /* CP- Power Device Flow */
+ kHIDUsage_PD_FlowID = 0x1F, /* Item IF- Power Device Flow ID */
+ kHIDUsage_PD_Outlet = 0x20, /* CP- Power Device Outlet */
+ kHIDUsage_PD_OutletID = 0x21, /* SV IF- Power Device Outlet ID */
+ kHIDUsage_PD_Gang = 0x22, /* CL/CP- Power Device Gang */
+ kHIDUsage_PD_GangID = 0x23, /* SV IF- Power Device Gang ID */
+ kHIDUsage_PD_PowerSummary = 0x24, /* CL/CP- Power Device Power Summary */
+ kHIDUsage_PD_PowerSummaryID = 0x25, /* SV IF- Power Device Power Summary ID */
+ /* Reserved 0x26 - 0x2F */
+ kHIDUsage_PD_Voltage = 0x30, /* DV IF- Power Device Voltage */
+ kHIDUsage_PD_Current = 0x31, /* DV IF- Power Device Current */
+ kHIDUsage_PD_Frequency = 0x32, /* DV IF- Power Device Frequency */
+ kHIDUsage_PD_ApparentPower = 0x33, /* DV IF- Power Device Apparent Power */
+ kHIDUsage_PD_ActivePower = 0x34, /* DV IF- Power Device RMS Power */
+ kHIDUsage_PD_PercentLoad = 0x35, /* DV IF- Power Device Percent Load */
+ kHIDUsage_PD_Temperature = 0x36, /* DV IF- Power Device Temperature */
+ kHIDUsage_PD_Humidity = 0x37, /* DV IF- Power Device Humidity */
+ kHIDUsage_PD_BadCount = 0x38, /* DV IF- Power Device Bad Condition Count */
+ /* Reserved 0x39 - 0x3F */
+ kHIDUsage_PD_ConfigVoltage = 0x40, /* SV/DV F- Power Device Nominal Voltage */
+ kHIDUsage_PD_ConfigCurrent = 0x41, /* SV/DV F- Power Device Nominal Current */
+ kHIDUsage_PD_ConfigFrequency = 0x42, /* SV/DV F- Power Device Nominal Frequency */
+ kHIDUsage_PD_ConfigApparentPower = 0x43, /* SV/DV F- Power Device Nominal Apparent Power */
+ kHIDUsage_PD_ConfigActivePower = 0x44, /* SV/DV F- Power Device Nominal RMS Power */
+ kHIDUsage_PD_ConfigPercentLoad = 0x45, /* SV/DV F- Power Device Nominal Percent Load */
+ kHIDUsage_PD_ConfigTemperature = 0x46, /* SV/DV F- Power Device Nominal Temperature */
+ kHIDUsage_PD_ConfigHumidity = 0x47, /* SV/DV F- Power Device Nominal Humidity */
+ /* Reserved 0x48 - 0x4F */
+ kHIDUsage_PD_SwitchOnControl = 0x50, /* DV F- Power Device Switch On Control */
+ kHIDUsage_PD_SwitchOffControl = 0x51, /* DV F- Power Device Switch Off Control */
+ kHIDUsage_PD_ToggleControl = 0x52, /* DV F- Power Device Toogle Sequence Control */
+ kHIDUsage_PD_LowVoltageTransfer = 0x53, /* DV F- Power Device Min Transfer Voltage */
+ kHIDUsage_PD_HighVoltageTransfer = 0x54, /* DV F- Power Device Max Transfer Voltage */
+ kHIDUsage_PD_DelayBeforeReboot = 0x55, /* DV F- Power Device Delay Before Reboot */
+ kHIDUsage_PD_DelayBeforeStartup = 0x56, /* DV F- Power Device Delay Before Startup */
+ kHIDUsage_PD_DelayBeforeShutdown = 0x57, /* DV F- Power Device Delay Before Shutdown */
+ kHIDUsage_PD_Test = 0x58, /* DV F- Power Device Test Request/Result */
+ kHIDUsage_PD_ModuleReset = 0x59, /* DV F- Power Device Reset Request/Result */
+ kHIDUsage_PD_AudibleAlarmControl = 0x5A, /* DV F- Power Device Audible Alarm Control */
+ /* Reserved 0x5B - 0x5F */
+ kHIDUsage_PD_Present = 0x60, /* DV IOF- Power Device Present */
+ kHIDUsage_PD_Good = 0x61, /* DV IOF- Power Device Good */
+ kHIDUsage_PD_InternalFailure = 0x62, /* DV IOF- Power Device Internal Failure */
+ kHIDUsage_PD_VoltageOutOfRange = 0x63, /* DV IOF- Power Device Voltage Out Of Range */
+ kHIDUsage_PD_FrequencyOutOfRange = 0x64, /* DV IOF- Power Device Frequency Out Of Range */
+ kHIDUsage_PD_Overload = 0x65, /* DV IOF- Power Device Overload */
+ kHIDUsage_PD_OverCharged = 0x66, /* DV IOF- Power Device Over Charged */
+ kHIDUsage_PD_OverTemperature = 0x67, /* DV IOF- Power Device Over Temperature */
+ kHIDUsage_PD_ShutdownRequested = 0x68, /* DV IOF- Power Device Shutdown Requested */
+ kHIDUsage_PD_ShutdownImminent = 0x69, /* DV IOF- Power Device Shutdown Imminent */
+ /* Reserved 0x6A */
+ kHIDUsage_PD_SwitchOnOff = 0x6B, /* DV IOF- Power Device On/Off Switch Status */
+ kHIDUsage_PD_Switchable = 0x6C, /* DV IOF- Power Device Switchable */
+ kHIDUsage_PD_Used = 0x6D, /* DV IOF- Power Device Used */
+ kHIDUsage_PD_Boost = 0x6E, /* DV IOF- Power Device Boosted */
+ kHIDUsage_PD_Buck = 0x6F, /* DV IOF- Power Device Bucked */
+ kHIDUsage_PD_Initialized = 0x70, /* DV IOF- Power Device Initialized */
+ kHIDUsage_PD_Tested = 0x71, /* DV IOF- Power Device Tested */
+ kHIDUsage_PD_AwaitingPower = 0x72, /* DV IOF- Power Device Awaiting Power */
+ kHIDUsage_PD_CommunicationLost = 0x73, /* DV IOF- Power Device Communication Lost */
+ /* Reserved 0x74 - 0xFC */
+ kHIDUsage_PD_iManufacturer = 0xFD, /* SV F- Power Device Manufacturer String Index */
+ kHIDUsage_PD_iProduct = 0xFE, /* SV F- Power Device Product String Index */
+ kHIDUsage_PD_iserialNumber = 0xFF, /* SV F- Power Device Serial Number String Index */
+
+ /* Battery System Page (x85) */
+ /* This section provides detailed descriptions of the usages employed by Battery Systems. */
+ kHIDUsage_BS_Undefined = 0x00, /* Battery System Undefined */
+ kHIDUsage_BS_SMBBatteryMode = 0x01, /* CL - SMB Mode */
+ kHIDUsage_BS_SMBBatteryStatus = 0x02, /* CL - SMB Status */
+ kHIDUsage_BS_SMBAlarmWarning = 0x03, /* CL - SMB Alarm Warning */
+ kHIDUsage_BS_SMBChargerMode = 0x04, /* CL - SMB Charger Mode */
+ kHIDUsage_BS_SMBChargerStatus = 0x05, /* CL - SMB Charger Status */
+ kHIDUsage_BS_SMBChargerSpecInfo = 0x06, /* CL - SMB Charger Extended Status */
+ kHIDUsage_BS_SMBSelectorState = 0x07, /* CL - SMB Selector State */
+ kHIDUsage_BS_SMBSelectorPresets = 0x08, /* CL - SMB Selector Presets */
+ kHIDUsage_BS_SMBSelectorInfo = 0x09, /* CL - SMB Selector Info */
+ /* Reserved 0x0A - 0x0F */
+ kHIDUsage_BS_OptionalMfgFunction1 = 0x10, /* DV F - Battery System Optional SMB Mfg Function 1 */
+ kHIDUsage_BS_OptionalMfgFunction2 = 0x11, /* DV F - Battery System Optional SMB Mfg Function 2 */
+ kHIDUsage_BS_OptionalMfgFunction3 = 0x12, /* DV F - Battery System Optional SMB Mfg Function 3 */
+ kHIDUsage_BS_OptionalMfgFunction4 = 0x13, /* DV F - Battery System Optional SMB Mfg Function 4 */
+ kHIDUsage_BS_OptionalMfgFunction5 = 0x14, /* DV F - Battery System Optional SMB Mfg Function 5 */
+ kHIDUsage_BS_ConnectionToSMBus = 0x15, /* DF F - Battery System Connection To System Management Bus */
+ kHIDUsage_BS_OutputConnection = 0x16, /* DF F - Battery System Output Connection Status */
+ kHIDUsage_BS_ChargerConnection = 0x17, /* DF F - Battery System Charger Connection */
+ kHIDUsage_BS_BatteryInsertion = 0x18, /* DF F - Battery System Battery Insertion */
+ kHIDUsage_BS_Usenext = 0x19, /* DF F - Battery System Use Next */
+ kHIDUsage_BS_OKToUse = 0x1A, /* DF F - Battery System OK To Use */
+ kHIDUsage_BS_BatterySupported = 0x1B, /* DF F - Battery System Battery Supported */
+ kHIDUsage_BS_SelectorRevision = 0x1C, /* DF F - Battery System Selector Revision */
+ kHIDUsage_BS_ChargingIndicator = 0x1D, /* DF F - Battery System Charging Indicator */
+ /* Reserved 0x1E - 0x27 */
+ kHIDUsage_BS_ManufacturerAccess = 0x28, /* DV F - Battery System Manufacturer Access */
+ kHIDUsage_BS_RemainingCapacityLimit = 0x29, /* DV F - Battery System Remaining Capacity Limit */
+ kHIDUsage_BS_RemainingTimeLimit = 0x2A, /* DV F - Battery System Remaining Time Limit */
+ kHIDUsage_BS_AtRate = 0x2B, /* DV F - Battery System At Rate... */
+ kHIDUsage_BS_CapacityMode = 0x2C, /* DV F - Battery System Capacity Mode */
+ kHIDUsage_BS_BroadcastToCharger = 0x2D, /* DV F - Battery System Broadcast To Charger */
+ kHIDUsage_BS_PrimaryBattery = 0x2E, /* DV F - Battery System Primary Battery */
+ kHIDUsage_BS_ChargeController = 0x2F, /* DV F - Battery System Charge Controller */
+ /* Reserved 0x30 - 0x3F */
+ kHIDUsage_BS_TerminateCharge = 0x40, /* DF IOF - Battery System Terminate Charge */
+ kHIDUsage_BS_TerminateDischarge = 0x41, /* DF IOF - Battery System Terminate Discharge */
+ kHIDUsage_BS_BelowRemainingCapacityLimit = 0x42, /* DF IOF - Battery System Below Remaining Capacity Limit */
+ kHIDUsage_BS_RemainingTimeLimitExpired = 0x43, /* DF IOF - Battery System Remaining Time Limit Expired */
+ kHIDUsage_BS_Charging = 0x44, /* DF IOF - Battery System Charging */
+ kHIDUsage_BS_Discharging = 0x45, /* DV IOF - Battery System Discharging */
+ kHIDUsage_BS_FullyCharged = 0x46, /* DF IOF - Battery System Fully Charged */
+ kHIDUsage_BS_FullyDischarged = 0x47, /* DV IOF - Battery System Fully Discharged */
+ kHIDUsage_BS_ConditioningFlag = 0x48, /* DV IOF - Battery System Conditioning Flag */
+ kHIDUsage_BS_AtRateOK = 0x49, /* DV IOF - Battery System At Rate OK */
+ kHIDUsage_BS_SMBErrorCode = 0x4A, /* DF IOF - Battery System SMB Error Code */
+ kHIDUsage_BS_NeedReplacement = 0x4B, /* DF IOF - Battery System Need Replacement */
+ /* Reserved 0x4C - 0x5F */
+ kHIDUsage_BS_AtRateTimeToFull = 0x60, /* DV IF - Battery System At Rate Time To Full */
+ kHIDUsage_BS_AtRateTimeToEmpty = 0x61, /* DV IF - Battery System At Rate Time To Empty */
+ kHIDUsage_BS_AverageCurrent = 0x62, /* DV IF - Battery System Average Current */
+ kHIDUsage_BS_Maxerror = 0x63, /* DV IF - Battery System Max Error */
+ kHIDUsage_BS_RelativeStateOfCharge = 0x64, /* DV IF - Battery System Relative State Of Charge */
+ kHIDUsage_BS_AbsoluteStateOfCharge = 0x65, /* DV IF - Battery System Absolute State Of Charge */
+ kHIDUsage_BS_RemainingCapacity = 0x66, /* DV IF - Battery System Remaining Capacity */
+ kHIDUsage_BS_FullChargeCapacity = 0x67, /* DV IF - Battery System Full Charge Capacity */
+ kHIDUsage_BS_RunTimeToEmpty = 0x68, /* DV IF - Battery System Run Time To Empty */
+ kHIDUsage_BS_AverageTimeToEmpty = 0x69, /* DV IF - Battery System Average Time To Empty */
+ kHIDUsage_BS_AverageTimeToFull = 0x6A, /* DV IF - Battery System Average Time To Full */
+ kHIDUsage_BS_CycleCount = 0x6B, /* DV IF - Battery System Cycle Count */
+ /* Reserved 0x6C - 0x7F */
+ kHIDUsage_BS_BattPackModelLevel = 0x80, /* SV F - Battery System Batt Pack Model Level */
+ kHIDUsage_BS_InternalChargeController = 0x81, /* SF F - Battery System Internal Charge Controller */
+ kHIDUsage_BS_PrimaryBatterySupport = 0x82, /* SF F - Battery System Primary Battery Support */
+ kHIDUsage_BS_DesignCapacity = 0x83, /* SV F - Battery System Design Capacity */
+ kHIDUsage_BS_SpecificationInfo = 0x84, /* SV F - Battery System Specification Info */
+ kHIDUsage_BS_ManufacturerDate = 0x85, /* SV F - Battery System Manufacturer Date */
+ kHIDUsage_BS_SerialNumber = 0x86, /* SV F - Battery System Serial Number */
+ kHIDUsage_BS_iManufacturerName = 0x87, /* SV F - Battery System Manufacturer Name Index */
+ kHIDUsage_BS_iDevicename = 0x88, /* SV F - Battery System Device Name Index */
+ kHIDUsage_BS_iDeviceChemistry = 0x89, /* SV F - Battery System Device Chemistry Index */
+ kHIDUsage_BS_ManufacturerData = 0x8A, /* SV F - Battery System Manufacturer Data */
+ kHIDUsage_BS_Rechargable = 0x8B, /* SV F - Battery System Rechargable */
+ kHIDUsage_BS_WarningCapacityLimit = 0x8C, /* SV F - Battery System Warning Capacity Limit */
+ kHIDUsage_BS_CapacityGranularity1 = 0x8D, /* SV F - Battery System Capacity Granularity 1 */
+ kHIDUsage_BS_CapacityGranularity2 = 0x8E, /* SV F - Battery System Capacity Granularity 2 */
+ kHIDUsage_BS_iOEMInformation = 0x8F, /* SV F - Battery System OEM Information Index */
+ /* Reserved 0x90 - 0xBF */
+ kHIDUsage_BS_InhibitCharge = 0xC0, /* DF IOF - Battery System Inhibit Charge */
+ kHIDUsage_BS_EnablePolling = 0xC1, /* DF IOF - Battery System Enable Polling */
+ kHIDUsage_BS_ResetToZero = 0xC2, /* DF IOF - Battery System Reset To Zero */
+ /* Reserved 0xC3 - 0xCF */
+ kHIDUsage_BS_ACPresent = 0xD0, /* DF IOF - Battery System AC Present */
+ kHIDUsage_BS_BatteryPresent = 0xD1, /* DF IOF - Battery System Battery Present */
+ kHIDUsage_BS_PowerFail = 0xD2, /* DF IOF - Battery System Power Fail */
+ kHIDUsage_BS_AlarmInhibited = 0xD3, /* DF IOF - Battery System Alarm Inhibited */
+ kHIDUsage_BS_ThermistorUnderRange = 0xD4, /* DF IOF - Battery System Thermistor Under Range */
+ kHIDUsage_BS_ThermistorHot = 0xD5, /* DF IOF - Battery System Thermistor Hot */
+ kHIDUsage_BS_ThermistorCold = 0xD6, /* DF IOF - Battery System Thermistor Cold */
+ kHIDUsage_BS_ThermistorOverRange = 0xD7, /* DF IOF - Battery System Thermistor Over Range */
+ kHIDUsage_BS_VoltageOutOfRange = 0xD8, /* DF IOF - Battery System Voltage Out Of Range */
+ kHIDUsage_BS_CurrentOutOfRange = 0xD9, /* DF IOF - Battery System Current Out Of Range */
+ kHIDUsage_BS_CurrentNotRegulated = 0xDA, /* DF IOF - Battery System Current Not Regulated */
+ kHIDUsage_BS_VoltageNotRegulated = 0xDB, /* DF IOF - Battery System Voltage Not Regulated */
+ kHIDUsage_BS_MasterMode = 0xDC, /* DF IOF - Battery System Master Mode */
+ /* Reserved 0xDD - 0xEF */
+ kHIDUsage_BS_ChargerSelectorSupport = 0xF0, /* SF F- Battery System Charger Support Selector */
+ kHIDUsage_BS_ChargerSpec = 0xF1, /* SF F- Battery System Charger Specification */
+ kHIDUsage_BS_Level2 = 0xF2, /* SF F- Battery System Charger Level 2 */
+ kHIDUsage_BS_Level3 = 0xF3 /* SF F- Battery System Charger Level 3 */
+ /* Reserved 0xF2 - 0xFF */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IOHIDPowerUsage__ */
+
diff --git a/HID_Utilities_Source/ImmrHIDUtilAddOn.c b/HID_Utilities_Source/ImmrHIDUtilAddOn.c
new file mode 100644
index 0000000..6d2cbaf
--- /dev/null
+++ b/HID_Utilities_Source/ImmrHIDUtilAddOn.c
@@ -0,0 +1,95 @@
+/*
+ * ImmrHIDUtilAddOn.c
+ * UseFFAPIFromHIDUtilities
+ *
+ * Created by rlacroix on Wed Oct 16 2002.
+ * Copyright (c) 2002 Immersion Corporation. All rights reserved.
+ *
+ */
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDUsageTables.h>
+
+#include "HID_Utilities_External.h"
+#include "ImmrHIDUtilAddOn.h"
+
+//---------------------------------------------------------------------------------
+//
+// AllocateHIDObjectFromRecDevice()
+//
+// returns:
+// NULL, or acceptable io_object_t
+//
+//---------------------------------------------------------------------------------
+io_service_t AllocateHIDObjectFromRecDevice( pRecDevice pDevice )
+{
+ CFMutableDictionaryRef matchingDict;
+ UInt32 locationID = pDevice->locID;
+ CFNumberRef refUsage = NULL;
+ mach_port_t masterPort = NULL;
+ IOReturn result = kIOReturnSuccess;
+ io_service_t hidDevice = NULL;
+
+ do // while( 0 )
+ {
+ result = IOMasterPort (bootstrap_port, &masterPort);
+ if( result != kIOReturnSuccess )
+ {
+ break;
+ }
+
+ // Set up the matching criteria for the devices we're interested in.
+ // We are interested in instances of class IOHIDDevice.
+ // matchingDict is consumed below (in IOServiceGetMatchingService)
+ // so we have no leak here.
+ //
+ matchingDict = IOServiceMatching(kIOHIDDeviceKey);
+ if (!matchingDict)
+ {
+ break;
+ }
+
+ // Add a key for locationID to our matching dictionary. This works for matching to
+ // IOHIDDevices, so we will only look for a device attached to that particular port
+ // on the machine.
+ //
+ refUsage = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &locationID);
+ CFDictionaryAddValue( matchingDict,
+ CFSTR(kIOHIDLocationIDKey),
+ refUsage);
+ CFRelease(refUsage);
+
+ // IOServiceGetMatchingService assumes that we already know that there is only one device
+ // that matches. This way we don't have to do the whole iteration dance to look at each
+ // device that matches. This is a new API in 10.2
+ //
+ hidDevice = IOServiceGetMatchingService( masterPort, matchingDict);
+ }
+ while( 0 );
+
+ // Free master port if we created one.
+ //
+ if (masterPort)
+ mach_port_deallocate(mach_task_self(), masterPort);
+
+ return hidDevice;
+}
+
+//---------------------------------------------------------------------------------
+//
+// FreeHIDObject()
+//
+//---------------------------------------------------------------------------------
+bool FreeHIDObject( io_service_t hidDevice )
+{
+ kern_return_t kr;
+
+ kr = IOObjectRelease(hidDevice);
+
+ return( kIOReturnSuccess == kr );
+} \ No newline at end of file
diff --git a/HID_Utilities_Source/ImmrHIDUtilAddOn.h b/HID_Utilities_Source/ImmrHIDUtilAddOn.h
new file mode 100644
index 0000000..4563a61
--- /dev/null
+++ b/HID_Utilities_Source/ImmrHIDUtilAddOn.h
@@ -0,0 +1,13 @@
+/*
+ * ImmrHIDUtilAddOn.h
+ * UseFFAPIFromHIDUtilities
+ *
+ * Created by rlacroix on Wed Oct 16 2002.
+ * Copyright (c) 2002 Immersion Corporation. All rights reserved.
+ *
+ */
+
+//extern io_object_t AllocateHIDObjectFromRecDevice( pRecDevice pDevice );
+//extern Boolean FreeHIDObject( io_object_t hidDevice );
+io_service_t AllocateHIDObjectFromRecDevice( pRecDevice pDevice );
+bool FreeHIDObject( io_service_t hidDevice );
diff --git a/HID_Utilities_Source/Makefile.am b/HID_Utilities_Source/Makefile.am
new file mode 100644
index 0000000..184c15c
--- /dev/null
+++ b/HID_Utilities_Source/Makefile.am
@@ -0,0 +1,29 @@
+AUTOMAKE_OPTIONS = foreign
+
+noinst_LIBRARIES = libHIDUtilities.a
+
+libHIDUtilities_a_SOURCES = \
+ HID_Config_Utilities.c \
+ HID_Error_Handler.c \
+ HID_Name_Lookup.c \
+ HID_Queue_Utilities.c \
+ HID_Transaction_Utilities.c \
+ HID_Utilities.c \
+ ImmrHIDUtilAddOn.c
+
+# include the headers in the dist so you can build
+nobase_noinst_HEADERS = \
+ HIDLib.h \
+ HID_APIs.h \
+ HID_Config_Utilities.h \
+ HID_Error_Handler.h \
+ HID_Name_Lookup.h \
+ HID_Queue_Utilities.h \
+ HID_Transaction_Utilities.h \
+ HID_Utilities.h \
+ HID_Utilities_CFM.h \
+ HID_Utilities_External.h \
+ HID_Utilities_Internal.h \
+ IOHIDPowerUsage.h \
+ ImmrHIDUtilAddOn.h \
+ PID.h
diff --git a/HID_Utilities_Source/PID.h b/HID_Utilities_Source/PID.h
new file mode 100644
index 0000000..fac1647
--- /dev/null
+++ b/HID_Utilities_Source/PID.h
@@ -0,0 +1 @@
+/* File: PID.h DRI: George Warner Contains: Definition of the PID constants (NOTE: Moved into <IOKit/hid/IOHIDUsageTables.h>) DRI: George Warner Copyright: Copyright © 2002 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, 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 Computer, 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. */ #ifndef __PID__ #define __PID__ #ifdef __cplusplus extern "C" { #endif #if PRAGMA_IMPORT #pragma import on #endif /* Physical Interface Device Page (0x0F) */ /* This section provides detailed descriptions of the usages employed by Digitizer Devices. */ enum { kHIDUsage_PID_PhysicalInterfaceDevice = 0x01, /* CA - A collection of PID usages */ /* 0x02 - 0x1F Reserved */ kHIDUsage_PID_Normal = 0x20, /* DV - A force applied perpendicular to the surface of an object */ kHIDUsage_PID_SetEffectReport = 0x21, /* XXX */ kHIDUsage_PID_EffectBlockIndex = 0x22, /* XXX */ kHIDUsage_PID_ParamBlockOffset = 0x23, /* XXX */ kHIDUsage_PID_ROM_Flag = 0x24, /* XXX */ kHIDUsage_PID_EffectType = 0x25, /* XXX */ kHIDUsage_PID_ET_ConstantForce = 0x26, /* XXX */ kHIDUsage_PID_ET_Ramp = 0x27, /* XXX */ kHIDUsage_PID_ET_CustomForceData = 0x28, /* XXX */ /* 0x29 - 0x2F Reserved */ kHIDUsage_PID_ET_Square = 0x30, /* XXX */ kHIDUsage_PID_ET_Sine = 0x31, /* XXX */ kHIDUsage_PID_ET_Triangle = 0x32, /* XXX */ kHIDUsage_PID_ET_SawtoothUp = 0x33, /* XXX */ kHIDUsage_PID_ET_SawtoothDown = 0x34, /* XXX */ /* 0x35 - 0x3F Reserved */ kHIDUsage_PID_ET_Spring = 0x40, /* XXX */ kHIDUsage_PID_ET_Damper = 0x41, /* XXX */ kHIDUsage_PID_ET_Inertia = 0x42, /* XXX */ kHIDUsage_PID_ET_Friction = 0x43, /* XXX */ /* 0x44 - 0x4F Reserved */ kHIDUsage_PID_Duration = 0x50, /* XXX */ kHIDUsage_PID_SamplePeriod = 0x51, /* XXX */ kHIDUsage_PID_Gain = 0x52, /* XXX */ kHIDUsage_PID_TriggerButton = 0x53, /* XXX */ kHIDUsage_PID_TriggerRepeatInterval = 0x54, /* XXX */ kHIDUsage_PID_AxesEnable = 0x55, /* XXX */ kHIDUsage_PID_DirectionEnable = 0x56, /* XXX */ kHIDUsage_PID_Direction = 0x57, /* XXX */ kHIDUsage_PID_TypeSpecificBlockOffset = 0x58, /* XXX */ kHIDUsage_PID_BlockType = 0x59, /* XXX */ kHIDUsage_PID_SetEnvelopeReport = 0x5A, /* XXX */ kHIDUsage_PID_AttackLevel = 0x5B, /* XXX */ kHIDUsage_PID_AttackTime = 0x5C, /* XXX */ kHIDUsage_PID_FadeLevel = 0x5D, /* XXX */ kHIDUsage_PID_FadeTime = 0x5E, /* XXX */ kHIDUsage_PID_SetConditionReport = 0x5F, /* XXX */ kHIDUsage_PID_CP_Offset = 0x60, /* XXX */ kHIDUsage_PID_PositiveCoefficient = 0x61, /* XXX */ kHIDUsage_PID_NegativeCoefficient = 0x62, /* XXX */ kHIDUsage_PID_PositiveSaturation = 0x63, /* XXX */ kHIDUsage_PID_NegativeSaturation = 0x64, /* XXX */ kHIDUsage_PID_DeadBand = 0x65, /* XXX */ kHIDUsage_PID_DownloadForceSample = 0x66, /* XXX */ kHIDUsage_PID_IsochCustomForceEnable = 0x67, /* XXX */ kHIDUsage_PID_CustomForceDataReport = 0x68, /* XXX */ kHIDUsage_PID_CustomForceData = 0x69, /* XXX */ kHIDUsage_PID_CustomForceVendorDefinedData = 0x6A, /* XXX */ kHIDUsage_PID_SetCustomForceReport = 0x6B, /* XXX */ kHIDUsage_PID_CustomForceDataOffset = 0x6C, /* XXX */ kHIDUsage_PID_SampleCount = 0x6D, /* XXX */ kHIDUsage_PID_SetPeriodicReport = 0x6E, /* XXX */ kHIDUsage_PID_Offset = 0x6F, /* XXX */ kHIDUsage_PID_Magnitude = 0x70, /* XXX */ kHIDUsage_PID_Phase = 0x71, /* XXX */ kHIDUsage_PID_Period = 0x72, /* XXX */ kHIDUsage_PID_SetConstantForceReport = 0x73, /* XXX */ kHIDUsage_PID_SetRampForceReport = 0x74, /* XXX */ kHIDUsage_PID_RampStart = 0x75, /* XXX */ kHIDUsage_PID_RampEnd = 0x76, /* XXX */ kHIDUsage_PID_EffectOperationReport = 0x77, /* XXX */ kHIDUsage_PID_EffectOperation = 0x78, /* XXX */ kHIDUsage_PID_OpEffectStart = 0x79, /* XXX */ kHIDUsage_PID_OpEffectStartSolo = 0x7A, /* XXX */ kHIDUsage_PID_OpEffectStop = 0x7B, /* XXX */ kHIDUsage_PID_LoopCount = 0x7C, /* XXX */ kHIDUsage_PID_DeviceGainReport = 0x7D, /* XXX */ kHIDUsage_PID_DeviceGain = 0x7E, /* XXX */ kHIDUsage_PID_PoolReport = 0x7F, /* XXX */ kHIDUsage_PID_RAM_PoolSize = 0x80, /* XXX */ kHIDUsage_PID_ROM_PoolSize = 0x81, /* XXX */ kHIDUsage_PID_ROM_EffectBlockCount = 0x82, /* XXX */ kHIDUsage_PID_SimultaneousEffectsMax = 0x83, /* XXX */ kHIDUsage_PID_PoolAlignment = 0x84, /* XXX */ kHIDUsage_PID_PoolMoveReport = 0x85, /* XXX */ kHIDUsage_PID_MoveSource = 0x86, /* XXX */ kHIDUsage_PID_MoveDestination = 0x87, /* XXX */ kHIDUsage_PID_MoveLength = 0x88, /* XXX */ kHIDUsage_PID_BlockLoadReport = 0x89, /* XXX */ /* 0x8A Reserved */ kHIDUsage_PID_BlockLoadStatus = 0x8B, /* XXX */ kHIDUsage_PID_BlockLoadSuccess = 0x8C, /* XXX */ kHIDUsage_PID_BlockLoadFull = 0x8D, /* XXX */ kHIDUsage_PID_BlockLoadError = 0x8E, /* XXX */ kHIDUsage_PID_BlockHandle = 0x8F, /* XXX */ kHIDUsage_PID_BlockFreeReport = 0x90, /* XXX */ kHIDUsage_PID_TypeSpecificBlockHandle = 0x91, /* XXX */ kHIDUsage_PID_StateReport = 0x92, /* XXX */ /* 0x93 Reserved */ kHIDUsage_PID_EffectPlaying = 0x94, /* XXX */ kHIDUsage_PID_DeviceControlReport = 0x95, /* XXX */ kHIDUsage_PID_DeviceControl = 0x96, /* XXX */ kHIDUsage_PID_DC_EnableActuators = 0x97, /* XXX */ kHIDUsage_PID_DC_DisableActuators = 0x98, /* XXX */ kHIDUsage_PID_DC_StopAllEffects = 0x99, /* XXX */ kHIDUsage_PID_DC_DeviceReset = 0x9A, /* XXX */ kHIDUsage_PID_DC_DevicePause = 0x9B, /* XXX */ kHIDUsage_PID_DC_DeviceContinue = 0x9C, /* XXX */ /* 0x9d - 0x9E Reserved */ kHIDUsage_PID_DevicePaused = 0x9F, /* XXX */ kHIDUsage_PID_ActuatorsEnabled = 0xA0, /* XXX */ /* 0xA1 - 0xA3 Reserved */ kHIDUsage_PID_SafetySwitch = 0xA4, /* XXX */ kHIDUsage_PID_ActuatorOverrideSwitch = 0xA5, /* XXX */ kHIDUsage_PID_ActuatorPower = 0xA6, /* XXX */ kHIDUsage_PID_StartDelay = 0xA7, /* XXX */ kHIDUsage_PID_ParameterBlockSize = 0xA8, /* XXX */ kHIDUsage_PID_DeviceManagedPool = 0xA9, /* XXX */ kHIDUsage_PID_SharedParameterBlocks = 0xAA, /* XXX */ kHIDUsage_PID_CreateNewEffectReport = 0xAB, /* XXX */ kHIDUsage_PID_RAM_PoolAvailable = 0xAC, /* XXX */ /* 0xAD - 0xFFFF Reserved */ kHIDUsage_PID_Reserved = 0xFFFF }; #ifdef __cplusplus } #endif #endif /* __PID__ */ \ No newline at end of file