Sample Code

OSX Driver and Kext Samples/ HID_LED_test_tool/ HID_LED_test_tool/ main.c/

//
//	File:		main.c
//
//	Contains:	main source code to HID LED test tool
//
//	Copyright:	Copyright (c) 2007 Apple Inc., All Rights Reserved
//
//	Disclaimer: IMPORTANT:	This Apple software is supplied to you by
//				Apple Inc. ("Apple") in consideration of your agreement to the
//				following terms, and your use, installation, modification or
//				redistribution of this Apple software constitutes acceptance of these
//				terms.	If you do not agree with these terms, please do not use,
//				install, modify or redistribute this Apple software.
//
//				In consideration of your agreement to abide by the following terms, and
//				subject to these terms, Apple grants you a personal, non-exclusive
//				license, under Apple's copyrights in this original Apple software (the
//				"Apple Software"), to use, reproduce, modify and redistribute the Apple
//				Software, with or without modifications, in source and/or binary forms;
//				provided that if you redistribute the Apple Software in its entirety and
//				without modifications, you must retain this notice and the following
//				text and disclaimers in all such redistributions of the Apple Software.
//				Neither the name, trademarks, service marks or logos of Apple Inc.
//				may be used to endorse or promote products derived from the Apple
//				Software without specific prior written permission from Apple.	Except
//				as expressly stated in this notice, no other rights or licenses, express
//				or implied, are granted by Apple herein, including but not limited to
//				any patent rights that may be infringed by your derivative works or by
//				other works in which the Apple Software may be incorporated.
//
//				The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
//				MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
//				THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
//				FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
//				OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
//				IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
//				OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//				SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//				INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
//				MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
//				AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
//				STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
//				POSSIBILITY OF SUCH DAMAGE.
//
// ****************************************************
#pragma mark -
#pragma mark * complation directives *
// ----------------------------------------------------

#ifndef FALSE
#define FALSE 0
#define TRUE !FALSE
#endif

// ****************************************************
#pragma mark -
#pragma mark * includes & imports *
// ----------------------------------------------------

#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDLib.h>

// ****************************************************
#pragma mark -
#pragma mark * typedef's, struct's, enums, defines, etc. *
// ----------------------------------------------------
// function to create a matching dictionary for usage page & usage
static CFMutableDictionaryRef hu_CreateMatchingDictionaryUsagePageUsage( Boolean isDeviceNotElement,
																		UInt32 inUsagePage,
																		UInt32 inUsage )
{
	// create a dictionary to add usage page / usages to
	CFMutableDictionaryRef result = CFDictionaryCreateMutable( kCFAllocatorDefault,
															  0,
															  &kCFTypeDictionaryKeyCallBacks,
															  &kCFTypeDictionaryValueCallBacks );
	
	if ( result ) {
		if ( inUsagePage ) {
			// Add key for device type to refine the matching dictionary.
			CFNumberRef pageCFNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &inUsagePage );
			
			if ( pageCFNumberRef ) {
				if ( isDeviceNotElement ) {
					CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsagePageKey ), pageCFNumberRef );
				} else {
					CFDictionarySetValue( result, CFSTR( kIOHIDElementUsagePageKey ), pageCFNumberRef );
				}
				CFRelease( pageCFNumberRef );
				
				// note: the usage is only valid if the usage page is also defined
				if ( inUsage ) {
					CFNumberRef usageCFNumberRef = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &inUsage );
					
					if ( usageCFNumberRef ) {
						if ( isDeviceNotElement ) {
							CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsageKey ), usageCFNumberRef );
						} else {
							CFDictionarySetValue( result, CFSTR( kIOHIDElementUsageKey ), usageCFNumberRef );
						}
						CFRelease( usageCFNumberRef );
					} else {
						fprintf( stderr, "%s: CFNumberCreate( usage ) failed.", __PRETTY_FUNCTION__ );
					}
				}
			} else {
				fprintf( stderr, "%s: CFNumberCreate( usage page ) failed.", __PRETTY_FUNCTION__ );
			}
		}
	} else {
		fprintf( stderr, "%s: CFDictionaryCreateMutable failed.", __PRETTY_FUNCTION__ );
	}
	return result;
}	// hu_CreateMatchingDictionaryUsagePageUsage

int main( int argc, const char * argv[] )
{
#pragma unused ( argc, argv )
	
	// create a IO HID Manager reference
	IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone );
	require( tIOHIDManagerRef, Oops );
	
	// Create a device matching dictionary
	CFDictionaryRef matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( TRUE,
																				  kHIDPage_GenericDesktop,
																				  kHIDUsage_GD_Keyboard );
	require( matchingCFDictRef, Oops );
	
	// set the HID device matching dictionary
	IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef );
	
	if ( matchingCFDictRef ) {
		CFRelease( matchingCFDictRef );
	}
	
	// Now open the IO HID Manager reference
	IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone );
	require_noerr( tIOReturn, Oops );
	
	// and copy out its devices
	CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef );
	require( deviceCFSetRef, Oops );
	
	// how many devices in the set?
	CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef );
	
	// allocate a block of memory to extact the device ref's from the set into
	IOHIDDeviceRef * tIOHIDDeviceRefs = malloc( sizeof( IOHIDDeviceRef ) * deviceCount );
	require( tIOHIDDeviceRefs, Oops );
	
	// now extract the device ref's from the set
	CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs );
	
	// before we get into the device loop we'll setup our element matching dictionary
	matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( FALSE, kHIDPage_LEDs, 0 );
	require( matchingCFDictRef, Oops );
	
	int pass;	// do 256 passes
	for ( pass = 0; pass < 256; pass++ ) {
		Boolean delayFlag = FALSE;	// if we find an LED element we'll set this to TRUE
		
		printf( "pass = %d.\n", pass );
		for ( deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++ ) {
			
			// if this isn't a keyboard device...
			if ( !IOHIDDeviceConformsTo( tIOHIDDeviceRefs[deviceIndex], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ) ) {
				continue;	// ...skip it
			}
			
			printf( "	 device = %p.\n", tIOHIDDeviceRefs[deviceIndex] );
			
			// copy all the elements
			CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRefs[deviceIndex],
																		   matchingCFDictRef,
																		   kIOHIDOptionsTypeNone );
			require( elementCFArrayRef, next_device );
			
			// for each device on the system these values are divided by the value ranges of all LED elements found
			// for example, if the first four LED element have a range of 0-1 then the four least significant bits of 
			// this value will be sent to these first four LED elements, etc.
			int device_value = pass;
			
			// iterate over all the elements
			CFIndex elementIndex, elementCount = CFArrayGetCount( elementCFArrayRef );
			for ( elementIndex = 0; elementIndex < elementCount; elementIndex++ ) {
				IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, elementIndex );
				require( tIOHIDElementRef, next_element );
				
				uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef );
				
				// if this isn't an LED element...
				if ( kHIDPage_LEDs != usagePage ) {
					continue;	// ...skip it
				}
				
				uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
				IOHIDElementType tIOHIDElementType = IOHIDElementGetType( tIOHIDElementRef );
				
				printf( "		 element = %p (page: %d, usage: %d, type: %d ).\n",
					   tIOHIDElementRef, usagePage, usage, tIOHIDElementType );
				
				// get the logical mix/max for this LED element
				CFIndex minCFIndex = IOHIDElementGetLogicalMin( tIOHIDElementRef );
				CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef );
				
				// calculate the range
				CFIndex modCFIndex = maxCFIndex - minCFIndex + 1;
				
				// compute the value for this LED element
				CFIndex tCFIndex = minCFIndex + ( device_value % modCFIndex );
				device_value /= modCFIndex;
				
				printf( "			 value = 0x%08lX.\n", tCFIndex );
				
				uint64_t timestamp = 0; // create the IO HID Value to be sent to this LED element
				IOHIDValueRef tIOHIDValueRef = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, tIOHIDElementRef, timestamp, tCFIndex );
				if ( tIOHIDValueRef ) {
					// now set it on the device
					tIOReturn = IOHIDDeviceSetValue( tIOHIDDeviceRefs[deviceIndex], tIOHIDElementRef, tIOHIDValueRef );
					CFRelease( tIOHIDValueRef );
					require_noerr( tIOReturn, next_element );
					delayFlag = TRUE;	// set this TRUE so we'll delay before changing our LED values again
				}
			next_element:	;
				continue;
			}
		next_device: ;
			CFRelease( elementCFArrayRef );
			continue;
		}
		
		// if we found an LED we'll delay before continuing
		if ( delayFlag ) {
			usleep( 500000 ); // sleep one half second
		}
	}						  // next pass
	
	if ( tIOHIDManagerRef ) {
		CFRelease( tIOHIDManagerRef );
	}
	
	if ( matchingCFDictRef ) {
		CFRelease( matchingCFDictRef );
	}
Oops:	;
	return 0;
} /* main */

Our Services

  • What our customers say about us?

© 2011-2024 All Rights Reserved. Joya Systems. 4425 South Mopac Building II Suite 101 Austin, TX 78735 Tel: 800-DEV-KERNEL

Privacy Policy. Terms of use. Valid XHTML & CSS