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
pull/4434/head
James Laird-Wah 6 years ago committed by Drashna Jaelre
parent 46cf8cc9b3
commit 39bd760faf

@ -261,3 +261,32 @@ Use these to enable or disable building certain features. The more you have enab
* Forces the keyboard to wait for a USB connection to be established before it starts up * Forces the keyboard to wait for a USB connection to be established before it starts up
* `NO_USB_STARTUP_CHECK` * `NO_USB_STARTUP_CHECK`
* 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. * 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.
## USB Endpoint Limitations
In order to provide services over USB, QMK has to use USB endpoints.
These are a finite resource: each microcontroller has only a certain number.
This limits what features can be enabled together.
If the available endpoints are exceeded, a build error is thrown.
The following features can require separate endpoints:
* `MOUSEKEY_ENABLE`
* `EXTRAKEY_ENABLE`
* `CONSOLE_ENABLE`
* `NKRO_ENABLE`
* `MIDI_ENABLE`
* `RAW_ENABLE`
* `VIRTSER_ENABLE`
In order to improve utilisation of the endpoints, the HID features can be combined to use a single endpoint.
By default, `MOUSEKEY`, `EXTRAKEY`, and `NKRO` are combined into a single endpoint.
The base keyboard functionality can also be combined into the endpoint,
by setting `KEYBOARD_SHARED_EP = yes`.
This frees up one more endpoint,
but it can prevent the keyboard working in some BIOSes,
as they do not implement Boot Keyboard protocol switching.
Combining the mouse also breaks Boot Mouse compatibility.
The mouse can be uncombined by setting `MOUSE_SHARED_EP = no` if this functionality is required.

@ -82,15 +82,31 @@ else
TMK_COMMON_SRC += $(COMMON_DIR)/magic.c TMK_COMMON_SRC += $(COMMON_DIR)/magic.c
endif endif
SHARED_EP_ENABLE = no
MOUSE_SHARED_EP ?= yes
ifeq ($(strip $(KEYBOARD_SHARED_EP)), yes)
TMK_COMMON_DEFS += -DKEYBOARD_SHARED_EP
SHARED_EP_ENABLE = yes
# With the current usb_descriptor.c code,
# you can't share kbd without sharing mouse;
# that would be a very unexpected use case anyway
MOUSE_SHARED_EP = yes
endif
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes) ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
TMK_COMMON_SRC += $(COMMON_DIR)/mousekey.c TMK_COMMON_SRC += $(COMMON_DIR)/mousekey.c
TMK_COMMON_DEFS += -DMOUSEKEY_ENABLE TMK_COMMON_DEFS += -DMOUSEKEY_ENABLE
TMK_COMMON_DEFS += -DMOUSE_ENABLE TMK_COMMON_DEFS += -DMOUSE_ENABLE
ifeq ($(strip $(MOUSE_SHARED_EP)), yes)
TMK_COMMON_DEFS += -DMOUSE_SHARED_EP
SHARED_EP_ENABLE = yes
endif
endif endif
ifeq ($(strip $(EXTRAKEY_ENABLE)), yes) ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE TMK_COMMON_DEFS += -DEXTRAKEY_ENABLE
SHARED_EP_ENABLE = yes
endif endif
ifeq ($(strip $(RAW_ENABLE)), yes) ifeq ($(strip $(RAW_ENABLE)), yes)
@ -111,6 +127,7 @@ endif
ifeq ($(strip $(NKRO_ENABLE)), yes) ifeq ($(strip $(NKRO_ENABLE)), yes)
TMK_COMMON_DEFS += -DNKRO_ENABLE TMK_COMMON_DEFS += -DNKRO_ENABLE
SHARED_EP_ENABLE = yes
endif endif
ifeq ($(strip $(USB_6KRO_ENABLE)), yes) ifeq ($(strip $(USB_6KRO_ENABLE)), yes)
@ -182,6 +199,10 @@ ifeq ($(strip $(KEYMAP_SECTION_ENABLE)), yes)
endif endif
endif endif
ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
TMK_COMMON_DEFS += -DSHARED_EP_ENABLE
endif
# Bootloader address # Bootloader address
ifdef STM32_BOOTLOADER_ADDRESS ifdef STM32_BOOTLOADER_ADDRESS
TMK_COMMON_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS) TMK_COMMON_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)

@ -22,6 +22,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "util.h" #include "util.h"
#include "debug.h" #include "debug.h"
#ifdef NKRO_ENABLE
#include "keycode_config.h"
extern keymap_config_t keymap_config;
#endif
static host_driver_t *driver; static host_driver_t *driver;
static uint16_t last_system_report = 0; static uint16_t last_system_report = 0;
static uint16_t last_consumer_report = 0; static uint16_t last_consumer_report = 0;
@ -46,6 +51,20 @@ uint8_t host_keyboard_leds(void)
void host_keyboard_send(report_keyboard_t *report) void host_keyboard_send(report_keyboard_t *report)
{ {
if (!driver) return; if (!driver) return;
#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP)
if (keyboard_protocol && keymap_config.nkro) {
/* The callers of this function assume that report->mods is where mods go in.
* But report->nkro.mods can be at a different offset if core keyboard does not have a report ID.
*/
report->nkro.mods = report->mods;
report->nkro.report_id = REPORT_ID_NKRO;
} else
#endif
{
#ifdef KEYBOARD_SHARED_EP
report->report_id = REPORT_ID_KEYBOARD;
#endif
}
(*driver->send_keyboard)(report); (*driver->send_keyboard)(report);
if (debug_keyboard) { if (debug_keyboard) {
@ -60,6 +79,9 @@ void host_keyboard_send(report_keyboard_t *report)
void host_mouse_send(report_mouse_t *report) void host_mouse_send(report_mouse_t *report)
{ {
if (!driver) return; if (!driver) return;
#ifdef MOUSE_SHARED_EP
report->report_id = REPORT_ID_MOUSE;
#endif
(*driver->send_mouse)(report); (*driver->send_mouse)(report);
} }

@ -19,6 +19,7 @@
#include "keycode_config.h" #include "keycode_config.h"
#include "debug.h" #include "debug.h"
#include "util.h" #include "util.h"
#include <string.h>
/** \brief has_anykey /** \brief has_anykey
* *
@ -27,8 +28,16 @@
uint8_t has_anykey(report_keyboard_t* keyboard_report) uint8_t has_anykey(report_keyboard_t* keyboard_report)
{ {
uint8_t cnt = 0; uint8_t cnt = 0;
for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) { uint8_t *p = keyboard_report->keys;
if (keyboard_report->raw[i]) uint8_t lp = sizeof(keyboard_report->keys);
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
p = keyboard_report->nkro.bits;
lp = sizeof(keyboard_report->nkro.bits);
}
#endif
while (lp--) {
if (*p++)
cnt++; cnt++;
} }
return cnt; return cnt;
@ -237,7 +246,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key)
void clear_keys_from_report(report_keyboard_t* keyboard_report) void clear_keys_from_report(report_keyboard_t* keyboard_report)
{ {
// not clear mods // not clear mods
for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) { #ifdef NKRO_ENABLE
keyboard_report->raw[i] = 0; if (keyboard_protocol && keymap_config.nkro) {
memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits));
return;
} }
#endif
memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys));
} }

@ -23,9 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* report id */ /* report id */
#define REPORT_ID_MOUSE 1 #define REPORT_ID_KEYBOARD 1
#define REPORT_ID_SYSTEM 2 #define REPORT_ID_MOUSE 2
#define REPORT_ID_CONSUMER 3 #define REPORT_ID_SYSTEM 3
#define REPORT_ID_CONSUMER 4
#define REPORT_ID_NKRO 5
/* mouse buttons */ /* mouse buttons */
#define MOUSE_BTN1 (1<<0) #define MOUSE_BTN1 (1<<0)
@ -72,32 +74,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SYSTEM_WAKE_UP 0x0083 #define SYSTEM_WAKE_UP 0x0083
#define NKRO_SHARED_EP
/* key report size(NKRO or boot mode) */ /* key report size(NKRO or boot mode) */
#if defined(NKRO_ENABLE) #if defined(NKRO_ENABLE)
#if defined(PROTOCOL_PJRC) #if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
#include "usb.h"
#define KEYBOARD_REPORT_SIZE KBD2_SIZE
#define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
#define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
#elif defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
#include "protocol/usb_descriptor.h" #include "protocol/usb_descriptor.h"
#define KEYBOARD_REPORT_SIZE NKRO_EPSIZE #define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2)
#define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
#define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
#elif defined(PROTOCOL_ARM_ATSAM) #elif defined(PROTOCOL_ARM_ATSAM)
#include "protocol/arm_atsam/usb/udi_device_epsize.h" #include "protocol/arm_atsam/usb/udi_device_epsize.h"
#define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
#define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
#define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1) #define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
#undef NKRO_SHARED_EP
#undef MOUSE_SHARED_EP
#else #else
#error "NKRO not supported with this protocol" #error "NKRO not supported with this protocol"
#endif
#endif #endif
#ifdef KEYBOARD_SHARED_EP
# define KEYBOARD_REPORT_SIZE 9
#else #else
# define KEYBOARD_REPORT_SIZE 8 # define KEYBOARD_REPORT_SIZE 8
# define KEYBOARD_REPORT_KEYS 6
#endif #endif
#define KEYBOARD_REPORT_KEYS 6
/* VUSB hardcodes keyboard and mouse+extrakey only */
#if defined(PROTOCOL_VUSB)
#undef KEYBOARD_SHARED_EP
#undef MOUSE_SHARED_EP
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -126,12 +131,18 @@ extern "C" {
typedef union { typedef union {
uint8_t raw[KEYBOARD_REPORT_SIZE]; uint8_t raw[KEYBOARD_REPORT_SIZE];
struct { struct {
#ifdef KEYBOARD_SHARED_EP
uint8_t report_id;
#endif
uint8_t mods; uint8_t mods;
uint8_t reserved; uint8_t reserved;
uint8_t keys[KEYBOARD_REPORT_KEYS]; uint8_t keys[KEYBOARD_REPORT_KEYS];
}; };
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
struct { struct nkro_report {
#ifdef NKRO_SHARED_EP
uint8_t report_id;
#endif
uint8_t mods; uint8_t mods;
uint8_t bits[KEYBOARD_REPORT_BITS]; uint8_t bits[KEYBOARD_REPORT_BITS];
} nkro; } nkro;
@ -139,6 +150,9 @@ typedef union {
} __attribute__ ((packed)) report_keyboard_t; } __attribute__ ((packed)) report_keyboard_t;
typedef struct { typedef struct {
#ifdef MOUSE_SHARED_EP
uint8_t report_id;
#endif
uint8_t buttons; uint8_t buttons;
int8_t x; int8_t x;
int8_t y; int8_t y;

@ -54,6 +54,7 @@
#include "udi_hid.h" #include "udi_hid.h"
#include "udi_hid_kbd.h" #include "udi_hid_kbd.h"
#include <string.h> #include <string.h>
#include "report.h"
//*************************************************************************** //***************************************************************************
// KBD // KBD
@ -430,7 +431,7 @@ UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
0x05, 0x01, // Usage Page (Generic Desktop), 0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x80, // Usage (System Control), 0x09, 0x80, // Usage (System Control),
0xA1, 0x01, // Collection (Application), 0xA1, 0x01, // Collection (Application),
0x85, 0x02, // Report ID (2) (System), 0x85, REPORT_ID_SYSTEM, // Report ID (2) (System),
0x16, 0x01, 0x00, // Logical Minimum (1), 0x16, 0x01, 0x00, // Logical Minimum (1),
0x26, 0x03, 0x00, // Logical Maximum (3), 0x26, 0x03, 0x00, // Logical Maximum (3),
0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down), 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 = {
0x05, 0x0C, // Usage Page (Consumer), 0x05, 0x0C, // Usage Page (Consumer),
0x09, 0x01, // Usage (Consumer Control), 0x09, 0x01, // Usage (Consumer Control),
0xA1, 0x01, // Collection (Application), 0xA1, 0x01, // Collection (Application),
0x85, 0x03, // Report ID (3) (Consumer), 0x85, REPORT_ID_CONSUMER, // Report ID (3) (Consumer),
0x16, 0x01, 0x00, // Logical Minimum (1), 0x16, 0x01, 0x00, // Logical Minimum (1),
0x26, 0x9C, 0x02, // Logical Maximum (668), 0x26, 0x9C, 0x02, // Logical Maximum (668),
0x1A, 0x01, 0x00, // Usage Minimum (1), 0x1A, 0x01, 0x00, // Usage Minimum (1),

@ -95,6 +95,7 @@ static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype
return &desc; return &desc;
} }
#ifndef KEYBOARD_SHARED_EP
/* keyboard endpoint state structure */ /* keyboard endpoint state structure */
static USBInEndpointState kbd_ep_state; static USBInEndpointState kbd_ep_state;
/* keyboard endpoint initialization structure (IN) */ /* keyboard endpoint initialization structure (IN) */
@ -110,8 +111,9 @@ static const USBEndpointConfig kbd_ep_config = {
2, /* IN multiplier */ 2, /* IN multiplier */
NULL /* SETUP buffer (not a SETUP endpoint) */ NULL /* SETUP buffer (not a SETUP endpoint) */
}; };
#endif
#ifdef MOUSE_ENABLE #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
/* mouse endpoint state structure */ /* mouse endpoint state structure */
static USBInEndpointState mouse_ep_state; static USBInEndpointState mouse_ep_state;
@ -128,45 +130,26 @@ static const USBEndpointConfig mouse_ep_config = {
2, /* IN multiplier */ 2, /* IN multiplier */
NULL /* SETUP buffer (not a SETUP endpoint) */ NULL /* SETUP buffer (not a SETUP endpoint) */
}; };
#endif /* MOUSE_ENABLE */ #endif
#ifdef EXTRAKEY_ENABLE
/* extrakey endpoint state structure */
static USBInEndpointState extra_ep_state;
/* extrakey endpoint initialization structure (IN) */
static const USBEndpointConfig extra_ep_config = {
USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
NULL, /* SETUP packet notification callback */
extra_in_cb, /* IN notification callback */
NULL, /* OUT notification callback */
EXTRAKEY_EPSIZE, /* IN maximum packet size */
0, /* OUT maximum packet size */
&extra_ep_state, /* IN Endpoint state */
NULL, /* OUT endpoint state */
2, /* IN multiplier */
NULL /* SETUP buffer (not a SETUP endpoint) */
};
#endif /* EXTRAKEY_ENABLE */
#ifdef NKRO_ENABLE #ifdef SHARED_EP_ENABLE
/* nkro endpoint state structure */ /* shared endpoint state structure */
static USBInEndpointState nkro_ep_state; static USBInEndpointState shared_ep_state;
/* nkro endpoint initialization structure (IN) */ /* shared endpoint initialization structure (IN) */
static const USBEndpointConfig nkro_ep_config = { static const USBEndpointConfig shared_ep_config = {
USB_EP_MODE_TYPE_INTR, /* Interrupt EP */ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
NULL, /* SETUP packet notification callback */ NULL, /* SETUP packet notification callback */
nkro_in_cb, /* IN notification callback */ shared_in_cb, /* IN notification callback */
NULL, /* OUT notification callback */ NULL, /* OUT notification callback */
NKRO_EPSIZE, /* IN maximum packet size */ SHARED_EPSIZE, /* IN maximum packet size */
0, /* OUT maximum packet size */ 0, /* OUT maximum packet size */
&nkro_ep_state, /* IN Endpoint state */ &shared_ep_state, /* IN Endpoint state */
NULL, /* OUT endpoint state */ NULL, /* OUT endpoint state */
2, /* IN multiplier */ 2, /* IN multiplier */
NULL /* SETUP buffer (not a SETUP endpoint) */ NULL /* SETUP buffer (not a SETUP endpoint) */
}; };
#endif /* NKRO_ENABLE */ #endif
typedef struct { typedef struct {
size_t queue_capacity_in; size_t queue_capacity_in;
@ -309,16 +292,15 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
case USB_EVENT_CONFIGURED: case USB_EVENT_CONFIGURED:
osalSysLockFromISR(); osalSysLockFromISR();
/* Enable the endpoints specified into the configuration. */ /* Enable the endpoints specified into the configuration. */
#ifndef KEYBOARD_SHARED_EP
usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config); usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
#ifdef MOUSE_ENABLE #endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config); usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config);
#endif /* MOUSE_ENABLE */ #endif
#ifdef EXTRAKEY_ENABLE #ifdef SHARED_EP_ENABLE
usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config); usbInitEndpointI(usbp, SHARED_IN_EPNUM, &shared_ep_config);
#endif /* EXTRAKEY_ENABLE */ #endif
#ifdef NKRO_ENABLE
usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config);
#endif /* NKRO_ENABLE */
for (int i=0;i<NUM_USB_DRIVERS;i++) { for (int i=0;i<NUM_USB_DRIVERS;i++) {
usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config); usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config);
usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config); 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) {
* Other Device Required Optional Optional Optional Optional Optional * Other Device Required Optional Optional Optional Optional Optional
*/ */
#ifdef SHARED_EP_ENABLE
static uint8_t set_report_buf[2] __attribute__((aligned(2)));
static void set_led_transfer_cb(USBDriver *usbp) {
if ((set_report_buf[0] == REPORT_ID_KEYBOARD) ||
(set_report_buf[0] == REPORT_ID_NKRO)) {
keyboard_led_stats = set_report_buf[1];
}
}
#endif
/* Callback for SETUP request on the endpoint 0 (control) */ /* Callback for SETUP request on the endpoint 0 (control) */
static bool usb_request_hook_cb(USBDriver *usbp) { static bool usb_request_hook_cb(USBDriver *usbp) {
const USBDescriptor *dp; const USBDescriptor *dp;
int has_report_id;
/* usbp->setup fields: /* usbp->setup fields:
* 0: bmRequestType (bitmask) * 0: bmRequestType (bitmask)
@ -409,42 +402,16 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
case HID_GET_REPORT: case HID_GET_REPORT:
switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */ switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
case KEYBOARD_INTERFACE: case KEYBOARD_INTERFACE:
#ifdef NKRO_ENABLE
case NKRO_INTERFACE:
#endif /* NKRO_ENABLE */
usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL); usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
return TRUE; return TRUE;
break; break;
#ifdef MOUSE_ENABLE #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
case MOUSE_INTERFACE: case MOUSE_INTERFACE:
usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL); usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
return TRUE; return TRUE;
break; break;
#endif /* MOUSE_ENABLE */ #endif
#ifdef EXTRAKEY_ENABLE
case EXTRAKEY_INTERFACE:
if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
case REPORT_ID_SYSTEM:
extra_report_blank[0] = REPORT_ID_SYSTEM;
usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
return TRUE;
break;
case REPORT_ID_CONSUMER:
extra_report_blank[0] = REPORT_ID_CONSUMER;
usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
return TRUE;
break;
default:
return FALSE;
}
} else {
return FALSE;
}
break;
#endif /* EXTRAKEY_ENABLE */
default: default:
usbSetupTransfer(usbp, NULL, 0, NULL); usbSetupTransfer(usbp, NULL, 0, NULL);
@ -472,12 +439,25 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
case HID_SET_REPORT: case HID_SET_REPORT:
switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */ switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
case KEYBOARD_INTERFACE: case KEYBOARD_INTERFACE:
#ifdef NKRO_ENABLE #if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
case NKRO_INTERFACE: case SHARED_INTERFACE:
#endif /* NKRO_ENABLE */ #endif
/* keyboard_led_stats = <read byte from next OUT report> /* keyboard_led_stats = <read byte from next OUT report>
* keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */ * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
has_report_id = 0;
#if defined(SHARED_EP_ENABLE)
if (usbp->setup[4] == SHARED_INTERFACE) {
has_report_id = 1;
}
#endif
if (usbp->setup[4] == KEYBOARD_INTERFACE && !keyboard_protocol) {
has_report_id = 0;
}
if (has_report_id) {
usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
} else {
usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL); usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
}
return TRUE; return TRUE;
break; break;
} }
@ -591,20 +571,13 @@ void init_usb_driver(USBDriver *usbp) {
* --------------------------------------------------------- * ---------------------------------------------------------
*/ */
/* keyboard IN callback hander (a kbd report has made it IN) */ /* keyboard IN callback hander (a kbd report has made it IN) */
#ifndef KEYBOARD_SHARED_EP
void kbd_in_cb(USBDriver *usbp, usbep_t ep) { void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
/* STUB */ /* STUB */
(void)usbp; (void)usbp;
(void)ep; (void)ep;
} }
#endif
#ifdef NKRO_ENABLE
/* nkro IN callback hander (a nkro report has made it IN) */
void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
/* STUB */
(void)usbp;
(void)ep;
}
#endif /* NKRO_ENABLE */
/* start-of-frame handler /* start-of-frame handler
* TODO: i guess it would be better to re-implement using timers, * TODO: i guess it would be better to re-implement using timers,
@ -628,9 +601,9 @@ static void keyboard_idle_timer_cb(void *arg) {
} }
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if(!keymap_config.nkro && keyboard_idle) { if(!keymap_config.nkro && keyboard_idle && keyboard_protocol) {
#else /* NKRO_ENABLE */ #else /* NKRO_ENABLE */
if(keyboard_idle) { if(keyboard_idle && keyboard_protocol) {
#endif /* NKRO_ENABLE */ #endif /* NKRO_ENABLE */
/* TODO: are we sure we want the KBD_ENDPOINT? */ /* TODO: are we sure we want the KBD_ENDPOINT? */
if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) { if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
@ -661,25 +634,25 @@ void send_keyboard(report_keyboard_t *report) {
osalSysUnlock(); osalSysUnlock();
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if(keymap_config.nkro) { /* NKRO protocol */ if(keymap_config.nkro && keyboard_protocol) { /* NKRO protocol */
/* need to wait until the previous packet has made it through */ /* need to wait until the previous packet has made it through */
/* can rewrite this using the synchronous API, then would wait /* can rewrite this using the synchronous API, then would wait
* until *after* the packet has been transmitted. I think * until *after* the packet has been transmitted. I think
* this is more efficient */ * this is more efficient */
/* busy wait, should be short and not very common */ /* busy wait, should be short and not very common */
osalSysLock(); osalSysLock();
if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_IN_EPNUM)) { if(usbGetTransmitStatusI(&USB_DRIVER, SHARED_IN_EPNUM)) {
/* Need to either suspend, or loop and call unlock/lock during /* Need to either suspend, or loop and call unlock/lock during
* every iteration - otherwise the system will remain locked, * every iteration - otherwise the system will remain locked,
* no interrupts served, so USB not going through as well. * no interrupts served, so USB not going through as well.
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_IN_EPNUM]->in_state->thread); osalThreadSuspendS(&(&USB_DRIVER)->epc[SHARED_IN_EPNUM]->in_state->thread);
} }
usbStartTransmitI(&USB_DRIVER, NKRO_IN_EPNUM, (uint8_t *)report, sizeof(report_keyboard_t)); usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)report, sizeof(struct nkro_report));
osalSysUnlock(); osalSysUnlock();
} else } else
#endif /* NKRO_ENABLE */ #endif /* NKRO_ENABLE */
{ /* boot protocol */ { /* regular protocol */
/* need to wait until the previous packet has made it through */ /* need to wait until the previous packet has made it through */
/* busy wait, should be short and not very common */ /* busy wait, should be short and not very common */
osalSysLock(); osalSysLock();
@ -690,7 +663,15 @@ void send_keyboard(report_keyboard_t *report) {
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread); osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread);
} }
usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, (uint8_t *)report, KEYBOARD_EPSIZE); uint8_t *data, size;
if (keyboard_protocol) {
data = (uint8_t*)report;
size = KEYBOARD_REPORT_SIZE;
} else { /* boot protocol */
data = &report->mods;
size = 8;
}
usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, data, size);
osalSysUnlock(); osalSysUnlock();
} }
keyboard_report_sent = *report; keyboard_report_sent = *report;
@ -703,11 +684,13 @@ void send_keyboard(report_keyboard_t *report) {
#ifdef MOUSE_ENABLE #ifdef MOUSE_ENABLE
#ifndef MOUSE_SHARED_EP
/* mouse IN callback hander (a mouse report has made it IN) */ /* mouse IN callback hander (a mouse report has made it IN) */
void mouse_in_cb(USBDriver *usbp, usbep_t ep) { void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
(void)usbp; (void)usbp;
(void)ep; (void)ep;
} }
#endif
void send_mouse(report_mouse_t *report) { void send_mouse(report_mouse_t *report) {
osalSysLock(); osalSysLock();
@ -737,19 +720,24 @@ void send_mouse(report_mouse_t *report) {
#endif /* MOUSE_ENABLE */ #endif /* MOUSE_ENABLE */
/* --------------------------------------------------------- /* ---------------------------------------------------------
* Extrakey functions * Shared EP functions
* --------------------------------------------------------- * ---------------------------------------------------------
*/ */
#ifdef SHARED_EP_ENABLE
#ifdef EXTRAKEY_ENABLE /* shared IN callback hander */
void shared_in_cb(USBDriver *usbp, usbep_t ep) {
/* extrakey IN callback hander */
void extra_in_cb(USBDriver *usbp, usbep_t ep) {
/* STUB */ /* STUB */
(void)usbp; (void)usbp;
(void)ep; (void)ep;
} }
#endif
/* ---------------------------------------------------------
* Extrakey functions
* ---------------------------------------------------------
*/
#ifdef EXTRAKEY_ENABLE
static void send_extra_report(uint8_t report_id, uint16_t data) { static void send_extra_report(uint8_t report_id, uint16_t data) {
osalSysLock(); osalSysLock();
if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) { if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
@ -762,7 +750,7 @@ static void send_extra_report(uint8_t report_id, uint16_t data) {
.usage = data .usage = data
}; };
usbStartTransmitI(&USB_DRIVER, EXTRAKEY_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t)); usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
osalSysUnlock(); osalSysUnlock();
} }

@ -65,6 +65,14 @@ void nkro_in_cb(USBDriver *usbp, usbep_t ep);
void mouse_in_cb(USBDriver *usbp, usbep_t ep); void mouse_in_cb(USBDriver *usbp, usbep_t ep);
#endif /* MOUSE_ENABLE */ #endif /* MOUSE_ENABLE */
/* ---------------
* Shared EP header
* ---------------
*/
/* shared IN request callback handler */
void shared_in_cb(USBDriver *usbp, usbep_t ep);
/* --------------- /* ---------------
* Extrakey header * Extrakey header
* --------------- * ---------------
@ -72,9 +80,6 @@ void mouse_in_cb(USBDriver *usbp, usbep_t ep);
#ifdef EXTRAKEY_ENABLE #ifdef EXTRAKEY_ENABLE
/* extrakey IN request callback handler */
void extra_in_cb(USBDriver *usbp, usbep_t ep);
/* extra report structure */ /* extra report structure */
typedef struct { typedef struct {
uint8_t report_id; uint8_t report_id;

@ -409,19 +409,21 @@ void EVENT_USB_Device_ConfigurationChanged(void)
bool ConfigSuccess = true; bool ConfigSuccess = true;
/* Setup Keyboard HID Report Endpoints */ /* Setup Keyboard HID Report Endpoints */
#ifndef KEYBOARD_SHARED_EP
ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
#ifdef MOUSE_ENABLE #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
/* Setup Mouse HID Report Endpoint */ /* Setup Mouse HID Report Endpoint */
ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif #endif
#ifdef EXTRAKEY_ENABLE #ifdef SHARED_EP_ENABLE
/* Setup Extra HID Report Endpoint */ /* Setup Shared HID Report Endpoint */
ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, ConfigSuccess &= ENDPOINT_CONFIG(SHARED_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE); SHARED_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif #endif
#ifdef RAW_ENABLE #ifdef RAW_ENABLE
@ -442,12 +444,6 @@ void EVENT_USB_Device_ConfigurationChanged(void)
#endif #endif
#endif #endif
#ifdef NKRO_ENABLE
/* Setup NKRO HID Report Endpoints */
ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
#ifdef MIDI_ENABLE #ifdef MIDI_ENABLE
ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); 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)
// Interface // Interface
switch (USB_ControlRequest.wIndex) { switch (USB_ControlRequest.wIndex) {
case KEYBOARD_INTERFACE: case KEYBOARD_INTERFACE:
#ifdef NKRO_ENABLE #if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
case NKRO_INTERFACE: case SHARED_INTERFACE:
#endif #endif
Endpoint_ClearSETUP(); Endpoint_ClearSETUP();
@ -521,7 +517,17 @@ void EVENT_USB_Device_ControlRequest(void)
if (USB_DeviceState == DEVICE_STATE_Unattached) if (USB_DeviceState == DEVICE_STATE_Unattached)
return; return;
} }
#if defined(SHARED_EP_ENABLE)
uint8_t report_id = REPORT_ID_KEYBOARD;
if (keyboard_protocol) {
report_id = Endpoint_Read_8();
}
if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
keyboard_led_stats = Endpoint_Read_8();
}
#else
keyboard_led_stats = Endpoint_Read_8(); keyboard_led_stats = Endpoint_Read_8();
#endif
Endpoint_ClearOUT(); Endpoint_ClearOUT();
Endpoint_ClearStatusStage(); Endpoint_ClearStatusStage();
@ -615,13 +621,17 @@ static void send_keyboard(report_keyboard_t *report)
bluefruit_serial_send(0xFD); bluefruit_serial_send(0xFD);
bluefruit_serial_send(0x09); bluefruit_serial_send(0x09);
bluefruit_serial_send(0x01); bluefruit_serial_send(0x01);
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) { bluefruit_serial_send(report->mods);
bluefruit_serial_send(report->raw[i]); bluefruit_serial_send(report->reserved);
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
bluefruit_serial_send(report->keys[i]);
} }
#else #else
bluefruit_serial_send(0xFD); bluefruit_serial_send(0xFD);
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) { bluefruit_serial_send(report->mods);
bluefruit_serial_send(report->raw[i]); bluefruit_serial_send(report->reserved);
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
bluefruit_serial_send(report->keys[i]);
} }
#endif #endif
} }
@ -632,30 +642,24 @@ static void send_keyboard(report_keyboard_t *report)
} }
/* Select the Keyboard Report Endpoint */ /* Select the Keyboard Report Endpoint */
uint8_t ep = KEYBOARD_IN_EPNUM;
uint8_t size = KEYBOARD_REPORT_SIZE;
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) { if (keyboard_protocol && keymap_config.nkro) {
/* Report protocol - NKRO */ ep = SHARED_IN_EPNUM;
Endpoint_SelectEndpoint(NKRO_IN_EPNUM); size = sizeof(struct nkro_report);
/* Check if write ready for a polling interval around 1ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
if (!Endpoint_IsReadWriteAllowed()) return;
/* Write Keyboard Report Data */
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
} }
else
#endif #endif
{ Endpoint_SelectEndpoint(ep);
/* Boot protocol */
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
/* Check if write ready for a polling interval around 10ms */ /* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return; if (!Endpoint_IsReadWriteAllowed()) return;
/* Write Keyboard Report Data */ /* If we're in Boot Protocol, don't send any report ID or other funky fields */
Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL); if (!keyboard_protocol) {
Endpoint_Write_Stream_LE(&report->mods, 8, NULL);
} else {
Endpoint_Write_Stream_LE(report, size, NULL);
} }
/* Finalize the stream transfer to send the last packet */ /* Finalize the stream transfer to send the last packet */
@ -718,6 +722,7 @@ static void send_mouse(report_mouse_t *report)
*/ */
static void send_system(uint16_t data) static void send_system(uint16_t data)
{ {
#ifdef EXTRAKEY_ENABLE
uint8_t timeout = 255; uint8_t timeout = 255;
if (USB_DeviceState != DEVICE_STATE_Configured) if (USB_DeviceState != DEVICE_STATE_Configured)
@ -727,7 +732,7 @@ static void send_system(uint16_t data)
.report_id = REPORT_ID_SYSTEM, .report_id = REPORT_ID_SYSTEM,
.usage = data - SYSTEM_POWER_DOWN + 1 .usage = data - SYSTEM_POWER_DOWN + 1
}; };
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
/* Check if write ready for a polling interval around 10ms */ /* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
@ -735,6 +740,7 @@ static void send_system(uint16_t data)
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
Endpoint_ClearIN(); Endpoint_ClearIN();
#endif
} }
/** \brief Send Consumer /** \brief Send Consumer
@ -743,6 +749,7 @@ static void send_system(uint16_t data)
*/ */
static void send_consumer(uint16_t data) static void send_consumer(uint16_t data)
{ {
#ifdef EXTRAKEY_ENABLE
uint8_t timeout = 255; uint8_t timeout = 255;
uint8_t where = where_to_send(); uint8_t where = where_to_send();
@ -786,7 +793,7 @@ static void send_consumer(uint16_t data)
.report_id = REPORT_ID_CONSUMER, .report_id = REPORT_ID_CONSUMER,
.usage = data .usage = data
}; };
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
/* Check if write ready for a polling interval around 10ms */ /* Check if write ready for a polling interval around 10ms */
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
@ -794,6 +801,7 @@ static void send_consumer(uint16_t data)
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
Endpoint_ClearIN(); Endpoint_ClearIN();
#endif
} }

@ -47,11 +47,18 @@
/******************************************************************************* /*******************************************************************************
* HID Report Descriptors * HID Report Descriptors
******************************************************************************/ ******************************************************************************/
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = #ifdef KEYBOARD_SHARED_EP
{ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
#define SHARED_REPORT_STARTED
#else
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
#endif
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RI_USAGE(8, 0x06), /* Keyboard */ HID_RI_USAGE(8, 0x06), /* Keyboard */
HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_COLLECTION(8, 0x01), /* Application */
# ifdef KEYBOARD_SHARED_EP
HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD),
# endif
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */ HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */ HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */ HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
@ -84,14 +91,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
HID_RI_REPORT_SIZE(8, 0x08), HID_RI_REPORT_SIZE(8, 0x08),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0),
#ifndef KEYBOARD_SHARED_EP
}; };
#endif
#ifdef MOUSE_ENABLE #if defined(MOUSE_ENABLE)
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
{ # if !defined(MOUSE_SHARED_EP)
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = {
# elif !defined(SHARED_REPORT_STARTED)
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
#define SHARED_REPORT_STARTED
# endif
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RI_USAGE(8, 0x02), /* Mouse */ HID_RI_USAGE(8, 0x02), /* Mouse */
HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_COLLECTION(8, 0x01), /* Application */
# ifdef MOUSE_SHARED_EP
HID_RI_REPORT_ID(8, REPORT_ID_MOUSE),
# endif
HID_RI_USAGE(8, 0x01), /* Pointer */ HID_RI_USAGE(8, 0x01), /* Pointer */
HID_RI_COLLECTION(8, 0x00), /* Physical */ HID_RI_COLLECTION(8, 0x00), /* Physical */
@ -133,12 +151,15 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0),
HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0),
# ifndef MOUSE_SHARED_EP
}; };
# endif
#endif #endif
#ifdef EXTRAKEY_ENABLE #if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED)
const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] = const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
{ #endif
# ifdef EXTRAKEY_ENABLE
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RI_USAGE(8, 0x80), /* System Control */ HID_RI_USAGE(8, 0x80), /* System Control */
HID_RI_COLLECTION(8, 0x01), /* Application */ HID_RI_COLLECTION(8, 0x01), /* Application */
@ -164,6 +185,43 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
HID_RI_REPORT_COUNT(8, 1), HID_RI_REPORT_COUNT(8, 1),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0),
# endif
# ifdef NKRO_ENABLE
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RI_USAGE(8, 0x06), /* Keyboard */
HID_RI_COLLECTION(8, 0x01), /* Application */
HID_RI_REPORT_ID(8, REPORT_ID_NKRO),
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_COUNT(8, 0x08),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
HID_RI_REPORT_COUNT(8, 0x05),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
HID_RI_REPORT_COUNT(8, 0x01),
HID_RI_REPORT_SIZE(8, 0x03),
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS*8-1),
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS*8),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0),
# endif
#ifdef SHARED_EP_ENABLE
}; };
#endif #endif
@ -211,42 +269,6 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
}; };
#endif #endif
#ifdef NKRO_ENABLE
const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
{
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
HID_RI_USAGE(8, 0x06), /* Keyboard */
HID_RI_COLLECTION(8, 0x01), /* Application */
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_COUNT(8, 0x08),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
HID_RI_REPORT_COUNT(8, 0x05),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
HID_RI_REPORT_COUNT(8, 0x01),
HID_RI_REPORT_SIZE(8, 0x03),
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
HID_RI_LOGICAL_MINIMUM(8, 0x00),
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_END_COLLECTION(0),
};
#endif
/******************************************************************************* /*******************************************************************************
* Device Descriptors * Device Descriptors
@ -303,6 +325,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
/* /*
* Keyboard * Keyboard
*/ */
#ifndef KEYBOARD_SHARED_EP
.Keyboard_Interface = .Keyboard_Interface =
{ {
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
@ -339,11 +362,12 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.EndpointSize = KEYBOARD_EPSIZE, .EndpointSize = KEYBOARD_EPSIZE,
.PollingIntervalMS = 0x0A .PollingIntervalMS = 0x0A
}, },
#endif
/* /*
* Mouse * Mouse
*/ */
#ifdef MOUSE_ENABLE #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
.Mouse_Interface = .Mouse_Interface =
{ {
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
@ -383,26 +407,31 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
#endif #endif
/* /*
* Extra * Shared
*/ */
#ifdef EXTRAKEY_ENABLE #ifdef SHARED_EP_ENABLE
.Extrakey_Interface = .Shared_Interface =
{ {
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = EXTRAKEY_INTERFACE, .InterfaceNumber = SHARED_INTERFACE,
.AlternateSetting = 0x00, .AlternateSetting = 0x00,
.TotalEndpoints = 1, .TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass, .Class = HID_CSCP_HIDClass,
# ifdef KEYBOARD_SHARED_EP
.SubClass = HID_CSCP_BootSubclass,
.Protocol = HID_CSCP_KeyboardBootProtocol,
# else
.SubClass = HID_CSCP_NonBootSubclass, .SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol, .Protocol = HID_CSCP_NonBootProtocol,
#endif
.InterfaceStrIndex = NO_DESCRIPTOR .InterfaceStrIndex = NO_DESCRIPTOR
}, },
.Extrakey_HID = .Shared_HID =
{ {
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID}, .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
@ -410,16 +439,16 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.CountryCode = 0x00, .CountryCode = 0x00,
.TotalReportDescriptors = 1, .TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report, .HIDReportType = HID_DTYPE_Report,
.HIDReportLength = sizeof(ExtrakeyReport) .HIDReportLength = sizeof(SharedReport)
}, },
.Extrakey_INEndpoint = .Shared_INEndpoint =
{ {
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM), .EndpointAddress = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = EXTRAKEY_EPSIZE, .EndpointSize = SHARED_EPSIZE,
.PollingIntervalMS = 0x0A .PollingIntervalMS = 0x0A
}, },
#endif #endif
@ -528,48 +557,6 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
}, },
#endif #endif
/*
* NKRO
*/
#ifdef NKRO_ENABLE
.NKRO_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = NKRO_INTERFACE,
.AlternateSetting = 0x00,
.TotalEndpoints = 1,
.Class = HID_CSCP_HIDClass,
.SubClass = HID_CSCP_NonBootSubclass,
.Protocol = HID_CSCP_NonBootProtocol,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.NKRO_HID =
{
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
.HIDSpec = VERSION_BCD(1,1,1),
.CountryCode = 0x00,
.TotalReportDescriptors = 1,
.HIDReportType = HID_DTYPE_Report,
.HIDReportLength = sizeof(NKROReport)
},
.NKRO_INEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DIR_IN | NKRO_IN_EPNUM),
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = NKRO_EPSIZE,
.PollingIntervalMS = 0x01
},
#endif
#ifdef MIDI_ENABLE #ifdef MIDI_ENABLE
.Audio_Interface_Association = .Audio_Interface_Association =
{ {
@ -936,19 +923,21 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
break; break;
case HID_DTYPE_HID: case HID_DTYPE_HID:
switch (wIndex) { switch (wIndex) {
#ifndef KEYBOARD_SHARED_EP
case KEYBOARD_INTERFACE: case KEYBOARD_INTERFACE:
Address = &ConfigurationDescriptor.Keyboard_HID; Address = &ConfigurationDescriptor.Keyboard_HID;
Size = sizeof(USB_HID_Descriptor_HID_t); Size = sizeof(USB_HID_Descriptor_HID_t);
break; break;
#ifdef MOUSE_ENABLE #endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
case MOUSE_INTERFACE: case MOUSE_INTERFACE:
Address = &ConfigurationDescriptor.Mouse_HID; Address = &ConfigurationDescriptor.Mouse_HID;
Size = sizeof(USB_HID_Descriptor_HID_t); Size = sizeof(USB_HID_Descriptor_HID_t);
break; break;
#endif #endif
#ifdef EXTRAKEY_ENABLE #ifdef SHARED_EP_ENABLE
case EXTRAKEY_INTERFACE: case SHARED_INTERFACE:
Address = &ConfigurationDescriptor.Extrakey_HID; Address = &ConfigurationDescriptor.Shared_HID;
Size = sizeof(USB_HID_Descriptor_HID_t); Size = sizeof(USB_HID_Descriptor_HID_t);
break; break;
#endif #endif
@ -963,31 +952,27 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
Address = &ConfigurationDescriptor.Console_HID; Address = &ConfigurationDescriptor.Console_HID;
Size = sizeof(USB_HID_Descriptor_HID_t); Size = sizeof(USB_HID_Descriptor_HID_t);
break; break;
#endif
#ifdef NKRO_ENABLE
case NKRO_INTERFACE:
Address = &ConfigurationDescriptor.NKRO_HID;
Size = sizeof(USB_HID_Descriptor_HID_t);
break;
#endif #endif
} }
break; break;
case HID_DTYPE_Report: case HID_DTYPE_Report:
switch (wIndex) { switch (wIndex) {
#ifndef KEYBOARD_SHARED_EP
case KEYBOARD_INTERFACE: case KEYBOARD_INTERFACE:
Address = &KeyboardReport; Address = &KeyboardReport;
Size = sizeof(KeyboardReport); Size = sizeof(KeyboardReport);
break; break;
#ifdef MOUSE_ENABLE #endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
case MOUSE_INTERFACE: case MOUSE_INTERFACE:
Address = &MouseReport; Address = &MouseReport;
Size = sizeof(MouseReport); Size = sizeof(MouseReport);
break; break;
#endif #endif
#ifdef EXTRAKEY_ENABLE #ifdef SHARED_EP_ENABLE
case EXTRAKEY_INTERFACE: case SHARED_INTERFACE:
Address = &ExtrakeyReport; Address = &SharedReport;
Size = sizeof(ExtrakeyReport); Size = sizeof(SharedReport);
break; break;
#endif #endif
#ifdef RAW_ENABLE #ifdef RAW_ENABLE
@ -1001,12 +986,6 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
Address = &ConsoleReport; Address = &ConsoleReport;
Size = sizeof(ConsoleReport); Size = sizeof(ConsoleReport);
break; break;
#endif
#ifdef NKRO_ENABLE
case NKRO_INTERFACE:
Address = &NKROReport;
Size = sizeof(NKROReport);
break;
#endif #endif
} }
break; break;

@ -53,26 +53,27 @@ typedef struct
{ {
USB_Descriptor_Configuration_Header_t Config; USB_Descriptor_Configuration_Header_t Config;
#ifndef KEYBOARD_SHARED_EP
// Keyboard HID Interface // Keyboard HID Interface
USB_Descriptor_Interface_t Keyboard_Interface; USB_Descriptor_Interface_t Keyboard_Interface;
USB_HID_Descriptor_HID_t Keyboard_HID; USB_HID_Descriptor_HID_t Keyboard_HID;
USB_Descriptor_Endpoint_t Keyboard_INEndpoint; USB_Descriptor_Endpoint_t Keyboard_INEndpoint;
#endif
#ifdef MOUSE_ENABLE #if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
// Mouse HID Interface // Mouse HID Interface
USB_Descriptor_Interface_t Mouse_Interface; USB_Descriptor_Interface_t Mouse_Interface;
USB_HID_Descriptor_HID_t Mouse_HID; USB_HID_Descriptor_HID_t Mouse_HID;
USB_Descriptor_Endpoint_t Mouse_INEndpoint; USB_Descriptor_Endpoint_t Mouse_INEndpoint;
#endif #endif
#ifdef EXTRAKEY_ENABLE #if defined(SHARED_EP_ENABLE)
// Extrakey HID Interface USB_Descriptor_Interface_t Shared_Interface;
USB_Descriptor_Interface_t Extrakey_Interface; USB_HID_Descriptor_HID_t Shared_HID;
USB_HID_Descriptor_HID_t Extrakey_HID; USB_Descriptor_Endpoint_t Shared_INEndpoint;
USB_Descriptor_Endpoint_t Extrakey_INEndpoint;
#endif #endif
#ifdef RAW_ENABLE #if defined(RAW_ENABLE)
// Raw HID Interface // Raw HID Interface
USB_Descriptor_Interface_t Raw_Interface; USB_Descriptor_Interface_t Raw_Interface;
USB_HID_Descriptor_HID_t Raw_HID; USB_HID_Descriptor_HID_t Raw_HID;
@ -88,13 +89,6 @@ typedef struct
USB_Descriptor_Endpoint_t Console_OUTEndpoint; USB_Descriptor_Endpoint_t Console_OUTEndpoint;
#endif #endif
#ifdef NKRO_ENABLE
// NKRO HID Interface
USB_Descriptor_Interface_t NKRO_Interface;
USB_HID_Descriptor_HID_t NKRO_HID;
USB_Descriptor_Endpoint_t NKRO_INEndpoint;
#endif
#ifdef MIDI_ENABLE #ifdef MIDI_ENABLE
USB_Descriptor_Interface_Association_t Audio_Interface_Association; USB_Descriptor_Interface_Association_t Audio_Interface_Association;
// MIDI Audio Control Interface // MIDI Audio Control Interface
@ -133,133 +127,105 @@ typedef struct
/* index of interface */ /* index of interface */
#define KEYBOARD_INTERFACE 0 enum usb_interfaces {
#if !defined(KEYBOARD_SHARED_EP)
KEYBOARD_INTERFACE,
#else
# define KEYBOARD_INTERFACE SHARED_INTERFACE
#endif
// It is important that the Raw HID interface is at a constant // It is important that the Raw HID interface is at a constant
// interface number, to support Linux/OSX platforms and chrome.hid // interface number, to support Linux/OSX platforms and chrome.hid
// If Raw HID is enabled, let it be always 1. // If Raw HID is enabled, let it be always 1.
#ifdef RAW_ENABLE #if defined(RAW_ENABLE)
# define RAW_INTERFACE (KEYBOARD_INTERFACE + 1) RAW_INTERFACE,
#else
# define RAW_INTERFACE KEYBOARD_INTERFACE
#endif #endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
#ifdef MOUSE_ENABLE MOUSE_INTERFACE,
# define MOUSE_INTERFACE (RAW_INTERFACE + 1)
#else
# define MOUSE_INTERFACE RAW_INTERFACE
#endif #endif
#if defined(SHARED_EP_ENABLE)
#ifdef EXTRAKEY_ENABLE SHARED_INTERFACE,
# define EXTRAKEY_INTERFACE (MOUSE_INTERFACE + 1)
#else
# define EXTRAKEY_INTERFACE MOUSE_INTERFACE
#endif #endif
#if defined(CONSOLE_ENABLE)
#ifdef CONSOLE_ENABLE CONSOLE_INTERFACE,
# define CONSOLE_INTERFACE (EXTRAKEY_INTERFACE + 1)
#else
# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
#endif
#ifdef NKRO_ENABLE
# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
#else
# define NKRO_INTERFACE CONSOLE_INTERFACE
#endif #endif
#if defined(MIDI_ENABLE)
#ifdef MIDI_ENABLE AC_INTERFACE,
# define AC_INTERFACE (NKRO_INTERFACE + 1) AS_INTERFACE,
# define AS_INTERFACE (NKRO_INTERFACE + 2)
#else
# define AS_INTERFACE NKRO_INTERFACE
#endif #endif
#if defined(VIRTSER_ENABLE)
#ifdef VIRTSER_ENABLE CCI_INTERFACE,
# define CCI_INTERFACE (AS_INTERFACE + 1) CDI_INTERFACE,
# define CDI_INTERFACE (AS_INTERFACE + 2)
#else
# define CDI_INTERFACE AS_INTERFACE
#endif #endif
TOTAL_INTERFACES
};
/* nubmer of interfaces */ #define NEXT_EPNUM __COUNTER__
#define TOTAL_INTERFACES (CDI_INTERFACE + 1)
// Endopoint number and size enum usb_endpoints {
#define KEYBOARD_IN_EPNUM 1 __unused_epnum__ = NEXT_EPNUM, /* EP numbering starts at 1 */
#if !defined(KEYBOARD_SHARED_EP)
#ifdef MOUSE_ENABLE KEYBOARD_IN_EPNUM = NEXT_EPNUM,
# define MOUSE_IN_EPNUM (KEYBOARD_IN_EPNUM + 1)
#else #else
# define MOUSE_IN_EPNUM KEYBOARD_IN_EPNUM # define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
#endif #endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
#ifdef EXTRAKEY_ENABLE MOUSE_IN_EPNUM = NEXT_EPNUM,
# define EXTRAKEY_IN_EPNUM (MOUSE_IN_EPNUM + 1)
#else #else
# define EXTRAKEY_IN_EPNUM MOUSE_IN_EPNUM # define MOUSE_IN_EPNUM SHARED_IN_EPNUM
#endif #endif
#if defined(RAW_ENABLE)
#ifdef RAW_ENABLE RAW_IN_EPNUM = NEXT_EPNUM,
# define RAW_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1) RAW_OUT_EPNUM = NEXT_EPNUM,
# define RAW_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
#else
# define RAW_OUT_EPNUM EXTRAKEY_IN_EPNUM
#endif #endif
#if defined(SHARED_EP_ENABLE)
#ifdef CONSOLE_ENABLE SHARED_IN_EPNUM = NEXT_EPNUM,
# define CONSOLE_IN_EPNUM (RAW_OUT_EPNUM + 1) #endif
#if defined(CONSOLE_ENABLE)
CONSOLE_IN_EPNUM = NEXT_EPNUM,
#ifdef PROTOCOL_CHIBIOS #ifdef PROTOCOL_CHIBIOS
// ChibiOS has enough memory and descriptor to actually enable the endpoint // ChibiOS has enough memory and descriptor to actually enable the endpoint
// It could use the same endpoint numbers, as that's supported by ChibiOS // It could use the same endpoint numbers, as that's supported by ChibiOS
// But the QMK code currently assumes that the endpoint numbers are different // But the QMK code currently assumes that the endpoint numbers are different
# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 2) CONSOLE_OUT_EPNUM = NEXT_EPNUM,
#else #else
# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 1) #define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM
#endif #endif
#else
# define CONSOLE_OUT_EPNUM RAW_OUT_EPNUM
#endif #endif
#ifdef NKRO_ENABLE
# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
#else
# define NKRO_IN_EPNUM CONSOLE_OUT_EPNUM
#endif
#ifdef MIDI_ENABLE #ifdef MIDI_ENABLE
# define MIDI_STREAM_IN_EPNUM (NKRO_IN_EPNUM + 1) MIDI_STREAM_IN_EPNUM = NEXT_EPNUM,
// # define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 1) MIDI_STREAM_OUT_EPNUM = NEXT_EPNUM,
# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2)
# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM) # define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM)
# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM) # define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM)
#else
# define MIDI_STREAM_OUT_EPNUM NKRO_IN_EPNUM
#endif #endif
#ifdef VIRTSER_ENABLE #ifdef VIRTSER_ENABLE
# define CDC_NOTIFICATION_EPNUM (MIDI_STREAM_OUT_EPNUM + 1) CDC_NOTIFICATION_EPNUM = NEXT_EPNUM,
# define CDC_IN_EPNUM (MIDI_STREAM_OUT_EPNUM + 2) CDC_IN_EPNUM = NEXT_EPNUM,
# define CDC_OUT_EPNUM (MIDI_STREAM_OUT_EPNUM + 3) CDC_OUT_EPNUM = NEXT_EPNUM,
# define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM) # define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM)
# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM) # define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM) # define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
#else
# define CDC_OUT_EPNUM MIDI_STREAM_OUT_EPNUM
#endif #endif
};
#if defined(PROTOCOL_LUFA)
/* LUFA tells us total endpoints including control */
#define MAX_ENDPOINTS (ENDPOINT_TOTAL_ENDPOINTS - 1)
#elif defined(PROTOCOL_CHIBIOS)
/* ChibiOS gives us number of available user endpoints, not control */
#define MAX_ENDPOINTS USB_MAX_ENDPOINTS
#endif
/* TODO - ARM_ATSAM */
#if (defined(PROTOCOL_LUFA) && CDC_OUT_EPNUM > (ENDPOINT_TOTAL_ENDPOINTS - 1)) || \ #if (NEXT_EPNUM - 1) > MAX_ENDPOINTS
(defined(PROTOCOL_CHIBIOS) && CDC_OUT_EPNUM > USB_MAX_ENDPOINTS) # 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)
# 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)"
#endif #endif
#define KEYBOARD_EPSIZE 8 #define KEYBOARD_EPSIZE 8
#define SHARED_EPSIZE 32
#define MOUSE_EPSIZE 8 #define MOUSE_EPSIZE 8
#define EXTRAKEY_EPSIZE 8
#define RAW_EPSIZE 32 #define RAW_EPSIZE 32
#define CONSOLE_EPSIZE 32 #define CONSOLE_EPSIZE 32
#define NKRO_EPSIZE 32
#define MIDI_STREAM_EPSIZE 64 #define MIDI_STREAM_EPSIZE 64
#define CDC_NOTIFICATION_EPSIZE 8 #define CDC_NOTIFICATION_EPSIZE 8
#define CDC_EPSIZE 16 #define CDC_EPSIZE 16

Loading…
Cancel
Save