2011-07-20 15:32:52 +00:00
/*
Copyright 2011 Jun Wako < wakojun @ gmail . com >
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2011-02-10 06:51:30 +00:00
# include "keyboard.h"
2011-02-21 06:43:17 +00:00
# include "matrix.h"
2012-10-05 17:23:12 +00:00
# include "keymap.h"
# include "host.h"
2011-02-08 15:03:58 +00:00
# include "led.h"
2012-10-09 05:36:13 +00:00
# include "keycode.h"
2011-02-10 06:51:30 +00:00
# include "timer.h"
2011-02-08 15:03:58 +00:00
# include "print.h"
2011-02-10 06:51:30 +00:00
# include "debug.h"
# include "command.h"
2012-10-05 17:23:12 +00:00
# include "util.h"
2011-02-10 06:51:30 +00:00
# ifdef MOUSEKEY_ENABLE
# include "mousekey.h"
# endif
2011-02-08 15:03:58 +00:00
2012-10-16 18:44:01 +00:00
# define Kdebug(s) do { if (debug_keyboard) debug(s); } while(0)
# define Kdebug_P(s) do { if (debug_keyboard) debug_P(s); } while(0)
# define Kdebug_hex(s) do { if (debug_keyboard) debug_hex(s); } while(0)
2012-10-05 17:23:12 +00:00
# define LAYER_DELAY 250
2011-02-08 15:03:58 +00:00
2012-10-05 17:23:12 +00:00
typedef enum keykind {
NONE ,
FN_DOWN , FN_UP ,
FNK_DOWN , FNK_UP ,
KEY_DOWN , KEY_UP ,
MOD_DOWN , MOD_UP ,
} keykind_t ;
2011-02-08 15:03:58 +00:00
2012-10-05 17:23:12 +00:00
typedef enum { IDLE , DELAYING , WAITING , PRESSING } kbdstate_t ;
2012-10-12 02:00:52 +00:00
# ifdef KEYMAP_DEFAULT_LAYER
uint8_t default_layer = KEYMAP_DEFAULT_LAYER ;
uint8_t current_layer = KEYMAP_DEFAULT_LAYER ;
# else
2012-10-05 17:23:12 +00:00
uint8_t default_layer = 0 ;
2012-10-12 02:00:52 +00:00
uint8_t current_layer = 0 ;
# endif
2012-10-05 17:23:12 +00:00
/* keyboard internal states */
static kbdstate_t kbdstate = IDLE ;
static uint8_t fn_state_bits = 0 ;
static keyrecord_t delayed_fn ;
static keyrecord_t waiting_key ;
static const char * state_str ( kbdstate_t state )
2011-02-08 15:03:58 +00:00
{
2012-10-05 17:23:12 +00:00
if ( state = = IDLE ) return PSTR ( " IDLE " ) ;
if ( state = = DELAYING ) return PSTR ( " DELAYING " ) ;
if ( state = = WAITING ) return PSTR ( " WAITING " ) ;
if ( state = = PRESSING ) return PSTR ( " PRESSING " ) ;
return PSTR ( " UNKNOWN " ) ;
2011-02-08 15:03:58 +00:00
}
2012-10-05 17:23:12 +00:00
static inline keykind_t get_keykind ( uint8_t code , bool pressed )
2011-02-08 15:03:58 +00:00
{
2012-10-09 04:48:39 +00:00
if IS_KEY ( code ) return ( pressed ? KEY_DOWN : KEY_UP ) ;
if IS_MOD ( code ) return ( pressed ? MOD_DOWN : MOD_UP ) ;
2012-10-05 17:23:12 +00:00
if IS_FN ( code ) {
if ( keymap_fn_keycode ( FN_INDEX ( code ) ) )
return ( pressed ? FNK_DOWN : FNK_UP ) ;
else
return ( pressed ? FN_DOWN : FN_UP ) ;
}
2012-10-09 04:48:39 +00:00
if IS_MOUSEKEY ( code ) return ( pressed ? KEY_DOWN : KEY_UP ) ;
if IS_SYSTEM ( code ) return ( pressed ? KEY_DOWN : KEY_UP ) ;
if IS_CONSUMER ( code ) return ( pressed ? KEY_DOWN : KEY_UP ) ;
2012-10-05 17:23:12 +00:00
return NONE ;
}
2011-02-10 06:51:30 +00:00
2012-10-09 07:50:14 +00:00
static void clear_keyboard ( void )
{
host_clear_keys ( ) ;
host_clear_mods ( ) ;
host_send_keyboard_report ( ) ;
host_system_send ( 0 ) ;
host_consumer_send ( 0 ) ;
2012-10-10 02:06:47 +00:00
# ifdef MOUSEKEY_ENABLE
2012-10-09 07:50:14 +00:00
mousekey_clear ( ) ;
mousekey_send ( ) ;
2012-10-10 02:06:47 +00:00
# endif
2012-10-09 07:50:14 +00:00
}
static void clear_keyboard_but_mods ( void )
{
host_clear_keys ( ) ;
host_send_keyboard_report ( ) ;
host_system_send ( 0 ) ;
host_consumer_send ( 0 ) ;
2012-10-10 02:06:47 +00:00
# ifdef MOUSEKEY_ENABLE
2012-10-09 07:50:14 +00:00
mousekey_clear ( ) ;
mousekey_send ( ) ;
2012-10-10 02:06:47 +00:00
# endif
2012-10-09 07:50:14 +00:00
}
2012-10-11 19:46:37 +00:00
static bool anykey_sent_to_host ( void )
{
return ( host_has_anykey ( ) | | host_mouse_in_use ( ) | |
host_last_sysytem_report ( ) | | host_last_consumer_report ( ) ) ;
}
2012-10-05 17:23:12 +00:00
static void layer_switch_on ( uint8_t code )
{
if ( ! IS_FN ( code ) ) return ;
fn_state_bits | = FN_BIT ( code ) ;
2012-10-12 02:00:52 +00:00
uint8_t new_layer = ( fn_state_bits ? keymap_fn_layer ( biton ( fn_state_bits ) ) : default_layer ) ;
if ( current_layer ! = new_layer ) {
2012-10-16 18:44:01 +00:00
Kdebug ( " Layer Switch(on): " ) ; Kdebug_hex ( current_layer ) ;
Kdebug ( " -> " ) ; Kdebug_hex ( new_layer ) ; Kdebug ( " \n " ) ;
2012-10-12 02:00:52 +00:00
clear_keyboard_but_mods ( ) ;
current_layer = new_layer ;
2011-02-08 15:03:58 +00:00
}
2012-10-05 17:23:12 +00:00
}
2011-02-10 06:51:30 +00:00
2012-10-11 19:46:37 +00:00
static bool layer_switch_off ( uint8_t code )
2012-10-05 17:23:12 +00:00
{
2012-10-11 19:46:37 +00:00
if ( ! IS_FN ( code ) ) return false ;
2012-10-05 17:23:12 +00:00
fn_state_bits & = ~ FN_BIT ( code ) ;
2012-10-12 02:00:52 +00:00
uint8_t new_layer = ( fn_state_bits ? keymap_fn_layer ( biton ( fn_state_bits ) ) : default_layer ) ;
if ( current_layer ! = new_layer ) {
2012-10-16 18:44:01 +00:00
Kdebug ( " Layer Switch(off): " ) ; Kdebug_hex ( current_layer ) ;
Kdebug ( " -> " ) ; Kdebug_hex ( new_layer ) ; Kdebug ( " \n " ) ;
2012-10-12 02:00:52 +00:00
clear_keyboard_but_mods ( ) ;
current_layer = new_layer ;
2012-10-11 19:46:37 +00:00
return true ;
2012-10-05 17:23:12 +00:00
}
return false ;
}
static void register_code ( uint8_t code )
{
if IS_KEY ( code ) {
2012-10-16 18:44:01 +00:00
if ( ! command_proc ( code ) ) {
2012-10-16 02:20:49 +00:00
host_add_key ( code ) ;
host_send_keyboard_report ( ) ;
}
2012-10-05 17:23:12 +00:00
}
else if IS_MOD ( code ) {
host_add_mod_bit ( MOD_BIT ( code ) ) ;
host_send_keyboard_report ( ) ;
}
2012-10-11 19:46:37 +00:00
else if IS_FN ( code ) {
2012-10-16 18:44:01 +00:00
if ( ! command_proc ( keymap_fn_keycode ( FN_INDEX ( code ) ) ) ) {
host_add_key ( keymap_fn_keycode ( FN_INDEX ( code ) ) ) ;
host_send_keyboard_report ( ) ;
}
2012-10-11 19:46:37 +00:00
}
2012-10-05 17:23:12 +00:00
else if IS_MOUSEKEY ( code ) {
2012-10-10 02:06:47 +00:00
# ifdef MOUSEKEY_ENABLE
2012-10-05 17:23:12 +00:00
mousekey_on ( code ) ;
mousekey_send ( ) ;
2012-10-10 02:06:47 +00:00
# endif
2012-10-05 17:23:12 +00:00
}
2012-10-09 04:48:39 +00:00
else if IS_CONSUMER ( code ) {
uint16_t usage = 0 ;
switch ( code ) {
2012-10-09 05:36:13 +00:00
case KC_AUDIO_MUTE :
2012-10-09 04:48:39 +00:00
usage = AUDIO_MUTE ;
break ;
2012-10-09 05:36:13 +00:00
case KC_AUDIO_VOL_UP :
2012-10-09 04:48:39 +00:00
usage = AUDIO_VOL_UP ;
break ;
2012-10-09 05:36:13 +00:00
case KC_AUDIO_VOL_DOWN :
2012-10-09 04:48:39 +00:00
usage = AUDIO_VOL_DOWN ;
break ;
2012-10-09 05:36:13 +00:00
case KC_MEDIA_NEXT_TRACK :
2012-10-09 04:48:39 +00:00
usage = TRANSPORT_NEXT_TRACK ;
break ;
2012-10-09 05:36:13 +00:00
case KC_MEDIA_PREV_TRACK :
2012-10-09 04:48:39 +00:00
usage = TRANSPORT_PREV_TRACK ;
break ;
2012-10-09 05:36:13 +00:00
case KC_MEDIA_STOP :
2012-10-09 04:48:39 +00:00
usage = TRANSPORT_STOP ;
break ;
2012-10-09 05:36:13 +00:00
case KC_MEDIA_PLAY_PAUSE :
2012-10-09 04:48:39 +00:00
usage = TRANSPORT_PLAY_PAUSE ;
break ;
2012-10-09 05:36:13 +00:00
case KC_MEDIA_SELECT :
2012-10-09 04:48:39 +00:00
usage = AL_CC_CONFIG ;
break ;
2012-10-09 05:36:13 +00:00
case KC_MAIL :
2012-10-09 04:48:39 +00:00
usage = AL_EMAIL ;
break ;
2012-10-09 05:36:13 +00:00
case KC_CALCULATOR :
2012-10-09 04:48:39 +00:00
usage = AL_CALCULATOR ;
break ;
2012-10-09 05:36:13 +00:00
case KC_MY_COMPUTER :
2012-10-09 04:48:39 +00:00
usage = AL_LOCAL_BROWSER ;
break ;
2012-10-09 05:36:13 +00:00
case KC_WWW_SEARCH :
2012-10-09 04:48:39 +00:00
usage = AC_SEARCH ;
break ;
2012-10-09 05:36:13 +00:00
case KC_WWW_HOME :
2012-10-09 04:48:39 +00:00
usage = AC_HOME ;
break ;
2012-10-09 05:36:13 +00:00
case KC_WWW_BACK :
2012-10-09 04:48:39 +00:00
usage = AC_BACK ;
break ;
2012-10-09 05:36:13 +00:00
case KC_WWW_FORWARD :
2012-10-09 04:48:39 +00:00
usage = AC_FORWARD ;
break ;
2012-10-09 05:36:13 +00:00
case KC_WWW_STOP :
2012-10-09 04:48:39 +00:00
usage = AC_STOP ;
break ;
2012-10-09 05:36:13 +00:00
case KC_WWW_REFRESH :
2012-10-09 04:48:39 +00:00
usage = AC_REFRESH ;
break ;
2012-10-09 05:36:13 +00:00
case KC_WWW_FAVORITES :
2012-10-09 04:48:39 +00:00
usage = AC_BOOKMARKS ;
break ;
}
host_consumer_send ( usage ) ;
}
else if IS_SYSTEM ( code ) {
uint16_t usage = 0 ;
switch ( code ) {
2012-10-09 05:36:13 +00:00
case KC_SYSTEM_POWER :
2012-10-09 04:48:39 +00:00
usage = SYSTEM_POWER_DOWN ;
break ;
2012-10-09 05:36:13 +00:00
case KC_SYSTEM_SLEEP :
2012-10-09 04:48:39 +00:00
usage = SYSTEM_SLEEP ;
break ;
2012-10-09 05:36:13 +00:00
case KC_SYSTEM_WAKE :
2012-10-09 04:48:39 +00:00
usage = SYSTEM_WAKE_UP ;
break ;
}
host_system_send ( usage ) ;
}
2012-10-05 17:23:12 +00:00
}
static void unregister_code ( uint8_t code )
{
if IS_KEY ( code ) {
host_del_key ( code ) ;
host_send_keyboard_report ( ) ;
}
else if IS_MOD ( code ) {
host_del_mod_bit ( MOD_BIT ( code ) ) ;
host_send_keyboard_report ( ) ;
}
2012-10-11 19:46:37 +00:00
else if IS_FN ( code ) {
host_del_key ( keymap_fn_keycode ( FN_INDEX ( code ) ) ) ;
host_send_keyboard_report ( ) ;
}
2012-10-05 17:23:12 +00:00
else if IS_MOUSEKEY ( code ) {
2012-10-10 02:06:47 +00:00
# ifdef MOUSEKEY_ENABLE
2012-10-05 17:23:12 +00:00
mousekey_off ( code ) ;
mousekey_send ( ) ;
2012-10-10 02:06:47 +00:00
# endif
2012-10-05 17:23:12 +00:00
}
2012-10-09 04:48:39 +00:00
else if IS_CONSUMER ( code ) {
host_consumer_send ( 0x0000 ) ;
}
else if IS_SYSTEM ( code ) {
host_system_send ( 0x0000 ) ;
}
2012-10-05 17:23:12 +00:00
}
/*
*
2012-10-11 19:46:37 +00:00
* Event / State | IDLE PRESSING DELAYING [ f ] WAITING [ f , k ]
2012-10-05 17:23:12 +00:00
* - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2012-10-11 19:46:37 +00:00
* Fn Down | ( L + ) - * 1 WAITING ( Sk ) IDLE ( Rf , Ps ) * 7
* Up | ( L - ) IDLE ( L - ) * 8 IDLE ( L - ) * 8 IDLE ( L - ) * 8
* Fnk Down | DELAYING ( Sf ) * ( Rf ) WAITING ( Sk ) IDLE ( Rf , Ps , Rf )
* Up | ( L - ) IDLE ( L - / Uf ) * 8 IDLE ( Rf , Uf / L - ) * 3 IDLE ( Rf , Ps , Uf / L - ) * 3
* Key Down | PRESSING ( Rk ) ( Rk ) WAITING ( Sk ) IDLE ( Rf , Ps , Rk )
* Up | ( Uk ) IDLE ( Uk ) * 4 ( Uk ) IDLE ( L + , Ps , Pk ) / ( Uk ) * a
2012-10-05 17:23:12 +00:00
* |
2012-10-11 19:46:37 +00:00
* Delay | - - IDLE ( L + ) IDLE ( L + , Ps )
* Magic Key | COMMAND * 5
2012-10-05 17:23:12 +00:00
*
2012-10-11 19:46:37 +00:00
* * 1 : ignore Fn if other key is down .
2012-10-05 17:23:12 +00:00
* * 2 : register Fnk if any key is pressing
2012-10-11 19:46:37 +00:00
* * 3 : register / unregister delayed Fnk and move to IDLE if code = = delayed Fnk , else * 8
* * 4 : if no keys registered to host
* * 5 : unregister all keys
* * 6 : only if no keys down
* * 7 : ignore Fn because Fnk key and stored key are down .
* * 8 : move to IDLE if layer switch ( off ) occurs , else stay at current state
* * 9 : repeat key if pressing Fnk twice quickly ( move to PRESSING )
* * a : layer switch and process waiting key and code if code = = wainting key , else unregister key
2012-10-05 17:23:12 +00:00
*
* States :
2012-10-11 19:46:37 +00:00
* IDLE : No key is down except modifiers
2012-10-05 17:23:12 +00:00
* DELAYING : delay layer switch after pressing Fn with alt keycode
* WAITING : key is pressed during DELAYING
*
* Events :
* Fn : Fn key without alternative keycode
* Fnk : Fn key with alternative keycode
* - : ignore
2012-10-11 19:46:37 +00:00
* Delay : layer switch delay term is elapsed
2012-10-05 17:23:12 +00:00
*
* Actions :
* Rk : register key
* Uk : unregister key
2012-10-11 19:46:37 +00:00
* Rf : register Fn ( alt keycode )
* Uf : unregister Fn ( alt keycode )
2012-10-05 17:23:12 +00:00
* Rs : register stored key
* Us : unregister stored key
2012-10-11 19:46:37 +00:00
* Sk : Store key ( waiting Key )
* Sf : Store Fn ( delayed Fn )
* Ps : Process stored key
* Ps : Process key
* Is : Interpret stored keys in current layer
2012-10-09 07:50:14 +00:00
* L + : Switch to new layer ( * unregister * all keys but modifiers )
* L - : Switch back to last layer ( * unregister * all keys but modifiers )
* Ld : Switch back to default layer ( * unregister * all keys but modifiers )
2012-10-05 17:23:12 +00:00
*/
# define NEXT(state) do { \
2012-10-16 18:44:01 +00:00
Kdebug ( " NEXT: " ) ; Kdebug_P ( state_str ( kbdstate ) ) ; \
2012-10-05 17:23:12 +00:00
kbdstate = state ; \
2012-10-16 18:44:01 +00:00
Kdebug ( " -> " ) ; Kdebug_P ( state_str ( kbdstate ) ) ; Kdebug ( " \n " ) ; \
2012-10-05 17:23:12 +00:00
} while ( 0 )
static inline void process_key ( keyevent_t event )
{
2012-10-09 07:50:14 +00:00
uint8_t code = keymap_get_keycode ( current_layer , event . key . row , event . key . col ) ;
2012-10-05 17:23:12 +00:00
keykind_t kind = get_keykind ( code , event . pressed ) ;
uint8_t tmp_mods ;
2012-10-16 18:44:01 +00:00
Kdebug ( " state: " ) ; Kdebug_P ( state_str ( kbdstate ) ) ;
Kdebug ( " kind: " ) ; Kdebug_hex ( kind ) ;
Kdebug ( " code: " ) ; Kdebug_hex ( code ) ;
if ( event . pressed ) { Kdebug ( " d " ) ; } else { Kdebug ( " u " ) ; }
Kdebug ( " \n " ) ;
2012-10-07 03:25:18 +00:00
2012-10-05 17:23:12 +00:00
switch ( kbdstate ) {
case IDLE :
switch ( kind ) {
case FN_DOWN :
layer_switch_on ( code ) ;
break ;
case FN_UP :
layer_switch_off ( code ) ;
break ;
case FNK_DOWN :
2012-10-07 03:25:18 +00:00
// repeat Fn alt key when press Fn key down, up then down again quickly
if ( KEYEQ ( delayed_fn . event . key , event . key ) & &
timer_elapsed ( delayed_fn . time ) < LAYER_DELAY ) {
2012-10-11 19:46:37 +00:00
register_code ( code ) ;
2012-10-07 03:25:18 +00:00
NEXT ( PRESSING ) ;
} else {
delayed_fn = ( keyrecord_t ) {
. event = event ,
. code = code ,
. mods = keyboard_report - > mods ,
. time = timer_read ( )
} ;
NEXT ( DELAYING ) ;
}
2012-10-05 17:23:12 +00:00
break ;
case FNK_UP :
layer_switch_off ( code ) ;
break ;
case KEY_DOWN :
register_code ( code ) ;
NEXT ( PRESSING ) ;
break ;
case MOD_DOWN :
register_code ( code ) ;
break ;
case KEY_UP :
case MOD_UP :
unregister_code ( code ) ;
break ;
default :
break ;
2011-02-10 06:51:30 +00:00
}
2012-10-05 17:23:12 +00:00
break ;
case PRESSING :
switch ( kind ) {
case FN_DOWN :
// ignored when any key is pressed
break ;
case FN_UP :
2012-10-11 19:46:37 +00:00
if ( layer_switch_off ( code ) )
NEXT ( IDLE ) ;
2012-10-05 17:23:12 +00:00
break ;
case FNK_DOWN :
2012-10-11 19:46:37 +00:00
register_code ( code ) ;
2012-10-05 17:23:12 +00:00
break ;
case FNK_UP :
2012-10-11 19:46:37 +00:00
if ( layer_switch_off ( code ) ) {
NEXT ( IDLE ) ;
} else {
unregister_code ( code ) ;
if ( ! anykey_sent_to_host ( ) )
NEXT ( IDLE ) ;
}
2012-10-05 17:23:12 +00:00
break ;
case KEY_DOWN :
case MOD_DOWN :
register_code ( code ) ;
break ;
case KEY_UP :
case MOD_UP :
unregister_code ( code ) ;
2012-10-11 19:46:37 +00:00
if ( ! anykey_sent_to_host ( ) )
2012-10-05 17:23:12 +00:00
NEXT ( IDLE ) ;
break ;
default :
break ;
2011-02-10 06:51:30 +00:00
}
2012-10-05 17:23:12 +00:00
break ;
case DELAYING :
switch ( kind ) {
case FN_DOWN :
case FNK_DOWN :
case KEY_DOWN :
2012-10-07 03:25:18 +00:00
waiting_key = ( keyrecord_t ) {
. event = event ,
. code = code ,
. mods = keyboard_report - > mods ,
. time = timer_read ( )
} ;
2012-10-05 17:23:12 +00:00
NEXT ( WAITING ) ;
break ;
case MOD_DOWN :
register_code ( code ) ;
break ;
case FN_UP :
2012-10-11 19:46:37 +00:00
if ( layer_switch_off ( code ) )
NEXT ( IDLE ) ;
2012-10-05 17:23:12 +00:00
break ;
case FNK_UP :
if ( code = = delayed_fn . code ) {
// type Fn with alt keycode
// restore the mod status at the time of pressing Fn key
tmp_mods = keyboard_report - > mods ;
host_set_mods ( delayed_fn . mods ) ;
2012-10-11 19:46:37 +00:00
register_code ( delayed_fn . code ) ;
unregister_code ( delayed_fn . code ) ;
2012-10-05 17:23:12 +00:00
host_set_mods ( tmp_mods ) ;
NEXT ( IDLE ) ;
} else {
2012-10-11 19:46:37 +00:00
if ( layer_switch_off ( code ) )
NEXT ( IDLE ) ;
2012-10-05 17:23:12 +00:00
}
break ;
case KEY_UP :
case MOD_UP :
unregister_code ( code ) ;
break ;
default :
break ;
2011-02-10 06:51:30 +00:00
}
2012-10-05 17:23:12 +00:00
break ;
case WAITING :
switch ( kind ) {
case FN_DOWN :
case FNK_DOWN :
case KEY_DOWN :
tmp_mods = keyboard_report - > mods ;
host_set_mods ( delayed_fn . mods ) ;
2012-10-11 19:46:37 +00:00
register_code ( delayed_fn . code ) ;
2012-10-05 17:23:12 +00:00
host_set_mods ( waiting_key . mods ) ;
register_code ( waiting_key . code ) ;
host_set_mods ( tmp_mods ) ;
2012-10-11 19:46:37 +00:00
if ( kind = = FN_DOWN ) {
// ignore Fn
} else if ( kind = = FNK_DOWN ) {
register_code ( code ) ;
} else if ( kind = = KEY_DOWN ) {
register_code ( code ) ;
}
2012-10-05 17:23:12 +00:00
NEXT ( IDLE ) ;
break ;
case MOD_DOWN :
register_code ( code ) ;
break ;
case FN_UP :
2012-10-11 19:46:37 +00:00
if ( layer_switch_off ( code ) )
NEXT ( IDLE ) ;
2012-10-05 17:23:12 +00:00
break ;
case FNK_UP :
if ( code = = delayed_fn . code ) {
// alt down, key down, alt up
tmp_mods = keyboard_report - > mods ;
host_set_mods ( delayed_fn . mods ) ;
2012-10-11 19:46:37 +00:00
register_code ( delayed_fn . code ) ;
2012-10-05 17:23:12 +00:00
host_set_mods ( waiting_key . mods ) ;
register_code ( waiting_key . code ) ;
2012-10-11 19:46:37 +00:00
unregister_code ( delayed_fn . code ) ;
2012-10-05 17:23:12 +00:00
host_set_mods ( tmp_mods ) ;
NEXT ( IDLE ) ;
} else {
2012-10-11 19:46:37 +00:00
if ( layer_switch_off ( code ) )
NEXT ( IDLE ) ;
2012-10-05 17:23:12 +00:00
}
break ;
case KEY_UP :
if ( code = = waiting_key . code ) {
layer_switch_on ( delayed_fn . code ) ;
NEXT ( IDLE ) ;
// process waiting_key
tmp_mods = keyboard_report - > mods ;
host_set_mods ( waiting_key . mods ) ;
process_key ( waiting_key . event ) ;
host_set_mods ( tmp_mods ) ;
process_key ( event ) ;
} else {
unregister_code ( code ) ;
}
break ;
case MOD_UP :
unregister_code ( code ) ;
break ;
default :
break ;
2011-02-10 06:51:30 +00:00
}
2012-10-05 17:23:12 +00:00
break ;
2011-02-08 15:03:58 +00:00
}
2012-10-05 17:23:12 +00:00
}
void keyboard_init ( void )
{
debug_keyboard = true ;
timer_init ( ) ;
matrix_init ( ) ;
# ifdef PS2_MOUSE_ENABLE
ps2_mouse_init ( ) ;
# endif
}
void keyboard_task ( void )
{
static matrix_row_t matrix_prev [ MATRIX_ROWS ] ;
2012-10-21 13:12:36 +00:00
static uint8_t led_status = 0 ;
2012-10-05 17:23:12 +00:00
matrix_row_t matrix_row = 0 ;
matrix_row_t matrix_change = 0 ;
2011-02-08 15:03:58 +00:00
2012-10-05 17:23:12 +00:00
matrix_scan ( ) ;
for ( int r = 0 ; r < MATRIX_ROWS ; r + + ) {
matrix_row = matrix_get_row ( r ) ;
matrix_change = matrix_row ^ matrix_prev [ r ] ;
if ( matrix_change ) {
2012-10-17 15:10:20 +00:00
if ( debug_matrix ) matrix_print ( ) ;
2011-02-08 15:03:58 +00:00
2012-10-05 17:23:12 +00:00
for ( int c = 0 ; c < MATRIX_COLS ; c + + ) {
if ( matrix_change & ( 1 < < c ) ) {
process_key ( ( keyevent_t ) {
. key = ( key_t ) { . row = r , . col = c } ,
. pressed = ( matrix_row & ( 1 < < c ) )
} ) ;
// record a processed key
matrix_prev [ r ] ^ = ( 1 < < c ) ;
// process a key per task call
goto MATRIX_LOOP_END ;
}
}
}
2011-02-08 15:03:58 +00:00
}
2012-10-05 17:23:12 +00:00
MATRIX_LOOP_END :
2011-02-08 15:03:58 +00:00
2012-10-05 17:23:12 +00:00
// layer switch when delay term elapses
if ( kbdstate = = DELAYING | | kbdstate = = WAITING ) {
if ( timer_elapsed ( delayed_fn . time ) > LAYER_DELAY ) {
if ( kbdstate = = DELAYING ) {
layer_switch_on ( delayed_fn . code ) ;
NEXT ( IDLE ) ;
}
if ( kbdstate = = WAITING ) {
layer_switch_on ( delayed_fn . code ) ;
NEXT ( IDLE ) ;
uint8_t tmp_mods = keyboard_report - > mods ;
host_set_mods ( waiting_key . mods ) ;
process_key ( waiting_key . event ) ;
host_set_mods ( tmp_mods ) ;
}
}
}
2011-02-08 15:03:58 +00:00
2012-10-10 02:06:47 +00:00
# ifdef MOUSEKEY_ENABLE
2012-10-05 17:23:12 +00:00
// mousekey repeat & acceleration
mousekey_task ( ) ;
2012-10-10 02:06:47 +00:00
# endif
2011-02-10 06:51:30 +00:00
2012-10-09 07:50:14 +00:00
// FAIL SAFE: clear all key if no key down
if ( matrix_change ) {
matrix_row_t is_matrix_on = 0 ;
for ( int r = 0 ; r < MATRIX_ROWS ; r + + ) {
is_matrix_on | = matrix_get_row ( r ) ;
}
if ( ! is_matrix_on ) {
2012-10-16 18:44:01 +00:00
Kdebug ( " FAIL SAFE: clear all keys(default layer). \n " ) ;
2012-10-09 07:50:14 +00:00
clear_keyboard ( ) ;
2012-10-12 02:00:52 +00:00
current_layer = default_layer ;
2012-10-09 07:50:14 +00:00
}
}
2012-10-16 02:20:49 +00:00
2012-10-21 13:12:36 +00:00
// update LED
if ( led_status ! = host_keyboard_leds ( ) ) {
led_status = host_keyboard_leds ( ) ;
keyboard_set_leds ( led_status ) ;
}
2012-10-05 17:23:12 +00:00
return ;
2011-02-08 15:03:58 +00:00
}
2011-02-12 15:15:51 +00:00
void keyboard_set_leds ( uint8_t leds )
{
led_set ( leds ) ;
}