From dcfffa7b67a072f7d9e37bd8c0029c53b61aeb0f Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Thu, 28 Oct 2021 22:31:59 +0100 Subject: Relocate protocol files within tmk_core/common/ (#14972) * Relocate non platform files within tmk_core/common/ * clang --- tmk_core/common.mk | 4 - tmk_core/common/host.c | 138 --------------- tmk_core/common/host.h | 58 ------- tmk_core/common/host_driver.h | 35 ---- tmk_core/common/raw_hid.h | 5 - tmk_core/common/report.c | 280 ------------------------------ tmk_core/common/report.h | 325 ----------------------------------- tmk_core/common/sync_timer.c | 58 ------- tmk_core/common/sync_timer.h | 54 ------ tmk_core/common/usb_util.c | 29 ---- tmk_core/common/usb_util.h | 22 --- tmk_core/common/virtser.h | 7 - tmk_core/protocol.mk | 6 + tmk_core/protocol/host.c | 138 +++++++++++++++ tmk_core/protocol/host.h | 58 +++++++ tmk_core/protocol/host_driver.h | 35 ++++ tmk_core/protocol/report.c | 280 ++++++++++++++++++++++++++++++ tmk_core/protocol/report.h | 325 +++++++++++++++++++++++++++++++++++ tmk_core/protocol/usb_device_state.c | 51 ++++++ tmk_core/protocol/usb_device_state.h | 39 +++++ tmk_core/protocol/usb_util.c | 29 ++++ tmk_core/protocol/usb_util.h | 22 +++ 22 files changed, 983 insertions(+), 1015 deletions(-) delete mode 100644 tmk_core/common/host.c delete mode 100644 tmk_core/common/host.h delete mode 100644 tmk_core/common/host_driver.h delete mode 100644 tmk_core/common/raw_hid.h delete mode 100644 tmk_core/common/report.c delete mode 100644 tmk_core/common/report.h delete mode 100644 tmk_core/common/sync_timer.c delete mode 100644 tmk_core/common/sync_timer.h delete mode 100644 tmk_core/common/usb_util.c delete mode 100644 tmk_core/common/usb_util.h delete mode 100644 tmk_core/common/virtser.h create mode 100644 tmk_core/protocol/host.c create mode 100644 tmk_core/protocol/host.h create mode 100644 tmk_core/protocol/host_driver.h create mode 100644 tmk_core/protocol/report.c create mode 100644 tmk_core/protocol/report.h create mode 100644 tmk_core/protocol/usb_device_state.c create mode 100644 tmk_core/protocol/usb_device_state.h create mode 100644 tmk_core/protocol/usb_util.c create mode 100644 tmk_core/protocol/usb_util.h (limited to 'tmk_core') diff --git a/tmk_core/common.mk b/tmk_core/common.mk index ce335f0d3c..8fa1a31e80 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -2,10 +2,6 @@ COMMON_DIR = common PLATFORM_COMMON_DIR = $(COMMON_DIR)/$(PLATFORM_KEY) TMK_COMMON_SRC += \ - $(COMMON_DIR)/host.c \ - $(COMMON_DIR)/report.c \ - $(COMMON_DIR)/sync_timer.c \ - $(COMMON_DIR)/usb_util.c \ $(PLATFORM_COMMON_DIR)/platform.c \ $(PLATFORM_COMMON_DIR)/suspend.c \ $(PLATFORM_COMMON_DIR)/timer.c \ diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c deleted file mode 100644 index 56d4bb0847..0000000000 --- a/tmk_core/common/host.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright 2011,2012 Jun Wako - -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 . -*/ - -#include -//#include -#include "keyboard.h" -#include "keycode.h" -#include "host.h" -#include "util.h" -#include "debug.h" -#include "digitizer.h" - -#ifdef NKRO_ENABLE -# include "keycode_config.h" -extern keymap_config_t keymap_config; -#endif - -static host_driver_t *driver; -static uint16_t last_system_report = 0; -static uint16_t last_consumer_report = 0; -static uint32_t last_programmable_button_report = 0; - -void host_set_driver(host_driver_t *d) { driver = d; } - -host_driver_t *host_get_driver(void) { return driver; } - -#ifdef SPLIT_KEYBOARD -uint8_t split_led_state = 0; -void set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; } -#endif - -uint8_t host_keyboard_leds(void) { -#ifdef SPLIT_KEYBOARD - if (!is_keyboard_master()) return split_led_state; -#endif - if (!driver) return 0; - return (*driver->keyboard_leds)(); -} - -led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); } - -/* send report */ -void host_keyboard_send(report_keyboard_t *report) { - if (!driver) return; -#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP) - if (keyboard_protocol && keymap_config.nkro) { - /* The callers of this function assume that report->mods is where mods go in. - * But report->nkro.mods can be at a different offset if core keyboard does not have a report ID. - */ - report->nkro.mods = report->mods; - report->nkro.report_id = REPORT_ID_NKRO; - } else -#endif - { -#ifdef KEYBOARD_SHARED_EP - report->report_id = REPORT_ID_KEYBOARD; -#endif - } - (*driver->send_keyboard)(report); - - if (debug_keyboard) { - dprint("keyboard_report: "); - for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { - dprintf("%02X ", report->raw[i]); - } - dprint("\n"); - } -} - -void host_mouse_send(report_mouse_t *report) { - if (!driver) return; -#ifdef MOUSE_SHARED_EP - report->report_id = REPORT_ID_MOUSE; -#endif - (*driver->send_mouse)(report); -} - -void host_system_send(uint16_t report) { - if (report == last_system_report) return; - last_system_report = report; - - if (!driver) return; - (*driver->send_system)(report); -} - -void host_consumer_send(uint16_t report) { - if (report == last_consumer_report) return; - last_consumer_report = report; - - if (!driver) return; - (*driver->send_consumer)(report); -} - -void host_digitizer_send(digitizer_t *digitizer) { - if (!driver) return; - - report_digitizer_t report = { -#ifdef DIGITIZER_SHARED_EP - .report_id = REPORT_ID_DIGITIZER, -#endif - .tip = digitizer->tipswitch & 0x1, - .inrange = digitizer->inrange & 0x1, - .x = (uint16_t)(digitizer->x * 0x7FFF), - .y = (uint16_t)(digitizer->y * 0x7FFF), - }; - - send_digitizer(&report); -} - -__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} - -void host_programmable_button_send(uint32_t report) { - if (report == last_programmable_button_report) return; - last_programmable_button_report = report; - - if (!driver) return; - (*driver->send_programmable_button)(report); -} - -uint16_t host_last_system_report(void) { return last_system_report; } - -uint16_t host_last_consumer_report(void) { return last_consumer_report; } - -uint32_t host_last_programmable_button_report(void) { return last_programmable_button_report; } diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h deleted file mode 100644 index 6b15f0d0c1..0000000000 --- a/tmk_core/common/host.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include -#include "report.h" -#include "host_driver.h" -#include "led.h" - -#define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name))) -#define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) - -#define IS_HOST_LED_ON(led_name) IS_LED_ON(host_keyboard_leds(), led_name) -#define IS_HOST_LED_OFF(led_name) IS_LED_OFF(host_keyboard_leds(), led_name) - -#ifdef __cplusplus -extern "C" { -#endif - -extern uint8_t keyboard_idle; -extern uint8_t keyboard_protocol; - -/* host driver */ -void host_set_driver(host_driver_t *driver); -host_driver_t *host_get_driver(void); - -/* host driver interface */ -uint8_t host_keyboard_leds(void); -led_t host_keyboard_led_state(void); -void host_keyboard_send(report_keyboard_t *report); -void host_mouse_send(report_mouse_t *report); -void host_system_send(uint16_t data); -void host_consumer_send(uint16_t data); -void host_programmable_button_send(uint32_t data); - -uint16_t host_last_system_report(void); -uint16_t host_last_consumer_report(void); -uint32_t host_last_programmable_button_report(void); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h deleted file mode 100644 index affd0dcb34..0000000000 --- a/tmk_core/common/host_driver.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2011 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include "report.h" -#ifdef MIDI_ENABLE -# include "midi.h" -#endif - -typedef struct { - uint8_t (*keyboard_leds)(void); - void (*send_keyboard)(report_keyboard_t *); - void (*send_mouse)(report_mouse_t *); - void (*send_system)(uint16_t); - void (*send_consumer)(uint16_t); - void (*send_programmable_button)(uint32_t); -} host_driver_t; - -void send_digitizer(report_digitizer_t *report); \ No newline at end of file diff --git a/tmk_core/common/raw_hid.h b/tmk_core/common/raw_hid.h deleted file mode 100644 index 6d60ab2bff..0000000000 --- a/tmk_core/common/raw_hid.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -void raw_hid_receive(uint8_t *data, uint8_t length); - -void raw_hid_send(uint8_t *data, uint8_t length); diff --git a/tmk_core/common/report.c b/tmk_core/common/report.c deleted file mode 100644 index 2a7fc006c4..0000000000 --- a/tmk_core/common/report.c +++ /dev/null @@ -1,280 +0,0 @@ -/* Copyright 2017 Fred Sundvik - * - * 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 . - */ - -#include "report.h" -#include "host.h" -#include "keycode_config.h" -#include "debug.h" -#include "util.h" -#include - -#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE -# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) -# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) -# define RO_INC(a) RO_ADD(a, 1) -# define RO_DEC(a) RO_SUB(a, 1) -static int8_t cb_head = 0; -static int8_t cb_tail = 0; -static int8_t cb_count = 0; -#endif - -/** \brief has_anykey - * - * FIXME: Needs doc - */ -uint8_t has_anykey(report_keyboard_t* keyboard_report) { - uint8_t cnt = 0; - uint8_t* p = keyboard_report->keys; - uint8_t lp = sizeof(keyboard_report->keys); -#ifdef NKRO_ENABLE - if (keyboard_protocol && keymap_config.nkro) { - p = keyboard_report->nkro.bits; - lp = sizeof(keyboard_report->nkro.bits); - } -#endif - while (lp--) { - if (*p++) cnt++; - } - return cnt; -} - -/** \brief get_first_key - * - * FIXME: Needs doc - */ -uint8_t get_first_key(report_keyboard_t* keyboard_report) { -#ifdef NKRO_ENABLE - if (keyboard_protocol && keymap_config.nkro) { - uint8_t i = 0; - for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) - ; - return i << 3 | biton(keyboard_report->nkro.bits[i]); - } -#endif -#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE - uint8_t i = cb_head; - do { - if (keyboard_report->keys[i] != 0) { - break; - } - i = RO_INC(i); - } while (i != cb_tail); - return keyboard_report->keys[i]; -#else - return keyboard_report->keys[0]; -#endif -} - -/** \brief Checks if a key is pressed in the report - * - * Returns true if the keyboard_report reports that the key is pressed, otherwise false - * Note: The function doesn't support modifers currently, and it returns false for KC_NO - */ -bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) { - if (key == KC_NO) { - return false; - } -#ifdef NKRO_ENABLE - if (keyboard_protocol && keymap_config.nkro) { - if ((key >> 3) < KEYBOARD_REPORT_BITS) { - return keyboard_report->nkro.bits[key >> 3] & 1 << (key & 7); - } else { - return false; - } - } -#endif - for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { - if (keyboard_report->keys[i] == key) { - return true; - } - } - return false; -} - -/** \brief add key byte - * - * FIXME: Needs doc - */ -void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { -#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE - int8_t i = cb_head; - int8_t empty = -1; - if (cb_count) { - do { - if (keyboard_report->keys[i] == code) { - return; - } - if (empty == -1 && keyboard_report->keys[i] == 0) { - empty = i; - } - i = RO_INC(i); - } while (i != cb_tail); - if (i == cb_tail) { - if (cb_tail == cb_head) { - // buffer is full - if (empty == -1) { - // pop head when has no empty space - cb_head = RO_INC(cb_head); - cb_count--; - } else { - // left shift when has empty space - uint8_t offset = 1; - i = RO_INC(empty); - do { - if (keyboard_report->keys[i] != 0) { - keyboard_report->keys[empty] = keyboard_report->keys[i]; - keyboard_report->keys[i] = 0; - empty = RO_INC(empty); - } else { - offset++; - } - i = RO_INC(i); - } while (i != cb_tail); - cb_tail = RO_SUB(cb_tail, offset); - } - } - } - } - // add to tail - keyboard_report->keys[cb_tail] = code; - cb_tail = RO_INC(cb_tail); - cb_count++; -#else - int8_t i = 0; - int8_t empty = -1; - for (; i < KEYBOARD_REPORT_KEYS; i++) { - if (keyboard_report->keys[i] == code) { - break; - } - if (empty == -1 && keyboard_report->keys[i] == 0) { - empty = i; - } - } - if (i == KEYBOARD_REPORT_KEYS) { - if (empty != -1) { - keyboard_report->keys[empty] = code; - } - } -#endif -} - -/** \brief del key byte - * - * FIXME: Needs doc - */ -void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { -#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE - uint8_t i = cb_head; - if (cb_count) { - do { - if (keyboard_report->keys[i] == code) { - keyboard_report->keys[i] = 0; - cb_count--; - if (cb_count == 0) { - // reset head and tail - cb_tail = cb_head = 0; - } - if (i == RO_DEC(cb_tail)) { - // left shift when next to tail - do { - cb_tail = RO_DEC(cb_tail); - if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) { - break; - } - } while (cb_tail != cb_head); - } - break; - } - i = RO_INC(i); - } while (i != cb_tail); - } -#else - for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { - if (keyboard_report->keys[i] == code) { - keyboard_report->keys[i] = 0; - } - } -#endif -} - -#ifdef NKRO_ENABLE -/** \brief add key bit - * - * FIXME: Needs doc - */ -void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { - if ((code >> 3) < KEYBOARD_REPORT_BITS) { - keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7); - } else { - dprintf("add_key_bit: can't add: %02X\n", code); - } -} - -/** \brief del key bit - * - * FIXME: Needs doc - */ -void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { - if ((code >> 3) < KEYBOARD_REPORT_BITS) { - keyboard_report->nkro.bits[code >> 3] &= ~(1 << (code & 7)); - } else { - dprintf("del_key_bit: can't del: %02X\n", code); - } -} -#endif - -/** \brief add key to report - * - * FIXME: Needs doc - */ -void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { -#ifdef NKRO_ENABLE - if (keyboard_protocol && keymap_config.nkro) { - add_key_bit(keyboard_report, key); - return; - } -#endif - add_key_byte(keyboard_report, key); -} - -/** \brief del key from report - * - * FIXME: Needs doc - */ -void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) { -#ifdef NKRO_ENABLE - if (keyboard_protocol && keymap_config.nkro) { - del_key_bit(keyboard_report, key); - return; - } -#endif - del_key_byte(keyboard_report, key); -} - -/** \brief clear key from report - * - * FIXME: Needs doc - */ -void clear_keys_from_report(report_keyboard_t* keyboard_report) { - // not clear mods -#ifdef NKRO_ENABLE - if (keyboard_protocol && keymap_config.nkro) { - memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits)); - return; - } -#endif - memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys)); -} diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h deleted file mode 100644 index 1adc892f3b..0000000000 --- a/tmk_core/common/report.h +++ /dev/null @@ -1,325 +0,0 @@ -/* -Copyright 2011,2012 Jun Wako - -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 . -*/ - -#pragma once - -#include -#include -#include "keycode.h" - -// clang-format off - -/* HID report IDs */ -enum hid_report_ids { - REPORT_ID_KEYBOARD = 1, - REPORT_ID_MOUSE, - REPORT_ID_SYSTEM, - REPORT_ID_CONSUMER, - REPORT_ID_PROGRAMMABLE_BUTTON, - REPORT_ID_NKRO, - REPORT_ID_JOYSTICK, - REPORT_ID_DIGITIZER -}; - -/* Mouse buttons */ -#define MOUSE_BTN_MASK(n) (1 << (n)) -enum mouse_buttons { - MOUSE_BTN1 = MOUSE_BTN_MASK(0), - MOUSE_BTN2 = MOUSE_BTN_MASK(1), - MOUSE_BTN3 = MOUSE_BTN_MASK(2), - MOUSE_BTN4 = MOUSE_BTN_MASK(3), - MOUSE_BTN5 = MOUSE_BTN_MASK(4), - MOUSE_BTN6 = MOUSE_BTN_MASK(5), - MOUSE_BTN7 = MOUSE_BTN_MASK(6), - MOUSE_BTN8 = MOUSE_BTN_MASK(7) -}; - -/* Consumer Page (0x0C) - * - * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=75 - */ -enum consumer_usages { - // 15.5 Display Controls - SNAPSHOT = 0x065, - BRIGHTNESS_UP = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf - BRIGHTNESS_DOWN = 0x070, - // 15.7 Transport Controls - TRANSPORT_RECORD = 0x0B2, - TRANSPORT_FAST_FORWARD = 0x0B3, - TRANSPORT_REWIND = 0x0B4, - TRANSPORT_NEXT_TRACK = 0x0B5, - TRANSPORT_PREV_TRACK = 0x0B6, - TRANSPORT_STOP = 0x0B7, - TRANSPORT_EJECT = 0x0B8, - TRANSPORT_RANDOM_PLAY = 0x0B9, - TRANSPORT_STOP_EJECT = 0x0CC, - TRANSPORT_PLAY_PAUSE = 0x0CD, - // 15.9.1 Audio Controls - Volume - AUDIO_MUTE = 0x0E2, - AUDIO_VOL_UP = 0x0E9, - AUDIO_VOL_DOWN = 0x0EA, - // 15.15 Application Launch Buttons - AL_CC_CONFIG = 0x183, - AL_EMAIL = 0x18A, - AL_CALCULATOR = 0x192, - AL_LOCAL_BROWSER = 0x194, - AL_LOCK = 0x19E, - AL_CONTROL_PANEL = 0x19F, - AL_ASSISTANT = 0x1CB, - AL_KEYBOARD_LAYOUT = 0x1AE, - // 15.16 Generic GUI Application Controls - AC_NEW = 0x201, - AC_OPEN = 0x202, - AC_CLOSE = 0x203, - AC_EXIT = 0x204, - AC_MAXIMIZE = 0x205, - AC_MINIMIZE = 0x206, - AC_SAVE = 0x207, - AC_PRINT = 0x208, - AC_PROPERTIES = 0x209, - AC_UNDO = 0x21A, - AC_COPY = 0x21B, - AC_CUT = 0x21C, - AC_PASTE = 0x21D, - AC_SELECT_ALL = 0x21E, - AC_FIND = 0x21F, - AC_SEARCH = 0x221, - AC_HOME = 0x223, - AC_BACK = 0x224, - AC_FORWARD = 0x225, - AC_STOP = 0x226, - AC_REFRESH = 0x227, - AC_BOOKMARKS = 0x22A -}; - -/* Generic Desktop Page (0x01) - * - * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=26 - */ -enum desktop_usages { - // 4.5.1 System Controls - Power Controls - SYSTEM_POWER_DOWN = 0x81, - SYSTEM_SLEEP = 0x82, - SYSTEM_WAKE_UP = 0x83, - SYSTEM_RESTART = 0x8F, - // 4.10 System Display Controls - SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5 -}; - -// clang-format on - -#define NKRO_SHARED_EP -/* key report size(NKRO or boot mode) */ -#if defined(NKRO_ENABLE) -# if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS) -# include "protocol/usb_descriptor.h" -# define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2) -# elif defined(PROTOCOL_ARM_ATSAM) -# include "protocol/arm_atsam/usb/udi_device_epsize.h" -# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) -# undef NKRO_SHARED_EP -# undef MOUSE_SHARED_EP -# else -# error "NKRO not supported with this protocol" -# endif -#endif - -#ifdef KEYBOARD_SHARED_EP -# define KEYBOARD_REPORT_SIZE 9 -#else -# define KEYBOARD_REPORT_SIZE 8 -#endif - -#define KEYBOARD_REPORT_KEYS 6 - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys. - * - * byte |0 |1 |2 |3 |4 |5 |6 |7 - * -----+--------+--------+--------+--------+--------+--------+--------+-------- - * desc |mods |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5] - * - * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode. - * - * byte |0 |1 |2 |3 |4 |5 |6 |7 ... |15 - * -----+--------+--------+--------+--------+--------+--------+--------+-------- +-------- - * desc |mods |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6] ... |bit[14] - * - * mods retains state of 8 modifiers. - * - * bit |0 |1 |2 |3 |4 |5 |6 |7 - * -----+--------+--------+--------+--------+--------+--------+--------+-------- - * desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui - * - */ -typedef union { - uint8_t raw[KEYBOARD_REPORT_SIZE]; - struct { -#ifdef KEYBOARD_SHARED_EP - uint8_t report_id; -#endif - uint8_t mods; - uint8_t reserved; - uint8_t keys[KEYBOARD_REPORT_KEYS]; - }; -#ifdef NKRO_ENABLE - struct nkro_report { -# ifdef NKRO_SHARED_EP - uint8_t report_id; -# endif - uint8_t mods; - uint8_t bits[KEYBOARD_REPORT_BITS]; - } nkro; -#endif -} __attribute__((packed)) report_keyboard_t; - -typedef struct { - uint8_t report_id; - uint16_t usage; -} __attribute__((packed)) report_extra_t; - -typedef struct { - uint8_t report_id; - uint32_t usage; -} __attribute__((packed)) report_programmable_button_t; - -typedef struct { -#ifdef MOUSE_SHARED_EP - uint8_t report_id; -#endif - uint8_t buttons; - int8_t x; - int8_t y; - int8_t v; - int8_t h; -} __attribute__((packed)) report_mouse_t; - -typedef struct { -#ifdef DIGITIZER_SHARED_EP - uint8_t report_id; -#endif - uint8_t tip : 1; - uint8_t inrange : 1; - uint8_t pad2 : 6; - uint16_t x; - uint16_t y; -} __attribute__((packed)) report_digitizer_t; - -typedef struct { -#if JOYSTICK_AXES_COUNT > 0 -# if JOYSTICK_AXES_RESOLUTION > 8 - int16_t axes[JOYSTICK_AXES_COUNT]; -# else - int8_t axes[JOYSTICK_AXES_COUNT]; -# endif -#endif - -#if JOYSTICK_BUTTON_COUNT > 0 - uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; -#endif -} __attribute__((packed)) joystick_report_t; - -/* keycode to system usage */ -static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { - switch (key) { - case KC_SYSTEM_POWER: - return SYSTEM_POWER_DOWN; - case KC_SYSTEM_SLEEP: - return SYSTEM_SLEEP; - case KC_SYSTEM_WAKE: - return SYSTEM_WAKE_UP; - default: - return 0; - } -} - -/* keycode to consumer usage */ -static inline uint16_t KEYCODE2CONSUMER(uint8_t key) { - switch (key) { - case KC_AUDIO_MUTE: - return AUDIO_MUTE; - case KC_AUDIO_VOL_UP: - return AUDIO_VOL_UP; - case KC_AUDIO_VOL_DOWN: - return AUDIO_VOL_DOWN; - case KC_MEDIA_NEXT_TRACK: - return TRANSPORT_NEXT_TRACK; - case KC_MEDIA_PREV_TRACK: - return TRANSPORT_PREV_TRACK; - case KC_MEDIA_FAST_FORWARD: - return TRANSPORT_FAST_FORWARD; - case KC_MEDIA_REWIND: - return TRANSPORT_REWIND; - case KC_MEDIA_STOP: - return TRANSPORT_STOP; - case KC_MEDIA_EJECT: - return TRANSPORT_STOP_EJECT; - case KC_MEDIA_PLAY_PAUSE: - return TRANSPORT_PLAY_PAUSE; - case KC_MEDIA_SELECT: - return AL_CC_CONFIG; - case KC_MAIL: - return AL_EMAIL; - case KC_CALCULATOR: - return AL_CALCULATOR; - case KC_MY_COMPUTER: - return AL_LOCAL_BROWSER; - case KC_WWW_SEARCH: - return AC_SEARCH; - case KC_WWW_HOME: - return AC_HOME; - case KC_WWW_BACK: - return AC_BACK; - case KC_WWW_FORWARD: - return AC_FORWARD; - case KC_WWW_STOP: - return AC_STOP; - case KC_WWW_REFRESH: - return AC_REFRESH; - case KC_BRIGHTNESS_UP: - return BRIGHTNESS_UP; - case KC_BRIGHTNESS_DOWN: - return BRIGHTNESS_DOWN; - case KC_WWW_FAVORITES: - return AC_BOOKMARKS; - default: - return 0; - } -} - -uint8_t has_anykey(report_keyboard_t* keyboard_report); -uint8_t get_first_key(report_keyboard_t* keyboard_report); -bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key); - -void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code); -void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code); -#ifdef NKRO_ENABLE -void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code); -void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code); -#endif - -void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key); -void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key); -void clear_keys_from_report(report_keyboard_t* keyboard_report); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/sync_timer.c b/tmk_core/common/sync_timer.c deleted file mode 100644 index de24b463b6..0000000000 --- a/tmk_core/common/sync_timer.c +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright (C) 2020 Ryan Caltabiano - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -If you happen to meet one of the copyright holders in a bar you are obligated -to buy them one pint of beer. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include "sync_timer.h" -#include "keyboard.h" - -#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) -volatile int32_t sync_timer_ms; - -void sync_timer_init(void) { sync_timer_ms = 0; } - -void sync_timer_update(uint32_t time) { - if (is_keyboard_master()) return; - sync_timer_ms = time - timer_read32(); -} - -uint16_t sync_timer_read(void) { - if (is_keyboard_master()) return timer_read(); - return sync_timer_read32(); -} - -uint32_t sync_timer_read32(void) { - if (is_keyboard_master()) return timer_read32(); - return sync_timer_ms + timer_read32(); -} - -uint16_t sync_timer_elapsed(uint16_t last) { - if (is_keyboard_master()) return timer_elapsed(last); - return TIMER_DIFF_16(sync_timer_read(), last); -} - -uint32_t sync_timer_elapsed32(uint32_t last) { - if (is_keyboard_master()) return timer_elapsed32(last); - return TIMER_DIFF_32(sync_timer_read32(), last); -} -#endif diff --git a/tmk_core/common/sync_timer.h b/tmk_core/common/sync_timer.h deleted file mode 100644 index 9ddef45bb2..0000000000 --- a/tmk_core/common/sync_timer.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright (C) 2020 Ryan Caltabiano - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -If you happen to meet one of the copyright holders in a bar you are obligated -to buy them one pint of beer. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#pragma once - -#include -#include "timer.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER) -void sync_timer_init(void); -void sync_timer_update(uint32_t time); -uint16_t sync_timer_read(void); -uint32_t sync_timer_read32(void); -uint16_t sync_timer_elapsed(uint16_t last); -uint32_t sync_timer_elapsed32(uint32_t last); -#else -# define sync_timer_init() -# define sync_timer_clear() -# define sync_timer_update(t) -# define sync_timer_read() timer_read() -# define sync_timer_read32() timer_read32() -# define sync_timer_elapsed(t) timer_elapsed(t) -# define sync_timer_elapsed32(t) timer_elapsed32(t) -#endif - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/common/usb_util.c b/tmk_core/common/usb_util.c deleted file mode 100644 index dd1deeaa11..0000000000 --- a/tmk_core/common/usb_util.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2021 QMK - * - * 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 3 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 . - */ -#include "quantum.h" -#include "usb_util.h" - -__attribute__((weak)) void usb_disconnect(void) {} -__attribute__((weak)) bool usb_connected_state(void) { return true; } -__attribute__((weak)) bool usb_vbus_state(void) { -#ifdef USB_VBUS_PIN - setPinInput(USB_VBUS_PIN); - wait_us(5); - return readPin(USB_VBUS_PIN); -#else - return true; -#endif -} diff --git a/tmk_core/common/usb_util.h b/tmk_core/common/usb_util.h deleted file mode 100644 index 13db9fbfbd..0000000000 --- a/tmk_core/common/usb_util.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright 2021 QMK - * - * 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 3 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 . - */ -#pragma once - -#include - -void usb_disconnect(void); -bool usb_connected_state(void); -bool usb_vbus_state(void); diff --git a/tmk_core/common/virtser.h b/tmk_core/common/virtser.h deleted file mode 100644 index a0645f9e03..0000000000 --- a/tmk_core/common/virtser.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -/* Define this function in your code to process incoming bytes */ -void virtser_recv(const uint8_t ch); - -/* Call this to send a character over the Virtual Serial Device */ -void virtser_send(const uint8_t byte); diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index d4ad50db6a..359ddbfef1 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -1,5 +1,11 @@ PROTOCOL_DIR = protocol +TMK_COMMON_SRC += \ + $(PROTOCOL_DIR)/host.c \ + $(PROTOCOL_DIR)/report.c \ + $(PROTOCOL_DIR)/usb_device_state.c \ + $(PROTOCOL_DIR)/usb_util.c \ + ifeq ($(strip $(USB_HID_ENABLE)), yes) include $(TMK_DIR)/protocol/usb_hid.mk endif diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c new file mode 100644 index 0000000000..56d4bb0847 --- /dev/null +++ b/tmk_core/protocol/host.c @@ -0,0 +1,138 @@ +/* +Copyright 2011,2012 Jun Wako + +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 . +*/ + +#include +//#include +#include "keyboard.h" +#include "keycode.h" +#include "host.h" +#include "util.h" +#include "debug.h" +#include "digitizer.h" + +#ifdef NKRO_ENABLE +# include "keycode_config.h" +extern keymap_config_t keymap_config; +#endif + +static host_driver_t *driver; +static uint16_t last_system_report = 0; +static uint16_t last_consumer_report = 0; +static uint32_t last_programmable_button_report = 0; + +void host_set_driver(host_driver_t *d) { driver = d; } + +host_driver_t *host_get_driver(void) { return driver; } + +#ifdef SPLIT_KEYBOARD +uint8_t split_led_state = 0; +void set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; } +#endif + +uint8_t host_keyboard_leds(void) { +#ifdef SPLIT_KEYBOARD + if (!is_keyboard_master()) return split_led_state; +#endif + if (!driver) return 0; + return (*driver->keyboard_leds)(); +} + +led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); } + +/* send report */ +void host_keyboard_send(report_keyboard_t *report) { + if (!driver) return; +#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP) + if (keyboard_protocol && keymap_config.nkro) { + /* The callers of this function assume that report->mods is where mods go in. + * But report->nkro.mods can be at a different offset if core keyboard does not have a report ID. + */ + report->nkro.mods = report->mods; + report->nkro.report_id = REPORT_ID_NKRO; + } else +#endif + { +#ifdef KEYBOARD_SHARED_EP + report->report_id = REPORT_ID_KEYBOARD; +#endif + } + (*driver->send_keyboard)(report); + + if (debug_keyboard) { + dprint("keyboard_report: "); + for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { + dprintf("%02X ", report->raw[i]); + } + dprint("\n"); + } +} + +void host_mouse_send(report_mouse_t *report) { + if (!driver) return; +#ifdef MOUSE_SHARED_EP + report->report_id = REPORT_ID_MOUSE; +#endif + (*driver->send_mouse)(report); +} + +void host_system_send(uint16_t report) { + if (report == last_system_report) return; + last_system_report = report; + + if (!driver) return; + (*driver->send_system)(report); +} + +void host_consumer_send(uint16_t report) { + if (report == last_consumer_report) return; + last_consumer_report = report; + + if (!driver) return; + (*driver->send_consumer)(report); +} + +void host_digitizer_send(digitizer_t *digitizer) { + if (!driver) return; + + report_digitizer_t report = { +#ifdef DIGITIZER_SHARED_EP + .report_id = REPORT_ID_DIGITIZER, +#endif + .tip = digitizer->tipswitch & 0x1, + .inrange = digitizer->inrange & 0x1, + .x = (uint16_t)(digitizer->x * 0x7FFF), + .y = (uint16_t)(digitizer->y * 0x7FFF), + }; + + send_digitizer(&report); +} + +__attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} + +void host_programmable_button_send(uint32_t report) { + if (report == last_programmable_button_report) return; + last_programmable_button_report = report; + + if (!driver) return; + (*driver->send_programmable_button)(report); +} + +uint16_t host_last_system_report(void) { return last_system_report; } + +uint16_t host_last_consumer_report(void) { return last_consumer_report; } + +uint32_t host_last_programmable_button_report(void) { return last_programmable_button_report; } diff --git a/tmk_core/protocol/host.h b/tmk_core/protocol/host.h new file mode 100644 index 0000000000..6b15f0d0c1 --- /dev/null +++ b/tmk_core/protocol/host.h @@ -0,0 +1,58 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include +#include "report.h" +#include "host_driver.h" +#include "led.h" + +#define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name))) +#define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) + +#define IS_HOST_LED_ON(led_name) IS_LED_ON(host_keyboard_leds(), led_name) +#define IS_HOST_LED_OFF(led_name) IS_LED_OFF(host_keyboard_leds(), led_name) + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint8_t keyboard_idle; +extern uint8_t keyboard_protocol; + +/* host driver */ +void host_set_driver(host_driver_t *driver); +host_driver_t *host_get_driver(void); + +/* host driver interface */ +uint8_t host_keyboard_leds(void); +led_t host_keyboard_led_state(void); +void host_keyboard_send(report_keyboard_t *report); +void host_mouse_send(report_mouse_t *report); +void host_system_send(uint16_t data); +void host_consumer_send(uint16_t data); +void host_programmable_button_send(uint32_t data); + +uint16_t host_last_system_report(void); +uint16_t host_last_consumer_report(void); +uint32_t host_last_programmable_button_report(void); + +#ifdef __cplusplus +} +#endif diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h new file mode 100644 index 0000000000..affd0dcb34 --- /dev/null +++ b/tmk_core/protocol/host_driver.h @@ -0,0 +1,35 @@ +/* +Copyright 2011 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include "report.h" +#ifdef MIDI_ENABLE +# include "midi.h" +#endif + +typedef struct { + uint8_t (*keyboard_leds)(void); + void (*send_keyboard)(report_keyboard_t *); + void (*send_mouse)(report_mouse_t *); + void (*send_system)(uint16_t); + void (*send_consumer)(uint16_t); + void (*send_programmable_button)(uint32_t); +} host_driver_t; + +void send_digitizer(report_digitizer_t *report); \ No newline at end of file diff --git a/tmk_core/protocol/report.c b/tmk_core/protocol/report.c new file mode 100644 index 0000000000..854b59ae48 --- /dev/null +++ b/tmk_core/protocol/report.c @@ -0,0 +1,280 @@ +/* Copyright 2017 Fred Sundvik + * + * 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 . + */ + +#include "report.h" +#include "host.h" +#include "keycode_config.h" +#include "debug.h" +#include "util.h" +#include + +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE +# define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) +# define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) +# define RO_INC(a) RO_ADD(a, 1) +# define RO_DEC(a) RO_SUB(a, 1) +static int8_t cb_head = 0; +static int8_t cb_tail = 0; +static int8_t cb_count = 0; +#endif + +/** \brief has_anykey + * + * FIXME: Needs doc + */ +uint8_t has_anykey(report_keyboard_t* keyboard_report) { + uint8_t cnt = 0; + uint8_t* p = keyboard_report->keys; + uint8_t lp = sizeof(keyboard_report->keys); +#ifdef NKRO_ENABLE + if (keyboard_protocol && keymap_config.nkro) { + p = keyboard_report->nkro.bits; + lp = sizeof(keyboard_report->nkro.bits); + } +#endif + while (lp--) { + if (*p++) cnt++; + } + return cnt; +} + +/** \brief get_first_key + * + * FIXME: Needs doc + */ +uint8_t get_first_key(report_keyboard_t* keyboard_report) { +#ifdef NKRO_ENABLE + if (keyboard_protocol && keymap_config.nkro) { + uint8_t i = 0; + for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) + ; + return i << 3 | biton(keyboard_report->nkro.bits[i]); + } +#endif +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE + uint8_t i = cb_head; + do { + if (keyboard_report->keys[i] != 0) { + break; + } + i = RO_INC(i); + } while (i != cb_tail); + return keyboard_report->keys[i]; +#else + return keyboard_report->keys[0]; +#endif +} + +/** \brief Checks if a key is pressed in the report + * + * Returns true if the keyboard_report reports that the key is pressed, otherwise false + * Note: The function doesn't support modifers currently, and it returns false for KC_NO + */ +bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) { + if (key == KC_NO) { + return false; + } +#ifdef NKRO_ENABLE + if (keyboard_protocol && keymap_config.nkro) { + if ((key >> 3) < KEYBOARD_REPORT_BITS) { + return keyboard_report->nkro.bits[key >> 3] & 1 << (key & 7); + } else { + return false; + } + } +#endif + for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { + if (keyboard_report->keys[i] == key) { + return true; + } + } + return false; +} + +/** \brief add key byte + * + * FIXME: Needs doc + */ +void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE + int8_t i = cb_head; + int8_t empty = -1; + if (cb_count) { + do { + if (keyboard_report->keys[i] == code) { + return; + } + if (empty == -1 && keyboard_report->keys[i] == 0) { + empty = i; + } + i = RO_INC(i); + } while (i != cb_tail); + if (i == cb_tail) { + if (cb_tail == cb_head) { + // buffer is full + if (empty == -1) { + // pop head when has no empty space + cb_head = RO_INC(cb_head); + cb_count--; + } else { + // left shift when has empty space + uint8_t offset = 1; + i = RO_INC(empty); + do { + if (keyboard_report->keys[i] != 0) { + keyboard_report->keys[empty] = keyboard_report->keys[i]; + keyboard_report->keys[i] = 0; + empty = RO_INC(empty); + } else { + offset++; + } + i = RO_INC(i); + } while (i != cb_tail); + cb_tail = RO_SUB(cb_tail, offset); + } + } + } + } + // add to tail + keyboard_report->keys[cb_tail] = code; + cb_tail = RO_INC(cb_tail); + cb_count++; +#else + int8_t i = 0; + int8_t empty = -1; + for (; i < KEYBOARD_REPORT_KEYS; i++) { + if (keyboard_report->keys[i] == code) { + break; + } + if (empty == -1 && keyboard_report->keys[i] == 0) { + empty = i; + } + } + if (i == KEYBOARD_REPORT_KEYS) { + if (empty != -1) { + keyboard_report->keys[empty] = code; + } + } +#endif +} + +/** \brief del key byte + * + * FIXME: Needs doc + */ +void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { +#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE + uint8_t i = cb_head; + if (cb_count) { + do { + if (keyboard_report->keys[i] == code) { + keyboard_report->keys[i] = 0; + cb_count--; + if (cb_count == 0) { + // reset head and tail + cb_tail = cb_head = 0; + } + if (i == RO_DEC(cb_tail)) { + // left shift when next to tail + do { + cb_tail = RO_DEC(cb_tail); + if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) { + break; + } + } while (cb_tail != cb_head); + } + break; + } + i = RO_INC(i); + } while (i != cb_tail); + } +#else + for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { + if (keyboard_report->keys[i] == code) { + keyboard_report->keys[i] = 0; + } + } +#endif +} + +#ifdef NKRO_ENABLE +/** \brief add key bit + * + * FIXME: Needs doc + */ +void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { + if ((code >> 3) < KEYBOARD_REPORT_BITS) { + keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7); + } else { + dprintf("add_key_bit: can't add: %02X\n", code); + } +} + +/** \brief del key bit + * + * FIXME: Needs doc + */ +void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { + if ((code >> 3) < KEYBOARD_REPORT_BITS) { + keyboard_report->nkro.bits[code >> 3] &= ~(1 << (code & 7)); + } else { + dprintf("del_key_bit: can't del: %02X\n", code); + } +} +#endif + +/** \brief add key to report + * + * FIXME: Needs doc + */ +void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { +#ifdef NKRO_ENABLE + if (keyboard_protocol && keymap_config.nkro) { + add_key_bit(keyboard_report, key); + return; + } +#endif + add_key_byte(keyboard_report, key); +} + +/** \brief del key from report + * + * FIXME: Needs doc + */ +void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) { +#ifdef NKRO_ENABLE + if (keyboard_protocol && keymap_config.nkro) { + del_key_bit(keyboard_report, key); + return; + } +#endif + del_key_byte(keyboard_report, key); +} + +/** \brief clear key from report + * + * FIXME: Needs doc + */ +void clear_keys_from_report(report_keyboard_t* keyboard_report) { + // not clear mods +#ifdef NKRO_ENABLE + if (keyboard_protocol && keymap_config.nkro) { + memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits)); + return; + } +#endif + memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys)); +} diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h new file mode 100644 index 0000000000..1adc892f3b --- /dev/null +++ b/tmk_core/protocol/report.h @@ -0,0 +1,325 @@ +/* +Copyright 2011,2012 Jun Wako + +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 . +*/ + +#pragma once + +#include +#include +#include "keycode.h" + +// clang-format off + +/* HID report IDs */ +enum hid_report_ids { + REPORT_ID_KEYBOARD = 1, + REPORT_ID_MOUSE, + REPORT_ID_SYSTEM, + REPORT_ID_CONSUMER, + REPORT_ID_PROGRAMMABLE_BUTTON, + REPORT_ID_NKRO, + REPORT_ID_JOYSTICK, + REPORT_ID_DIGITIZER +}; + +/* Mouse buttons */ +#define MOUSE_BTN_MASK(n) (1 << (n)) +enum mouse_buttons { + MOUSE_BTN1 = MOUSE_BTN_MASK(0), + MOUSE_BTN2 = MOUSE_BTN_MASK(1), + MOUSE_BTN3 = MOUSE_BTN_MASK(2), + MOUSE_BTN4 = MOUSE_BTN_MASK(3), + MOUSE_BTN5 = MOUSE_BTN_MASK(4), + MOUSE_BTN6 = MOUSE_BTN_MASK(5), + MOUSE_BTN7 = MOUSE_BTN_MASK(6), + MOUSE_BTN8 = MOUSE_BTN_MASK(7) +}; + +/* Consumer Page (0x0C) + * + * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=75 + */ +enum consumer_usages { + // 15.5 Display Controls + SNAPSHOT = 0x065, + BRIGHTNESS_UP = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf + BRIGHTNESS_DOWN = 0x070, + // 15.7 Transport Controls + TRANSPORT_RECORD = 0x0B2, + TRANSPORT_FAST_FORWARD = 0x0B3, + TRANSPORT_REWIND = 0x0B4, + TRANSPORT_NEXT_TRACK = 0x0B5, + TRANSPORT_PREV_TRACK = 0x0B6, + TRANSPORT_STOP = 0x0B7, + TRANSPORT_EJECT = 0x0B8, + TRANSPORT_RANDOM_PLAY = 0x0B9, + TRANSPORT_STOP_EJECT = 0x0CC, + TRANSPORT_PLAY_PAUSE = 0x0CD, + // 15.9.1 Audio Controls - Volume + AUDIO_MUTE = 0x0E2, + AUDIO_VOL_UP = 0x0E9, + AUDIO_VOL_DOWN = 0x0EA, + // 15.15 Application Launch Buttons + AL_CC_CONFIG = 0x183, + AL_EMAIL = 0x18A, + AL_CALCULATOR = 0x192, + AL_LOCAL_BROWSER = 0x194, + AL_LOCK = 0x19E, + AL_CONTROL_PANEL = 0x19F, + AL_ASSISTANT = 0x1CB, + AL_KEYBOARD_LAYOUT = 0x1AE, + // 15.16 Generic GUI Application Controls + AC_NEW = 0x201, + AC_OPEN = 0x202, + AC_CLOSE = 0x203, + AC_EXIT = 0x204, + AC_MAXIMIZE = 0x205, + AC_MINIMIZE = 0x206, + AC_SAVE = 0x207, + AC_PRINT = 0x208, + AC_PROPERTIES = 0x209, + AC_UNDO = 0x21A, + AC_COPY = 0x21B, + AC_CUT = 0x21C, + AC_PASTE = 0x21D, + AC_SELECT_ALL = 0x21E, + AC_FIND = 0x21F, + AC_SEARCH = 0x221, + AC_HOME = 0x223, + AC_BACK = 0x224, + AC_FORWARD = 0x225, + AC_STOP = 0x226, + AC_REFRESH = 0x227, + AC_BOOKMARKS = 0x22A +}; + +/* Generic Desktop Page (0x01) + * + * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=26 + */ +enum desktop_usages { + // 4.5.1 System Controls - Power Controls + SYSTEM_POWER_DOWN = 0x81, + SYSTEM_SLEEP = 0x82, + SYSTEM_WAKE_UP = 0x83, + SYSTEM_RESTART = 0x8F, + // 4.10 System Display Controls + SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5 +}; + +// clang-format on + +#define NKRO_SHARED_EP +/* key report size(NKRO or boot mode) */ +#if defined(NKRO_ENABLE) +# if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS) +# include "protocol/usb_descriptor.h" +# define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2) +# elif defined(PROTOCOL_ARM_ATSAM) +# include "protocol/arm_atsam/usb/udi_device_epsize.h" +# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) +# undef NKRO_SHARED_EP +# undef MOUSE_SHARED_EP +# else +# error "NKRO not supported with this protocol" +# endif +#endif + +#ifdef KEYBOARD_SHARED_EP +# define KEYBOARD_REPORT_SIZE 9 +#else +# define KEYBOARD_REPORT_SIZE 8 +#endif + +#define KEYBOARD_REPORT_KEYS 6 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys. + * + * byte |0 |1 |2 |3 |4 |5 |6 |7 + * -----+--------+--------+--------+--------+--------+--------+--------+-------- + * desc |mods |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5] + * + * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode. + * + * byte |0 |1 |2 |3 |4 |5 |6 |7 ... |15 + * -----+--------+--------+--------+--------+--------+--------+--------+-------- +-------- + * desc |mods |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6] ... |bit[14] + * + * mods retains state of 8 modifiers. + * + * bit |0 |1 |2 |3 |4 |5 |6 |7 + * -----+--------+--------+--------+--------+--------+--------+--------+-------- + * desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui + * + */ +typedef union { + uint8_t raw[KEYBOARD_REPORT_SIZE]; + struct { +#ifdef KEYBOARD_SHARED_EP + uint8_t report_id; +#endif + uint8_t mods; + uint8_t reserved; + uint8_t keys[KEYBOARD_REPORT_KEYS]; + }; +#ifdef NKRO_ENABLE + struct nkro_report { +# ifdef NKRO_SHARED_EP + uint8_t report_id; +# endif + uint8_t mods; + uint8_t bits[KEYBOARD_REPORT_BITS]; + } nkro; +#endif +} __attribute__((packed)) report_keyboard_t; + +typedef struct { + uint8_t report_id; + uint16_t usage; +} __attribute__((packed)) report_extra_t; + +typedef struct { + uint8_t report_id; + uint32_t usage; +} __attribute__((packed)) report_programmable_button_t; + +typedef struct { +#ifdef MOUSE_SHARED_EP + uint8_t report_id; +#endif + uint8_t buttons; + int8_t x; + int8_t y; + int8_t v; + int8_t h; +} __attribute__((packed)) report_mouse_t; + +typedef struct { +#ifdef DIGITIZER_SHARED_EP + uint8_t report_id; +#endif + uint8_t tip : 1; + uint8_t inrange : 1; + uint8_t pad2 : 6; + uint16_t x; + uint16_t y; +} __attribute__((packed)) report_digitizer_t; + +typedef struct { +#if JOYSTICK_AXES_COUNT > 0 +# if JOYSTICK_AXES_RESOLUTION > 8 + int16_t axes[JOYSTICK_AXES_COUNT]; +# else + int8_t axes[JOYSTICK_AXES_COUNT]; +# endif +#endif + +#if JOYSTICK_BUTTON_COUNT > 0 + uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; +#endif +} __attribute__((packed)) joystick_report_t; + +/* keycode to system usage */ +static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { + switch (key) { + case KC_SYSTEM_POWER: + return SYSTEM_POWER_DOWN; + case KC_SYSTEM_SLEEP: + return SYSTEM_SLEEP; + case KC_SYSTEM_WAKE: + return SYSTEM_WAKE_UP; + default: + return 0; + } +} + +/* keycode to consumer usage */ +static inline uint16_t KEYCODE2CONSUMER(uint8_t key) { + switch (key) { + case KC_AUDIO_MUTE: + return AUDIO_MUTE; + case KC_AUDIO_VOL_UP: + return AUDIO_VOL_UP; + case KC_AUDIO_VOL_DOWN: + return AUDIO_VOL_DOWN; + case KC_MEDIA_NEXT_TRACK: + return TRANSPORT_NEXT_TRACK; + case KC_MEDIA_PREV_TRACK: + return TRANSPORT_PREV_TRACK; + case KC_MEDIA_FAST_FORWARD: + return TRANSPORT_FAST_FORWARD; + case KC_MEDIA_REWIND: + return TRANSPORT_REWIND; + case KC_MEDIA_STOP: + return TRANSPORT_STOP; + case KC_MEDIA_EJECT: + return TRANSPORT_STOP_EJECT; + case KC_MEDIA_PLAY_PAUSE: + return TRANSPORT_PLAY_PAUSE; + case KC_MEDIA_SELECT: + return AL_CC_CONFIG; + case KC_MAIL: + return AL_EMAIL; + case KC_CALCULATOR: + return AL_CALCULATOR; + case KC_MY_COMPUTER: + return AL_LOCAL_BROWSER; + case KC_WWW_SEARCH: + return AC_SEARCH; + case KC_WWW_HOME: + return AC_HOME; + case KC_WWW_BACK: + return AC_BACK; + case KC_WWW_FORWARD: + return AC_FORWARD; + case KC_WWW_STOP: + return AC_STOP; + case KC_WWW_REFRESH: + return AC_REFRESH; + case KC_BRIGHTNESS_UP: + return BRIGHTNESS_UP; + case KC_BRIGHTNESS_DOWN: + return BRIGHTNESS_DOWN; + case KC_WWW_FAVORITES: + return AC_BOOKMARKS; + default: + return 0; + } +} + +uint8_t has_anykey(report_keyboard_t* keyboard_report); +uint8_t get_first_key(report_keyboard_t* keyboard_report); +bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key); + +void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code); +void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code); +#ifdef NKRO_ENABLE +void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code); +void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code); +#endif + +void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key); +void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key); +void clear_keys_from_report(report_keyboard_t* keyboard_report); + +#ifdef __cplusplus +} +#endif diff --git a/tmk_core/protocol/usb_device_state.c b/tmk_core/protocol/usb_device_state.c new file mode 100644 index 0000000000..5ccd309ec2 --- /dev/null +++ b/tmk_core/protocol/usb_device_state.c @@ -0,0 +1,51 @@ +/* + * Copyright 2021 Andrei Purdea + * + * 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 . + */ + +#include "usb_device_state.h" + +enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT; + +__attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { notify_usb_device_state_change_user(usb_device_state); } + +__attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} + +static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { notify_usb_device_state_change_kb(usb_device_state); } + +void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { + usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) { + usb_device_state = USB_DEVICE_STATE_SUSPEND; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) { + usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_set_reset(void) { + usb_device_state = USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} + +void usb_device_state_init(void) { + usb_device_state = USB_DEVICE_STATE_INIT; + notify_usb_device_state_change(usb_device_state); +} diff --git a/tmk_core/protocol/usb_device_state.h b/tmk_core/protocol/usb_device_state.h new file mode 100644 index 0000000000..c229311d46 --- /dev/null +++ b/tmk_core/protocol/usb_device_state.h @@ -0,0 +1,39 @@ +/* + * Copyright 2021 Andrei Purdea + * + * 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 . + */ + +#pragma once + +#include +#include + +void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber); +void usb_device_state_set_reset(void); +void usb_device_state_init(void); + +enum usb_device_state { + USB_DEVICE_STATE_NO_INIT = 0, // We're in this state before calling usb_device_state_init() + USB_DEVICE_STATE_INIT = 1, // Can consume up to 100mA + USB_DEVICE_STATE_CONFIGURED = 2, // Can consume up to what is specified in configuration descriptor, typically 500mA + USB_DEVICE_STATE_SUSPEND = 3 // Can consume only suspend current +}; + +extern enum usb_device_state usb_device_state; + +void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state); +void notify_usb_device_state_change_user(enum usb_device_state usb_device_state); diff --git a/tmk_core/protocol/usb_util.c b/tmk_core/protocol/usb_util.c new file mode 100644 index 0000000000..dd1deeaa11 --- /dev/null +++ b/tmk_core/protocol/usb_util.c @@ -0,0 +1,29 @@ +/* Copyright 2021 QMK + * + * 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 3 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 . + */ +#include "quantum.h" +#include "usb_util.h" + +__attribute__((weak)) void usb_disconnect(void) {} +__attribute__((weak)) bool usb_connected_state(void) { return true; } +__attribute__((weak)) bool usb_vbus_state(void) { +#ifdef USB_VBUS_PIN + setPinInput(USB_VBUS_PIN); + wait_us(5); + return readPin(USB_VBUS_PIN); +#else + return true; +#endif +} diff --git a/tmk_core/protocol/usb_util.h b/tmk_core/protocol/usb_util.h new file mode 100644 index 0000000000..13db9fbfbd --- /dev/null +++ b/tmk_core/protocol/usb_util.h @@ -0,0 +1,22 @@ +/* Copyright 2021 QMK + * + * 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 3 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 . + */ +#pragma once + +#include + +void usb_disconnect(void); +bool usb_connected_state(void); +bool usb_vbus_state(void); -- cgit v1.2.1