hid.c (13385B)
1 #include "hid.h" 2 3 #include "led.h" 4 #include "split.h" 5 #include "keymat.h" 6 #include "keysym.h" 7 #include "keymap.h" 8 9 #include "class/hid/hid.h" 10 #include "keysym/consumer.h" 11 #include "hid/keyboard.h" 12 #include "hardware/timer.h" 13 #include "bsp/board.h" 14 #include "pico/types.h" 15 16 #include <stdbool.h> 17 #include <string.h> 18 19 #define HID_REPORT_CODES 6 20 21 #define MACRO_X 0 22 #define MACRO_Y 7 23 24 struct layerkey { 25 uint layer; 26 uint key; 27 }; 28 29 struct hid_keyboard_report { 30 uint8_t mods, weak_mods; 31 uint8_t codes[HID_REPORT_CODES]; 32 uint8_t cnt; 33 }; 34 35 struct hid_mouse_report { 36 uint8_t btns; 37 int8_t x, y; 38 int8_t v, h; 39 }; 40 41 struct hid_consumer_report { 42 uint16_t code; 43 }; 44 45 struct hid_system_report { 46 uint16_t code; 47 }; 48 49 struct hid_gamepad_report { 50 int8_t x, y, z; 51 int8_t rx, ry, rz; 52 uint8_t hat; 53 uint32_t btns; 54 }; 55 56 static uint32_t keysyms[KEY_ROWS][KEY_COLS] = { 0 }; 57 58 static struct layerkey active_layers[16] = { 0 }; 59 static uint active_layers_top = 0; 60 61 static struct hid_keyboard_report keyboard_report_prev = { 0 }; 62 static struct hid_keyboard_report keyboard_report = { 0 }; 63 64 static struct hid_mouse_report mouse_report_prev = { 0 }; 65 static struct hid_mouse_report mouse_report = { 0 }; 66 67 static struct hid_consumer_report consumer_report_prev = { 0 }; 68 static struct hid_consumer_report consumer_report = { 0 }; 69 70 static struct hid_system_report system_report_prev = { 0 }; 71 static struct hid_system_report system_report = { 0 }; 72 73 static struct hid_gamepad_report gamepad_report_prev = { 0 }; 74 static struct hid_gamepad_report gamepad_report = { 0 }; 75 76 static uint8_t active_weak_mods = 0; 77 static uint8_t active_mods = 0; 78 79 static bool seen_mat[KEY_ROWS][KEY_COLS] = { 0 }; 80 81 static uint32_t macro_held_stack[MACRO_HOLD_MAX] = { 0 }; 82 static uint macro_held_cnt = 0; 83 84 static bool macro_running = false; 85 86 /* TODO replace these two with stack method primitives (added to util) */ 87 88 static void active_layers_reset(void); 89 static void active_layers_pop(uint layer); 90 static void active_layers_push(uint layer, uint key); 91 92 static void macro_held_reset(void); 93 static void macro_held_pop(uint32_t keysym); 94 static void macro_held_push(uint32_t keysym); 95 static bool macro_held_find(uint32_t keysym); 96 97 static void add_keycode(uint8_t keycode); 98 99 /* TODO: add static prototypes */ 100 101 void 102 active_layers_reset(void) 103 { 104 active_layers_top = 0; 105 } 106 107 bool 108 active_layers_find(uint layer) 109 { 110 uint i; 111 112 for (i = 0; i <= active_layers_top; i++) { 113 if (active_layers[i].layer == layer) 114 return true; 115 } 116 117 return false; 118 } 119 120 void 121 active_layers_pop(uint layer) 122 { 123 uint i; 124 125 for (i = layer + 1; i <= active_layers_top; i++) 126 active_layers[i-1] = active_layers[i]; 127 if (layer <= active_layers_top) 128 active_layers_top--; 129 } 130 131 void 132 active_layers_push(uint layer, uint key) 133 { 134 uint i; 135 136 if (active_layers_top == ARRLEN(active_layers) - 1) { 137 WARN(LOG_KEYMAP, "Active stack overflow"); 138 return; 139 } 140 141 active_layers_top += 1; 142 active_layers[active_layers_top].layer = layer; 143 active_layers[active_layers_top].key = key; 144 145 for (i = 0; i <= active_layers_top; i++) { 146 DEBUG(LOG_KEYMAP, "%i. ACTIVE %u %u", i, 147 active_layers[i].layer, active_layers[i].key); 148 } 149 } 150 151 void 152 macro_held_reset(void) 153 { 154 macro_held_cnt = 0; 155 } 156 157 void 158 macro_held_pop(uint32_t keysym) 159 { 160 uint i, cnt; 161 162 for (i = cnt = 0; i < macro_held_cnt; i++) { 163 if (macro_held_stack[i] != keysym) { 164 macro_held_stack[cnt] = macro_held_stack[i]; 165 cnt++; 166 } 167 } 168 macro_held_cnt = cnt; 169 } 170 171 void 172 macro_held_push(uint32_t keysym) 173 { 174 if (macro_held_cnt == MACRO_HOLD_MAX) { 175 WARN(LOG_KEYMAP, "Macro held keys overflow"); 176 return; 177 } 178 179 macro_held_stack[macro_held_cnt] = keysym; 180 macro_held_cnt++; 181 } 182 183 bool 184 macro_held_find(uint32_t keysym) 185 { 186 uint i; 187 188 for (i = 0; i < macro_held_cnt; i++) { 189 if (macro_held_stack[i] == keysym) 190 return true; 191 } 192 193 return false; 194 } 195 196 void 197 add_keycode(uint8_t keycode) 198 { 199 if (keyboard_report.cnt >= 6) { 200 WARN(LOG_HID, "HID report overflow"); 201 return; 202 } 203 204 keyboard_report.codes[keyboard_report.cnt] = keycode; 205 keyboard_report.cnt++; 206 } 207 208 uint8_t 209 parse_modifiers(uint32_t keysym) 210 { 211 uint8_t mods; 212 213 mods = 0; 214 215 if (IS_LEFT_CTRL(keysym)) 216 mods |= MOD_BIT(KC_LEFT_CTRL); 217 218 if (IS_RIGHT_CTRL(keysym)) 219 mods |= MOD_BIT(KC_RIGHT_CTRL); 220 221 if (IS_LEFT_SHIFT(keysym)) 222 mods |= MOD_BIT(KC_LEFT_SHIFT); 223 224 if (IS_RIGHT_SHIFT(keysym)) 225 mods |= MOD_BIT(KC_RIGHT_SHIFT); 226 227 if (IS_LEFT_GUI(keysym)) 228 mods |= MOD_BIT(KC_LEFT_GUI); 229 230 if (IS_RIGHT_GUI(keysym)) 231 mods |= MOD_BIT(KC_RIGHT_GUI); 232 233 if (IS_LEFT_ALT(keysym)) 234 mods |= MOD_BIT(KC_LEFT_ALT); 235 236 if (IS_RIGHT_ALT(keysym)) 237 mods |= MOD_BIT(KC_RIGHT_ALT); 238 239 return mods; 240 } 241 242 uint32_t 243 determine_keysym(uint x, uint y) 244 { 245 uint32_t keysym; 246 int i; 247 248 keysym = KC_NO; 249 for (i = (int) active_layers_top; i >= 0; i--) { 250 keysym = keymap_layers[active_layers[i].layer][y][x]; 251 if (keysym != KC_TRNS && keysym != KC_NO) 252 break; 253 } 254 255 return keysym; 256 } 257 258 void 259 process_keypress(uint32_t keysym, uint x, uint y) 260 { 261 if (IS_SWITCH(keysym)) { 262 active_layers_push(TO_LAYER(keysym), y * KEY_COLS + x); 263 } else if (IS_TOGGLE(keysym)) { 264 if (active_layers_find(TO_LAYER(keysym))) 265 active_layers_pop(TO_LAYER(keysym)); 266 else 267 active_layers_push(TO_LAYER(keysym), y * KEY_COLS + x); 268 } else if (IS_REBASE(keysym)) { 269 active_layers_reset(); 270 active_layers[0].layer = TO_LAYER(keysym); 271 } else if (IS_USER(keysym)) { 272 process_user_keypress(TO_USER(keysym), x, y); 273 } else if (IS_KC(keysym) && IS_KEY_KC(TO_KC(keysym))) { 274 /* FIXME: two keys pressed at the exact same time with 275 * different weak modifiers will not be reported correctly */ 276 active_weak_mods = parse_modifiers(keysym); 277 } else if (IS_CONSUMER(keysym)) { 278 consumer_report.code = keysym_to_consumer(keysym); 279 } 280 } 281 282 void 283 process_keydown(uint32_t keysym, uint x, uint y) 284 { 285 if (x != MACRO_X || y != MACRO_Y) { 286 if (seen_mat[y][x]) return; 287 seen_mat[y][x] = true; 288 } 289 290 if (IS_KC(keysym) && IS_KEY_KC(TO_KC(keysym))) { 291 add_keycode(TO_KC(keysym)); 292 } else if (IS_KC(keysym) && IS_MOD_KC(TO_KC(keysym))) { 293 active_mods |= MOD_BIT(TO_KC(keysym)); 294 } else if (IS_SWITCH(keysym) && IS_MOD(keysym)) { 295 active_mods |= parse_modifiers(keysym); 296 } 297 } 298 299 void 300 process_keyrelease(uint32_t keysym, uint x, uint y) 301 { 302 uint i; 303 304 if (IS_USER(keysym)) 305 process_user_keyrelease(TO_USER(keysym), x, y); 306 307 for (i = 1; i <= active_layers_top; i++) { 308 if (active_layers[i].key == y * KEY_COLS + x) { 309 active_layers_pop(i); 310 break; 311 } 312 } 313 } 314 315 void 316 process_keyup(uint32_t keysym, uint x, uint y) 317 { 318 } 319 320 void 321 process_key(uint x, uint y, uint64_t now_us) 322 { 323 if (keymat[y][x] && !keymat_prev[y][x]) 324 keysyms[y][x] = determine_keysym(x, y); 325 326 if (keymat[y][x]) { 327 if (!keymat_prev[y][x]) 328 process_keypress(keysyms[y][x], x, y); 329 process_keydown(keysyms[y][x], x, y); 330 } else { 331 if (keymat_prev[y][x]) 332 process_keyrelease(keysyms[y][x], x, y); 333 process_keyup(keysyms[y][x], x, y); 334 } 335 } 336 337 void 338 update_report(void) 339 { 340 uint64_t now_us; 341 uint x, y; 342 343 now_us = time_us_64(); 344 for (y = 0; y < KEY_ROWS; y++) { 345 for (x = 0; x < KEY_COLS; x++) { 346 process_key(x, y, now_us); 347 } 348 } 349 } 350 351 bool 352 update_keyboard_report(struct hid_keyboard_report *new, 353 struct hid_keyboard_report *old) 354 { 355 return new->mods != old->mods 356 || memcmp(new->codes, old->codes, HID_REPORT_CODES); 357 } 358 359 bool 360 update_weak_mods(struct hid_keyboard_report *new, 361 struct hid_keyboard_report *old) 362 { 363 int i, k; 364 365 /* only need weak modes if new keycode added */ 366 for (i = 0; i < new->cnt; i++) { 367 for (k = 0; k < old->cnt; k++) { 368 if (new->codes[i] != old->codes[k]) 369 break; 370 } 371 if (k == old->cnt) 372 return true; 373 } 374 375 return false; 376 } 377 378 bool 379 send_keyboard_report(void) 380 { 381 bool sent; 382 383 sent = false; 384 385 keyboard_report.mods = active_mods; 386 if (update_weak_mods(&keyboard_report, &keyboard_report_prev)) 387 keyboard_report.weak_mods = active_weak_mods; 388 389 if (update_keyboard_report(&keyboard_report, &keyboard_report_prev)) { 390 tud_hid_n_keyboard_report(INST_HID_KBD, REPORT_ID_NONE, 391 keyboard_report.mods | keyboard_report.weak_mods, 392 keyboard_report.codes); 393 memcpy(&keyboard_report_prev, &keyboard_report, 394 sizeof(keyboard_report)); 395 sent = true; 396 397 active_weak_mods = 0; 398 } 399 400 active_mods = 0; 401 402 memset(keyboard_report.codes, 0, HID_REPORT_CODES); 403 keyboard_report.cnt = 0; 404 405 memset(seen_mat, 0, sizeof(seen_mat)); 406 407 return sent; 408 } 409 410 bool 411 send_mouse_report(void) 412 { 413 bool sent; 414 415 sent = false; 416 if (memcmp(&mouse_report, &mouse_report_prev, 417 sizeof(mouse_report))) { 418 tud_hid_n_mouse_report(INST_HID_MISC, 419 REPORT_ID_MOUSE, mouse_report.btns, 420 mouse_report.x, mouse_report.y, 421 mouse_report.h, mouse_report.v); 422 memcpy(&mouse_report_prev, &mouse_report, 423 sizeof(mouse_report)); 424 sent = true; 425 } 426 427 memset(&mouse_report, 0, sizeof(mouse_report)); 428 429 return sent; 430 } 431 432 bool 433 send_consumer_report(void) 434 { 435 bool sent; 436 437 sent = false; 438 if (memcmp(&consumer_report, &consumer_report_prev, 439 sizeof(consumer_report))) { 440 INFO(LOG_HID, "CONSUMER SEND"); 441 tud_hid_n_report(INST_HID_MISC, REPORT_ID_CONSUMER, 442 &consumer_report.code, 2); 443 memcpy(&consumer_report_prev, &consumer_report, 444 sizeof(consumer_report)); 445 return true; 446 } 447 448 memset(&consumer_report, 0, sizeof(consumer_report)); 449 450 return sent; 451 } 452 453 bool 454 send_system_report(void) 455 { 456 bool sent; 457 458 sent = false; 459 if (memcmp(&system_report, &system_report_prev, 460 sizeof(system_report))) { 461 tud_hid_n_report(INST_HID_MISC, REPORT_ID_SYSTEM, 462 &system_report.code, 2); 463 memcpy(&system_report_prev, &system_report, 464 sizeof(system_report)); 465 sent = true; 466 } 467 468 memset(&system_report, 0, sizeof(system_report)); 469 470 return sent; 471 } 472 473 bool 474 send_gamepad_report(void) 475 { 476 bool sent; 477 478 sent = false; 479 if (memcmp(&gamepad_report, &gamepad_report_prev, 480 sizeof(gamepad_report))) { 481 tud_hid_n_gamepad_report(INST_HID_MISC, REPORT_ID_GAMEPAD, 482 gamepad_report.x, gamepad_report.y, gamepad_report.z, 483 gamepad_report.rz, gamepad_report.rx, gamepad_report.ry, 484 gamepad_report.hat, gamepad_report.btns); 485 memcpy(&gamepad_report_prev, &gamepad_report, 486 sizeof(gamepad_report)); 487 sent = true; 488 } 489 490 memset(&gamepad_report, 0, sizeof(gamepad_report)); 491 492 return sent; 493 } 494 495 bool 496 send_hid_report(int id) 497 { 498 switch (id) { 499 case REPORT_ID_MOUSE: 500 return send_mouse_report(); 501 case REPORT_ID_CONSUMER: 502 return send_consumer_report(); 503 case REPORT_ID_SYSTEM: 504 return send_system_report(); 505 case REPORT_ID_GAMEPAD: 506 return send_gamepad_report(); 507 } 508 509 return false; 510 } 511 512 void 513 send_next_hid_report(uint8_t min) 514 { 515 uint8_t id; 516 517 for (id = min; id < REPORT_ID_MAX; id++) { 518 if (send_hid_report(id)) 519 break; 520 } 521 } 522 523 bool 524 hid_ready() 525 { 526 return tud_hid_n_ready(INST_HID_KBD) 527 && tud_hid_n_ready(INST_HID_MISC); 528 } 529 530 void 531 tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) 532 { 533 if (protocol == HID_PROTOCOL_BOOT) { 534 led_rgb = SOFT_YELLOW; 535 } else { 536 led_rgb = SOFT_PURPLE; 537 } 538 led_mode = LED_ON; 539 led_reset = true; 540 } 541 542 void 543 tud_hid_report_complete_cb(uint8_t instance, 544 uint8_t const *report, uint8_t len) 545 { 546 if (report[0] >= REPORT_ID_MIN) 547 send_next_hid_report(report[0] + 1); 548 } 549 550 void 551 hid_init(void) 552 { 553 } 554 555 void 556 hid_force_release(uint x, uint y) 557 { 558 process_keyrelease(keysyms[y][x], x, y); 559 keysyms[y][x] = KC_NO; 560 } 561 562 void 563 hid_switch_layer_with_key(uint8_t layer, uint x, uint y) 564 { 565 active_layers_push(layer, y * KEY_COLS + x); 566 keysyms[y][x] = SW(layer); 567 seen_mat[y][x] = true; 568 } 569 570 void 571 hid_send_macro(const uint32_t *keysyms, uint cnt) 572 { 573 static const uint mx = MACRO_X, my = MACRO_Y; 574 struct hid_keyboard_report tmp; 575 uint32_t start_ms; 576 uint i, k; 577 578 /* NOTE: layer switching is not supported for macros (not needed), 579 * to preserve the current layers we reference a key which is not 580 * in-use to prevent accidentally unmapping layers on release */ 581 582 macro_held_reset(); 583 584 active_mods = 0; 585 active_weak_mods = 0; 586 macro_running = true; 587 memset(&keyboard_report, 0, sizeof(keyboard_report)); 588 memset(&keyboard_report_prev, 0, sizeof(keyboard_report)); 589 memset(&seen_mat, 0, sizeof(seen_mat)); 590 while (!hid_ready()) tud_task(); 591 592 for (i = 0; i < cnt; i++) { 593 if (IS_MACRO_DELAY(keysyms[i])) { 594 start_ms = board_millis(); 595 while (board_millis() - start_ms < TO_DELAY(keysyms[i])) 596 tud_task(); 597 continue; 598 } 599 600 memset(&keyboard_report, 0, sizeof(keyboard_report)); 601 602 if (IS_MACRO_RELEASE(keysyms[i])) 603 macro_held_pop(TO_SYM(keysyms[i])); 604 605 for (k = 0; k < i; k++) { 606 if (!IS_MACRO_HOLD(keysyms[k])) 607 continue; 608 if (macro_held_find(TO_SYM(keysyms[k]))) 609 process_keydown(TO_SYM(keysyms[k]), mx, my); 610 } 611 612 if (IS_MACRO_PRESS(keysyms[i])) { 613 keyboard_report.mods = active_weak_mods | active_mods; 614 memcpy(&tmp, &keyboard_report, sizeof(keyboard_report)); 615 process_keypress(TO_SYM(keysyms[i]), mx, my); 616 process_keydown(TO_SYM(keysyms[i]), mx, my); 617 } else if (IS_MACRO_HOLD(keysyms[i])) { 618 macro_held_push(TO_SYM(keysyms[i])); 619 } else if (IS_MACRO_RELEASE(keysyms[i])) { 620 process_keyrelease(TO_SYM(keysyms[i]), mx, my); 621 process_keyup(TO_SYM(keysyms[i]), mx, my); 622 } 623 624 send_keyboard_report(); 625 while (!hid_ready()) tud_task(); 626 627 if (IS_MACRO_PRESS(keysyms[i])) { 628 memcpy(&keyboard_report, &tmp, sizeof(keyboard_report)); 629 send_keyboard_report(); 630 while (!hid_ready()) tud_task(); 631 } 632 } 633 634 memset(&keyboard_report, 0, sizeof(keyboard_report)); 635 send_keyboard_report(); 636 while (!hid_ready()) tud_task(); 637 638 macro_running = false; 639 } 640 641 void 642 hid_task(void) 643 { 644 update_report(); 645 if (tud_hid_n_ready(INST_HID_KBD)) 646 send_keyboard_report(); 647 if (tud_hid_n_ready(INST_HID_MISC)) 648 send_next_hid_report(REPORT_ID_MIN); 649 } 650