xref: /btstack/test/hid_parser/hid_parser_test.cpp (revision c70b3b486dde2b96829c110a442a90c62ebfbd82)
1 
2 // *****************************************************************************
3 //
4 // HID Parser Test
5 //
6 // *****************************************************************************
7 
8 
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "CppUTest/TestHarness.h"
15 #include "CppUTest/CommandLineTestRunner.h"
16 
17 #include "btstack_hid_parser.h"
18 #include "hci_dump_posix_fs.h"
19 
20 const uint8_t mouse_descriptor_without_report_id[] = {
21     0x05, 0x01, /*  Usage Page (Desktop),               */
22     0x09, 0x02, /*  Usage (Mouse),                      */
23     0xA1, 0x01, /*  Collection (Application),           */
24     0x09, 0x01, /*      Usage (Pointer),                */
25     0xA0,       /*      Collection (Physical),          */
26     0x05, 0x09, /*          Usage Page (Button),        */
27     0x19, 0x01, /*          Usage Minimum (01h),        */
28     0x29, 0x03, /*          Usage Maximum (03h),        */
29     0x14,       /*          Logical Minimum (0),        */
30     0x25, 0x01, /*          Logical Maximum (1),        */
31     0x75, 0x01, /*          Report Size (1),            */
32     0x95, 0x03, /*          Report Count (3),           */
33     0x81, 0x02, /*          Input (Variable),           */
34     0x75, 0x05, /*          Report Size (5),            */
35     0x95, 0x01, /*          Report Count (1),           */
36     0x81, 0x01, /*          Input (Constant),           */
37     0x05, 0x01, /*          Usage Page (Desktop),       */
38     0x09, 0x30, /*          Usage (X),                  */
39     0x09, 0x31, /*          Usage (Y),                  */
40     0x15, 0x81, /*          Logical Minimum (-127),     */
41     0x25, 0x7F, /*          Logical Maximum (127),      */
42     0x75, 0x08, /*          Report Size (8),            */
43     0x95, 0x02, /*          Report Count (2),           */
44     0x81, 0x06, /*          Input (Variable, Relative), */
45     0xC0,       /*      End Collection,                 */
46     0xC0        /*  End Collection                      */
47 };
48 
49 const uint8_t mouse_descriptor_with_report_id[] = {
50     0x05, 0x01, /*  Usage Page (Desktop),               */
51     0x09, 0x02, /*  Usage (Mouse),                      */
52     0xA1, 0x01, /*  Collection (Application),           */
53 
54     0x85,  0x01,                    // Report ID 1
55 
56     0x09, 0x01, /*      Usage (Pointer),                */
57     0xA0,       /*      Collection (Physical),          */
58     0x05, 0x09, /*          Usage Page (Button),        */
59     0x19, 0x01, /*          Usage Minimum (01h),        */
60     0x29, 0x03, /*          Usage Maximum (03h),        */
61     0x14,       /*          Logical Minimum (0),        */
62     0x25, 0x01, /*          Logical Maximum (1),        */
63     0x75, 0x01, /*          Report Size (1),            */
64     0x95, 0x03, /*          Report Count (3),           */
65     0x81, 0x02, /*          Input (Variable),           */
66     0x75, 0x05, /*          Report Size (5),            */
67     0x95, 0x01, /*          Report Count (1),           */
68     0x81, 0x01, /*          Input (Constant),           */
69     0x05, 0x01, /*          Usage Page (Desktop),       */
70     0x09, 0x30, /*          Usage (X),                  */
71     0x09, 0x31, /*          Usage (Y),                  */
72     0x15, 0x81, /*          Logical Minimum (-127),     */
73     0x25, 0x7F, /*          Logical Maximum (127),      */
74     0x75, 0x08, /*          Report Size (8),            */
75     0x95, 0x02, /*          Report Count (2),           */
76     0x81, 0x06, /*          Input (Variable, Relative), */
77     0xC0,       /*      End Collection,                 */
78     0xC0        /*  End Collection                      */
79 };
80 
81 // from USB HID Specification 1.1, Appendix B.1
82 const uint8_t hid_descriptor_keyboard_boot_mode[] = {
83 
84     0x05, 0x01,                    // Usage Page (Generic Desktop)
85     0x09, 0x06,                    // Usage (Keyboard)
86     0xa1, 0x01,                    // Collection (Application)
87 
88     // Modifier byte
89 
90     0x75, 0x01,                    //   Report Size (1)
91     0x95, 0x08,                    //   Report Count (8)
92     0x05, 0x07,                    //   Usage Page (Key codes)
93     0x19, 0xe0,                    //   Usage Minimum (Keyboard LeftControl)
94     0x29, 0xe7,                    //   Usage Maxium (Keyboard Right GUI)
95     0x15, 0x00,                    //   Logical Minimum (0)
96     0x25, 0x01,                    //   Logical Maximum (1)
97     0x81, 0x02,                    //   Input (Data, Variable, Absolute)
98 
99     // Reserved byte
100 
101     0x75, 0x01,                    //   Report Size (1)
102     0x95, 0x08,                    //   Report Count (8)
103     0x81, 0x03,                    //   Input (Constant, Variable, Absolute)
104 
105     // LED report + padding
106 
107     0x95, 0x05,                    //   Report Count (5)
108     0x75, 0x01,                    //   Report Size (1)
109     0x05, 0x08,                    //   Usage Page (LEDs)
110     0x19, 0x01,                    //   Usage Minimum (Num Lock)
111     0x29, 0x05,                    //   Usage Maxium (Kana)
112     0x91, 0x02,                    //   Output (Data, Variable, Absolute)
113 
114     0x95, 0x01,                    //   Report Count (1)
115     0x75, 0x03,                    //   Report Size (3)
116     0x91, 0x03,                    //   Output (Constant, Variable, Absolute)
117 
118     // Keycodes
119 
120     0x95, 0x06,                    //   Report Count (6)
121     0x75, 0x08,                    //   Report Size (8)
122     0x15, 0x00,                    //   Logical Minimum (0)
123     0x25, 0xff,                    //   Logical Maximum (1)
124     0x05, 0x07,                    //   Usage Page (Key codes)
125     0x19, 0x00,                    //   Usage Minimum (Reserved (no event indicated))
126     0x29, 0xff,                    //   Usage Maxium (Reserved)
127     0x81, 0x00,                    //   Input (Data, Array)
128 
129     0xc0,                          // End collection
130 };
131 
132 const uint8_t combo_descriptor_with_report_ids[] = {
133 
134     0x05, 0x01, /*  Usage Page (Desktop),               */
135     0x09, 0x02, /*  Usage (Mouse),                      */
136     0xA1, 0x01, /*  Collection (Application),           */
137 
138     0x85, 0x01, // Report ID 1
139 
140     0x09, 0x01, /*      Usage (Pointer),                */
141     0xA0,       /*      Collection (Physical),          */
142     0x05, 0x09, /*          Usage Page (Button),        */
143     0x19, 0x01, /*          Usage Minimum (01h),        */
144     0x29, 0x03, /*          Usage Maximum (03h),        */
145     0x14,       /*          Logical Minimum (0),        */
146     0x25, 0x01, /*          Logical Maximum (1),        */
147     0x75, 0x01, /*          Report Size (1),            */
148     0x95, 0x03, /*          Report Count (3),           */
149     0x81, 0x02, /*          Input (Variable),           */
150     0x75, 0x05, /*          Report Size (5),            */
151     0x95, 0x01, /*          Report Count (1),           */
152     0x81, 0x01, /*          Input (Constant),           */
153     0x05, 0x01, /*          Usage Page (Desktop),       */
154     0x09, 0x30, /*          Usage (X),                  */
155     0x09, 0x31, /*          Usage (Y),                  */
156     0x15, 0x81, /*          Logical Minimum (-127),     */
157     0x25, 0x7F, /*          Logical Maximum (127),      */
158     0x75, 0x08, /*          Report Size (8),            */
159     0x95, 0x02, /*          Report Count (2),           */
160     0x81, 0x06, /*          Input (Variable, Relative), */
161     0xC0,       /*      End Collection,                 */
162     0xC0,       /*  End Collection                      */
163 
164     0xa1, 0x01,                    // Collection (Application)
165 
166     0x85, 0x02, // Report ID 2
167 
168     // Modifier byte
169 
170     0x75, 0x01,                    //   Report Size (1)
171     0x95, 0x08,                    //   Report Count (8)
172     0x05, 0x07,                    //   Usage Page (Key codes)
173     0x19, 0xe0,                    //   Usage Minimum (Keyboard LeftControl)
174     0x29, 0xe7,                    //   Usage Maxium (Keyboard Right GUI)
175     0x15, 0x00,                    //   Logical Minimum (0)
176     0x25, 0x01,                    //   Logical Maximum (1)
177     0x81, 0x02,                    //   Input (Data, Variable, Absolute)
178 
179     // Reserved byte
180 
181     0x75, 0x01,                    //   Report Size (1)
182     0x95, 0x08,                    //   Report Count (8)
183     0x81, 0x03,                    //   Input (Constant, Variable, Absolute)
184 
185     // LED report + padding
186 
187     0x95, 0x05,                    //   Report Count (5)
188     0x75, 0x01,                    //   Report Size (1)
189     0x05, 0x08,                    //   Usage Page (LEDs)
190     0x19, 0x01,                    //   Usage Minimum (Num Lock)
191     0x29, 0x05,                    //   Usage Maxium (Kana)
192     0x91, 0x02,                    //   Output (Data, Variable, Absolute)
193 
194     0x95, 0x01,                    //   Report Count (1)
195     0x75, 0x03,                    //   Report Size (3)
196     0x91, 0x03,                    //   Output (Constant, Variable, Absolute)
197 
198     // Keycodes
199 
200     0x95, 0x06,                    //   Report Count (6)
201     0x75, 0x08,                    //   Report Size (8)
202     0x15, 0x00,                    //   Logical Minimum (0)
203     0x25, 0xff,                    //   Logical Maximum (1)
204     0x05, 0x07,                    //   Usage Page (Key codes)
205     0x19, 0x00,                    //   Usage Minimum (Reserved (no event indicated))
206     0x29, 0xff,                    //   Usage Maxium (Reserved)
207     0x81, 0x00,                    //   Input (Data, Array)
208 
209     0xc0,                          // En
210 
211 };
212 
213 const uint8_t mouse_report_without_id_positive_xy[]    = {       0x03, 0x02, 0x03 };
214 const uint8_t mouse_report_without_id_negative_xy[]    = {       0x03, 0xFE, 0xFD };
215 const uint8_t mouse_report_with_id_1[]    = { 0x01, 0x03, 0x02, 0x03 };
216 
217 const uint8_t keyboard_report1[] = { 0x01, 0x00, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00 };
218 
219 const uint8_t combo_report1[]    = { 0x01, 0x03, 0x02, 0x03 };
220 const uint8_t combo_report2[]    = { 0x02, 0x01, 0x00,  0x04, 0x05, 0x06, 0x00, 0x00, 0x00 };
221 
222 
223 
224 static void expect_field(btstack_hid_parser_t * parser, uint16_t expected_usage_page, uint16_t expected_usage, int32_t expected_value){
225     // printf("expected - usage page %02x, usage %04x, value %02x (bit pos %u)\n", expected_usage_page, expected_usage, expected_value, parser->report_pos_in_bit);
226     CHECK_EQUAL(1, btstack_hid_parser_has_more(parser));
227     uint16_t usage_page;
228     uint16_t usage;
229     int32_t value;
230     btstack_hid_parser_get_field(parser, &usage_page, &usage, &value);
231     CHECK_EQUAL(expected_usage_page, usage_page);
232     CHECK_EQUAL(expected_usage, usage);
233     CHECK_EQUAL(expected_value, value);
234 }
235 
236 // test
237 TEST_GROUP(HID){
238 	void setup(void){
239     }
240 };
241 
242 TEST(HID, MouseWithoutReportID){
243     static btstack_hid_parser_t hid_parser;
244     btstack_hid_parser_init(&hid_parser, mouse_descriptor_without_report_id, sizeof(mouse_descriptor_without_report_id), HID_REPORT_TYPE_INPUT, mouse_report_without_id_positive_xy, sizeof(mouse_report_without_id_positive_xy));
245     expect_field(&hid_parser, 9, 1, 1);
246     expect_field(&hid_parser, 9, 2, 1);
247     expect_field(&hid_parser, 9, 3, 0);
248     expect_field(&hid_parser, 1, 0x30, 2);
249     expect_field(&hid_parser, 1, 0x31, 3);
250     CHECK_EQUAL(24, hid_parser.report_pos_in_bit);
251     CHECK_EQUAL(0, btstack_hid_parser_has_more(&hid_parser));
252 }
253 
254 TEST(HID, MouseWithoutReportIDSigned){
255     static btstack_hid_parser_t hid_parser;
256     btstack_hid_parser_init(&hid_parser, mouse_descriptor_without_report_id, sizeof(mouse_descriptor_without_report_id), HID_REPORT_TYPE_INPUT, mouse_report_without_id_negative_xy, sizeof(mouse_report_without_id_negative_xy));
257     expect_field(&hid_parser, 9, 1, 1);
258     expect_field(&hid_parser, 9, 2, 1);
259     expect_field(&hid_parser, 9, 3, 0);
260     expect_field(&hid_parser, 1, 0x30, -2);
261     expect_field(&hid_parser, 1, 0x31, -3);
262     CHECK_EQUAL(24, hid_parser.report_pos_in_bit);
263     CHECK_EQUAL(0, btstack_hid_parser_has_more(&hid_parser));
264 }
265 
266 TEST(HID, MouseWithReportID){
267     static btstack_hid_parser_t hid_parser;
268     btstack_hid_parser_init(&hid_parser, mouse_descriptor_with_report_id, sizeof(mouse_descriptor_with_report_id), HID_REPORT_TYPE_INPUT, mouse_report_with_id_1, sizeof(mouse_report_with_id_1));
269     expect_field(&hid_parser, 9, 1, 1);
270     expect_field(&hid_parser, 9, 2, 1);
271     expect_field(&hid_parser, 9, 3, 0);
272     expect_field(&hid_parser, 1, 0x30, 2);
273     expect_field(&hid_parser, 1, 0x31, 3);
274     CHECK_EQUAL(32, hid_parser.report_pos_in_bit);
275     CHECK_EQUAL(0, btstack_hid_parser_has_more(&hid_parser));
276 }
277 
278 TEST(HID, BootKeyboard){
279     static btstack_hid_parser_t hid_parser;
280     btstack_hid_parser_init(&hid_parser, hid_descriptor_keyboard_boot_mode, sizeof(hid_descriptor_keyboard_boot_mode), HID_REPORT_TYPE_INPUT, keyboard_report1, sizeof(keyboard_report1));
281     expect_field(&hid_parser, 7, 0xe0, 1);
282     expect_field(&hid_parser, 7, 0xe1, 0);
283     expect_field(&hid_parser, 7, 0xe2, 0);
284     expect_field(&hid_parser, 7, 0xe3, 0);
285     expect_field(&hid_parser, 7, 0xe4, 0);
286     expect_field(&hid_parser, 7, 0xe5, 0);
287     expect_field(&hid_parser, 7, 0xe6, 0);
288     expect_field(&hid_parser, 7, 0xe7, 0);
289     expect_field(&hid_parser, 7, 0x04, 1);
290     expect_field(&hid_parser, 7, 0x05, 1);
291     expect_field(&hid_parser, 7, 0x06, 1);
292     expect_field(&hid_parser, 7, 0x00, 1);
293     expect_field(&hid_parser, 7, 0x00, 1);
294     expect_field(&hid_parser, 7, 0x00, 1);
295     CHECK_EQUAL(64, hid_parser.report_pos_in_bit);
296     CHECK_EQUAL(0, btstack_hid_parser_has_more(&hid_parser));
297 }
298 
299 TEST(HID, Combo1){
300     static btstack_hid_parser_t hid_parser;
301     btstack_hid_parser_init(&hid_parser, combo_descriptor_with_report_ids, sizeof(combo_descriptor_with_report_ids), HID_REPORT_TYPE_INPUT, combo_report1, sizeof(combo_report1));
302     expect_field(&hid_parser, 9, 1, 1);
303     expect_field(&hid_parser, 9, 2, 1);
304     expect_field(&hid_parser, 9, 3, 0);
305     expect_field(&hid_parser, 1, 0x30, 2);
306     expect_field(&hid_parser, 1, 0x31, 3);
307     CHECK_EQUAL(32, hid_parser.report_pos_in_bit);
308     CHECK_EQUAL(0, btstack_hid_parser_has_more(&hid_parser));
309 }
310 
311 TEST(HID, Combo2){
312     static btstack_hid_parser_t hid_parser;
313     btstack_hid_parser_init(&hid_parser, combo_descriptor_with_report_ids, sizeof(combo_descriptor_with_report_ids), HID_REPORT_TYPE_INPUT, combo_report2, sizeof(combo_report2));
314     expect_field(&hid_parser, 7, 0xe0, 1);
315     expect_field(&hid_parser, 7, 0xe1, 0);
316     expect_field(&hid_parser, 7, 0xe2, 0);
317     expect_field(&hid_parser, 7, 0xe3, 0);
318     expect_field(&hid_parser, 7, 0xe4, 0);
319     expect_field(&hid_parser, 7, 0xe5, 0);
320     expect_field(&hid_parser, 7, 0xe6, 0);
321     expect_field(&hid_parser, 7, 0xe7, 0);
322     expect_field(&hid_parser, 7, 0x04, 1);
323     expect_field(&hid_parser, 7, 0x05, 1);
324     expect_field(&hid_parser, 7, 0x06, 1);
325     expect_field(&hid_parser, 7, 0x00, 1);
326     expect_field(&hid_parser, 7, 0x00, 1);
327     expect_field(&hid_parser, 7, 0x00, 1);
328     CHECK_EQUAL(72, hid_parser.report_pos_in_bit);
329     CHECK_EQUAL(0, btstack_hid_parser_has_more(&hid_parser));
330 }
331 
332 TEST(HID, GetReportSize){
333     int report_size = 0;
334     const uint8_t * hid_descriptor =  combo_descriptor_with_report_ids;
335     uint16_t hid_descriptor_len = sizeof(combo_descriptor_with_report_ids);
336     report_size = btstack_hid_get_report_size_for_id(1, HID_REPORT_TYPE_INPUT, hid_descriptor_len, hid_descriptor);
337     CHECK_EQUAL(3, report_size);
338 
339     hid_descriptor = hid_descriptor_keyboard_boot_mode;
340     hid_descriptor_len = sizeof(hid_descriptor_keyboard_boot_mode);
341     report_size = btstack_hid_get_report_size_for_id(0, HID_REPORT_TYPE_OUTPUT, hid_descriptor_len, hid_descriptor);
342     CHECK_EQUAL(1, report_size);
343     report_size = btstack_hid_get_report_size_for_id(0, HID_REPORT_TYPE_INPUT, hid_descriptor_len, hid_descriptor);
344     CHECK_EQUAL(8, report_size);
345 }
346 
347 
348 int main (int argc, const char * argv[]){
349     // log into file using HCI_DUMP_PACKETLOGGER format
350     const char * pklg_path = "hci_dump.pklg";
351     hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
352     hci_dump_init(hci_dump_posix_fs_get_instance());
353     printf("Packet Log: %s\n", pklg_path);
354 
355     return CommandLineTestRunner::RunAllTests(argc, argv);
356 }
357