[PD-cvs] externals/io/hidio/HID Utilities Source HID Utilities Read Me.rtf, NONE, 1.1 HIDLib.h, NONE, 1.1 HID_APIs.h, NONE, 1.1 HID_CFM.c, NONE, 1.1 HID_Config_Utilities.c, NONE, 1.1 HID_Config_Utilities.h, NONE, 1.1 HID_Error_Handler.c, NONE, 1.1 HID_Error_Handler.h, NONE, 1.1 HID_Name_Lookup.c, NONE, 1.1 HID_Name_Lookup.h, NONE, 1.1 HID_Queue_Utilities.c, NONE, 1.1 HID_Queue_Utilities.h, NONE, 1.1 HID_Transaction_Utilities.c, NONE, 1.1 HID_Transaction_Utilities.h, NONE, 1.1 HID_Utilities.c, NONE, 1.1 HID_Utilities.h, NONE, 1.1 HID_Utilities_CFM.h, NONE, 1.1 HID_Utilities_External.h, NONE, 1.1 HID_Utilities_Internal.h, NONE, 1.1 IOHIDPowerUsage.h, NONE, 1.1 ImmrHIDUtilAddOn.c, NONE, 1.1 ImmrHIDUtilAddOn.h, NONE, 1.1 PID.h, NONE, 1.1

Hans-Christoph Steiner eighthave at users.sourceforge.net
Thu Nov 30 06:47:58 CET 2006


Update of /cvsroot/pure-data/externals/io/hidio/HID Utilities Source
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2762

Added Files:
	HID Utilities Read Me.rtf HIDLib.h HID_APIs.h HID_CFM.c 
	HID_Config_Utilities.c HID_Config_Utilities.h 
	HID_Error_Handler.c HID_Error_Handler.h HID_Name_Lookup.c 
	HID_Name_Lookup.h HID_Queue_Utilities.c HID_Queue_Utilities.h 
	HID_Transaction_Utilities.c HID_Transaction_Utilities.h 
	HID_Utilities.c HID_Utilities.h HID_Utilities_CFM.h 
	HID_Utilities_External.h HID_Utilities_Internal.h 
	IOHIDPowerUsage.h ImmrHIDUtilAddOn.c ImmrHIDUtilAddOn.h PID.h 
Log Message:
moved over sources from externals/hcs/hid/HID Utilities Source.  This is not just a straight download of the .sit package, it includes some necessary updates that were posted to the Apple lists.  See the history in externals/hcs/hid/HID Utilities Source for more info.

--- NEW FILE: PID.h ---
(This appears to be a binary file; contents omitted.)

--- NEW FILE: HID_Utilities_CFM.h ---
/*
	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_

--- NEW FILE: HID_APIs.h ---

/*
	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


--- NEW FILE: IOHIDPowerUsage.h ---
/*
	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__ */


--- NEW FILE: HID_CFM.c ---
/*
 	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"
// ==================================

--- NEW FILE: HID_Error_Handler.c ---
/*
	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
}

--- NEW FILE: HID_Error_Handler.h ---
/*
	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
--- NEW FILE: HID_Name_Lookup.c ---
/*
	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;
}

--- NEW FILE: HID_Config_Utilities.h ---
/*
	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


--- NEW FILE: HID_Name_Lookup.h ---
/*
	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_


--- NEW FILE: HID_Utilities_External.h ---
/*
	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_

--- NEW FILE: HID_Utilities.c ---
/*
	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
[...2159 lines suppressed...]
		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;
}

--- NEW FILE: HID_Config_Utilities.c ---
/*
	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;
}

--- NEW FILE: HIDLib.h ---
/*
	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
--- NEW FILE: HID_Utilities.h ---
/*
	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_

--- NEW FILE: HID Utilities Read Me.rtf ---
{\rtf1\mac\ansicpg10000\cocoartf102
{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\vieww17000\viewh11120\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural

\f0\fs22 \cf0 HID Utilities Source\
Human Interface Device Manager Utility Functions\
\
Version 3.7		28 Oct 2K2\
			General cleanup for web posting.\
\
Version 3.6		23 Oct 2K2\
			Added new API's: HIDSetElementValue, HIDSetQueueCallback, HIDGetReport, HIDSetReport & HIDPrintElement,\
			Note: <IOHIDPowerUsage.h> & <PID.h> have been incorporated into <IOKit/hid/IOHIDUsageTables.h>.\
\
Version 3.5		10 Aug 2K2\
			HIDConfigureAction now only checks kHIDElementTypeInput elements.\
			Changed some "for (x=0;x<n;x++) i[x] = 0;" code to use bzero instead.\
			Moved device & element finding code into its own routines: HIDFindActionDeviceAndElement & HIDFindSubElement.\
			The original HID utilities depended on the BSD FILE* implementation for HID[Save/Restore]ElementConfig and didn't work in CFM applications.\
			So two new routine (HIDSaveElementPref & HIDRestoreElementPref) were added that use the CFPreferences API's instead. \
\
Version 3.4		Added code to support hot plugging & un-plugging devices. Note to developers: It's very important to use the HIDIsValidDevice\
			and HIDIsValidElement API's to verify that cached device or element pointers are still valid before de-referencing them.\
			This validation code has been added to all HID Utilities AIP's that take a device or element pointer as a parameter.\
			Note also that this required that queueRunLoopSource and notification port fields be added to the device record. (see <HID_Utilities.h>)\
\
Version 3.3		Added output transaction support for UPS & FFB devices (see <HID_Transaction_Utilities.c> & <HID_Transaction_Utilities.h>).\
\
Version 3.2		Since 10.2 changed the cookie numbers (by adding a usage == -1element for arrays) a cookie agnostic method of getting\
			device and element names was needed. Plus the nested (device & element) switch statements hardcoding the strings.\
			So all the device, element & cookie strings have been moved out of the source file(s) and put into XML data files instead.\
			NOTE: all local (static) routines now begin with "hid_" instead of "HID".\
			All references to "Kernel/IOKit/hidsystem/" now (correctly) point to "IOKit/hid/" instead.\
\
Version 3.1: 	Added the basics of a element naming scheme.  Right now it just supports one device (macally iShock) but as I get more \
			device info I can add other devices (feel free to add to the name lookup file and send me the results).  Added bad device \
			and element chencking in config/save.  Fixed one case of swapped usage page and usage variables.  Fixed a few leaks \
			noted by a developer.  Add a NULL check to top level element handler to prevent NULL deference also noted by developer.  \
			Checked build with gcc3. Rebuilt bundle and static lib.\
\
Version 3.0: 	Major Change: Added CFM support.\
			Project now can be built in three different ways with the interface being straight C with Mac OS X type reliance, thus completely\
			suitable for CFM or MachO binary formats and Carbon, Cocoa, or command line interfaces.\
\
			- Static Library: For use with Mac OS X MachO projects.  The build product (in the build directory) can be static linked\
			  into any exisiting Mac OS X MachO project.  The project should include HID_Utilities_External.h only for declarations.\
\
			- Source: This is just including the HID Utilities source files in the target project.  Works as previous, but now all the \
			  declarations needed are in the HID_Utilities_External.h header file.\
\
			- Dynamic Library: Should only be used by CFM applications.  There are some notes which MUST be followed.  See the HID Explorer\
			  or the HID Config Save samples for CW7 projects which show the actual use of the library.  The dylib is housed in a bundle\
			  which the CFM app finds at runtime and calls into.  This bundle is included and the dylib project will automatically place\
			  the actual dylib in the bundle (contents/MacOS/). NOTE: The path to this is an absolute path for the build product of the \
			  project, you MUST modify this if you rebuild the dylib (which never be required).  To do this select the prject name in the\
			  Files tab and Get Info.  Point the build product to the HID.bundle/contents/MacOS/ directory in the HID Utilities directory.\
			  Then point the intermediates to the intermediates directory already in the build directory.  This is required since the build\
			  product path is absolute and can't be project relative (yes, a bug has been filed). Again, this is only if you wnat to rebuild\
			  the dylib used for CFM applications.  Also note, you must copy the HID.bundle into your application directory (if you are using\
			  the method in the sample to find the bundle) for your CFM application to use it.\
				  \
			Other Notes:\
			  The interface is now completely Mac OS X type free. This means minor mods to your projects.  See the element and device structures\
			  for guidence on the types.  For example cookies now should be void *'s.  Fixed a couple bugs in allocating queues.  CLean up error\
			  checking to only dump DebugStrs if the source is used (vice the static or dynamic libraries).\
\
Version 2.0: 	Update. Fixed some 10.1 issues, notably spelling errors in constants and include differences.  Fixed 10.0.x errors, notably \
			type errors in retrieving element info, negative value handling (see GetElementValue), queuing error, and other minor changes.\
			Major change in element list handling...  Elements are now stored in a binary tree to mimic the tree sturcture of the \
			device.  This allows hierarchial diplay and parsing (See HID Explorer sample). Additionally, some of the routine declarations \
			have chnaged to work with this tree structure, one can still get same list functionality by using GetNextDeviceElement routine \
			with kHIDElementTypeIO constant. Collections are now stored in tree, so users of these functions must understand if they are \
			looking at a valid IO element or a collection. Lastly, new parsing strings and two new headers are included to aid in decoding \
			PID and power device elements.\
\
Version 1.0: 	Initial release featuring functions to get HID device list, get devices and elements, poll for values, setup queues and get events, \
			handle configuration set up and saving/restoring of configurations.\
\
----\
\
This group of utilities is stand alone code to help developers work more easily with the HID Manager for Mac OS X with both MachO and CFM support.  \
It provides a high level abstract of the current HID interface that sacrifices slight flexibility in favor single function set up, device and element \
retrieval, current value and event query, and configuration.  This sample is the source code for the Utilities and does not provide a sample of the \
utilization.  There are other samples which provide complete working examples of a HID device explorer and a simple game implementation.  More samples \
will be forth coming shortly.\
\
This set of utilities is constantly evolving to both address any bugs and provide better support for developer requested features.\
Any suggestions and/or bugs can be directed to the Apple bug reporter at:\
<http://developer.apple.com/bugreporter/index.html>\
\
// ==================================\
\
// Device and Element Interfaces\
\
enum HIDElementTypeMask\
\{\
	kHIDElementTypeInput				= 1 << 1,\
	kHIDElementTypeOutput            			= 1 << 2,\
	kHIDElementTypeFeature           			= 1 << 3,\
	kHIDElementTypeCollection        			= 1 << 4,\
	kHIDElementTypeIO					= kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature,\
	kHIDElementTypeAll					= kHIDElementTypeIO | kHIDElementTypeCollection\
\};\
typedef enum HIDElementTypeMask 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 (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\
\{\
    void * interface;						// interface to device, NULL = no interface\
    void * queue;							// device queue, NULL = no queue\
    char transport[256];						// 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\
    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;\
\
// ==================================\
\
// 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)\
unsigned char HIDBuildDeviceList (unsigned long usagePage, unsigned long 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\
void HIDReleaseDeviceList (void);\
\
// does a device list exist\
unsigned char HIDHaveDeviceList (void);\
\
// how many HID devices have been found\
// returns 0 if no device list exist\
unsigned long 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\
unsigned long HIDCountDeviceElements (pRecDevice pDevice, HIDElementTypeMask typeMask);\
\
// get the first device in the device list\
// returns NULL if no list exists\
pRecDevice HIDGetFirstDevice (void);\
\
// get next device in list given current device as parameter\
// returns NULL if end of list\
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\
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\
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\
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\
void HIDGetTypeName (unsigned long 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\
void HIDGetUsageName (long valueUsagePage, long valueUsage, char * cstrName);\
\
// ==================================\
\
// 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\
unsigned long  HIDQueueElement (pRecDevice pDevice, pRecElement pElement);\
\
// adds all elements to queue, performing any device queue set up required\
unsigned long  HIDQueueDevice (pRecDevice pDevice);\
\
// removes element for queue, if last element in queue will release queue and device\
unsigned long  HIDDequeueElement (pRecDevice pDevice, pRecElement pElement);\
\
// completely removes all elements from queue and releases queue and device\
unsigned long  HIDDequeueDevice (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\
unsigned char HIDGetEvent (pRecDevice pDevice, void * pHIDEvent);\
\
// returns current value for element, creating device interface as required, polling element\
// Note: this DOES NOT release the inteface so applications must properly release devices via ReleaseHIDDeviceList\
long HIDGetElementValue (pRecDevice pDevice, pRecElement pElement);\
\
// 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\
long HIDCalibrateValue (long 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\
long HIDScaleValue (long value, pRecElement pElement);\
\
// ==================================\
\
// Conguration and Save Interfaces\
\
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\
unsigned char HIDConfigureAction (pRecDevice * ppDevice, pRecElement * ppElement, float timeout);\
\
// take input records, save required info\
// assume file is open and at correct position.\
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\
long HIDRestoreElementConfig (FILE * fileRef, pRecDevice * ppDevice, pRecElement * ppElement);\
\
----\
\
Requirements: Mac OS X, Project Builder (CodeWarrior 7 for sample CFM projects)\
\
We hope this helps people get up and running with HID Manager in a quick and painless manner.\
\
ggs}
--- NEW FILE: HID_Transaction_Utilities.c ---
/*
	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;
}

--- NEW FILE: HID_Transaction_Utilities.h ---
/*
	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_


--- NEW FILE: ImmrHIDUtilAddOn.h ---
/*
 *  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 );

--- NEW FILE: HID_Queue_Utilities.c ---
/*
	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
--- NEW FILE: HID_Utilities_Internal.h ---
/*
	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_


--- NEW FILE: ImmrHIDUtilAddOn.c ---
/*
 *  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 );
}
--- NEW FILE: HID_Queue_Utilities.h ---
/*
	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_






More information about the Pd-cvs mailing list