command.c (19683B)
1 /* 2 Copyright 2011 Jun Wako <wakojun@gmail.com> 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 #include <stdint.h> 18 #include <stdbool.h> 19 #include "wait.h" 20 #include "keycode.h" 21 #include "host.h" 22 #include "print.h" 23 #include "debug.h" 24 #include "util.h" 25 #include "timer.h" 26 #include "keyboard.h" 27 #include "bootloader.h" 28 #include "action_layer.h" 29 #include "action_util.h" 30 #include "eeconfig.h" 31 #include "led.h" 32 #include "command.h" 33 #include "quantum.h" 34 #include "usb_device_state.h" 35 #include "version.h" 36 37 #ifdef BACKLIGHT_ENABLE 38 # include "backlight.h" 39 #endif 40 41 #ifdef SLEEP_LED_ENABLE 42 # include "sleep_led.h" 43 #endif 44 45 #if defined(MOUSEKEY_ENABLE) 46 # include "mousekey.h" 47 #endif 48 49 #ifdef AUDIO_ENABLE 50 # include "audio.h" 51 #endif /* AUDIO_ENABLE */ 52 53 static bool command_common(uint8_t code); 54 static void command_common_help(void); 55 static void print_version(void); 56 static void print_status(void); 57 static bool command_console(uint8_t code); 58 static void command_console_help(void); 59 #if defined(MOUSEKEY_ENABLE) 60 static bool mousekey_console(uint8_t code); 61 #endif 62 63 static void switch_default_layer(uint8_t layer); 64 65 command_state_t command_state = ONESHOT; 66 67 bool command_proc(uint8_t code) { 68 switch (command_state) { 69 case ONESHOT: 70 if (!IS_COMMAND()) return false; 71 return (command_extra(code) || command_common(code)); 72 break; 73 case CONSOLE: 74 if (IS_COMMAND()) 75 return (command_extra(code) || command_common(code)); 76 else 77 return (command_console_extra(code) || command_console(code)); 78 break; 79 #if defined(MOUSEKEY_ENABLE) 80 case MOUSEKEY: 81 mousekey_console(code); 82 break; 83 #endif 84 default: 85 command_state = ONESHOT; 86 return false; 87 } 88 return true; 89 } 90 91 /* TODO: Refactoring is needed. */ 92 /* This allows to define extra commands. return false when not processed. */ 93 bool command_extra(uint8_t code) __attribute__((weak)); 94 bool command_extra(uint8_t code) { 95 (void)code; 96 return false; 97 } 98 99 bool command_console_extra(uint8_t code) __attribute__((weak)); 100 bool command_console_extra(uint8_t code) { 101 (void)code; 102 return false; 103 } 104 105 /*********************************************************** 106 * Command common 107 ***********************************************************/ 108 109 static void command_common_help(void) { 110 print(/* clang-format off */ 111 "\n\t- Magic -\n" 112 113 STR(MAGIC_KEY_DEBUG) ": Debug Message Toggle\n" 114 STR(MAGIC_KEY_DEBUG_MATRIX) ": Matrix Debug Mode Toggle" 115 " - Show keypresses in matrix grid\n" 116 STR(MAGIC_KEY_DEBUG_KBD) ": Keyboard Debug Toggle" 117 " - Show keypress report\n" 118 STR(MAGIC_KEY_DEBUG_MOUSE) ": Debug Mouse Toggle\n" 119 STR(MAGIC_KEY_VERSION) ": Version\n" 120 STR(MAGIC_KEY_STATUS) ": Status\n" 121 STR(MAGIC_KEY_CONSOLE) ": Activate Console Mode\n" 122 123 #if MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM 124 STR(MAGIC_KEY_LAYER0) ": Switch to Layer 0\n" 125 STR(MAGIC_KEY_LAYER1) ": Switch to Layer 1\n" 126 STR(MAGIC_KEY_LAYER2) ": Switch to Layer 2\n" 127 STR(MAGIC_KEY_LAYER3) ": Switch to Layer 3\n" 128 STR(MAGIC_KEY_LAYER4) ": Switch to Layer 4\n" 129 STR(MAGIC_KEY_LAYER5) ": Switch to Layer 5\n" 130 STR(MAGIC_KEY_LAYER6) ": Switch to Layer 6\n" 131 STR(MAGIC_KEY_LAYER7) ": Switch to Layer 7\n" 132 STR(MAGIC_KEY_LAYER8) ": Switch to Layer 8\n" 133 STR(MAGIC_KEY_LAYER9) ": Switch to Layer 9\n" 134 #endif 135 136 #if MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS 137 "F1-F10: Switch to Layer 0-9 (F10 = L0)\n" 138 #endif 139 140 #if MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS 141 "0-9: Switch to Layer 0-9\n" 142 #endif 143 144 STR(MAGIC_KEY_LAYER0_ALT) ": Switch to Layer 0 (alternate)\n" 145 146 STR(MAGIC_KEY_BOOTLOADER) ": Jump to Bootloader\n" 147 STR(MAGIC_KEY_BOOTLOADER_ALT) ": Jump to Bootloader (alternate)\n" 148 149 #ifdef KEYBOARD_LOCK_ENABLE 150 STR(MAGIC_KEY_LOCK) ": Lock Keyboard\n" 151 #endif 152 153 STR(MAGIC_KEY_EEPROM) ": Print EEPROM Settings\n" 154 STR(MAGIC_KEY_EEPROM_CLEAR) ": Clear EEPROM\n" 155 156 #ifdef NKRO_ENABLE 157 STR(MAGIC_KEY_NKRO) ": NKRO Toggle\n" 158 #endif 159 160 #ifdef SLEEP_LED_ENABLE 161 STR(MAGIC_KEY_SLEEP_LED) ": Sleep LED Test\n" 162 #endif 163 ); /* clang-format on */ 164 } 165 166 static void print_version(void) { 167 xprintf("%s", /* clang-format off */ 168 "\n\t- Version -\n" 169 "VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") " 170 "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") " 171 "VER: " STR(DEVICE_VER) "\n" 172 "BUILD: (" __DATE__ ")\n" 173 #ifndef SKIP_VERSION 174 # ifdef PROTOCOL_CHIBIOS 175 "CHIBIOS: " STR(CHIBIOS_VERSION) 176 ", CONTRIB: " STR(CHIBIOS_CONTRIB_VERSION) "\n" 177 # endif 178 #endif 179 180 /* build options */ 181 "OPTIONS:" 182 183 #ifdef PROTOCOL_LUFA 184 " LUFA" 185 #endif 186 #ifdef PROTOCOL_VUSB 187 " VUSB" 188 #endif 189 #ifdef BOOTMAGIC_ENABLE 190 " BOOTMAGIC" 191 #endif 192 #ifdef MOUSEKEY_ENABLE 193 " MOUSEKEY" 194 #endif 195 #ifdef EXTRAKEY_ENABLE 196 " EXTRAKEY" 197 #endif 198 #ifdef CONSOLE_ENABLE 199 " CONSOLE" 200 #endif 201 #ifdef COMMAND_ENABLE 202 " COMMAND" 203 #endif 204 #ifdef NKRO_ENABLE 205 " NKRO" 206 #endif 207 #ifdef LTO_ENABLE 208 " LTO" 209 #endif 210 211 " " STR(BOOTLOADER_SIZE) "\n" 212 213 "GCC: " STR(__GNUC__) 214 "." STR(__GNUC_MINOR__) 215 "." STR(__GNUC_PATCHLEVEL__) 216 #if defined(__AVR__) 217 " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__ 218 " AVR_ARCH: avr" STR(__AVR_ARCH__) 219 #endif 220 "\n" 221 ); /* clang-format on */ 222 } 223 224 static void print_status(void) { 225 xprintf(/* clang-format off */ 226 "\n\t- Status -\n" 227 228 "host_keyboard_leds(): %02X\n" 229 "keyboard_protocol: %02X\n" 230 "keyboard_idle: %02X\n" 231 #ifdef NKRO_ENABLE 232 "keymap_config.nkro: %02X\n" 233 #endif 234 "timer_read32(): %08lX\n" 235 236 , host_keyboard_leds() 237 , usb_device_state_get_protocol() 238 , usb_device_state_get_idle_rate() 239 #ifdef NKRO_ENABLE 240 , keymap_config.nkro 241 #endif 242 , timer_read32() 243 244 ); /* clang-format on */ 245 } 246 247 #if !defined(NO_PRINT) && !defined(USER_PRINT) 248 static void print_eeconfig(void) { 249 xprintf("eeconfig:\ndefault_layer: %" PRIu32 "\n", (uint32_t)eeconfig_read_default_layer()); 250 251 debug_config_t dc; 252 eeconfig_read_debug(&dc); 253 xprintf(/* clang-format off */ 254 255 "debug_config.raw: %02X\n" 256 ".enable: %u\n" 257 ".matrix: %u\n" 258 ".keyboard: %u\n" 259 ".mouse: %u\n" 260 261 , dc.raw 262 , dc.enable 263 , dc.matrix 264 , dc.keyboard 265 , dc.mouse 266 ); /* clang-format on */ 267 268 keymap_config_t kc; 269 eeconfig_read_keymap(&kc); 270 xprintf(/* clang-format off */ 271 272 "keymap_config.raw: %02X\n" 273 ".swap_control_capslock: %u\n" 274 ".capslock_to_control: %u\n" 275 ".swap_lctl_lgui: %u\n" 276 ".swap_rctl_rgui: %u\n" 277 ".swap_lalt_lgui: %u\n" 278 ".swap_ralt_rgui: %u\n" 279 ".no_gui: %u\n" 280 ".swap_grave_esc: %u\n" 281 ".swap_backslash_backspace: %u\n" 282 ".nkro: %u\n" 283 ".swap_escape_capslock: %u\n" 284 285 , kc.raw 286 , kc.swap_control_capslock 287 , kc.capslock_to_control 288 , kc.swap_lctl_lgui 289 , kc.swap_rctl_rgui 290 , kc.swap_lalt_lgui 291 , kc.swap_ralt_rgui 292 , kc.no_gui 293 , kc.swap_grave_esc 294 , kc.swap_backslash_backspace 295 , kc.nkro 296 , kc.swap_escape_capslock 297 ); /* clang-format on */ 298 299 # ifdef BACKLIGHT_ENABLE 300 301 backlight_config_t bc; 302 eeconfig_read_backlight(&bc); 303 xprintf(/* clang-format off */ 304 "backlight_config" 305 306 ".raw: %02X\n" 307 ".enable: %u\n" 308 ".level: %u\n" 309 310 , bc.raw 311 , bc.enable 312 , bc.level 313 314 ); /* clang-format on */ 315 316 # endif /* BACKLIGHT_ENABLE */ 317 } 318 #endif /* !NO_PRINT && !USER_PRINT */ 319 320 static bool command_common(uint8_t code) { 321 #ifdef KEYBOARD_LOCK_ENABLE 322 static host_driver_t *host_driver = 0; 323 #endif 324 325 switch (code) { 326 #ifdef SLEEP_LED_ENABLE 327 328 // test breathing sleep LED 329 case MAGIC_KC(MAGIC_KEY_SLEEP_LED): 330 print("Sleep LED Test\n"); 331 sleep_led_toggle(); 332 led_set(host_keyboard_leds()); 333 break; 334 #endif 335 336 // print stored eeprom config 337 case MAGIC_KC(MAGIC_KEY_EEPROM): 338 #if !defined(NO_PRINT) && !defined(USER_PRINT) 339 print_eeconfig(); 340 #endif /* !NO_PRINT && !USER_PRINT */ 341 break; 342 343 // clear eeprom 344 case MAGIC_KC(MAGIC_KEY_EEPROM_CLEAR): 345 print("Clearing EEPROM\n"); 346 eeconfig_init(); 347 break; 348 349 #ifdef KEYBOARD_LOCK_ENABLE 350 351 // lock/unlock keyboard 352 case MAGIC_KC(MAGIC_KEY_LOCK): 353 if (host_get_driver()) { 354 host_driver = host_get_driver(); 355 clear_keyboard(); 356 host_set_driver(0); 357 print("Locked.\n"); 358 } else { 359 host_set_driver(host_driver); 360 print("Unlocked.\n"); 361 } 362 break; 363 #endif 364 365 // print help 366 case MAGIC_KC(MAGIC_KEY_HELP): 367 case MAGIC_KC(MAGIC_KEY_HELP_ALT): 368 command_common_help(); 369 break; 370 371 // activate console 372 case MAGIC_KC(MAGIC_KEY_CONSOLE): 373 debug_matrix = false; 374 debug_keyboard = false; 375 debug_mouse = false; 376 debug_enable = false; 377 command_console_help(); 378 print("C> "); 379 command_state = CONSOLE; 380 break; 381 382 // jump to bootloader 383 case MAGIC_KC(MAGIC_KEY_BOOTLOADER): 384 case MAGIC_KC(MAGIC_KEY_BOOTLOADER_ALT): 385 print("\n\nJumping to bootloader... "); 386 reset_keyboard(); 387 break; 388 389 // debug toggle 390 case MAGIC_KC(MAGIC_KEY_DEBUG): 391 debug_enable = !debug_enable; 392 if (debug_enable) { 393 print("\ndebug: on\n"); 394 } else { 395 print("\ndebug: off\n"); 396 debug_matrix = false; 397 debug_keyboard = false; 398 debug_mouse = false; 399 } 400 break; 401 402 // debug matrix toggle 403 case MAGIC_KC(MAGIC_KEY_DEBUG_MATRIX): 404 debug_matrix = !debug_matrix; 405 if (debug_matrix) { 406 print("\nmatrix: on\n"); 407 debug_enable = true; 408 } else { 409 print("\nmatrix: off\n"); 410 } 411 break; 412 413 // debug keyboard toggle 414 case MAGIC_KC(MAGIC_KEY_DEBUG_KBD): 415 debug_keyboard = !debug_keyboard; 416 if (debug_keyboard) { 417 print("\nkeyboard: on\n"); 418 debug_enable = true; 419 } else { 420 print("\nkeyboard: off\n"); 421 } 422 break; 423 424 // debug mouse toggle 425 case MAGIC_KC(MAGIC_KEY_DEBUG_MOUSE): 426 debug_mouse = !debug_mouse; 427 if (debug_mouse) { 428 print("\nmouse: on\n"); 429 debug_enable = true; 430 } else { 431 print("\nmouse: off\n"); 432 } 433 break; 434 435 // print version 436 case MAGIC_KC(MAGIC_KEY_VERSION): 437 print_version(); 438 break; 439 440 // print status 441 case MAGIC_KC(MAGIC_KEY_STATUS): 442 print_status(); 443 break; 444 445 #ifdef NKRO_ENABLE 446 447 // NKRO toggle 448 case MAGIC_KC(MAGIC_KEY_NKRO): 449 clear_keyboard(); // clear to prevent stuck keys 450 keymap_config.nkro = !keymap_config.nkro; 451 if (keymap_config.nkro) { 452 print("NKRO: on\n"); 453 } else { 454 print("NKRO: off\n"); 455 } 456 break; 457 #endif 458 459 // switch layers 460 461 case MAGIC_KC(MAGIC_KEY_LAYER0_ALT): 462 switch_default_layer(0); 463 break; 464 465 #if MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM 466 467 case MAGIC_KC(MAGIC_KEY_LAYER0): 468 switch_default_layer(0); 469 break; 470 471 case MAGIC_KC(MAGIC_KEY_LAYER1): 472 switch_default_layer(1); 473 break; 474 475 case MAGIC_KC(MAGIC_KEY_LAYER2): 476 switch_default_layer(2); 477 break; 478 479 case MAGIC_KC(MAGIC_KEY_LAYER3): 480 switch_default_layer(3); 481 break; 482 483 case MAGIC_KC(MAGIC_KEY_LAYER4): 484 switch_default_layer(4); 485 break; 486 487 case MAGIC_KC(MAGIC_KEY_LAYER5): 488 switch_default_layer(5); 489 break; 490 491 case MAGIC_KC(MAGIC_KEY_LAYER6): 492 switch_default_layer(6); 493 break; 494 495 case MAGIC_KC(MAGIC_KEY_LAYER7): 496 switch_default_layer(7); 497 break; 498 499 case MAGIC_KC(MAGIC_KEY_LAYER8): 500 switch_default_layer(8); 501 break; 502 503 case MAGIC_KC(MAGIC_KEY_LAYER9): 504 switch_default_layer(9); 505 break; 506 #endif 507 508 #if MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS 509 510 case KC_F1 ... KC_F9: 511 switch_default_layer((code - KC_F1) + 1); 512 break; 513 case KC_F10: 514 switch_default_layer(0); 515 break; 516 #endif 517 518 #if MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS 519 520 case KC_1 ... KC_9: 521 switch_default_layer((code - KC_1) + 1); 522 break; 523 case KC_0: 524 switch_default_layer(0); 525 break; 526 #endif 527 528 default: 529 print("?"); 530 return false; 531 } 532 return true; 533 } 534 535 /*********************************************************** 536 * Command console 537 ***********************************************************/ 538 static void command_console_help(void) { 539 print("\n\t- Console -\n" 540 "ESC/q: quit\n" 541 #ifdef MOUSEKEY_ENABLE 542 "m: mousekey\n" 543 #endif 544 ); 545 } 546 547 static bool command_console(uint8_t code) { 548 switch (code) { 549 case KC_H: 550 case KC_SLASH: /* ? */ 551 command_console_help(); 552 print("C> "); 553 return true; 554 case KC_Q: 555 case KC_ESC: 556 command_state = ONESHOT; 557 return false; 558 #if defined(MOUSEKEY_ENABLE) 559 case KC_M: 560 command_state = MOUSEKEY; 561 mousekey_console(KC_SLASH /* ? */); 562 return true; 563 #endif 564 default: 565 print("?"); 566 return false; 567 } 568 } 569 570 /*********************************************************** 571 * Mousekey console 572 ***********************************************************/ 573 574 #if defined(MOUSEKEY_ENABLE) 575 576 # if !defined(NO_PRINT) && !defined(USER_PRINT) 577 static void mousekey_param_print(void) { 578 xprintf(/* clang-format off */ 579 580 #ifndef MK_3_SPEED 581 "1: delay(*10ms): %u\n" 582 "2: interval(ms): %u\n" 583 "3: max_speed: %u\n" 584 "4: time_to_max: %u\n" 585 "5: wheel_max_speed: %u\n" 586 "6: wheel_time_to_max: %u\n" 587 588 , mk_delay 589 , mk_interval 590 , mk_max_speed 591 , mk_time_to_max 592 , mk_wheel_max_speed 593 , mk_wheel_time_to_max 594 #else 595 "no knobs sorry\n" 596 #endif 597 598 ); /* clang-format on */ 599 } 600 # endif /* !NO_PRINT && !USER_PRINT */ 601 602 # if !defined(NO_PRINT) && !defined(USER_PRINT) 603 static void mousekey_console_help(void) { 604 mousekey_param_print(); 605 xprintf(/* clang-format off */ 606 "p: print values\n" 607 "d: set defaults\n" 608 "up: +1\n" 609 "dn: -1\n" 610 "lt: +10\n" 611 "rt: -10\n" 612 "ESC/q: quit\n" 613 614 #ifndef MK_3_SPEED 615 "\n" 616 "speed = delta * max_speed * (repeat / time_to_max)\n" 617 "where delta: cursor=%d, wheel=%d\n" 618 "See http://en.wikipedia.org/wiki/Mouse_keys\n" 619 , MOUSEKEY_MOVE_DELTA, MOUSEKEY_WHEEL_DELTA 620 #endif 621 622 ); /* clang-format on */ 623 } 624 # endif /* !NO_PRINT && !USER_PRINT */ 625 626 /* Only used by `quantum/command.c` / `command_proc()`. To avoid 627 * any doubt: we return `false` to return to the main console, 628 * which differs from the `bool` that `command_proc()` returns. */ 629 bool mousekey_console(uint8_t code) { 630 static uint8_t param = 0; 631 static uint8_t *pp = NULL; 632 static char *desc = NULL; 633 634 # if defined(NO_PRINT) || defined(USER_PRINT) /* -Wunused-parameter */ 635 (void)desc; 636 # endif 637 638 int8_t change = 0; 639 640 switch (code) { 641 case KC_H: 642 case KC_SLASH: /* ? */ 643 # if !defined(NO_PRINT) && !defined(USER_PRINT) 644 print("\n\t- Mousekey -\n"); 645 mousekey_console_help(); 646 # endif 647 break; 648 649 case KC_Q: 650 case KC_ESC: 651 print("q\n"); 652 if (!param) return false; 653 param = 0; 654 pp = NULL; 655 desc = NULL; 656 break; 657 658 case KC_P: 659 # if !defined(NO_PRINT) && !defined(USER_PRINT) 660 print("\n\t- Values -\n"); 661 mousekey_param_print(); 662 # endif 663 break; 664 665 case KC_1 ... KC_0: /* KC_0 gives param = 10 */ 666 param = 1 + code - KC_1; 667 switch (param) { /* clang-format off */ 668 # define PARAM(n, v) case n: pp = &(v); desc = #v; break 669 670 #ifndef MK_3_SPEED 671 PARAM(1, mk_delay); 672 PARAM(2, mk_interval); 673 PARAM(3, mk_max_speed); 674 PARAM(4, mk_time_to_max); 675 PARAM(5, mk_wheel_max_speed); 676 PARAM(6, mk_wheel_time_to_max); 677 #endif /* MK_3_SPEED */ 678 679 # undef PARAM 680 default: 681 param = 0; 682 print("?\n"); 683 break; 684 } /* clang-format on */ 685 if (param) xprintf("%u\n", param); 686 break; 687 688 /* clang-format off */ 689 case KC_UP: change = +1; break; 690 case KC_DOWN: change = -1; break; 691 case KC_LEFT: change = -10; break; 692 case KC_RIGHT: change = +10; break; 693 /* clang-format on */ 694 695 case KC_D: 696 697 # ifndef MK_3_SPEED 698 mk_delay = MOUSEKEY_DELAY / 10; 699 mk_interval = MOUSEKEY_INTERVAL; 700 mk_max_speed = MOUSEKEY_MAX_SPEED; 701 mk_time_to_max = MOUSEKEY_TIME_TO_MAX; 702 mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; 703 mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; 704 # endif /* MK_3_SPEED */ 705 706 print("defaults\n"); 707 break; 708 709 default: 710 print("?\n"); 711 break; 712 } 713 714 if (change) { 715 if (pp) { 716 int16_t val = *pp + change; 717 if (val > (int16_t)UINT8_MAX) 718 *pp = UINT8_MAX; 719 else if (val < 0) 720 *pp = 0; 721 else 722 *pp = (uint8_t)val; 723 xprintf("= %u\n", *pp); 724 } else { 725 print("?\n"); 726 } 727 } 728 729 if (param) { 730 xprintf("M%u:%s> ", param, desc ? desc : "???"); 731 } else { 732 print("M> "); 733 } 734 return true; 735 } 736 737 #endif /* MOUSEKEY_ENABLE */ 738 739 /*********************************************************** 740 * Utilities 741 ***********************************************************/ 742 743 static void switch_default_layer(uint8_t layer) { 744 xprintf("L%d\n", layer); 745 default_layer_set((layer_state_t)1 << layer); 746 clear_keyboard(); 747 }