diff options
Diffstat (limited to 'quantum/send_string')
| -rw-r--r-- | quantum/send_string/send_string.c | 324 | ||||
| -rw-r--r-- | quantum/send_string/send_string.h | 152 | ||||
| -rw-r--r-- | quantum/send_string/send_string_keycodes.h | 434 | 
3 files changed, 910 insertions, 0 deletions
| diff --git a/quantum/send_string/send_string.c b/quantum/send_string/send_string.c new file mode 100644 index 0000000000..818a52f6dc --- /dev/null +++ b/quantum/send_string/send_string.c @@ -0,0 +1,324 @@ +/* Copyright 2021 + * + * 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/>. + */ + +#include <ctype.h> + +#include "quantum.h" + +#include "send_string.h" + +#if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL) +#    include "audio.h" +#    ifndef BELL_SOUND +#        define BELL_SOUND TERMINAL_SOUND +#    endif +float bell_song[][2] = SONG(BELL_SOUND); +#endif + +// clang-format off + +/* Bit-Packed look-up table to convert an ASCII character to whether + * [Shift] needs to be sent with the keycode. + */ +__attribute__((weak)) const uint8_t ascii_to_shift_lut[16] PROGMEM = { +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + +    KCLUT_ENTRY(0, 1, 1, 1, 1, 1, 1, 0), +    KCLUT_ENTRY(1, 1, 1, 1, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 1, 0, 1, 0, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 1, 1, 1, 1, 1), +    KCLUT_ENTRY(1, 1, 1, 0, 0, 0, 1, 1), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 1, 1, 1, 1, 0) +}; + +/* Bit-Packed look-up table to convert an ASCII character to whether + * [AltGr] needs to be sent with the keycode. + */ +__attribute__((weak)) const uint8_t ascii_to_altgr_lut[16] PROGMEM = { +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0) +}; + +/* Bit-Packed look-up table to convert an ASCII character to whether + * [Space] needs to be sent after the keycode + */ +__attribute__((weak)) const uint8_t ascii_to_dead_lut[16] PROGMEM = { +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), + +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0), +    KCLUT_ENTRY(0, 0, 0, 0, 0, 0, 0, 0) +}; + +/* Look-up table to convert an ASCII character to a keycode. + */ +__attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = { +    // NUL   SOH      STX      ETX      EOT      ENQ      ACK      BEL +    XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, +    // BS    TAB      LF       VT       FF       CR       SO       SI +    KC_BSPC, KC_TAB,  KC_ENT,  XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, +    // DLE   DC1      DC2      DC3      DC4      NAK      SYN      ETB +    XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, +    // CAN   EM       SUB      ESC      FS       GS       RS       US +    XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC,  XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + +    //       !        "        #        $        %        &        ' +    KC_SPC,  KC_1,    KC_QUOT, KC_3,    KC_4,    KC_5,    KC_7,    KC_QUOT, +    // (     )        *        +        ,        -        .        / +    KC_9,    KC_0,    KC_8,    KC_EQL,  KC_COMM, KC_MINS, KC_DOT,  KC_SLSH, +    // 0     1        2        3        4        5        6        7 +    KC_0,    KC_1,    KC_2,    KC_3,    KC_4,    KC_5,    KC_6,    KC_7, +    // 8     9        :        ;        <        =        >        ? +    KC_8,    KC_9,    KC_SCLN, KC_SCLN, KC_COMM, KC_EQL,  KC_DOT,  KC_SLSH, +    // @     A        B        C        D        E        F        G +    KC_2,    KC_A,    KC_B,    KC_C,    KC_D,    KC_E,    KC_F,    KC_G, +    // H     I        J        K        L        M        N        O +    KC_H,    KC_I,    KC_J,    KC_K,    KC_L,    KC_M,    KC_N,    KC_O, +    // P     Q        R        S        T        U        V        W +    KC_P,    KC_Q,    KC_R,    KC_S,    KC_T,    KC_U,    KC_V,    KC_W, +    // X     Y        Z        [        \        ]        ^        _ +    KC_X,    KC_Y,    KC_Z,    KC_LBRC, KC_BSLS, KC_RBRC, KC_6,    KC_MINS, +    // `     a        b        c        d        e        f        g +    KC_GRV,  KC_A,    KC_B,    KC_C,    KC_D,    KC_E,    KC_F,    KC_G, +    // h     i        j        k        l        m        n        o +    KC_H,    KC_I,    KC_J,    KC_K,    KC_L,    KC_M,    KC_N,    KC_O, +    // p     q        r        s        t        u        v        w +    KC_P,    KC_Q,    KC_R,    KC_S,    KC_T,    KC_U,    KC_V,    KC_W, +    // x     y        z        {        |        }        ~        DEL +    KC_X,    KC_Y,    KC_Z,    KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV,  KC_DEL +}; + +// clang-format on + +// Note: we bit-pack in "reverse" order to optimize loading +#define PGM_LOADBIT(mem, pos) ((pgm_read_byte(&((mem)[(pos) / 8])) >> ((pos) % 8)) & 0x01) + +void send_string(const char *string) { +    send_string_with_delay(string, 0); +} + +void send_string_with_delay(const char *string, uint8_t interval) { +    while (1) { +        char ascii_code = *string; +        if (!ascii_code) break; +        if (ascii_code == SS_QMK_PREFIX) { +            ascii_code = *(++string); +            if (ascii_code == SS_TAP_CODE) { +                // tap +                uint8_t keycode = *(++string); +                tap_code(keycode); +            } else if (ascii_code == SS_DOWN_CODE) { +                // down +                uint8_t keycode = *(++string); +                register_code(keycode); +            } else if (ascii_code == SS_UP_CODE) { +                // up +                uint8_t keycode = *(++string); +                unregister_code(keycode); +            } else if (ascii_code == SS_DELAY_CODE) { +                // delay +                int     ms      = 0; +                uint8_t keycode = *(++string); +                while (isdigit(keycode)) { +                    ms *= 10; +                    ms += keycode - '0'; +                    keycode = *(++string); +                } +                while (ms--) +                    wait_ms(1); +            } +        } else { +            send_char(ascii_code); +        } +        ++string; +        // interval +        { +            uint8_t ms = interval; +            while (ms--) +                wait_ms(1); +        } +    } +} + +void send_char(char ascii_code) { +#if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL) +    if (ascii_code == '\a') { // BEL +        PLAY_SONG(bell_song); +        return; +    } +#endif + +    uint8_t keycode    = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]); +    bool    is_shifted = PGM_LOADBIT(ascii_to_shift_lut, (uint8_t)ascii_code); +    bool    is_altgred = PGM_LOADBIT(ascii_to_altgr_lut, (uint8_t)ascii_code); +    bool    is_dead    = PGM_LOADBIT(ascii_to_dead_lut, (uint8_t)ascii_code); + +    if (is_shifted) { +        register_code(KC_LEFT_SHIFT); +    } +    if (is_altgred) { +        register_code(KC_RIGHT_ALT); +    } +    tap_code(keycode); +    if (is_altgred) { +        unregister_code(KC_RIGHT_ALT); +    } +    if (is_shifted) { +        unregister_code(KC_LEFT_SHIFT); +    } +    if (is_dead) { +        tap_code(KC_SPACE); +    } +} + +void send_dword(uint32_t number) { +    send_word(number >> 16); +    send_word(number & 0xFFFFUL); +} + +void send_word(uint16_t number) { +    send_byte(number >> 8); +    send_byte(number & 0xFF); +} + +void send_byte(uint8_t number) { +    send_nibble(number >> 4); +    send_nibble(number & 0xF); +} + +void send_nibble(uint8_t number) { +    switch (number & 0xF) { +        case 0 ... 9: +            send_char(number + '0'); +            break; +        case 10 ... 15: +            send_char(number - 10 + 'a'); +            break; +    } +} + +void tap_random_base64(void) { +#if defined(__AVR_ATmega32U4__) +    uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64; +#else +    uint8_t key = rand() % 64; +#endif +    switch (key) { +        case 0 ... 25: +            send_char(key + 'A'); +            break; +        case 26 ... 51: +            send_char(key - 26 + 'a'); +            break; +        case 52: +            send_char('0'); +            break; +        case 53 ... 61: +            send_char(key - 53 + '1'); +            break; +        case 62: +            send_char('+'); +            break; +        case 63: +            send_char('/'); +            break; +    } +} + +#if defined(__AVR__) +void send_string_P(const char *string) { +    send_string_with_delay_P(string, 0); +} + +void send_string_with_delay_P(const char *string, uint8_t interval) { +    while (1) { +        char ascii_code = pgm_read_byte(string); +        if (!ascii_code) break; +        if (ascii_code == SS_QMK_PREFIX) { +            ascii_code = pgm_read_byte(++string); +            if (ascii_code == SS_TAP_CODE) { +                // tap +                uint8_t keycode = pgm_read_byte(++string); +                tap_code(keycode); +            } else if (ascii_code == SS_DOWN_CODE) { +                // down +                uint8_t keycode = pgm_read_byte(++string); +                register_code(keycode); +            } else if (ascii_code == SS_UP_CODE) { +                // up +                uint8_t keycode = pgm_read_byte(++string); +                unregister_code(keycode); +            } else if (ascii_code == SS_DELAY_CODE) { +                // delay +                int     ms      = 0; +                uint8_t keycode = pgm_read_byte(++string); +                while (isdigit(keycode)) { +                    ms *= 10; +                    ms += keycode - '0'; +                    keycode = pgm_read_byte(++string); +                } +                while (ms--) +                    wait_ms(1); +            } +        } else { +            send_char(ascii_code); +        } +        ++string; +        // interval +        { +            uint8_t ms = interval; +            while (ms--) +                wait_ms(1); +        } +    } +} +#endif diff --git a/quantum/send_string/send_string.h b/quantum/send_string/send_string.h new file mode 100644 index 0000000000..4eb55b88dc --- /dev/null +++ b/quantum/send_string/send_string.h @@ -0,0 +1,152 @@ +/* Copyright 2021 + * + * 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/>. + */ + +/** + * \defgroup send_string + * + * Send String API. These functions allow you to create macros by typing out sequences of keystrokes. + * \{ + */ + +#include <stdint.h> + +#include "progmem.h" +#include "send_string_keycodes.h" + +// Look-Up Tables (LUTs) to convert ASCII character to keycode sequence. +extern const uint8_t ascii_to_shift_lut[16]; +extern const uint8_t ascii_to_altgr_lut[16]; +extern const uint8_t ascii_to_dead_lut[16]; +extern const uint8_t ascii_to_keycode_lut[128]; + +// clang-format off +#define KCLUT_ENTRY(a, b, c, d, e, f, g, h) \ +    ( ((a) ? 1 : 0) << 0 \ +    | ((b) ? 1 : 0) << 1 \ +    | ((c) ? 1 : 0) << 2 \ +    | ((d) ? 1 : 0) << 3 \ +    | ((e) ? 1 : 0) << 4 \ +    | ((f) ? 1 : 0) << 5 \ +    | ((g) ? 1 : 0) << 6 \ +    | ((h) ? 1 : 0) << 7 ) +// clang-format on + +/** + * \brief Type out a string of ASCII characters. + * + * This function simply calls `send_string_with_delay(string, 0)`. + * + * Most keycodes from the basic keycode range are also supported by way of a special sequence - see `send_string_keycodes.h`. + * + * \param string The string to type out. + */ +void send_string(const char *string); + +/** + * \brief Type out a string of ASCII characters, with a delay between each character. + * + * \param string The string to type out. + * \param interval The amount of time, in milliseconds, to wait before typing the next character. + */ +void send_string_with_delay(const char *string, uint8_t interval); + +/** + * \brief Type out an ASCII character. + * + * \param ascii_code The character to type. + */ +void send_char(char ascii_code); + +/** + * \brief Type out an eight digit (unsigned 32-bit) hexadecimal value. + * + * The format is `[0-9a-f]{8}`, eg. `00000000` through `ffffffff`. + * + * \param number The value to type, from 0 to 4,294,967,295. + */ +void send_dword(uint32_t number); + +/** + * \brief Type out a four digit (unsigned 16-bit) hexadecimal value. + * + * The format is `[0-9a-f]{4}`, eg. `0000` through `ffff`. + * + * \param number The value to type, from 0 to 65,535. + */ +void send_word(uint16_t number); + +/** + * \brief Type out a two digit (8-bit) hexadecimal value. + * + * The format is `[0-9a-f]{2}`, eg. `00` through `ff`. + * + * \param number The value to type, from 0 to 255. + */ +void send_byte(uint8_t number); + +/** + * \brief Type out a single hexadecimal digit. + * + * The format is `[0-9a-f]{1}`, eg. `0` through `f`. + * + * \param number The value to type, from 0 to 15. + */ +void send_nibble(uint8_t number); + +/** + * \brief Type a pseudorandom character from the set `A-Z`, `a-z`, `0-9`, `+` and `/`. + */ +void tap_random_base64(void); + +#if defined(__AVR__) || defined(__DOXYGEN__) +/** + * \brief Type out a PROGMEM string of ASCII characters. + * + * On ARM devices, this function is simply an alias for send_string_with_delay(string, 0). + * + * \param string The string to type out. + */ +void send_string_P(const char *string); + +/** + * \brief Type out a PROGMEM string of ASCII characters, with a delay between each character. + * + * On ARM devices, this function is simply an alias for send_string_with_delay(string, interval). + * + * \param string The string to type out. + * \param interval The amount of time, in milliseconds, to wait before typing the next character. + */ +void send_string_with_delay_P(const char *string, uint8_t interval); +#else +#    define send_string_P(string) send_string_with_delay(string, 0) +#    define send_string_with_delay_P(string, interval) send_string_with_delay(string, interval) +#endif + +/** + * \brief Shortcut macro for send_string_with_delay_P(PSTR(string), 0). + * + * On ARM devices, this define evaluates to send_string_with_delay(string, 0). + */ +#define SEND_STRING(string) send_string_with_delay_P(PSTR(string), 0) + +/** + * \brief Shortcut macro for send_string_with_delay_P(PSTR(string), interval). + * + * On ARM devices, this define evaluates to send_string_with_delay(string, interval). + */ +#define SEND_STRING_DELAY(string, interval) send_string_with_delay_P(PSTR(string), interval) + +/** \} */ diff --git a/quantum/send_string/send_string_keycodes.h b/quantum/send_string/send_string_keycodes.h new file mode 100644 index 0000000000..7017e03d5a --- /dev/null +++ b/quantum/send_string/send_string_keycodes.h @@ -0,0 +1,434 @@ +/* Copyright 2019 + * + * 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/>. + */ + +#pragma once + +// clang-format off + +/* Punctuation */ +#define X_ENT  X_ENTER +#define X_ESC  X_ESCAPE +#define X_BSPC X_BSPACE +#define X_SPC  X_SPACE +#define X_MINS X_MINUS +#define X_EQL  X_EQUAL +#define X_LBRC X_LBRACKET +#define X_RBRC X_RBRACKET +#define X_BSLS X_BSLASH +#define X_NUHS X_NONUS_HASH +#define X_SCLN X_SCOLON +#define X_QUOT X_QUOTE +#define X_GRV  X_GRAVE +#define X_COMM X_COMMA +#define X_SLSH X_SLASH +#define X_NUBS X_NONUS_BSLASH + +/* Lock Keys */ +#define X_CLCK X_CAPSLOCK +#define X_CAPS X_CAPSLOCK +#define X_SLCK X_SCROLLLOCK +#define X_NLCK X_NUMLOCK +#define X_LCAP X_LOCKING_CAPS +#define X_LNUM X_LOCKING_NUM +#define X_LSCR X_LOCKING_SCROLL + +/* Commands */ +#define X_PSCR X_PSCREEN +#define X_PAUS X_PAUSE +#define X_BRK  X_PAUSE +#define X_INS  X_INSERT +#define X_DEL  X_DELETE +#define X_PGDN X_PGDOWN +#define X_RGHT X_RIGHT +#define X_APP  X_APPLICATION +#define X_EXEC X_EXECUTE +#define X_SLCT X_SELECT +#define X_AGIN X_AGAIN +#define X_PSTE X_PASTE +#define X_ERAS X_ALT_ERASE +#define X_CLR  X_CLEAR + +/* Keypad */ +#define X_PSLS X_KP_SLASH +#define X_PAST X_KP_ASTERISK +#define X_PMNS X_KP_MINUS +#define X_PPLS X_KP_PLUS +#define X_PENT X_KP_ENTER +#define X_P1   X_KP_1 +#define X_P2   X_KP_2 +#define X_P3   X_KP_3 +#define X_P4   X_KP_4 +#define X_P5   X_KP_5 +#define X_P6   X_KP_6 +#define X_P7   X_KP_7 +#define X_P8   X_KP_8 +#define X_P9   X_KP_9 +#define X_P0   X_KP_0 +#define X_PDOT X_KP_DOT +#define X_PEQL X_KP_EQUAL +#define X_PCMM X_KP_COMMA + +/* Japanese specific */ +#define X_ZKHK X_GRAVE +#define X_RO   X_INT1 +#define X_KANA X_INT2 +#define X_JYEN X_INT3 +#define X_HENK X_INT4 +#define X_MHEN X_INT5 + +/* Korean specific */ +#define X_HAEN X_LANG1 +#define X_HANJ X_LANG2 + +/* Modifiers */ +#define X_LCTL X_LCTRL +#define X_LSFT X_LSHIFT +#define X_LOPT X_LALT +#define X_LCMD X_LGUI +#define X_LWIN X_LGUI +#define X_RCTL X_RCTRL +#define X_RSFT X_RSHIFT +#define X_ALGR X_RALT +#define X_ROPT X_RALT +#define X_RCMD X_RGUI +#define X_RWIN X_RGUI + +/* Generic Desktop Page (0x01) */ +#define X_PWR  X_SYSTEM_POWER +#define X_SLEP X_SYSTEM_SLEEP +#define X_WAKE X_SYSTEM_WAKE + +/* Consumer Page (0x0C) */ +#define X_MUTE X_AUDIO_MUTE +#define X_VOLU X_AUDIO_VOL_UP +#define X_VOLD X_AUDIO_VOL_DOWN +#define X_MNXT X_MEDIA_NEXT_TRACK +#define X_MPRV X_MEDIA_PREV_TRACK +#define X_MSTP X_MEDIA_STOP +#define X_MPLY X_MEDIA_PLAY_PAUSE +#define X_MSEL X_MEDIA_SELECT +#define X_EJCT X_MEDIA_EJECT +#define X_CALC X_CALCULATOR +#define X_MYCM X_MY_COMPUTER +#define X_WSCH X_WWW_SEARCH +#define X_WHOM X_WWW_HOME +#define X_WBAK X_WWW_BACK +#define X_WFWD X_WWW_FORWARD +#define X_WSTP X_WWW_STOP +#define X_WREF X_WWW_REFRESH +#define X_WFAV X_WWW_FAVORITES +#define X_MFFD X_MEDIA_FAST_FORWARD +#define X_MRWD X_MEDIA_REWIND +#define X_BRIU X_BRIGHTNESS_UP +#define X_BRID X_BRIGHTNESS_DOWN + +/* System Specific */ +#define X_BRMU X_PAUSE +#define X_BRMD X_SCROLLLOCK + +/* Mouse Keys */ +#define X_MS_U X_MS_UP +#define X_MS_D X_MS_DOWN +#define X_MS_L X_MS_LEFT +#define X_MS_R X_MS_RIGHT +#define X_BTN1 X_MS_BTN1 +#define X_BTN2 X_MS_BTN2 +#define X_BTN3 X_MS_BTN3 +#define X_BTN4 X_MS_BTN4 +#define X_BTN5 X_MS_BTN5 +#define X_WH_U X_MS_WH_UP +#define X_WH_D X_MS_WH_DOWN +#define X_WH_L X_MS_WH_LEFT +#define X_WH_R X_MS_WH_RIGHT +#define X_ACL0 X_MS_ACCEL0 +#define X_ACL1 X_MS_ACCEL1 +#define X_ACL2 X_MS_ACCEL2 + +/* Keyboard/Keypad Page (0x07) */ +#define X_A                  04 +#define X_B                  05 +#define X_C                  06 +#define X_D                  07 +#define X_E                  08 +#define X_F                  09 +#define X_G                  0a +#define X_H                  0b +#define X_I                  0c +#define X_J                  0d +#define X_K                  0e +#define X_L                  0f +#define X_M                  10 +#define X_N                  11 +#define X_O                  12 +#define X_P                  13 +#define X_Q                  14 +#define X_R                  15 +#define X_S                  16 +#define X_T                  17 +#define X_U                  18 +#define X_V                  19 +#define X_W                  1a +#define X_X                  1b +#define X_Y                  1c +#define X_Z                  1d +#define X_1                  1e +#define X_2                  1f +#define X_3                  20 +#define X_4                  21 +#define X_5                  22 +#define X_6                  23 +#define X_7                  24 +#define X_8                  25 +#define X_9                  26 +#define X_0                  27 +#define X_ENTER              28 +#define X_ESCAPE             29 +#define X_BSPACE             2a +#define X_TAB                2b +#define X_SPACE              2c +#define X_MINUS              2d +#define X_EQUAL              2e +#define X_LBRACKET           2f +#define X_RBRACKET           30 +#define X_BSLASH             31 +#define X_NONUS_HASH         32 +#define X_SCOLON             33 +#define X_QUOTE              34 +#define X_GRAVE              35 +#define X_COMMA              36 +#define X_DOT                37 +#define X_SLASH              38 +#define X_CAPSLOCK           39 +#define X_F1                 3a +#define X_F2                 3b +#define X_F3                 3c +#define X_F4                 3d +#define X_F5                 3e +#define X_F6                 3f +#define X_F7                 40 +#define X_F8                 41 +#define X_F9                 42 +#define X_F10                43 +#define X_F11                44 +#define X_F12                45 +#define X_PSCREEN            46 +#define X_SCROLLLOCK         47 +#define X_PAUSE              48 +#define X_INSERT             49 +#define X_HOME               4a +#define X_PGUP               4b +#define X_DELETE             4c +#define X_END                4d +#define X_PGDOWN             4e +#define X_RIGHT              4f +#define X_LEFT               50 +#define X_DOWN               51 +#define X_UP                 52 +#define X_NUMLOCK            53 +#define X_KP_SLASH           54 +#define X_KP_ASTERISK        55 +#define X_KP_MINUS           56 +#define X_KP_PLUS            57 +#define X_KP_ENTER           58 +#define X_KP_1               59 +#define X_KP_2               5a +#define X_KP_3               5b +#define X_KP_4               5c +#define X_KP_5               5d +#define X_KP_6               5e +#define X_KP_7               5f +#define X_KP_8               60 +#define X_KP_9               61 +#define X_KP_0               62 +#define X_KP_DOT             63 +#define X_NONUS_BSLASH       64 +#define X_APPLICATION        65 +#define X_POWER              66 +#define X_KP_EQUAL           67 +#define X_F13                68 +#define X_F14                69 +#define X_F15                6a +#define X_F16                6b +#define X_F17                6c +#define X_F18                6d +#define X_F19                6e +#define X_F20                6f +#define X_F21                70 +#define X_F22                71 +#define X_F23                72 +#define X_F24                73 +#define X_EXECUTE            74 +#define X_HELP               75 +#define X_MENU               76 +#define X_SELECT             77 +#define X_STOP               78 +#define X_AGAIN              79 +#define X_UNDO               7a +#define X_CUT                7b +#define X_COPY               7c +#define X_PASTE              7d +#define X_FIND               7e +#define X__MUTE              7f +#define X__VOLUP             80 +#define X__VOLDOWN           81 +#define X_LOCKING_CAPS       82 +#define X_LOCKING_NUM        83 +#define X_LOCKING_SCROLL     84 +#define X_KP_COMMA           85 +#define X_KP_EQUAL_AS400     86 +#define X_INT1               87 +#define X_INT2               88 +#define X_INT3               89 +#define X_INT4               8a +#define X_INT5               8b +#define X_INT6               8c +#define X_INT7               8d +#define X_INT8               8e +#define X_INT9               8f +#define X_LANG1              90 +#define X_LANG2              91 +#define X_LANG3              92 +#define X_LANG4              93 +#define X_LANG5              94 +#define X_LANG6              95 +#define X_LANG7              96 +#define X_LANG8              97 +#define X_LANG9              98 +#define X_ALT_ERASE          99 +#define X_SYSREQ             9a +#define X_CANCEL             9b +#define X_CLEAR              9c +#define X_PRIOR              9d +#define X_RETURN             9e +#define X_SEPARATOR          9f +#define X_OUT                a0 +#define X_OPER               a1 +#define X_CLEAR_AGAIN        a2 +#define X_CRSEL              a3 +#define X_EXSEL              a4 + +/* Modifiers */ +#define X_LCTRL              e0 +#define X_LSHIFT             e1 +#define X_LALT               e2 +#define X_LGUI               e3 +#define X_RCTRL              e4 +#define X_RSHIFT             e5 +#define X_RALT               e6 +#define X_RGUI               e7 + +/* Media and Function keys */ +/* Generic Desktop Page (0x01) */ +#define X_SYSTEM_POWER       a5 +#define X_SYSTEM_SLEEP       a6 +#define X_SYSTEM_WAKE        a7 + +/* Consumer Page (0x0C) */ +#define X_AUDIO_MUTE         a8 +#define X_AUDIO_VOL_UP       a9 +#define X_AUDIO_VOL_DOWN     aa +#define X_MEDIA_NEXT_TRACK   ab +#define X_MEDIA_PREV_TRACK   ac +#define X_MEDIA_STOP         ad +#define X_MEDIA_PLAY_PAUSE   ae +#define X_MEDIA_SELECT       af +#define X_MEDIA_EJECT        b0 +#define X_MAIL               b1 +#define X_CALCULATOR         b2 +#define X_MY_COMPUTER        b3 +#define X_WWW_SEARCH         b4 +#define X_WWW_HOME           b5 +#define X_WWW_BACK           b6 +#define X_WWW_FORWARD        b7 +#define X_WWW_STOP           b8 +#define X_WWW_REFRESH        b9 +#define X_WWW_FAVORITES      ba +#define X_MEDIA_FAST_FORWARD bb +#define X_MEDIA_REWIND       bc +#define X_BRIGHTNESS_UP      bd +#define X_BRIGHTNESS_DOWN    be + +/* Mouse Buttons (unallocated range in HID spec) */ +#ifdef VIA_ENABLE +#define X_MS_UP              f0 +#define X_MS_DOWN            f1 +#define X_MS_LEFT            f2 +#define X_MS_RIGHT           f3 +#define X_MS_BTN1            f4 +#define X_MS_BTN2            f5 +#define X_MS_BTN3            f6 +#define X_MS_BTN4            f7 +#define X_MS_BTN5            f8 +#define X_MS_BTN6            f8 +#define X_MS_BTN7            f8 +#define X_MS_BTN8            f8 +#else +#define X_MS_UP              ed +#define X_MS_DOWN            ee +#define X_MS_LEFT            ef +#define X_MS_RIGHT           f0 +#define X_MS_BTN1            f1 +#define X_MS_BTN2            f2 +#define X_MS_BTN3            f3 +#define X_MS_BTN4            f4 +#define X_MS_BTN5            f5 +#define X_MS_BTN6            f6 +#define X_MS_BTN7            f7 +#define X_MS_BTN8            f8 +#endif +#define X_MS_WH_UP           f9 +#define X_MS_WH_DOWN         fa +#define X_MS_WH_LEFT         fb +#define X_MS_WH_RIGHT        fc +#define X_MS_ACCEL0          fd +#define X_MS_ACCEL1          fe +#define X_MS_ACCEL2          ff + +// Send string macros +#define STRINGIZE(z) #z +#define ADD_SLASH_X(y) STRINGIZE(\x##y) +#define SYMBOL_STR(x) ADD_SLASH_X(x) + +#define SS_QMK_PREFIX 1 + +#define SS_TAP_CODE 1 +#define SS_DOWN_CODE 2 +#define SS_UP_CODE 3 +#define SS_DELAY_CODE 4 + +#define SS_TAP(keycode) "\1\1" SYMBOL_STR(keycode) +#define SS_DOWN(keycode) "\1\2" SYMBOL_STR(keycode) +#define SS_UP(keycode) "\1\3" SYMBOL_STR(keycode) +#define SS_DELAY(msecs) "\1\4" STRINGIZE(msecs) "|" + +// `string` arguments must not be parenthesized +#define SS_LCTL(string) SS_DOWN(X_LCTL) string SS_UP(X_LCTL) +#define SS_LSFT(string) SS_DOWN(X_LSFT) string SS_UP(X_LSFT) +#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT) +#define SS_LGUI(string) SS_DOWN(X_LGUI) string SS_UP(X_LGUI) +#define SS_LCMD(string) SS_LGUI(string) +#define SS_LWIN(string) SS_LGUI(string) + +#define SS_RCTL(string) SS_DOWN(X_RCTL) string SS_UP(X_RCTL) +#define SS_RSFT(string) SS_DOWN(X_RSFT) string SS_UP(X_RSFT) +#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT) +#define SS_RGUI(string) SS_DOWN(X_RGUI) string SS_UP(X_RGUI) +#define SS_ALGR(string) SS_RALT(string) +#define SS_RCMD(string) SS_RGUI(string) +#define SS_RWIN(string) SS_RGUI(string) + +// DEPRECATED +#define SS_LCTRL(string) SS_LCTL(string) | 
