summaryrefslogtreecommitdiff
path: root/usb/device/hid-keyboard/hid-keyboard.dir
blob: 923a362013e9d024f89b5ea9469dd6dcac2aea56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
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.

*/
personal git repositories of Harald Welte. Your mileage may vary