at master 20 kB view raw
1/* 2Copyright 2011 Jun Wako <wakojun@gmail.com> 3 4This program is free software: you can redistribute it and/or modify 5it under the terms of the GNU General Public License as published by 6the Free Software Foundation, either version 2 of the License, or 7(at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12GNU General Public License for more details. 13 14You should have received a copy of the GNU General Public License 15along 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 53static bool command_common(uint8_t code); 54static void command_common_help(void); 55static void print_version(void); 56static void print_status(void); 57static bool command_console(uint8_t code); 58static void command_console_help(void); 59#if defined(MOUSEKEY_ENABLE) 60static bool mousekey_console(uint8_t code); 61#endif 62 63static void switch_default_layer(uint8_t layer); 64 65command_state_t command_state = ONESHOT; 66 67bool 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. */ 93bool command_extra(uint8_t code) __attribute__((weak)); 94bool command_extra(uint8_t code) { 95 (void)code; 96 return false; 97} 98 99bool command_console_extra(uint8_t code) __attribute__((weak)); 100bool command_console_extra(uint8_t code) { 101 (void)code; 102 return false; 103} 104 105/*********************************************************** 106 * Command common 107 ***********************************************************/ 108 109static 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 166static 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 224static 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) 248static 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 320static 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 ***********************************************************/ 538static 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 547static 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) 577static 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) 603static 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. */ 629bool 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 743static 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}