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