]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/common/command.c
xt_usb: Fix XT soft reset
[max/tmk_keyboard.git] / tmk_core / common / command.c
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 "keymap.h"
23 #include "print.h"
24 #include "debug.h"
25 #include "util.h"
26 #include "timer.h"
27 #include "keyboard.h"
28 #include "bootloader.h"
29 #include "action_layer.h"
30 #include "action_util.h"
31 #include "eeconfig.h"
32 #include "sleep_led.h"
33 #include "led.h"
34 #include "command.h"
35 #include "backlight.h"
36
37 #ifdef MOUSEKEY_ENABLE
38 #include "mousekey.h"
39 #endif
40
41 #ifdef PROTOCOL_PJRC
42 #   include "usb_keyboard.h"
43 #   ifdef EXTRAKEY_ENABLE
44 #       include "usb_extra.h"
45 #   endif
46 #endif
47
48 #ifdef PROTOCOL_VUSB
49 #   include "usbdrv.h"
50 #endif
51
52
53 static bool command_common(uint8_t code);
54 static void command_common_help(void);
55 static bool command_console(uint8_t code);
56 static void command_console_help(void);
57 #ifdef MOUSEKEY_ENABLE
58 static bool mousekey_console(uint8_t code);
59 static void mousekey_console_help(void);
60 static uint8_t numkey2num(uint8_t code);
61 #endif
62
63
64 static void switch_default_layer(uint8_t layer);
65
66
67 command_state_t command_state = ONESHOT;
68
69
70 bool command_proc(uint8_t code)
71 {
72     switch (command_state) {
73         case ONESHOT:
74             if (!IS_COMMAND())
75                 return false;
76             return (command_extra(code) || command_common(code));
77             break;
78         case CONSOLE:
79             if (IS_COMMAND())
80                 return (command_extra(code) || command_common(code));
81             else
82                 return (command_console_extra(code) || command_console(code));
83             break;
84 #ifdef MOUSEKEY_ENABLE
85         case MOUSEKEY:
86             mousekey_console(code);
87             break;
88 #endif
89         default:
90             command_state = ONESHOT;
91             return false;
92     }
93     return true;
94 }
95
96 /* TODO: Refactoring is needed. */
97 /* This allows to define extra commands. return false when not processed. */
98 bool command_extra(uint8_t code) __attribute__ ((weak));
99 bool command_extra(uint8_t code)
100 {
101     (void)code;
102     return false;
103 }
104
105 bool command_console_extra(uint8_t code) __attribute__ ((weak));
106 bool command_console_extra(uint8_t code)
107 {
108     (void)code;
109     return false;
110 }
111
112
113 /***********************************************************
114  * Command common
115  ***********************************************************/
116 static void command_common_help(void)
117 {
118     print("\n\t- Magic -\n"
119           "d:   debug\n"
120           "x:   debug matrix\n"
121           "k:   debug keyboard\n"
122           "m:   debug mouse\n"
123           "v:   version\n"
124           "s:   status\n"
125           "c:   console mode\n"
126           "0-4: layer0-4(F10-F4)\n"
127           "Paus:        bootloader\n"
128
129 #ifdef KEYBOARD_LOCK_ENABLE
130           "Caps:        Lock\n"
131 #endif
132
133 #ifdef BOOTMAGIC_ENABLE
134           "e:   eeprom\n"
135 #endif
136
137 #ifdef NKRO_ENABLE
138           "n:   NKRO\n"
139 #endif
140
141 #ifdef SLEEP_LED_ENABLE
142           "z:   sleep LED test\n"
143 #endif
144     );
145 }
146
147 #ifdef BOOTMAGIC_ENABLE
148 static void print_eeconfig(void)
149 {
150     print("default_layer: "); print_dec(eeconfig_read_default_layer()); print("\n");
151
152     debug_config_t dc;
153     dc.raw = eeconfig_read_debug();
154     print("debug_config.raw: "); print_hex8(dc.raw); print("\n");
155     print(".enable: "); print_dec(dc.enable); print("\n");
156     print(".matrix: "); print_dec(dc.matrix); print("\n");
157     print(".keyboard: "); print_dec(dc.keyboard); print("\n");
158     print(".mouse: "); print_dec(dc.mouse); print("\n");
159
160     keymap_config_t kc;
161     kc.raw = eeconfig_read_keymap();
162     print("keymap_config.raw: "); print_hex8(kc.raw); print("\n");
163     print(".swap_control_capslock: "); print_dec(kc.swap_control_capslock); print("\n");
164     print(".capslock_to_control: "); print_dec(kc.capslock_to_control); print("\n");
165     print(".swap_lalt_lgui: "); print_dec(kc.swap_lalt_lgui); print("\n");
166     print(".swap_ralt_rgui: "); print_dec(kc.swap_ralt_rgui); print("\n");
167     print(".no_gui: "); print_dec(kc.no_gui); print("\n");
168     print(".swap_grave_esc: "); print_dec(kc.swap_grave_esc); print("\n");
169     print(".swap_backslash_backspace: "); print_dec(kc.swap_backslash_backspace); print("\n");
170     print(".nkro: "); print_dec(kc.nkro); print("\n");
171
172 #ifdef BACKLIGHT_ENABLE
173     backlight_config_t bc;
174     bc.raw = eeconfig_read_backlight();
175     print("backlight_config.raw: "); print_hex8(bc.raw); print("\n");
176     print(".enable: "); print_dec(bc.enable); print("\n");
177     print(".level: "); print_dec(bc.level); print("\n");
178 #endif
179 }
180 #endif
181
182 static bool command_common(uint8_t code)
183 {
184 #ifdef KEYBOARD_LOCK_ENABLE
185     static host_driver_t *host_driver = 0;
186 #endif
187 #ifdef SLEEP_LED_ENABLE
188     static bool sleep_led_test = false;
189 #endif
190     switch (code) {
191 #ifdef SLEEP_LED_ENABLE
192         case KC_Z:
193             // test breathing sleep LED
194             print("Sleep LED test\n");
195             if (sleep_led_test) {
196                 sleep_led_disable();
197                 led_set(host_keyboard_leds());
198             } else {
199                 sleep_led_enable();
200             }
201             sleep_led_test = !sleep_led_test;
202             break;
203 #endif
204 #ifdef BOOTMAGIC_ENABLE
205         case KC_E:
206             print("eeconfig:\n");
207             print_eeconfig();
208             break;
209 #endif
210 #ifdef KEYBOARD_LOCK_ENABLE
211         case KC_CAPSLOCK:
212             if (host_get_driver()) {
213                 host_driver = host_get_driver();
214                 clear_keyboard();
215                 host_set_driver(0);
216                 print("Locked.\n");
217             } else {
218                 host_set_driver(host_driver);
219                 print("Unlocked.\n");
220             }
221             break;
222 #endif
223         case KC_H:
224         case KC_SLASH: /* ? */
225             command_common_help();
226             break;
227         case KC_C:
228             debug_matrix   = false;
229             debug_keyboard = false;
230             debug_mouse    = false;
231             debug_enable   = false;
232             command_console_help();
233             print("C> ");
234             command_state = CONSOLE;
235             break;
236         case KC_PAUSE:
237             clear_keyboard();
238             print("\n\nbootloader... ");
239             wait_ms(1000);
240             bootloader_jump(); // not return
241             break;
242         case KC_D:
243             if (debug_enable) {
244                 print("\ndebug: off\n");
245                 debug_matrix   = false;
246                 debug_keyboard = false;
247                 debug_mouse    = false;
248                 debug_enable   = false;
249             } else {
250                 print("\ndebug: on\n");
251                 debug_enable   = true;
252             }
253             break;
254         case KC_X: // debug matrix toggle
255             debug_matrix = !debug_matrix;
256             if (debug_matrix) {
257                 print("\nmatrix: on\n");
258                 debug_enable = true;
259             } else {
260                 print("\nmatrix: off\n");
261             }
262             break;
263         case KC_K: // debug keyboard toggle
264             debug_keyboard = !debug_keyboard;
265             if (debug_keyboard) {
266                 print("\nkeyboard: on\n");
267                 debug_enable = true;
268             } else {
269                 print("\nkeyboard: off\n");
270             }
271             break;
272         case KC_M: // debug mouse toggle
273             debug_mouse = !debug_mouse;
274             if (debug_mouse) {
275                 print("\nmouse: on\n");
276                 debug_enable = true;
277             } else {
278                 print("\nmouse: off\n");
279             }
280             break;
281         case KC_V: // print version & information
282             print("\n\t- Version -\n");
283             print("DESC: " STR(DESCRIPTION) "\n");
284             print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
285                   "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
286                   "VER: " STR(DEVICE_VER) "\n");
287             print("BUILD: " STR(TMK_VERSION) " (" __TIME__ " " __DATE__ ")\n");
288             /* build options */
289             print("OPTIONS:"
290 #ifdef PROTOCOL_PJRC
291             " PJRC"
292 #endif
293 #ifdef PROTOCOL_LUFA
294             " LUFA"
295 #endif
296 #ifdef PROTOCOL_VUSB
297             " VUSB"
298 #endif
299 #ifdef PROTOCOL_CHIBIOS
300             " CHIBIOS"
301 #endif
302 #ifdef BOOTMAGIC_ENABLE
303             " BOOTMAGIC"
304 #endif
305 #ifdef MOUSEKEY_ENABLE
306             " MOUSEKEY"
307 #endif
308 #ifdef EXTRAKEY_ENABLE
309             " EXTRAKEY"
310 #endif
311 #ifdef CONSOLE_ENABLE
312             " CONSOLE"
313 #endif
314 #ifdef COMMAND_ENABLE
315             " COMMAND"
316 #endif
317 #ifdef NKRO_ENABLE
318             " NKRO"
319 #endif
320 #ifdef KEYMAP_SECTION_ENABLE
321             " KEYMAP_SECTION"
322 #endif
323             " " STR(BOOTLOADER_SIZE) "\n");
324
325             print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
326 #if defined(__AVR__)
327                   " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
328                   " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n");
329 #elif defined(__arm__)
330             // TODO
331             );
332 #endif
333             break;
334         case KC_S:
335             print("\n\t- Status -\n");
336             print_val_hex8(host_keyboard_leds());
337             print_val_hex8(keyboard_protocol);
338             print_val_hex8(keyboard_idle);
339 #ifdef NKRO_ENABLE
340             print_val_hex8(keyboard_nkro);
341 #endif
342             print_val_hex32(timer_read32());
343
344 #ifdef PROTOCOL_PJRC
345             print_val_hex8(UDCON);
346             print_val_hex8(UDIEN);
347             print_val_hex8(UDINT);
348             print_val_hex8(usb_keyboard_leds);
349             print_val_hex8(usb_keyboard_idle_count);
350 #endif
351
352 #ifdef PROTOCOL_PJRC
353 #   if USB_COUNT_SOF
354             print_val_hex8(usbSofCount);
355 #   endif
356 #endif
357             break;
358 #ifdef NKRO_ENABLE
359         case KC_N:
360             clear_keyboard(); //Prevents stuck keys.
361             keyboard_nkro = !keyboard_nkro;
362             if (keyboard_nkro) {
363                 print("NKRO: on\n");
364             } else {
365                 print("NKRO: off\n");
366             }
367             break;
368 #endif
369         case KC_ESC:
370         case KC_GRV:
371         case KC_0:
372         case KC_F10:
373             switch_default_layer(0);
374             break;
375         case KC_1 ... KC_9:
376             switch_default_layer((code - KC_1) + 1);
377             break;
378         case KC_F1 ... KC_F9:
379             switch_default_layer((code - KC_F1) + 1);
380             break;
381         default:
382             print("?");
383             return false;
384     }
385     return true;
386 }
387
388
389 /***********************************************************
390  * Command console
391  ***********************************************************/
392 static void command_console_help(void)
393 {
394     print("\n\t- Console -\n"
395           "ESC/q:       quit\n"
396 #ifdef MOUSEKEY_ENABLE
397           "m:   mousekey\n"
398 #endif
399     );
400 }
401
402 static bool command_console(uint8_t code)
403 {
404     switch (code) {
405         case KC_H:
406         case KC_SLASH: /* ? */
407             command_console_help();
408             break;
409         case KC_Q:
410         case KC_ESC:
411             command_state = ONESHOT;
412             return false;
413 #ifdef MOUSEKEY_ENABLE
414         case KC_M:
415             mousekey_console_help();
416             print("M> ");
417             command_state = MOUSEKEY;
418             return true;
419 #endif
420         default:
421             print("?");
422             return false;
423     }
424     print("C> ");
425     return true;
426 }
427
428
429 #ifdef MOUSEKEY_ENABLE
430 /***********************************************************
431  * Mousekey console
432  ***********************************************************/
433 static uint8_t mousekey_param = 0;
434
435 static void mousekey_param_print(void)
436 {
437     print("\n\t- Values -\n");
438     print("1: delay(*10ms): "); pdec(mk_delay); print("\n");
439     print("2: interval(ms): "); pdec(mk_interval); print("\n");
440     print("3: max_speed: "); pdec(mk_max_speed); print("\n");
441     print("4: time_to_max: "); pdec(mk_time_to_max); print("\n");
442     print("5: wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n");
443     print("6: wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n");
444 }
445
446 //#define PRINT_SET_VAL(v)  print(#v " = "); print_dec(v); print("\n");
447 #define PRINT_SET_VAL(v)  xprintf(#v " = %d\n", (v))
448 static void mousekey_param_inc(uint8_t param, uint8_t inc)
449 {
450     switch (param) {
451         case 1:
452             if (mk_delay + inc < UINT8_MAX)
453                 mk_delay += inc;
454             else
455                 mk_delay = UINT8_MAX;
456             PRINT_SET_VAL(mk_delay);
457             break;
458         case 2:
459             if (mk_interval + inc < UINT8_MAX)
460                 mk_interval += inc;
461             else
462                 mk_interval = UINT8_MAX;
463             PRINT_SET_VAL(mk_interval);
464             break;
465         case 3:
466             if (mk_max_speed + inc < UINT8_MAX)
467                 mk_max_speed += inc;
468             else
469                 mk_max_speed = UINT8_MAX;
470             PRINT_SET_VAL(mk_max_speed);
471             break;
472         case 4:
473             if (mk_time_to_max + inc < UINT8_MAX)
474                 mk_time_to_max += inc;
475             else
476                 mk_time_to_max = UINT8_MAX;
477             PRINT_SET_VAL(mk_time_to_max);
478             break;
479         case 5:
480             if (mk_wheel_max_speed + inc < UINT8_MAX)
481                 mk_wheel_max_speed += inc;
482             else
483                 mk_wheel_max_speed = UINT8_MAX;
484             PRINT_SET_VAL(mk_wheel_max_speed);
485             break;
486         case 6:
487             if (mk_wheel_time_to_max + inc < UINT8_MAX)
488                 mk_wheel_time_to_max += inc;
489             else
490                 mk_wheel_time_to_max = UINT8_MAX;
491             PRINT_SET_VAL(mk_wheel_time_to_max);
492             break;
493     }
494 }
495
496 static void mousekey_param_dec(uint8_t param, uint8_t dec)
497 {
498     switch (param) {
499         case 1:
500             if (mk_delay > dec)
501                 mk_delay -= dec;
502             else
503                 mk_delay = 0;
504             PRINT_SET_VAL(mk_delay);
505             break;
506         case 2:
507             if (mk_interval > dec)
508                 mk_interval -= dec;
509             else
510                 mk_interval = 0;
511             PRINT_SET_VAL(mk_interval);
512             break;
513         case 3:
514             if (mk_max_speed > dec)
515                 mk_max_speed -= dec;
516             else
517                 mk_max_speed = 0;
518             PRINT_SET_VAL(mk_max_speed);
519             break;
520         case 4:
521             if (mk_time_to_max > dec)
522                 mk_time_to_max -= dec;
523             else
524                 mk_time_to_max = 0;
525             PRINT_SET_VAL(mk_time_to_max);
526             break;
527         case 5:
528             if (mk_wheel_max_speed > dec)
529                 mk_wheel_max_speed -= dec;
530             else
531                 mk_wheel_max_speed = 0;
532             PRINT_SET_VAL(mk_wheel_max_speed);
533             break;
534         case 6:
535             if (mk_wheel_time_to_max > dec)
536                 mk_wheel_time_to_max -= dec;
537             else
538                 mk_wheel_time_to_max = 0;
539             PRINT_SET_VAL(mk_wheel_time_to_max);
540             break;
541     }
542 }
543
544 static void mousekey_console_help(void)
545 {
546     print("\n\t- Mousekey -\n"
547           "ESC/q:       quit\n"
548           "1:   delay(*10ms)\n"
549           "2:   interval(ms)\n"
550           "3:   max_speed\n"
551           "4:   time_to_max\n"
552           "5:   wheel_max_speed\n"
553           "6:   wheel_time_to_max\n"
554           "\n"
555           "p:   print values\n"
556           "d:   set defaults\n"
557           "up:  +1\n"
558           "down:        -1\n"
559           "pgup:        +10\n"
560           "pgdown:      -10\n"
561           "\n"
562           "speed = delta * max_speed * (repeat / time_to_max)\n");
563     xprintf("where delta: cursor=%d, wheel=%d\n" 
564             "See http://en.wikipedia.org/wiki/Mouse_keys\n", MOUSEKEY_MOVE_DELTA,  MOUSEKEY_WHEEL_DELTA);
565 }
566
567 static bool mousekey_console(uint8_t code)
568 {
569     switch (code) {
570         case KC_H:
571         case KC_SLASH: /* ? */
572             mousekey_console_help();
573             break;
574         case KC_Q:
575         case KC_ESC:
576             if (mousekey_param) {
577                 mousekey_param = 0;
578             } else {
579                 print("C> ");
580                 command_state = CONSOLE;
581                 return false;
582             }
583             break;
584         case KC_P:
585             mousekey_param_print();
586             break;
587         case KC_1:
588         case KC_2:
589         case KC_3:
590         case KC_4:
591         case KC_5:
592         case KC_6:
593             mousekey_param = numkey2num(code);
594             break;
595         case KC_UP:
596             mousekey_param_inc(mousekey_param, 1);
597             break;
598         case KC_DOWN:
599             mousekey_param_dec(mousekey_param, 1);
600             break;
601         case KC_PGUP:
602             mousekey_param_inc(mousekey_param, 10);
603             break;
604         case KC_PGDN:
605             mousekey_param_dec(mousekey_param, 10);
606             break;
607         case KC_D:
608             mk_delay = MOUSEKEY_DELAY/10;
609             mk_interval = MOUSEKEY_INTERVAL;
610             mk_max_speed = MOUSEKEY_MAX_SPEED;
611             mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
612             mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
613             mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
614             print("set default\n");
615             break;
616         default:
617             print("?");
618             return false;
619     }
620     if (mousekey_param) {
621         xprintf("M%d> ", mousekey_param);
622     } else {
623         print("M>" );
624     }
625     return true;
626 }
627 #endif
628
629
630 /***********************************************************
631  * Utilities
632  ***********************************************************/
633 #if MOUSEKEY_ENABLE
634 static uint8_t numkey2num(uint8_t code)
635 {
636     switch (code) {
637         case KC_1: return 1;
638         case KC_2: return 2;
639         case KC_3: return 3;
640         case KC_4: return 4;
641         case KC_5: return 5;
642         case KC_6: return 6;
643         case KC_7: return 7;
644         case KC_8: return 8;
645         case KC_9: return 9;
646         case KC_0: return 0;
647     }
648     return 0;
649 }
650 #endif
651
652 static void switch_default_layer(uint8_t layer)
653 {
654     xprintf("L%d\n", layer);
655     default_layer_set(1UL<<layer);
656     clear_keyboard();
657 }