~ruther/qmk_firmware

16ba9bda5601ebef6e4db04a5ad079af32370815 — tmk 12 years ago e9af482
Add consumer/system usage support.
5 files changed, 141 insertions(+), 38 deletions(-)

M common/host.c
M common/host.h
M common/keyboard.c
M common/mousekey.c
M common/usb_keycodes.h
M common/host.c => common/host.c +8 -0
@@ 69,6 69,14 @@ void host_unregister_key(uint8_t 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 */
void host_add_key(uint8_t key)
{

M common/host.h => common/host.h +1 -0
@@ 42,6 42,7 @@ 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 */
void host_add_key(uint8_t key);

M common/keyboard.c => common/keyboard.c +106 -16
@@ 41,8 41,6 @@ typedef enum keykind {
    FNK_DOWN, FNK_UP,
    KEY_DOWN, KEY_UP,
    MOD_DOWN, MOD_UP,
    MOUSEKEY_DOWN, MOUSEKEY_UP,
    DELAY
} keykind_t;

typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;


@@ 69,15 67,17 @@ static const char *state_str(kbdstate_t state)

static inline keykind_t get_keykind(uint8_t code, bool pressed)
{
    if IS_KEY(code) return (pressed ? KEY_DOWN      : KEY_UP);
    if IS_MOD(code) return (pressed ? MOD_DOWN      : MOD_UP);
    if IS_KEY(code)         return (pressed ? KEY_DOWN : KEY_UP);
    if IS_MOD(code)         return (pressed ? MOD_DOWN : MOD_UP);
    if IS_FN(code) {
        if (keymap_fn_keycode(FN_INDEX(code)))
            return (pressed ? FNK_DOWN : FNK_UP);
        else
            return (pressed ? FN_DOWN : FN_UP);
    }
    if IS_MOUSEKEY(code)    return (pressed ? MOUSEKEY_DOWN : MOUSEKEY_UP);
    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);
    return  NONE;
}



@@ 86,7 86,13 @@ static void layer_switch_on(uint8_t code)
    if (!IS_FN(code)) return;
    fn_state_bits |= FN_BIT(code);
    if (current_layer != keymap_fn_layer(FN_INDEX(code))) {
        //TODO: clear all key execpt Mod key
        // clear all key execpt Mod key
        host_clear_all_keys_but_mods();
        host_system_send(0);
        host_consumer_send(0);
        mousekey_clear();
        mousekey_send();

        debug("Layer Switch(on): "); debug_hex(current_layer);
        current_layer = keymap_fn_layer(FN_INDEX(code));
        debug(" -> "); debug_hex(current_layer); debug("\n");


@@ 98,7 104,13 @@ static void layer_switch_off(uint8_t code)
    if (!IS_FN(code)) return;
    fn_state_bits &= ~FN_BIT(code);
    if (current_layer != keymap_fn_layer(biton(fn_state_bits))) {
        //TODO: clear all key execpt Mod key
        // clear all key execpt Mod key
        host_clear_all_keys_but_mods();
        host_system_send(0);
        host_consumer_send(0);
        mousekey_clear();
        mousekey_send();

        debug("Layer Switch(off): "); debug_hex(current_layer);
        current_layer = keymap_fn_layer(biton(fn_state_bits));
        debug(" -> "); debug_hex(current_layer); debug("\n");


@@ 128,6 140,7 @@ static inline bool is_anykey_down(void)

static void register_code(uint8_t code)
{
debug("register_code\n");
    if IS_KEY(code) {
        host_add_key(code);
        host_send_keyboard_report();


@@ 140,6 153,84 @@ static void register_code(uint8_t code)
        mousekey_on(code);
        mousekey_send();
    }
    else if IS_CONSUMER(code) {
debug("consumer\n");
        uint16_t usage = 0;
        switch (code) {
            case KB_AUDIO_MUTE:
                usage = AUDIO_MUTE;
                break;
            case KB_AUDIO_VOL_UP:
                usage = AUDIO_VOL_UP;
                break;
            case KB_AUDIO_VOL_DOWN:
                usage = AUDIO_VOL_DOWN;
                break;
            case KB_MEDIA_NEXT_TRACK:
                usage = TRANSPORT_NEXT_TRACK;
                break;
            case KB_MEDIA_PREV_TRACK:
                usage = TRANSPORT_PREV_TRACK;
                break;
            case KB_MEDIA_STOP:
                usage = TRANSPORT_STOP;
                break;
            case KB_MEDIA_PLAY_PAUSE:
                usage = TRANSPORT_PLAY_PAUSE;
                break;
            case KB_MEDIA_SELECT:
                usage = AL_CC_CONFIG;
                break;
            case KB_MAIL:
                usage = AL_EMAIL;
                break;
            case KB_CALCULATOR:
                usage = AL_CALCULATOR;
                break;
            case KB_MY_COMPUTER:
                usage = AL_LOCAL_BROWSER;
                break;
            case KB_WWW_SEARCH:
                usage = AC_SEARCH;
                break;
            case KB_WWW_HOME:
                usage = AC_HOME;
                break;
            case KB_WWW_BACK:
                usage = AC_BACK;
                break;
            case KB_WWW_FORWARD:
                usage = AC_FORWARD;
                break;
            case KB_WWW_STOP:
                usage = AC_STOP;
                break;
            case KB_WWW_REFRESH:
                usage = AC_REFRESH;
                break;
            case KB_WWW_FAVORITES:
                usage = AC_BOOKMARKS;
                break;
        }
debug("usage: "); phex16(usage); debug("\n");
        host_consumer_send(usage);
    }
    else if IS_SYSTEM(code) {
        uint16_t usage = 0;
        switch (code) {
            case KB_SYSTEM_POWER:
                usage = SYSTEM_POWER_DOWN;
                break;
            case KB_SYSTEM_SLEEP:
                usage = SYSTEM_SLEEP;
                break;
            case KB_SYSTEM_WAKE:
                usage = SYSTEM_WAKE_UP;
                break;
        }
        host_system_send(usage);
    }

}

static void unregister_code(uint8_t code)


@@ 156,6 247,12 @@ static void unregister_code(uint8_t code)
        mousekey_off(code);
        mousekey_send();
    }
    else if IS_CONSUMER(code) {
        host_consumer_send(0x0000);
    }
    else if IS_SYSTEM(code) {
        host_system_send(0x0000);
    }
}

/*


@@ 254,7 351,6 @@ static inline void process_key(keyevent_t event)
                    layer_switch_off(code);
                    break;
                case KEY_DOWN:
                case MOUSEKEY_DOWN:
                    register_code(code);
                    NEXT(PRESSING);
                    break;


@@ 262,7 358,6 @@ static inline void process_key(keyevent_t event)
                    register_code(code);
                    break;
                case KEY_UP:
                case MOUSEKEY_UP:
                case MOD_UP:
                    unregister_code(code);
                    break;


@@ 283,16 378,16 @@ static inline void process_key(keyevent_t event)
                    register_code(keymap_fn_keycode(FN_INDEX(code)));
                    break;
                case FNK_UP:
                    // can't know whether layer switched or not
                    layer_switch_off(code);
                    unregister_code(keymap_fn_keycode(FN_INDEX(code)));
                    break;
                case KEY_DOWN:
                case MOD_DOWN:
                case MOUSEKEY_DOWN:
                    register_code(code);
                    break;
                case KEY_UP:
                case MOD_UP:
                case MOUSEKEY_UP:
                    unregister_code(code);
                    // no key registered? mousekey, mediakey, systemkey
                    if (!host_has_anykey())


@@ 307,7 402,6 @@ static inline void process_key(keyevent_t event)
                case FN_DOWN:
                case FNK_DOWN:
                case KEY_DOWN:
                case MOUSEKEY_DOWN:
                    waiting_key = (keyrecord_t) {
                        .event = event,
                        .code = code,


@@ 339,7 433,6 @@ static inline void process_key(keyevent_t event)
                    }
                    break;
                case KEY_UP:
                case MOUSEKEY_UP:
                    unregister_code(code);
                    NEXT(IDLE);
                    break;


@@ 355,7 448,6 @@ static inline void process_key(keyevent_t event)
                case FN_DOWN:
                case FNK_DOWN:
                case KEY_DOWN:
                case MOUSEKEY_DOWN:
                    tmp_mods = keyboard_report->mods;
                    host_set_mods(delayed_fn.mods);
                    register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));


@@ 389,7 481,6 @@ static inline void process_key(keyevent_t event)
                    }
                    break;
                case KEY_UP:
                case MOUSEKEY_UP:
                    if (code == waiting_key.code) {
                        layer_switch_on(delayed_fn.code);
                        NEXT(IDLE);


@@ 444,7 535,6 @@ void keyboard_task(void)
        matrix_row = matrix_get_row(r);
        matrix_change = matrix_row ^ matrix_prev[r];
        if (matrix_change) {
            // TODO: print once per scan
            if (debug_matrix) matrix_print();

            for (int c = 0; c < MATRIX_COLS; c++) {

M common/mousekey.c => common/mousekey.c +0 -7
@@ 135,13 135,6 @@ void mousekey_send(void)
void mousekey_clear(void)
{
    report = (report_mouse_t){};
/*
    report.buttons = 0;
    report.x = 0;
    report.y = 0;
    report.v = 0;
    report.h = 0;
*/
}

static void mousekey_debug(void)

M common/usb_keycodes.h => common/usb_keycodes.h +26 -15
@@ 24,15 24,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.


#define IS_ERROR(code)           (KB_ROLL_OVER <= (code) && (code) <= KB_UNDEFINED)
#define IS_ANY(code)             (KB_A         <= (code))
#define IS_ANY(code)             (KB_A         <= (code) && (code) <= 0xFF)
#define IS_KEY(code)             (KB_A         <= (code) && (code) <= KB_EXSEL)
#define IS_MOD(code)             (KB_LCTRL     <= (code) && (code) <= KB_RGUI)

#define IS_FN(code)              (KB_FN0       <= (code) && (code) <= KB_FN7)
#define IS_MOUSEKEY(code)        (KB_MS_UP     <= (code) && (code) <= KB_MS_WH_RIGHT)
#define IS_MOUSEKEY_MOVE(code)   (KB_MS_UP     <= (code) && (code) <= KB_MS_RIGHT)
#define IS_MOUSEKEY_BUTTON(code) (KB_MS_BTN1   <= (code) && (code) <= KB_MS_BTN5)
#define IS_MOUSEKEY_WHEEL(code)  (KB_MS_WH_UP  <= (code) && (code) <= KB_MS_WH_RIGHT)

#define IS_SPECIAL(code)         ((0xB0 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
#define IS_CONSUMER(code)        (KB_MUTE      <= (code) && (code) <= KB_WFAV)
#define IS_SYSTEM(code)          (KB_POWER     <= (code) && (code) <= KB_WAKE)

#define MOD_BIT(code)   (1<<((code) & 0x07))
#define FN_BIT(code)    (1<<((code) - KB_FN0))
#define FN_INDEX(code)  ((code) - KB_FN0)


@@ 137,14 142,16 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.


/* Special keycode */
/* NOTE: 0xA5-DF and 0xE8-FF can be used for internal special purpose */
enum special_keycodes {
    /* System Control */
    KB_SYSTEM_POWER = 0xB0,
    KB_SYSTEM_POWER = 0xA5,
    KB_SYSTEM_SLEEP,
    KB_SYSTEM_WAKE,
    KB_SYSTEM_WAKE,     /* 0xA7 */
                        /* 0xA8-AF */

    /* Consumer Page */
    KB_AUDIO_MUTE,
    KB_AUDIO_MUTE = 0xB0,
    KB_AUDIO_VOL_UP,
    KB_AUDIO_VOL_DOWN,
    KB_MEDIA_NEXT_TRACK,


@@ 157,13 164,14 @@ enum special_keycodes {
    KB_MY_COMPUTER,
    KB_WWW_SEARCH,
    KB_WWW_HOME,
    KB_WWW_BACK,        /* 0xC0 */
    KB_WWW_BACK,
    KB_WWW_FORWARD,
    KB_WWW_STOP,
    KB_WWW_REFRESH,
    KB_WWW_FAVORITES,
    KB_WWW_REFRESH,     /* 0xC0 */
    KB_WWW_FAVORITES,   /* 0xC1 */
                        /* 0xC2-DF vacant for future use */

    /* reserve 0xE0-E7 for Modifiers */
    /* 0xE0-E7 for Modifiers. DO NOT USE. */

    /* Layer Switching */
    KB_FN0 = 0xE8,


@@ 173,7 181,7 @@ enum special_keycodes {
    KB_FN4,
    KB_FN5,
    KB_FN6,
    KB_FN7,
    KB_FN7,             /* 0xEF */

    /* Mousekey */
    KB_MS_UP = 0xF0,


@@ 189,11 197,13 @@ enum special_keycodes {
    KB_MS_WH_UP,
    KB_MS_WH_DOWN,
    KB_MS_WH_LEFT,
    KB_MS_WH_RIGHT,
    KB_MS_WH_RIGHT,     /* 0xFC */
                        /* 0xFD-FF vacant for future use */
};

/* USB HID Keyboard/Keypad Usage(0x07) */
enum keycodes {
    KB_NO = 0,
    KB_NO               = 0x00,
    KB_ROLL_OVER,
    KB_POST_FAIL,
    KB_UNDEFINED,


@@ 357,9 367,10 @@ enum keycodes {
    KB_OPER,
    KB_CLEAR_AGAIN,
    KB_CRSEL,
    KB_EXSEL,
    KB_EXSEL,           /* 0xA4 */

    /* NOTE: 0xA5-DF are used for internal special purpose */

    /* NOTE: 0xB0-DF are used as special_keycodes */
#if 0
    KB_KP_00 = 0xB0,
    KB_KP_000,


@@ 406,7 417,7 @@ enum keycodes {
    KB_KP_BINARY,
    KB_KP_OCTAL,
    KB_KP_DECIMAL,
    KB_KP_HEXADECIMAL,
    KB_KP_HEXADECIMAL,  /* 0xDD */
#endif

    /* Modifiers */


@@ 419,7 430,7 @@ enum keycodes {
    KB_RALT,
    KB_RGUI,

    /* NOTE: 0xE8-FF are used as special_keycodes */
    /* NOTE: 0xE8-FF are used for internal special purpose */ 
};

#endif /* USB_KEYCODES_H */