]> git.donarmstrong.com Git - tmk_firmware.git/blob - common/keyboard.c
Fix build option MOUSEKEY_ENABLE.
[tmk_firmware.git] / common / keyboard.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 "keyboard.h"
18 #include "matrix.h"
19 #include "keymap.h"
20 #include "host.h"
21 #include "led.h"
22 #include "keycode.h"
23 #include "timer.h"
24 #include "print.h"
25 #include "debug.h"
26 #include "command.h"
27 #include "util.h"
28 #ifdef MOUSEKEY_ENABLE
29 #include "mousekey.h"
30 #endif
31 #ifdef EXTRAKEY_ENABLE
32 #include <util/delay.h>
33 #endif
34
35
36 #define LAYER_DELAY     250
37
38 typedef enum keykind {
39     NONE,
40     FN_DOWN, FN_UP,
41     FNK_DOWN, FNK_UP,
42     KEY_DOWN, KEY_UP,
43     MOD_DOWN, MOD_UP,
44 } keykind_t;
45
46 typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
47
48
49 uint8_t current_layer = 0;
50 uint8_t default_layer = 0;
51
52 /* keyboard internal states */
53 static kbdstate_t kbdstate = IDLE;
54 static uint8_t fn_state_bits = 0;
55 static keyrecord_t delayed_fn;
56 static keyrecord_t waiting_key;
57
58
59 static const char *state_str(kbdstate_t state)
60 {
61     if (state == IDLE)      return PSTR("IDLE");
62     if (state == DELAYING)  return PSTR("DELAYING");
63     if (state == WAITING)   return PSTR("WAITING");
64     if (state == PRESSING)  return PSTR("PRESSING");
65     return PSTR("UNKNOWN");
66 }
67
68 static inline keykind_t get_keykind(uint8_t code, bool pressed)
69 {
70     if IS_KEY(code)         return (pressed ? KEY_DOWN : KEY_UP);
71     if IS_MOD(code)         return (pressed ? MOD_DOWN : MOD_UP);
72     if IS_FN(code) {
73         if (keymap_fn_keycode(FN_INDEX(code)))
74             return (pressed ? FNK_DOWN : FNK_UP);
75         else
76             return (pressed ? FN_DOWN : FN_UP);
77     }
78     if IS_MOUSEKEY(code)    return (pressed ? KEY_DOWN : KEY_UP);
79     if IS_SYSTEM(code)      return (pressed ? KEY_DOWN : KEY_UP);
80     if IS_CONSUMER(code)    return (pressed ? KEY_DOWN : KEY_UP);
81     return  NONE;
82 }
83
84 static void clear_keyboard(void)
85 {
86     host_clear_keys();
87     host_clear_mods();
88     host_send_keyboard_report();
89
90     host_system_send(0);
91     host_consumer_send(0);
92
93 #ifdef MOUSEKEY_ENABLE
94     mousekey_clear();
95     mousekey_send();
96 #endif
97 }
98
99 static void clear_keyboard_but_mods(void)
100 {
101     host_clear_keys();
102     host_send_keyboard_report();
103
104     host_system_send(0);
105     host_consumer_send(0);
106
107 #ifdef MOUSEKEY_ENABLE
108     mousekey_clear();
109     mousekey_send();
110 #endif
111 }
112
113 static void layer_switch_on(uint8_t code)
114 {
115     if (!IS_FN(code)) return;
116     fn_state_bits |= FN_BIT(code);
117     if (current_layer != keymap_fn_layer(FN_INDEX(code))) {
118         clear_keyboard_but_mods();
119
120         debug("Layer Switch(on): "); debug_hex(current_layer);
121         current_layer = keymap_fn_layer(FN_INDEX(code));
122         debug(" -> "); debug_hex(current_layer); debug("\n");
123     }
124 }
125
126 static void layer_switch_off(uint8_t code)
127 {
128     if (!IS_FN(code)) return;
129     fn_state_bits &= ~FN_BIT(code);
130     if (current_layer != keymap_fn_layer(biton(fn_state_bits))) {
131         clear_keyboard_but_mods();
132
133         debug("Layer Switch(off): "); debug_hex(current_layer);
134         current_layer = keymap_fn_layer(biton(fn_state_bits));
135         debug(" -> "); debug_hex(current_layer); debug("\n");
136     }
137 }
138
139 // whether any key except modifier is down or not
140 static inline bool is_anykey_down(void)
141 {
142     for (int r = 0; r < MATRIX_ROWS; r++) {
143         matrix_row_t matrix_row = matrix_get_row(r);
144         for (int c = 0; c < MATRIX_COLS; c++) {
145             if (matrix_row && (1<<c)) {
146                 if (IS_KEY(keymap_get_keycode(current_layer, r, c))) {
147                     return true;
148                 }
149             }
150         }
151     }
152     return false;
153 }
154
155 static void register_code(uint8_t code)
156 {
157     if IS_KEY(code) {
158         host_add_key(code);
159         host_send_keyboard_report();
160     }
161     else if IS_MOD(code) {
162         host_add_mod_bit(MOD_BIT(code));
163         host_send_keyboard_report();
164     }
165     else if IS_MOUSEKEY(code) {
166 #ifdef MOUSEKEY_ENABLE
167         mousekey_on(code);
168         mousekey_send();
169 #endif
170     }
171     else if IS_CONSUMER(code) {
172         uint16_t usage = 0;
173         switch (code) {
174             case KC_AUDIO_MUTE:
175                 usage = AUDIO_MUTE;
176                 break;
177             case KC_AUDIO_VOL_UP:
178                 usage = AUDIO_VOL_UP;
179                 break;
180             case KC_AUDIO_VOL_DOWN:
181                 usage = AUDIO_VOL_DOWN;
182                 break;
183             case KC_MEDIA_NEXT_TRACK:
184                 usage = TRANSPORT_NEXT_TRACK;
185                 break;
186             case KC_MEDIA_PREV_TRACK:
187                 usage = TRANSPORT_PREV_TRACK;
188                 break;
189             case KC_MEDIA_STOP:
190                 usage = TRANSPORT_STOP;
191                 break;
192             case KC_MEDIA_PLAY_PAUSE:
193                 usage = TRANSPORT_PLAY_PAUSE;
194                 break;
195             case KC_MEDIA_SELECT:
196                 usage = AL_CC_CONFIG;
197                 break;
198             case KC_MAIL:
199                 usage = AL_EMAIL;
200                 break;
201             case KC_CALCULATOR:
202                 usage = AL_CALCULATOR;
203                 break;
204             case KC_MY_COMPUTER:
205                 usage = AL_LOCAL_BROWSER;
206                 break;
207             case KC_WWW_SEARCH:
208                 usage = AC_SEARCH;
209                 break;
210             case KC_WWW_HOME:
211                 usage = AC_HOME;
212                 break;
213             case KC_WWW_BACK:
214                 usage = AC_BACK;
215                 break;
216             case KC_WWW_FORWARD:
217                 usage = AC_FORWARD;
218                 break;
219             case KC_WWW_STOP:
220                 usage = AC_STOP;
221                 break;
222             case KC_WWW_REFRESH:
223                 usage = AC_REFRESH;
224                 break;
225             case KC_WWW_FAVORITES:
226                 usage = AC_BOOKMARKS;
227                 break;
228         }
229         host_consumer_send(usage);
230     }
231     else if IS_SYSTEM(code) {
232         uint16_t usage = 0;
233         switch (code) {
234             case KC_SYSTEM_POWER:
235                 usage = SYSTEM_POWER_DOWN;
236                 break;
237             case KC_SYSTEM_SLEEP:
238                 usage = SYSTEM_SLEEP;
239                 break;
240             case KC_SYSTEM_WAKE:
241                 usage = SYSTEM_WAKE_UP;
242                 break;
243         }
244         host_system_send(usage);
245     }
246
247 }
248
249 static void unregister_code(uint8_t code)
250 {
251     if IS_KEY(code) {
252         host_del_key(code);
253         host_send_keyboard_report();
254     }
255     else if IS_MOD(code) {
256         host_del_mod_bit(MOD_BIT(code));
257         host_send_keyboard_report();
258     }
259     else if IS_MOUSEKEY(code) {
260 #ifdef MOUSEKEY_ENABLE
261         mousekey_off(code);
262         mousekey_send();
263 #endif
264     }
265     else if IS_CONSUMER(code) {
266         host_consumer_send(0x0000);
267     }
268     else if IS_SYSTEM(code) {
269         host_system_send(0x0000);
270     }
271 }
272
273 /*
274  *
275  * Event/State|IDLE             DELAYING[f]     WAITING[f,k]        PRESSING
276  * -----------+------------------------------------------------------------------
277  * Fn  Down   |IDLE(L+)         WAITING(Sk)     WAITING(Sk)         -
278  *     Up     |IDLE(L-)         IDLE(L-)        IDLE(L-)            IDLE(L-)
279  * Fnk Down   |DELAYING(Sf)     WAITING(Sk)     WAINTING(Sk)        PRESSING(Rf)
280  *     Up     |IDLE(L-)         IDLE(Rf,Uf)     IDLE(Rf,Ps,Uf)*3    PRESSING(Uf)
281  * Key Down   |PRESSING(Rk)     WAITING(Sk)     WAITING(Sk)         PRESSING(Rk)
282  *     Up     |IDLE(Uk)         DELAYING(Uk)    IDLE(L+,Ps,Uk)      IDLE(Uk)*4
283  * Delay      |-                IDLE(L+)        IDLE(L+,Ps)         -
284  *            |
285  * No key Down|IDLE(Ld)         IDLE(Ld)        IDLE(Ld)            IDLE(Ld)
286  *
287  * *2: register Fnk if any key is pressing
288  * *3: when Fnk == Stored Fnk, if not ignore.
289  * *4: when no registered key any more
290  *
291  * States:
292  *      IDLE:
293  *      DELAYING: delay layer switch after pressing Fn with alt keycode
294  *      WAITING: key is pressed during DELAYING
295  *
296  * Events:
297  *      Fn: Fn key without alternative keycode
298  *      Fnk: Fn key with alternative keycode
299  *      -: ignore
300  *
301  * Actions:
302  *      Rk: register key
303  *      Uk: unregister key
304  *      Rf: register stored Fn(alt keycode)
305  *      Uf: unregister stored Fn(alt keycode)
306  *      Rs: register stored key
307  *      Us: unregister stored key
308  *      Sk: store key
309  *      Sf: store Fn
310  *      Ps: play stored key(Interpret stored key and transit state)
311  *      L+: Switch to new layer(*unregister* all keys but modifiers)
312  *      L-: Switch back to last layer(*unregister* all keys but modifiers)
313  *      Ld: Switch back to default layer(*unregister* all keys but modifiers)
314  */
315 #define NEXT(state)     do { \
316     debug("NEXT: "); print_P(state_str(kbdstate)); \
317     kbdstate = state; \
318     debug(" -> "); print_P(state_str(kbdstate)); debug("\n"); \
319 } while (0)
320
321 static inline void process_key(keyevent_t event)
322 {
323     uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col);
324     keykind_t kind = get_keykind(code, event.pressed);
325
326     uint8_t tmp_mods;
327
328     debug("state: "); print_P(state_str(kbdstate));
329     debug(" kind: "); debug_hex(kind);
330     debug(" code: "); debug_hex(code);
331     if (event.pressed) { debug("d"); } else { debug("u"); }
332     debug("\n");
333
334     switch (kbdstate) {
335         case IDLE:
336             switch (kind) {
337                 case FN_DOWN:
338                     layer_switch_on(code);
339                     break;
340                 case FN_UP:
341                     layer_switch_off(code);
342                     break;
343                 case FNK_DOWN:
344                     // repeat Fn alt key when press Fn key down, up then down again quickly
345                     if (KEYEQ(delayed_fn.event.key, event.key) &&
346                             timer_elapsed(delayed_fn.time) < LAYER_DELAY) {
347                         register_code(keymap_fn_keycode(FN_INDEX(code)));
348                         NEXT(PRESSING);
349                     } else {
350                         delayed_fn = (keyrecord_t) {
351                             .event = event,
352                             .code = code,
353                             .mods = keyboard_report->mods,
354                             .time = timer_read()
355                         };
356                         NEXT(DELAYING);
357                     }
358                     break;
359                 case FNK_UP:
360                     layer_switch_off(code);
361                     break;
362                 case KEY_DOWN:
363                     register_code(code);
364                     NEXT(PRESSING);
365                     break;
366                 case MOD_DOWN:
367                     register_code(code);
368                     break;
369                 case KEY_UP:
370                 case MOD_UP:
371                     unregister_code(code);
372                     break;
373                 default:
374                     break;
375             }
376             break;
377         case PRESSING:
378             switch (kind) {
379                 case FN_DOWN:
380                     // ignored when any key is pressed
381                     break;
382                 case FN_UP:
383                     layer_switch_off(code);
384                     NEXT(IDLE);
385                     break;
386                 case FNK_DOWN:
387                     register_code(keymap_fn_keycode(FN_INDEX(code)));
388                     break;
389                 case FNK_UP:
390                     // can't know whether layer switched or not
391                     layer_switch_off(code);
392                     unregister_code(keymap_fn_keycode(FN_INDEX(code)));
393                     break;
394                 case KEY_DOWN:
395                 case MOD_DOWN:
396                     register_code(code);
397                     break;
398                 case KEY_UP:
399                 case MOD_UP:
400                     unregister_code(code);
401                     // TODO: no key registered? mousekey, mediakey, systemkey
402                     if (!host_has_anykey())
403                         NEXT(IDLE);
404                     break;
405                 default:
406                     break;
407             }
408             break;
409         case DELAYING:
410             switch (kind) {
411                 case FN_DOWN:
412                 case FNK_DOWN:
413                 case KEY_DOWN:
414                     waiting_key = (keyrecord_t) {
415                         .event = event,
416                         .code = code,
417                         .mods = keyboard_report->mods,
418                         .time = timer_read()
419                     };
420                     NEXT(WAITING);
421                     break;
422                 case MOD_DOWN:
423                     register_code(code);
424                     break;
425                 case FN_UP:
426                     layer_switch_off(code);
427                     NEXT(IDLE);
428                     break;
429                 case FNK_UP:
430                     if (code == delayed_fn.code) {
431                         // type Fn with alt keycode
432                         // restore the mod status at the time of pressing Fn key
433                         tmp_mods = keyboard_report->mods;
434                         host_set_mods(delayed_fn.mods);
435                         register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
436                         unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
437                         host_set_mods(tmp_mods);
438                         NEXT(IDLE);
439                     } else {
440                         layer_switch_off(code);
441                         NEXT(IDLE);
442                     }
443                     break;
444                 case KEY_UP:
445                     unregister_code(code);
446                     NEXT(IDLE);
447                     break;
448                 case MOD_UP:
449                     unregister_code(code);
450                     break;
451                 default:
452                     break;
453             }
454             break;
455         case WAITING:
456             switch (kind) {
457                 case FN_DOWN:
458                 case FNK_DOWN:
459                 case KEY_DOWN:
460                     tmp_mods = keyboard_report->mods;
461                     host_set_mods(delayed_fn.mods);
462                     register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
463                     host_set_mods(waiting_key.mods);
464                     register_code(waiting_key.code);
465                     host_set_mods(tmp_mods);
466                     register_code(code);
467                     NEXT(IDLE);
468                     break;
469                 case MOD_DOWN:
470                     register_code(code);
471                     break;
472                 case FN_UP:
473                     layer_switch_off(code);
474                     NEXT(IDLE);
475                     break;
476                 case FNK_UP:
477                     if (code == delayed_fn.code) {
478                         // alt down, key down, alt up
479                         tmp_mods = keyboard_report->mods;
480                         host_set_mods(delayed_fn.mods);
481                         register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
482                         host_set_mods(waiting_key.mods);
483                         register_code(waiting_key.code);
484                         unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
485                         host_set_mods(tmp_mods);
486                         NEXT(IDLE);
487                     } else {
488                         layer_switch_off(code);
489                         NEXT(IDLE);
490                     }
491                     break;
492                 case KEY_UP:
493                     if (code == waiting_key.code) {
494                         layer_switch_on(delayed_fn.code);
495                         NEXT(IDLE);
496                         // process waiting_key
497                         tmp_mods = keyboard_report->mods;
498                         host_set_mods(waiting_key.mods);
499                         process_key(waiting_key.event);
500                         host_set_mods(tmp_mods);
501                         process_key(event);
502                     } else {
503                         unregister_code(code);
504                     }
505                     break;
506                 case MOD_UP:
507                     unregister_code(code);
508                     break;
509                 default:
510                     break;
511             }
512             break;
513     }
514 }
515
516 void keyboard_init(void)
517 {
518     debug_keyboard = true;
519
520     timer_init();
521     matrix_init();
522 #ifdef PS2_MOUSE_ENABLE
523     ps2_mouse_init();
524 #endif
525 }
526
527 void keyboard_task(void)
528 {
529     static matrix_row_t matrix_prev[MATRIX_ROWS];
530     matrix_row_t matrix_row = 0;
531     matrix_row_t matrix_change = 0;
532
533     matrix_scan();
534     if (command_proc()) {
535         debug("COMMAND\n");
536         // TODO: COMMAND state?
537         clear_keyboard();
538         return;
539     }
540
541     for (int r = 0; r < MATRIX_ROWS; r++) {
542         matrix_row = matrix_get_row(r);
543         matrix_change = matrix_row ^ matrix_prev[r];
544         if (matrix_change) {
545             if (debug_matrix) matrix_print();
546
547             for (int c = 0; c < MATRIX_COLS; c++) {
548                 if (matrix_change & (1<<c)) {
549                     process_key((keyevent_t){
550                         .key = (key_t){ .row = r, .col = c },
551                         .pressed = (matrix_row & (1<<c))
552                     });
553                     // record a processed key
554                     matrix_prev[r] ^= (1<<c);
555                     // process a key per task call
556                     goto MATRIX_LOOP_END;
557                 }
558             }
559         }
560     }
561     MATRIX_LOOP_END:
562
563     // layer switch when delay term elapses
564     if (kbdstate == DELAYING || kbdstate == WAITING) {
565         if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) {
566             if (kbdstate == DELAYING) {
567                 layer_switch_on(delayed_fn.code);
568                 NEXT(IDLE);
569             }
570             if (kbdstate == WAITING) {
571                 layer_switch_on(delayed_fn.code);
572                 NEXT(IDLE);
573                 uint8_t tmp_mods = keyboard_report->mods;
574                 host_set_mods(waiting_key.mods);
575                 process_key(waiting_key.event);
576                 host_set_mods(tmp_mods);
577             }
578         }
579     }
580
581 #ifdef MOUSEKEY_ENABLE
582     // mousekey repeat & acceleration
583     mousekey_task();
584 #endif
585
586     // FAIL SAFE: clear all key if no key down
587     if (matrix_change) {
588         matrix_row_t is_matrix_on = 0;
589         for (int r = 0; r < MATRIX_ROWS; r++) {
590             is_matrix_on |= matrix_get_row(r);
591         }
592         if (!is_matrix_on) {
593             debug("FAIL SAFE: clear all keys.\n");
594             clear_keyboard();
595         }
596     }
597     
598     return;
599 }
600
601 void keyboard_set_leds(uint8_t leds)
602 {
603     led_set(leds);
604 }