summaryrefslogtreecommitdiff
path: root/usb/device/hid-keyboard/hid-keyboard.dir
diff options
context:
space:
mode:
Diffstat (limited to 'usb/device/hid-keyboard/hid-keyboard.dir')
-rw-r--r--usb/device/hid-keyboard/hid-keyboard.dir787
1 files changed, 787 insertions, 0 deletions
diff --git a/usb/device/hid-keyboard/hid-keyboard.dir b/usb/device/hid-keyboard/hid-keyboard.dir
new file mode 100644
index 0000000..923a362
--- /dev/null
+++ b/usb/device/hid-keyboard/hid-keyboard.dir
@@ -0,0 +1,787 @@
+/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB HID
+/// %device - USB HID Keyboard driver, to implement an USB keyboard %device.
+///
+/// !!!Contents
+///
+/// There are three things for the implement of the USB HID Keyboard driver:
+/// - Implement the USB HID driver structs and functions for the %device,
+/// to initialize, to handle HID-specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the HID Keyboard device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the %device as a USB Keyboard %device.
+/// - Implement methods to update the keyboard keys status, so that host can
+/// get it through USB.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB HID Keyboard".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB HID Keyboard"
+ This page describes how to use the "AT91 USB device framework" to produce a USB
+ HID Keyboard driver, which appears as a USB keyboard on host.
+
+ Details about the USB and the HID class can be found in the }USB specification
+ 2.0} and the }HID specification 1.11}, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+ !!!HID Basic
+ See "USB HID Basic".
+
+ !!!Architecture
+ See "USB Device Framework Architecture".
+
+ !!!Descriptors
+
+ ...
+
+ !!Device Descriptor
+ The Device descriptor of an HID %device is very basic, since the HID class
+ code is only specified at the Interface level. Thus, it only contains
+ standard values, as shown below:
+\code
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDKeyboardDriverDescriptors_VENDORID,
+ HIDDKeyboardDriverDescriptors_PRODUCTID,
+ HIDDKeyboardDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+\endcode
+ Note that the Vendor ID is a special value attributed by the USB-IF
+ organization. The product ID can be chosen freely by the vendor.
+
+ !!Configuration Descriptor
+ Since one interface is required by the HID specification, this must be
+ specified in the Configuration descriptor. There is no other value of
+ interest to put here.
+\code
+// Configuration descriptor
+{
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+},
+\endcode
+ When the Configuration descriptor is requested by the host (by using the
+ GET_DESCRIPTOR command), the %device must also sent all the related
+ descriptors, i.e. Interface, Endpoint and Class-Specific descriptors. It is
+ convenient to create a single structure to hold all this data, for sending
+ everything in one chunk. In the example software, a
+ HIDDKeyboardDriverConfigurationDescriptors structure has been declared for
+ that.
+
+ !!HID Class Interface Descriptor
+ Since a keyboard %device needs to transmit as well as receive data, two
+ Interrupt (IN & OUT) endpoints are needed. This must be indicated in the
+ Interface descriptor. Conversely to the mouse example, the Boot protocol is
+ not implemented here, since there are more constraints on a keyboard %device.
+\code
+// Interface descriptor
+{
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+},
+\endcode
+
+ !!HID Descriptor
+ While a HID keyboard produces two different reports, one Input and one Output,
+ only one Report descriptor can be used to describe them. Since having Physical
+ descriptors is also useless for a keyboard, there will only be one HID class
+ descriptor specified here.
+
+ For a keyboard, the }bCountryCode} field can be used to specify the language
+ of the key caps. As this is optional, it is simply set to 00h in the example:
+\code
+// HID descriptor
+{
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+},
+\endcode
+
+ !!Report Descriptor
+ Two current reports are defined in the Report descriptor. The first one is
+ used to notify the host of which keys are pressed, with both modifier keys
+ (alt, ctrl, etc.) and alphanumeric keys. The second report is necessary for
+ the host to send the LED (num lock, caps lock, etc.) states.
+
+ The Report descriptor starts with the global %device functionality, described
+ with a #Usage Page# and a #Usage# items:
+\code
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
+\endcode
+
+ As in the mouse example, the }Generic Desktop} page is used. This time, the
+ specific usage is the }Keyboard} one. An Application collection is then
+ defined to group the reports together:
+\code
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+\endcode
+
+ The first report to be defined is the modifier keys. They are represented as a
+ bitmap field, indicating whether or not each key is pressed. A single byte is
+ used to map keys \#224-231 defined in the }HID Usage Tables} document:
+ LeftControl, LeftShift, LeftAlt, LeftGUI (e.g. Windows key),
+ RightControl, RightShift, RightAlt and RightGUI.
+ The }Keypad} usage page must be specified for this report, and since this is a
+ bitmap value, the data is flagged as }Variable}:
+\code
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Then, the actual alphanumeric key report is described. This is done by
+ defining several bytes of data, one for each pressed key. In the example,
+ up to three keys can be pressed at the same time (and detected) by the user.
+ Once again, the usage page is set to }Keypad}. This time however, the data
+ must be specified as an }Array}, since the same control (the keypad) produces
+ several values:
+\code
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+\endcode
+
+ The LED array is then defined, with the associated usage page. The Report
+ descriptor is formatted in this order to avoid redefining unchanged }Global}
+ items, in order to save memory. This time again, the LED status is reported as
+ a bitmap field. Three LEDs are used here: Num Lock, Caps Lock and Scroll Lock
+ (IDs 01h to 03h). It is important to note that this is an #Output# report:
+\code
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Since the previous report only contains 3 bits, the data must be padded to a
+ multiple of one byte. This is done by using constant Output data, as follows:
+\code
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+\endcode
+
+ The last item, }End Collection}, is necessary to close the previously opened
+ }Application Collection}.
+\code
+ HIDReport_ENDCOLLECTION
+};
+\endcode
+
+ The Input and Output reports defined by this descriptor can be modeled by the
+ following structures:
+\code
+// HID Input Report
+typedef struct {
+
+ // State of modifier keys.
+ unsigned char bmModifierKeys:8;
+ // Key codes of pressed keys.
+ unsigned char pressedKeys[HIDDKeyboardInputReport_MAXKEYPRESSES];
+
+} __attribute__ ((packed)) HIDDKeyboardInputReport; // GCC
+// HID Output Report
+typedef struct {
+
+ unsigned char numLockStatus:1, // State of the num. lock LED.
+ capsLockStatus:1, // State of the caps lock LED.
+ scrollLockStatus:1, // State of the scroll lock LED.
+ padding:5; // Padding bits.
+
+} __attribute__ ((packed)) HIDDKeyboardOutputReport; // GCC
+\endcode
+
+ An instance of each one of the reports is stored in a HIDDKeyboardDriver
+ structure, which holds the standard class driver and HID keyboard-specific
+ data.
+
+ !!Physical Descriptor
+ A Physical descriptor is useless for a keyboard %device, so none are defined
+ in this example.
+
+ !!Endpoint Descriptor
+ Following the Interface and HID-specific descriptors, the two necessary
+ endpoints are defined.
+\code
+// Interrupt IN endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+},
+// Interrupt OUT endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+}
+\endcode
+
+ !!String Descriptors
+ Please refer to "Usage: USBD VID, PID & Strings".
+
+ !!!Class-specific requests
+ A driver request handler should first differentiate between class-specific and
+ standard requests using the corresponding bits in the }bmRequestType} field.
+ In most cases, standard requests can be immediately forwarded to the standard
+ request handler method; class-specific methods must be decoded and treated by
+ the custom handler.
+
+ !!GetDescriptor
+ Three values have been added by the HID specification for the #GET_DESCRIPTOR#
+ request. The high byte of the }wValue} field contains the type of the
+ requested descriptor; in addition to the standard types, the #HID
+ specification# adds the #HID descriptor# (21h), the #Report descriptor#
+ (22h) and the #Physical descriptor# (23h) types.
+
+ There is no particular action to perform besides sending the descriptor. This
+ can be done by using the USBD_Write method, after the requested descriptor has
+ been identified:
+\code
+switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor,
+ // otherwise forward it to
+ // the standard driver
+ if (!HIDDKeyboardDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+}
+\endcode
+ A slight complexity of the GET_DESCRIPTOR and SET_DESCRIPTOR requests is that
+ those are standard requests, but the standard request handler
+ (USBDDriver_RequestHandler) must not always be called to treat them (since
+ they may refer to HID descriptors). The solution is to first identify
+ GET/SET_DESCRIPTOR requests, treat the HID-specific cases and, finally,
+ forward any other request to the standard handler.
+
+ In this case, a GET_DESCRIPTOR request for the Physical descriptor is first
+ forwarded to the standard handler, and STALLed there because it is not
+ recognized. This is done because the %device does not have any Physical
+ descriptors, and thus, does not need to handle the associated request.
+
+ !!SetDescriptor
+ This request is optional and is never issued by most hosts. It is not
+ implemented in this example.
+
+ !!GetReport
+ Since the HID keyboard defines two different reports, the Report Type value
+ specified by this request (upper byte of the }wValue} field) must be examined
+ to decide which report to send. If the type value is 01h, then the Input
+ report must be returned; if it is 02h, the Output report is requested:
+\code
+case HIDGenericRequest_GETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardInputReport)) {
+
+ length = sizeof(HIDDKeyboardInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardOutputReport)) {
+
+ length = sizeof(HIDDKeyboardOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetReport
+ For an HID keyboard, the #SET_REPORT# command can be sent by the host to
+ change the state of the LEDs. Normally, the dedicated Interrupt OUT endpoint
+ will be used for this; but in some cases, using the default Control endpoint
+ can save some bandwidth on the host side.
+
+ Note that the SET_REPORT request can be directed at the Input report of the
+ keyboard; in this case, it can be safely discarded, according to the HID
+ specification. Normally, most host drivers only target the Output report. The
+ Report Type value is stored in the upper byte of the }wValue} field.
+
+ The length of the data phase to follow is stored in the }wLength} field of the
+ request. It should be equal to the total length of the Output report. If it is
+ different, the report status must still be updated with the received data as
+ best as possible.
+
+ When the reception of the new data is completed, some processing must be done
+ to enable/disable the corresponding LEDs. This is done in the callback
+ function passed as an argument to USBD_Read:
+\code
+case HIDGenericRequest_SETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch(type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDKeyboardOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetIdle
+ In this case study, the #SET_IDLE# request is used to set a delay before a key
+ is repeated. This is common behavior on keyboard devices. Usually, this delay
+ is set to about 500 ms by the host.
+
+ The only action here is to store the new Idle rate. The management of this
+ setting must be done in the main function, since Interrupt IN reports are sent
+ from there.
+
+ In practice, it is not necessary to perform any action, apart from sending a
+ zero-length packet to acknowledge it. The main application however has to make
+ sure that only new reports are sent by the %device.
+\code
+case HIDGenericRequest_SETIDLE:
+//-----------------------------
+ hiddKeyboardDriver.inputReportIdleRate =
+ HIDIdleRequest_GetIdleRate(request);
+ USBD_Write(0, 0, 0, 0, 0);
+break;
+\endcode
+
+ !!GetIdle
+ The only necessary operation for this request is to send the previously saved
+ Idle rate. This is done by calling the USBD_Write method with the one-byte
+ variable as its parameter:
+\code
+case HIDGenericRequest_GETIDLE:
+//-----------------------------
+ USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
+break;
+\endcode
+
+ !!GetProtocol, SetProtocol
+ This HID keyboard example does not support the Boot protocol, so there is no
+ need to implement the SET_PROTOCOL and GET_PROTOCOL requests. This means they
+ can be safely STALLed when received.
+
+ !!!Main Application
+ Like the mouse example, the main program must perform two different
+ operations. First, it has to monitor the physical inputs used as keys. In the
+ example software, the buttons present on the evaluation boards are used to
+ produce several modifier and alphanumeric keys.
+
+ Also, the main program is in charge of sending reports as they are modified,
+ taking into account the Idle rate specified by the host. Idle rate management
+ can be carried out by firing/resetting a timer once a new report is sent; if
+ the timer expires, this means the Input report has not changed since.
+ According to the HID specification, a single instance of the report must be
+ sent in this case.
+
+ Finally, the HID specification also defines that if too many keys are pressed
+ at the same time, the %device should report an }ErrorRollOver} usage value
+ (01h) in every byte of the key array. This has to be handled by the main
+ application as well.
+
+*/
+
+/**
+ \page "USB HID Mouse"
+ This page describes how to implement a mouse %device using the HID class and
+ the "AT91 USB device framework". Details about the USB and the HID class can
+ be found in the }USB specification 2.0} and the }HID specification 1.11}
+ documents, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+
+
+*/
+
+/**
+ \page "USB HID Basic"
+
+ This page gives generic details on the HID class, including its purpose,
+ architecture and how it is supported by various operating systems.
+
+ !!!Purpose
+
+ The HID class has been specifically designed for Human Interface Devices,
+ i.e., devices which are manipulated by humans to control a computer or an
+ electronic %device. This includes common peripherals such as a keyboard, a
+ mouse or a joystick, as well as many other interfaces: remote controllers,
+ switches, buttons, dedicated game controls, and so on.
+
+ It is also possible to use the HID class for devices which do not require
+ human interaction, but still deliver information in a similar format. For
+ example, devices like a thermometer or a battery indicator are supported.
+
+ In addition, the HID class also makes it possible to not only receive data
+ from devices but also to send commands to them. Indeed, many devices offer
+ some kind of display to give back information to the user, e.g., the LEDs on a
+ keyboard.
+
+ Finally, since it is quite simple to send and receive data using the HID
+ class, it can be used as a generic means of communication between a %device
+ and a host. This is made possible because of the very flexible framework
+ defined in the HID specification.
+
+ In this document, three uses of the HID class will be detailed step-by-step,
+ each showing one particular feature of the class. The first example shows the
+ interaction with a simple mouse. In the second example, a keyboard is
+ implemented to demonstrate the possibility to send data to a peripheral. The
+ last example explains how to use HID as a simple two-way communication
+ channel.
+
+ !!!Architecture
+ ...
+
+ !!Interface
+ An HID %device only needs #one interface descriptor#. It should have the HID
+ interface class code in its bInterfaceClass field. There are special subclass
+ and protocol codes to specify if the HID %device is a mouse or a keyboard, and
+ must be supported by the BIOS. In such a case, the interface must be declared
+ as a Boot Interface, and the type of the %device (mouse or keyboard) must be
+ given in the bInterfaceProtocol field.
+
+ !!Endpoints
+ Up to three endpoints can be used with an HID interface. The first two are the
+ default Control endpoint 0, as well as an Interrupt IN endpoint. They are
+ mandatory and shall always be declared. An optional Interrupt OUT endpoint can
+ be added as well.
+
+ Endpoint 0 is used for class-specific requests, as well as receiving data from
+ the host if no Interrupt OUT endpoint has been defined. In addition, the host
+ can also explicitly request or send report data through this endpoint.
+
+ The Interrupt IN and OUT pipes are used for sending asynchronous data to the
+ host, and to receive low-latency information.
+
+ \image HIDClassArch.png "HID Class Driver Architecture"
+
+ !!Class-Specific Descriptors
+ There are three class-specific descriptors defined in the }HID specification
+ 1.11}: the HID descriptor, the report descriptor and the physical descriptor.
+
+ !HID Descriptor
+ The HID descriptor gives information about the HID specification revision
+ used, the country for which a %device is localized, and lists the number of
+ class-specific descriptors, including their length and type.
+
+ HID Descriptor Format
+||Field||Size(bytes)||Description
+|bLength|1|Total length of the HID descriptor
+|bDescriptorType|1|HID descriptor type (21h)
+|bcdHID|2|HID specification release number in BCD format
+|bCountryCode|1|Code of the country for which the %device is located.\n
+ Should be 0 if the %device is not localized.
+|bNumDescriptors|1|Number of class-specific descriptors used by the %device.
+|bDescriptorType|1|Type of the first class-specific descriptor.
+|bDescriptorLength|1|Total length of the first class-specific descriptor.
+|[bDescriptorType]|1|Type of the second class-specific descriptor.
+|[bDescriptorLength]|1|Total length of the second class-specific descriptor.
+|...| |
+
+ There is always at least one Report descriptor for an HID %device, so the
+ corresponding fields must be present in the HID descriptor. If other
+ descriptors are defined, they must also be described here.
+
+ !Report Descriptor
+ A HID %device must have at least one #Report descriptor#. It defines the type
+ of data manipulated by the %device, which is referred to as report. When the
+ %device wants to notify that the cursor has moved, for example, it sends the
+ corresponding report in the format previously defined in the Report
+ descriptor.
+
+ This descriptor is quite different from others, as it does not have a fixed
+ table of values. Instead, it is made up of a variable number of items, which
+ collectively identify the information that a host can expect from or send to
+ the %device.
+
+ There are five categories of items:
+ - #Input# items, which define the format and type of the data sent by the
+ %device.
+ - #Output# items, which define the format and type of the data expected by
+ the %device
+ - #Feature# items, which define data sent to or received from the %device,
+ and not intended for the end user, such as configuration parameters.
+- #Collection# items, which identify a set of data as related to the same
+ group.
+- #End Collection# items, which close other Collection items.
+
+ Usually, a Report descriptor defines only one use (report) for a %device, e.g.,
+ a mouse. However, it is possible to declare several reports to perform
+ different tasks, e.g., mouse & keyboard. This is done by assigning a different
+ #Report ID# to each report; this makes it possible for the %device to send
+ both reports through the same Interrupt endpoint, while still permitting the
+ host to correctly identify the data. Using only a single endpoint for several
+ functionalities is very powerful, as the remaining ones can then be used by
+ other interfaces (CDC, MSD, etc.) for an even more versatile %device.
+
+ More details about Report descriptors will be given in the implementation
+ examples. For more information about the possible items, tags and values,
+ please refer to the }HID specification 1.11.}
+
+ !Physical Descriptor
+ A #Physical descriptor# can be used to give information about which human body
+ part is used to activate a particular control. While this is a useless piece
+ of information for most devices, it can be relevant for complex devices which
+ provide many similar controls. In such a case, a Physical descriptor allows an
+ application to assign its functionalities more appropriately; for example, a
+ game controller often has a large number of buttons, with some of them more
+ accessible than the others. Those buttons would be assigned the most useful
+ actions.
+
+ Since physical descriptors are not used very often, and are not useful in the
+ case studies described in this document, they will not be discussed further.
+
+ !!Class-specific Requests
+ ...
+
+ !GetDescriptor
+ While #GET_DESCRIPTOR# is a standard request (defined in the }USB
+ specification 2.0}), new descriptor type values have been added for the HID
+ class. They make it possible for the host to request the HID descriptor,
+ Report descriptor and Physical descriptors used by the %device.
+
+ When requesting a HID-specific descriptor, the }wIndex} field of the request
+ must be set to the HID interface number. For standard requests, this field is
+ either set to 0 or, for String descriptors, to the index of the language ID
+ used.
+
+ !SetDescriptor
+ Similarly, #SET_DESCRIPTOR# is a standard request with added HID-specific
+ values. It is used by the host to change the HID descriptors of a %device.
+ This is an optional request, and has few practical uses.
+
+ !GetReport
+ The host can explicitly ask the %device for a report by using the #GET_REPORT#
+ request. However, it should be used primarily to get the state of feature
+ items and absolute values at initialization time, not for consistent %device
+ polling.
+
+ The requested report is identified either by its Report ID (if they are used),
+ and/or by its type (Input, Output or Feature).
+
+ Please note that a GET_REPORT request is different from a GET_DESCRIPTOR
+ request for the Report descriptor. The latter returns the whole Report
+ descriptor, i.e., all the items declared. The former returns the data defined
+ by this descriptor.
+
+ !SetReport
+ #SET_REPORT# is similar to GET_REPORT, except this request is used for
+ changing the state of a report, instead of simply retrieving it.
+
+ For an Input report, this request can either be considered meaningless, or can
+ be used to reset the current status of a control. For example, it could be
+ used to calibrate the neutral position of a joystick.
+
+ !SetIdle
+ This request is used to specify the minimum amount of time, called #Idle
+ rate#, that a %device must wait before transmitting a report if its state has
+ not changed. This means the %device must NAK all polls on its Interrupt IN
+ endpoint until the report state changes, or the guarding period expires.
+
+ The SET_IDLE command can either be issued for a particular duration, or for an
+ undefined period of time. The upper byte of the wValue field is used to
+ specify this duration. In addition, if the %device generates multiple reports,
+ the Report ID of the target report to affect can be specified in the lower
+ byte.
+
+ In practice, this request is often used with a keyboard to put a small delay
+ before a key is repeated continuously. For a mouse, it must be set to 0,
+ meaning that the %device should never report an unchanged state.
+
+ !GetIdle
+ The GET_IDLE request is issued by the host to retrieve the current Idle rate
+ of the %device. A particular Report can be specified with its Report ID.
+
+ !GetProtocol
+ This request returns the protocol currently used by the %device. This can
+ either be the Report protocol (}wValue} set to 0) or the Boot protocol
+ (}wValue} set to 1). Since a %device supporting the Boot protocol can operate
+ differently depending on which mode it is in, the host system can retrieve or
+ change this mode with the GET_PROTOCOL and SET_PROTOCOL requests.
+
+ This request is only need for devices supporting the Boot protocol.
+
+ !SetProtocol
+ Whenever an HID %device starts up, it should use the Report protocol by
+ default. However, the host driver shall still use the SET_PROTOCOL
+ request to specify if the %device should use the Report protocol or the
+ Boot protocol.
+
+ !!!Host Drivers
+ Most operating systems provide a generic HID driver which automatically
+ handles standard devices, such as keyboard, mice and joystick. In addition,
+ the driver can also be used by the application to easily access custom and
+ vendor-specific devices.
+
+*/ \ No newline at end of file
personal git repositories of Harald Welte. Your mileage may vary