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
//! HID (Human Interface Device) class support. The class covers
//! keyboards, mice, game controllers, and other input devices; there are
//! boot-protocol keyboard ([`keyboard`](crate::usb::hid::keyboard)) and
//! mouse ([`mouse`](crate::usb::hid::mouse)) drivers — the stage-2
//! milestone that validates the host controller, enumeration, and
//! interrupt transfers end to end by turning a real device's report
//! endpoint into input events — plus a gamepad driver
//! ([`gamepad`](crate::usb::hid::gamepad)) that goes through the full HID
//! report protocol instead.
//!
//! Those are the class's two ways of reading a device, and the drivers
//! here split along that line:
//!
//! - **Boot protocol** (keyboard, mouse): fixed-format reports defined by
//! the HID spec itself, needing no report-descriptor parsing — the
//! smallest real class driver, but available only from devices that
//! declare the boot subclass, and limited to the fields the boot
//! reports happen to carry.
//! - **Report protocol** (gamepad): the device declares its own report
//! layout in a HID *report descriptor*, which the host parses
//! ([`crate::hid_report`]) to learn where each control lives. More work,
//! but it reads devices that support nothing else — which is every
//! device outside the keyboard/mouse boot subclass.
/// Game controller driver, decoded through the HID report descriptor —
/// see [`gamepad::Gamepad`].
/// Boot-protocol keyboard driver — see [`keyboard::Keyboard`].
/// Boot-protocol mouse driver — see [`mouse::Mouse`].
use crate;
/// `bInterfaceClass` value identifying a Human Interface Device.
const HID_CLASS: u8 = 3;
/// `bInterfaceSubClass` value for the HID "boot interface subclass" — a
/// device declares this only when it actually supports the boot protocol
/// (fixed-format reports). Required in addition to the class/protocol
/// match: a composite device can expose a non-boot interface that still
/// claims a keyboard/mouse `bInterfaceProtocol` (an illuminated keyboard
/// observed here advertises a protocol-2 "mouse" interface whose reports
/// are report-ID-prefixed, not boot format), and driving it as a boot
/// device reads garbage. Insisting on subclass 1 keeps to interfaces
/// whose reports really are the boot format these drivers parse.
const BOOT_INTERFACE_SUBCLASS: u8 = 1;
/// `SET_PROTOCOL` value selecting the boot protocol (fixed-format
/// reports), as opposed to the report protocol (`1`).
const BOOT_PROTOCOL: u8 = 0;
/// `bDescriptorType` of a HID class descriptor (HID spec §6.2.1) — the
/// per-interface descriptor that follows an interface descriptor in the
/// configuration block and lists the interface's subordinate descriptors
/// (chiefly the report descriptor and its length).
const HID_CLASS_DESCRIPTOR: u8 = 0x21;
/// `bDescriptorType` of a HID report descriptor, as listed in the HID
/// class descriptor's subordinate-descriptor table.
const HID_REPORT_DESCRIPTOR: u8 = 0x22;
/// Offset of the subordinate-descriptor table (pairs of
/// `bDescriptorType`, `wDescriptorLength`) within a HID class descriptor.
const SUBORDINATE_TABLE_OFFSET: usize = 6;
/// Size of one subordinate-descriptor table entry: a one-byte type and a
/// two-byte length.
const SUBORDINATE_ENTRY_LEN: usize = 3;
/// A HID interface and its interrupt-IN report endpoint, located in a
/// configuration descriptor — the common shape all three drivers key off,
/// differing only in which interfaces they accept (see [`Self::find`]).
/// The report descriptor length a HID class descriptor declares, or `0` if
/// it lists no report descriptor. Its subordinate-descriptor table is
/// `bNumDescriptors` (type, length) pairs — normally just the report
/// descriptor, but a device may list optional physical descriptors too, so
/// the table is searched rather than indexed.
/// Whether `iface` is a HID boot interface with boot `protocol` (`1`
/// keyboard, `2` mouse) — the [`HidInterface::find`] filter the
/// boot-protocol drivers use. See [`BOOT_INTERFACE_SUBCLASS`] for why the
/// subclass has to match too.