Making USB Device Drivers Easier Using the HID Class

Similar documents
Using the HID class eases the job of writing USB device drivers

PEI TEL Communications GmbH Potsdamer Str. 12 b, D Teltow, Tel: , Fax: ,

Human Interface Devices: Using Control and Interrupt Transfers

USB for Embedded Devices. Mohit Maheshwari Prashant Garg

DEVELOPER FRIENDLY USB: A detailed look at how easily a USB-based device can be developed

Chapter 2: Operating-System Structures

Chapter 2: Operating-System Structures

An Introduction to Universal Serial Bus

Chapter 2: System Structures

Chapter 2: Operating-System Structures

USB Interrupt Transfer Example PSoC 3 / PSoC 5

USB Complete. The Developer's Guide Fifth Edition. Jan Axelson. Lakeview Research LLC Madison, WI 53704

M Tech credit seminar report, Electronic Systems group, EE Dept, IIT Bombay, submitted Nov 2002 UNIVERSAL SERIAL BUS

Objectives. Chapter 2: Operating-System Structures. 2.1 Operating System Services

David Harrison, Design Engineer for Model Sounds Inc.

the NXT-G programming environment

PDF created with pdffactory Pro trial version How USB Ports Work by Marshall Brain. Introduction to How USB Ports Work

Chapter 2: Operating-System Structures. Operating System Concepts Essentials 8 th Edition

Bus Example: Pentium II

Chapter 2: Operating-System

Universal Serial Bus - USB 2.0

Chapter 2: Operating-System Structures

GENOVATION. Application Note: MiniTerm USB Low-Level Programming

Chapter 2: Operating-System Structures. Chapter 2: Operating-System Structures. Objectives. Operating System Services

Ricardo Rocha. Department of Computer Science Faculty of Sciences University of Porto

USB2 Debug Device A Functional Device Specification

Chapter 5 - Input / Output

Designing a Low-Cost USB Interface for an Uninterruptable Power Supply with the Cypress Semiconductor CY7C63001 USB Controller

LibUSB - Create a Solution Without the Class Struggle

Part 1 Using Serial EEPROMs

Designing a USB Keyboard with the Cypress Semiconductor CY7C63413 USB Microcontroller

USB 3.0 A Cost Effective High Bandwidth Solution for FPGA Host Interface Introduction

CHAPTER 2: SYSTEM STRUCTURES. By I-Chen Lin Textbook: Operating System Concepts 9th Ed.

Project Final Report Internet Ready Refrigerator Inventory Control System

USB Framework, IP Core and related software Tropea S.E., Melo R.A.

The Microcontroller Idea Book

CY3660-enCoRe V and encore V LV DVK Kit Guide

Introduction to USB/LPC23xx

PIC-P28-USB development board Users Manual

Author: Steve Gorman Title: Programming with the Intel architecture in the flat memory model

Fully Mobile Telephony Using VoIP Computer Software

Bulk endpoints transport data whenever required and reliably; bulk data is acknowledged and therefore fault tolerant.

Serial Port Complete

Copyright 2006 Prentice-Hall. All rights reserved. 1

Testing and Debugging

EZ-Link (AN2720SC) Single-Chip USB-to-USB Networking Solution FEATURES OVERVIEW

Static Methods. Why use methods?

Using Images in FF&EZ within a Citrix Environment

How to Choose the Right Bus for Your Measurement System

PLX USB Development Kit

OPERATING SYSTEMS & UTILITY PROGRAMS

Part 2 (Disk Pane, Network Pane, Process Details & Troubleshooting)

Chapter Two - SRAM 1. Introduction to Memories. Static Random Access Memory (SRAM)

Understand USB (in Linux)

OPERATING SYSTEMS CS136

Operating Systems. Designed and Presented by Dr. Ayman Elshenawy Elsefy

Developing Reusable Device Drivers for MCU's

Operating-System Structures

AN EZ-USB FX3 I 2 C Boot Option. Application Note Abstract. Introduction. FX3 Boot Options

4-Port USB 3.1 (10Gbps) Card - 4x USB-A with Two Dedicated Channels - PCIe

USB 3.0 pco camera interface

Chapter 2. Operating-System Structures

MSP430 Microcontroller Basics

Future Additions: USB: The Universal Serial Bus Dated: 30 August 2017

CS 179: GPU Computing LECTURE 4: GPU MEMORY SYSTEMS

Design Of Linux USB Device Driver For LPC2148 Based Data Acquisition System Including GSM.

FPGA Augmented ASICs: The Time Has Come

Four Components of a Computer System

Accelerometer with Analog and Digital I/O for StackableUSB USB1600

Computers and Microprocessors. Lecture 34 PHYS3360/AEP3630

Presentation to Linux Users of Victoria Beginner's Workshop. August 20, Dedicated to Christopher Espinosa

(Refer Slide Time 00:01:09)

Hacking USB HID for Easy Tethered Ubicomp. Tod E. Kurt / ThingM

Cypress HX2VL Configuration Utility Blaster User Guide

Data Sheet. Packet-Master USB12 Bus Analyser

Unit 1. Aries Technology Course

Creating a USB to Serial Bridge Solution using Cypress Low and Full-speed M8 USB Devices

Arithmetic/logic Unit (ALU)

Programming with MPI

Unit 2 : Computer and Operating System Structure

Introducing Class-Level Decoding Video See a video demonstration of the new real-time class-level decoding feature of the Data Center Software.

Fastboot Techniques for the x86 Architecture. Ben Biron QNX Software Systems

The personal computer system uses the following hardware device types -

Main Parts of Personal Computer

10 C Language Tips for Hardware Engineers

Last Class: OS and Computer Architecture. Last Class: OS and Computer Architecture

I2C and SPI Foundation

CS307: Operating Systems

AN1814 APPLICATION NOTE

Operating System Services

USB: Features and Circuits Manoj Purohit ( ) Supervisor: Prof P.C.Pandey

CMSC131. Hardware and Software. Hardware

CMSC131. Hardware and Software

I2C a learn.sparkfun.com tutorial

An open-source, multi-parameter, full fledged human body vital sign monitoring HAT for Raspberry Pi as well as standalone use.

Main Window. June 25, 2017, Beginners SIG Activity Monitor (Part 1 of 2)

CY4615B AT2LP DDK User s Guide

Resource Guide Implementing QoS for WX/WXC Application Acceleration Platforms

mikropascal PRO for 8051

Chapter Operation Pinout Operation 35

Transcription:

Making USB Device Drivers Easier Using the HID Class Stuart Allman Cypress Semiconductor 15050 Avenue of Science San Diego, CA 92128 (858) 613-7900 One of the major barriers that exist in the adoption of the Universal Serial Bus (USB) is the difficulty in writing device drivers. As a typical embedded engineer, I think I speak for a large percentage of embedded developers who can comfortably design embedded systems all day long, but get nervous at the thought of writing a PC device driver. Things are just not quite as simple as using the parallel port or serial port anymore. However the USB offers quite a few advantages; including multi-platform support, standard device classes, and support for vendor defined devices. Motherboard vendors are also ma king an attempt to eliminate the legacy connections in favor of the USB, which forces a large number of us to accept the evolution of technology. Move to the USB, or become obsolete. This article focuses on encapsulating the concepts of a Windows based application to talk to an embedded device using the Human Interface Device (HID) class. The HID class is a standard device classification for the USB; however don t let the words standard or classification fool you. The HID class doesn t represent a set of fixed function devices; rather it supports a wide variety of devices with widely varying characteristics. Some examples include a computer mouse, keyboard, sports equipment, medical instruments, AV devices, vendor defined functions, and more. HID also supports device primitives like an LED, button, and standard measurements like time, temperature, distance etc. The general idea is that the HID class can be used to support a wide range of vendor specific applications that aren t currently supported by a USB device class. To add to this, Microsoft supports the HID class with a well rounded library; included as part of the Windows DDK. This article explains how to use the library in a typical situation for a vendor defined HID usage. The end goal of the example Windows application and USB device shown in this article is to show the basic steps of data exchange across the USB using the HID driver. How Does a Device Get on the USB? The whole process begins with the act of a simple pull up resistor. After the device is plugged into an active USB host, the device turns on a pull up resistor onto one of the USB data signals. D- is pulled up if the device is low speed, D+ is pulled up if the device is full- or high-speed. The USB host detects this condition and begins a startup process on the USB 1. This process is called device enumeration. During enumeration the host requests a number of data structures called descriptors from the device. These descriptors contain information about the number and type of communication channels that the USB device desires to use, as well as information about any device class information. These communication channels are referred to as endpoints. Enumeration itself takes place on the default endpoint, known as endpoint 0, or the control endpoint. The host also assigns a unique 7-bit address to the device, so that communications can be directed to a particular device. On PC or Mac platforms the first part of the enumeration process takes place without class specific or custom device drivers. During the first part of enumeration the USB driver retrieves the general descriptors that all devices support and gives the device a unique address on the USB. If the descriptors indicate that the device belongs to a particular USB device class, the USB driver hands off the rest of the enumeration process to the specified class driver. In the example for this article the driver handoff will be 1 Note that high-speed hosts go through additional processes.

to the HID class driver. If no class is specified, then the device VID (vendor ID) and PID (product ID) gathered from the descriptors is used to identify an appropriate driver for the USB device. If everything is designed properly on the USB device end, you will not need to worry about the driver process. The enumeration process and class driver handoff are handled for you. The device is simply enumerated and ready to use with your application. However, if the descriptors are not properly formatted or the device fails to respond properly the device is disabled by the USB or class driver; depending on when the failure occurred during enumeration. What is a HID? HID turns on Pull up System transfers control to HID Class Driver, gathers HID descriptors & starts HID reports USB Host Starts General Enumeration The host sets the USB device address and gathers general descriptors. Figure 1. HID Device Enumeration Process Don t let the name confuse you. A USB device that claims to belong to the Human Interface Device class doesn t necessarily have to have a human interface at all. The HID class supports a wide variety of devices that you would generally never associate with a human interface. Devices can be as obvious as a mouse or keyboard, but also as unexpected as an IC programmer or thermometer. The class also supports a variety of device primitives that you would associate with a general digital device, such as a LED, button, vector, or LCD display. The HID class allows you to create a collection of HID usages to describe a device. This collection is described within the HID report descriptor, which is gathered by the host during the enumeration process. The report descriptor describes what the input and output stream of bits mean. For instance, a clock could be described as an input stream of three bytes corresponding to hours, minutes, and seconds. The clock could also have an output report in the collection that describes how to write to device s LCD display. The HID class also has the capacity to allow vendor defined usages. Even if your device cannot be described by any of the pre-defined usages in the HID usage tables (see references), you can still reserve a generic vendor defined slot in the HID report collection. The downside to using the HID class is that the typical class drivers only support one type of endpoint communication (i.e. interrupt) and the bandwidth is limited well below the USB s maximum throughput. For low-speed devices the bandwidth is limited to 800 bytes/s/report (8 bytes every 10ms per input/output report), for full-speed devices it is limited to 64,000 bytes/s /report (64 bytes every millisecond per input/output report), and for high-speed the limit is approximately 23.4 Mbytes/s/report (3072 bytes per micro-frame per input/output report). A HID may specify multiple reports if more than the *per report* bandwidth is required. Don t let this immediately discourage you. Using an intelligent USB controller often helps pre-sort data and lower the bandwidth required to support an application. The low-speed bandwidth limit was far, far more than was needed for the example application given later in this article. So what is the bottom line of using the HID class? No Windows/Mac/Linux device driver to write! If that s not encouragement enough, the rest of this article explains the steps to get your device up and running quickly. How Do We Make a HID? Many steps are required to make a HID device enumerate and be able to communicate using HID reports on the USB. I have no intention of Makin g USB Device Drivers Easier 2 of 8

implying that this is easy, however the example application presented later in this article is a framework that can be copied and edited as a starting point (see references at the end of this article for the example design package). The references at the end of this article also serve as a good starting point if you wish to further explore the possibilities of the HID class. This section describes the pieces of the puzzle that are necessary to get a HID working. All USB devices handle a standard set of requests, commonly referred to as the Chapter 9 tests. These requests are literally described in chapter 9 of the USB specification. The requests include tasks like retrieving a standard set of descriptors from the device and setting standard device parameters. The first specific to making a HID is specifying the HID class in the USB interface descriptor s binterfaceclass field. A value of 0x03 corresponds to the HID class. This lets the general USB driver know which class driver the application will need to be passed on to after the general enumeration process is complete. A HID class descriptor is also supplied as a subsection of the configuration descriptor in between the interface and endpoint descriptor sub-sections (see the example device firmware). This descriptor basically contains the HID specification version information and the length of the HID report descriptor. The second aspect of making a HID is the HID report descriptor itself. These can actually be quite complex. The HID descriptor is made up of a collection of HID usages, each of which describe a field in an input or output report. The HID usage table document shows a large number of useful examples of how to create a HID report descriptor. When the chapter 9 requests and HID specific parameters are correctly handled the remainder of the work lies in the application itself. For this part, the article concentrates on a Microsoft Windows based application. Examples are also available elsewhere for MacOS and Linux (see references). Usage Page (vendor defined) Collection (application) End Collection ** input report Logical Minimum (-128) Logical Maximum (127) Report Size (8) Input (Data) ** output report Logical Minimum (-128) Logical Maximum (127) Report Size (8) Output (Data) Figure 2. Minimal HID Report Descriptor. This Descriptor calls for a one byte input report and a one byte output report with a completely vendor defined usage. The descriptor could also consist of only an input report or only an output report. The first thing an application must be able to do is to open the device for communications. This actually turns out to be a fairly lengthy process however the example application encapsulates the process into a reusable function called bopenhiddevice(). The procedure is mostly taken from Jan Axelson s description in the book USB Complete. The bopenhiddevice function takes a device handle reference, a target device VID, and a target device PID as function arguments. If a device is found that matches the desired VID and PID, then the function returns TRUE and the device handle is assigned a valid value. If the function returns false, it more than likely means that the either the device is not plugged in or the device failed enumeration. The process of opening a device consists of seven steps as described below and in figure 3. [See Figure 3. Opening a HID device within Windows at the end of this document] 1. Obtain the Windows Globally Unique ID (GUID) for HID devices via a call to HidD_GetHidGuid(). Makin g USB Device Drivers Easier 3 of 8

2. Get an array of structures that contain information about all attached HIDs via a call to SetupDiGetClassDevs(). This uses the previously obtained HID GUID to specify that the list should only contain HID devices 3. Use the Windows function SetupDiEnumDeviceInterfaces() to get information about a particular device in the list. We need to step through each index of device information until we find one with the correct VID & PID. If this function returns FALSE, then we have gone to the end of the list without finding the desired device. 4. A call to SetupDiGetDeviceInterfaceDetail() returns detailed data about the particular device indexed in the previous step. We want to use the device path to open the device in the next step. 5. Call CreateFile() to open the device using the path obtained in the previous step. If a valid handle is returned, then we can examine the VID & PID to determine if this is the device we want. 6. Compare the open device s VID & PID to determine if this is the device we want. If so, then we should return the device handle and a TRUE condition. 7. If the VID & PID are not correct, then we need to close the device handle and return to step 3 to check the next device indexed in the list. The next function that the HID application must handle is device attach/detach notification. This process is encapsulated with the bhiddevicenotify() function in the example application. This causes the Windows USB system to send a WM_DEVICECHANGE message to the application any time a USB HID device is plugged or unplugged from the system. The notification system is not quite intelligent enough to indicate a HID device change for a particular VID & PID, so the application must check if the device is still attached on any notification message. The process for setting up device notifications is a five part process: 1. Obtain the Windows Globally Unique ID (GUID) for HID devices via a call to HidD_GetHidGuid(). 2. Clear the contents of a DEV_BROADCAST_DEVICEINTERFA CE structure 0. 3. Assign the members of the structure such that the HID GUID is specified 4. Register the application for device notifications by calling the function RegisterDeviceNotification(). 5. If the handle returned from the previous step is invalid, then an error has occurred and the function should return an error. Otherwise return success. The Windows DDK provides a number of functions that allow you to find devices with certain capabilities and retrieve particular pieces of data from the USB device. The library functions are too numerous to mention here, but they can be found by performing a search for HID Support Routines for Clients on the MSDN web. Obviously the next functionality that the application needs to have is the ability to read input reports and write output reports. To do this an application uses the ReadFile() and WriteFile() functions respectively. Each of these functions use the device handle returned by the CreateFile() function. The example application uses a concept called overlapped transactions. An overlapped transaction allows the application to go into a low CPU overhead state while waiting for a requested USB transaction to occur. By default, up to eight overlapped transactions can be queued at once; mo re if specified. If an application doesn t use overlapped transactions, then the whole application has to wait until the USB transaction finishes before the application can perform any additional tasks. Obviously this is a bad state to be in when an application spends most of it s time waiting for data to be returned from a USB device. The bopenhiddevice() function opens the device with the FILE_FLAG_OVERLAPPED parameter, so all transactions are assumed to be overlapped ones in the example application. A second aspect of data transfer is the use of multiple threads. Because the main application needs to remain responsive even while waiting for USB transactions, it is highly desirable to put Makin g USB Device Drivers Easier 4 of 8

the USB reads and writes in a separate thread. This allows the main application to continue processing messages while the USB transaction thread waits for overlapped transactions to complete. An Example HID Thermometer The example presented in this article is a thermometer that communicates with a PC via the HID class driver. The goal of this article was to show an unconventional use of the versatile HID class. This thermometer has three main components: an LED, a button, and a temperature measurement. The button and thermometer are grouped into an input report, and the LED is controlled by the host application via an output report. A design package for this example application is on the web site listed in the references section. An LED is a pre-defined usage page (i.e. collection of LED related functions) of the HID class (see the HID usage tables specification). For the purposes of this application the LED usage is defined as a Ready LED. The intention of providing this control is to show how to use a HID output report. The report is made up of a single byte that turns the LED on (0x01) or off (0x00). The LED is turned on when the computer starts taking measurements and it turned off when the measurements stop (i.e. when the application closes). WriteFile() is used to send an overlapped HID output report to the USB device. The button is also a pre-defined usage page of the HID class. A general purpose button can be defined without a particular usage in mind. The format of the button report is shown in figure 4. In order to request button information from the USB device, the windows application uses an overlapped transaction via a call to ReadFile(). The temperature measurement is a bit more complex. The generic desktop usage page contains a usage called a non-oriented vector. The intended use of a non-oriented vector is for measurement of time, distance, temperature, light intensity etc where spatial locality is not important. The HID report descriptor also indicates the units for the measurement (i.e. SI linear Kelvin) and the exponent (10 0 ) for the reported value. The temperature measurement IC used on the USB device reports in Celsius, so reporting in Kelvin was simply a matter of adding 273 to the IC s measured value. The example application does not actually look for units, exponents and other information because the application searches for a specific USB device. However, the Windows HID DDK allows your application to search for devices with certain capabilities instead of a dedicated device. See the Windows DDK documentation for more information on this subject. Both the button and temperature measurement are provided as one report. Any time the button changes or a temperature measurement is complete, the USB device reports these values back to the host in the format shown in figure 4. Byte 0 Byte 1 Byte 2 Button state (LSB) Temperature Low Byte Temperature High Byte Figure 4. Format of HID input report The format of the HID report descriptor is shown in figure 5. This shows the vendor defined usage and a collection of three reports, two of which are combined into a single input report. The Windows HID driver follows the conventions set in the HID class specification to parse the HID report descriptor. Even if the host side application doesn t use some of the information in the HID report descriptor, it is still required for the HID driver to accept your device. Detailed information about how to format HID report descriptors is beyond the scope of this article. This HID class and HID Usage table specifications provide complete information on this subject. A HID descriptor tool is also available to help you with this task. Makin g USB Device Drivers Easier 5 of 8

Usage Page (vendor defined) Collection (application) Usage Page (button) Usage Minimum (1) Usage Maximum (1) Logical Minimum (0) Logical Maximum (1) Report Size (1) Input (Data) Report Size (7) Input (Constant) Vector Report Provides Temperature Measurement Button Report Selects Temperature Units End Collection Usage Page (Generic Desktop) Usage (non-oriented vector) Logical Minimu m (218) Logical Maximum (393) Units (SI Linear Kelvin) Units Exponent (0) Report Size (16) Input (Data) Usage Page (LED) Usage (Ready) Logical Minimum (0) Logical Maximum (1) Report Size (1) Output (Data) Report Size (7) Output (Constant) Figure 5. Thermometer HID Report Descriptor Figure 6 contains a screen shot of the example HID thermometer application. The host application was written using the VisualC++ v6.0 tools and the Win98 DDK. The Win98 DDK certainly isn t the most up to date, but I wanted to ensure that the application could be built using all versions of the Windows DDK and would run with all USB enabled versions of Windows. The USB device side was developed for the CY7C63743 USB microcontroller from Cypress. The CY3644 applications board that comes with the microcontroller s development kit has buttons, LEDs, and a temperature IC already installed. The microcontroller s source code, assembler, and ROM image are provided as part of the design package. Debug Messages Summary Figure 5. Example HID Thermometer Hopefully by now you have realized that the USB HID class is a powerful and versatile way to get your device on the USB. Even if your device doesn t fit into one of the pre-defined HID usages, there is always the possibility of using a completely vendor defined usage. The example design package for this article is available on the web site listed in the references section. If your USB device can exist within the bandwidth limits of the HID driver, then using this driver may save your sanity and your schedule in the long run. References Output Report Turns On/Off LED Design package for this article http://www.cypress.com/aboutus/press_release_l ist.cfm?pr_type=techarticles USB specification http://www.usb.org/developers/docs.html Makin g USB Device Drivers Easier 6 of 8

USB HID specification, HID usages tables, HID descriptor tool http://www.usb.org/developers/hidpage.html Microsoft DDK reference http://msdn.microsoft.com/ Apple USB reference http://developer.apple.com/hardware/usb/ Linux USB reference www.linux-usb.org USB Complete, Jan Axelson, Lakeview Research www.lvr.com USB Design by Example, John Hyde, Intel www.usb-by-example.com Makin g USB Device Drivers Easier 7 of 8

Get the Windows Globally Unique ID for HID devices. HidD_GetHidGuid() Gather an array of structures describing all HID devices. SetupDiGetClassDevs() Gather info about HID device with index i, starting at 0. SetupDiGetClassDevs() FALSE HID Device Not Found Get detailed info about device pointed to by index i. TRUE SetupDiGetDeviceInterface Detail() Open a handle to the device CreateFile() Check VID and PID of open device to see if it s the device we want Desired VID & PID? TRUE HID Device Found FALSE (increment index i and try again) Figure 3. Opening a HID device within Windows Makin g USB Device Drivers Easier 8 of 8