]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/common/action.c
xt_usb: Fix XT soft reset
[max/tmk_keyboard.git] / tmk_core / common / action.c
1 /*
2 Copyright 2012,2013,2020 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 "host.h"
18 #include "keycode.h"
19 #include "keyboard.h"
20 #include "mousekey.h"
21 #include "command.h"
22 #include "led.h"
23 #include "backlight.h"
24 #include "action_layer.h"
25 #include "action_tapping.h"
26 #include "action_macro.h"
27 #include "action_util.h"
28 #include "action.h"
29 #include "hook.h"
30 #include "wait.h"
31 #include "bootloader.h"
32
33 #ifdef DEBUG_ACTION
34 #include "debug.h"
35 #else
36 #include "nodebug.h"
37 #endif
38
39
40 void action_exec(keyevent_t event)
41 {
42     if (!IS_NOEVENT(event)) {
43         dprint("\n---- action_exec: start -----\n");
44         dprint("EVENT: "); debug_event(event); dprintln();
45         hook_matrix_change(event);
46     }
47
48     keyrecord_t record = { .event = event };
49
50 #ifndef NO_ACTION_TAPPING
51     action_tapping_process(record);
52 #else
53     process_action(&record);
54     if (!IS_NOEVENT(record.event)) {
55         dprint("processed: "); debug_record(record); dprintln();
56     }
57 #endif
58 }
59
60 void process_action(keyrecord_t *record)
61 {
62     if (hook_process_action(record)) return;
63
64     keyevent_t event = record->event;
65 #ifndef NO_ACTION_TAPPING
66     uint8_t tap_count = record->tap.count;
67 #endif
68
69     if (IS_NOEVENT(event)) { return; }
70
71     action_t action = layer_switch_get_action(event);
72     dprint("ACTION: "); debug_action(action);
73 #ifndef NO_ACTION_LAYER
74     dprint(" layer_state: "); layer_debug();
75     dprint(" default_layer_state: "); default_layer_debug();
76 #endif
77     dprintln();
78
79     switch (action.kind.id) {
80         /* Key and Mods */
81         case ACT_LMODS:
82         case ACT_RMODS:
83             {
84                 uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
85                                                                 action.key.mods<<4;
86                 if (event.pressed) {
87                     if (mods) {
88                         add_weak_mods(mods);
89                         send_keyboard_report();
90                     }
91                     register_code(action.key.code);
92                 } else {
93                     unregister_code(action.key.code);
94                     if (mods) {
95                         del_weak_mods(mods);
96                         send_keyboard_report();
97                     }
98                 }
99             }
100             break;
101 #ifndef NO_ACTION_TAPPING
102         case ACT_LMODS_TAP:
103         case ACT_RMODS_TAP:
104             {
105                 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
106                                                                     action.key.mods<<4;
107                 switch (action.key.code) {
108     #ifndef NO_ACTION_ONESHOT
109                     case MODS_ONESHOT:
110                         // Oneshot modifier
111                         if (event.pressed) {
112                             if (tap_count == 0) {
113                                 register_mods(mods);
114                             }
115                             else if (tap_count == 1) {
116                                 dprint("MODS_TAP: Oneshot: start\n");
117                                 set_oneshot_mods(mods);
118                             }
119                             else {
120                                 register_mods(mods);
121                             }
122                         } else {
123                             if (tap_count == 0) {
124                                 clear_oneshot_mods();
125                                 unregister_mods(mods);
126                             }
127                             else if (tap_count == 1) {
128                                 // Retain Oneshot mods
129                             }
130                             else {
131                                 clear_oneshot_mods();
132                                 unregister_mods(mods);
133                             }
134                         }
135                         break;
136     #endif
137                     case MODS_TAP_TOGGLE:
138                         if (event.pressed) {
139                             if (tap_count <= TAPPING_TOGGLE) {
140                                 if (mods & get_mods()) {
141                                     dprint("MODS_TAP_TOGGLE: toggle mods off\n");
142                                     unregister_mods(mods);
143                                 } else {
144                                     dprint("MODS_TAP_TOGGLE: toggle mods on\n");
145                                     register_mods(mods);
146                                 }
147                             }
148                         } else {
149                             if (tap_count < TAPPING_TOGGLE) {
150                                 dprint("MODS_TAP_TOGGLE: release : unregister_mods\n");
151                                 unregister_mods(mods);
152                             }
153                         }
154                         break;
155                     default:
156                         if (event.pressed) {
157                             if (tap_count > 0) {
158                                 if (record->tap.interrupted) {
159                                     dprint("MODS_TAP: Tap: Cancel: add_mods\n");
160                                     // ad hoc: set 0 to cancel tap
161                                     record->tap.count = 0;
162                                     register_mods(mods);
163                                 } else {
164                                     dprint("MODS_TAP: Tap: register_code\n");
165                                     register_code(action.key.code);
166                                 }
167                             } else {
168                                 dprint("MODS_TAP: No tap: add_mods\n");
169                                 register_mods(mods);
170                             }
171                         } else {
172                             if (tap_count > 0) {
173                                 dprint("MODS_TAP: Tap: unregister_code\n");
174                                 unregister_code(action.key.code);
175                             } else {
176                                 dprint("MODS_TAP: No tap: add_mods\n");
177                                 unregister_mods(mods);
178                             }
179                         }
180                         break;
181                 }
182             }
183             break;
184 #endif
185 #ifdef EXTRAKEY_ENABLE
186         /* other HID usage */
187         case ACT_USAGE:
188             switch (action.usage.page) {
189                 case PAGE_SYSTEM:
190                     if (event.pressed) {
191                         host_system_send(action.usage.code);
192                     } else {
193                         host_system_send(0);
194                     }
195                     break;
196                 case PAGE_CONSUMER:
197                     if (event.pressed) {
198                         host_consumer_send(action.usage.code);
199                     } else {
200                         host_consumer_send(0);
201                     }
202                     break;
203             }
204             break;
205 #endif
206 #ifdef MOUSEKEY_ENABLE
207         /* Mouse key */
208         case ACT_MOUSEKEY:
209             if (event.pressed) {
210                 mousekey_on(action.key.code);
211                 mousekey_send();
212             } else {
213                 mousekey_off(action.key.code);
214                 mousekey_send();
215             }
216             break;
217 #endif
218 #ifndef NO_ACTION_LAYER
219         case ACT_LAYER:
220             if (action.layer_bitop.on == 0) {
221                 /* Default Layer Bitwise Operation */
222                 if (!event.pressed) {
223                     uint8_t shift = action.layer_bitop.part*4;
224                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
225                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
226                     switch (action.layer_bitop.op) {
227                         case OP_BIT_AND: default_layer_and(bits | mask); break;
228                         case OP_BIT_OR:  default_layer_or(bits | mask);  break;
229                         case OP_BIT_XOR: default_layer_xor(bits | mask); break;
230                         case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
231                     }
232                 }
233             } else {
234                 /* Layer Bitwise Operation */
235                 if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
236                                     (action.layer_bitop.on & ON_RELEASE)) {
237                     uint8_t shift = action.layer_bitop.part*4;
238                     uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
239                     uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
240                     switch (action.layer_bitop.op) {
241                         case OP_BIT_AND: layer_and(bits | mask); break;
242                         case OP_BIT_OR:  layer_or(bits | mask);  break;
243                         case OP_BIT_XOR: layer_xor(bits | mask); break;
244                         case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
245                     }
246                 }
247             }
248             break;
249     #ifndef NO_ACTION_TAPPING
250         case ACT_LAYER_TAP:
251         case ACT_LAYER_TAP_EXT:
252             switch (action.layer_tap.code) {
253                 case 0xc0 ... 0xdf:
254                     /* layer On/Off with modifiers */
255                     if (event.pressed) {
256                         layer_on(action.layer_tap.val);
257                         register_mods((action.layer_tap.code & 0x10) ?
258                                 (action.layer_tap.code & 0x0f) << 4 :
259                                 (action.layer_tap.code & 0x0f));
260                     } else {
261                         layer_off(action.layer_tap.val);
262                         unregister_mods((action.layer_tap.code & 0x10) ?
263                                 (action.layer_tap.code & 0x0f) << 4 :
264                                 (action.layer_tap.code & 0x0f));
265                     }
266                     break;
267                 case OP_TAP_TOGGLE:
268                     /* tap toggle */
269                     if (event.pressed) {
270                         if (tap_count < TAPPING_TOGGLE) {
271                             layer_invert(action.layer_tap.val);
272                         }
273                     } else {
274                         if (tap_count <= TAPPING_TOGGLE) {
275                             layer_invert(action.layer_tap.val);
276                         }
277                     }
278                     break;
279                 case OP_ON_OFF:
280                     event.pressed ? layer_on(action.layer_tap.val) :
281                                     layer_off(action.layer_tap.val);
282                     break;
283                 case OP_OFF_ON:
284                     event.pressed ? layer_off(action.layer_tap.val) :
285                                     layer_on(action.layer_tap.val);
286                     break;
287                 case OP_SET_CLEAR:
288                     event.pressed ? layer_move(action.layer_tap.val) :
289                                     layer_clear();
290                     break;
291                 default:
292                     /* tap key */
293                     if (event.pressed) {
294                         if (tap_count > 0) {
295                             dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
296                             register_code(action.layer_tap.code);
297                         } else {
298                             dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
299                             layer_on(action.layer_tap.val);
300                         }
301                     } else {
302                         if (tap_count > 0) {
303                             dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
304                             unregister_code(action.layer_tap.code);
305                         } else {
306                             dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
307                             layer_off(action.layer_tap.val);
308                         }
309                     }
310                     break;
311             }
312             break;
313     #endif
314 #endif
315         /* Extentions */
316 #ifndef NO_ACTION_MACRO
317         case ACT_MACRO:
318             action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
319             break;
320 #endif
321 #ifdef BACKLIGHT_ENABLE
322         case ACT_BACKLIGHT:
323             if (!event.pressed) {
324                 switch (action.backlight.opt) {
325                     case BACKLIGHT_INCREASE:
326                         backlight_increase();
327                         break;
328                     case BACKLIGHT_DECREASE:
329                         backlight_decrease();
330                         break;
331                     case BACKLIGHT_TOGGLE:
332                         backlight_toggle();
333                         break;
334                     case BACKLIGHT_STEP:
335                         backlight_step();
336                         break;
337                     case BACKLIGHT_LEVEL:
338                         backlight_level(action.backlight.level);
339                         break;
340                 }
341             }
342             break;
343 #endif
344         case ACT_COMMAND:
345             switch (action.command.id) {
346                 case COMMAND_BOOTLOADER:
347                     if (event.pressed) {
348                         clear_keyboard();
349                         wait_ms(50);
350                         bootloader_jump();
351                     }
352                     break;
353             }
354             break;
355 #ifndef NO_ACTION_FUNCTION
356         case ACT_FUNCTION:
357             action_function(record, action.func.id, action.func.opt);
358             break;
359 #endif
360         default:
361             break;
362     }
363 }
364
365
366
367
368 /*
369  * Utilities for actions.
370  */
371 void register_code(uint8_t code)
372 {
373     if (code == KC_NO) {
374         return;
375     }
376
377 #ifdef LOCKING_SUPPORT_ENABLE
378     else if (KC_LOCKING_CAPS == code) {
379 #ifdef LOCKING_RESYNC_ENABLE
380         // Resync: ignore if caps lock already is on
381         if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
382 #endif
383         add_key(KC_CAPSLOCK);
384         send_keyboard_report();
385         wait_ms(100);
386         del_key(KC_CAPSLOCK);
387         send_keyboard_report();
388     }
389
390     else if (KC_LOCKING_NUM == code) {
391 #ifdef LOCKING_RESYNC_ENABLE
392         if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
393 #endif
394         add_key(KC_NUMLOCK);
395         send_keyboard_report();
396         wait_ms(100);
397         del_key(KC_NUMLOCK);
398         send_keyboard_report();
399     }
400
401     else if (KC_LOCKING_SCROLL == code) {
402 #ifdef LOCKING_RESYNC_ENABLE
403         if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
404 #endif
405         add_key(KC_SCROLLLOCK);
406         send_keyboard_report();
407         wait_ms(100);
408         del_key(KC_SCROLLLOCK);
409         send_keyboard_report();
410     }
411 #endif
412
413     else if IS_KEY(code) {
414         // TODO: should push command_proc out of this block?
415         if (command_proc(code)) return;
416
417 #ifndef NO_ACTION_ONESHOT
418 /* TODO: remove
419         if (oneshot_state.mods && !oneshot_state.disabled) {
420             uint8_t tmp_mods = get_mods();
421             add_mods(oneshot_state.mods);
422
423             add_key(code);
424             send_keyboard_report();
425
426             set_mods(tmp_mods);
427             send_keyboard_report();
428             oneshot_cancel();
429         } else 
430 */
431 #endif
432         {
433             add_key(code);
434             send_keyboard_report();
435         }
436     }
437     else if IS_MOD(code) {
438         add_mods(MOD_BIT(code));
439         send_keyboard_report();
440     }
441     else if IS_SYSTEM(code) {
442         host_system_send(KEYCODE2SYSTEM(code));
443     }
444     else if IS_CONSUMER(code) {
445         host_consumer_send(KEYCODE2CONSUMER(code));
446     }
447 }
448
449 void unregister_code(uint8_t code)
450 {
451     if (code == KC_NO) {
452         return;
453     }
454
455 #ifdef LOCKING_SUPPORT_ENABLE
456     else if (KC_LOCKING_CAPS == code) {
457 #ifdef LOCKING_RESYNC_ENABLE
458         // Resync: ignore if caps lock already is off
459         if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
460 #endif
461         add_key(KC_CAPSLOCK);
462         send_keyboard_report();
463         wait_ms(100);
464         del_key(KC_CAPSLOCK);
465         send_keyboard_report();
466     }
467
468     else if (KC_LOCKING_NUM == code) {
469 #ifdef LOCKING_RESYNC_ENABLE
470         if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
471 #endif
472         add_key(KC_NUMLOCK);
473         send_keyboard_report();
474         wait_ms(100);
475         del_key(KC_NUMLOCK);
476         send_keyboard_report();
477     }
478
479     else if (KC_LOCKING_SCROLL == code) {
480 #ifdef LOCKING_RESYNC_ENABLE
481         if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
482 #endif
483         add_key(KC_SCROLLLOCK);
484         send_keyboard_report();
485         wait_ms(100);
486         del_key(KC_SCROLLLOCK);
487         send_keyboard_report();
488     }
489 #endif
490
491     else if IS_KEY(code) {
492         del_key(code);
493         send_keyboard_report();
494     }
495     else if IS_MOD(code) {
496         del_mods(MOD_BIT(code));
497         send_keyboard_report();
498     }
499     else if IS_SYSTEM(code) {
500         host_system_send(0);
501     }
502     else if IS_CONSUMER(code) {
503         host_consumer_send(0);
504     }
505 }
506
507 void type_code(uint8_t code)
508 {
509     register_code(code);
510     unregister_code(code);
511 }
512
513 void register_mods(uint8_t mods)
514 {
515     if (mods) {
516         add_mods(mods);
517         send_keyboard_report();
518     }
519 }
520
521 void unregister_mods(uint8_t mods)
522 {
523     if (mods) {
524         del_mods(mods);
525         send_keyboard_report();
526     }
527 }
528
529 void clear_keyboard(void)
530 {
531     clear_mods();
532     clear_keyboard_but_mods();
533 }
534
535 void clear_keyboard_but_mods(void)
536 {
537     clear_weak_mods();
538     clear_keys();
539     send_keyboard_report();
540 #ifdef MOUSEKEY_ENABLE
541     mousekey_clear();
542     mousekey_send();
543 #endif
544 #ifdef EXTRAKEY_ENABLE
545     host_system_send(0);
546     host_consumer_send(0);
547 #endif
548 }
549
550 bool is_tap_key(keyevent_t event)
551 {
552     if (IS_NOEVENT(event)) { return false; }
553
554     action_t action = layer_switch_get_action(event);
555
556     switch (action.kind.id) {
557         case ACT_LMODS_TAP:
558         case ACT_RMODS_TAP:
559             switch (action.key.code) {
560                 case MODS_ONESHOT:
561                 case MODS_TAP_TOGGLE:
562                 case KC_A ... KC_EXSEL:                 // tap key
563                 case KC_LCTRL ... KC_RGUI:              // tap key
564                     return true;
565             }
566         case ACT_LAYER_TAP:
567         case ACT_LAYER_TAP_EXT:
568             switch (action.layer_tap.code) {
569                 case 0xc0 ... 0xdf:         // with modifiers
570                     return false;
571                 case KC_A ... KC_EXSEL:     // tap key
572                 case KC_LCTRL ... KC_RGUI:  // tap key
573                 case OP_TAP_TOGGLE:
574                     return true;
575             }
576             return false;
577         case ACT_MACRO:
578         case ACT_FUNCTION:
579             if (action.func.opt & FUNC_TAP) { return true; }
580             return false;
581     }
582     return false;
583 }
584
585
586 /*
587  * debug print
588  */
589 void debug_event(keyevent_t event)
590 {
591     dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
592 }
593
594 void debug_record(keyrecord_t record)
595 {
596     debug_event(record.event);
597 #ifndef NO_ACTION_TAPPING
598     dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
599 #endif
600 }
601
602 void debug_action(action_t action)
603 {
604     switch (action.kind.id) {
605         case ACT_LMODS:             dprint("ACT_LMODS");             break;
606         case ACT_RMODS:             dprint("ACT_RMODS");             break;
607         case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
608         case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
609         case ACT_USAGE:             dprint("ACT_USAGE");             break;
610         case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
611         case ACT_LAYER:             dprint("ACT_LAYER");             break;
612         case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
613         case ACT_LAYER_TAP_EXT:     dprint("ACT_LAYER_TAP_EXT");     break;
614         case ACT_MACRO:             dprint("ACT_MACRO");             break;
615         case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
616         case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
617         default:                    dprint("UNKNOWN");               break;
618     }
619     dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
620 }