USB : USB Classes    A Closer Look at HID Class  

Page 1


HID devices can be used for all sorts of applications, like these:

  • data acquisition devices
  • test instruments
  • data loggers
  • devices to control hardware
  • display devices,
  • and of course keyboards, mice, and joysticks.

 

In fact, just about any kind of device that doesn't already fit into some other existing USB class, and in which a 64,000 byte per second data rate is acceptable, can usually be done better, faster, and more intelligently as a USB HID class device. And it will never require a special device driver to be installed, either.





Page 2


The designers of the HID class seem to have had lots of uses in mind for HID class in addition to keyboards, mice, and joysticks. You can tell by the way the HID spec was written. 

The writers of the HID class spec included things like this:

  • a way to encode the units of each data item:
    • linear and angular distances and velocities,
    • temperatures,
    • voltages and currents, 
    • even more complicated units can be declared.
  • Also, scale factors can be declared which can be large powers of 10.

Think about that: you wouldn’t need units and big scale factors for a device class that was intended to be limited to keyboards and mice.





Page 3


The way that HID class avoids separate device drivers is to make a protocol that is completely self describing, and centered on the data that will be passed back and forth between the PC and the USB HID-class peripheral.

That is, you start by exhaustively defining the data: which direction each data item goes (Peripheral -> PC, PC -> Peripheral, or both ways), the size of each item in bits, and so on.

 

  Click on the image for page view.




Page 4


In the process of designing your HID class device, you also collect the data items into groups called Reports.

Once the data is completely specified, you encode this information into tables of numbers called “descriptors,” which the PC reads when you plug your device into a USB cable. The information encoded into these descriptors enables the PC to figure out everything it needs to know about the device and the data it will send and receive. No custom device driver is needed.

(Yes, this is a lot of work to do. That's why HIDmaker FS does it for you!)

  Click on the image for page view.




Page 5


HID devices use only Control and Interrupt transfer types.

For these transfer types, USB rules say that a full speed USB device can send at most one packet (whose size can be up to 64 bytes) per 1 msec frame from any single Interrupt endpoint. That's a transfer rate of 64,000 bytes per second per USB Interface, equivalent to a serial port speed of over half a million Baud. That's more than fast enough for many, many applications.

The USB rules are much more restrictive for low speed devices: only one 8 byte packet can be sent every 10 msec from a single Interrupt endpoint, for a throughput of 800 bytes/sec.

Although many mouse, keyboard, and joystick devices happen to be low speed devices, there is no rule that says they have to be.





Page 6


HID class is designed to not waste precious USB bus bandwidth. One way it does this is to allow you to send only the number of bits that are actually meaningful for any given data item. Data item sizes can range from 1 bit to 32 bits, or anywhere in between.

That is, a real HID device (not those free demo programs that you see on the Web) is not limited to sending byte data. You can have 1 bit data items, 7 bit data items, 23 bit data items, or whatever is meaningful to your application.

Think about what that means for a second. If you need to send a number of data items that were measured with a 10-bit A/D converter, why should you have to waste 16 bits to send each data value? With a real HID class device, you only need to send the actual 10 bits that are meaningful, with all of these values packed together tightly at the sending end, and unpacked and separated at the receiving end.

The ability to send a mixture of odd sized data items is not just some obscure concept that nobody uses. This is used all the time in real commercial HID devices, e.g. keyboards, game controllers, mice, digitizer devices, simulation devices, and so on. A real HID device must be able to handle odd sized data items.





Page 7


This data is packed tightly into pre-defined Reports, which can be many packets long. A HID Report is not limited to a single packet.

A Report is a group of data items, that are packed together tightly as a series of bit fields, and sent between the PC host and the peripheral device. Each time the PC wants to send or receive new values for those data items, it sends or asks for a new Report. We will define the 3 types of Reports in a later slide in this tutorial.

Note that for simplicity, Reports use a prearranged, fixed format that you define as you design your device. The size, type, and order of data items in all the Reports are described in a Report Descriptor that gets sent to the PC during the enumeration process. (Writing a correct Report Descriptor is a tricky business, but you don't need to worry: HIDmaker FS will make a customized Report Descriptor for you, that precisely defines all the data items you define, and which tells the PC how to find it in a Report.)

Notice that we never said that the meaning of the data in a HID report had to be fixed, only that the format is fixed. You can easily build in plenty of flexibility into your data by keeping a simple fixed format, but by defining some extra variables that indicate what the data currently means.  (We show you how!)

 

  Click on the image for page view.




Page 8


In USB-speak, “IN” or “INPUT” always means “going toward the PC Host.”

Input items, therefore, are items that are ONLY transmitted from your peripheral device toward the PC host.Input Reports get sent IN to PC host, at a regular predetermined interval (1-255 msec for a full speed device).

This is an important concept: Input Reports are requested by the PC on a regular (timed) basis, whether any data has changed or not.

The device can decline to send Input Report data if it decides that the data is not ready yet. This is very easy to do in HIDmaker FS: our generated peripheral side code provides flags with names like Ep1XmtDataReady, that your code can set to 0 (or False) to make sure that data is not sent this time around.

  Click on the image for page view.




Page 9


In USB-speak, “OUT” or “OUTPUT” always means “going away from the PC Host.”

Output items, therefore, are items that are ONLY transmitted from the PC host, toward your peripheral device. Output Reports only get sent OUT from PC, at any time that PC program wants.

This is another important concept: Output Reports are NOT requested by the PC on a regular basis, but only relatively rarely, in response to something that has happened in the end user’s program. Typically, this means “only when the user clicks on something in the PC program.”

  Click on the image for page view.




Page 10


Feature Reports are special, in that they are the only type of HID data reports that can travel in EITHER direction, either TO or FROM the PC Host.  (In the picture below, we only show the data being sent IN to the PC Host.)

Feature Reports were originally intended to be used to set properties or parameters of a HID device from something like a Control Panel applet, like for example the process of “calibrating” a joystick.

For this reason, Feature Reports are NOT requested or sent by the PC on a regular basis, but only rarely, when the end user does something.

This is another important concept: Unlike Input or Output data items, which can only be read by the PC or only be written by the PC, any Feature data item can either be written by the PC or read back by the PC. This means that any data item that you want to be able to set from the PC, and then be able to read back later, should be a Feature item.

  Click on the image for page view.




Page 11


A USB HID Report is the actual data that the device sends or receives.

By contrast, a Report Descriptor is a table of numbers that describes the data.  A Report Descriptor only gets sent to the PC during the Enumeration process. The Report Descriptor tells the PC what kinds of Reports the device will send (i.e. whether any Input, Output, or Feature Reports are present). It also tells the PC all about the data items that are present in each type of Report.

When we say that it tells the PC all about the data items, we really mean ALL about the data items. The Report Descriptor describes each data item in exhaustive detail, telling the PC things like:

  • the item's size in bits
  • whether the item is a simple variable or an array
  • whether the item is a special Keyboard Array,
  • its position in the Report,
  • in what direction the data goes relative to the PC,
  • its minimum and maximum value
  • some standardized numbers called Usage Page and Usage ID that can describe what the data item is actually used for
  • optional information that allows the PC to scale the item to larger values, what its units are, and a whole lot more...

Please note that every USB HID class device has to have at least one Report Descriptor. (Yes, some devices need more than one.)





Page 12


Here is an example of a typical Report Descriptor, with a few comments added. It happens to be the Report Descriptor of a USB Keyboard device.

Usage Page (Generic Desktop), 
Usage (Keyboard), 
Collection (Application), 
    Report Size (1),
    Report Count (8),
    Usage Page (Key Codes),
    Usage Minimum (224),
    Usage Maximum (231),
    Logical Minimum (0),
    Logical Maximum (1),
    Input (Data, Variable, Absolute), ;Modifier byte
    Report Count (1),
    Report Size (8),
    Input (Constant),  ;Reserved byte
    Report Count (5),
    Report Size (1),
    Usage Page (LEDs),
    Usage Minimum (1),
    Usage Maximum (5),
    Output (Data, Variable, Absolute), ;LED report
    Report Count (1),
    Report Size (3),
    Output (Constant), ;LED report padding
    Report Count (6),
    Report Size (8),
    Logical Minimum (0),
    Logical Maximum(255),
    Usage Page (Key Codes),
    Usage Minimum (0),
    Usage Maximum (255),
    Input (Data, Array),
End Collection

 

Note that this is in human readable form: it is NOT what the PC sees.





Page 13


Here is what a Report Descriptor looks like to the PC. Like any USB descriptor, it has to be sent to the PC as just a table of binary numbers. (We have shown these numbers in hex format.)

05 01 09 06 A1 01 15 00
25 01 95 01 75 01 05 07
09 E0 81 02 09 E1 81 02
09 E2 81 02 09 E3 81 02
09 E4 81 02 09 E5 81 02
09 E6 81 02 09 E7 81 02
15 80 25 7F 75 08 81 03
95 06 05 07 19 01 29 65
81 00 15 00 25 01 95 01
75 01 05 08 09 01 91 02
09 02 91 02 09 03 91 02
09 04 91 02 09 05 91 02
95 01 75 03 91 03 C0

 





Page 14


You can learn to write Report Descriptors yourself, but it requires you to learn a lot of rules. It's a lot like learning another programming language. And yes, getting your Report Descriptor wrong can crash your PC.

As the human readable version of the sample Report Descriptor shows, Report Descriptors are written in a complex sort of programming language. That language is unlike any other programming language that you have ever seen. (It's sort of a cross between assembly language and the VHDL language that is used by programmable logic circuit designers.)





Page 15


The USB gods at www.usb.org provide a free program called Descriptor Tool that is supposed to help. However, you really need to know all those Report Descriptor rules first in order to be able to use this tool.

That is, you already need to know a whole lot before you can even begin to use the USB Implementers Forum's Descriptor Tool. (After all these years, this Descriptor Tool program is still almost totally undocumented.  This is yet another example of how "free" is not necessarily a bargain...)

The main thing that Descriptor Tool does for you is to turn your human-readable Report Descriptor into the table of numbers that the PC needs to see.

In that sense, using Descriptor Tool is a lot like using assembly language: you still need to understand assembly language in order to be able to write a program in assembler. Once you have written your program, the assembler converts what you wrote into a bunch of numbers which are the actual binary machine language that a processor can actually run.





Page 16


Do you need to learn how to build a car to be able to drive one? Of course not. You don't even want to build a car.  You just want to drive one.

By the same token, do you need to learn how to write these complicated Report Descriptors in order to make powerful USB HID devices? No, because HIDmaker FS will do it for you.

As we show in one of the following tutorials, the basic process contains these simple steps:

  1. You use HIDmaker FS's Visual Data Designer to create your data items and to set the properties of each data item.
  2. When HIDmaker FS generates your custom code, it will declare convenient sized variables, in both the peripheral side code and the PC side code, for all of the data items you created.
  3. At the same time, HIDmaker FS will generate the Report Descriptor as part of the peripheral side code, along with all the other USB descriptors your device needs.
  4. Once HIDmaker FS has finished generating code, all you need to do is to compile that code, using compilers that you already own.
  5. Program the compiled peripheral code (hex file) into your peripheral's processor, connect your board to the PC, and either a) run your compiled custom PC program, or b) use our AnyHID test program (part of the HIDmaker FS product), and your device will immediately start exchanging data with the PC.

 That's all there is to it!  (Stick around, we'll demonstrate it for you in another tutorial.)





Page 17


A real HID device (not those free demo programs that you see on the Web) has to be able to handle data items of any size between 1 bit and 32 bits. That means that a real HID device has to be able to put the data items into the right place in each data packet of a Report before sending it out, and it has to be able to extract the data items from the packets of any Reports that the device has received. We refer to this as packing and unpacking.

Packing and unpacking odd size data items is also tricky business to do fast and to always get right, but it's an essential part of making real USB HID class devices that can do everything that the USB standards say they should. The code that HIDmaker FS creates for both peripheral and PC automatically packs and unpacks data for you, on the fly, without wasting time or precious data memory on the peripheral device. It even automatically handles tricky situations like where a data item actually straddles the boundary between two packets in the Report.

It's part of the standard. You have a right to expect your HID device to be able to handle Reports that are larger than one packet, and you have a right to expect your HID device to be able to pack and unpack odd sized data items for you. If you don't have a tool that can do that for you, than get a tool that can! (Hint: It's HIDmaker FS.)

In our next tutorial, we'll show how packing and unpacking provides the real power for your USB device.

  Click on the image for page view.



Text Author: Dr. Bob Miller   Copyright Notice and Author Information