diff options
Diffstat (limited to 'common/keyboard.c')
| -rwxr-xr-x[-rw-r--r--] | common/keyboard.c | 543 |
1 files changed, 413 insertions, 130 deletions
diff --git a/common/keyboard.c b/common/keyboard.c index 25f32eb02..9f0c27670 100644..100755 --- a/common/keyboard.c +++ b/common/keyboard.c | |||
| @@ -15,15 +15,16 @@ 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/>. | 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ | 16 | */ |
| 17 | #include "keyboard.h" | 17 | #include "keyboard.h" |
| 18 | #include "host.h" | ||
| 19 | #include "layer.h" | ||
| 20 | #include "matrix.h" | 18 | #include "matrix.h" |
| 19 | #include "keymap.h" | ||
| 20 | #include "host.h" | ||
| 21 | #include "led.h" | 21 | #include "led.h" |
| 22 | #include "usb_keycodes.h" | 22 | #include "usb_keycodes.h" |
| 23 | #include "timer.h" | 23 | #include "timer.h" |
| 24 | #include "print.h" | 24 | #include "print.h" |
| 25 | #include "debug.h" | 25 | #include "debug.h" |
| 26 | #include "command.h" | 26 | #include "command.h" |
| 27 | #include "util.h" | ||
| 27 | #ifdef MOUSEKEY_ENABLE | 28 | #ifdef MOUSEKEY_ENABLE |
| 28 | #include "mousekey.h" | 29 | #include "mousekey.h" |
| 29 | #endif | 30 | #endif |
| @@ -32,162 +33,444 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 32 | #endif | 33 | #endif |
| 33 | 34 | ||
| 34 | 35 | ||
| 35 | static uint8_t last_leds = 0; | 36 | #define LAYER_DELAY 250 |
| 36 | 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 | MOUSEKEY_DOWN, MOUSEKEY_UP, | ||
| 45 | DELAY | ||
| 46 | } keykind_t; | ||
| 37 | 47 | ||
| 38 | void keyboard_init(void) | 48 | typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t; |
| 49 | |||
| 50 | |||
| 51 | uint8_t current_layer = 0; | ||
| 52 | uint8_t default_layer = 0; | ||
| 53 | |||
| 54 | /* keyboard internal states */ | ||
| 55 | static kbdstate_t kbdstate = IDLE; | ||
| 56 | static uint8_t fn_state_bits = 0; | ||
| 57 | static keyrecord_t delayed_fn; | ||
| 58 | static keyrecord_t waiting_key; | ||
| 59 | |||
| 60 | |||
| 61 | static const char *state_str(kbdstate_t state) | ||
| 39 | { | 62 | { |
| 40 | timer_init(); | 63 | if (state == IDLE) return PSTR("IDLE"); |
| 41 | matrix_init(); | 64 | if (state == DELAYING) return PSTR("DELAYING"); |
| 42 | #ifdef PS2_MOUSE_ENABLE | 65 | if (state == WAITING) return PSTR("WAITING"); |
| 43 | ps2_mouse_init(); | 66 | if (state == PRESSING) return PSTR("PRESSING"); |
| 44 | #endif | 67 | return PSTR("UNKNOWN"); |
| 45 | } | 68 | } |
| 46 | 69 | ||
| 47 | void keyboard_proc(void) | 70 | static inline keykind_t get_keykind(uint8_t code, bool pressed) |
| 48 | { | 71 | { |
| 49 | uint8_t fn_bits = 0; | 72 | if IS_KEY(code) return (pressed ? KEY_DOWN : KEY_UP); |
| 50 | #ifdef EXTRAKEY_ENABLE | 73 | if IS_MOD(code) return (pressed ? MOD_DOWN : MOD_UP); |
| 51 | uint16_t consumer_code = 0; | 74 | if IS_FN(code) { |
| 52 | uint16_t system_code = 0; | 75 | if (keymap_fn_keycode(FN_INDEX(code))) |
| 53 | #endif | 76 | return (pressed ? FNK_DOWN : FNK_UP); |
| 54 | 77 | else | |
| 55 | matrix_scan(); | 78 | return (pressed ? FN_DOWN : FN_UP); |
| 79 | } | ||
| 80 | if IS_MOUSEKEY(code) return (pressed ? MOUSEKEY_DOWN : MOUSEKEY_UP); | ||
| 81 | return NONE; | ||
| 82 | } | ||
| 56 | 83 | ||
| 57 | if (matrix_is_modified()) { | 84 | static void layer_switch_on(uint8_t code) |
| 58 | if (debug_matrix) matrix_print(); | 85 | { |
| 59 | #ifdef DEBUG_LED | 86 | if (!IS_FN(code)) return; |
| 60 | // LED flash for debug | 87 | fn_state_bits |= FN_BIT(code); |
| 61 | DEBUG_LED_CONFIG; | 88 | if (current_layer != keymap_fn_layer(FN_INDEX(code))) { |
| 62 | DEBUG_LED_ON; | 89 | //TODO: clear all key execpt Mod key |
| 63 | #endif | 90 | debug("Layer Switch(on): "); debug_hex(current_layer); |
| 91 | current_layer = keymap_fn_layer(FN_INDEX(code)); | ||
| 92 | debug(" -> "); debug_hex(current_layer); debug("\n"); | ||
| 64 | } | 93 | } |
| 94 | } | ||
| 65 | 95 | ||
| 66 | if (matrix_has_ghost()) { | 96 | static void layer_switch_off(uint8_t code) |
| 67 | // should send error? | 97 | { |
| 68 | debug("matrix has ghost!!\n"); | 98 | if (!IS_FN(code)) return; |
| 69 | return; | 99 | fn_state_bits &= ~FN_BIT(code); |
| 100 | if (current_layer != keymap_fn_layer(biton(fn_state_bits))) { | ||
| 101 | //TODO: clear all key execpt Mod key | ||
| 102 | debug("Layer Switch(off): "); debug_hex(current_layer); | ||
| 103 | current_layer = keymap_fn_layer(biton(fn_state_bits)); | ||
| 104 | debug(" -> "); debug_hex(current_layer); debug("\n"); | ||
| 70 | } | 105 | } |
| 106 | } | ||
| 71 | 107 | ||
| 72 | host_swap_keyboard_report(); | 108 | static inline uint8_t get_keycode(key_t key) |
| 73 | host_clear_keyboard_report(); | 109 | { |
| 74 | for (int row = 0; row < matrix_rows(); row++) { | 110 | return keymap_get_keycode(current_layer, key.row, key.col); |
| 75 | for (int col = 0; col < matrix_cols(); col++) { | 111 | } |
| 76 | if (!matrix_is_on(row, col)) continue; | 112 | |
| 77 | 113 | // whether any key except modifier is down or not | |
| 78 | uint8_t code = layer_get_keycode(row, col); | 114 | static inline bool is_anykey_down(void) |
| 79 | if (code == KB_NO) { | 115 | { |
| 80 | // do nothing | 116 | for (int r = 0; r < MATRIX_ROWS; r++) { |
| 81 | } else if (IS_MOD(code)) { | 117 | matrix_row_t matrix_row = matrix_get_row(r); |
| 82 | host_add_mod_bit(MOD_BIT(code)); | 118 | for (int c = 0; c < MATRIX_COLS; c++) { |
| 83 | } else if (IS_FN(code)) { | 119 | if (matrix_row && (1<<c)) { |
| 84 | fn_bits |= FN_BIT(code); | 120 | if (IS_KEY(get_keycode((key_t){ .row = r, .col = c }))) { |
| 85 | } | 121 | return true; |
| 86 | // TODO: use table or something | ||
| 87 | #ifdef EXTRAKEY_ENABLE | ||
| 88 | // System Control | ||
| 89 | else if (code == KB_SYSTEM_POWER) { | ||
| 90 | #ifdef HOST_PJRC | ||
| 91 | if (suspend && remote_wakeup) { | ||
| 92 | usb_remote_wakeup(); | ||
| 93 | } | 122 | } |
| 94 | #endif | ||
| 95 | system_code = SYSTEM_POWER_DOWN; | ||
| 96 | } else if (code == KB_SYSTEM_SLEEP) { | ||
| 97 | system_code = SYSTEM_SLEEP; | ||
| 98 | } else if (code == KB_SYSTEM_WAKE) { | ||
| 99 | system_code = SYSTEM_WAKE_UP; | ||
| 100 | } | ||
| 101 | // Consumer Page | ||
| 102 | else if (code == KB_AUDIO_MUTE) { | ||
| 103 | consumer_code = AUDIO_MUTE; | ||
| 104 | } else if (code == KB_AUDIO_VOL_UP) { | ||
| 105 | consumer_code = AUDIO_VOL_UP; | ||
| 106 | } else if (code == KB_AUDIO_VOL_DOWN) { | ||
| 107 | consumer_code = AUDIO_VOL_DOWN; | ||
| 108 | } | 123 | } |
| 109 | else if (code == KB_MEDIA_NEXT_TRACK) { | 124 | } |
| 110 | consumer_code = TRANSPORT_NEXT_TRACK; | 125 | } |
| 111 | } else if (code == KB_MEDIA_PREV_TRACK) { | 126 | return false; |
| 112 | consumer_code = TRANSPORT_PREV_TRACK; | 127 | } |
| 113 | } else if (code == KB_MEDIA_STOP) { | 128 | |
| 114 | consumer_code = TRANSPORT_STOP; | 129 | static void register_code(uint8_t code) |
| 115 | } else if (code == KB_MEDIA_PLAY_PAUSE) { | 130 | { |
| 116 | consumer_code = TRANSPORT_PLAY_PAUSE; | 131 | if IS_KEY(code) { |
| 117 | } else if (code == KB_MEDIA_SELECT) { | 132 | host_add_key(code); |
| 118 | consumer_code = AL_CC_CONFIG; | 133 | host_send_keyboard_report(); |
| 119 | } | 134 | } |
| 120 | else if (code == KB_MAIL) { | 135 | else if IS_MOD(code) { |
| 121 | consumer_code = AL_EMAIL; | 136 | host_add_mod_bit(MOD_BIT(code)); |
| 122 | } else if (code == KB_CALCULATOR) { | 137 | host_send_keyboard_report(); |
| 123 | consumer_code = AL_CALCULATOR; | 138 | } |
| 124 | } else if (code == KB_MY_COMPUTER) { | 139 | else if IS_MOUSEKEY(code) { |
| 125 | consumer_code = AL_LOCAL_BROWSER; | 140 | mousekey_on(code); |
| 126 | } | 141 | mousekey_send(); |
| 127 | else if (code == KB_WWW_SEARCH) { | 142 | } |
| 128 | consumer_code = AC_SEARCH; | 143 | } |
| 129 | } else if (code == KB_WWW_HOME) { | 144 | |
| 130 | consumer_code = AC_HOME; | 145 | static void unregister_code(uint8_t code) |
| 131 | } else if (code == KB_WWW_BACK) { | 146 | { |
| 132 | consumer_code = AC_BACK; | 147 | if IS_KEY(code) { |
| 133 | } else if (code == KB_WWW_FORWARD) { | 148 | host_del_key(code); |
| 134 | consumer_code = AC_FORWARD; | 149 | host_send_keyboard_report(); |
| 135 | } else if (code == KB_WWW_STOP) { | 150 | } |
| 136 | consumer_code = AC_STOP; | 151 | else if IS_MOD(code) { |
| 137 | } else if (code == KB_WWW_REFRESH) { | 152 | host_del_mod_bit(MOD_BIT(code)); |
| 138 | consumer_code = AC_REFRESH; | 153 | host_send_keyboard_report(); |
| 139 | } else if (code == KB_WWW_FAVORITES) { | 154 | } |
| 140 | consumer_code = AC_BOOKMARKS; | 155 | else if IS_MOUSEKEY(code) { |
| 156 | mousekey_off(code); | ||
| 157 | mousekey_send(); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | /* | ||
| 162 | * | ||
| 163 | * Event/State|IDLE DELAYING[f] WAITING[f,k] PRESSING | ||
| 164 | * -----------+------------------------------------------------------------------ | ||
| 165 | * Fn Down |IDLE(L+) WAITING(Sk) WAITING(Sk) - | ||
| 166 | * Up |IDLE(L-) IDLE(L-) IDLE(L-) IDLE(L-) | ||
| 167 | * Fnk Down |DELAYING(Sf) WAITING(Sk) WAINTING(Sk) PRESSING(Rf) | ||
| 168 | * Up |IDLE(L-) IDLE(Rf,Uf) IDLE(Rf,Ps,Uf)*3 PRESSING(Uf) | ||
| 169 | * Key Down |PRESSING(Rk) WAITING(Sk) WAITING(Sk) PRESSING(Rk) | ||
| 170 | * Up |IDLE(Uk) DELAYING(Uk) IDLE(L+,Ps,Uk) IDLE(Uk)*4 | ||
| 171 | * Delay |- IDLE(L+) IDLE(L+,Ps) - | ||
| 172 | * | | ||
| 173 | * No key Down|IDLE(Ld) IDLE(Ld) IDLE(Ld) IDLE(Ld) | ||
| 174 | * | ||
| 175 | * *2: register Fnk if any key is pressing | ||
| 176 | * *3: when Fnk == Stored Fnk, if not ignore. | ||
| 177 | * *4: when no registered key any more | ||
| 178 | * | ||
| 179 | * States: | ||
| 180 | * IDLE: | ||
| 181 | * DELAYING: delay layer switch after pressing Fn with alt keycode | ||
| 182 | * WAITING: key is pressed during DELAYING | ||
| 183 | * | ||
| 184 | * Events: | ||
| 185 | * Fn: Fn key without alternative keycode | ||
| 186 | * Fnk: Fn key with alternative keycode | ||
| 187 | * -: ignore | ||
| 188 | * | ||
| 189 | * Actions: | ||
| 190 | * Rk: register key | ||
| 191 | * Uk: unregister key | ||
| 192 | * Rf: register stored Fn(alt keycode) | ||
| 193 | * Uf: unregister stored Fn(alt keycode) | ||
| 194 | * Rs: register stored key | ||
| 195 | * Us: unregister stored key | ||
| 196 | * Sk: store key | ||
| 197 | * Sf: store Fn | ||
| 198 | * Ps: play stored key(Interpret stored key and transit state) | ||
| 199 | * L+: Switch to new layer(*retain* Modifiers only) | ||
| 200 | * L-: Switch back to last layer(*clear* stored key/Fn, *unregister* all Modifier/key) | ||
| 201 | * Ld: Switch back to default layer(*clear* stored key/Fn, *unregister* all Modifier/key) | ||
| 202 | */ | ||
| 203 | #define NEXT(state) do { \ | ||
| 204 | debug("NEXT: "); print_P(state_str(kbdstate)); \ | ||
| 205 | kbdstate = state; \ | ||
| 206 | debug(" -> "); print_P(state_str(kbdstate)); debug("\n"); \ | ||
| 207 | } while (0) | ||
| 208 | |||
| 209 | static inline void process_key(keyevent_t event) | ||
| 210 | { | ||
| 211 | |||
| 212 | /* TODO: ring buffer | ||
| 213 | static keyrecord_t waiting_keys[5]; | ||
| 214 | static uint8_t waiting_keys_head = 0; | ||
| 215 | static uint8_t waiting_keys_tail = 0; | ||
| 216 | */ | ||
| 217 | |||
| 218 | uint8_t code = get_keycode(event.key); | ||
| 219 | keykind_t kind = get_keykind(code, event.pressed); | ||
| 220 | |||
| 221 | uint8_t tmp_mods; | ||
| 222 | |||
| 223 | //debug("kbdstate: "); debug_hex(kbdstate); | ||
| 224 | debug("state: "); print_P(state_str(kbdstate)); | ||
| 225 | debug(" kind: "); debug_hex(kind); | ||
| 226 | debug(" code: "); debug_hex(code); | ||
| 227 | if (event.pressed) { debug("d"); } else { debug("u"); } | ||
| 228 | debug("\n"); | ||
| 229 | switch (kbdstate) { | ||
| 230 | case IDLE: | ||
| 231 | switch (kind) { | ||
| 232 | case FN_DOWN: | ||
| 233 | layer_switch_on(code); | ||
| 234 | break; | ||
| 235 | case FN_UP: | ||
| 236 | layer_switch_off(code); | ||
| 237 | break; | ||
| 238 | case FNK_DOWN: | ||
| 239 | // store event | ||
| 240 | delayed_fn = (keyrecord_t) { .event = event, .code = code, .mods = keyboard_report->mods, .time = timer_read() }; | ||
| 241 | NEXT(DELAYING); | ||
| 242 | break; | ||
| 243 | case FNK_UP: | ||
| 244 | layer_switch_off(code); | ||
| 245 | break; | ||
| 246 | case KEY_DOWN: | ||
| 247 | case MOUSEKEY_DOWN: | ||
| 248 | register_code(code); | ||
| 249 | NEXT(PRESSING); | ||
| 250 | break; | ||
| 251 | case MOD_DOWN: | ||
| 252 | register_code(code); | ||
| 253 | break; | ||
| 254 | case KEY_UP: | ||
| 255 | case MOUSEKEY_UP: | ||
| 256 | case MOD_UP: | ||
| 257 | unregister_code(code); | ||
| 258 | break; | ||
| 259 | default: | ||
| 260 | break; | ||
| 141 | } | 261 | } |
| 142 | #endif | 262 | break; |
| 143 | else if (IS_KEY(code)) { | 263 | case PRESSING: |
| 144 | host_add_key(code); | 264 | switch (kind) { |
| 265 | case FN_DOWN: | ||
| 266 | // ignored when any key is pressed | ||
| 267 | break; | ||
| 268 | case FN_UP: | ||
| 269 | layer_switch_off(code); | ||
| 270 | NEXT(IDLE); | ||
| 271 | break; | ||
| 272 | case FNK_DOWN: | ||
| 273 | register_code(keymap_fn_keycode(FN_INDEX(code))); | ||
| 274 | break; | ||
| 275 | case FNK_UP: | ||
| 276 | unregister_code(keymap_fn_keycode(FN_INDEX(code))); | ||
| 277 | break; | ||
| 278 | case KEY_DOWN: | ||
| 279 | case MOD_DOWN: | ||
| 280 | case MOUSEKEY_DOWN: | ||
| 281 | register_code(code); | ||
| 282 | break; | ||
| 283 | case KEY_UP: | ||
| 284 | case MOD_UP: | ||
| 285 | case MOUSEKEY_UP: | ||
| 286 | unregister_code(code); | ||
| 287 | // no key registered? mousekey, mediakey, systemkey | ||
| 288 | if (!host_has_anykey()) | ||
| 289 | NEXT(IDLE); | ||
| 290 | break; | ||
| 291 | default: | ||
| 292 | break; | ||
| 145 | } | 293 | } |
| 146 | #ifdef MOUSEKEY_ENABLE | 294 | break; |
| 147 | else if (IS_MOUSEKEY(code)) { | 295 | case DELAYING: |
| 148 | mousekey_decode(code); | 296 | switch (kind) { |
| 297 | case FN_DOWN: | ||
| 298 | case FNK_DOWN: | ||
| 299 | case KEY_DOWN: | ||
| 300 | case MOUSEKEY_DOWN: | ||
| 301 | waiting_key = (keyrecord_t) { .event = event, .code = code, .mods = keyboard_report->mods, .time = timer_read() }; | ||
| 302 | NEXT(WAITING); | ||
| 303 | break; | ||
| 304 | case MOD_DOWN: | ||
| 305 | register_code(code); | ||
| 306 | break; | ||
| 307 | case FN_UP: | ||
| 308 | layer_switch_off(code); | ||
| 309 | NEXT(IDLE); | ||
| 310 | break; | ||
| 311 | case FNK_UP: | ||
| 312 | if (code == delayed_fn.code) { | ||
| 313 | // type Fn with alt keycode | ||
| 314 | // restore the mod status at the time of pressing Fn key | ||
| 315 | tmp_mods = keyboard_report->mods; | ||
| 316 | host_set_mods(delayed_fn.mods); | ||
| 317 | register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); | ||
| 318 | unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); | ||
| 319 | host_set_mods(tmp_mods); | ||
| 320 | NEXT(IDLE); | ||
| 321 | } else { | ||
| 322 | layer_switch_off(code); | ||
| 323 | NEXT(IDLE); | ||
| 324 | } | ||
| 325 | break; | ||
| 326 | case KEY_UP: | ||
| 327 | case MOUSEKEY_UP: | ||
| 328 | unregister_code(code); | ||
| 329 | NEXT(IDLE); | ||
| 330 | break; | ||
| 331 | case MOD_UP: | ||
| 332 | unregister_code(code); | ||
| 333 | break; | ||
| 334 | default: | ||
| 335 | break; | ||
| 149 | } | 336 | } |
| 150 | #endif | 337 | break; |
| 151 | else { | 338 | case WAITING: |
| 152 | debug("ignore keycode: "); debug_hex(code); debug("\n"); | 339 | switch (kind) { |
| 340 | case FN_DOWN: | ||
| 341 | case FNK_DOWN: | ||
| 342 | case KEY_DOWN: | ||
| 343 | case MOUSEKEY_DOWN: | ||
| 344 | tmp_mods = keyboard_report->mods; | ||
| 345 | host_set_mods(delayed_fn.mods); | ||
| 346 | register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); | ||
| 347 | host_set_mods(waiting_key.mods); | ||
| 348 | register_code(waiting_key.code); | ||
| 349 | host_set_mods(tmp_mods); | ||
| 350 | register_code(code); | ||
| 351 | NEXT(IDLE); | ||
| 352 | break; | ||
| 353 | case MOD_DOWN: | ||
| 354 | register_code(code); | ||
| 355 | break; | ||
| 356 | case FN_UP: | ||
| 357 | layer_switch_off(code); | ||
| 358 | NEXT(IDLE); | ||
| 359 | break; | ||
| 360 | case FNK_UP: | ||
| 361 | if (code == delayed_fn.code) { | ||
| 362 | // alt down, key down, alt up | ||
| 363 | tmp_mods = keyboard_report->mods; | ||
| 364 | host_set_mods(delayed_fn.mods); | ||
| 365 | register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); | ||
| 366 | host_set_mods(waiting_key.mods); | ||
| 367 | register_code(waiting_key.code); | ||
| 368 | unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code))); | ||
| 369 | host_set_mods(tmp_mods); | ||
| 370 | NEXT(IDLE); | ||
| 371 | } else { | ||
| 372 | layer_switch_off(code); | ||
| 373 | NEXT(IDLE); | ||
| 374 | } | ||
| 375 | break; | ||
| 376 | case KEY_UP: | ||
| 377 | case MOUSEKEY_UP: | ||
| 378 | if (code == waiting_key.code) { | ||
| 379 | layer_switch_on(delayed_fn.code); | ||
| 380 | NEXT(IDLE); | ||
| 381 | // process waiting_key | ||
| 382 | tmp_mods = keyboard_report->mods; | ||
| 383 | host_set_mods(waiting_key.mods); | ||
| 384 | process_key(waiting_key.event); | ||
| 385 | host_set_mods(tmp_mods); | ||
| 386 | process_key(event); | ||
| 387 | } else { | ||
| 388 | unregister_code(code); | ||
| 389 | } | ||
| 390 | break; | ||
| 391 | case MOD_UP: | ||
| 392 | unregister_code(code); | ||
| 393 | break; | ||
| 394 | default: | ||
| 395 | break; | ||
| 153 | } | 396 | } |
| 154 | } | 397 | break; |
| 155 | } | 398 | } |
| 156 | 399 | ||
| 157 | layer_switching(fn_bits); | 400 | // TODO: FAIL SAFE: unregister all keys when no key down |
| 401 | } | ||
| 402 | |||
| 403 | void keyboard_init(void) | ||
| 404 | { | ||
| 405 | debug_keyboard = true; | ||
| 406 | |||
| 407 | timer_init(); | ||
| 408 | matrix_init(); | ||
| 409 | #ifdef PS2_MOUSE_ENABLE | ||
| 410 | ps2_mouse_init(); | ||
| 411 | #endif | ||
| 412 | } | ||
| 413 | |||
| 414 | void keyboard_task(void) | ||
| 415 | { | ||
| 416 | static matrix_row_t matrix_prev[MATRIX_ROWS]; | ||
| 417 | matrix_row_t matrix_row = 0; | ||
| 418 | matrix_row_t matrix_change = 0; | ||
| 158 | 419 | ||
| 420 | matrix_scan(); | ||
| 159 | if (command_proc()) { | 421 | if (command_proc()) { |
| 422 | debug("COMMAND\n"); | ||
| 423 | // TODO: clear all keys | ||
| 424 | host_clear_keyboard_report(); | ||
| 425 | host_send_keyboard_report(); | ||
| 160 | return; | 426 | return; |
| 161 | } | 427 | } |
| 428 | for (int r = 0; r < MATRIX_ROWS; r++) { | ||
| 429 | matrix_row = matrix_get_row(r); | ||
| 430 | matrix_change = matrix_row ^ matrix_prev[r]; | ||
| 431 | if (matrix_change) { | ||
| 432 | // TODO: print once per scan | ||
| 433 | if (debug_matrix) matrix_print(); | ||
| 162 | 434 | ||
| 163 | // TODO: should send only when changed from last report | 435 | for (int c = 0; c < MATRIX_COLS; c++) { |
| 164 | if (matrix_is_modified()) { | 436 | if (matrix_change & (1<<c)) { |
| 165 | host_send_keyboard_report(); | 437 | process_key((keyevent_t){ |
| 166 | #ifdef EXTRAKEY_ENABLE | 438 | .key = (key_t){ .row = r, .col = c }, |
| 167 | host_consumer_send(consumer_code); | 439 | .pressed = (matrix_row & (1<<c)) |
| 168 | host_system_send(system_code); | 440 | }); |
| 169 | #endif | 441 | // record a processed key |
| 170 | #ifdef DEBUG_LED | 442 | matrix_prev[r] ^= (1<<c); |
| 171 | // LED flash for debug | 443 | // process a key per task call |
| 172 | DEBUG_LED_CONFIG; | 444 | goto MATRIX_LOOP_END; |
| 173 | DEBUG_LED_OFF; | 445 | } |
| 174 | #endif | 446 | } |
| 447 | } | ||
| 175 | } | 448 | } |
| 449 | MATRIX_LOOP_END: | ||
| 450 | // TODO: FAIL SAFE: clear all key if no key down | ||
| 176 | 451 | ||
| 177 | #ifdef MOUSEKEY_ENABLE | 452 | // layer switch when delay term elapses |
| 178 | mousekey_send(); | 453 | if (kbdstate == DELAYING || kbdstate == WAITING) { |
| 179 | #endif | 454 | if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) { |
| 455 | if (kbdstate == DELAYING) { | ||
| 456 | layer_switch_on(delayed_fn.code); | ||
| 457 | NEXT(IDLE); | ||
| 458 | } | ||
| 459 | if (kbdstate == WAITING) { | ||
| 460 | layer_switch_on(delayed_fn.code); | ||
| 461 | NEXT(IDLE); | ||
| 462 | uint8_t tmp_mods = keyboard_report->mods; | ||
| 463 | host_set_mods(waiting_key.mods); | ||
| 464 | process_key(waiting_key.event); | ||
| 465 | host_set_mods(tmp_mods); | ||
| 466 | } | ||
| 467 | } | ||
| 468 | } | ||
| 180 | 469 | ||
| 181 | #ifdef PS2_MOUSE_ENABLE | 470 | // mousekey repeat & acceleration |
| 182 | // TODO: should comform new API | 471 | mousekey_task(); |
| 183 | if (ps2_mouse_read() == 0) | ||
| 184 | ps2_mouse_usb_send(); | ||
| 185 | #endif | ||
| 186 | 472 | ||
| 187 | if (last_leds != host_keyboard_leds()) { | 473 | return; |
| 188 | keyboard_set_leds(host_keyboard_leds()); | ||
| 189 | last_leds = host_keyboard_leds(); | ||
| 190 | } | ||
| 191 | } | 474 | } |
| 192 | 475 | ||
| 193 | void keyboard_set_leds(uint8_t leds) | 476 | void keyboard_set_leds(uint8_t leds) |
