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 24struct layerkey { 25 uint layer; 26 uint key; 27}; 28 29struct hid_keyboard_report { 30 uint8_t mods, weak_mods; 31 uint8_t codes[HID_REPORT_CODES]; 32 uint8_t cnt; 33}; 34 35struct hid_mouse_report { 36 uint8_t btns; 37 int8_t x, y; 38 int8_t v, h; 39}; 40 41struct hid_consumer_report { 42 uint16_t code; 43}; 44 45struct hid_system_report { 46 uint16_t code; 47}; 48 49struct 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 56static uint32_t keysyms[KEY_ROWS][KEY_COLS] = { 0 }; 57 58static struct layerkey active_layers[16] = { 0 }; 59static uint active_layers_top = 0; 60 61static struct hid_keyboard_report keyboard_report_prev = { 0 }; 62static struct hid_keyboard_report keyboard_report = { 0 }; 63 64static struct hid_mouse_report mouse_report_prev = { 0 }; 65static struct hid_mouse_report mouse_report = { 0 }; 66 67static struct hid_consumer_report consumer_report_prev = { 0 }; 68static struct hid_consumer_report consumer_report = { 0 }; 69 70static struct hid_system_report system_report_prev = { 0 }; 71static struct hid_system_report system_report = { 0 }; 72 73static struct hid_gamepad_report gamepad_report_prev = { 0 }; 74static struct hid_gamepad_report gamepad_report = { 0 }; 75 76static uint8_t active_weak_mods = 0; 77static uint8_t active_mods = 0; 78 79static bool seen_mat[KEY_ROWS][KEY_COLS] = { 0 }; 80 81static uint32_t macro_held_stack[MACRO_HOLD_MAX] = { 0 }; 82static uint macro_held_cnt = 0; 83 84static bool macro_running = false; 85 86/* TODO replace these two with stack method primitives (added to util) */ 87 88static void active_layers_reset(void); 89static void active_layers_pop(uint layer); 90static void active_layers_push(uint layer, uint key); 91 92static void macro_held_reset(void); 93static void macro_held_pop(uint32_t keysym); 94static void macro_held_push(uint32_t keysym); 95static bool macro_held_find(uint32_t keysym); 96 97static void add_keycode(uint8_t keycode); 98 99/* TODO: add static prototypes */ 100 101void 102active_layers_reset(void) 103{ 104 active_layers_top = 0; 105} 106 107bool 108active_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 120void 121active_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 131void 132active_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 151void 152macro_held_reset(void) 153{ 154 macro_held_cnt = 0; 155} 156 157void 158macro_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 171void 172macro_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 183bool 184macro_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 196void 197add_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 208uint8_t 209parse_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 242uint32_t 243determine_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 258void 259process_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 282void 283process_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 299void 300process_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 315void 316process_keyup(uint32_t keysym, uint x, uint y) 317{ 318} 319 320void 321process_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 337void 338update_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 351bool 352update_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 359bool 360update_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 378bool 379send_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 410bool 411send_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 432bool 433send_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 453bool 454send_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 473bool 474send_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 495bool 496send_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 512void 513send_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 523bool 524hid_ready() 525{ 526 return tud_hid_n_ready(INST_HID_KBD) 527 && tud_hid_n_ready(INST_HID_MISC); 528} 529 530void 531tud_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 542void 543tud_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 550void 551hid_init(void) 552{ 553} 554 555void 556hid_force_release(uint x, uint y) 557{ 558 process_keyrelease(keysyms[y][x], x, y); 559 keysyms[y][x] = KC_NO; 560} 561 562void 563hid_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 570void 571hid_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 641void 642hid_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