USB HID Overview

The Human Interface Device (HID) class is one of several device classes described by the USB (Universal Serial Bus) architecture. The HID class consists primarily of devices humans use to control a computer system’s operations. Examples of such HID class devices include:

OS X provides the HID Manager (described in The HID Manager) to support access to any devices that conform to the USB HID specification. While this is most commonly used for communicating with input devices, a number of other devices also use HID descriptors, and can thus be accessed using the same mechanism.

For example, you can use the HID Manager to get information from many UPS (uninterruptible power supply) devices. UPS devices share the same report descriptor structure as other HID class devices and provide information such as voltage, current, and frequency. To control a UPS device, however, you access the device’s information using HID Manager functions and use it to drive the Power Manager, a process not described in this document.

HID interfaces are also sometimes used as a mechanism to peek and poke small amounts of data when communicating with certain devices that you might not think of as being human–interface-related. For example, there are various generic interface chips designed to provide low-bandwidth control of and input from non-computing devices, such as motor controllers, thermistors, and so on.

HID Class Terminology and Concepts

Information about a HID class device is contained in its HID report descriptors. The report descriptors are provided by the kernel-resident driver of the device and contain descriptions of each piece of data generated by the device. A key component of these report descriptors is the usage information defined in the USB HID Usage Tables. (You can download these from http://www.usb.org/developers/hidpage.) Usage values describe three basic types of information about the device:

Taken together, the usage page and usage number define a unique constant that describes a particular type of device or part of that device. For example, on the Generic Desktop usage page (page number 0x01), usage number 0x05 is a game pad and usage number 0x39 is a hat switch.

Logically distinct components of a HID class device such as an x axis, y axis, dial, or slider, are called elements. Information about the elements of a HID class device are grouped into arrays of nested dictionaries. The top or outer level element usually describes the device itself. For example, the top level element for a game pad would include usage page 0x01 (generic desktop) and usage number 0x05 (game pad) followed by an array of other elements. For a game pad that contains both a pointing device and some number of buttons, this array would contain an element for the pointing device and an element for each button. In turn, the element representing the pointing device would probably contain its own array of elements, each representing an axis.

Each element dictionary contains the element cookie (a 32-bit value used to reference that specific element), the usage page and usage number, the collection type, and perhaps other information such as the element’s minimum and maximum (for example, an x-axis might have a minimum of -127 and a maximum of 127), and whether or not the element has a preferred state. The element information for all HID class devices currently attached to the running system is available in the I/O Registry so you can check to see if a device has the elements you need before you create a device interface to communicate with it.

The HID Manager

The OS X HID Manager consists of three layers:

As an application developer, you will be directly concerned only with the first layer, the HID Manager client API, which this document simply calls the HID Manager. You can access information about the HID Manager from the Sample Code > Hardware & Drivers > Human Interface Device & Force Feedback section of the developer documentation website.

Device Interface Functions

The HID Manager includes IOHIDManager.h, IOHIDLib.h, and IOHIDKeys.h (located in /System/Library/Frameworks/IOKit.framework/Headers/hid) which define the property keys that describe a device, the element keys that describe a device’s elements, and the device interface functions and data structures you use to communicate with a device. After you’ve created a device interface for a selected HID class device, you can use the device interface functions to open and close the device, get the most recent value of an element, or set an element value. For the complete list of functions, see IOHIDLib.h.

Modern HID manager functions pass around raw HID reports (arrays of bytes). The HID manager provides tools for working with these reports and simple abstraction layers that allow you to perform many tasks without needing to understand the structure of these reports.

Many legacy device interface functions such as getElementValue, getNextEvent, and setElementDefault use a structure called the IOHIDEventStruct to contain information about events. (An event is the value of a particular element along with the time it occurred.) These legacy functions that need access to the value of an element use the IOHIDEventStruct even though some may ignore the time the value occurred.

Queues

Once you’ve created a device interface, you can use functions provided by the HID Manager to get the most recent value of an element. For many elements this is sufficient. If, however, you need to keep track of all values of an element, rather than just the most recent one, you can use functions provided by the HID Manager to create a queue and add the element to it. Then, all events involving that element will be contained in the queue (up to the queue depth).

For example, during game play, it’s not necessary to keep track of every value of a game device’s x and y axis, it’s sufficient to update the state of the game to the most recent values of these elements. If there’s a “fire” button, however, it’s important to respond to every button press, not just the most recent one, so you should add the “fire” button to a queue. Then, every time through the game loop, you can read the queue until it’s empty and you won’t miss any “fire" events.