aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Laird-Wah <james@laird-wah.net>2018-11-16 17:22:05 +1100
committerDrashna Jaelre <drashna@live.com>2018-11-15 22:22:05 -0800
commit39bd760faf2666e91d6dc5b199f02fa3206c6acd (patch)
tree12db265881a0d358bb0e186689a7b20a81c37bc6
parent46cf8cc9b33a3c8bdbb0ce7df7f48f28e4d979a5 (diff)
downloadqmk_firmware-39bd760faf2666e91d6dc5b199f02fa3206c6acd.tar.gz
qmk_firmware-39bd760faf2666e91d6dc5b199f02fa3206c6acd.zip
Use a single endpoint for HID reports (#3951)
* Unify multiple HID interfaces into one This reduces the number of USB endpoints required, which frees them up for other things. NKRO and EXTRAKEY always use the shared endpoint. By default, MOUSEKEY also uses it. This means it won't work as a Boot Procotol mouse in some BIOSes, etc. If you really think your keyboard needs to work as a mouse in your BIOS, set MOUSE_SHARED_EP = no in your rules.mk. By default, the core keyboard does not use the shared endpoint, as not all BIOSes are standards compliant and that's one place you don't want to find out your keyboard doesn't work.. If you are really confident, you can set KEYBOARD_SHARED_EP = yes to use the shared endpoint here too. * unify endpoints: ChibiOS protocol implementation * fixup: missing #ifdef EXTRAKEY_ENABLEs broke build on AVR with EXTRAKEY disabled * endpoints: restore error when too many endpoints required * lufa: wait up to 10ms to send keyboard input This avoids packets being dropped when two reports are sent in quick succession (eg. releasing a dual role key). * endpoints: fix compile on ARM_ATSAM * endpoint: ARM_ATSAM fixes No longer use wrong or unexpected endpoint IDs * endpoints: accommodate VUSB protocol V-USB has its own, understandably simple ideas about the report formats. It already blasts the mouse and extrakeys through one endpoint with report IDs. We just stay out of its way. * endpoints: document new endpoint configuration options * endpoints: respect keyboard_report->mods in NKRO The caller(s) of host_keyboard_send expect to be able to just drop modifiers in the mods field and not worry about whether NKRO is in use. This is a good thing. So we just shift it over if needs be. * endpoints: report.c: update for new keyboard_report format
-rw-r--r--docs/config_options.md29
-rw-r--r--tmk_core/common.mk21
-rw-r--r--tmk_core/common/host.c22
-rw-r--r--tmk_core/common/report.c21
-rw-r--r--tmk_core/common/report.h46
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c5
-rw-r--r--tmk_core/protocol/chibios/usb_main.c176
-rw-r--r--tmk_core/protocol/chibios/usb_main.h11
-rw-r--r--tmk_core/protocol/lufa/lufa.c92
-rw-r--r--tmk_core/protocol/usb_descriptor.c213
-rw-r--r--tmk_core/protocol/usb_descriptor.h170
11 files changed, 426 insertions, 380 deletions
diff --git a/docs/config_options.md b/docs/config_options.md
index c4921c21d..b811fa877 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -261,3 +261,32 @@ Use these to enable or disable building certain features. The more you have enab
261 * Forces the keyboard to wait for a USB connection to be established before it starts up 261 * Forces the keyboard to wait for a USB connection to be established before it starts up
262* `NO_USB_STARTUP_CHECK` 262* `NO_USB_STARTUP_CHECK`
263 * Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master. 263 * Disables usb suspend check after keyboard startup. Usually the keyboard waits for the host to wake it up before any tasks are performed. This is useful for split keyboards as one half will not get a wakeup call but must send commands to the master.
264
265## USB Endpoint Limitations
266
267In order to provide services over USB, QMK has to use USB endpoints.
268These are a finite resource: each microcontroller has only a certain number.
269This limits what features can be enabled together.
270If the available endpoints are exceeded, a build error is thrown.
271
272The following features can require separate endpoints:
273
274* `MOUSEKEY_ENABLE`
275* `EXTRAKEY_ENABLE`
276* `CONSOLE_ENABLE`
277* `NKRO_ENABLE`
278* `MIDI_ENABLE`
279* `RAW_ENABLE`
280* `VIRTSER_ENABLE`
281
282In order to improve utilisation of the endpoints, the HID features can be combined to use a single endpoint.
283By default, `MOUSEKEY`, `EXTRAKEY`, and `NKRO` are combined into a single endpoint.
284
285The base keyboard functionality can also be combined into the endpoint,
286by setting `KEYBOARD_SHARED_EP = yes`.
287This frees up one more endpoint,
288but it can prevent the keyboard working in some BIOSes,
289as they do not implement Boot Keyboard protocol switching.
290
291Combining the mouse also breaks Boot Mouse compatibility.
292The mouse can be uncombined by setting `MOUSE_SHARED_EP = no` if this functionality is required.
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
index 8eac1734f..063115acb 100644
--- a/tmk_core/common.mk
+++ b/tmk_core/common.mk
@@ -82,15 +82,31 @@ else
82 TMK_COMMON_SRC += $(COMMON_DIR)/magic.c 82 TMK_COMMON_SRC += $(COMMON_DIR)/magic.c
83endif 83endif
84 84
85SHARED_EP_ENABLE = no
86MOUSE_SHARED_EP ?= yes
87ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes)
88 TMK_COMMON_DEFS += -DKEYBOARD_SHARED_EP
89 SHARED_EP_ENABLE = yes
90 # With the current usb_descriptor.c code,
91 # you can't share kbd without sharing mouse;
92 # that would be a very unexpected use case anyway
93 MOUSE_SHARED_EP = yes
94endif
85 95
86ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) 96ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
87 TMK_COMMON_SRC += $(COMMON_DIR)/mousekey.c 97 TMK_COMMON_SRC += $(COMMON_DIR)/mousekey.c
88 TMK_COMMON_DEFS += -DMOUSEKEY_ENABLE 98 TMK_COMMON_DEFS += -DMOUSEKEY_ENABLE
89 TMK_COMMON_DEFS += -DMOUSE_ENABLE 99 TMK_COMMON_DEFS += -DMOUSE_ENABLE
100
101 ifeq ($(strip $(MOUSE_SHARED_EP)), yes)
102 TMK_COMMON_DEFS += -DMOUSE_SHARED_EP
103 SHARED_EP_ENABLE = yes
104 endif
90endif 105endif
91 106
92ifeq ($(strip $(EXTRAKEY_ENABLE)), yes) 107ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
93 TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE 108 TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE
109 SHARED_EP_ENABLE = yes
94endif 110endif
95 111
96ifeq ($(strip $(RAW_ENABLE)), yes) 112ifeq ($(strip $(RAW_ENABLE)), yes)
@@ -111,6 +127,7 @@ endif
111 127
112ifeq ($(strip $(NKRO_ENABLE)), yes) 128ifeq ($(strip $(NKRO_ENABLE)), yes)
113 TMK_COMMON_DEFS += -DNKRO_ENABLE 129 TMK_COMMON_DEFS += -DNKRO_ENABLE
130 SHARED_EP_ENABLE = yes
114endif 131endif
115 132
116ifeq ($(strip $(USB_6KRO_ENABLE)), yes) 133ifeq ($(strip $(USB_6KRO_ENABLE)), yes)
@@ -182,6 +199,10 @@ ifeq ($(strip $(KEYMAP_SECTION_ENABLE)), yes)
182 endif 199 endif
183endif 200endif
184 201
202ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
203 TMK_COMMON_DEFS += -DSHARED_EP_ENABLE
204endif
205
185# Bootloader address 206# Bootloader address
186ifdef STM32_BOOTLOADER_ADDRESS 207ifdef STM32_BOOTLOADER_ADDRESS
187 TMK_COMMON_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS) 208 TMK_COMMON_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c
index e12b62216..f5d041699 100644
--- a/tmk_core/common/host.c
+++ b/tmk_core/common/host.c
@@ -22,6 +22,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
22#include "util.h" 22#include "util.h"
23#include "debug.h" 23#include "debug.h"
24 24
25#ifdef NKRO_ENABLE
26 #include "keycode_config.h"
27 extern keymap_config_t keymap_config;
28#endif
29
25static host_driver_t *driver; 30static host_driver_t *driver;
26static uint16_t last_system_report = 0; 31static uint16_t last_system_report = 0;
27static uint16_t last_consumer_report = 0; 32static uint16_t last_consumer_report = 0;
@@ -46,6 +51,20 @@ uint8_t host_keyboard_leds(void)
46void host_keyboard_send(report_keyboard_t *report) 51void host_keyboard_send(report_keyboard_t *report)
47{ 52{
48 if (!driver) return; 53 if (!driver) return;
54#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP)
55 if (keyboard_protocol && keymap_config.nkro) {
56 /* The callers of this function assume that report->mods is where mods go in.
57 * But report->nkro.mods can be at a different offset if core keyboard does not have a report ID.
58 */
59 report->nkro.mods = report->mods;
60 report->nkro.report_id = REPORT_ID_NKRO;
61 } else
62#endif
63 {
64#ifdef KEYBOARD_SHARED_EP
65 report->report_id = REPORT_ID_KEYBOARD;
66#endif
67 }
49 (*driver->send_keyboard)(report); 68 (*driver->send_keyboard)(report);
50 69
51 if (debug_keyboard) { 70 if (debug_keyboard) {
@@ -60,6 +79,9 @@ void host_keyboard_send(report_keyboard_t *report)
60void host_mouse_send(report_mouse_t *report) 79void host_mouse_send(report_mouse_t *report)
61{ 80{
62 if (!driver) return; 81 if (!driver) return;
82#ifdef MOUSE_SHARED_EP
83 report->report_id = REPORT_ID_MOUSE;
84#endif
63 (*driver->send_mouse)(report); 85 (*driver->send_mouse)(report);
64} 86}
65 87
diff --git a/tmk_core/common/report.c b/tmk_core/common/report.c
index eb3b44312..6a06b70c6 100644
--- a/tmk_core/common/report.c
+++ b/tmk_core/common/report.c
@@ -19,6 +19,7 @@
19#include "keycode_config.h" 19#include "keycode_config.h"
20#include "debug.h" 20#include "debug.h"
21#include "util.h" 21#include "util.h"
22#include <string.h>
22 23
23/** \brief has_anykey 24/** \brief has_anykey
24 * 25 *
@@ -27,8 +28,16 @@
27uint8_t has_anykey(report_keyboard_t* keyboard_report) 28uint8_t has_anykey(report_keyboard_t* keyboard_report)
28{ 29{
29 uint8_t cnt = 0; 30 uint8_t cnt = 0;
30 for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) { 31 uint8_t *p = keyboard_report->keys;
31 if (keyboard_report->raw[i]) 32 uint8_t lp = sizeof(keyboard_report->keys);
33#ifdef NKRO_ENABLE
34 if (keyboard_protocol && keymap_config.nkro) {
35 p = keyboard_report->nkro.bits;
36 lp = sizeof(keyboard_report->nkro.bits);
37 }
38#endif
39 while (lp--) {
40 if (*p++)
32 cnt++; 41 cnt++;
33 } 42 }
34 return cnt; 43 return cnt;
@@ -237,7 +246,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key)
237void clear_keys_from_report(report_keyboard_t* keyboard_report) 246void clear_keys_from_report(report_keyboard_t* keyboard_report)
238{ 247{
239 // not clear mods 248 // not clear mods
240 for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) { 249#ifdef NKRO_ENABLE
241 keyboard_report->raw[i] = 0; 250 if (keyboard_protocol && keymap_config.nkro) {
251 memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits));
252 return;
242 } 253 }
254#endif
255 memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys));
243} 256}
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
index 167f38275..5a1a6b19c 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/common/report.h
@@ -23,9 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
23 23
24 24
25/* report id */ 25/* report id */
26#define REPORT_ID_MOUSE 1 26#define REPORT_ID_KEYBOARD 1
27#define REPORT_ID_SYSTEM 2 27#define REPORT_ID_MOUSE 2
28#define REPORT_ID_CONSUMER 3 28#define REPORT_ID_SYSTEM 3
29#define REPORT_ID_CONSUMER 4
30#define REPORT_ID_NKRO 5
29 31
30/* mouse buttons */ 32/* mouse buttons */
31#define MOUSE_BTN1 (1<<0) 33#define MOUSE_BTN1 (1<<0)
@@ -72,32 +74,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
72#define SYSTEM_WAKE_UP 0x0083 74#define SYSTEM_WAKE_UP 0x0083
73 75
74 76
77#define NKRO_SHARED_EP
75/* key report size(NKRO or boot mode) */ 78/* key report size(NKRO or boot mode) */
76#if defined(NKRO_ENABLE) 79#if defined(NKRO_ENABLE)
77 #if defined(PROTOCOL_PJRC) 80 #if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
78 #include "usb.h"
79 #define KEYBOARD_REPORT_SIZE KBD2_SIZE
80 #define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
81 #define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
82 #elif defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
83 #include "protocol/usb_descriptor.h" 81 #include "protocol/usb_descriptor.h"
84 #define KEYBOARD_REPORT_SIZE NKRO_EPSIZE 82 #define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2)
85 #define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
86 #define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
87 #elif defined(PROTOCOL_ARM_ATSAM) 83 #elif defined(PROTOCOL_ARM_ATSAM)
88 #include "protocol/arm_atsam/usb/udi_device_epsize.h" 84 #include "protocol/arm_atsam/usb/udi_device_epsize.h"
89 #define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
90 #define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
91 #define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) 85 #define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
86 #undef NKRO_SHARED_EP
87 #undef MOUSE_SHARED_EP
92 #else 88 #else
93 #error "NKRO not supported with this protocol" 89 #error "NKRO not supported with this protocol"
90 #endif
94#endif 91#endif
95 92
93#ifdef KEYBOARD_SHARED_EP
94# define KEYBOARD_REPORT_SIZE 9
96#else 95#else
97# define KEYBOARD_REPORT_SIZE 8 96# define KEYBOARD_REPORT_SIZE 8
98# define KEYBOARD_REPORT_KEYS 6
99#endif 97#endif
100 98
99#define KEYBOARD_REPORT_KEYS 6
100
101/* VUSB hardcodes keyboard and mouse+extrakey only */
102#if defined(PROTOCOL_VUSB)
103 #undef KEYBOARD_SHARED_EP
104 #undef MOUSE_SHARED_EP
105#endif
101 106
102#ifdef __cplusplus 107#ifdef __cplusplus
103extern "C" { 108extern "C" {
@@ -126,12 +131,18 @@ extern "C" {
126typedef union { 131typedef union {
127 uint8_t raw[KEYBOARD_REPORT_SIZE]; 132 uint8_t raw[KEYBOARD_REPORT_SIZE];
128 struct { 133 struct {
134#ifdef KEYBOARD_SHARED_EP
135 uint8_t report_id;
136#endif
129 uint8_t mods; 137 uint8_t mods;
130 uint8_t reserved; 138 uint8_t reserved;
131 uint8_t keys[KEYBOARD_REPORT_KEYS]; 139 uint8_t keys[KEYBOARD_REPORT_KEYS];
132 }; 140 };
133#ifdef NKRO_ENABLE 141#ifdef NKRO_ENABLE
134 struct { 142 struct nkro_report {
143#ifdef NKRO_SHARED_EP
144 uint8_t report_id;
145#endif
135 uint8_t mods; 146 uint8_t mods;
136 uint8_t bits[KEYBOARD_REPORT_BITS]; 147 uint8_t bits[KEYBOARD_REPORT_BITS];
137 } nkro; 148 } nkro;
@@ -139,6 +150,9 @@ typedef union {
139} __attribute__ ((packed)) report_keyboard_t; 150} __attribute__ ((packed)) report_keyboard_t;
140 151
141typedef struct { 152typedef struct {
153#ifdef MOUSE_SHARED_EP
154 uint8_t report_id;
155#endif
142 uint8_t buttons; 156 uint8_t buttons;
143 int8_t x; 157 int8_t x;
144 int8_t y; 158 int8_t y;
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
index 18f9784ae..c263ac4aa 100644
--- a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
+++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c
@@ -54,6 +54,7 @@
54#include "udi_hid.h" 54#include "udi_hid.h"
55#include "udi_hid_kbd.h" 55#include "udi_hid_kbd.h"
56#include <string.h> 56#include <string.h>
57#include "report.h"
57 58
58//*************************************************************************** 59//***************************************************************************
59// KBD 60// KBD
@@ -430,7 +431,7 @@ UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
430 0x05, 0x01, // Usage Page (Generic Desktop), 431 0x05, 0x01, // Usage Page (Generic Desktop),
431 0x09, 0x80, // Usage (System Control), 432 0x09, 0x80, // Usage (System Control),
432 0xA1, 0x01, // Collection (Application), 433 0xA1, 0x01, // Collection (Application),
433 0x85, 0x02, // Report ID (2) (System), 434 0x85, REPORT_ID_SYSTEM, // Report ID (2) (System),
434 0x16, 0x01, 0x00, // Logical Minimum (1), 435 0x16, 0x01, 0x00, // Logical Minimum (1),
435 0x26, 0x03, 0x00, // Logical Maximum (3), 436 0x26, 0x03, 0x00, // Logical Maximum (3),
436 0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down), 437 0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down),
@@ -445,7 +446,7 @@ UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
445 0x05, 0x0C, // Usage Page (Consumer), 446 0x05, 0x0C, // Usage Page (Consumer),
446 0x09, 0x01, // Usage (Consumer Control), 447 0x09, 0x01, // Usage (Consumer Control),
447 0xA1, 0x01, // Collection (Application), 448 0xA1, 0x01, // Collection (Application),
448 0x85, 0x03, // Report ID (3) (Consumer), 449 0x85, REPORT_ID_CONSUMER, // Report ID (3) (Consumer),
449 0x16, 0x01, 0x00, // Logical Minimum (1), 450 0x16, 0x01, 0x00, // Logical Minimum (1),
450 0x26, 0x9C, 0x02, // Logical Maximum (668), 451 0x26, 0x9C, 0x02, // Logical Maximum (668),
451 0x1A, 0x01, 0x00, // Usage Minimum (1), 452 0x1A, 0x01, 0x00, // Usage Minimum (1),
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index 71892c4f4..3028e7ea2 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -95,6 +95,7 @@ static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype
95 return &desc; 95 return &desc;
96} 96}
97 97
98#ifndef KEYBOARD_SHARED_EP
98/* keyboard endpoint state structure */ 99/* keyboard endpoint state structure */
99static USBInEndpointState kbd_ep_state; 100static USBInEndpointState kbd_ep_state;
100/* keyboard endpoint initialization structure (IN) */ 101/* keyboard endpoint initialization structure (IN) */
@@ -110,8 +111,9 @@ static const USBEndpointConfig kbd_ep_config = {
110 2, /* IN multiplier */ 111 2, /* IN multiplier */
111 NULL /* SETUP buffer (not a SETUP endpoint) */ 112 NULL /* SETUP buffer (not a SETUP endpoint) */
112}; 113};
114#endif
113 115
114#ifdef MOUSE_ENABLE 116#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
115/* mouse endpoint state structure */ 117/* mouse endpoint state structure */
116static USBInEndpointState mouse_ep_state; 118static USBInEndpointState mouse_ep_state;
117 119
@@ -128,45 +130,26 @@ static const USBEndpointConfig mouse_ep_config = {
128 2, /* IN multiplier */ 130 2, /* IN multiplier */
129 NULL /* SETUP buffer (not a SETUP endpoint) */ 131 NULL /* SETUP buffer (not a SETUP endpoint) */
130}; 132};
131#endif /* MOUSE_ENABLE */ 133#endif
132
133#ifdef EXTRAKEY_ENABLE
134/* extrakey endpoint state structure */
135static USBInEndpointState extra_ep_state;
136
137/* extrakey endpoint initialization structure (IN) */
138static const USBEndpointConfig extra_ep_config = {
139 USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
140 NULL, /* SETUP packet notification callback */
141 extra_in_cb, /* IN notification callback */
142 NULL, /* OUT notification callback */
143 EXTRAKEY_EPSIZE, /* IN maximum packet size */
144 0, /* OUT maximum packet size */
145 &extra_ep_state, /* IN Endpoint state */
146 NULL, /* OUT endpoint state */
147 2, /* IN multiplier */
148 NULL /* SETUP buffer (not a SETUP endpoint) */
149};
150#endif /* EXTRAKEY_ENABLE */
151 134
152#ifdef NKRO_ENABLE 135#ifdef SHARED_EP_ENABLE
153/* nkro endpoint state structure */ 136/* shared endpoint state structure */
154static USBInEndpointState nkro_ep_state; 137static USBInEndpointState shared_ep_state;
155 138
156/* nkro endpoint initialization structure (IN) */ 139/* shared endpoint initialization structure (IN) */
157static const USBEndpointConfig nkro_ep_config = { 140static const USBEndpointConfig shared_ep_config = {
158 USB_EP_MODE_TYPE_INTR, /* Interrupt EP */ 141 USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
159 NULL, /* SETUP packet notification callback */ 142 NULL, /* SETUP packet notification callback */
160 nkro_in_cb, /* IN notification callback */ 143 shared_in_cb, /* IN notification callback */
161 NULL, /* OUT notification callback */ 144 NULL, /* OUT notification callback */
162 NKRO_EPSIZE, /* IN maximum packet size */ 145 SHARED_EPSIZE, /* IN maximum packet size */
163 0, /* OUT maximum packet size */ 146 0, /* OUT maximum packet size */
164 &nkro_ep_state, /* IN Endpoint state */ 147 &shared_ep_state, /* IN Endpoint state */
165 NULL, /* OUT endpoint state */ 148 NULL, /* OUT endpoint state */
166 2, /* IN multiplier */ 149 2, /* IN multiplier */
167 NULL /* SETUP buffer (not a SETUP endpoint) */ 150 NULL /* SETUP buffer (not a SETUP endpoint) */
168}; 151};
169#endif /* NKRO_ENABLE */ 152#endif
170 153
171typedef struct { 154typedef struct {
172 size_t queue_capacity_in; 155 size_t queue_capacity_in;
@@ -309,16 +292,15 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
309 case USB_EVENT_CONFIGURED: 292 case USB_EVENT_CONFIGURED:
310 osalSysLockFromISR(); 293 osalSysLockFromISR();
311 /* Enable the endpoints specified into the configuration. */ 294 /* Enable the endpoints specified into the configuration. */
295#ifndef KEYBOARD_SHARED_EP
312 usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config); 296 usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
313#ifdef MOUSE_ENABLE 297#endif
298#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
314 usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config); 299 usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config);
315#endif /* MOUSE_ENABLE */ 300#endif
316#ifdef EXTRAKEY_ENABLE 301#ifdef SHARED_EP_ENABLE
317 usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config); 302 usbInitEndpointI(usbp, SHARED_IN_EPNUM, &shared_ep_config);
318#endif /* EXTRAKEY_ENABLE */ 303#endif
319#ifdef NKRO_ENABLE
320 usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config);
321#endif /* NKRO_ENABLE */
322 for (int i=0;i<NUM_USB_DRIVERS;i++) { 304 for (int i=0;i<NUM_USB_DRIVERS;i++) {
323 usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config); 305 usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config);
324 usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config); 306 usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config);
@@ -389,9 +371,20 @@ static uint16_t get_hword(uint8_t *p) {
389 * Other Device Required Optional Optional Optional Optional Optional 371 * Other Device Required Optional Optional Optional Optional Optional
390 */ 372 */
391 373
374#ifdef SHARED_EP_ENABLE
375static uint8_t set_report_buf[2] __attribute__((aligned(2)));
376static void set_led_transfer_cb(USBDriver *usbp) {
377 if ((set_report_buf[0] == REPORT_ID_KEYBOARD) ||
378 (set_report_buf[0] == REPORT_ID_NKRO)) {
379 keyboard_led_stats = set_report_buf[1];
380 }
381}
382#endif
383
392/* Callback for SETUP request on the endpoint 0 (control) */ 384/* Callback for SETUP request on the endpoint 0 (control) */
393static bool usb_request_hook_cb(USBDriver *usbp) { 385static bool usb_request_hook_cb(USBDriver *usbp) {
394 const USBDescriptor *dp; 386 const USBDescriptor *dp;
387 int has_report_id;
395 388
396 /* usbp->setup fields: 389 /* usbp->setup fields:
397 * 0: bmRequestType (bitmask) 390 * 0: bmRequestType (bitmask)
@@ -409,42 +402,16 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
409 case HID_GET_REPORT: 402 case HID_GET_REPORT:
410 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */ 403 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
411 case KEYBOARD_INTERFACE: 404 case KEYBOARD_INTERFACE:
412#ifdef NKRO_ENABLE
413 case NKRO_INTERFACE:
414#endif /* NKRO_ENABLE */
415 usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL); 405 usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
416 return TRUE; 406 return TRUE;
417 break; 407 break;
418 408
419#ifdef MOUSE_ENABLE 409#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
420 case MOUSE_INTERFACE: 410 case MOUSE_INTERFACE:
421 usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL); 411 usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
422 return TRUE; 412 return TRUE;
423 break; 413 break;
424#endif /* MOUSE_ENABLE */ 414#endif
425
426#ifdef EXTRAKEY_ENABLE
427 case EXTRAKEY_INTERFACE:
428 if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
429 switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
430 case REPORT_ID_SYSTEM:
431 extra_report_blank[0] = REPORT_ID_SYSTEM;
432 usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
433 return TRUE;
434 break;
435 case REPORT_ID_CONSUMER:
436 extra_report_blank[0] = REPORT_ID_CONSUMER;
437 usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
438 return TRUE;
439 break;
440 default:
441 return FALSE;
442 }
443 } else {
444 return FALSE;
445 }
446 break;
447#endif /* EXTRAKEY_ENABLE */
448 415
449 default: 416 default:
450 usbSetupTransfer(usbp, NULL, 0, NULL); 417 usbSetupTransfer(usbp, NULL, 0, NULL);
@@ -472,12 +439,25 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
472 case HID_SET_REPORT: 439 case HID_SET_REPORT:
473 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */ 440 switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
474 case KEYBOARD_INTERFACE: 441 case KEYBOARD_INTERFACE:
475#ifdef NKRO_ENABLE 442#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
476 case NKRO_INTERFACE: 443 case SHARED_INTERFACE:
477#endif /* NKRO_ENABLE */ 444#endif
478 /* keyboard_led_stats = <read byte from next OUT report> 445 /* keyboard_led_stats = <read byte from next OUT report>
479 * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */ 446 * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
480 usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL); 447 has_report_id = 0;
448#if defined(SHARED_EP_ENABLE)
449 if (usbp->setup[4] == SHARED_INTERFACE) {
450 has_report_id = 1;
451 }
452#endif
453 if (usbp->setup[4] == KEYBOARD_INTERFACE && !keyboard_protocol) {
454 has_report_id = 0;
455 }
456 if (has_report_id) {
457 usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
458 } else {
459 usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
460 }
481 return TRUE; 461 return TRUE;
482 break; 462 break;
483 } 463 }
@@ -591,20 +571,13 @@ void init_usb_driver(USBDriver *usbp) {
591 * --------------------------------------------------------- 571 * ---------------------------------------------------------
592 */ 572 */
593/* keyboard IN callback hander (a kbd report has made it IN) */ 573/* keyboard IN callback hander (a kbd report has made it IN) */
574#ifndef KEYBOARD_SHARED_EP
594void kbd_in_cb(USBDriver *usbp, usbep_t ep) { 575void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
595 /* STUB */ 576 /* STUB */
596 (void)usbp; 577 (void)usbp;
597 (void)ep; 578 (void)ep;
598} 579}
599 580#endif
600#ifdef NKRO_ENABLE
601/* nkro IN callback hander (a nkro report has made it IN) */
602void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
603 /* STUB */
604 (void)usbp;
605 (void)ep;
606}
607#endif /* NKRO_ENABLE */
608 581
609/* start-of-frame handler 582/* start-of-frame handler
610 * TODO: i guess it would be better to re-implement using timers, 583 * TODO: i guess it would be better to re-implement using timers,
@@ -628,9 +601,9 @@ static void keyboard_idle_timer_cb(void *arg) {
628 } 601 }
629 602
630#ifdef NKRO_ENABLE 603#ifdef NKRO_ENABLE
631 if(!keymap_config.nkro && keyboard_idle) { 604 if(!keymap_config.nkro && keyboard_idle && keyboard_protocol) {
632#else /* NKRO_ENABLE */ 605#else /* NKRO_ENABLE */
633 if(keyboard_idle) { 606 if(keyboard_idle && keyboard_protocol) {
634#endif /* NKRO_ENABLE */ 607#endif /* NKRO_ENABLE */
635 /* TODO: are we sure we want the KBD_ENDPOINT? */ 608 /* TODO: are we sure we want the KBD_ENDPOINT? */
636 if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) { 609 if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
@@ -661,25 +634,25 @@ void send_keyboard(report_keyboard_t *report) {
661 osalSysUnlock(); 634 osalSysUnlock();
662 635
663#ifdef NKRO_ENABLE 636#ifdef NKRO_ENABLE
664 if(keymap_config.nkro) { /* NKRO protocol */ 637 if(keymap_config.nkro && keyboard_protocol) { /* NKRO protocol */
665 /* need to wait until the previous packet has made it through */ 638 /* need to wait until the previous packet has made it through */
666 /* can rewrite this using the synchronous API, then would wait 639 /* can rewrite this using the synchronous API, then would wait
667 * until *after* the packet has been transmitted. I think 640 * until *after* the packet has been transmitted. I think
668 * this is more efficient */ 641 * this is more efficient */
669 /* busy wait, should be short and not very common */ 642 /* busy wait, should be short and not very common */
670 osalSysLock(); 643 osalSysLock();
671 if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_IN_EPNUM)) { 644 if(usbGetTransmitStatusI(&USB_DRIVER, SHARED_IN_EPNUM)) {
672 /* Need to either suspend, or loop and call unlock/lock during 645 /* Need to either suspend, or loop and call unlock/lock during
673 * every iteration - otherwise the system will remain locked, 646 * every iteration - otherwise the system will remain locked,
674 * no interrupts served, so USB not going through as well. 647 * no interrupts served, so USB not going through as well.
675 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */ 648 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
676 osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_IN_EPNUM]->in_state->thread); 649 osalThreadSuspendS(&(&USB_DRIVER)->epc[SHARED_IN_EPNUM]->in_state->thread);
677 } 650 }
678 usbStartTransmitI(&USB_DRIVER, NKRO_IN_EPNUM, (uint8_t *)report, sizeof(report_keyboard_t)); 651 usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)report, sizeof(struct nkro_report));
679 osalSysUnlock(); 652 osalSysUnlock();
680 } else 653 } else
681#endif /* NKRO_ENABLE */ 654#endif /* NKRO_ENABLE */
682 { /* boot protocol */ 655 { /* regular protocol */
683 /* need to wait until the previous packet has made it through */ 656 /* need to wait until the previous packet has made it through */
684 /* busy wait, should be short and not very common */ 657 /* busy wait, should be short and not very common */
685 osalSysLock(); 658 osalSysLock();
@@ -690,7 +663,15 @@ void send_keyboard(report_keyboard_t *report) {
690 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */ 663 * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
691 osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread); 664 osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread);
692 } 665 }
693 usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, (uint8_t *)report, KEYBOARD_EPSIZE); 666 uint8_t *data, size;
667 if (keyboard_protocol) {
668 data = (uint8_t*)report;
669 size = KEYBOARD_REPORT_SIZE;
670 } else { /* boot protocol */
671 data = &report->mods;
672 size = 8;
673 }
674 usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, data, size);
694 osalSysUnlock(); 675 osalSysUnlock();
695 } 676 }
696 keyboard_report_sent = *report; 677 keyboard_report_sent = *report;
@@ -703,11 +684,13 @@ void send_keyboard(report_keyboard_t *report) {
703 684
704#ifdef MOUSE_ENABLE 685#ifdef MOUSE_ENABLE
705 686
687#ifndef MOUSE_SHARED_EP
706/* mouse IN callback hander (a mouse report has made it IN) */ 688/* mouse IN callback hander (a mouse report has made it IN) */
707void mouse_in_cb(USBDriver *usbp, usbep_t ep) { 689void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
708 (void)usbp; 690 (void)usbp;
709 (void)ep; 691 (void)ep;
710} 692}
693#endif
711 694
712void send_mouse(report_mouse_t *report) { 695void send_mouse(report_mouse_t *report) {
713 osalSysLock(); 696 osalSysLock();
@@ -737,19 +720,24 @@ void send_mouse(report_mouse_t *report) {
737#endif /* MOUSE_ENABLE */ 720#endif /* MOUSE_ENABLE */
738 721
739/* --------------------------------------------------------- 722/* ---------------------------------------------------------
740 * Extrakey functions 723 * Shared EP functions
741 * --------------------------------------------------------- 724 * ---------------------------------------------------------
742 */ 725 */
743 726#ifdef SHARED_EP_ENABLE
744#ifdef EXTRAKEY_ENABLE 727/* shared IN callback hander */
745 728void shared_in_cb(USBDriver *usbp, usbep_t ep) {
746/* extrakey IN callback hander */
747void extra_in_cb(USBDriver *usbp, usbep_t ep) {
748 /* STUB */ 729 /* STUB */
749 (void)usbp; 730 (void)usbp;
750 (void)ep; 731 (void)ep;
751} 732}
733#endif
734
735/* ---------------------------------------------------------
736 * Extrakey functions
737 * ---------------------------------------------------------
738 */
752 739
740#ifdef EXTRAKEY_ENABLE
753static void send_extra_report(uint8_t report_id, uint16_t data) { 741static void send_extra_report(uint8_t report_id, uint16_t data) {
754 osalSysLock(); 742 osalSysLock();
755 if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) { 743 if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
@@ -762,7 +750,7 @@ static void send_extra_report(uint8_t report_id, uint16_t data) {
762 .usage = data 750 .usage = data
763 }; 751 };
764 752
765 usbStartTransmitI(&USB_DRIVER, EXTRAKEY_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t)); 753 usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
766 osalSysUnlock(); 754 osalSysUnlock();
767} 755}
768 756
diff --git a/tmk_core/protocol/chibios/usb_main.h b/tmk_core/protocol/chibios/usb_main.h
index 1f7eb12f8..55e8882cc 100644
--- a/tmk_core/protocol/chibios/usb_main.h
+++ b/tmk_core/protocol/chibios/usb_main.h
@@ -66,15 +66,20 @@ void mouse_in_cb(USBDriver *usbp, usbep_t ep);
66#endif /* MOUSE_ENABLE */ 66#endif /* MOUSE_ENABLE */
67 67
68/* --------------- 68/* ---------------
69 * Shared EP header
70 * ---------------
71 */
72
73/* shared IN request callback handler */
74void shared_in_cb(USBDriver *usbp, usbep_t ep);
75
76/* ---------------
69 * Extrakey header 77 * Extrakey header
70 * --------------- 78 * ---------------
71 */ 79 */
72 80
73#ifdef EXTRAKEY_ENABLE 81#ifdef EXTRAKEY_ENABLE
74 82
75/* extrakey IN request callback handler */
76void extra_in_cb(USBDriver *usbp, usbep_t ep);
77
78/* extra report structure */ 83/* extra report structure */
79typedef struct { 84typedef struct {
80 uint8_t report_id; 85 uint8_t report_id;
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 95e0b95b2..e88e6f34a 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -409,19 +409,21 @@ void EVENT_USB_Device_ConfigurationChanged(void)
409 bool ConfigSuccess = true; 409 bool ConfigSuccess = true;
410 410
411 /* Setup Keyboard HID Report Endpoints */ 411 /* Setup Keyboard HID Report Endpoints */
412#ifndef KEYBOARD_SHARED_EP
412 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, 413 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
413 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); 414 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
415#endif
414 416
415#ifdef MOUSE_ENABLE 417#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
416 /* Setup Mouse HID Report Endpoint */ 418 /* Setup Mouse HID Report Endpoint */
417 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, 419 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
418 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); 420 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
419#endif 421#endif
420 422
421#ifdef EXTRAKEY_ENABLE 423#ifdef SHARED_EP_ENABLE
422 /* Setup Extra HID Report Endpoint */ 424 /* Setup Shared HID Report Endpoint */
423 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, 425 ConfigSuccess &= ENDPOINT_CONFIG(SHARED_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
424 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE); 426 SHARED_EPSIZE, ENDPOINT_BANK_SINGLE);
425#endif 427#endif
426 428
427#ifdef RAW_ENABLE 429#ifdef RAW_ENABLE
@@ -442,12 +444,6 @@ void EVENT_USB_Device_ConfigurationChanged(void)
442#endif 444#endif
443#endif 445#endif
444 446
445#ifdef NKRO_ENABLE
446 /* Setup NKRO HID Report Endpoints */
447 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
448 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
449#endif
450
451#ifdef MIDI_ENABLE 447#ifdef MIDI_ENABLE
452 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); 448 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
453 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); 449 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
@@ -512,8 +508,8 @@ void EVENT_USB_Device_ControlRequest(void)
512 // Interface 508 // Interface
513 switch (USB_ControlRequest.wIndex) { 509 switch (USB_ControlRequest.wIndex) {
514 case KEYBOARD_INTERFACE: 510 case KEYBOARD_INTERFACE:
515#ifdef NKRO_ENABLE 511#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
516 case NKRO_INTERFACE: 512 case SHARED_INTERFACE:
517#endif 513#endif
518 Endpoint_ClearSETUP(); 514 Endpoint_ClearSETUP();
519 515
@@ -521,7 +517,17 @@ void EVENT_USB_Device_ControlRequest(void)
521 if (USB_DeviceState == DEVICE_STATE_Unattached) 517 if (USB_DeviceState == DEVICE_STATE_Unattached)
522 return; 518 return;
523 } 519 }
520#if defined(SHARED_EP_ENABLE)
521 uint8_t report_id = REPORT_ID_KEYBOARD;
522 if (keyboard_protocol) {
523 report_id = Endpoint_Read_8();
524 }
525 if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
526 keyboard_led_stats = Endpoint_Read_8();
527 }
528#else
524 keyboard_led_stats = Endpoint_Read_8(); 529 keyboard_led_stats = Endpoint_Read_8();
530#endif
525 531
526 Endpoint_ClearOUT(); 532 Endpoint_ClearOUT();
527 Endpoint_ClearStatusStage(); 533 Endpoint_ClearStatusStage();
@@ -612,16 +618,20 @@ static void send_keyboard(report_keyboard_t *report)
612 #ifdef MODULE_ADAFRUIT_BLE 618 #ifdef MODULE_ADAFRUIT_BLE
613 adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys)); 619 adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
614 #elif MODULE_RN42 620 #elif MODULE_RN42
615 bluefruit_serial_send(0xFD); 621 bluefruit_serial_send(0xFD);
616 bluefruit_serial_send(0x09); 622 bluefruit_serial_send(0x09);
617 bluefruit_serial_send(0x01); 623 bluefruit_serial_send(0x01);
618 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) { 624 bluefruit_serial_send(report->mods);
619 bluefruit_serial_send(report->raw[i]); 625 bluefruit_serial_send(report->reserved);
620 } 626 for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
627 bluefruit_serial_send(report->keys[i]);
628 }
621 #else 629 #else
622 bluefruit_serial_send(0xFD); 630 bluefruit_serial_send(0xFD);
623 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) { 631 bluefruit_serial_send(report->mods);
624 bluefruit_serial_send(report->raw[i]); 632 bluefruit_serial_send(report->reserved);
633 for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
634 bluefruit_serial_send(report->keys[i]);
625 } 635 }
626 #endif 636 #endif
627 } 637 }
@@ -632,30 +642,24 @@ static void send_keyboard(report_keyboard_t *report)
632 } 642 }
633 643
634 /* Select the Keyboard Report Endpoint */ 644 /* Select the Keyboard Report Endpoint */
645 uint8_t ep = KEYBOARD_IN_EPNUM;
646 uint8_t size = KEYBOARD_REPORT_SIZE;
635#ifdef NKRO_ENABLE 647#ifdef NKRO_ENABLE
636 if (keyboard_protocol && keymap_config.nkro) { 648 if (keyboard_protocol && keymap_config.nkro) {
637 /* Report protocol - NKRO */ 649 ep = SHARED_IN_EPNUM;
638 Endpoint_SelectEndpoint(NKRO_IN_EPNUM); 650 size = sizeof(struct nkro_report);
639
640 /* Check if write ready for a polling interval around 1ms */
641 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
642 if (!Endpoint_IsReadWriteAllowed()) return;
643
644 /* Write Keyboard Report Data */
645 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
646 } 651 }
647 else
648#endif 652#endif
649 { 653 Endpoint_SelectEndpoint(ep);
650 /* Boot protocol */ 654 /* Check if write ready for a polling interval around 10ms */
651 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); 655 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
652 656 if (!Endpoint_IsReadWriteAllowed()) return;
653 /* Check if write ready for a polling interval around 10ms */
654 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
655 if (!Endpoint_IsReadWriteAllowed()) return;
656 657
657 /* Write Keyboard Report Data */ 658 /* If we're in Boot Protocol, don't send any report ID or other funky fields */
658 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL); 659 if (!keyboard_protocol) {
660 Endpoint_Write_Stream_LE(&report->mods, 8, NULL);
661 } else {
662 Endpoint_Write_Stream_LE(report, size, NULL);
659 } 663 }
660 664
661 /* Finalize the stream transfer to send the last packet */ 665 /* Finalize the stream transfer to send the last packet */
@@ -718,6 +722,7 @@ static void send_mouse(report_mouse_t *report)
718 */ 722 */
719static void send_system(uint16_t data) 723static void send_system(uint16_t data)
720{ 724{
725#ifdef EXTRAKEY_ENABLE
721 uint8_t timeout = 255; 726 uint8_t timeout = 255;
722 727
723 if (USB_DeviceState != DEVICE_STATE_Configured) 728 if (USB_DeviceState != DEVICE_STATE_Configured)
@@ -727,7 +732,7 @@ static void send_system(uint16_t data)
727 .report_id = REPORT_ID_SYSTEM, 732 .report_id = REPORT_ID_SYSTEM,
728 .usage = data - SYSTEM_POWER_DOWN + 1 733 .usage = data - SYSTEM_POWER_DOWN + 1
729 }; 734 };
730 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); 735 Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
731 736
732 /* Check if write ready for a polling interval around 10ms */ 737 /* Check if write ready for a polling interval around 10ms */
733 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); 738 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
@@ -735,6 +740,7 @@ static void send_system(uint16_t data)
735 740
736 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); 741 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
737 Endpoint_ClearIN(); 742 Endpoint_ClearIN();
743#endif
738} 744}
739 745
740/** \brief Send Consumer 746/** \brief Send Consumer
@@ -743,6 +749,7 @@ static void send_system(uint16_t data)
743 */ 749 */
744static void send_consumer(uint16_t data) 750static void send_consumer(uint16_t data)
745{ 751{
752#ifdef EXTRAKEY_ENABLE
746 uint8_t timeout = 255; 753 uint8_t timeout = 255;
747 uint8_t where = where_to_send(); 754 uint8_t where = where_to_send();
748 755
@@ -786,7 +793,7 @@ static void send_consumer(uint16_t data)
786 .report_id = REPORT_ID_CONSUMER, 793 .report_id = REPORT_ID_CONSUMER,
787 .usage = data 794 .usage = data
788 }; 795 };
789 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); 796 Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
790 797
791 /* Check if write ready for a polling interval around 10ms */ 798 /* Check if write ready for a polling interval around 10ms */
792 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); 799 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
@@ -794,6 +801,7 @@ static void send_consumer(uint16_t data)
794 801
795 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); 802 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
796 Endpoint_ClearIN(); 803 Endpoint_ClearIN();
804#endif
797} 805}
798 806
799 807
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index cab344675..589ad23cd 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -47,11 +47,18 @@
47/******************************************************************************* 47/*******************************************************************************
48 * HID Report Descriptors 48 * HID Report Descriptors
49 ******************************************************************************/ 49 ******************************************************************************/
50const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = 50#ifdef KEYBOARD_SHARED_EP
51{ 51const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
52#define SHARED_REPORT_STARTED
53#else
54const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
55#endif
52 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ 56 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
53 HID_RI_USAGE(8, 0x06), /* Keyboard */ 57 HID_RI_USAGE(8, 0x06), /* Keyboard */
54 HID_RI_COLLECTION(8, 0x01), /* Application */ 58 HID_RI_COLLECTION(8, 0x01), /* Application */
59# ifdef KEYBOARD_SHARED_EP
60 HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD),
61# endif
55 HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ 62 HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
56 HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */ 63 HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
57 HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */ 64 HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
@@ -84,14 +91,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
84 HID_RI_REPORT_SIZE(8, 0x08), 91 HID_RI_REPORT_SIZE(8, 0x08),
85 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), 92 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
86 HID_RI_END_COLLECTION(0), 93 HID_RI_END_COLLECTION(0),
94
95#ifndef KEYBOARD_SHARED_EP
87}; 96};
97#endif
88 98
89#ifdef MOUSE_ENABLE 99#if defined(MOUSE_ENABLE)
90const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = 100
91{ 101# if !defined(MOUSE_SHARED_EP)
102const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = {
103# elif !defined(SHARED_REPORT_STARTED)
104const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
105#define SHARED_REPORT_STARTED
106# endif
92 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ 107 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
93 HID_RI_USAGE(8, 0x02), /* Mouse */ 108 HID_RI_USAGE(8, 0x02), /* Mouse */
94 HID_RI_COLLECTION(8, 0x01), /* Application */ 109 HID_RI_COLLECTION(8, 0x01), /* Application */
110# ifdef MOUSE_SHARED_EP
111 HID_RI_REPORT_ID(8, REPORT_ID_MOUSE),
112# endif
95 HID_RI_USAGE(8, 0x01), /* Pointer */ 113 HID_RI_USAGE(8, 0x01), /* Pointer */
96 HID_RI_COLLECTION(8, 0x00), /* Physical */ 114 HID_RI_COLLECTION(8, 0x00), /* Physical */
97 115
@@ -133,12 +151,15 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
133 151
134 HID_RI_END_COLLECTION(0), 152 HID_RI_END_COLLECTION(0),
135 HID_RI_END_COLLECTION(0), 153 HID_RI_END_COLLECTION(0),
154# ifndef MOUSE_SHARED_EP
136}; 155};
156# endif
137#endif 157#endif
138 158
139#ifdef EXTRAKEY_ENABLE 159#if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED)
140const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] = 160const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
141{ 161#endif
162# ifdef EXTRAKEY_ENABLE
142 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ 163 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
143 HID_RI_USAGE(8, 0x80), /* System Control */ 164 HID_RI_USAGE(8, 0x80), /* System Control */
144 HID_RI_COLLECTION(8, 0x01), /* Application */ 165 HID_RI_COLLECTION(8, 0x01), /* Application */
@@ -164,6 +185,43 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
164 HID_RI_REPORT_COUNT(8, 1), 185 HID_RI_REPORT_COUNT(8, 1),
165 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), 186 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
166 HID_RI_END_COLLECTION(0), 187 HID_RI_END_COLLECTION(0),
188# endif
189
190# ifdef NKRO_ENABLE
191 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
192 HID_RI_USAGE(8, 0x06), /* Keyboard */
193 HID_RI_COLLECTION(8, 0x01), /* Application */
194 HID_RI_REPORT_ID(8, REPORT_ID_NKRO),
195 HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
196 HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
197 HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
198 HID_RI_LOGICAL_MINIMUM(8, 0x00),
199 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
200 HID_RI_REPORT_COUNT(8, 0x08),
201 HID_RI_REPORT_SIZE(8, 0x01),
202 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
203
204 HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
205 HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
206 HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
207 HID_RI_REPORT_COUNT(8, 0x05),
208 HID_RI_REPORT_SIZE(8, 0x01),
209 HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
210 HID_RI_REPORT_COUNT(8, 0x01),
211 HID_RI_REPORT_SIZE(8, 0x03),
212 HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
213
214 HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
215 HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
216 HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS*8-1),
217 HID_RI_LOGICAL_MINIMUM(8, 0x00),
218 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
219 HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS*8),
220 HID_RI_REPORT_SIZE(8, 0x01),
221 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
222 HID_RI_END_COLLECTION(0),
223# endif
224#ifdef SHARED_EP_ENABLE
167}; 225};
168#endif 226#endif
169 227
@@ -211,42 +269,6 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
211}; 269};
212#endif 270#endif
213 271
214#ifdef NKRO_ENABLE
215const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
216{
217 HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
218 HID_RI_USAGE(8, 0x06), /* Keyboard */
219 HID_RI_COLLECTION(8, 0x01), /* Application */
220 HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
221 HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
222 HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
223 HID_RI_LOGICAL_MINIMUM(8, 0x00),
224 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
225 HID_RI_REPORT_COUNT(8, 0x08),
226 HID_RI_REPORT_SIZE(8, 0x01),
227 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
228
229 HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
230 HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
231 HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
232 HID_RI_REPORT_COUNT(8, 0x05),
233 HID_RI_REPORT_SIZE(8, 0x01),
234 HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
235 HID_RI_REPORT_COUNT(8, 0x01),
236 HID_RI_REPORT_SIZE(8, 0x03),
237 HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
238
239 HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
240 HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
241 HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
242 HID_RI_LOGICAL_MINIMUM(8, 0x00),
243 HID_RI_LOGICAL_MAXIMUM(8, 0x01),
244 HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
245 HID_RI_REPORT_SIZE(8, 0x01),
246 HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
247 HID_RI_END_COLLECTION(0),
248};
249#endif
250 272
251/******************************************************************************* 273/*******************************************************************************
252 * Device Descriptors 274 * Device Descriptors
@@ -303,6 +325,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
303 /* 325 /*
304 * Keyboard 326 * Keyboard
305 */ 327 */
328#ifndef KEYBOARD_SHARED_EP
306 .Keyboard_Interface = 329 .Keyboard_Interface =
307 { 330 {
308 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, 331 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
@@ -339,11 +362,12 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
339 .EndpointSize = KEYBOARD_EPSIZE, 362 .EndpointSize = KEYBOARD_EPSIZE,
340 .PollingIntervalMS = 0x0A 363 .PollingIntervalMS = 0x0A
341 }, 364 },
365#endif
342 366
343 /* 367 /*
344 * Mouse 368 * Mouse
345 */ 369 */
346#ifdef MOUSE_ENABLE 370#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
347 .Mouse_Interface = 371 .Mouse_Interface =
348 { 372 {
349 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, 373 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
@@ -383,26 +407,31 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
383#endif 407#endif
384 408
385 /* 409 /*
386 * Extra 410 * Shared
387 */ 411 */
388#ifdef EXTRAKEY_ENABLE 412#ifdef SHARED_EP_ENABLE
389 .Extrakey_Interface = 413 .Shared_Interface =
390 { 414 {
391 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, 415 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
392 416
393 .InterfaceNumber = EXTRAKEY_INTERFACE, 417 .InterfaceNumber = SHARED_INTERFACE,
394 .AlternateSetting = 0x00, 418 .AlternateSetting = 0x00,
395 419
396 .TotalEndpoints = 1, 420 .TotalEndpoints = 1,
397 421
398 .Class = HID_CSCP_HIDClass, 422 .Class = HID_CSCP_HIDClass,
423# ifdef KEYBOARD_SHARED_EP
424 .SubClass = HID_CSCP_BootSubclass,
425 .Protocol = HID_CSCP_KeyboardBootProtocol,
426# else
399 .SubClass = HID_CSCP_NonBootSubclass, 427 .SubClass = HID_CSCP_NonBootSubclass,
400 .Protocol = HID_CSCP_NonBootProtocol, 428 .Protocol = HID_CSCP_NonBootProtocol,
429#endif
401 430
402 .InterfaceStrIndex = NO_DESCRIPTOR 431 .InterfaceStrIndex = NO_DESCRIPTOR
403 }, 432 },
404 433
405 .Extrakey_HID = 434 .Shared_HID =
406 { 435 {
407 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, 436 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
408 437
@@ -410,16 +439,16 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
410 .CountryCode = 0x00, 439 .CountryCode = 0x00,
411 .TotalReportDescriptors = 1, 440 .TotalReportDescriptors = 1,
412 .HIDReportType = HID_DTYPE_Report, 441 .HIDReportType = HID_DTYPE_Report,
413 .HIDReportLength = sizeof(ExtrakeyReport) 442 .HIDReportLength = sizeof(SharedReport)
414 }, 443 },
415 444
416 .Extrakey_INEndpoint = 445 .Shared_INEndpoint =
417 { 446 {
418 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, 447 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
419 448
420 .EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM), 449 .EndpointAddress = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM),
421 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), 450 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
422 .EndpointSize = EXTRAKEY_EPSIZE, 451 .EndpointSize = SHARED_EPSIZE,
423 .PollingIntervalMS = 0x0A 452 .PollingIntervalMS = 0x0A
424 }, 453 },
425#endif 454#endif
@@ -528,48 +557,6 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
528 }, 557 },
529#endif 558#endif
530 559
531 /*
532 * NKRO
533 */
534#ifdef NKRO_ENABLE
535 .NKRO_Interface =
536 {
537 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
538
539 .InterfaceNumber = NKRO_INTERFACE,
540 .AlternateSetting = 0x00,
541
542 .TotalEndpoints = 1,
543
544 .Class = HID_CSCP_HIDClass,
545 .SubClass = HID_CSCP_NonBootSubclass,
546 .Protocol = HID_CSCP_NonBootProtocol,
547
548 .InterfaceStrIndex = NO_DESCRIPTOR
549 },
550
551 .NKRO_HID =
552 {
553 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
554
555 .HIDSpec = VERSION_BCD(1,1,1),
556 .CountryCode = 0x00,
557 .TotalReportDescriptors = 1,
558 .HIDReportType = HID_DTYPE_Report,
559 .HIDReportLength = sizeof(NKROReport)
560 },
561
562 .NKRO_INEndpoint =
563 {
564 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
565
566 .EndpointAddress = (ENDPOINT_DIR_IN | NKRO_IN_EPNUM),
567 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
568 .EndpointSize = NKRO_EPSIZE,
569 .PollingIntervalMS = 0x01
570 },
571#endif
572
573#ifdef MIDI_ENABLE 560#ifdef MIDI_ENABLE
574 .Audio_Interface_Association = 561 .Audio_Interface_Association =
575 { 562 {
@@ -936,19 +923,21 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
936 break; 923 break;
937 case HID_DTYPE_HID: 924 case HID_DTYPE_HID:
938 switch (wIndex) { 925 switch (wIndex) {
926#ifndef KEYBOARD_SHARED_EP
939 case KEYBOARD_INTERFACE: 927 case KEYBOARD_INTERFACE:
940 Address = &ConfigurationDescriptor.Keyboard_HID; 928 Address = &ConfigurationDescriptor.Keyboard_HID;
941 Size = sizeof(USB_HID_Descriptor_HID_t); 929 Size = sizeof(USB_HID_Descriptor_HID_t);
942 break; 930 break;
943#ifdef MOUSE_ENABLE 931#endif
932#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
944 case MOUSE_INTERFACE: 933 case MOUSE_INTERFACE:
945 Address = &ConfigurationDescriptor.Mouse_HID; 934 Address = &ConfigurationDescriptor.Mouse_HID;
946 Size = sizeof(USB_HID_Descriptor_HID_t); 935 Size = sizeof(USB_HID_Descriptor_HID_t);
947 break; 936 break;
948#endif 937#endif
949#ifdef EXTRAKEY_ENABLE 938#ifdef SHARED_EP_ENABLE
950 case EXTRAKEY_INTERFACE: 939 case SHARED_INTERFACE:
951 Address = &ConfigurationDescriptor.Extrakey_HID; 940 Address = &ConfigurationDescriptor.Shared_HID;
952 Size = sizeof(USB_HID_Descriptor_HID_t); 941 Size = sizeof(USB_HID_Descriptor_HID_t);
953 break; 942 break;
954#endif 943#endif
@@ -964,30 +953,26 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
964 Size = sizeof(USB_HID_Descriptor_HID_t); 953 Size = sizeof(USB_HID_Descriptor_HID_t);
965 break; 954 break;
966#endif 955#endif
967#ifdef NKRO_ENABLE
968 case NKRO_INTERFACE:
969 Address = &ConfigurationDescriptor.NKRO_HID;
970 Size = sizeof(USB_HID_Descriptor_HID_t);
971 break;
972#endif
973 } 956 }
974 break; 957 break;
975 case HID_DTYPE_Report: 958 case HID_DTYPE_Report:
976 switch (wIndex) { 959 switch (wIndex) {
960#ifndef KEYBOARD_SHARED_EP
977 case KEYBOARD_INTERFACE: 961 case KEYBOARD_INTERFACE:
978 Address = &KeyboardReport; 962 Address = &KeyboardReport;
979 Size = sizeof(KeyboardReport); 963 Size = sizeof(KeyboardReport);
980 break; 964 break;
981#ifdef MOUSE_ENABLE 965#endif
966#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
982 case MOUSE_INTERFACE: 967 case MOUSE_INTERFACE:
983 Address = &MouseReport; 968 Address = &MouseReport;
984 Size = sizeof(MouseReport); 969 Size = sizeof(MouseReport);
985 break; 970 break;
986#endif 971#endif
987#ifdef EXTRAKEY_ENABLE 972#ifdef SHARED_EP_ENABLE
988 case EXTRAKEY_INTERFACE: 973 case SHARED_INTERFACE:
989 Address = &ExtrakeyReport; 974 Address = &SharedReport;
990 Size = sizeof(ExtrakeyReport); 975 Size = sizeof(SharedReport);
991 break; 976 break;
992#endif 977#endif
993#ifdef RAW_ENABLE 978#ifdef RAW_ENABLE
@@ -1002,12 +987,6 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
1002 Size = sizeof(ConsoleReport); 987 Size = sizeof(ConsoleReport);
1003 break; 988 break;
1004#endif 989#endif
1005#ifdef NKRO_ENABLE
1006 case NKRO_INTERFACE:
1007 Address = &NKROReport;
1008 Size = sizeof(NKROReport);
1009 break;
1010#endif
1011 } 990 }
1012 break; 991 break;
1013 } 992 }
diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h
index 586d07df6..3ca0c00b3 100644
--- a/tmk_core/protocol/usb_descriptor.h
+++ b/tmk_core/protocol/usb_descriptor.h
@@ -53,26 +53,27 @@ typedef struct
53{ 53{
54 USB_Descriptor_Configuration_Header_t Config; 54 USB_Descriptor_Configuration_Header_t Config;
55 55
56#ifndef KEYBOARD_SHARED_EP
56 // Keyboard HID Interface 57 // Keyboard HID Interface
57 USB_Descriptor_Interface_t Keyboard_Interface; 58 USB_Descriptor_Interface_t Keyboard_Interface;
58 USB_HID_Descriptor_HID_t Keyboard_HID; 59 USB_HID_Descriptor_HID_t Keyboard_HID;
59 USB_Descriptor_Endpoint_t Keyboard_INEndpoint; 60 USB_Descriptor_Endpoint_t Keyboard_INEndpoint;
61#endif
60 62
61#ifdef MOUSE_ENABLE 63#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
62 // Mouse HID Interface 64 // Mouse HID Interface
63 USB_Descriptor_Interface_t Mouse_Interface; 65 USB_Descriptor_Interface_t Mouse_Interface;
64 USB_HID_Descriptor_HID_t Mouse_HID; 66 USB_HID_Descriptor_HID_t Mouse_HID;
65 USB_Descriptor_Endpoint_t Mouse_INEndpoint; 67 USB_Descriptor_Endpoint_t Mouse_INEndpoint;
66#endif 68#endif
67 69
68#ifdef EXTRAKEY_ENABLE 70#if defined(SHARED_EP_ENABLE)
69 // Extrakey HID Interface 71 USB_Descriptor_Interface_t Shared_Interface;
70 USB_Descriptor_Interface_t Extrakey_Interface; 72 USB_HID_Descriptor_HID_t Shared_HID;
71 USB_HID_Descriptor_HID_t Extrakey_HID; 73 USB_Descriptor_Endpoint_t Shared_INEndpoint;
72 USB_Descriptor_Endpoint_t Extrakey_INEndpoint;
73#endif 74#endif
74 75
75#ifdef RAW_ENABLE 76#if defined(RAW_ENABLE)
76 // Raw HID Interface 77 // Raw HID Interface
77 USB_Descriptor_Interface_t Raw_Interface; 78 USB_Descriptor_Interface_t Raw_Interface;
78 USB_HID_Descriptor_HID_t Raw_HID; 79 USB_HID_Descriptor_HID_t Raw_HID;
@@ -88,13 +89,6 @@ typedef struct
88 USB_Descriptor_Endpoint_t Console_OUTEndpoint; 89 USB_Descriptor_Endpoint_t Console_OUTEndpoint;
89#endif 90#endif
90 91
91#ifdef NKRO_ENABLE
92 // NKRO HID Interface
93 USB_Descriptor_Interface_t NKRO_Interface;
94 USB_HID_Descriptor_HID_t NKRO_HID;
95 USB_Descriptor_Endpoint_t NKRO_INEndpoint;
96#endif
97
98#ifdef MIDI_ENABLE 92#ifdef MIDI_ENABLE
99 USB_Descriptor_Interface_Association_t Audio_Interface_Association; 93 USB_Descriptor_Interface_Association_t Audio_Interface_Association;
100 // MIDI Audio Control Interface 94 // MIDI Audio Control Interface
@@ -133,133 +127,105 @@ typedef struct
133 127
134 128
135/* index of interface */ 129/* index of interface */
136#define KEYBOARD_INTERFACE 0 130enum usb_interfaces {
137 131#if !defined(KEYBOARD_SHARED_EP)
132 KEYBOARD_INTERFACE,
133#else
134# define KEYBOARD_INTERFACE SHARED_INTERFACE
135#endif
138// It is important that the Raw HID interface is at a constant 136// It is important that the Raw HID interface is at a constant
139// interface number, to support Linux/OSX platforms and chrome.hid 137// interface number, to support Linux/OSX platforms and chrome.hid
140// If Raw HID is enabled, let it be always 1. 138// If Raw HID is enabled, let it be always 1.
141#ifdef RAW_ENABLE 139#if defined(RAW_ENABLE)
142# define RAW_INTERFACE (KEYBOARD_INTERFACE + 1) 140 RAW_INTERFACE,
143#else
144# define RAW_INTERFACE KEYBOARD_INTERFACE
145#endif 141#endif
146 142#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
147#ifdef MOUSE_ENABLE 143 MOUSE_INTERFACE,
148# define MOUSE_INTERFACE (RAW_INTERFACE + 1)
149#else
150# define MOUSE_INTERFACE RAW_INTERFACE
151#endif 144#endif
152 145#if defined(SHARED_EP_ENABLE)
153#ifdef EXTRAKEY_ENABLE 146 SHARED_INTERFACE,
154# define EXTRAKEY_INTERFACE (MOUSE_INTERFACE + 1)
155#else
156# define EXTRAKEY_INTERFACE MOUSE_INTERFACE
157#endif 147#endif
158 148#if defined(CONSOLE_ENABLE)
159#ifdef CONSOLE_ENABLE 149 CONSOLE_INTERFACE,
160# define CONSOLE_INTERFACE (EXTRAKEY_INTERFACE + 1)
161#else
162# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
163#endif
164
165#ifdef NKRO_ENABLE
166# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
167#else
168# define NKRO_INTERFACE CONSOLE_INTERFACE
169#endif 150#endif
170 151#if defined(MIDI_ENABLE)
171#ifdef MIDI_ENABLE 152 AC_INTERFACE,
172# define AC_INTERFACE (NKRO_INTERFACE + 1) 153 AS_INTERFACE,
173# define AS_INTERFACE (NKRO_INTERFACE + 2)
174#else
175# define AS_INTERFACE NKRO_INTERFACE
176#endif 154#endif
177 155#if defined(VIRTSER_ENABLE)
178#ifdef VIRTSER_ENABLE 156 CCI_INTERFACE,
179# define CCI_INTERFACE (AS_INTERFACE + 1) 157 CDI_INTERFACE,
180# define CDI_INTERFACE (AS_INTERFACE + 2)
181#else
182# define CDI_INTERFACE AS_INTERFACE
183#endif 158#endif
159 TOTAL_INTERFACES
160};
184 161
185/* nubmer of interfaces */ 162#define NEXT_EPNUM __COUNTER__
186#define TOTAL_INTERFACES (CDI_INTERFACE + 1)
187
188 163
189// Endopoint number and size 164enum usb_endpoints {
190#define KEYBOARD_IN_EPNUM 1 165 __unused_epnum__ = NEXT_EPNUM, /* EP numbering starts at 1 */
191 166#if !defined(KEYBOARD_SHARED_EP)
192#ifdef MOUSE_ENABLE 167 KEYBOARD_IN_EPNUM = NEXT_EPNUM,
193# define MOUSE_IN_EPNUM (KEYBOARD_IN_EPNUM + 1)
194#else 168#else
195# define MOUSE_IN_EPNUM KEYBOARD_IN_EPNUM 169# define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
196#endif 170#endif
197 171#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
198#ifdef EXTRAKEY_ENABLE 172 MOUSE_IN_EPNUM = NEXT_EPNUM,
199# define EXTRAKEY_IN_EPNUM (MOUSE_IN_EPNUM + 1)
200#else 173#else
201# define EXTRAKEY_IN_EPNUM MOUSE_IN_EPNUM 174# define MOUSE_IN_EPNUM SHARED_IN_EPNUM
202#endif 175#endif
203 176#if defined(RAW_ENABLE)
204#ifdef RAW_ENABLE 177 RAW_IN_EPNUM = NEXT_EPNUM,
205# define RAW_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1) 178 RAW_OUT_EPNUM = NEXT_EPNUM,
206# define RAW_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
207#else
208# define RAW_OUT_EPNUM EXTRAKEY_IN_EPNUM
209#endif 179#endif
210 180#if defined(SHARED_EP_ENABLE)
211#ifdef CONSOLE_ENABLE 181 SHARED_IN_EPNUM = NEXT_EPNUM,
212# define CONSOLE_IN_EPNUM (RAW_OUT_EPNUM + 1) 182#endif
183#if defined(CONSOLE_ENABLE)
184 CONSOLE_IN_EPNUM = NEXT_EPNUM,
213#ifdef PROTOCOL_CHIBIOS 185#ifdef PROTOCOL_CHIBIOS
214// ChibiOS has enough memory and descriptor to actually enable the endpoint 186// ChibiOS has enough memory and descriptor to actually enable the endpoint
215// It could use the same endpoint numbers, as that's supported by ChibiOS 187// It could use the same endpoint numbers, as that's supported by ChibiOS
216// But the QMK code currently assumes that the endpoint numbers are different 188// But the QMK code currently assumes that the endpoint numbers are different
217# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 2) 189 CONSOLE_OUT_EPNUM = NEXT_EPNUM,
218#else 190#else
219# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 1) 191#define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM
220#endif 192#endif
221#else
222# define CONSOLE_OUT_EPNUM RAW_OUT_EPNUM
223#endif 193#endif
224
225#ifdef NKRO_ENABLE
226# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
227#else
228# define NKRO_IN_EPNUM CONSOLE_OUT_EPNUM
229#endif
230
231#ifdef MIDI_ENABLE 194#ifdef MIDI_ENABLE
232# define MIDI_STREAM_IN_EPNUM (NKRO_IN_EPNUM + 1) 195 MIDI_STREAM_IN_EPNUM = NEXT_EPNUM,
233// # define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 1) 196 MIDI_STREAM_OUT_EPNUM = NEXT_EPNUM,
234# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2)
235# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM) 197# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM)
236# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM) 198# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM)
237#else
238# define MIDI_STREAM_OUT_EPNUM NKRO_IN_EPNUM
239#endif 199#endif
240
241#ifdef VIRTSER_ENABLE 200#ifdef VIRTSER_ENABLE
242# define CDC_NOTIFICATION_EPNUM (MIDI_STREAM_OUT_EPNUM + 1) 201 CDC_NOTIFICATION_EPNUM = NEXT_EPNUM,
243# define CDC_IN_EPNUM (MIDI_STREAM_OUT_EPNUM + 2) 202 CDC_IN_EPNUM = NEXT_EPNUM,
244# define CDC_OUT_EPNUM (MIDI_STREAM_OUT_EPNUM + 3) 203 CDC_OUT_EPNUM = NEXT_EPNUM,
245# define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM) 204# define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM)
246# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM) 205# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
247# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM) 206# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
248#else
249# define CDC_OUT_EPNUM MIDI_STREAM_OUT_EPNUM
250#endif 207#endif
208};
209
210#if defined(PROTOCOL_LUFA)
211/* LUFA tells us total endpoints including control */
212#define MAX_ENDPOINTS (ENDPOINT_TOTAL_ENDPOINTS - 1)
213#elif defined(PROTOCOL_CHIBIOS)
214/* ChibiOS gives us number of available user endpoints, not control */
215#define MAX_ENDPOINTS USB_MAX_ENDPOINTS
216#endif
217/* TODO - ARM_ATSAM */
218
251 219
252#if (defined(PROTOCOL_LUFA) && CDC_OUT_EPNUM > (ENDPOINT_TOTAL_ENDPOINTS - 1)) || \ 220#if (NEXT_EPNUM - 1) > MAX_ENDPOINTS
253 (defined(PROTOCOL_CHIBIOS) && CDC_OUT_EPNUM > USB_MAX_ENDPOINTS) 221# error There are not enough available endpoints to support all functions. Remove some in the rules.mk file. (MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL, STENO)
254# error "There are not enough available endpoints to support all functions. Remove some in the rules.mk file.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL, STENO)"
255#endif 222#endif
256 223
257#define KEYBOARD_EPSIZE 8 224#define KEYBOARD_EPSIZE 8
225#define SHARED_EPSIZE 32
258#define MOUSE_EPSIZE 8 226#define MOUSE_EPSIZE 8
259#define EXTRAKEY_EPSIZE 8
260#define RAW_EPSIZE 32 227#define RAW_EPSIZE 32
261#define CONSOLE_EPSIZE 32 228#define CONSOLE_EPSIZE 32
262#define NKRO_EPSIZE 32
263#define MIDI_STREAM_EPSIZE 64 229#define MIDI_STREAM_EPSIZE 64
264#define CDC_NOTIFICATION_EPSIZE 8 230#define CDC_NOTIFICATION_EPSIZE 8
265#define CDC_EPSIZE 16 231#define CDC_EPSIZE 16