help(); | help(); | ||||
break; | break; | ||||
case KC_B: | case KC_B: | ||||
host_clear_keyboard_report(); | |||||
host_send_keyboard_report(); | |||||
print("jump to bootloader... "); | print("jump to bootloader... "); | ||||
_delay_ms(1000); | _delay_ms(1000); | ||||
bootloader_jump(); // not return | bootloader_jump(); // not return | ||||
break; | break; | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
case KC_N: | case KC_N: | ||||
// send empty report before change | |||||
host_clear_keyboard_report(); | |||||
host_send_keyboard_report(); | |||||
keyboard_nkro = !keyboard_nkro; | keyboard_nkro = !keyboard_nkro; | ||||
if (keyboard_nkro) | if (keyboard_nkro) | ||||
print("NKRO: enabled\n"); | print("NKRO: enabled\n"); | ||||
#endif | #endif | ||||
#ifdef EXTRAKEY_ENABLE | #ifdef EXTRAKEY_ENABLE | ||||
case KC_ESC: | case KC_ESC: | ||||
host_clear_keyboard_report(); | |||||
host_send_keyboard_report(); | |||||
#ifdef HOST_PJRC | #ifdef HOST_PJRC | ||||
if (suspend && remote_wakeup) { | if (suspend && remote_wakeup) { | ||||
usb_remote_wakeup(); | usb_remote_wakeup(); |
/* | /* | ||||
Copyright 2011 Jun Wako <[email protected]> | |||||
Copyright 2011,2012 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | ||||
#endif | #endif | ||||
static host_driver_t *driver; | static host_driver_t *driver; | ||||
static report_keyboard_t report0; | |||||
static report_keyboard_t report1; | |||||
report_keyboard_t *keyboard_report = &report0; | |||||
report_keyboard_t *keyboard_report_prev = &report1; | |||||
report_keyboard_t *keyboard_report = &(report_keyboard_t){}; | |||||
static inline void add_key_byte(uint8_t code); | static inline void add_key_byte(uint8_t code); | ||||
return (*driver->keyboard_leds)(); | return (*driver->keyboard_leds)(); | ||||
} | } | ||||
/* new interface */ | |||||
void host_register_key(uint8_t key) | |||||
{ | |||||
host_add_key(key); | |||||
host_send_keyboard_report(); | |||||
} | |||||
void host_unregister_key(uint8_t key) | |||||
{ | |||||
host_del_key(key); | |||||
host_send_keyboard_report(); | |||||
} | |||||
void host_clear_all_keys_but_mods(void) | |||||
{ | |||||
for (int8_t i = 0; i < REPORT_KEYS; i++) { | |||||
keyboard_report->keys[i] = 0; | |||||
} | |||||
host_send_keyboard_report(); | |||||
} | |||||
/* keyboard report operations */ | /* keyboard report operations */ | ||||
void host_add_key(uint8_t key) | void host_add_key(uint8_t key) | ||||
{ | { | ||||
del_key_byte(key); | del_key_byte(key); | ||||
} | } | ||||
void host_clear_keys(void) | |||||
{ | |||||
for (int8_t i = 0; i < REPORT_KEYS; i++) { | |||||
keyboard_report->keys[i] = 0; | |||||
} | |||||
} | |||||
void host_add_mod_bit(uint8_t mod) | void host_add_mod_bit(uint8_t mod) | ||||
{ | { | ||||
keyboard_report->mods |= mod; | keyboard_report->mods |= mod; | ||||
keyboard_report->mods = mods; | keyboard_report->mods = mods; | ||||
} | } | ||||
void host_add_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
host_add_mod_bit(MOD_BIT(code)); | |||||
} else { | |||||
host_add_key(code); | |||||
} | |||||
} | |||||
void host_del_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
host_del_mod_bit(MOD_BIT(code)); | |||||
} else { | |||||
host_del_key(code); | |||||
} | |||||
} | |||||
void host_swap_keyboard_report(void) | |||||
{ | |||||
uint8_t sreg = SREG; | |||||
cli(); | |||||
report_keyboard_t *tmp = keyboard_report_prev; | |||||
keyboard_report_prev = keyboard_report; | |||||
keyboard_report = tmp; | |||||
SREG = sreg; | |||||
} | |||||
void host_clear_keyboard_report(void) | |||||
void host_clear_mods(void) | |||||
{ | { | ||||
keyboard_report->mods = 0; | keyboard_report->mods = 0; | ||||
for (int8_t i = 0; i < REPORT_KEYS; i++) { | |||||
keyboard_report->keys[i] = 0; | |||||
} | |||||
} | } | ||||
uint8_t host_has_anykey(void) | uint8_t host_has_anykey(void) | ||||
return keyboard_report->keys[0]; | return keyboard_report->keys[0]; | ||||
} | } | ||||
void host_send_keyboard_report(void) | void host_send_keyboard_report(void) | ||||
{ | { | ||||
if (!driver) return; | if (!driver) return; | ||||
} | } | ||||
} | } | ||||
/* send report */ | |||||
void host_keyboard_send(report_keyboard_t *report) | |||||
{ | |||||
if (!driver) return; | |||||
(*driver->send_keyboard)(report); | |||||
} | |||||
void host_mouse_send(report_mouse_t *report) | void host_mouse_send(report_mouse_t *report) | ||||
{ | { | ||||
if (!driver) return; | if (!driver) return; | ||||
static inline void add_key_byte(uint8_t code) | static inline void add_key_byte(uint8_t code) | ||||
{ | { | ||||
// TODO: fix ugly code | |||||
int8_t i = 0; | int8_t i = 0; | ||||
int8_t empty = -1; | int8_t empty = -1; | ||||
for (; i < REPORT_KEYS; i++) { | for (; i < REPORT_KEYS; i++) { | ||||
if (keyboard_report_prev->keys[i] == code) { | |||||
keyboard_report->keys[i] = code; | |||||
if (keyboard_report->keys[i] == code) { | |||||
break; | break; | ||||
} | } | ||||
if (empty == -1 && | |||||
keyboard_report_prev->keys[i] == 0 && | |||||
keyboard_report->keys[i] == 0) { | |||||
if (empty == -1 && keyboard_report->keys[i] == 0) { | |||||
empty = i; | empty = i; | ||||
} | } | ||||
} | } |
extern report_keyboard_t *keyboard_report_prev; | extern report_keyboard_t *keyboard_report_prev; | ||||
/* host driver */ | |||||
void host_set_driver(host_driver_t *driver); | void host_set_driver(host_driver_t *driver); | ||||
host_driver_t *host_get_driver(void); | host_driver_t *host_get_driver(void); | ||||
uint8_t host_keyboard_leds(void); | uint8_t host_keyboard_leds(void); | ||||
/* new interface */ | |||||
void host_register_key(uint8_t key); | |||||
void host_unregister_key(uint8_t key); | |||||
void host_clear_all_keys_but_mods(void); | |||||
/* keyboard report operations */ | /* keyboard report operations */ | ||||
/* key */ | |||||
void host_add_key(uint8_t key); | void host_add_key(uint8_t key); | ||||
void host_del_key(uint8_t key); | void host_del_key(uint8_t key); | ||||
void host_clear_keys(void); | |||||
/* modifier */ | |||||
void host_add_mod_bit(uint8_t mod); | void host_add_mod_bit(uint8_t mod); | ||||
void host_del_mod_bit(uint8_t mod); | void host_del_mod_bit(uint8_t mod); | ||||
void host_set_mods(uint8_t mods); | void host_set_mods(uint8_t mods); | ||||
void host_add_code(uint8_t code); | |||||
void host_del_code(uint8_t code); | |||||
void host_swap_keyboard_report(void); | |||||
void host_clear_keyboard_report(void); | |||||
void host_clear_mods(void); | |||||
/* query */ | |||||
uint8_t host_has_anykey(void); | uint8_t host_has_anykey(void); | ||||
uint8_t host_get_first_key(void); | uint8_t host_get_first_key(void); | ||||
/* send report */ | |||||
void host_send_keyboard_report(void); | |||||
void host_send_keyboard_report(void); | |||||
/* send report: mouse, system contorl and consumer page */ | |||||
void host_mouse_send(report_mouse_t *report); | void host_mouse_send(report_mouse_t *report); | ||||
void host_system_send(uint16_t data); | void host_system_send(uint16_t data); | ||||
void host_consumer_send(uint16_t data); | void host_consumer_send(uint16_t data); |
return NONE; | return NONE; | ||||
} | } | ||||
static void clear_keyboard(void) | |||||
{ | |||||
host_clear_keys(); | |||||
host_clear_mods(); | |||||
host_send_keyboard_report(); | |||||
host_system_send(0); | |||||
host_consumer_send(0); | |||||
mousekey_clear(); | |||||
mousekey_send(); | |||||
} | |||||
static void clear_keyboard_but_mods(void) | |||||
{ | |||||
host_clear_keys(); | |||||
host_send_keyboard_report(); | |||||
host_system_send(0); | |||||
host_consumer_send(0); | |||||
mousekey_clear(); | |||||
mousekey_send(); | |||||
} | |||||
static void layer_switch_on(uint8_t code) | static void layer_switch_on(uint8_t code) | ||||
{ | { | ||||
if (!IS_FN(code)) return; | if (!IS_FN(code)) return; | ||||
fn_state_bits |= FN_BIT(code); | fn_state_bits |= FN_BIT(code); | ||||
if (current_layer != keymap_fn_layer(FN_INDEX(code))) { | if (current_layer != keymap_fn_layer(FN_INDEX(code))) { | ||||
// clear all key execpt Mod key | |||||
host_clear_all_keys_but_mods(); | |||||
host_system_send(0); | |||||
host_consumer_send(0); | |||||
mousekey_clear(); | |||||
mousekey_send(); | |||||
clear_keyboard_but_mods(); | |||||
debug("Layer Switch(on): "); debug_hex(current_layer); | debug("Layer Switch(on): "); debug_hex(current_layer); | ||||
current_layer = keymap_fn_layer(FN_INDEX(code)); | current_layer = keymap_fn_layer(FN_INDEX(code)); | ||||
if (!IS_FN(code)) return; | if (!IS_FN(code)) return; | ||||
fn_state_bits &= ~FN_BIT(code); | fn_state_bits &= ~FN_BIT(code); | ||||
if (current_layer != keymap_fn_layer(biton(fn_state_bits))) { | if (current_layer != keymap_fn_layer(biton(fn_state_bits))) { | ||||
// clear all key execpt Mod key | |||||
host_clear_all_keys_but_mods(); | |||||
host_system_send(0); | |||||
host_consumer_send(0); | |||||
mousekey_clear(); | |||||
mousekey_send(); | |||||
clear_keyboard_but_mods(); | |||||
debug("Layer Switch(off): "); debug_hex(current_layer); | debug("Layer Switch(off): "); debug_hex(current_layer); | ||||
current_layer = keymap_fn_layer(biton(fn_state_bits)); | current_layer = keymap_fn_layer(biton(fn_state_bits)); | ||||
} | } | ||||
} | } | ||||
static inline uint8_t get_keycode(key_t key) | |||||
{ | |||||
return keymap_get_keycode(current_layer, key.row, key.col); | |||||
} | |||||
// whether any key except modifier is down or not | // whether any key except modifier is down or not | ||||
static inline bool is_anykey_down(void) | static inline bool is_anykey_down(void) | ||||
{ | { | ||||
matrix_row_t matrix_row = matrix_get_row(r); | matrix_row_t matrix_row = matrix_get_row(r); | ||||
for (int c = 0; c < MATRIX_COLS; c++) { | for (int c = 0; c < MATRIX_COLS; c++) { | ||||
if (matrix_row && (1<<c)) { | if (matrix_row && (1<<c)) { | ||||
if (IS_KEY(get_keycode((key_t){ .row = r, .col = c }))) { | |||||
if (IS_KEY(keymap_get_keycode(current_layer, r, c))) { | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
static void register_code(uint8_t code) | static void register_code(uint8_t code) | ||||
{ | { | ||||
debug("register_code\n"); | |||||
if IS_KEY(code) { | if IS_KEY(code) { | ||||
host_add_key(code); | host_add_key(code); | ||||
host_send_keyboard_report(); | host_send_keyboard_report(); | ||||
mousekey_send(); | mousekey_send(); | ||||
} | } | ||||
else if IS_CONSUMER(code) { | else if IS_CONSUMER(code) { | ||||
debug("consumer\n"); | |||||
uint16_t usage = 0; | uint16_t usage = 0; | ||||
switch (code) { | switch (code) { | ||||
case KC_AUDIO_MUTE: | case KC_AUDIO_MUTE: | ||||
usage = AC_BOOKMARKS; | usage = AC_BOOKMARKS; | ||||
break; | break; | ||||
} | } | ||||
debug("usage: "); phex16(usage); debug("\n"); | |||||
host_consumer_send(usage); | host_consumer_send(usage); | ||||
} | } | ||||
else if IS_SYSTEM(code) { | else if IS_SYSTEM(code) { | ||||
* Sk: store key | * Sk: store key | ||||
* Sf: store Fn | * Sf: store Fn | ||||
* Ps: play stored key(Interpret stored key and transit state) | * Ps: play stored key(Interpret stored key and transit state) | ||||
* L+: Switch to new layer(*retain* Modifiers only) | |||||
* L-: Switch back to last layer(*clear* stored key/Fn, *unregister* all Modifier/key) | |||||
* Ld: Switch back to default layer(*clear* stored key/Fn, *unregister* all Modifier/key) | |||||
* 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) | |||||
*/ | */ | ||||
#define NEXT(state) do { \ | #define NEXT(state) do { \ | ||||
debug("NEXT: "); print_P(state_str(kbdstate)); \ | debug("NEXT: "); print_P(state_str(kbdstate)); \ | ||||
static inline void process_key(keyevent_t event) | static inline void process_key(keyevent_t event) | ||||
{ | { | ||||
/* TODO: ring buffer | |||||
static keyrecord_t waiting_keys[5]; | |||||
static uint8_t waiting_keys_head = 0; | |||||
static uint8_t waiting_keys_tail = 0; | |||||
*/ | |||||
uint8_t code = get_keycode(event.key); | |||||
uint8_t code = keymap_get_keycode(current_layer, event.key.row, event.key.col); | |||||
keykind_t kind = get_keykind(code, event.pressed); | keykind_t kind = get_keykind(code, event.pressed); | ||||
uint8_t tmp_mods; | uint8_t tmp_mods; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
// TODO: FAIL SAFE: unregister all keys when no key down | |||||
} | } | ||||
void keyboard_init(void) | void keyboard_init(void) | ||||
matrix_scan(); | matrix_scan(); | ||||
if (command_proc()) { | if (command_proc()) { | ||||
debug("COMMAND\n"); | debug("COMMAND\n"); | ||||
// TODO: clear all keys | |||||
host_clear_keyboard_report(); | |||||
host_send_keyboard_report(); | |||||
// TODO: COMMAND state? | |||||
clear_keyboard(); | |||||
return; | return; | ||||
} | } | ||||
for (int r = 0; r < MATRIX_ROWS; r++) { | for (int r = 0; r < MATRIX_ROWS; r++) { | ||||
matrix_row = matrix_get_row(r); | matrix_row = matrix_get_row(r); | ||||
matrix_change = matrix_row ^ matrix_prev[r]; | matrix_change = matrix_row ^ matrix_prev[r]; | ||||
} | } | ||||
} | } | ||||
MATRIX_LOOP_END: | MATRIX_LOOP_END: | ||||
// TODO: FAIL SAFE: clear all key if no key down | |||||
// layer switch when delay term elapses | // layer switch when delay term elapses | ||||
if (kbdstate == DELAYING || kbdstate == WAITING) { | if (kbdstate == DELAYING || kbdstate == WAITING) { | ||||
// mousekey repeat & acceleration | // mousekey repeat & acceleration | ||||
mousekey_task(); | mousekey_task(); | ||||
// 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) { | |||||
debug("FAIL SAFE: clear all keys.\n"); | |||||
clear_keyboard(); | |||||
} | |||||
} | |||||
return; | return; | ||||
} | } | ||||
/* key combination for command */ | /* key combination for command */ | ||||
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT))) | |||||
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) | |||||
/* mouse keys */ | /* mouse keys */ | ||||
#ifdef MOUSEKEY_ENABLE | #ifdef MOUSEKEY_ENABLE |
if(rq->bRequest == USBRQ_HID_GET_REPORT){ | if(rq->bRequest == USBRQ_HID_GET_REPORT){ | ||||
debug("GET_REPORT:"); | debug("GET_REPORT:"); | ||||
/* we only have one report type, so don't look at wValue */ | /* we only have one report type, so don't look at wValue */ | ||||
usbMsgPtr = (void *)keyboard_report_prev; | |||||
return sizeof(*keyboard_report_prev); | |||||
usbMsgPtr = (void *)keyboard_report; | |||||
return sizeof(*keyboard_report); | |||||
}else if(rq->bRequest == USBRQ_HID_GET_IDLE){ | }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ | ||||
debug("GET_IDLE: "); | debug("GET_IDLE: "); | ||||
//debug_hex(vusb_idle_rate); | //debug_hex(vusb_idle_rate); |