| 
	
		  
			| 
			By Michael Dolinar - Wednesday, 2 May, 2012 There are several classes of USB device. One of these is the HID (Human 
			Interface Device) class. The HID class of device includes things like 
			keyboards, mice, joysticks and some data acquisition hardware!
 In this article, we will be looking at Apple’s supplied interface for 
			accessing the HID class devices attached to your system. Particularly, 
			we’ll be using the HID Manager to detect I/O devices from ONTRAK Control 
			Systems. If you don’t have any of ONTRAK’s USB I/O devices, don’t worry 
			- the code will work for detecting HID devices from any manufacturer.
 Note: retrieving and sending data to the USB device will be covered in 
			part 2.
 Apple’s HID Manager provides a very neat way to work with HID devices. 
			Since the HID Manager interfaces with all of the system’s HID devices, 
			we’ll use a matching dictionary to tell the HID Manager which devices 
			we’re interested in. Then we’ll register some callback functions do 
			detect the addition or removal of USB devices. Finally, we’ll query the 
			HID Manager to get a device set that we’ll use to count the devices that 
			match our dictionary.
 Pseudocode for initialization of our app:
 
 
 
				Create an HID 
				Manager
 Create a Matching Dictionary Specify a device manufacturer in the 
				Matching Dictionary
 Register the Matching Dictionary to the 
				HID Manager
 Register a callback for USB device 
				detection with the HID Manager Register a callback fro USB device 
				removal with the HID Manager
 Register the HID Manager on our app’s 
				run loop   Open the 
				HID Manager Let’s dive right into the implementation! Create a new Cocoa application
 - Crack open Xcode 4 & select Create a new Xcode project
 -Under Mac OS X / Application select Cocoa Application
 -Click Next
 -For simplicity, use the same project name as me: USBHID
 -Use the same value for class prefix too: USBHID
 -Click Next
 -Select a folder where you’d like to save your project
 -Click Create
 Ah, there’s nothing like a shiny new Cocoa app!
 Before we begin coding, we need to add the IOKit framework:
 -Click on the project root USBHID
 -In the Linked Frameworks and Libraries section, click the +
 -In the search field, type IOKit
 -Select the IOKit.framework
 -Click Add
 Well done! Let’s start coding!
 Click on the USBHIDAppDelegate.m file to begin coding. We start by 
			importing IOHIDManager.h header file. Insert this line after the other 
			#import statements:
 
 
			#import "IOKit/hid/IOHIDManager.h" Next, move your cursor down to the function 
			named:applicationDidFinishLaunching:
 This is where you’ll write your initialization code. We’ll start coding 
			right after the Apple-supplied comment:
 // Insert code here to initialize your application
 Enter the following code to accomplish the tasks listed in our 
			pseudocode:
 
 // Create an HID Manager 
 IOHIDManagerRef HIDManager =
			IOHIDManagerCreate(kCFAllocatorDefault,
			
                                                    
			kIOHIDOptionsTypeNone);
 
 // Create a Matching Dictionary
 CFMutableDictionaryRef 
			matchDict = CFDictionaryCreateMutable(
                                                   
			kCFAllocatorDefault,                                                    
			2,                                                     
			&kCFTypeDictionaryKeyCallBacks,                                                     
			&kCFTypeDictionaryValueCallBacks); 
 
 // Specify a device manufacturer in the Matching 
			Dictionary
 CFDictionarySetValue(matchDict, 
                                            
			CFSTR(kIOHIDManufacturerKey), 
                                            
			CFSTR("www.ontrak.net"));
			
 
 // Register the Matching Dictionary to the HID 
			Manager
 IOHIDManagerSetDeviceMatching(HIDManager, 
			matchDict);  No doubt you’ve noticed that we stopped short of 
			registering the callback functions. Why you ask? Simply because we 
			haven’t declared them yet, and Xcode will complain when we try to 
			register a callback to a function that doesn’t exist. At this point, it’s worth noting that we’ve specified a manufacturer 
			name of “www.ontrak.net”. This tells the HID Manager to react only to 
			devices with this manufacturer name. If you want to detect another 
			manufacturer’s devices, just change this string to the device 
			manufacturer’s name. For example, you can substitute “Apple Inc.” for 
			“www.ontrak.net” and the HID Manager will detect the Apple USB HID 
			devices connected to your system.
 Editors Note:  An 
			alternative way to detect a particular manufacturers device is to use 
			the Manufacturer ID , which is HEX 0A07 for Ontrak Control Systems 
			devices. All manufacturers of USB based products are assigned a 4 digit 
			Hex code by usb.org Let’s take a minute to declare our callback functions in the our 
			application’s header file. Open the USBHIDAppDelegate.h by clicking on 
			it. Start by importing the all important HIDManager.h file by entering 
			the following line of code after the other #import statements:
 
 |  
			| #import 
			"IOKit/hid/IOHIDManager.h" |  
			|   |  Now we can declare our callback functions. Enter the following code just 
		above the line that reads @end:
 
								// USB device added 
								callback function
 
								static void 
								Handle_DeviceMatchingCallback(void
								*inContext, 
                                                  
								IOReturn inResult, 
                                                  
								void *inSender, 
                                                  
								IOHIDDeviceRef inIOHIDDeviceRef);
 
 // USB device removed 
								callback function
 
								static void 
								Handle_DeviceRemovalCallback(void 
								*inContext, 
                                                  
								IOReturn inResult, 
                                                  
								void *inSender, 
                                                  
								IOHIDDeviceRef inIOHIDDeviceRef);
 
 // Counts the number of 
								devices in the device set (includes all USB devices 
								that match our dictionary)
 
								static long 
								USBDeviceCount(IOHIDManagerRef 
								HIDManager); The first line of code declares the function that 
							shall be called when a USB device is added. The second 
							is for USB device removal. The third line declares a counter function. We’re going 
							to implement this counter function to query the HID 
							Manager and return the number of matching devices. This 
							function is not a callback function.
 Let’s jump back to the implementation file and code 
							these babies! Click on the USBHIDAppDelegate.m file and 
							enter the following code just above the line that reads 
							@end:
 
 // New USB device specified 
							in the matching dictionary has been added (callback 
							function)
 
							static void 
							Handle_DeviceMatchingCallback(void 
							*inContext, 
                                                     
							IOReturn inResult, 
                                                     
							void *inSender, 
                                                     
							IOHIDDeviceRef inIOHIDDeviceRef){
 
 // Log the device ID & 
							device count
 NSLog(@"\nONTRAK 
							device added: %p\nONTRAK device count: %ld", 
                       
							(void *)inIOHIDDeviceRef,
							
                       
							USBDeviceCount(inSender));
 }
 
 
 
 
 
 // USB device specified in 
							the matching dictionary has been removed (callback 
							function)
 
							static void 
							Handle_DeviceRemovalCallback(void 
							*inContext, 
                                                          
							IOReturn inResult, 
                                                          
							void *inSender, 
                                                          
							IOHIDDeviceRef inIOHIDDeviceRef){
 
 // Log the device ID & 
							device count
 NSLog(@"\nONTRAK 
							device removed: %p\nONTRAK device count: %ld", 
                    
							(void *)inIOHIDDeviceRef,
							
                    
							USBDeviceCount(inSender));
 }
 
 
 
 
 
 // Counts the number of 
							devices in the device set (includes all USB devices that 
							match our dictionary)
      
							static long 
							USBDeviceCount(IOHIDManagerRef 
							HIDManager){
 
 // The device set includes 
							all USB devices that match our matching dictionary. 
							Fetch it.
      
							CFSetRef devSet = 
							IOHIDManagerCopyDevices(HIDManager);
 
 // The devSet will be NULL 
							if there are 0 devices, so only try to count the devices 
							if devSet exists
     
							if(devSet) return 
							CFSetGetCount(devSet);
 
 // There were no matching 
							devices (devSet was NULL), so return a count of 0
      
							return 0;
 }
 The first two functions look much the same: When a 
							device is attached or removed from the system, the 
							device’s identifier and the device count are printed to 
							the debug window. 
							 The USBDeviceCount function requests the device set from 
							the HID Manager, counts the devices in the set and 
							returns the result. This is where the device count is 
							generated for the callback functions.
  With the callback functions declared and implemented, we 
							can continue with our application initialization. Scroll 
							back up to the function:
 
                                                                                                  
							applicationDidFinishLaunching:
 Append our previous code in this function with the 
							following:
 
								// Register a callback 
								for USB device detection with the HID Manager
 
								IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, 
								&Handle_DeviceMatchingCallback,
								NULL);
 // Register a callback 
								fro USB device removal with the HID Manager
 
								IOHIDManagerRegisterDeviceRemovalCallback(HIDManager, 
								&Handle_DeviceRemovalCallback,
								NULL);
 
 // Register the HID 
								Manager on our app’s run loop
 
								IOHIDManagerScheduleWithRunLoop(HIDManager, 
								CFRunLoopGetMain(), 
								kCFRunLoopDefaultMode);
 
 // Open the HID Manager
 
								IOReturn IOReturn = 
								IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone);
 
								if(IOReturn) NSLog(@"IOHIDManagerOpen 
								failed."); // Couldn't open the HID manager! That does it! You can now click Xcode’s Run button to 
							compile & execute your project. 
							 When an ONTRAK Control Systems USB device is attached, 
							the debug window will show you the device ID and device 
							count. The code can manage multiple devices. Finally, 
							when disconnecting a device, another message will be 
							posted to the debug window.
 Complete Code Listing
 Complete code listing for the project’s header file:
 
							HIDManager.h
 
 
								
								#import <Cocoa/Cocoa.h>
 
								#import <IOKit/hid/IOHIDManager.h>
 
 
								@interface USBHIDAppDelegate :
								NSObject <NSApplicationDelegate>
 
 
								@property (assign)
								IBOutlet
								NSWindow *window;
 
 // USB device added 
								callback function
 
								static void 
								Handle_DeviceMatchingCallback(void 
								*inContext, 
                                   
								IOReturn inResult, 
                                   
								void *inSender, 
                                   
								IOHIDDeviceRef inIOHIDDeviceRef);
 
 // USB device removed 
								callback function
 
								static void 
								Handle_DeviceRemovalCallback(void 
								*inContext, 
                                   
								IOReturn inResult, 
                                   
								void *inSender, 
                                    
								IOHIDDeviceRef inIOHIDDeviceRef);
 
 // Counts the number of 
								devices in the device set (includes all USB devices 
								that match our dictionary)
 
								static long 
								USBDeviceCount(IOHIDManagerRef 
								HIDManager);
 
 @end Complete code listing for the project’s 
							implementation file: HIDManager.m
 
 
								
								#import "USBHIDAppDelegate.h"
								
 
								#import "IOKit/hid/IOHIDManager.h"
								
 
 
								@implementation USBHIDAppDelegate
 
 @synthesize window =
								_window;
 
 - (void)applicationDidFinishLaunching:(NSNotification 
								*)aNotification
 {
 // Insert code here to 
								initialize your application
 
 // Create an HID 
								Manager 
 IOHIDManagerRef 
								HIDManager = 
								IOHIDManagerCreate(kCFAllocatorDefault, 
                                         
								kIOHIDOptionsTypeNone);
 
 // Create a Matching 
								Dictionary
 
								CFMutableDictionaryRef matchDict = 
								CFDictionaryCreateMutable(kCFAllocatorDefault,
								
                                         
								2, 
                                          
								&kCFTypeDictionaryKeyCallBacks/span>,,
								
                                          
								&kCFTypeDictionaryValueCallBacks/span>);
								
 
 // Specify a device 
								manufacturer in the Matching Dictionary
 
								CCFDictionarySetValue(matchDict, 
                            
								CFSTR(span class="style_3">kIOHIDManufacturerKey)),
								
                            
								CFSTR(span class="style_9">"www.ontrak.net"));
								
 
 // Register the 
								Matching Dictionary to the HID Manager
 
								IOHIDManagerSetDeviceMatching(HIDManager, 
								matchDict); 
 
 // Register a callback 
								for USB device detection with the HID Manager
 
								IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, 
								&Handle_DeviceMatchingCallback,
								NULL);
 // Register a callback 
								fro USB device removal with the HID Manager
 
								IOHIDManagerRegisterDeviceRemovalCallback(HIDManager, 
								&Handle_DeviceRemovalCallback,
								NULL);
 
 // Register the HID 
								Manager on our app’s run loop
 
								IOHIDManagerScheduleWithRunLoop(HIDManager, 
								CFRunLoopGetMain(), 
								kCFRunLoopDefaultMode);
 
 // Open the HID Manager
 
								IOReturn IOReturn = 
								IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone);
 
								if(IOReturn) NSLog(@"IOHIDManagerOpen 
								failed."); // Couldn't open the HID manager! 
								TODO: proper error handling
 }
 
 
 
 
 
 
 // New USB device 
								specified in the matching dictionary has been added 
								(callback function)
 
								static void 
								Handle_DeviceMatchingCallback(void  
								*inContext, 
                                          
								IOReturn inResult, 
                                          
								void *inSender, 
                                          
								IOHIDDeviceRef inIOHIDDeviceRef){
 
 // Log the device ID & 
								device countbr />
								 
								NSLog((@"\nONTRAK device added: %p\nONTRAK 
								device count: %ld", 
                 
								(void/span>  
								*)inIOHIDDeviceRef, 
                 
								USBDeviceCount(inSender));
 }br />
								 
 
 
 
 
 // USB device specified 
								in the matching dictionary has been removed 
								(callback function)
 
								static void 
								Handle_DeviceRemovalCallback(void  
								*inContext, 
                                         
								IOReturn inResult, 
                                         
								void *inSender, 
                                         
								IOHIDDeviceRef inIOHIDDeviceRef){
 
 // Log the device ID & 
								device countbr />
								 
								NSLog((@"\nONTRAK device removed: %p\nONTRAK 
								device count: %ld", 
               
								(void/span>  
								*)inIOHIDDeviceRef, 
               
								USBDeviceCount(inSender));
 
 // TODO: make sure your 
								application doesn't try to do anything with the 
								removed devicebr />
								 }
 
 
 
 
 
 // Counts the number of 
								devices in the device set (incudes all USB devices 
								that match our dictionary)
 
								static long 
								USBDeviceCount(IOHIDManagerRef 
								HIDManager){
 
 // The device set 
								includes all USB devices that match our matching 
								dictionary. Fetch it.
 
								CFSetRef devSet = 
								IOHIDManagerCopyDevices(HIDManager);
 
 // The devSet will be 
								NULL if there are 0 devices, so only try to count 
								the devices if devSet exists
 
								if(devSet) return 
								CFSetGetCount(devSet);
 
 // There were no 
								matching devices (devSet was NULL), so return a 
								count of 0
 return
								0;
 }
 
 @@end 
 
 Download the Xcode 4 project fileUSBHID.zip. 
							View USB HID Device Access From 
							XCODE Part 2 
							This project was created on OS X 10.7.3 using Xcode 
							4.2.1.
 Thanks to Tom Fortin from ONTRAK Control Systems for 
							providing the ADU208 
							and
							ADU200 
							USB I/O devices used in 
							the development of this series of articles.
 
   
							Back to Programming Page> |