usbd_hid/lib.rs
1//! HID report descriptor generation & USB HID class implementation
2//!
3//! This crate implements components necessary to build a USB HID device. This
4//! includes generation of the report descriptor, serialization of input reports,
5//! and communicating with a host that implements USB HID.
6#![no_std]
7
8pub use usb_device::{Result, UsbError};
9pub mod descriptor;
10pub mod hid_class;
11
12// Allow gen_hid_descriptor macro to access usbd_hid types from within usbd_hid itself,
13// while retaining the ability to run the macro in user crates as well.
14extern crate self as usbd_hid;
15
16#[cfg(test)]
17#[allow(unused_imports)]
18mod tests {
19 use crate::descriptor::{generator_prelude::*, CtapReport};
20 use crate::descriptor::{KeyboardReport, MouseReport, SystemControlReport};
21
22 fn serialize<T: AsInputReport>(buf: &mut [u8], report: T) -> &[u8] {
23 let size = report.serialize(buf).unwrap();
24 &buf[..size]
25 }
26
27 // This should generate this descriptor:
28 // 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
29 // 0x09, 0x01, // Usage (0x01)
30 // 0xA1, 0x01, // Collection (Application)
31 // 0x15, 0x00, // Logical Minimum (0)
32 // 0x26, 0xFF, 0x00, // Logical Maximum (255)
33 // 0x75, 0x08, // Report Size (8)
34 // 0x95, 0x01, // Report Count (1)
35 // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
36 // 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)
37 // 0x75, 0x10, // Report Size (16)
38 // 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
39 // 0xC1, // End Collection
40 #[gen_hid_descriptor(
41 (collection = 0x01, usage = 0x01, usage_page = 0xff00) = {
42 f1=input;
43 f2=output;
44 }
45 )]
46 #[allow(dead_code)]
47 struct CustomUnaryUnsignedFrame {
48 f1: u8,
49 f2: u16,
50 }
51
52 #[test]
53 fn test_custom_unsigned() {
54 let expected = &[
55 6u8, 0u8, 255u8, 9u8, 1u8, 161u8, 1u8, 21u8, 0u8, 38u8, 255u8, 0u8, 117u8, 8u8, 149u8,
56 1u8, 129u8, 2u8, 39u8, 255u8, 255u8, 0u8, 0u8, 117u8, 16u8, 145u8, 2u8, 192u8,
57 ];
58 assert_eq!(CustomUnaryUnsignedFrame::desc(), expected);
59 }
60
61 #[test]
62 fn test_custom_unsigned_serialize() {
63 let expected = &[1];
64 let report = CustomUnaryUnsignedFrame { f1: 1, f2: 2 };
65 let mut buf = [0; 64];
66 let result = serialize(&mut buf, report);
67 assert_eq!(result, expected);
68 }
69
70 // This should generate this descriptor:
71 // 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
72 // 0x09, 0x01, // Usage (0x01)
73 // 0xA1, 0x01, // Collection (Application)
74 // 0x17, 0x81, 0xFF, 0xFF, 0xFF, // Logical Minimum (-128)
75 // 0x25, 0x7F, // Logical Maximum (127)
76 // 0x75, 0x08, // Report Size (8)
77 // 0x95, 0x01, // Report Count (1)
78 // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
79 // 0x17, 0x01, 0x80, 0xFF, 0xFF, // Logical Minimum (-32768)
80 // 0x26, 0xFF, 0x7F, // Logical Maximum (32767)
81 // 0x75, 0x10, // Report Size (16)
82 // 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
83 // 0xC0, // End Collection
84 #[gen_hid_descriptor(
85 (collection = 0x01, usage = 0x01, usage_page = 0xff00) = {
86 f1=input;
87 f2=output;
88 }
89 )]
90 #[allow(dead_code)]
91 struct CustomUnarySignedFrame {
92 f1: i8,
93 f2: i16,
94 }
95
96 #[test]
97 fn test_custom_signed() {
98 let expected = &[
99 6u8, 0u8, 255u8, 9u8, 1u8, 161u8, 1u8, 23u8, 129u8, 255u8, 255u8, 255u8, 37u8, 127u8,
100 117u8, 8u8, 149u8, 1u8, 129u8, 2u8, 23u8, 1u8, 128u8, 255u8, 255u8, 38u8, 255u8, 127u8,
101 117u8, 16u8, 145u8, 2u8, 192u8,
102 ];
103 assert_eq!(CustomUnarySignedFrame::desc()[0..32], expected[0..32]);
104 }
105
106 #[test]
107 fn test_custom_signed_serialize() {
108 let expected = &[1];
109 let report = CustomUnarySignedFrame { f1: 1, f2: 2 };
110 let mut buf = [0; 64];
111 let result = serialize(&mut buf, report);
112 assert_eq!(result, expected);
113 }
114
115 #[gen_hid_descriptor(
116 (report_id = 0x01,) = {
117 f1=input
118 },
119 (report_id = 0x02,) = {
120 f2=input
121 },
122 )]
123 #[allow(dead_code)]
124 struct CustomMultiReport {
125 f1: u8,
126 f2: u8,
127 }
128
129 #[test]
130 fn test_custom_reports() {
131 let expected: &[u8] = &[
132 133, 1, 21, 0, 38, 255, 0, 117, 8, 149, 1, 129, 2, 133, 2, 129, 2,
133 ];
134 assert_eq!(CustomMultiReport::desc(), expected);
135 }
136
137 // This should generate the following descriptor:
138 // 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
139 // 0x09, 0x01, // Usage (0x01)
140 // 0xA1, 0x01, // Collection (Application)
141 // 0x15, 0x00, // Logical Minimum (0)
142 // 0x26, 0xFF, 0x00, // Logical Maximum (255)
143 // 0x75, 0x08, // Report Size (8)
144 // 0x95, 0x20, // Report Count (32)
145 // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
146 // 0xC0, // End Collection
147 #[gen_hid_descriptor(
148 (collection = 0x01, usage = 0x01, usage_page = 0xff00) = {
149 buff=input;
150 }
151 )]
152 #[allow(dead_code)]
153 struct CustomArray {
154 buff: [u8; 32],
155 }
156
157 #[test]
158 fn test_array() {
159 let expected: &[u8] = &[
160 6, 0, 255, 9, 1, 161, 1, 21, 0, 38, 255, 0, 117, 8, 149, 32, 129, 2, 192,
161 ];
162 assert_eq!(CustomArray::desc(), expected);
163 }
164
165 #[test]
166 fn test_array_serialize() {
167 let expected = [
168 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
169 4, 4, 4,
170 ];
171 let report = CustomArray { buff: [4; 32] };
172 let mut buf = [0; 64];
173 let result = serialize(&mut buf, report);
174 assert_eq!(result, expected);
175 }
176
177 #[gen_hid_descriptor(
178 (collection = APPLICATION, usage_page = VENDOR_DEFINED_START, usage = 0x01) = {
179 (usage_min = BUTTON_1, usage_max = BUTTON_3) = {
180 #[item_settings(data,variable,relative)] f1=input;
181 };
182 }
183 )]
184 #[allow(dead_code)]
185 struct CustomConst {
186 f1: u8,
187 }
188
189 #[test]
190 fn test_custom_const() {
191 let expected = &[
192 6u8, 0u8, 255u8, 9u8, 1u8, 161u8, 1u8, 25u8, 1u8, 41u8, 3u8, 21u8, 0u8, 38u8, 255u8,
193 0u8, 117u8, 8u8, 149u8, 1u8, 129u8, 6u8, 192u8,
194 ];
195 assert_eq!(CustomConst::desc(), expected);
196 }
197
198 #[test]
199 fn test_custom_const_serialize() {
200 let expected = &[1];
201 let report = CustomConst { f1: 1 };
202 let mut buf = [0; 64];
203 let result = serialize(&mut buf, report);
204 assert_eq!(result, expected);
205 }
206
207 // This should generate the following descriptor:
208 // 0x85, 0x01, // Report ID (1)
209 // 0x15, 0x00, // Logical Minimum (0)
210 // 0x25, 0x01, // Logical Maximum (1)
211 // 0x75, 0x01, // Report Size (1)
212 // 0x95, 0x03, // Report Count (3)
213 // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
214 // 0x95, 0x05, // Report Count (5)
215 // 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
216 // 0x95, 0x09, // Report Count (9)
217 // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
218 // 0x95, 0x07, // Report Count (7)
219 // 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
220 // 0x95, 0x14, // Report Count (20)
221 // 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
222 // 0x95, 0x04, // Report Count (4)
223 // 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
224 #[gen_hid_descriptor(
225 (report_id = 0x01,) = {
226 #[packed_bits = 3] f1=input;
227 #[packed_bits = 9] f2=input;
228 #[packed_bits = 20] f3=input;
229 }
230 )]
231 #[allow(dead_code)]
232 struct CustomPackedBits {
233 f1: u8,
234 f2: u16,
235 f3: [u8; 3],
236 }
237
238 #[test]
239 fn test_custom_packed_bits() {
240 let expected = &[
241 133u8, 1u8, 21u8, 0u8, 37u8, 1u8, 117u8, 1u8, 149u8, 3u8, 129u8, 2u8, 149u8, 5u8,
242 129u8, 3u8, 149u8, 9u8, 129u8, 2u8, 149u8, 7u8, 129u8, 3u8, 149u8, 20u8, 129u8, 2u8,
243 149u8, 4u8, 129u8, 3u8,
244 ];
245 assert_eq!(CustomPackedBits::desc(), expected);
246 }
247
248 #[test]
249 fn test_mouse_descriptor() {
250 let expected = &[
251 5u8, 1u8, 9u8, 2u8, 161u8, 1u8, 9u8, 1u8, 161u8, 0u8, 5u8, 9u8, 25u8, 1u8, 41u8, 8u8,
252 21u8, 0u8, 37u8, 1u8, 117u8, 1u8, 149u8, 8u8, 129u8, 2u8, 5u8, 1u8, 9u8, 48u8, 23u8,
253 129u8, 255u8, 255u8, 255u8, 37u8, 127u8, 117u8, 8u8, 149u8, 1u8, 129u8, 6u8, 9u8, 49u8,
254 129u8, 6u8, 9u8, 56u8, 129u8, 6u8, 5u8, 12u8, 10u8, 56u8, 2u8, 129u8, 6u8, 192u8,
255 192u8,
256 ];
257 assert_eq!(MouseReport::desc()[0..32], expected[0..32]);
258 }
259
260 #[test]
261 fn test_mouse_serialize() {
262 let expected = &[1, 2, 3, 4, 5];
263 let report = MouseReport {
264 buttons: 1,
265 x: 2,
266 y: 3,
267 wheel: 4,
268 pan: 5,
269 };
270 let mut buf = [0; 64];
271 let result = serialize(&mut buf, report);
272 assert_eq!(result, expected);
273 }
274
275 #[test]
276 fn test_keyboard_descriptor() {
277 let expected = &[
278 0x05, 0x01, // Usage Page (Generic Desktop)
279 0x09, 0x06, // Usage (Keyboard)
280 0xa1, 0x01, // Collection (Application)
281 0x05, 0x07, // Usage Page (Key Codes)
282 0x19, 0xe0, // Usage Minimum (224)
283 0x29, 0xe7, // Usage Maximum (231)
284 0x15, 0x00, // Logical Minimum (0)
285 0x25, 0x01, // Logical Maximum (1)
286 0x75, 0x01, // Report Size (1)
287 0x95, 0x08, // Report count (8)
288 0x81, 0x02, // Input (Data, Variable, Absolute)
289 0x19, 0x00, // Usage Minimum (0)
290 0x29, 0xFF, // Usage Maximum (255)
291 0x26, 0xFF, 0x00, // Logical Maximum (255)
292 0x75, 0x08, // Report Size (8)
293 0x95, 0x01, // Report Count (1)
294 0x81, 0x03, // Input (Const, Variable, Absolute)
295 0x05, 0x08, // Usage Page (LEDs)
296 0x19, 0x01, // Usage Minimum (1)
297 0x29, 0x05, // Usage Maximum (5)
298 0x25, 0x01, // Logical Maximum (1)
299 0x75, 0x01, // Report Size (1)
300 0x95, 0x05, // Report Count (5)
301 0x91, 0x02, // Output (Data, Variable, Absolute)
302 0x95, 0x03, // Report Count (3)
303 0x91, 0x03, // Output (Constant, Variable, Absolute)
304 0x05, 0x07, // Usage Page (Key Codes)
305 0x19, 0x00, // Usage Minimum (0)
306 0x29, 0xDD, // Usage Maximum (221)
307 0x26, 0xFF, 0x00, // Logical Maximum (255)
308 0x75, 0x08, // Report Size (8)
309 0x95, 0x06, // Report Count (6)
310 0x81, 0x00, // Input (Data, Array, Absolute)
311 0xc0, // End Collection
312 ];
313 assert_eq!(KeyboardReport::desc(), expected);
314 }
315
316 #[test]
317 fn test_keyboard_serialize() {
318 let expected = &[1, 2, 4, 5, 6, 7, 8, 9];
319 let report = KeyboardReport {
320 modifier: 1,
321 reserved: 2,
322 leds: 3,
323 keycodes: [4, 5, 6, 7, 8, 9],
324 };
325 let mut buf = [0; 64];
326 let result = serialize(&mut buf, report);
327 assert_eq!(result, expected);
328 }
329
330 #[test]
331 fn test_system_control_descriptor() {
332 let expected = &[
333 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
334 0x09, 0x80, // Usage (Sys Control)
335 0xA1, 0x01, // Collection (Application)
336 0x19, 0x81, // Usage Minimum (Sys Power Down)
337 0x29, 0xB7, // Usage Maximum (Sys Display LCD Autoscale)
338 0x15, 0x01, // Logical Minimum (1)
339 0x26, 0xFF, 0x00, // Logical Maximum (255)
340 0x75, 0x08, // Report Size (8)
341 0x95, 0x01, // Report Count (1)
342 0x81,
343 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
344 0xC0, // End Collection
345 ];
346 assert_eq!(SystemControlReport::desc(), expected);
347 }
348
349 #[test]
350 fn test_system_control_serialize() {
351 let expected = &[4];
352 let report = SystemControlReport { usage_id: 4 };
353 let mut buf = [0; 64];
354 let result = serialize(&mut buf, report);
355 assert_eq!(result, expected);
356 }
357
358 #[test]
359 fn test_ctap_serialize() {
360 let expected = &[
361 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
362 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
363 1, 1, 1, 1, 1, 1,
364 ];
365 let report = CtapReport {
366 data_in: [1; 64],
367 data_out: [2; 64],
368 };
369 let mut buf = [0; 64];
370 let result = serialize(&mut buf, report);
371 assert_eq!(result, expected);
372 }
373}