aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/action.c572
-rw-r--r--common/action.h219
-rw-r--r--common/host.c8
-rw-r--r--common/host.h4
-rw-r--r--common/keyboard.c550
-rw-r--r--common/keyboard.h5
-rw-r--r--common/keycode.h2
-rw-r--r--common/keymap.h14
-rw-r--r--common/report.h81
9 files changed, 898 insertions, 557 deletions
diff --git a/common/action.c b/common/action.c
new file mode 100644
index 000000000..d4aae207f
--- /dev/null
+++ b/common/action.c
@@ -0,0 +1,572 @@
1#include "host.h"
2#include "timer.h"
3//#include "keymap.h"
4#include "keycode.h"
5#include "keyboard.h"
6#include "mousekey.h"
7#include "command.h"
8#include "util.h"
9#include "debug.h"
10#include "action.h"
11
12#define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0)
13#define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0)
14#define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0)
15
16
17/*
18 *
19 * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k]
20 * -----------+------------------------------------------------------------------
21 * Fn Down |(L+) -*1 WAITING(Sk) IDLE(Rf,Ps)*7
22 * Up |(L-) IDLE(L-)*8 IDLE(L-)*8 IDLE(L-)*8
23 * Fnk Down |DELAYING(Sf)* (Rf) WAITING(Sk) IDLE(Rf,Ps,Rf)
24 * Up |(L-) IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3
25 * Key Down |PRESSING(Rk) (Rk) WAITING(Sk) IDLE(Rf,Ps,Rk)
26 * Up |(Uk) IDLE(Uk)*4 (Uk) IDLE(L+,Ps,Pk)/(Uk)*a
27 * |
28 * Delay |- - IDLE(L+) IDLE(L+,Ps)
29 * Magic Key |COMMAND*5
30 *
31 * *1: ignore Fn if other key is down.
32 * *2: register Fnk if any key is pressing
33 * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8
34 * *4: if no keys registered to host
35 * *5: unregister all keys
36 * *6: only if no keys down
37 * *7: ignore Fn because Fnk key and stored key are down.
38 * *8: move to IDLE if layer switch(off) occurs, else stay at current state
39 * *9: repeat key if pressing Fnk twice quickly(move to PRESSING)
40 * *a: layer switch and process waiting key and code if code == wainting key, else unregister key
41 *
42 * States:
43 * IDLE: No key is down except modifiers
44 * DELAYING: delay layer switch after pressing Fn with alt keycode
45 * WAITING: key is pressed during DELAYING
46 *
47 * Events:
48 * Fn: Fn key without alternative keycode
49 * Fnk: Fn key with alternative keycode
50 * -: ignore
51 * Delay: layer switch delay term is elapsed
52 *
53 * Actions:
54 * Rk: register key
55 * Uk: unregister key
56 * Rf: register Fn(alt keycode)
57 * Uf: unregister Fn(alt keycode)
58 * Rs: register stored key
59 * Us: unregister stored key
60 * Sk: Store key(waiting Key)
61 * Sf: Store Fn(delayed Fn)
62 * Ps: Process stored key
63 * Ps: Process key
64 * Is: Interpret stored keys in current layer
65 * L+: Switch to new layer(*unregister* all keys but modifiers)
66 * L-: Switch back to last layer(*unregister* all keys but modifiers)
67 * Ld: Switch back to default layer(*unregister* all keys but modifiers)
68 */
69
70
71typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
72#define NEXT(state) do { \
73 Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \
74 kbdstate = state; \
75 Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \
76} while (0)
77
78
79static kbdstate_t kbdstate = IDLE;
80static uint8_t fn_state_bits = 0;
81static keyrecord_t delayed_fn = {};
82static keyrecord_t waiting_key = {};
83
84static const char *state_str(kbdstate_t state)
85{
86 if (state == IDLE) return PSTR("IDLE");
87 if (state == DELAYING) return PSTR("DELAYING");
88 if (state == WAITING) return PSTR("WAITING");
89 if (state == PRESSING) return PSTR("PRESSING");
90 return PSTR("UNKNOWN");
91}
92static bool anykey_sent_to_host(void)
93{
94 return (host_has_anykey() || host_mouse_in_use() ||
95 host_last_sysytem_report() || host_last_consumer_report());
96}
97
98
99
100/*
101static void layer_switch_on(uint8_t code);
102static void layer_switch_off(uint8_t code);
103static void key_action(uint8_t code, keyevent_t event);
104static void key_pressed(uint8_t code, keyevent_t event);
105static void key_released(uint8_t code, keyevent_t event);
106static void mod_pressed(uint8_t code, keyevent_t event);
107static void mod_released(uint8_t code, keyevent_t event);
108*/
109
110static void register_code(uint8_t code);
111static void unregister_code(uint8_t code);
112static void register_mods(uint8_t mods);
113static void unregister_mods(uint8_t mods);
114static void clear_keyboard(void);
115static void clear_keyboard_but_mods(void);
116static void layer_switch(uint8_t new_layer);
117
118
119/* tap */
120#define TAP_TIME 200
121static keyevent_t last_event = {};
122static uint16_t last_event_time = 0;
123static uint8_t tap_count = 0;
124
125/* layer */
126uint8_t default_layer = 0;
127uint8_t current_layer = 0;
128uint8_t waiting_layer = 0;
129
130
131void action_exec(action_t action, keyevent_t event)
132{
133 /* count tap when key is up */
134 if (KEYEQ(event.key, last_event.key) && timer_elapsed(last_event_time) < TAP_TIME) {
135 if (!event.pressed) tap_count++;
136 } else {
137 tap_count = 0;
138 }
139
140 debug("action: "); debug_hex16(action.code); debug("\n");
141 debug("kind.id: "); debug_hex(action.kind.id); debug("\n");
142 debug("kind.param: "); debug_hex16(action.kind.param); debug("\n");
143 debug("key.code: "); debug_hex(action.key.code); debug("\n");
144 debug("key.mods: "); debug_hex(action.key.mods); debug("\n");
145
146 switch (action.kind.id) {
147 case ACT_LMODS:
148 if (event.pressed) {
149 register_mods(action.key.mods);
150 register_code(action.key.code);
151 } else {
152 unregister_code(action.key.code);
153 unregister_mods(action.key.mods);
154 }
155 break;
156 case ACT_RMODS:
157 if (event.pressed) {
158 register_mods(action.key.mods<<4);
159 register_code(action.key.code);
160 } else {
161 unregister_code(action.key.code);
162 unregister_mods(action.key.mods<<4);
163 }
164 break;
165 case ACT_LAYER:
166 switch (action.layer_key.code) {
167 case 0x00: // Momentary switch
168 // TODO: history of layer switch
169 if (event.pressed) {
170 layer_switch(action.layer_key.layer);
171 } else {
172 layer_switch(default_layer);
173 }
174 break;
175 case 0x01: // Oneshot switch
176 // TODO:
177 break;
178 case 0x02: // reserved
179 case 0x03: // reserved
180 break;
181 case 0xF0 ... 0xF7: // Tap to enable/disable
182 case 0xF8 ... 0xFF: // Tap to toggle layer
183 // TODO:
184 break;
185 default: // with keycode for tap
186 debug("tap: "); debug_hex(tap_count); debug("\n");
187 // TODO: layer switch
188 // TODO: in case tap is interrupted by other key
189
190
191 if (event.pressed) {
192 // when any key down
193 if (host_has_anykey()) {
194 if (tap_count == 0)
195 register_code(action.layer_key.code);
196 } else {
197 }
198
199 if (tap_count == 0) {
200 if (host_has_anykey()) {
201 register_code(action.layer_key.code);
202 } else {
203 waiting_layer = action.layer_key.layer;
204 }
205 }
206 // register key when press after a tap
207 if (tap_count > 0) {
208 register_code(action.layer_key.code);
209 }
210 } else {
211 // type key after tap
212 if (tap_count == 1) {
213 register_code(action.layer_key.code);
214 }
215 unregister_code(action.layer_key.code);
216 }
217 break;
218 }
219 break;
220 case ACT_USAGE:
221#ifdef EXTRAKEY_ENABLE
222 switch (action.usage.page) {
223 case ACTION_USAGE_PAGE_SYSTEM:
224 if (event.pressed) {
225 host_system_send(action.usage.code);
226 } else {
227 host_system_send(0);
228 }
229 break;
230 case ACTION_USAGE_PAGE_CONSUMER:
231 if (event.pressed) {
232 host_consumer_send(action.usage.code);
233 } else {
234 host_consumer_send(0);
235 }
236 break;
237 }
238#endif
239 break;
240 case ACT_MOUSEKEY:
241#ifdef MOUSEKEY_ENABLE
242 if (event.pressed) {
243 mousekey_on(action.key.code);
244 mousekey_send();
245 } else {
246 mousekey_off(action.key.code);
247 mousekey_send();
248 }
249#endif
250 break;
251 case ACT_LMOD_TAP:
252 case ACT_RMOD_TAP:
253 case ACT_MACRO:
254 case ACT_COMMAND:
255 case ACT_FUNCTION:
256 default:
257 break;
258 }
259
260 /* last event */
261 last_event = event;
262 last_event_time = timer_read();
263}
264
265
266#if 0
267/* Key Action */
268inline
269static void key_action(uint8_t code, keyevent_t event)
270{
271 if (event.pressed)
272 key_pressed(code, event);
273 else
274 key_released(code, event);
275}
276
277void fn_action(uint8_t code, keyevent_t event)
278{
279}
280
281/* Key */
282inline static void key_pressed(uint8_t code, keyevent_t event)
283{
284 uint8_t tmp_mods;
285 switch (kbdstate) {
286 case IDLE:
287 register_code(code);
288 NEXT(PRESSING);
289 break;
290 case PRESSING:
291 register_code(code);
292 break;
293 case DELAYING:
294 waiting_key = (keyrecord_t) {
295 .event = event,
296 .code = code,
297 .mods = keyboard_report->mods,
298 .time = timer_read()
299 };
300 NEXT(WAITING);
301 break;
302 case WAITING:
303 // play back key stroke
304 tmp_mods = keyboard_report->mods;
305 host_set_mods(delayed_fn.mods);
306 register_code(delayed_fn.code);
307 host_set_mods(waiting_key.mods);
308 register_code(waiting_key.code);
309 host_set_mods(tmp_mods);
310 register_code(code);
311 NEXT(IDLE);
312 break;
313 }
314}
315inline static void key_released(uint8_t code, keyevent_t event)
316{
317 uint8_t tmp_mods;
318 switch (kbdstate) {
319 case IDLE:
320 unregister_code(code);
321 break;
322 case PRESSING:
323 unregister_code(code);
324 if (!anykey_sent_to_host())
325 NEXT(IDLE);
326 break;
327 case DELAYING:
328 unregister_code(code);
329 break;
330 case WAITING:
331 if (code == waiting_key.code) {
332 layer_switch_on(delayed_fn.code);
333 NEXT(IDLE);
334 // process waiting_key
335 tmp_mods = keyboard_report->mods;
336 host_set_mods(waiting_key.mods);
337 keymap_process_event(waiting_key.event);
338 host_set_mods(tmp_mods);
339 keymap_process_event(event);
340 } else {
341 unregister_code(code);
342 }
343 break;
344 }
345}
346
347/* layer switch momentary */
348inline static void layerkey_pressed(uint8_t code, keyevent_t event)
349{
350 uint8_t tmp_mods;
351 switch (kbdstate) {
352 case IDLE:
353 layer_switch_on(code);
354 break;
355 case PRESSING:
356 // ignore
357 break;
358 case DELAYING:
359 waiting_key = (keyrecord_t) {
360 .event = event,
361 .code = code,
362 .mods = keyboard_report->mods,
363 .time = timer_read()
364 };
365 NEXT(WAITING);
366 break;
367 case WAITING:
368 tmp_mods = keyboard_report->mods;
369 host_set_mods(delayed_fn.mods);
370 register_code(delayed_fn.code);
371 host_set_mods(waiting_key.mods);
372 register_code(waiting_key.code);
373 host_set_mods(tmp_mods);
374 if (kind == FN_DOWN) {
375 // ignore Fn
376 } else if (kind == FNK_DOWN) {
377 register_code(code);
378 } else if (kind == KEY_DOWN) {
379 register_code(code);
380 }
381 NEXT(IDLE);
382 break;
383 }
384}
385inline static void layerkey_released(uint8_t code, keyevent_t event)
386{
387 switch (kbdstate) {
388 case IDLE:
389 layer_switch_off(code);
390 break;
391 case PRESSING:
392 case DELAYING:
393 case WAITING:
394 if (layer_switch_off(code))
395 NEXT(IDLE);
396 break;
397 }
398}
399#endif
400
401
402static void register_code(uint8_t code)
403{
404 if (code == KC_NO) {
405 return;
406 }
407 else if IS_KEY(code) {
408 // TODO: should push command_proc out of this block?
409 if (!command_proc(code)) {
410 host_add_key(code);
411 host_send_keyboard_report();
412 }
413 }
414 else if IS_MOD(code) {
415 host_add_mods(MOD_BIT(code));
416 host_send_keyboard_report();
417 }
418#ifdef MOUSEKEY_ENABLE
419 else if IS_MOUSEKEY(code) {
420 mousekey_on(code);
421 mousekey_send();
422 }
423#endif
424#ifdef EXTRAKEY_ENABLE
425 else if IS_CONSUMER(code) {
426 uint16_t usage = 0;
427 switch (code) {
428 case KC_AUDIO_MUTE:
429 usage = AUDIO_MUTE;
430 break;
431 case KC_AUDIO_VOL_UP:
432 usage = AUDIO_VOL_UP;
433 break;
434 case KC_AUDIO_VOL_DOWN:
435 usage = AUDIO_VOL_DOWN;
436 break;
437 case KC_MEDIA_NEXT_TRACK:
438 usage = TRANSPORT_NEXT_TRACK;
439 break;
440 case KC_MEDIA_PREV_TRACK:
441 usage = TRANSPORT_PREV_TRACK;
442 break;
443 case KC_MEDIA_STOP:
444 usage = TRANSPORT_STOP;
445 break;
446 case KC_MEDIA_PLAY_PAUSE:
447 usage = TRANSPORT_PLAY_PAUSE;
448 break;
449 case KC_MEDIA_SELECT:
450 usage = AL_CC_CONFIG;
451 break;
452 case KC_MAIL:
453 usage = AL_EMAIL;
454 break;
455 case KC_CALCULATOR:
456 usage = AL_CALCULATOR;
457 break;
458 case KC_MY_COMPUTER:
459 usage = AL_LOCAL_BROWSER;
460 break;
461 case KC_WWW_SEARCH:
462 usage = AC_SEARCH;
463 break;
464 case KC_WWW_HOME:
465 usage = AC_HOME;
466 break;
467 case KC_WWW_BACK:
468 usage = AC_BACK;
469 break;
470 case KC_WWW_FORWARD:
471 usage = AC_FORWARD;
472 break;
473 case KC_WWW_STOP:
474 usage = AC_STOP;
475 break;
476 case KC_WWW_REFRESH:
477 usage = AC_REFRESH;
478 break;
479 case KC_WWW_FAVORITES:
480 usage = AC_BOOKMARKS;
481 break;
482 }
483 host_consumer_send(usage);
484 }
485 else if IS_SYSTEM(code) {
486 uint16_t usage = 0;
487 switch (code) {
488 case KC_SYSTEM_POWER:
489 usage = SYSTEM_POWER_DOWN;
490 break;
491 case KC_SYSTEM_SLEEP:
492 usage = SYSTEM_SLEEP;
493 break;
494 case KC_SYSTEM_WAKE:
495 usage = SYSTEM_WAKE_UP;
496 break;
497 }
498 host_system_send(usage);
499 }
500#endif
501}
502
503static void unregister_code(uint8_t code)
504{
505 if IS_KEY(code) {
506 host_del_key(code);
507 host_send_keyboard_report();
508 }
509 else if IS_MOD(code) {
510 host_del_mods(MOD_BIT(code));
511 host_send_keyboard_report();
512 }
513#ifdef MOUSEKEY_ENABLE
514 else if IS_MOUSEKEY(code) {
515 mousekey_off(code);
516 mousekey_send();
517 }
518#endif
519#ifdef EXTRAKEY_ENABLE
520 else if IS_CONSUMER(code) {
521 host_consumer_send(0x0000);
522 }
523 else if IS_SYSTEM(code) {
524 host_system_send(0x0000);
525 }
526#endif
527}
528
529static void register_mods(uint8_t mods)
530{
531 if (!mods) return;
532 host_add_mods(mods);
533 host_send_keyboard_report();
534}
535
536static void unregister_mods(uint8_t mods)
537{
538 if (!mods) return;
539 host_del_mods(mods);
540 host_send_keyboard_report();
541}
542
543static void clear_keyboard(void)
544{
545 host_clear_mods();
546 clear_keyboard_but_mods();
547}
548
549static void clear_keyboard_but_mods(void)
550{
551 host_clear_keys();
552 host_send_keyboard_report();
553#ifdef MOUSEKEY_ENABLE
554 mousekey_clear();
555 mousekey_send();
556#endif
557#ifdef EXTRAKEY_ENABLE
558 host_system_send(0);
559 host_consumer_send(0);
560#endif
561}
562
563static void layer_switch(uint8_t new_layer)
564{
565 if (current_layer != new_layer) {
566 Kdebug("Layer Switch: "); Kdebug_hex(current_layer);
567 Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
568
569 current_layer = new_layer;
570 clear_keyboard_but_mods(); // To avoid stuck keys
571 }
572}
diff --git a/common/action.h b/common/action.h
new file mode 100644
index 000000000..08f8c5608
--- /dev/null
+++ b/common/action.h
@@ -0,0 +1,219 @@
1#ifndef ACTION_H
2#define ACTION_H
3
4#include "keyboard.h"
5
6
7/* Key Action(16bit code)
8 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
9------------------------------------------------
10ACT_LMODS(0000)
11 0 0 0 0| 0 0 0 0| 0 0 0 0 0 0| 0 0 No action
12 0 0 0 0| 0 0 0 0| keycode(8) Key
13 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 0 Lmods Momentary
14 0 0 0 0| mods(4) | 0 0 0 0 0 0| 0 1 Lmods OneShot
15 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 0 (reserved)
16 0 0 0 0| mods(4) | 0 0 0 0 0 0| 1 1 (reserved)
17 0 0 0 0| mods(4) | keycode(8) Key+Lmods
18???
19 0 0 0 0| mods(4) | 1 1 1 1 0| tap(3) Lmods+tap Switch(enable/disable)
20 0 0 0 0| mods(4) | 1 1 1 1 1| tap(3) Lmods+tap Toggle(on/off)
21???
22
23ACT_RMODS(0001)
24 0 0 0 1| 0 0 0 0| 0 0 0 0 0 0 0 0 No action(not used)
25 0 0 0 1| 0 0 0 0| keycode(8) Key(not used)
26 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 0 Rmods Momentary
27 0 0 0 1| mods(4) | 0 0 0 0 0 0| 0 1 Rmods OneShot
28 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 0 (reserved)
29 0 0 0 1| mods(4) | 0 0 0 0 0 0| 1 1 (reserved)
30 0 0 0 1| mods(4) | keycode(8) Key+Rmod
31???
32 0 0 0 1| mods(4) | 1 1 1 1 0| tap(3) Rmods+tap Switch(enable/disable)
33 0 0 0 1| mods(4) | 1 1 1 1 1| tap(3) Rmods+tap Toggle(on/off)
34???
35
36ACT_LMODS_TAP(0010)
37 0 0 1 0| 0 0 0 0| X X X X X X X X (reserved)[00-FF]
38 0 0 1 0| mods(4) | 0 0 0 0 0 0| X X (reserved)
39 0 0 1 0| mods(4) | keycode(8) Lmods+tap Key
40 0 0 1 0| mods(4) | 1 1 1 1| X X X X (reserved)[F0-FF]
41
42ACT_RMODS_TAP(0011)
43 0 0 1 1| 0 0 0 0| X X X X X X X X (reserved)[00-FF]
44 0 0 1 1| mods(4) | 0 0 0 0 0 0| X X (reserved)
45 0 0 1 1| mods(4) | keycode(8) Rmods+tap Key
46 0 0 1 1| mods(4) | 1 1 1 1| X X X X (reserved)[F0-FF]
47
48ACT_LAYER(0100)
49 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 0 Momentary
50 0 1 0 0| layer(4) | 0 0 0 0 0 0| 0 1 Oneshot
51 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 0 (reserved)
52 0 1 0 0| layer(4) | 0 0 0 0 0 0| 1 1 (reserved)
53 0 1 0 0| layer(4) | keycode(8) Fn momentary + tap Key
54 0 1 0 0| layer(4) | 1 1 1 1 0| tap(3) Fn+tap Switch(enable/disable)
55 0 1 0 0| layer(4) | 1 1 1 1 1| tap(3) Fn+tap Toggle(on/off)
56
57ACT_USAGE(0101)
58 0 1 0 1| 0 0| usage(10) System usage
59 0 1 0 1| 0 1| usage(10) Consumer usage
60 0 1 0 1| 1 0| usage(10) (reserved)
61 0 1 0 1| 1 1| usage(10) (reserved)
62
63ACT_MOUSEKEY(0110)
64 0 1 1 0| X X X X| keycode(8) Mouse key
65??? TODO: refactor
66 0 1 1 0| 0 0 X X| accel(5) |cursor(3) Mouse key
67 0 1 1 0| 0 1 X X| accel(5) |wheel(3) Mouse key
68 0 1 1 0| 1 0 X X| button(8) Mouse key
69 0 1 1 0| 1 1 X X| button(8) Mouse key
70???
71
72 0 1 1 1| (reserved)
73 1 0 0 0| (reserved)
74 1 0 0 1| (reserved)
75 1 0 1 0| (reserved)
76 1 0 1 1| (reserved)
77 1 1 0 0| (reserved)
78
79ACT_MACRO(1100)
80 1 1 0 0| option(4) | macro-table id(8) Macro play(Flash)
81 1 1 0 0| option(4) | macro-table id(8) Macro play(EEPROM)
82 1 1 0 0| 1 1 1 1| macro-table id(8) Macro record
83
84ACT_COMMAND(1110)
85 1 1 1 0| option(4) | comamnd id(8) Built-in Command exec
86
87ACT_FUNCTION(1111)
88 1 1 1 1| function address(4K range) Function
89 Macro record(dynamicly)
90 Macro play(dynamicly)
91*/
92
93enum action_id {
94 ACT_LMODS = 0,
95 ACT_RMODS,
96 ACT_LMOD_TAP,
97 ACT_RMOD_TAP,
98 ACT_LAYER,
99 ACT_USAGE,
100 ACT_MOUSEKEY,
101 ACT_MACRO = 14,
102 ACT_COMMAND = 15,
103 ACT_FUNCTION = 16
104};
105
106// TODO: not portable across compiler/endianness?
107/*
108In avr-gcc bit fields seems to be assigned from LSB(bit0) to MSB(bit15).
109AVR seems like little endian in avr-gcc.
110
111Byte order and bit order of 0x1234:
112Big endian: 15 ... 8 7 ... 210
113 | 0x12 | 0x34 |
114 0001 0010 0011 0100
115Little endian: 012 ... 7 8 ... 15
116 | 0x34 | 0x12 |
117 0010 1100 0100 1000
118*/
119typedef union {
120 uint16_t code;
121 struct action_kind {
122 uint16_t param :12;
123 uint16_t id :4;
124 } kind;
125 struct action_key {
126 uint16_t code :8;
127 uint16_t mods :4;
128 uint16_t kind :4;
129 } key;
130 struct action_layer_key {
131 uint16_t code :8;
132 uint16_t layer :4;
133 uint16_t kind :4;
134 } layer_key;
135 struct action_layer_tap {
136 uint16_t count :3;
137 uint16_t rest :5;
138 uint16_t layer :4;
139 uint16_t kind :4;
140 } layer_tap;
141 struct action_usage {
142 uint16_t code :10;
143 uint16_t page :2;
144 uint16_t kind :4;
145 } usage;
146 struct action_command {
147 uint16_t id :8;
148 uint16_t option :4;
149 uint16_t kind :4;
150 } command;
151} action_t;
152
153
154enum stroke_cmd {
155 STROKE_DOWN,
156 STROKE_UP,
157 STROKE_ALLUP, /* release all keys in reverse order */
158};
159
160void action_exec(action_t act, keyevent_t event);
161/*
162void key_action(uint8_t code, keyevent_t event);
163void mod_action(uint8_t code, keyevent_t event);
164void fn_action(uint8_t code, keyevent_t event);
165*/
166
167
168/* action_t utility */
169#define ACTION(kind, param) { .code = ((kind)<<12 | (param)) }
170#define NO_ACTION ACTION(0, 0)
171#define LAYER_PARAM(layer, key) ((layer)<<8|(key))
172
173/* Key & Mods */
174#define ACTION_KEY(key) ACTION(ACT_LMODS, key)
175#define ACTION_LMODS(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x00)
176#define ACTION_LMODS_KEY(mods, key) ACTION(ACT_LMODS, (mods)<<8 | (key))
177#define ACTION_LMODS_ONESHOT(mods) ACTION(ACT_LMODS, (mods)<<8 | 0x01)
178#define ACTION_LMODS_SWITCH(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF0 | (tap))
179#define ACTION_LMODS_TOGGLE(mods, tap) ACTION(ACT_LMODS, (mods)<<8 | 0xF1 | (tap))
180#define ACTION_RMODS(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x00)
181#define ACTION_RMODS_KEY(mods, key) ACTION(ACT_RMODS, (mods)<<8 | (key))
182#define ACTION_RMODS_ONESHOT(mods) ACTION(ACT_RMODS, (mods)<<8 | 0x01)
183#define ACTION_RMODS_SWITCH(mods, tap) ACTION(ACT_RMODS, (mods)<<8 | 0xF0 | (tap))
184#define ACTION_RMODS_TOGGLE(mods, tap) ACTION(ACT_RMODS, (mods)<<8 | 0xF1 | (tap))
185/* Mods + Tap key */
186#define ACTION_LMODS_TAP(mods, key) ACTION(ACT_LMODS_TAP,(mods)<<8 | (key))
187#define ACTION_RMODS_TAP(mods, key) ACTION(ACT_RMODS_TAP,(mods)<<8 | (key))
188/* Layer Switch */
189#define ACTION_LAYER(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x00)
190#define ACTION_LAYER_ONESHOT(layer) ACTION(ACT_LAYER, (layer)<<8 | 0x01)
191#define ACTION_LAYER_KEY(layer, key) ACTION(ACT_LAYER, (layer)<<8 | (key))
192#define ACTION_LAYER_SWITCH(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF0 | (tap))
193#define ACTION_LAYER_TOGGLE(layer, tap) ACTION(ACT_LAYER, (layer)<<8 | 0xF1 | (tap))
194/* HID Usage */
195#define ACTION_USAGE_PAGE_SYSTEM 0
196#define ACTION_USAGE_PAGE_CONSUMER 1
197#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_SYSTEM<<10 | (id))
198#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, ACTION_USAGE_PAGE_CONSUMER<<10 | (id))
199/* Mousekey */
200#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)
201/* Macro */
202#define ACTION_MACRO(opt, id) ACTION(ACT_FUNCTION, (opt)<<8 | (addr))
203/* Command */
204#define ACTION_COMMAND(opt, id) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
205/* Function */
206#define ACTION_FUNCTION(addr) ACTION(ACT_FUNCTION, addr)
207
208
209/* helpers for readability */
210#define LAYER(layer) (layer)
211#define TAP(tap) (tap)
212#define DOUBLE_TAP 2
213#define TRIPLE_TAP 3
214#define QUADRUPLE_TAP 4
215#define QUINTUPLE_TAP 5
216#define DOWN(key) (key)
217#define UP(key) STROKE_UP, (key)
218
219#endif /* ACTION_H */
diff --git a/common/host.c b/common/host.c
index 261ec6472..28c8a819f 100644
--- a/common/host.c
+++ b/common/host.c
@@ -127,14 +127,14 @@ void host_clear_keys(void)
127 } 127 }
128} 128}
129 129
130void host_add_mod_bit(uint8_t mod) 130void host_add_mods(uint8_t mods)
131{ 131{
132 keyboard_report->mods |= mod; 132 keyboard_report->mods |= mods;
133} 133}
134 134
135void host_del_mod_bit(uint8_t mod) 135void host_del_mods(uint8_t mods)
136{ 136{
137 keyboard_report->mods &= ~mod; 137 keyboard_report->mods &= ~mods;
138} 138}
139 139
140void host_set_mods(uint8_t mods) 140void host_set_mods(uint8_t mods)
diff --git a/common/host.h b/common/host.h
index 207b68310..4f1f234a9 100644
--- a/common/host.h
+++ b/common/host.h
@@ -51,8 +51,8 @@ void host_consumer_send(uint16_t data);
51void host_add_key(uint8_t key); 51void host_add_key(uint8_t key);
52void host_del_key(uint8_t key); 52void host_del_key(uint8_t key);
53void host_clear_keys(void); 53void host_clear_keys(void);
54void host_add_mod_bit(uint8_t mod); 54void host_add_mods(uint8_t mods);
55void host_del_mod_bit(uint8_t mod); 55void host_del_mods(uint8_t mods);
56void host_set_mods(uint8_t mods); 56void host_set_mods(uint8_t mods);
57void host_clear_mods(void); 57void host_clear_mods(void);
58uint8_t host_has_anykey(void); 58uint8_t host_has_anykey(void);
diff --git a/common/keyboard.c b/common/keyboard.c
index fa22116f1..5e95fb984 100644
--- a/common/keyboard.c
+++ b/common/keyboard.c
@@ -31,517 +31,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
31#endif 31#endif
32 32
33 33
34#define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0)
35#define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0)
36#define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0)
37
38#define LAYER_DELAY 250
39
40typedef enum keykind {
41 NONE,
42 FN_DOWN, FN_UP,
43 FNK_DOWN, FNK_UP,
44 KEY_DOWN, KEY_UP,
45 MOD_DOWN, MOD_UP,
46} keykind_t;
47
48typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
49
50
51#ifdef KEYMAP_DEFAULT_LAYER
52uint8_t default_layer = KEYMAP_DEFAULT_LAYER;
53uint8_t current_layer = KEYMAP_DEFAULT_LAYER;
54#else
55uint8_t default_layer = 0;
56uint8_t current_layer = 0;
57#endif
58
59/* keyboard internal states */
60static kbdstate_t kbdstate = IDLE;
61static uint8_t fn_state_bits = 0;
62static keyrecord_t delayed_fn;
63static keyrecord_t waiting_key;
64
65
66static const char *state_str(kbdstate_t state)
67{
68 if (state == IDLE) return PSTR("IDLE");
69 if (state == DELAYING) return PSTR("DELAYING");
70 if (state == WAITING) return PSTR("WAITING");
71 if (state == PRESSING) return PSTR("PRESSING");
72 return PSTR("UNKNOWN");
73}
74
75static inline keykind_t get_keykind(uint8_t code, bool pressed)
76{
77 if IS_KEY(code) return (pressed ? KEY_DOWN : KEY_UP);
78 if IS_MOD(code) return (pressed ? MOD_DOWN : MOD_UP);
79 if IS_FN(code) {
80 if (keymap_fn_keycode(FN_INDEX(code)))
81 return (pressed ? FNK_DOWN : FNK_UP);
82 else
83 return (pressed ? FN_DOWN : FN_UP);
84 }
85 if IS_MOUSEKEY(code) return (pressed ? KEY_DOWN : KEY_UP);
86 if IS_SYSTEM(code) return (pressed ? KEY_DOWN : KEY_UP);
87 if IS_CONSUMER(code) return (pressed ? KEY_DOWN : KEY_UP);
88 return NONE;
89}
90
91static void clear_keyboard(void)
92{
93 host_clear_keys();
94 host_clear_mods();
95 host_send_keyboard_report();
96
97 host_system_send(0);
98 host_consumer_send(0);
99
100#ifdef MOUSEKEY_ENABLE
101 mousekey_clear();
102 mousekey_send();
103#endif
104}
105
106static void clear_keyboard_but_mods(void)
107{
108 host_clear_keys();
109 host_send_keyboard_report();
110
111 host_system_send(0);
112 host_consumer_send(0);
113
114#ifdef MOUSEKEY_ENABLE
115 mousekey_clear();
116 mousekey_send();
117#endif
118}
119
120static bool anykey_sent_to_host(void)
121{
122 return (host_has_anykey() || host_mouse_in_use() ||
123 host_last_sysytem_report() || host_last_consumer_report());
124}
125
126static void layer_switch_on(uint8_t code)
127{
128 if (!IS_FN(code)) return;
129 fn_state_bits |= FN_BIT(code);
130 uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer);
131 if (current_layer != new_layer) {
132 Kdebug("Layer Switch(on): "); Kdebug_hex(current_layer);
133 Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
134
135 clear_keyboard_but_mods();
136 current_layer = new_layer;
137 }
138}
139
140static bool layer_switch_off(uint8_t code)
141{
142 if (!IS_FN(code)) return false;
143 fn_state_bits &= ~FN_BIT(code);
144 uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer);
145 if (current_layer != new_layer) {
146 Kdebug("Layer Switch(off): "); Kdebug_hex(current_layer);
147 Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");
148
149 clear_keyboard_but_mods();
150 current_layer = new_layer;
151 return true;
152 }
153 return false;
154}
155
156static void register_code(uint8_t code)
157{
158 if IS_KEY(code) {
159 if (!command_proc(code)) {
160 host_add_key(code);
161 host_send_keyboard_report();
162 }
163 }
164 else if IS_MOD(code) {
165 host_add_mod_bit(MOD_BIT(code));
166 host_send_keyboard_report();
167 }
168 else if IS_FN(code) {
169 if (!command_proc(keymap_fn_keycode(FN_INDEX(code)))) {
170 host_add_key(keymap_fn_keycode(FN_INDEX(code)));
171 host_send_keyboard_report();
172 }
173 }
174 else if IS_MOUSEKEY(code) {
175#ifdef MOUSEKEY_ENABLE
176 mousekey_on(code);
177 mousekey_send();
178#endif
179 }
180 else if IS_CONSUMER(code) {
181 uint16_t usage = 0;
182 switch (code) {
183 case KC_AUDIO_MUTE:
184 usage = AUDIO_MUTE;
185 break;
186 case KC_AUDIO_VOL_UP:
187 usage = AUDIO_VOL_UP;
188 break;
189 case KC_AUDIO_VOL_DOWN:
190 usage = AUDIO_VOL_DOWN;
191 break;
192 case KC_MEDIA_NEXT_TRACK:
193 usage = TRANSPORT_NEXT_TRACK;
194 break;
195 case KC_MEDIA_PREV_TRACK:
196 usage = TRANSPORT_PREV_TRACK;
197 break;
198 case KC_MEDIA_STOP:
199 usage = TRANSPORT_STOP;
200 break;
201 case KC_MEDIA_PLAY_PAUSE:
202 usage = TRANSPORT_PLAY_PAUSE;
203 break;
204 case KC_MEDIA_SELECT:
205 usage = AL_CC_CONFIG;
206 break;
207 case KC_MAIL:
208 usage = AL_EMAIL;
209 break;
210 case KC_CALCULATOR:
211 usage = AL_CALCULATOR;
212 break;
213 case KC_MY_COMPUTER:
214 usage = AL_LOCAL_BROWSER;
215 break;
216 case KC_WWW_SEARCH:
217 usage = AC_SEARCH;
218 break;
219 case KC_WWW_HOME:
220 usage = AC_HOME;
221 break;
222 case KC_WWW_BACK:
223 usage = AC_BACK;
224 break;
225 case KC_WWW_FORWARD:
226 usage = AC_FORWARD;
227 break;
228 case KC_WWW_STOP:
229 usage = AC_STOP;
230 break;
231 case KC_WWW_REFRESH:
232 usage = AC_REFRESH;
233 break;
234 case KC_WWW_FAVORITES:
235 usage = AC_BOOKMARKS;
236 break;
237 }
238 host_consumer_send(usage);
239 }
240 else if IS_SYSTEM(code) {
241 uint16_t usage = 0;
242 switch (code) {
243 case KC_SYSTEM_POWER:
244 usage = SYSTEM_POWER_DOWN;
245 break;
246 case KC_SYSTEM_SLEEP:
247 usage = SYSTEM_SLEEP;
248 break;
249 case KC_SYSTEM_WAKE:
250 usage = SYSTEM_WAKE_UP;
251 break;
252 }
253 host_system_send(usage);
254 }
255
256}
257
258static void unregister_code(uint8_t code)
259{
260 if IS_KEY(code) {
261 host_del_key(code);
262 host_send_keyboard_report();
263 }
264 else if IS_MOD(code) {
265 host_del_mod_bit(MOD_BIT(code));
266 host_send_keyboard_report();
267 }
268 else if IS_FN(code) {
269 host_del_key(keymap_fn_keycode(FN_INDEX(code)));
270 host_send_keyboard_report();
271 }
272 else if IS_MOUSEKEY(code) {
273#ifdef MOUSEKEY_ENABLE
274 mousekey_off(code);
275 mousekey_send();
276#endif
277 }
278 else if IS_CONSUMER(code) {
279 host_consumer_send(0x0000);
280 }
281 else if IS_SYSTEM(code) {
282 host_system_send(0x0000);
283 }
284}
285
286/*
287 *
288 * Event/State|IDLE PRESSING DELAYING[f] WAITING[f,k]
289 * -----------+------------------------------------------------------------------
290 * Fn Down |(L+) -*1 WAITING(Sk) IDLE(Rf,Ps)*7
291 * Up |(L-) IDLE(L-)*8 IDLE(L-)*8 IDLE(L-)*8
292 * Fnk Down |DELAYING(Sf)* (Rf) WAITING(Sk) IDLE(Rf,Ps,Rf)
293 * Up |(L-) IDLE(L-/Uf)*8 IDLE(Rf,Uf/L-)*3 IDLE(Rf,Ps,Uf/L-)*3
294 * Key Down |PRESSING(Rk) (Rk) WAITING(Sk) IDLE(Rf,Ps,Rk)
295 * Up |(Uk) IDLE(Uk)*4 (Uk) IDLE(L+,Ps,Pk)/(Uk)*a
296 * |
297 * Delay |- - IDLE(L+) IDLE(L+,Ps)
298 * Magic Key |COMMAND*5
299 *
300 * *1: ignore Fn if other key is down.
301 * *2: register Fnk if any key is pressing
302 * *3: register/unregister delayed Fnk and move to IDLE if code == delayed Fnk, else *8
303 * *4: if no keys registered to host
304 * *5: unregister all keys
305 * *6: only if no keys down
306 * *7: ignore Fn because Fnk key and stored key are down.
307 * *8: move to IDLE if layer switch(off) occurs, else stay at current state
308 * *9: repeat key if pressing Fnk twice quickly(move to PRESSING)
309 * *a: layer switch and process waiting key and code if code == wainting key, else unregister key
310 *
311 * States:
312 * IDLE: No key is down except modifiers
313 * DELAYING: delay layer switch after pressing Fn with alt keycode
314 * WAITING: key is pressed during DELAYING
315 *
316 * Events:
317 * Fn: Fn key without alternative keycode
318 * Fnk: Fn key with alternative keycode
319 * -: ignore
320 * Delay: layer switch delay term is elapsed
321 *
322 * Actions:
323 * Rk: register key
324 * Uk: unregister key
325 * Rf: register Fn(alt keycode)
326 * Uf: unregister Fn(alt keycode)
327 * Rs: register stored key
328 * Us: unregister stored key
329 * Sk: Store key(waiting Key)
330 * Sf: Store Fn(delayed Fn)
331 * Ps: Process stored key
332 * Ps: Process key
333 * Is: Interpret stored keys in current layer
334 * L+: Switch to new layer(*unregister* all keys but modifiers)
335 * L-: Switch back to last layer(*unregister* all keys but modifiers)
336 * Ld: Switch back to default layer(*unregister* all keys but modifiers)
337 */
338#define NEXT(state) do { \
339 Kdebug("NEXT: "); Kdebug_P(state_str(kbdstate)); \
340 kbdstate = state; \
341 Kdebug(" -> "); Kdebug_P(state_str(kbdstate)); Kdebug("\n"); \
342} while (0)
343
344static inline void process_key(keyevent_t event)
345{
346 uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col);
347 keykind_t kind = get_keykind(code, event.pressed);
348
349 uint8_t tmp_mods;
350
351 Kdebug("state: "); Kdebug_P(state_str(kbdstate));
352 Kdebug(" kind: "); Kdebug_hex(kind);
353 Kdebug(" code: "); Kdebug_hex(code);
354 if (event.pressed) { Kdebug("d"); } else { Kdebug("u"); }
355 Kdebug("\n");
356
357 switch (kbdstate) {
358 case IDLE:
359 switch (kind) {
360 case FN_DOWN:
361 layer_switch_on(code);
362 break;
363 case FN_UP:
364 layer_switch_off(code);
365 break;
366 case FNK_DOWN:
367 // repeat Fn alt key when press Fn key down, up then down again quickly
368 if (KEYEQ(delayed_fn.event.key, event.key) &&
369 timer_elapsed(delayed_fn.time) < LAYER_DELAY) {
370 register_code(code);
371 NEXT(PRESSING);
372 } else {
373 delayed_fn = (keyrecord_t) {
374 .event = event,
375 .code = code,
376 .mods = keyboard_report->mods,
377 .time = timer_read()
378 };
379 NEXT(DELAYING);
380 }
381 break;
382 case FNK_UP:
383 layer_switch_off(code);
384 break;
385 case KEY_DOWN:
386 register_code(code);
387 NEXT(PRESSING);
388 break;
389 case MOD_DOWN:
390 register_code(code);
391 break;
392 case KEY_UP:
393 case MOD_UP:
394 unregister_code(code);
395 break;
396 default:
397 break;
398 }
399 break;
400 case PRESSING:
401 switch (kind) {
402 case FN_DOWN:
403 // ignored when any key is pressed
404 break;
405 case FN_UP:
406 if (layer_switch_off(code))
407 NEXT(IDLE);
408 break;
409 case FNK_DOWN:
410 register_code(code);
411 break;
412 case FNK_UP:
413 if (layer_switch_off(code)) {
414 NEXT(IDLE);
415 } else {
416 unregister_code(code);
417 if (!anykey_sent_to_host())
418 NEXT(IDLE);
419 }
420 break;
421 case KEY_DOWN:
422 case MOD_DOWN:
423 register_code(code);
424 break;
425 case KEY_UP:
426 case MOD_UP:
427 unregister_code(code);
428 if (!anykey_sent_to_host())
429 NEXT(IDLE);
430 break;
431 default:
432 break;
433 }
434 break;
435 case DELAYING:
436 switch (kind) {
437 case FN_DOWN:
438 case FNK_DOWN:
439 case KEY_DOWN:
440 waiting_key = (keyrecord_t) {
441 .event = event,
442 .code = code,
443 .mods = keyboard_report->mods,
444 .time = timer_read()
445 };
446 NEXT(WAITING);
447 break;
448 case MOD_DOWN:
449 register_code(code);
450 break;
451 case FN_UP:
452 if (layer_switch_off(code))
453 NEXT(IDLE);
454 break;
455 case FNK_UP:
456 if (code == delayed_fn.code) {
457 // type Fn with alt keycode
458 // restore the mod status at the time of pressing Fn key
459 tmp_mods = keyboard_report->mods;
460 host_set_mods(delayed_fn.mods);
461 register_code(delayed_fn.code);
462 unregister_code(delayed_fn.code);
463 host_set_mods(tmp_mods);
464 NEXT(IDLE);
465 } else {
466 if (layer_switch_off(code))
467 NEXT(IDLE);
468 }
469 break;
470 case KEY_UP:
471 case MOD_UP:
472 unregister_code(code);
473 break;
474 default:
475 break;
476 }
477 break;
478 case WAITING:
479 switch (kind) {
480 case FN_DOWN:
481 case FNK_DOWN:
482 case KEY_DOWN:
483 tmp_mods = keyboard_report->mods;
484 host_set_mods(delayed_fn.mods);
485 register_code(delayed_fn.code);
486 host_set_mods(waiting_key.mods);
487 register_code(waiting_key.code);
488 host_set_mods(tmp_mods);
489 if (kind == FN_DOWN) {
490 // ignore Fn
491 } else if (kind == FNK_DOWN) {
492 register_code(code);
493 } else if (kind == KEY_DOWN) {
494 register_code(code);
495 }
496 NEXT(IDLE);
497 break;
498 case MOD_DOWN:
499 register_code(code);
500 break;
501 case FN_UP:
502 if (layer_switch_off(code))
503 NEXT(IDLE);
504 break;
505 case FNK_UP:
506 if (code == delayed_fn.code) {
507 // alt down, key down, alt up
508 tmp_mods = keyboard_report->mods;
509 host_set_mods(delayed_fn.mods);
510 register_code(delayed_fn.code);
511 host_set_mods(waiting_key.mods);
512 register_code(waiting_key.code);
513 unregister_code(delayed_fn.code);
514 host_set_mods(tmp_mods);
515 NEXT(IDLE);
516 } else {
517 if (layer_switch_off(code))
518 NEXT(IDLE);
519 }
520 break;
521 case KEY_UP:
522 if (code == waiting_key.code) {
523 layer_switch_on(delayed_fn.code);
524 NEXT(IDLE);
525 // process waiting_key
526 tmp_mods = keyboard_report->mods;
527 host_set_mods(waiting_key.mods);
528 process_key(waiting_key.event);
529 host_set_mods(tmp_mods);
530 process_key(event);
531 } else {
532 unregister_code(code);
533 }
534 break;
535 case MOD_UP:
536 unregister_code(code);
537 break;
538 default:
539 break;
540 }
541 break;
542 }
543}
544
545void keyboard_init(void) 34void keyboard_init(void)
546{ 35{
547 // TODO: to enable debug print magic key bind on boot time 36 // TODO: to enable debug print magic key bind on boot time
@@ -556,6 +45,10 @@ void keyboard_init(void)
556#endif 45#endif
557} 46}
558 47
48/*
49 * Do keyboard routine jobs: scan mantrix, light LEDs, ...
50 * This is repeatedly called as fast as possible.
51 */
559void keyboard_task(void) 52void keyboard_task(void)
560{ 53{
561 static matrix_row_t matrix_prev[MATRIX_ROWS]; 54 static matrix_row_t matrix_prev[MATRIX_ROWS];
@@ -572,8 +65,8 @@ void keyboard_task(void)
572 65
573 for (int c = 0; c < MATRIX_COLS; c++) { 66 for (int c = 0; c < MATRIX_COLS; c++) {
574 if (matrix_change & (1<<c)) { 67 if (matrix_change & (1<<c)) {
575 process_key((keyevent_t){ 68 keymap_process_event((keyevent_t){
576 .key = (key_t){ .row = r, .col = c }, 69 .key = (keypos_t){ .row = r, .col = c },
577 .pressed = (matrix_row & (1<<c)) 70 .pressed = (matrix_row & (1<<c))
578 }); 71 });
579 // record a processed key 72 // record a processed key
@@ -586,42 +79,11 @@ void keyboard_task(void)
586 } 79 }
587 MATRIX_LOOP_END: 80 MATRIX_LOOP_END:
588 81
589 // layer switch when delay term elapses
590 if (kbdstate == DELAYING || kbdstate == WAITING) {
591 if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) {
592 if (kbdstate == DELAYING) {
593 layer_switch_on(delayed_fn.code);
594 NEXT(IDLE);
595 }
596 if (kbdstate == WAITING) {
597 layer_switch_on(delayed_fn.code);
598 NEXT(IDLE);
599 uint8_t tmp_mods = keyboard_report->mods;
600 host_set_mods(waiting_key.mods);
601 process_key(waiting_key.event);
602 host_set_mods(tmp_mods);
603 }
604 }
605 }
606
607#ifdef MOUSEKEY_ENABLE 82#ifdef MOUSEKEY_ENABLE
608 // mousekey repeat & acceleration 83 // mousekey repeat & acceleration
609 mousekey_task(); 84 mousekey_task();
610#endif 85#endif
611 86
612 // FAIL SAFE: clear all key if no key down
613 if (matrix_change) {
614 matrix_row_t is_matrix_on = 0;
615 for (int r = 0; r < MATRIX_ROWS; r++) {
616 is_matrix_on |= matrix_get_row(r);
617 }
618 if (!is_matrix_on) {
619 Kdebug("FAIL SAFE: clear all keys(default layer).\n");
620 clear_keyboard();
621 current_layer = default_layer;
622 }
623 }
624
625 // update LED 87 // update LED
626 if (led_status != host_keyboard_leds()) { 88 if (led_status != host_keyboard_leds()) {
627 led_status = host_keyboard_leds(); 89 led_status = host_keyboard_leds();
diff --git a/common/keyboard.h b/common/keyboard.h
index 2353805e1..37df6a4de 100644
--- a/common/keyboard.h
+++ b/common/keyboard.h
@@ -29,10 +29,10 @@ extern "C" {
29typedef struct { 29typedef struct {
30 uint8_t row; 30 uint8_t row;
31 uint8_t col; 31 uint8_t col;
32} key_t; 32} keypos_t;
33 33
34typedef struct { 34typedef struct {
35 key_t key; 35 keypos_t key;
36 bool pressed; 36 bool pressed;
37} keyevent_t; 37} keyevent_t;
38 38
@@ -45,7 +45,6 @@ typedef struct {
45 45
46#define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col) 46#define KEYEQ(keya, keyb) (keya.row == keyb.row && keya.col == keyb.col)
47 47
48
49extern uint8_t current_layer; 48extern uint8_t current_layer;
50extern uint8_t default_layer; 49extern uint8_t default_layer;
51 50
diff --git a/common/keycode.h b/common/keycode.h
index f9331cdbf..2eec2af85 100644
--- a/common/keycode.h
+++ b/common/keycode.h
@@ -43,6 +43,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
43#define MOD_INDEX(code) ((code) & 0x07) 43#define MOD_INDEX(code) ((code) & 0x07)
44#define FN_BIT(code) (1<<FN_INDEX(code)) 44#define FN_BIT(code) (1<<FN_INDEX(code))
45#define FN_INDEX(code) ((code) - KC_FN0) 45#define FN_INDEX(code) ((code) - KC_FN0)
46#define FN_MIN KC_FN0
47#define FN_MAX KC_FN7
46 48
47 49
48/* 50/*
diff --git a/common/keymap.h b/common/keymap.h
index 7dfd6c2a1..935d886d7 100644
--- a/common/keymap.h
+++ b/common/keymap.h
@@ -20,15 +20,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
20 20
21#include <stdint.h> 21#include <stdint.h>
22#include <stdbool.h> 22#include <stdbool.h>
23#include "action.h"
23 24
24 25/*
25/* keycode in specific layer */ 26 * legacy keymap interface: keycode
27 */
26uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); 28uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
27
28/* layer to move during press Fn key */ 29/* layer to move during press Fn key */
29uint8_t keymap_fn_layer(uint8_t fn_bits); 30uint8_t keymap_fn_layer(uint8_t fn_bits);
30
31/* keycode to send when release Fn key without using */ 31/* keycode to send when release Fn key without using */
32uint8_t keymap_fn_keycode(uint8_t fn_bits); 32uint8_t keymap_fn_keycode(uint8_t fn_bits);
33 33
34/*
35 * new keymap interface: action
36 */
37action_t keymap_get_action(uint8_t layer, uint8_t row, uint8_t col);
38uint8_t keymap_process_event(keyevent_t event);
39
34#endif 40#endif
diff --git a/common/report.h b/common/report.h
index a73e0aba1..e8582d81f 100644
--- a/common/report.h
+++ b/common/report.h
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
19#define REPORT_H 19#define REPORT_H
20 20
21#include <stdint.h> 21#include <stdint.h>
22#include <keycode.h>
22 23
23 24
24/* report id */ 25/* report id */
@@ -97,6 +98,86 @@ typedef struct {
97 int8_t h; 98 int8_t h;
98} __attribute__ ((packed)) report_mouse_t; 99} __attribute__ ((packed)) report_mouse_t;
99 100
101
102static uint16_t key2system(uint8_t key)
103{
104 uint16_t usage = 0;
105 switch (key) {
106 case KC_SYSTEM_POWER:
107 usage = SYSTEM_POWER_DOWN;
108 break;
109 case KC_SYSTEM_SLEEP:
110 usage = SYSTEM_SLEEP;
111 break;
112 case KC_SYSTEM_WAKE:
113 usage = SYSTEM_WAKE_UP;
114 break;
115 }
116 return usage;
117}
118
119static uint16_t key2consumer(uint8_t key)
120{
121 uint16_t usage = 0;
122 switch (key) {
123 case KC_AUDIO_MUTE:
124 usage = AUDIO_MUTE;
125 break;
126 case KC_AUDIO_VOL_UP:
127 usage = AUDIO_VOL_UP;
128 break;
129 case KC_AUDIO_VOL_DOWN:
130 usage = AUDIO_VOL_DOWN;
131 break;
132 case KC_MEDIA_NEXT_TRACK:
133 usage = TRANSPORT_NEXT_TRACK;
134 break;
135 case KC_MEDIA_PREV_TRACK:
136 usage = TRANSPORT_PREV_TRACK;
137 break;
138 case KC_MEDIA_STOP:
139 usage = TRANSPORT_STOP;
140 break;
141 case KC_MEDIA_PLAY_PAUSE:
142 usage = TRANSPORT_PLAY_PAUSE;
143 break;
144 case KC_MEDIA_SELECT:
145 usage = AL_CC_CONFIG;
146 break;
147 case KC_MAIL:
148 usage = AL_EMAIL;
149 break;
150 case KC_CALCULATOR:
151 usage = AL_CALCULATOR;
152 break;
153 case KC_MY_COMPUTER:
154 usage = AL_LOCAL_BROWSER;
155 break;
156 case KC_WWW_SEARCH:
157 usage = AC_SEARCH;
158 break;
159 case KC_WWW_HOME:
160 usage = AC_HOME;
161 break;
162 case KC_WWW_BACK:
163 usage = AC_BACK;
164 break;
165 case KC_WWW_FORWARD:
166 usage = AC_FORWARD;
167 break;
168 case KC_WWW_STOP:
169 usage = AC_STOP;
170 break;
171 case KC_WWW_REFRESH:
172 usage = AC_REFRESH;
173 break;
174 case KC_WWW_FAVORITES:
175 usage = AC_BOOKMARKS;
176 break;
177 }
178 return usage;
179}
180
100#ifdef __cplusplus 181#ifdef __cplusplus
101} 182}
102#endif 183#endif