aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2021-10-28 22:31:59 +0100
committerGitHub <noreply@github.com>2021-10-28 22:31:59 +0100
commitdcfffa7b67a072f7d9e37bd8c0029c53b61aeb0f (patch)
tree65491c3878ee76f50c4b46a318503cc27fdb4a6b /tmk_core/protocol
parent0c87e2e7025140ca6105b7fec2639c78c3cd8109 (diff)
downloadqmk_firmware-dcfffa7b67a072f7d9e37bd8c0029c53b61aeb0f.tar.gz
qmk_firmware-dcfffa7b67a072f7d9e37bd8c0029c53b61aeb0f.zip
Relocate protocol files within tmk_core/common/ (#14972)
* Relocate non platform files within tmk_core/common/ * clang
Diffstat (limited to 'tmk_core/protocol')
-rw-r--r--tmk_core/protocol/host.c138
-rw-r--r--tmk_core/protocol/host.h58
-rw-r--r--tmk_core/protocol/host_driver.h35
-rw-r--r--tmk_core/protocol/report.c280
-rw-r--r--tmk_core/protocol/report.h325
-rw-r--r--tmk_core/protocol/usb_device_state.c51
-rw-r--r--tmk_core/protocol/usb_device_state.h39
-rw-r--r--tmk_core/protocol/usb_util.c29
-rw-r--r--tmk_core/protocol/usb_util.h22
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/*
2Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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"
29extern keymap_config_t keymap_config;
30#endif
31
32static host_driver_t *driver;
33static uint16_t last_system_report = 0;
34static uint16_t last_consumer_report = 0;
35static uint32_t last_programmable_button_report = 0;
36
37void host_set_driver(host_driver_t *d) { driver = d; }
38
39host_driver_t *host_get_driver(void) { return driver; }
40
41#ifdef SPLIT_KEYBOARD
42uint8_t split_led_state = 0;
43void set_split_host_keyboard_leds(uint8_t led_state) { split_led_state = led_state; }
44#endif
45
46uint8_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
54led_t host_keyboard_led_state(void) { return (led_t)host_keyboard_leds(); }
55
56/* send report */
57void 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
84void 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
92void 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
100void 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
108void 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
126void 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
134uint16_t host_last_system_report(void) { return last_system_report; }
135
136uint16_t host_last_consumer_report(void) { return last_consumer_report; }
137
138uint32_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/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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
33extern "C" {
34#endif
35
36extern uint8_t keyboard_idle;
37extern uint8_t keyboard_protocol;
38
39/* host driver */
40void host_set_driver(host_driver_t *driver);
41host_driver_t *host_get_driver(void);
42
43/* host driver interface */
44uint8_t host_keyboard_leds(void);
45led_t host_keyboard_led_state(void);
46void host_keyboard_send(report_keyboard_t *report);
47void host_mouse_send(report_mouse_t *report);
48void host_system_send(uint16_t data);
49void host_consumer_send(uint16_t data);
50void host_programmable_button_send(uint32_t data);
51
52uint16_t host_last_system_report(void);
53uint16_t host_last_consumer_report(void);
54uint32_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/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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
26typedef 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
35void 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)
29static int8_t cb_head = 0;
30static int8_t cb_tail = 0;
31static int8_t cb_count = 0;
32#endif
33
34/** \brief has_anykey
35 *
36 * FIXME: Needs doc
37 */
38uint8_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 */
58uint8_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 */
86bool 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 */
111void 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 */
178void 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 */
218void 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 */
230void 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 */
243void 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 */
257void 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 */
271void 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/*
2Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along 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 */
27enum 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))
40enum 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 */
55enum 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 */
113enum 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
150extern "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 */
173typedef 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
194typedef struct {
195 uint8_t report_id;
196 uint16_t usage;
197} __attribute__((packed)) report_extra_t;
198
199typedef struct {
200 uint8_t report_id;
201 uint32_t usage;
202} __attribute__((packed)) report_programmable_button_t;
203
204typedef 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
215typedef 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
226typedef 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 */
241static 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 */
255static 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
308uint8_t has_anykey(report_keyboard_t* keyboard_report);
309uint8_t get_first_key(report_keyboard_t* keyboard_report);
310bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key);
311
312void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code);
313void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code);
314#ifdef NKRO_ENABLE
315void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code);
316void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code);
317#endif
318
319void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key);
320void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key);
321void 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
20enum 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
26static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { notify_usb_device_state_change_kb(usb_device_state); }
27
28void 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
33void 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
38void 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
43void 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
48void 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
23void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber);
24void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber);
25void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber);
26void usb_device_state_set_reset(void);
27void usb_device_state_init(void);
28
29enum 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
36extern enum usb_device_state usb_device_state;
37
38void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state);
39void 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
20void usb_disconnect(void);
21bool usb_connected_state(void);
22bool usb_vbus_state(void);