diff options
Diffstat (limited to 'tmk_core/protocol')
| -rw-r--r-- | tmk_core/protocol/host.c | 138 | ||||
| -rw-r--r-- | tmk_core/protocol/host.h | 58 | ||||
| -rw-r--r-- | tmk_core/protocol/host_driver.h | 35 | ||||
| -rw-r--r-- | tmk_core/protocol/report.c | 280 | ||||
| -rw-r--r-- | tmk_core/protocol/report.h | 325 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_device_state.c | 51 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_device_state.h | 39 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_util.c | 29 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_util.h | 22 |
9 files changed, 977 insertions, 0 deletions
diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c new file mode 100644 index 000000000..56d4bb084 --- /dev/null +++ b/tmk_core/protocol/host.c | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2011,2012 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <stdint.h> | ||
| 19 | //#include <avr/interrupt.h> | ||
| 20 | #include "keyboard.h" | ||
| 21 | #include "keycode.h" | ||
| 22 | #include "host.h" | ||
| 23 | #include "util.h" | ||
| 24 | #include "debug.h" | ||
| 25 | #include "digitizer.h" | ||
| 26 | |||
| 27 | #ifdef NKRO_ENABLE | ||
| 28 | # include "keycode_config.h" | ||
| 29 | extern keymap_config_t keymap_config; | ||
| 30 | #endif | ||
| 31 | |||
| 32 | static host_driver_t *driver; | ||
| 33 | static uint16_t last_system_report = 0; | ||
| 34 | static uint16_t last_consumer_report = 0; | ||
| 35 | static uint32_t last_programmable_button_report = 0; | ||
| 36 | |||
| 37 | void host_set_driver(host_driver_t *d) { driver = d; } | ||
| 38 | |||
| 39 | host_driver_t *host_get_driver(void) { return driver; } | ||
| 40 | |||
| 41 | #ifdef SPLIT_KEYBOARD | ||
| 42 | uint8_t split_led_state = 0; | ||
| 43 | void set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; } | ||
| 44 | #endif | ||
| 45 | |||
| 46 | uint8_t host_keyboard_leds(void) { | ||
| 47 | #ifdef SPLIT_KEYBOARD | ||
| 48 | if (!is_keyboard_master()) return split_led_state; | ||
| 49 | #endif | ||
| 50 | if (!driver) return 0; | ||
| 51 | return (*driver->keyboard_leds)(); | ||
| 52 | } | ||
| 53 | |||
| 54 | led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); } | ||
| 55 | |||
| 56 | /* send report */ | ||
| 57 | void host_keyboard_send(report_keyboard_t *report) { | ||
| 58 | if (!driver) return; | ||
| 59 | #if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP) | ||
| 60 | if (keyboard_protocol && keymap_config.nkro) { | ||
| 61 | /* The callers of this function assume that report->mods is where mods go in. | ||
| 62 | * But report->nkro.mods can be at a different offset if core keyboard does not have a report ID. | ||
| 63 | */ | ||
| 64 | report->nkro.mods = report->mods; | ||
| 65 | report->nkro.report_id = REPORT_ID_NKRO; | ||
| 66 | } else | ||
| 67 | #endif | ||
| 68 | { | ||
| 69 | #ifdef KEYBOARD_SHARED_EP | ||
| 70 | report->report_id = REPORT_ID_KEYBOARD; | ||
| 71 | #endif | ||
| 72 | } | ||
| 73 | (*driver->send_keyboard)(report); | ||
| 74 | |||
| 75 | if (debug_keyboard) { | ||
| 76 | dprint("keyboard_report: "); | ||
| 77 | for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) { | ||
| 78 | dprintf("%02X ", report->raw[i]); | ||
| 79 | } | ||
| 80 | dprint("\n"); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | void host_mouse_send(report_mouse_t *report) { | ||
| 85 | if (!driver) return; | ||
| 86 | #ifdef MOUSE_SHARED_EP | ||
| 87 | report->report_id = REPORT_ID_MOUSE; | ||
| 88 | #endif | ||
| 89 | (*driver->send_mouse)(report); | ||
| 90 | } | ||
| 91 | |||
| 92 | void host_system_send(uint16_t report) { | ||
| 93 | if (report == last_system_report) return; | ||
| 94 | last_system_report = report; | ||
| 95 | |||
| 96 | if (!driver) return; | ||
| 97 | (*driver->send_system)(report); | ||
| 98 | } | ||
| 99 | |||
| 100 | void host_consumer_send(uint16_t report) { | ||
| 101 | if (report == last_consumer_report) return; | ||
| 102 | last_consumer_report = report; | ||
| 103 | |||
| 104 | if (!driver) return; | ||
| 105 | (*driver->send_consumer)(report); | ||
| 106 | } | ||
| 107 | |||
| 108 | void host_digitizer_send(digitizer_t *digitizer) { | ||
| 109 | if (!driver) return; | ||
| 110 | |||
| 111 | report_digitizer_t report = { | ||
| 112 | #ifdef DIGITIZER_SHARED_EP | ||
| 113 | .report_id = REPORT_ID_DIGITIZER, | ||
| 114 | #endif | ||
| 115 | .tip = digitizer->tipswitch & 0x1, | ||
| 116 | .inrange = digitizer->inrange & 0x1, | ||
| 117 | .x = (uint16_t)(digitizer->x * 0x7FFF), | ||
| 118 | .y = (uint16_t)(digitizer->y * 0x7FFF), | ||
| 119 | }; | ||
| 120 | |||
| 121 | send_digitizer(&report); | ||
| 122 | } | ||
| 123 | |||
| 124 | __attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} | ||
| 125 | |||
| 126 | void host_programmable_button_send(uint32_t report) { | ||
| 127 | if (report == last_programmable_button_report) return; | ||
| 128 | last_programmable_button_report = report; | ||
| 129 | |||
| 130 | if (!driver) return; | ||
| 131 | (*driver->send_programmable_button)(report); | ||
| 132 | } | ||
| 133 | |||
| 134 | uint16_t host_last_system_report(void) { return last_system_report; } | ||
| 135 | |||
| 136 | uint16_t host_last_consumer_report(void) { return last_consumer_report; } | ||
| 137 | |||
| 138 | 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 000000000..6b15f0d0c --- /dev/null +++ b/tmk_core/protocol/host.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #pragma once | ||
| 19 | |||
| 20 | #include <stdint.h> | ||
| 21 | #include <stdbool.h> | ||
| 22 | #include "report.h" | ||
| 23 | #include "host_driver.h" | ||
| 24 | #include "led.h" | ||
| 25 | |||
| 26 | #define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name))) | ||
| 27 | #define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) | ||
| 28 | |||
| 29 | #define IS_HOST_LED_ON(led_name) IS_LED_ON(host_keyboard_leds(), led_name) | ||
| 30 | #define IS_HOST_LED_OFF(led_name) IS_LED_OFF(host_keyboard_leds(), led_name) | ||
| 31 | |||
| 32 | #ifdef __cplusplus | ||
| 33 | extern "C" { | ||
| 34 | #endif | ||
| 35 | |||
| 36 | extern uint8_t keyboard_idle; | ||
| 37 | extern uint8_t keyboard_protocol; | ||
| 38 | |||
| 39 | /* host driver */ | ||
| 40 | void host_set_driver(host_driver_t *driver); | ||
| 41 | host_driver_t *host_get_driver(void); | ||
| 42 | |||
| 43 | /* host driver interface */ | ||
| 44 | uint8_t host_keyboard_leds(void); | ||
| 45 | led_t host_keyboard_led_state(void); | ||
| 46 | void host_keyboard_send(report_keyboard_t *report); | ||
| 47 | void host_mouse_send(report_mouse_t *report); | ||
| 48 | void host_system_send(uint16_t data); | ||
| 49 | void host_consumer_send(uint16_t data); | ||
| 50 | void host_programmable_button_send(uint32_t data); | ||
| 51 | |||
| 52 | uint16_t host_last_system_report(void); | ||
| 53 | uint16_t host_last_consumer_report(void); | ||
| 54 | uint32_t host_last_programmable_button_report(void); | ||
| 55 | |||
| 56 | #ifdef __cplusplus | ||
| 57 | } | ||
| 58 | #endif | ||
diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h new file mode 100644 index 000000000..affd0dcb3 --- /dev/null +++ b/tmk_core/protocol/host_driver.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2011 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #pragma once | ||
| 19 | |||
| 20 | #include <stdint.h> | ||
| 21 | #include "report.h" | ||
| 22 | #ifdef MIDI_ENABLE | ||
| 23 | # include "midi.h" | ||
| 24 | #endif | ||
| 25 | |||
| 26 | typedef struct { | ||
| 27 | uint8_t (*keyboard_leds)(void); | ||
| 28 | void (*send_keyboard)(report_keyboard_t *); | ||
| 29 | void (*send_mouse)(report_mouse_t *); | ||
| 30 | void (*send_system)(uint16_t); | ||
| 31 | void (*send_consumer)(uint16_t); | ||
| 32 | void (*send_programmable_button)(uint32_t); | ||
| 33 | } host_driver_t; | ||
| 34 | |||
| 35 | 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 000000000..854b59ae4 --- /dev/null +++ b/tmk_core/protocol/report.c | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* Copyright 2017 Fred Sundvik | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include "report.h" | ||
| 18 | #include "host.h" | ||
| 19 | #include "keycode_config.h" | ||
| 20 | #include "debug.h" | ||
| 21 | #include "util.h" | ||
| 22 | #include <string.h> | ||
| 23 | |||
| 24 | #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||
| 25 | # define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS) | ||
| 26 | # define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS) | ||
| 27 | # define RO_INC(a) RO_ADD(a, 1) | ||
| 28 | # define RO_DEC(a) RO_SUB(a, 1) | ||
| 29 | static int8_t cb_head = 0; | ||
| 30 | static int8_t cb_tail = 0; | ||
| 31 | static int8_t cb_count = 0; | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /** \brief has_anykey | ||
| 35 | * | ||
| 36 | * FIXME: Needs doc | ||
| 37 | */ | ||
| 38 | uint8_t has_anykey(report_keyboard_t* keyboard_report) { | ||
| 39 | uint8_t cnt = 0; | ||
| 40 | uint8_t* p = keyboard_report->keys; | ||
| 41 | uint8_t lp = sizeof(keyboard_report->keys); | ||
| 42 | #ifdef NKRO_ENABLE | ||
| 43 | if (keyboard_protocol && keymap_config.nkro) { | ||
| 44 | p = keyboard_report->nkro.bits; | ||
| 45 | lp = sizeof(keyboard_report->nkro.bits); | ||
| 46 | } | ||
| 47 | #endif | ||
| 48 | while (lp--) { | ||
| 49 | if (*p++) cnt++; | ||
| 50 | } | ||
| 51 | return cnt; | ||
| 52 | } | ||
| 53 | |||
| 54 | /** \brief get_first_key | ||
| 55 | * | ||
| 56 | * FIXME: Needs doc | ||
| 57 | */ | ||
| 58 | uint8_t get_first_key(report_keyboard_t* keyboard_report) { | ||
| 59 | #ifdef NKRO_ENABLE | ||
| 60 | if (keyboard_protocol && keymap_config.nkro) { | ||
| 61 | uint8_t i = 0; | ||
| 62 | for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | ||
| 63 | ; | ||
| 64 | return i << 3 | biton(keyboard_report->nkro.bits[i]); | ||
| 65 | } | ||
| 66 | #endif | ||
| 67 | #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||
| 68 | uint8_t i = cb_head; | ||
| 69 | do { | ||
| 70 | if (keyboard_report->keys[i] != 0) { | ||
| 71 | break; | ||
| 72 | } | ||
| 73 | i = RO_INC(i); | ||
| 74 | } while (i != cb_tail); | ||
| 75 | return keyboard_report->keys[i]; | ||
| 76 | #else | ||
| 77 | return keyboard_report->keys[0]; | ||
| 78 | #endif | ||
| 79 | } | ||
| 80 | |||
| 81 | /** \brief Checks if a key is pressed in the report | ||
| 82 | * | ||
| 83 | * Returns true if the keyboard_report reports that the key is pressed, otherwise false | ||
| 84 | * Note: The function doesn't support modifers currently, and it returns false for KC_NO | ||
| 85 | */ | ||
| 86 | bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) { | ||
| 87 | if (key == KC_NO) { | ||
| 88 | return false; | ||
| 89 | } | ||
| 90 | #ifdef NKRO_ENABLE | ||
| 91 | if (keyboard_protocol && keymap_config.nkro) { | ||
| 92 | if ((key >> 3) < KEYBOARD_REPORT_BITS) { | ||
| 93 | return keyboard_report->nkro.bits[key >> 3] & 1 << (key & 7); | ||
| 94 | } else { | ||
| 95 | return false; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | #endif | ||
| 99 | for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | ||
| 100 | if (keyboard_report->keys[i] == key) { | ||
| 101 | return true; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | return false; | ||
| 105 | } | ||
| 106 | |||
| 107 | /** \brief add key byte | ||
| 108 | * | ||
| 109 | * FIXME: Needs doc | ||
| 110 | */ | ||
| 111 | void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { | ||
| 112 | #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||
| 113 | int8_t i = cb_head; | ||
| 114 | int8_t empty = -1; | ||
| 115 | if (cb_count) { | ||
| 116 | do { | ||
| 117 | if (keyboard_report->keys[i] == code) { | ||
| 118 | return; | ||
| 119 | } | ||
| 120 | if (empty == -1 && keyboard_report->keys[i] == 0) { | ||
| 121 | empty = i; | ||
| 122 | } | ||
| 123 | i = RO_INC(i); | ||
| 124 | } while (i != cb_tail); | ||
| 125 | if (i == cb_tail) { | ||
| 126 | if (cb_tail == cb_head) { | ||
| 127 | // buffer is full | ||
| 128 | if (empty == -1) { | ||
| 129 | // pop head when has no empty space | ||
| 130 | cb_head = RO_INC(cb_head); | ||
| 131 | cb_count--; | ||
| 132 | } else { | ||
| 133 | // left shift when has empty space | ||
| 134 | uint8_t offset = 1; | ||
| 135 | i = RO_INC(empty); | ||
| 136 | do { | ||
| 137 | if (keyboard_report->keys[i] != 0) { | ||
| 138 | keyboard_report->keys[empty] = keyboard_report->keys[i]; | ||
| 139 | keyboard_report->keys[i] = 0; | ||
| 140 | empty = RO_INC(empty); | ||
| 141 | } else { | ||
| 142 | offset++; | ||
| 143 | } | ||
| 144 | i = RO_INC(i); | ||
| 145 | } while (i != cb_tail); | ||
| 146 | cb_tail = RO_SUB(cb_tail, offset); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
| 150 | } | ||
| 151 | // add to tail | ||
| 152 | keyboard_report->keys[cb_tail] = code; | ||
| 153 | cb_tail = RO_INC(cb_tail); | ||
| 154 | cb_count++; | ||
| 155 | #else | ||
| 156 | int8_t i = 0; | ||
| 157 | int8_t empty = -1; | ||
| 158 | for (; i < KEYBOARD_REPORT_KEYS; i++) { | ||
| 159 | if (keyboard_report->keys[i] == code) { | ||
| 160 | break; | ||
| 161 | } | ||
| 162 | if (empty == -1 && keyboard_report->keys[i] == 0) { | ||
| 163 | empty = i; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | if (i == KEYBOARD_REPORT_KEYS) { | ||
| 167 | if (empty != -1) { | ||
| 168 | keyboard_report->keys[empty] = code; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | #endif | ||
| 172 | } | ||
| 173 | |||
| 174 | /** \brief del key byte | ||
| 175 | * | ||
| 176 | * FIXME: Needs doc | ||
| 177 | */ | ||
| 178 | void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { | ||
| 179 | #ifdef RING_BUFFERED_6KRO_REPORT_ENABLE | ||
| 180 | uint8_t i = cb_head; | ||
| 181 | if (cb_count) { | ||
| 182 | do { | ||
| 183 | if (keyboard_report->keys[i] == code) { | ||
| 184 | keyboard_report->keys[i] = 0; | ||
| 185 | cb_count--; | ||
| 186 | if (cb_count == 0) { | ||
| 187 | // reset head and tail | ||
| 188 | cb_tail = cb_head = 0; | ||
| 189 | } | ||
| 190 | if (i == RO_DEC(cb_tail)) { | ||
| 191 | // left shift when next to tail | ||
| 192 | do { | ||
| 193 | cb_tail = RO_DEC(cb_tail); | ||
| 194 | if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) { | ||
| 195 | break; | ||
| 196 | } | ||
| 197 | } while (cb_tail != cb_head); | ||
| 198 | } | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | i = RO_INC(i); | ||
| 202 | } while (i != cb_tail); | ||
| 203 | } | ||
| 204 | #else | ||
| 205 | for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { | ||
| 206 | if (keyboard_report->keys[i] == code) { | ||
| 207 | keyboard_report->keys[i] = 0; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | #endif | ||
| 211 | } | ||
| 212 | |||
| 213 | #ifdef NKRO_ENABLE | ||
| 214 | /** \brief add key bit | ||
| 215 | * | ||
| 216 | * FIXME: Needs doc | ||
| 217 | */ | ||
| 218 | void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { | ||
| 219 | if ((code >> 3) < KEYBOARD_REPORT_BITS) { | ||
| 220 | keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7); | ||
| 221 | } else { | ||
| 222 | dprintf("add_key_bit: can't add: %02X\n", code); | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | /** \brief del key bit | ||
| 227 | * | ||
| 228 | * FIXME: Needs doc | ||
| 229 | */ | ||
| 230 | void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) { | ||
| 231 | if ((code >> 3) < KEYBOARD_REPORT_BITS) { | ||
| 232 | keyboard_report->nkro.bits[code >> 3] &= ~(1 << (code & 7)); | ||
| 233 | } else { | ||
| 234 | dprintf("del_key_bit: can't del: %02X\n", code); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | #endif | ||
| 238 | |||
| 239 | /** \brief add key to report | ||
| 240 | * | ||
| 241 | * FIXME: Needs doc | ||
| 242 | */ | ||
| 243 | void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) { | ||
| 244 | #ifdef NKRO_ENABLE | ||
| 245 | if (keyboard_protocol && keymap_config.nkro) { | ||
| 246 | add_key_bit(keyboard_report, key); | ||
| 247 | return; | ||
| 248 | } | ||
| 249 | #endif | ||
| 250 | add_key_byte(keyboard_report, key); | ||
| 251 | } | ||
| 252 | |||
| 253 | /** \brief del key from report | ||
| 254 | * | ||
| 255 | * FIXME: Needs doc | ||
| 256 | */ | ||
| 257 | void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) { | ||
| 258 | #ifdef NKRO_ENABLE | ||
| 259 | if (keyboard_protocol && keymap_config.nkro) { | ||
| 260 | del_key_bit(keyboard_report, key); | ||
| 261 | return; | ||
| 262 | } | ||
| 263 | #endif | ||
| 264 | del_key_byte(keyboard_report, key); | ||
| 265 | } | ||
| 266 | |||
| 267 | /** \brief clear key from report | ||
| 268 | * | ||
| 269 | * FIXME: Needs doc | ||
| 270 | */ | ||
| 271 | void clear_keys_from_report(report_keyboard_t* keyboard_report) { | ||
| 272 | // not clear mods | ||
| 273 | #ifdef NKRO_ENABLE | ||
| 274 | if (keyboard_protocol && keymap_config.nkro) { | ||
| 275 | memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits)); | ||
| 276 | return; | ||
| 277 | } | ||
| 278 | #endif | ||
| 279 | memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys)); | ||
| 280 | } | ||
diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h new file mode 100644 index 000000000..1adc892f3 --- /dev/null +++ b/tmk_core/protocol/report.h | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2011,2012 Jun Wako <wakojun@gmail.com> | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #pragma once | ||
| 19 | |||
| 20 | #include <stdint.h> | ||
| 21 | #include <stdbool.h> | ||
| 22 | #include "keycode.h" | ||
| 23 | |||
| 24 | // clang-format off | ||
| 25 | |||
| 26 | /* HID report IDs */ | ||
| 27 | enum hid_report_ids { | ||
| 28 | REPORT_ID_KEYBOARD = 1, | ||
| 29 | REPORT_ID_MOUSE, | ||
| 30 | REPORT_ID_SYSTEM, | ||
| 31 | REPORT_ID_CONSUMER, | ||
| 32 | REPORT_ID_PROGRAMMABLE_BUTTON, | ||
| 33 | REPORT_ID_NKRO, | ||
| 34 | REPORT_ID_JOYSTICK, | ||
| 35 | REPORT_ID_DIGITIZER | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* Mouse buttons */ | ||
| 39 | #define MOUSE_BTN_MASK(n) (1 << (n)) | ||
| 40 | enum mouse_buttons { | ||
| 41 | MOUSE_BTN1 = MOUSE_BTN_MASK(0), | ||
| 42 | MOUSE_BTN2 = MOUSE_BTN_MASK(1), | ||
| 43 | MOUSE_BTN3 = MOUSE_BTN_MASK(2), | ||
| 44 | MOUSE_BTN4 = MOUSE_BTN_MASK(3), | ||
| 45 | MOUSE_BTN5 = MOUSE_BTN_MASK(4), | ||
| 46 | MOUSE_BTN6 = MOUSE_BTN_MASK(5), | ||
| 47 | MOUSE_BTN7 = MOUSE_BTN_MASK(6), | ||
| 48 | MOUSE_BTN8 = MOUSE_BTN_MASK(7) | ||
| 49 | }; | ||
| 50 | |||
| 51 | /* Consumer Page (0x0C) | ||
| 52 | * | ||
| 53 | * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=75 | ||
| 54 | */ | ||
| 55 | enum consumer_usages { | ||
| 56 | // 15.5 Display Controls | ||
| 57 | SNAPSHOT = 0x065, | ||
| 58 | BRIGHTNESS_UP = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf | ||
| 59 | BRIGHTNESS_DOWN = 0x070, | ||
| 60 | // 15.7 Transport Controls | ||
| 61 | TRANSPORT_RECORD = 0x0B2, | ||
| 62 | TRANSPORT_FAST_FORWARD = 0x0B3, | ||
| 63 | TRANSPORT_REWIND = 0x0B4, | ||
| 64 | TRANSPORT_NEXT_TRACK = 0x0B5, | ||
| 65 | TRANSPORT_PREV_TRACK = 0x0B6, | ||
| 66 | TRANSPORT_STOP = 0x0B7, | ||
| 67 | TRANSPORT_EJECT = 0x0B8, | ||
| 68 | TRANSPORT_RANDOM_PLAY = 0x0B9, | ||
| 69 | TRANSPORT_STOP_EJECT = 0x0CC, | ||
| 70 | TRANSPORT_PLAY_PAUSE = 0x0CD, | ||
| 71 | // 15.9.1 Audio Controls - Volume | ||
| 72 | AUDIO_MUTE = 0x0E2, | ||
| 73 | AUDIO_VOL_UP = 0x0E9, | ||
| 74 | AUDIO_VOL_DOWN = 0x0EA, | ||
| 75 | // 15.15 Application Launch Buttons | ||
| 76 | AL_CC_CONFIG = 0x183, | ||
| 77 | AL_EMAIL = 0x18A, | ||
| 78 | AL_CALCULATOR = 0x192, | ||
| 79 | AL_LOCAL_BROWSER = 0x194, | ||
| 80 | AL_LOCK = 0x19E, | ||
| 81 | AL_CONTROL_PANEL = 0x19F, | ||
| 82 | AL_ASSISTANT = 0x1CB, | ||
| 83 | AL_KEYBOARD_LAYOUT = 0x1AE, | ||
| 84 | // 15.16 Generic GUI Application Controls | ||
| 85 | AC_NEW = 0x201, | ||
| 86 | AC_OPEN = 0x202, | ||
| 87 | AC_CLOSE = 0x203, | ||
| 88 | AC_EXIT = 0x204, | ||
| 89 | AC_MAXIMIZE = 0x205, | ||
| 90 | AC_MINIMIZE = 0x206, | ||
| 91 | AC_SAVE = 0x207, | ||
| 92 | AC_PRINT = 0x208, | ||
| 93 | AC_PROPERTIES = 0x209, | ||
| 94 | AC_UNDO = 0x21A, | ||
| 95 | AC_COPY = 0x21B, | ||
| 96 | AC_CUT = 0x21C, | ||
| 97 | AC_PASTE = 0x21D, | ||
| 98 | AC_SELECT_ALL = 0x21E, | ||
| 99 | AC_FIND = 0x21F, | ||
| 100 | AC_SEARCH = 0x221, | ||
| 101 | AC_HOME = 0x223, | ||
| 102 | AC_BACK = 0x224, | ||
| 103 | AC_FORWARD = 0x225, | ||
| 104 | AC_STOP = 0x226, | ||
| 105 | AC_REFRESH = 0x227, | ||
| 106 | AC_BOOKMARKS = 0x22A | ||
| 107 | }; | ||
| 108 | |||
| 109 | /* Generic Desktop Page (0x01) | ||
| 110 | * | ||
| 111 | * See https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=26 | ||
| 112 | */ | ||
| 113 | enum desktop_usages { | ||
| 114 | // 4.5.1 System Controls - Power Controls | ||
| 115 | SYSTEM_POWER_DOWN = 0x81, | ||
| 116 | SYSTEM_SLEEP = 0x82, | ||
| 117 | SYSTEM_WAKE_UP = 0x83, | ||
| 118 | SYSTEM_RESTART = 0x8F, | ||
| 119 | // 4.10 System Display Controls | ||
| 120 | SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5 | ||
| 121 | }; | ||
| 122 | |||
| 123 | // clang-format on | ||
| 124 | |||
| 125 | #define NKRO_SHARED_EP | ||
| 126 | /* key report size(NKRO or boot mode) */ | ||
| 127 | #if defined(NKRO_ENABLE) | ||
| 128 | # if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS) | ||
| 129 | # include "protocol/usb_descriptor.h" | ||
| 130 | # define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2) | ||
| 131 | # elif defined(PROTOCOL_ARM_ATSAM) | ||
| 132 | # include "protocol/arm_atsam/usb/udi_device_epsize.h" | ||
| 133 | # define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) | ||
| 134 | # undef NKRO_SHARED_EP | ||
| 135 | # undef MOUSE_SHARED_EP | ||
| 136 | # else | ||
| 137 | # error "NKRO not supported with this protocol" | ||
| 138 | # endif | ||
| 139 | #endif | ||
| 140 | |||
| 141 | #ifdef KEYBOARD_SHARED_EP | ||
| 142 | # define KEYBOARD_REPORT_SIZE 9 | ||
| 143 | #else | ||
| 144 | # define KEYBOARD_REPORT_SIZE 8 | ||
| 145 | #endif | ||
| 146 | |||
| 147 | #define KEYBOARD_REPORT_KEYS 6 | ||
| 148 | |||
| 149 | #ifdef __cplusplus | ||
| 150 | extern "C" { | ||
| 151 | #endif | ||
| 152 | |||
| 153 | /* | ||
| 154 | * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys. | ||
| 155 | * | ||
| 156 | * byte |0 |1 |2 |3 |4 |5 |6 |7 | ||
| 157 | * -----+--------+--------+--------+--------+--------+--------+--------+-------- | ||
| 158 | * desc |mods |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5] | ||
| 159 | * | ||
| 160 | * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode. | ||
| 161 | * | ||
| 162 | * byte |0 |1 |2 |3 |4 |5 |6 |7 ... |15 | ||
| 163 | * -----+--------+--------+--------+--------+--------+--------+--------+-------- +-------- | ||
| 164 | * desc |mods |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6] ... |bit[14] | ||
| 165 | * | ||
| 166 | * mods retains state of 8 modifiers. | ||
| 167 | * | ||
| 168 | * bit |0 |1 |2 |3 |4 |5 |6 |7 | ||
| 169 | * -----+--------+--------+--------+--------+--------+--------+--------+-------- | ||
| 170 | * desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui | ||
| 171 | * | ||
| 172 | */ | ||
| 173 | typedef union { | ||
| 174 | uint8_t raw[KEYBOARD_REPORT_SIZE]; | ||
| 175 | struct { | ||
| 176 | #ifdef KEYBOARD_SHARED_EP | ||
| 177 | uint8_t report_id; | ||
| 178 | #endif | ||
| 179 | uint8_t mods; | ||
| 180 | uint8_t reserved; | ||
| 181 | uint8_t keys[KEYBOARD_REPORT_KEYS]; | ||
| 182 | }; | ||
| 183 | #ifdef NKRO_ENABLE | ||
| 184 | struct nkro_report { | ||
| 185 | # ifdef NKRO_SHARED_EP | ||
| 186 | uint8_t report_id; | ||
| 187 | # endif | ||
| 188 | uint8_t mods; | ||
| 189 | uint8_t bits[KEYBOARD_REPORT_BITS]; | ||
| 190 | } nkro; | ||
| 191 | #endif | ||
| 192 | } __attribute__((packed)) report_keyboard_t; | ||
| 193 | |||
| 194 | typedef struct { | ||
| 195 | uint8_t report_id; | ||
| 196 | uint16_t usage; | ||
| 197 | } __attribute__((packed)) report_extra_t; | ||
| 198 | |||
| 199 | typedef struct { | ||
| 200 | uint8_t report_id; | ||
| 201 | uint32_t usage; | ||
| 202 | } __attribute__((packed)) report_programmable_button_t; | ||
| 203 | |||
| 204 | typedef struct { | ||
| 205 | #ifdef MOUSE_SHARED_EP | ||
| 206 | uint8_t report_id; | ||
| 207 | #endif | ||
| 208 | uint8_t buttons; | ||
| 209 | int8_t x; | ||
| 210 | int8_t y; | ||
| 211 | int8_t v; | ||
| 212 | int8_t h; | ||
| 213 | } __attribute__((packed)) report_mouse_t; | ||
| 214 | |||
| 215 | typedef struct { | ||
| 216 | #ifdef DIGITIZER_SHARED_EP | ||
| 217 | uint8_t report_id; | ||
| 218 | #endif | ||
| 219 | uint8_t tip : 1; | ||
| 220 | uint8_t inrange : 1; | ||
| 221 | uint8_t pad2 : 6; | ||
| 222 | uint16_t x; | ||
| 223 | uint16_t y; | ||
| 224 | } __attribute__((packed)) report_digitizer_t; | ||
| 225 | |||
| 226 | typedef struct { | ||
| 227 | #if JOYSTICK_AXES_COUNT > 0 | ||
| 228 | # if JOYSTICK_AXES_RESOLUTION > 8 | ||
| 229 | int16_t axes[JOYSTICK_AXES_COUNT]; | ||
| 230 | # else | ||
| 231 | int8_t axes[JOYSTICK_AXES_COUNT]; | ||
| 232 | # endif | ||
| 233 | #endif | ||
| 234 | |||
| 235 | #if JOYSTICK_BUTTON_COUNT > 0 | ||
| 236 | uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; | ||
| 237 | #endif | ||
| 238 | } __attribute__((packed)) joystick_report_t; | ||
| 239 | |||
| 240 | /* keycode to system usage */ | ||
| 241 | static inline uint16_t KEYCODE2SYSTEM(uint8_t key) { | ||
| 242 | switch (key) { | ||
| 243 | case KC_SYSTEM_POWER: | ||
| 244 | return SYSTEM_POWER_DOWN; | ||
| 245 | case KC_SYSTEM_SLEEP: | ||
| 246 | return SYSTEM_SLEEP; | ||
| 247 | case KC_SYSTEM_WAKE: | ||
| 248 | return SYSTEM_WAKE_UP; | ||
| 249 | default: | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | /* keycode to consumer usage */ | ||
| 255 | static inline uint16_t KEYCODE2CONSUMER(uint8_t key) { | ||
| 256 | switch (key) { | ||
| 257 | case KC_AUDIO_MUTE: | ||
| 258 | return AUDIO_MUTE; | ||
| 259 | case KC_AUDIO_VOL_UP: | ||
| 260 | return AUDIO_VOL_UP; | ||
| 261 | case KC_AUDIO_VOL_DOWN: | ||
| 262 | return AUDIO_VOL_DOWN; | ||
| 263 | case KC_MEDIA_NEXT_TRACK: | ||
| 264 | return TRANSPORT_NEXT_TRACK; | ||
| 265 | case KC_MEDIA_PREV_TRACK: | ||
| 266 | return TRANSPORT_PREV_TRACK; | ||
| 267 | case KC_MEDIA_FAST_FORWARD: | ||
| 268 | return TRANSPORT_FAST_FORWARD; | ||
| 269 | case KC_MEDIA_REWIND: | ||
| 270 | return TRANSPORT_REWIND; | ||
| 271 | case KC_MEDIA_STOP: | ||
| 272 | return TRANSPORT_STOP; | ||
| 273 | case KC_MEDIA_EJECT: | ||
| 274 | return TRANSPORT_STOP_EJECT; | ||
| 275 | case KC_MEDIA_PLAY_PAUSE: | ||
| 276 | return TRANSPORT_PLAY_PAUSE; | ||
| 277 | case KC_MEDIA_SELECT: | ||
| 278 | return AL_CC_CONFIG; | ||
| 279 | case KC_MAIL: | ||
| 280 | return AL_EMAIL; | ||
| 281 | case KC_CALCULATOR: | ||
| 282 | return AL_CALCULATOR; | ||
| 283 | case KC_MY_COMPUTER: | ||
| 284 | return AL_LOCAL_BROWSER; | ||
| 285 | case KC_WWW_SEARCH: | ||
| 286 | return AC_SEARCH; | ||
| 287 | case KC_WWW_HOME: | ||
| 288 | return AC_HOME; | ||
| 289 | case KC_WWW_BACK: | ||
| 290 | return AC_BACK; | ||
| 291 | case KC_WWW_FORWARD: | ||
| 292 | return AC_FORWARD; | ||
| 293 | case KC_WWW_STOP: | ||
| 294 | return AC_STOP; | ||
| 295 | case KC_WWW_REFRESH: | ||
| 296 | return AC_REFRESH; | ||
| 297 | case KC_BRIGHTNESS_UP: | ||
| 298 | return BRIGHTNESS_UP; | ||
| 299 | case KC_BRIGHTNESS_DOWN: | ||
| 300 | return BRIGHTNESS_DOWN; | ||
| 301 | case KC_WWW_FAVORITES: | ||
| 302 | return AC_BOOKMARKS; | ||
| 303 | default: | ||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | uint8_t has_anykey(report_keyboard_t* keyboard_report); | ||
| 309 | uint8_t get_first_key(report_keyboard_t* keyboard_report); | ||
| 310 | bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key); | ||
| 311 | |||
| 312 | void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code); | ||
| 313 | void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code); | ||
| 314 | #ifdef NKRO_ENABLE | ||
| 315 | void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code); | ||
| 316 | void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code); | ||
| 317 | #endif | ||
| 318 | |||
| 319 | void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key); | ||
| 320 | void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key); | ||
| 321 | void clear_keys_from_report(report_keyboard_t* keyboard_report); | ||
| 322 | |||
| 323 | #ifdef __cplusplus | ||
| 324 | } | ||
| 325 | #endif | ||
diff --git a/tmk_core/protocol/usb_device_state.c b/tmk_core/protocol/usb_device_state.c new file mode 100644 index 000000000..5ccd309ec --- /dev/null +++ b/tmk_core/protocol/usb_device_state.c | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2021 Andrei Purdea <andrei@purdea.ro> | ||
| 3 | * | ||
| 4 | * This program is free software: you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation, either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "usb_device_state.h" | ||
| 19 | |||
| 20 | enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT; | ||
| 21 | |||
| 22 | __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); } | ||
| 23 | |||
| 24 | __attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} | ||
| 25 | |||
| 26 | static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { notify_usb_device_state_change_kb(usb_device_state); } | ||
| 27 | |||
| 28 | void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { | ||
| 29 | usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; | ||
| 30 | notify_usb_device_state_change(usb_device_state); | ||
| 31 | } | ||
| 32 | |||
| 33 | void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) { | ||
| 34 | usb_device_state = USB_DEVICE_STATE_SUSPEND; | ||
| 35 | notify_usb_device_state_change(usb_device_state); | ||
| 36 | } | ||
| 37 | |||
| 38 | void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) { | ||
| 39 | usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; | ||
| 40 | notify_usb_device_state_change(usb_device_state); | ||
| 41 | } | ||
| 42 | |||
| 43 | void usb_device_state_set_reset(void) { | ||
| 44 | usb_device_state = USB_DEVICE_STATE_INIT; | ||
| 45 | notify_usb_device_state_change(usb_device_state); | ||
| 46 | } | ||
| 47 | |||
| 48 | void usb_device_state_init(void) { | ||
| 49 | usb_device_state = USB_DEVICE_STATE_INIT; | ||
| 50 | notify_usb_device_state_change(usb_device_state); | ||
| 51 | } | ||
diff --git a/tmk_core/protocol/usb_device_state.h b/tmk_core/protocol/usb_device_state.h new file mode 100644 index 000000000..c229311d4 --- /dev/null +++ b/tmk_core/protocol/usb_device_state.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2021 Andrei Purdea <andrei@purdea.ro> | ||
| 3 | * | ||
| 4 | * This program is free software: you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation, either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #pragma once | ||
| 19 | |||
| 20 | #include <stdbool.h> | ||
| 21 | #include <stdint.h> | ||
| 22 | |||
| 23 | void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber); | ||
| 24 | void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber); | ||
| 25 | void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber); | ||
| 26 | void usb_device_state_set_reset(void); | ||
| 27 | void usb_device_state_init(void); | ||
| 28 | |||
| 29 | enum usb_device_state { | ||
| 30 | USB_DEVICE_STATE_NO_INIT = 0, // We're in this state before calling usb_device_state_init() | ||
| 31 | USB_DEVICE_STATE_INIT = 1, // Can consume up to 100mA | ||
| 32 | USB_DEVICE_STATE_CONFIGURED = 2, // Can consume up to what is specified in configuration descriptor, typically 500mA | ||
| 33 | USB_DEVICE_STATE_SUSPEND = 3 // Can consume only suspend current | ||
| 34 | }; | ||
| 35 | |||
| 36 | extern enum usb_device_state usb_device_state; | ||
| 37 | |||
| 38 | void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state); | ||
| 39 | 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 000000000..dd1deeaa1 --- /dev/null +++ b/tmk_core/protocol/usb_util.c | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 3 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | #include "quantum.h" | ||
| 17 | #include "usb_util.h" | ||
| 18 | |||
| 19 | __attribute__((weak)) void usb_disconnect(void) {} | ||
| 20 | __attribute__((weak)) bool usb_connected_state(void) { return true; } | ||
| 21 | __attribute__((weak)) bool usb_vbus_state(void) { | ||
| 22 | #ifdef USB_VBUS_PIN | ||
| 23 | setPinInput(USB_VBUS_PIN); | ||
| 24 | wait_us(5); | ||
| 25 | return readPin(USB_VBUS_PIN); | ||
| 26 | #else | ||
| 27 | return true; | ||
| 28 | #endif | ||
| 29 | } | ||
diff --git a/tmk_core/protocol/usb_util.h b/tmk_core/protocol/usb_util.h new file mode 100644 index 000000000..13db9fbfb --- /dev/null +++ b/tmk_core/protocol/usb_util.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 3 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | #pragma once | ||
| 17 | |||
| 18 | #include <stdbool.h> | ||
| 19 | |||
| 20 | void usb_disconnect(void); | ||
| 21 | bool usb_connected_state(void); | ||
| 22 | bool usb_vbus_state(void); | ||
