SAMV71 Xplained Ultra Software Package 1.3

hid-mouse.dir

00001 /* ----------------------------------------------------------------------------
00002  *         ATMEL Microcontroller Software Support 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2008, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /**
00031  *  \dir usb/device/hid-mouse
00032  * 
00033  *  \section Purpose
00034  * 
00035  *  This directory provides definitions, structs and functions for a USB HID
00036  *  %device - USB HID Mouse driver, to implement an USB Mouse %device.
00037  * 
00038  *  \section Contents
00039  * 
00040  *  There are three things for the implement of the USB HID Mouse driver:
00041  *  - Implement the USB HID driver structs and functions for the %device,
00042  *    to initialize, to handle HID-specific requests and dispach
00043  *    standard requests in USBD callbacks, to read/write through assigned USB
00044  *    endpoints,
00045  *  - Create the HID Mouse device's descriptors that should be passed to
00046  *    the USBDDriver instance on initialization, so that the host can 
00047  *    recognize the %device as a USB Mouse %device.
00048  *  - Implement methods to update the Mouse keys status, so that host can
00049  *    get it through USB.
00050  * 
00051  *  For more information about what a particular group contains, please refer to
00052  *  "USB HID Mouse".
00053  */
00054 
00055 /**
00056  \page usbd_hid_mouse_drv USB Device HID Mouse Driver
00057 
00058  This page describes how to use the \ref usbd_framework to produce a USB
00059  HID Mouse driver, which appears as a USB Mouse on host.
00060 
00061  Details about the USB and the HID class can be found in the <i>USB specification
00062  2.0</i> and the <i>HID specification 1.11</i>, respectively.
00063 
00064  \section References
00065  - \ref usbd_framework
00066  - \ref usbd_enum
00067  - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
00068    Universal Serial Bus Revision 2.0 specification
00069    </a> (.zip file format, size 9.80 MB)
00070  - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
00071    Device Class Definition for HID 1.11</a>
00072  - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
00073    HID Usage Tables 1.12</a>
00074 
00075  \section  hid_basic HID Basic
00076  See \ref usb_hid_basic "USB HID Basic".
00077 
00078  \section Architecture
00079  See \ref usbd_framework_arch "USB Device Framework Architecture".
00080 
00081  \section Descriptors
00082 
00083  \subsection  dev_desc Device Descriptor
00084  The Device descriptor of an HID %device is very basic, since the HID class
00085  code is only specified at the Interface level. Thus, it only contains
00086  standard values, as shown below:
00087 \code
00088 static const USBDeviceDescriptor deviceDescriptor = {
00089 
00090     sizeof(USBDeviceDescriptor),
00091     USBGenericDescriptor_DEVICE,
00092     USBDeviceDescriptor_USB2_00,
00093     HIDDeviceDescriptor_CLASS,
00094     HIDDeviceDescriptor_SUBCLASS,
00095     HIDDeviceDescriptor_PROTOCOL,
00096     BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
00097     HIDDMouseDriverDescriptors_VENDORID,
00098     HIDDMouseDriverDescriptors_PRODUCTID,
00099     HIDDMouseDriverDescriptors_RELEASE,
00100     1, // Index of manufacturer description
00101     2, // Index of product description
00102     3, // Index of serial number description
00103     1  // One possible configuration
00104 };
00105 \endcode
00106  Note that the Vendor ID is a special value attributed by the USB-IF
00107  organization. The product ID can be chosen freely by the vendor.
00108 
00109  \subsection  cfg_desc Configuration Descriptor
00110  Since one interface is required by the HID specification, this must be
00111  specified in the Configuration descriptor. There is no other value of
00112  interest to put here.
00113 \code
00114 // Configuration descriptor
00115 {
00116     sizeof(USBConfigurationDescriptor),
00117     USBGenericDescriptor_CONFIGURATION,
00118     sizeof(HIDDMouseDriverConfigurationDescriptors),
00119     1, // One interface in this configuration
00120     1, // This is configuration #1
00121     0, // No associated string descriptor
00122     BOARD_USB_BMATTRIBUTES,
00123     USBConfigurationDescriptor_POWER(100)
00124 },
00125 \endcode
00126  When the Configuration descriptor is requested by the host (by using the
00127  GET_DESCRIPTOR command), the %device must also sent all the related
00128  descriptors, i.e. Interface, Endpoint and Class-Specific descriptors. It is
00129  convenient to create a single structure to hold all this data, for sending
00130  everything in one chunk. In the example software, a
00131  HIDDMouseDriverConfigurationDescriptors structure has been declared for
00132  that.
00133 
00134  \subsection  hid_class_if_desc HID Class Interface Descriptor
00135  Since a Mouse %device needs to transmit as well as receive data, two
00136  Interrupt (IN & OUT) endpoints are needed. This must be indicated in the
00137  Interface descriptor. Conversely to the mouse example, the Boot protocol is
00138  not implemented here, since there are more constraints on a Mouse %device.
00139 \code
00140 // Interface descriptor
00141 {
00142     sizeof(USBInterfaceDescriptor),
00143     USBGenericDescriptor_INTERFACE,
00144     0, // This is interface #0
00145     0, // This is alternate setting #0
00146     2, // Two endpoints used
00147     HIDInterfaceDescriptor_CLASS,
00148     HIDInterfaceDescriptor_SUBCLASS_NONE,
00149     HIDInterfaceDescriptor_PROTOCOL_NONE,
00150     0  // No associated string descriptor
00151 },
00152 \endcode
00153 
00154  \subsection  hid_desc HID Descriptor
00155  While a HID Mouse produces two different reports, one Input and one Output,
00156  only one Report descriptor can be used to describe them. Since having Physical
00157  descriptors is also useless for a Mouse, there will only be one HID class
00158  descriptor specified here.
00159 
00160  For a Mouse, the }bCountryCode} field can be used to specify the language
00161  of the key caps. As this is optional, it is simply set to 00h in the example:
00162 \code
00163 // HID descriptor
00164 {
00165     sizeof(HIDDescriptor),
00166     HIDGenericDescriptor_HID,
00167     HIDDescriptor_HID1_11,
00168     0, // Device is not localized, no country code
00169     1, // One HID-specific descriptor (apart from this one)
00170     HIDGenericDescriptor_REPORT,
00171     HIDDMouseDriverDescriptors_REPORTSIZE
00172 },
00173 \endcode
00174 
00175  \subsection  hid_rep_desc Report Descriptor
00176  Two current reports are defined in the Report descriptor. The first one is
00177  used to notify the host of which keys are pressed, with both modifier keys
00178  (alt, ctrl, etc.) and alphanumeric keys. The second report is necessary for
00179  the host to send the LED (num lock, caps lock, etc.) states.
00180 
00181  The Report descriptor starts with the global %device functionality, described
00182  with a <b>Usage Page</b> and a <b>Usage</b> items:
00183 \code
00184 const unsigned char hiddReportDescriptor[] = {
00185 
00186     HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
00187     HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_Mouse,
00188 \endcode
00189 
00190  As in the mouse example, the }Generic Desktop} page is used. This time, the
00191  specific usage is the }Mouse} one. An Application collection is then
00192  defined to group the reports together:
00193 \code
00194     HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
00195 \endcode
00196 
00197  The first report to be defined is the modifier keys. They are represented as a
00198  bitmap field, indicating whether or not each key is pressed. A single byte is
00199  used to map keys \#224-231 defined in the }HID Usage Tables} document:
00200  LeftControl, LeftShift, LeftAlt, LeftGUI (e.g. Windows key),
00201  RightControl, RightShift, RightAlt and RightGUI.
00202  The }Keypad} usage page must be specified for this report, and since this is a
00203  bitmap value, the data is flagged as }Variable}:
00204 \code
00205         // Input report: modifier keys
00206         HIDReport_GLOBAL_REPORTSIZE + 1, 1,
00207         HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
00208         HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
00209         HIDReport_LOCAL_USAGEMINIMUM + 1,
00210             HIDDMouseDriverDescriptors_FIRSTMODIFIERKEY,
00211         HIDReport_LOCAL_USAGEMAXIMUM + 1,
00212             HIDDMouseDriverDescriptors_LASTMODIFIERKEY,
00213         HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
00214         HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
00215         HIDReport_INPUT + 1, HIDReport_VARIABLE,
00216 \endcode
00217 
00218  Then, the actual alphanumeric key report is described. This is done by
00219  defining several bytes of data, one for each pressed key. In the example,
00220  up to three keys can be pressed at the same time (and detected) by the user.
00221  Once again, the usage page is set to }Keypad}. This time however, the data
00222  must be specified as an }Array}, since the same control (the keypad) produces
00223  several values:
00224 \code
00225         // Input report: standard keys
00226         HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
00227         HIDReport_GLOBAL_REPORTSIZE + 1, 8,
00228         HIDReport_GLOBAL_LOGICALMINIMUM + 1,
00229             HIDDMouseDriverDescriptors_FIRSTSTANDARDKEY,
00230         HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
00231             HIDDMouseDriverDescriptors_LASTSTANDARDKEY,
00232         HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
00233         HIDReport_LOCAL_USAGEMINIMUM + 1,
00234             HIDDMouseDriverDescriptors_FIRSTSTANDARDKEY,
00235         HIDReport_LOCAL_USAGEMAXIMUM + 1,
00236             HIDDMouseDriverDescriptors_LASTSTANDARDKEY,
00237         HIDReport_INPUT + 1, 0 /* Data array */,
00238 \endcode
00239 
00240  The LED array is then defined, with the associated usage page. The Report
00241  descriptor is formatted in this order to avoid redefining unchanged <i>Global</i>
00242  items, in order to save memory. This time again, the LED status is reported as
00243  a bitmap field. Three LEDs are used here: Num Lock, Caps Lock and Scroll Lock
00244  (IDs 01h to 03h). It is important to note that this is an <b>Output</b> report:
00245 \code
00246         // Output report: LEDs
00247         HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
00248         HIDReport_GLOBAL_REPORTSIZE + 1, 1,
00249         HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
00250         HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
00251         HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
00252         HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
00253         HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
00254         HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
00255 \endcode
00256 
00257  Since the previous report only contains 3 bits, the data must be padded to a
00258  multiple of one byte. This is done by using constant Output data, as follows:
00259 \code
00260         // Output report: padding
00261         HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
00262         HIDReport_GLOBAL_REPORTSIZE + 1, 5,
00263         HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
00264 \endcode
00265 
00266  The last item, <i>End Collection</i>, is necessary to close the previously opened
00267  <i>Application Collection</i>.
00268 \code
00269     HIDReport_ENDCOLLECTION
00270 };
00271 \endcode
00272 
00273  The Input and Output reports defined by this descriptor can be modeled by the
00274  following structures:
00275 \code
00276 // HID Input Report
00277 typedef struct {
00278 
00279   // State of modifier keys.
00280   unsigned char bmModifierKeys:8;
00281   // Key codes of pressed keys.
00282   unsigned char pressedKeys[HIDDMouseInputReport_MAXKEYPRESSES];
00283 
00284 } __attribute__ ((packed)) HIDDMouseInputReport; // GCC
00285 // HID Output Report
00286 typedef struct {
00287 
00288   unsigned char numLockStatus:1, // State of the num. lock LED.
00289     capsLockStatus:1,   // State of the caps lock LED.
00290     scrollLockStatus:1, // State of the scroll lock LED.
00291     padding:5;          // Padding bits.
00292 
00293 } __attribute__ ((packed)) HIDDMouseOutputReport; // GCC
00294 \endcode
00295 
00296  An instance of each one of the reports is stored in a HIDDMouseDriver
00297  structure, which holds the standard class driver and HID Mouse-specific
00298  data.
00299 
00300  \subsection  psy_desc Physical Descriptor
00301  A Physical descriptor is useless for a Mouse %device, so none are defined
00302  in this example.
00303 
00304  \subsection  ep_desc Endpoint Descriptor
00305  Following the Interface and HID-specific descriptors, the two necessary
00306  endpoints are defined.
00307 \code
00308 // Interrupt IN endpoint descriptor
00309 {
00310     sizeof(USBEndpointDescriptor),
00311     USBGenericDescriptor_ENDPOINT,
00312     USBEndpointDescriptor_ADDRESS(
00313         USBEndpointDescriptor_IN,
00314         HIDDMouseDriverDescriptors_INTERRUPTIN),
00315     USBEndpointDescriptor_INTERRUPT,
00316     sizeof(HIDDMouseInputReport),
00317     HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING
00318 },
00319 // Interrupt OUT endpoint descriptor
00320 {
00321     sizeof(USBEndpointDescriptor),
00322     USBGenericDescriptor_ENDPOINT,
00323     USBEndpointDescriptor_ADDRESS(
00324         USBEndpointDescriptor_OUT,
00325         HIDDMouseDriverDescriptors_INTERRUPTOUT),
00326     USBEndpointDescriptor_INTERRUPT,
00327     sizeof(HIDDMouseOutputReport),
00328     HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING
00329 }
00330 \endcode
00331 
00332  \subsection  str_desc String Descriptors
00333  Please refer to \ref usbd_id_str "Usage: USBD VID, PID & Strings".
00334 
00335  \section  class_spec_req Class-specific requests
00336  A driver request handler should first differentiate between class-specific and
00337  standard requests using the corresponding bits in the <i>bmRequestType</i> field.
00338  In most cases, standard requests can be immediately forwarded to the standard
00339  request handler method; class-specific methods must be decoded and treated by
00340  the custom handler.
00341 
00342  \subsection GetDescriptor
00343  Three values have been added by the HID specification for the <b>GET_DESCRIPTOR</b>
00344  request. The high byte of the <i>wValue</i> field contains the type of the
00345  requested descriptor; in addition to the standard types, the <b>HID specification</b>
00346  adds the <b>HID descriptor</b> (21h), the <b>Report descriptor</b>
00347  (22h) and the <b>Physical descriptor</b> (23h) types.
00348 
00349  There is no particular action to perform besides sending the descriptor. This
00350  can be done by using the USBD_Write() method, after the requested descriptor has
00351  been identified:
00352 \code
00353 switch (USBGenericRequest_GetRequest(request)) {
00354 
00355   case USBGenericRequest_GETDESCRIPTOR:
00356     // Check if this is a HID descriptor,
00357     // otherwise forward it to
00358     // the standard driver
00359     if (!HIDDMouseDriver_GetDescriptor(
00360         USBGetDescriptorRequest_GetDescriptorType(request),
00361         USBGenericRequest_GetLength(request))) {
00362 
00363       USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver),
00364                               request);
00365     }
00366     break;
00367 
00368   default:
00369     USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver),
00370                                   request);
00371 }
00372 \endcode
00373  A slight complexity of the GET_DESCRIPTOR and SET_DESCRIPTOR requests is that
00374  those are standard requests, but the standard request handler
00375  (USBDDriver_RequestHandler()) must not always be called to treat them (since
00376  they may refer to HID descriptors). The solution is to first identify
00377  GET/SET_DESCRIPTOR requests, treat the HID-specific cases and, finally,
00378  forward any other request to the standard handler.
00379 
00380  In this case, a GET_DESCRIPTOR request for the Physical descriptor is first
00381  forwarded to the standard handler, and STALLed there because it is not
00382  recognized. This is done because the %device does not have any Physical
00383  descriptors, and thus, does not need to handle the associated request.
00384 
00385  \subsection SetDescriptor
00386  This request is optional and is never issued by most hosts. It is not
00387  implemented in this example.
00388 
00389  \subsection GetReport
00390  Since the HID Mouse defines two different reports, the Report Type value
00391  specified by this request (upper byte of the <i>wValue</i> field) must be examined
00392  to decide which report to send. If the type value is 01h, then the Input
00393  report must be returned; if it is 02h, the Output report is requested:
00394 \code
00395 case HIDGenericRequest_GETREPORT:
00396 //-------------------------------
00397   type = HIDReportRequest_GetReportType(request);
00398   length = USBGenericRequest_GetLength(request);
00399   switch (type) {
00400 
00401       case HIDReportRequest_INPUT:
00402 
00403         // Adjust size and send report
00404         if (length > sizeof(HIDDMouseInputReport)) {
00405 
00406           length = sizeof(HIDDMouseInputReport);
00407         }
00408         USBD_Write(0, // Endpoint #0
00409            &(hiddMouseDriver.inputReport),
00410            length,
00411            0, // No callback
00412            0);
00413         break;
00414 
00415       case HIDReportRequest_OUTPUT:
00416 
00417         // Adjust size and send report
00418         if (length > sizeof(HIDDMouseOutputReport)) {
00419 
00420           length = sizeof(HIDDMouseOutputReport);
00421         }
00422         USBD_Write(0, // Endpoint #0
00423            &(hiddMouseDriver.outputReport),
00424            length,
00425            0, // No callback
00426            0);
00427         break;
00428 
00429       default:
00430         USBD_Stall(0);
00431   }
00432 break;
00433 \endcode
00434 
00435  \subsection SetReport
00436  For an HID Mouse, the <b>SET_REPORT</b> command can be sent by the host to
00437  change the state of the LEDs. Normally, the dedicated Interrupt OUT endpoint
00438  will be used for this; but in some cases, using the default Control endpoint
00439  can save some bandwidth on the host side.
00440 
00441  Note that the SET_REPORT request can be directed at the Input report of the
00442  Mouse; in this case, it can be safely discarded, according to the HID
00443  specification. Normally, most host drivers only target the Output report. The
00444  Report Type value is stored in the upper byte of the <i>wValue</i> field.
00445 
00446  The length of the data phase to follow is stored in the <i>wLength</i> field of the
00447  request. It should be equal to the total length of the Output report. If it is
00448  different, the report status must still be updated with the received data as
00449  best as possible.
00450 
00451  When the reception of the new data is completed, some processing must be done
00452  to enable/disable the corresponding LEDs. This is done in the callback
00453  function passed as an argument to USBD_Read():
00454 \code
00455 case HIDGenericRequest_SETREPORT:
00456 //-------------------------------
00457   type = HIDReportRequest_GetReportType(request);
00458   length = USBGenericRequest_GetLength(request);
00459   switch(type) {
00460 
00461     case HIDReportRequest_INPUT:
00462       // SET_REPORT requests on input reports are ignored
00463       USBD_Stall(0);
00464       break;
00465 
00466     case HIDReportRequest_OUTPUT:
00467       // Check report length
00468       if (length != sizeof(HIDDMouseOutputReport)) {
00469 
00470         USBD_Stall(0);
00471       }
00472       else {
00473       
00474         USBD_Read(0, // Endpoint #0
00475           &(hiddMouseDriver.outputReport),
00476           length,
00477           (TransferCallback) HIDDMouseDriver_ReportReceived,
00478           0); // No argument to the callback function
00479       }
00480       break;
00481 
00482     default:
00483       USBD_Stall(0);
00484   }
00485 break;
00486 \endcode
00487 
00488  \subsection SetIdle
00489  In this case study, the <b>SET_IDLE</b> request is used to set a delay before a key
00490  is repeated. This is common behavior on Mouse devices. Usually, this delay
00491  is set to about 500 ms by the host.
00492 
00493  The only action here is to store the new Idle rate. The management of this
00494  setting must be done in the main function, since Interrupt IN reports are sent
00495  from there.
00496 
00497  In practice, it is not necessary to perform any action, apart from sending a
00498  zero-length packet to acknowledge it. The main application however has to make
00499  sure that only new reports are sent by the %device.
00500 \code
00501 case HIDGenericRequest_SETIDLE:
00502 //-----------------------------
00503   hiddMouseDriver.inputReportIdleRate =
00504            HIDIdleRequest_GetIdleRate(request);
00505   USBD_Write(0, 0, 0, 0, 0);
00506 break;
00507 \endcode
00508 
00509  \subsection GetIdle
00510  The only necessary operation for this request is to send the previously saved
00511  Idle rate. This is done by calling the USBD_Write() method with the one-byte
00512  variable as its parameter:
00513 \code
00514 case HIDGenericRequest_GETIDLE:
00515 //-----------------------------
00516   USBD_Write(0, &(hiddMouseDriver.inputReportIdleRate), 1, 0, 0);
00517 break;
00518 \endcode
00519 
00520  \subsection get_set_prot GetProtocol, SetProtocol
00521  This HID Mouse example does not support the Boot protocol, so there is no
00522  need to implement the SET_PROTOCOL and GET_PROTOCOL requests. This means they
00523  can be safely STALLed when received.
00524 
00525  \section main_app Main Application
00526  Like the mouse example, the main program must perform two different
00527  operations. First, it has to monitor the physical inputs used as keys. In the
00528  example software, the buttons present on the evaluation boards are used to
00529  produce several modifier and alphanumeric keys.
00530 
00531  Also, the main program is in charge of sending reports as they are modified,
00532  taking into account the Idle rate specified by the host. Idle rate management
00533  can be carried out by firing/resetting a timer once a new report is sent; if
00534  the timer expires, this means the Input report has not changed since.
00535  According to the HID specification, a single instance of the report must be
00536  sent in this case.
00537 
00538  Finally, the HID specification also defines that if too many keys are pressed
00539  at the same time, the %device should report an <i>ErrorRollOver</i> usage value
00540  (01h) in every byte of the key array. This has to be handled by the main
00541  application as well.
00542 
00543 */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines