summaryrefslogtreecommitdiff
path: root/tmk_core/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/protocol')
-rw-r--r--tmk_core/protocol/arm_atsam/main_arm_atsam.c59
-rw-r--r--tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h2
-rw-r--r--tmk_core/protocol/chibios/chibios.c3
-rw-r--r--tmk_core/protocol/chibios/usb_main.c173
-rw-r--r--tmk_core/protocol/host.c33
-rw-r--r--tmk_core/protocol/host.h4
-rw-r--r--tmk_core/protocol/host_driver.h1
-rw-r--r--tmk_core/protocol/lufa/lufa.c34
-rw-r--r--tmk_core/protocol/report.c43
-rw-r--r--tmk_core/protocol/report.h166
-rw-r--r--tmk_core/protocol/usb_descriptor.c4
-rw-r--r--tmk_core/protocol/usb_descriptor.h2
-rw-r--r--tmk_core/protocol/usb_types.h23
-rw-r--r--tmk_core/protocol/vusb/protocol.c1
-rw-r--r--tmk_core/protocol/vusb/vusb.c276
-rw-r--r--tmk_core/protocol/vusb/vusb.h1
16 files changed, 406 insertions, 419 deletions
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
index 30817c17b6..8abcfd6090 100644
--- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c
+++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c
@@ -36,6 +36,7 @@ uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; // Saved USB state from ha
void main_subtasks(void);
uint8_t keyboard_leds(void);
void send_keyboard(report_keyboard_t *report);
+void send_nkro(report_nkro_t *report);
void send_mouse(report_mouse_t *report);
void send_extra(report_extra_t *report);
@@ -43,7 +44,7 @@ void send_extra(report_extra_t *report);
void deferred_exec_task(void);
#endif // DEFERRED_EXEC_ENABLE
-host_driver_t arm_atsam_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra};
+host_driver_t arm_atsam_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
uint8_t led_states;
@@ -59,41 +60,41 @@ uint8_t keyboard_leds(void) {
void send_keyboard(report_keyboard_t *report) {
uint32_t irqflags;
-#ifdef NKRO_ENABLE
- if (!keymap_config.nkro) {
-#endif // NKRO_ENABLE
- while (udi_hid_kbd_b_report_trans_ongoing) {
- main_subtasks();
- } // Run other tasks while waiting for USB to be free
+ while (udi_hid_kbd_b_report_trans_ongoing) {
+ main_subtasks();
+ } // Run other tasks while waiting for USB to be free
- irqflags = __get_PRIMASK();
- __disable_irq();
- __DMB();
+ irqflags = __get_PRIMASK();
+ __disable_irq();
+ __DMB();
- memcpy(udi_hid_kbd_report, report->raw, UDI_HID_KBD_REPORT_SIZE);
- udi_hid_kbd_b_report_valid = 1;
- udi_hid_kbd_send_report();
+ memcpy(udi_hid_kbd_report, report, UDI_HID_KBD_REPORT_SIZE);
+ udi_hid_kbd_b_report_valid = 1;
+ udi_hid_kbd_send_report();
- __DMB();
- __set_PRIMASK(irqflags);
+ __DMB();
+ __set_PRIMASK(irqflags);
+}
+
+void send_nkro(report_nkro_t *report) {
#ifdef NKRO_ENABLE
- } else {
- while (udi_hid_nkro_b_report_trans_ongoing) {
- main_subtasks();
- } // Run other tasks while waiting for USB to be free
+ uint32_t irqflags;
- irqflags = __get_PRIMASK();
- __disable_irq();
- __DMB();
+ while (udi_hid_nkro_b_report_trans_ongoing) {
+ main_subtasks();
+ } // Run other tasks while waiting for USB to be free
- memcpy(udi_hid_nkro_report, report->raw, UDI_HID_NKRO_REPORT_SIZE);
- udi_hid_nkro_b_report_valid = 1;
- udi_hid_nkro_send_report();
+ irqflags = __get_PRIMASK();
+ __disable_irq();
+ __DMB();
- __DMB();
- __set_PRIMASK(irqflags);
- }
-#endif // NKRO_ENABLE
+ memcpy(udi_hid_nkro_report, report, UDI_HID_NKRO_REPORT_SIZE);
+ udi_hid_nkro_b_report_valid = 1;
+ udi_hid_nkro_send_report();
+
+ __DMB();
+ __set_PRIMASK(irqflags);
+#endif
}
void send_mouse(report_mouse_t *report) {
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h b/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h
index 7a9ed31930..47bd02c074 100644
--- a/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h
+++ b/tmk_core/protocol/arm_atsam/usb/udi_device_epsize.h
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define _UDI_DEVICE_EPSIZE_H_
#define KEYBOARD_EPSIZE 8
-#define MOUSE_EPSIZE 8
+#define MOUSE_EPSIZE 16
#define EXTRAKEY_EPSIZE 8
#define RAW_EPSIZE 32
#define CONSOLE_EPSIZE 32
diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c
index 4d97f1cd82..91bb252c7c 100644
--- a/tmk_core/protocol/chibios/chibios.c
+++ b/tmk_core/protocol/chibios/chibios.c
@@ -59,11 +59,12 @@
/* declarations */
uint8_t keyboard_leds(void);
void send_keyboard(report_keyboard_t *report);
+void send_nkro(report_nkro_t *report);
void send_mouse(report_mouse_t *report);
void send_extra(report_extra_t *report);
/* host struct */
-host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra};
+host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
#ifdef VIRTSER_ENABLE
void virtser_task(void);
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
index b14ca30c1a..66f9ad0318 100644
--- a/tmk_core/protocol/chibios/usb_main.c
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -43,6 +43,7 @@
#include "usb_device_state.h"
#include "usb_descriptor.h"
#include "usb_driver.h"
+#include "usb_types.h"
#ifdef NKRO_ENABLE
# include "keycode_config.h"
@@ -71,7 +72,7 @@ static virtual_timer_t keyboard_idle_timer;
static void keyboard_idle_timer_cb(struct ch_virtual_timer *, void *arg);
-report_keyboard_t keyboard_report_sent = {{0}};
+report_keyboard_t keyboard_report_sent = {0};
report_mouse_t mouse_report_sent = {0};
union {
@@ -103,30 +104,18 @@ union {
NULL, /* SETUP buffer (not a SETUP endpoint) */
#endif
-/* HID specific constants */
-#define HID_GET_REPORT 0x01
-#define HID_GET_IDLE 0x02
-#define HID_GET_PROTOCOL 0x03
-#define HID_SET_REPORT 0x09
-#define HID_SET_IDLE 0x0A
-#define HID_SET_PROTOCOL 0x0B
-
-/*
- * Handles the GET_DESCRIPTOR callback
- *
- * Returns the proper descriptor
- */
static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) {
- (void)usbp;
- static USBDescriptor desc;
- uint16_t wValue = ((uint16_t)dtype << 8) | dindex;
- uint16_t wLength = ((uint16_t)usbp->setup[7] << 8) | usbp->setup[6];
- desc.ud_string = NULL;
- desc.ud_size = get_usb_descriptor(wValue, wIndex, wLength, (const void **const) & desc.ud_string);
- if (desc.ud_string == NULL)
+ usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
+
+ static USBDescriptor descriptor;
+ descriptor.ud_string = NULL;
+ descriptor.ud_size = get_usb_descriptor(setup->wValue.word, setup->wIndex, setup->wLength, (const void **const) & descriptor.ud_string);
+
+ if (descriptor.ud_string == NULL) {
return NULL;
- else
- return &desc;
+ }
+
+ return &descriptor;
}
/*
@@ -497,8 +486,7 @@ void usb_event_queue_task(void) {
}
}
-/* Handles the USB driver global events
- * TODO: maybe disable some things when connection is lost? */
+/* Handles the USB driver global events. */
static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
switch (event) {
case USB_EVENT_ADDRESS:
@@ -570,16 +558,6 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
}
}
-/* Function used locally in os/hal/src/usb.c for getting descriptors
- * need it here for HID descriptor */
-static uint16_t get_hword(uint8_t *p) {
- uint16_t hw;
-
- hw = (uint16_t)*p++;
- hw |= (uint16_t)*p << 8U;
- return hw;
-}
-
/*
* Appendix G: HID Request Support Requirements
*
@@ -596,7 +574,9 @@ static uint16_t get_hword(uint8_t *p) {
static uint8_t set_report_buf[2] __attribute__((aligned(4)));
static void set_led_transfer_cb(USBDriver *usbp) {
- if (usbp->setup[6] == 2) { /* LSB(wLength) */
+ usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
+
+ if (setup->wLength == 2) {
uint8_t report_id = set_report_buf[0];
if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) {
keyboard_led_state = set_report_buf[1];
@@ -606,24 +586,16 @@ static void set_led_transfer_cb(USBDriver *usbp) {
}
}
-/* Callback for SETUP request on the endpoint 0 (control) */
-static bool usb_request_hook_cb(USBDriver *usbp) {
- const USBDescriptor *dp;
-
- /* usbp->setup fields:
- * 0: bmRequestType (bitmask)
- * 1: bRequest
- * 2,3: (LSB,MSB) wValue
- * 4,5: (LSB,MSB) wIndex
- * 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
+static bool usb_requests_hook_cb(USBDriver *usbp) {
+ usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
/* Handle HID class specific requests */
- if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
- switch (usbp->setup[0] & USB_RTYPE_DIR_MASK) {
+ if ((setup->bmRequestType & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) {
+ switch (setup->bmRequestType & USB_RTYPE_DIR_MASK) {
case USB_RTYPE_DIR_DEV2HOST:
- switch (usbp->setup[1]) { /* bRequest */
- case HID_GET_REPORT:
- switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
+ switch (setup->bRequest) {
+ case HID_REQ_GetReport:
+ switch (setup->wIndex) {
#ifndef KEYBOARD_SHARED_EP
case KEYBOARD_INTERFACE:
usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
@@ -639,59 +611,54 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
#ifdef SHARED_EP_ENABLE
case SHARED_INTERFACE:
# ifdef KEYBOARD_SHARED_EP
- if (usbp->setup[2] == REPORT_ID_KEYBOARD) {
+ if (setup->wValue.lbyte == REPORT_ID_KEYBOARD) {
usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
- return TRUE;
- break;
+ return true;
}
# endif
# ifdef MOUSE_SHARED_EP
- if (usbp->setup[2] == REPORT_ID_MOUSE) {
+ if (setup->wValue.lbyte == REPORT_ID_MOUSE) {
usbSetupTransfer(usbp, (uint8_t *)&mouse_report_sent, sizeof(mouse_report_sent), NULL);
- return TRUE;
- break;
+ return true;
}
# endif
#endif /* SHARED_EP_ENABLE */
default:
- universal_report_blank.report_id = usbp->setup[2];
- usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, usbp->setup[6], NULL);
- return TRUE;
- break;
+ universal_report_blank.report_id = setup->wValue.lbyte;
+ usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, setup->wLength, NULL);
+ return true;
}
break;
- case HID_GET_PROTOCOL:
- if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
- usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
- return TRUE;
+ case HID_REQ_GetProtocol:
+ if (setup->wIndex == KEYBOARD_INTERFACE) {
+ usbSetupTransfer(usbp, &keyboard_protocol, sizeof(uint8_t), NULL);
+ return true;
}
break;
- case HID_GET_IDLE:
- usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
- return TRUE;
- break;
+ case HID_REQ_GetIdle:
+ usbSetupTransfer(usbp, &keyboard_idle, sizeof(uint8_t), NULL);
+ return true;
}
break;
case USB_RTYPE_DIR_HOST2DEV:
- switch (usbp->setup[1]) { /* bRequest */
- case HID_SET_REPORT:
- switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
+ switch (setup->bRequest) {
+ case HID_REQ_SetReport:
+ switch (setup->wIndex) {
case KEYBOARD_INTERFACE:
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
case SHARED_INTERFACE:
#endif
usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
- return TRUE;
- break;
+ return true;
}
break;
- case HID_SET_PROTOCOL:
- if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
- keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
+ case HID_REQ_SetProtocol:
+ if (setup->wIndex == KEYBOARD_INTERFACE) {
+ keyboard_protocol = setup->wValue.word;
#ifdef NKRO_ENABLE
if (!keyboard_protocol && keyboard_idle) {
#else /* NKRO_ENABLE */
@@ -704,12 +671,11 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
}
}
usbSetupTransfer(usbp, NULL, 0, NULL);
- return TRUE;
- break;
+ return true;
- case HID_SET_IDLE:
- keyboard_idle = usbp->setup[3]; /* MSB(wValue) */
- /* arm the timer */
+ case HID_REQ_SetIdle:
+ keyboard_idle = setup->wValue.hbyte;
+ /* arm the timer */
#ifdef NKRO_ENABLE
if (!keymap_config.nkro && keyboard_idle) {
#else /* NKRO_ENABLE */
@@ -720,19 +686,21 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
osalSysUnlockFromISR();
}
usbSetupTransfer(usbp, NULL, 0, NULL);
- return TRUE;
- break;
+ return true;
}
break;
}
}
- /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
- if ((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
- dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
- if (dp == NULL) return FALSE;
- usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
- return TRUE;
+ /* Handle the Get_Descriptor Request for HID class, which is not handled by
+ * the ChibiOS USB driver */
+ if (((setup->bmRequestType & (USB_RTYPE_DIR_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_DIR_DEV2HOST | USB_RTYPE_RECIPIENT_INTERFACE)) && (setup->bRequest == USB_REQ_GET_DESCRIPTOR)) {
+ const USBDescriptor *descriptor = usbp->config->get_descriptor_cb(usbp, setup->wValue.lbyte, setup->wValue.hbyte, setup->wIndex);
+ if (descriptor == NULL) {
+ return false;
+ }
+ usbSetupTransfer(usbp, (uint8_t *)descriptor->ud_string, descriptor->ud_size, NULL);
+ return true;
}
for (int i = 0; i < NUM_USB_DRIVERS; i++) {
@@ -742,10 +710,9 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
}
}
- return FALSE;
+ return false;
}
-/* Start-of-frame callback */
static void usb_sof_cb(USBDriver *usbp) {
osalSysLockFromISR();
for (int i = 0; i < NUM_USB_DRIVERS; i++) {
@@ -758,7 +725,7 @@ static void usb_sof_cb(USBDriver *usbp) {
static const USBConfig usbcfg = {
usb_event_cb, /* USB events callback */
usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
- usb_request_hook_cb, /* Requests hook callback */
+ usb_requests_hook_cb, /* Requests hook callback */
usb_sof_cb /* Start Of Frame callback */
};
@@ -883,26 +850,22 @@ void send_report(uint8_t endpoint, void *report, size_t size) {
/* prepare and start sending a report IN
* not callable from ISR or locked state */
void send_keyboard(report_keyboard_t *report) {
- uint8_t ep = KEYBOARD_IN_EPNUM;
- size_t size = KEYBOARD_REPORT_SIZE;
-
/* If we're in Boot Protocol, don't send any report ID or other funky fields */
if (!keyboard_protocol) {
- send_report(ep, &report->mods, 8);
+ send_report(KEYBOARD_IN_EPNUM, &report->mods, 8);
} else {
-#ifdef NKRO_ENABLE
- if (keymap_config.nkro) {
- ep = SHARED_IN_EPNUM;
- size = sizeof(struct nkro_report);
- }
-#endif
-
- send_report(ep, report, size);
+ send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE);
}
keyboard_report_sent = *report;
}
+void send_nkro(report_nkro_t *report) {
+#ifdef NKRO_ENABLE
+ send_report(SHARED_IN_EPNUM, report, sizeof(report_nkro_t));
+#endif
+}
+
/* ---------------------------------------------------------
* Mouse functions
* ---------------------------------------------------------
diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c
index 2c6654e9a6..732fbdc37d 100644
--- a/tmk_core/protocol/host.c
+++ b/tmk_core/protocol/host.c
@@ -81,26 +81,29 @@ void host_keyboard_send(report_keyboard_t *report) {
#endif
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;
+ report->report_id = REPORT_ID_KEYBOARD;
#endif
- }
(*driver->send_keyboard)(report);
if (debug_keyboard) {
- dprint("keyboard_report: ");
- for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
- dprintf("%02X ", report->raw[i]);
+ dprintf("keyboard_report: %02X | ", report->mods);
+ for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+ dprintf("%02X ", report->keys[i]);
+ }
+ dprint("\n");
+ }
+}
+
+void host_nkro_send(report_nkro_t *report) {
+ if (!driver) return;
+ report->report_id = REPORT_ID_NKRO;
+ (*driver->send_nkro)(report);
+
+ if (debug_keyboard) {
+ dprintf("nkro_report: %02X | ", report->mods);
+ for (uint8_t i = 0; i < NKRO_REPORT_BITS; i++) {
+ dprintf("%02X ", report->bits[i]);
}
dprint("\n");
}
diff --git a/tmk_core/protocol/host.h b/tmk_core/protocol/host.h
index add408caf6..959753ae02 100644
--- a/tmk_core/protocol/host.h
+++ b/tmk_core/protocol/host.h
@@ -23,9 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "host_driver.h"
#include "led.h"
-#define IS_LED_ON(leds, led_name) ((leds) & (1 << (led_name)))
-#define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name)))
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -41,6 +38,7 @@ host_driver_t *host_get_driver(void);
uint8_t host_keyboard_leds(void);
led_t host_keyboard_led_state(void);
void host_keyboard_send(report_keyboard_t *report);
+void host_nkro_send(report_nkro_t *report);
void host_mouse_send(report_mouse_t *report);
void host_system_send(uint16_t usage);
void host_consumer_send(uint16_t usage);
diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h
index 7dc6c3d810..8aa38b6dee 100644
--- a/tmk_core/protocol/host_driver.h
+++ b/tmk_core/protocol/host_driver.h
@@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
typedef struct {
uint8_t (*keyboard_leds)(void);
void (*send_keyboard)(report_keyboard_t *);
+ void (*send_nkro)(report_nkro_t *);
void (*send_mouse)(report_mouse_t *);
void (*send_extra)(report_extra_t *);
} host_driver_t;
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index f04ca79a0c..553f69b1e4 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -55,12 +55,6 @@
#include "usb_device_state.h"
#include <util/atomic.h>
-#ifdef NKRO_ENABLE
-# include "keycode_config.h"
-
-extern keymap_config_t keymap_config;
-#endif
-
#ifdef VIRTSER_ENABLE
# include "virtser.h"
#endif
@@ -83,9 +77,10 @@ static report_keyboard_t keyboard_report_sent;
/* Host driver */
static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report);
+static void send_nkro(report_nkro_t *report);
static void send_mouse(report_mouse_t *report);
static void send_extra(report_extra_t *report);
-host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_extra};
+host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
void send_report(uint8_t endpoint, void *report, size_t size) {
uint8_t timeout = 255;
@@ -559,27 +554,26 @@ static uint8_t keyboard_leds(void) {
* FIXME: Needs doc
*/
static void send_keyboard(report_keyboard_t *report) {
- /* Select the Keyboard Report Endpoint */
- uint8_t ep = KEYBOARD_IN_EPNUM;
- uint8_t size = KEYBOARD_REPORT_SIZE;
-
/* If we're in Boot Protocol, don't send any report ID or other funky fields */
if (!keyboard_protocol) {
- send_report(ep, &report->mods, 8);
+ send_report(KEYBOARD_IN_EPNUM, &report->mods, 8);
} else {
-#ifdef NKRO_ENABLE
- if (keymap_config.nkro) {
- ep = SHARED_IN_EPNUM;
- size = sizeof(struct nkro_report);
- }
-#endif
-
- send_report(ep, report, size);
+ send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE);
}
keyboard_report_sent = *report;
}
+/** \brief Send NKRO
+ *
+ * FIXME: Needs doc
+ */
+static void send_nkro(report_nkro_t *report) {
+#ifdef NKRO_ENABLE
+ send_report(SHARED_IN_EPNUM, report, sizeof(report_nkro_t));
+#endif
+}
+
/** \brief Send Mouse
*
* FIXME: Needs doc
diff --git a/tmk_core/protocol/report.c b/tmk_core/protocol/report.c
index 1ba3be4604..0166bf654f 100644
--- a/tmk_core/protocol/report.c
+++ b/tmk_core/protocol/report.c
@@ -15,6 +15,7 @@
*/
#include "report.h"
+#include "action_util.h"
#include "host.h"
#include "keycode_config.h"
#include "debug.h"
@@ -35,14 +36,14 @@ static int8_t cb_count = 0;
*
* FIXME: Needs doc
*/
-uint8_t has_anykey(report_keyboard_t* keyboard_report) {
+uint8_t has_anykey(void) {
uint8_t cnt = 0;
uint8_t* p = keyboard_report->keys;
uint8_t lp = sizeof(keyboard_report->keys);
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
- p = keyboard_report->nkro.bits;
- lp = sizeof(keyboard_report->nkro.bits);
+ p = nkro_report->bits;
+ lp = sizeof(nkro_report->bits);
}
#endif
while (lp--) {
@@ -55,13 +56,13 @@ uint8_t has_anykey(report_keyboard_t* keyboard_report) {
*
* FIXME: Needs doc
*/
-uint8_t get_first_key(report_keyboard_t* keyboard_report) {
+uint8_t get_first_key(void) {
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
uint8_t i = 0;
- for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
+ for (; i < NKRO_REPORT_BITS && !nkro_report->bits[i]; i++)
;
- return i << 3 | biton(keyboard_report->nkro.bits[i]);
+ return i << 3 | biton(nkro_report->bits[i]);
}
#endif
#ifdef RING_BUFFERED_6KRO_REPORT_ENABLE
@@ -83,14 +84,14 @@ uint8_t get_first_key(report_keyboard_t* keyboard_report) {
* Returns true if the keyboard_report reports that the key is pressed, otherwise false
* Note: The function doesn't support modifers currently, and it returns false for KC_NO
*/
-bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key) {
+bool is_key_pressed(uint8_t key) {
if (key == KC_NO) {
return false;
}
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
- if ((key >> 3) < KEYBOARD_REPORT_BITS) {
- return keyboard_report->nkro.bits[key >> 3] & 1 << (key & 7);
+ if ((key >> 3) < NKRO_REPORT_BITS) {
+ return nkro_report->bits[key >> 3] & 1 << (key & 7);
} else {
return false;
}
@@ -215,9 +216,9 @@ void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) {
*
* FIXME: Needs doc
*/
-void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
- if ((code >> 3) < KEYBOARD_REPORT_BITS) {
- keyboard_report->nkro.bits[code >> 3] |= 1 << (code & 7);
+void add_key_bit(report_nkro_t* nkro_report, uint8_t code) {
+ if ((code >> 3) < NKRO_REPORT_BITS) {
+ nkro_report->bits[code >> 3] |= 1 << (code & 7);
} else {
dprintf("add_key_bit: can't add: %02X\n", code);
}
@@ -227,9 +228,9 @@ void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
*
* FIXME: Needs doc
*/
-void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
- if ((code >> 3) < KEYBOARD_REPORT_BITS) {
- keyboard_report->nkro.bits[code >> 3] &= ~(1 << (code & 7));
+void del_key_bit(report_nkro_t* nkro_report, uint8_t code) {
+ if ((code >> 3) < NKRO_REPORT_BITS) {
+ nkro_report->bits[code >> 3] &= ~(1 << (code & 7));
} else {
dprintf("del_key_bit: can't del: %02X\n", code);
}
@@ -240,10 +241,10 @@ void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code) {
*
* FIXME: Needs doc
*/
-void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) {
+void add_key_to_report(uint8_t key) {
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
- add_key_bit(keyboard_report, key);
+ add_key_bit(nkro_report, key);
return;
}
#endif
@@ -254,10 +255,10 @@ void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key) {
*
* FIXME: Needs doc
*/
-void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) {
+void del_key_from_report(uint8_t key) {
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
- del_key_bit(keyboard_report, key);
+ del_key_bit(nkro_report, key);
return;
}
#endif
@@ -268,11 +269,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key) {
*
* FIXME: Needs doc
*/
-void clear_keys_from_report(report_keyboard_t* keyboard_report) {
+void clear_keys_from_report(void) {
// not clear mods
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
- memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits));
+ memset(nkro_report->bits, 0, sizeof(nkro_report->bits));
return;
}
#endif
diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h
index 9d415a3bfd..3028cf9426 100644
--- a/tmk_core/protocol/report.h
+++ b/tmk_core/protocol/report.h
@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
#include "keycode.h"
+#include "util.h"
// clang-format off
@@ -54,9 +55,9 @@ enum mouse_buttons {
*/
enum consumer_usages {
// 15.5 Display Controls
- SNAPSHOT = 0x065,
- BRIGHTNESS_UP = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf
- BRIGHTNESS_DOWN = 0x070,
+ SNAPSHOT = 0x065,
+ BRIGHTNESS_UP = 0x06F, // https://www.usb.org/sites/default/files/hutrr41_0.pdf
+ BRIGHTNESS_DOWN = 0x070,
// 15.7 Transport Controls
TRANSPORT_RECORD = 0x0B2,
TRANSPORT_FAST_FORWARD = 0x0B3,
@@ -69,43 +70,44 @@ enum consumer_usages {
TRANSPORT_STOP_EJECT = 0x0CC,
TRANSPORT_PLAY_PAUSE = 0x0CD,
// 15.9.1 Audio Controls - Volume
- AUDIO_MUTE = 0x0E2,
- AUDIO_VOL_UP = 0x0E9,
- AUDIO_VOL_DOWN = 0x0EA,
+ AUDIO_MUTE = 0x0E2,
+ AUDIO_VOL_UP = 0x0E9,
+ AUDIO_VOL_DOWN = 0x0EA,
// 15.15 Application Launch Buttons
- AL_CC_CONFIG = 0x183,
- AL_EMAIL = 0x18A,
- AL_CALCULATOR = 0x192,
- AL_LOCAL_BROWSER = 0x194,
- AL_LOCK = 0x19E,
- AL_CONTROL_PANEL = 0x19F,
- AL_ASSISTANT = 0x1CB,
- AL_KEYBOARD_LAYOUT = 0x1AE,
+ AL_CC_CONFIG = 0x183,
+ AL_EMAIL = 0x18A,
+ AL_CALCULATOR = 0x192,
+ AL_LOCAL_BROWSER = 0x194,
+ AL_LOCK = 0x19E,
+ AL_CONTROL_PANEL = 0x19F,
+ AL_ASSISTANT = 0x1CB,
+ AL_KEYBOARD_LAYOUT = 0x1AE,
// 15.16 Generic GUI Application Controls
- AC_NEW = 0x201,
- AC_OPEN = 0x202,
- AC_CLOSE = 0x203,
- AC_EXIT = 0x204,
- AC_MAXIMIZE = 0x205,
- AC_MINIMIZE = 0x206,
- AC_SAVE = 0x207,
- AC_PRINT = 0x208,
- AC_PROPERTIES = 0x209,
- AC_UNDO = 0x21A,
- AC_COPY = 0x21B,
- AC_CUT = 0x21C,
- AC_PASTE = 0x21D,
- AC_SELECT_ALL = 0x21E,
- AC_FIND = 0x21F,
- AC_SEARCH = 0x221,
- AC_HOME = 0x223,
- AC_BACK = 0x224,
- AC_FORWARD = 0x225,
- AC_STOP = 0x226,
- AC_REFRESH = 0x227,
- AC_BOOKMARKS = 0x22A,
- AC_MISSION_CONTROL = 0x29F,
- AC_LAUNCHPAD = 0x2A0
+ AC_NEW = 0x201,
+ AC_OPEN = 0x202,
+ AC_CLOSE = 0x203,
+ AC_EXIT = 0x204,
+ AC_MAXIMIZE = 0x205,
+ AC_MINIMIZE = 0x206,
+ AC_SAVE = 0x207,
+ AC_PRINT = 0x208,
+ AC_PROPERTIES = 0x209,
+ AC_UNDO = 0x21A,
+ AC_COPY = 0x21B,
+ AC_CUT = 0x21C,
+ AC_PASTE = 0x21D,
+ AC_SELECT_ALL = 0x21E,
+ AC_FIND = 0x21F,
+ AC_SEARCH = 0x221,
+ AC_HOME = 0x223,
+ AC_BACK = 0x224,
+ AC_FORWARD = 0x225,
+ AC_STOP = 0x226,
+ AC_REFRESH = 0x227,
+ AC_BOOKMARKS = 0x22A,
+ AC_NEXT_KEYBOARD_LAYOUT_SELECT = 0x29D,
+ AC_DESKTOP_SHOW_ALL_WINDOWS = 0x29F,
+ AC_SOFT_KEY_LEFT = 0x2A0
};
/* Generic Desktop Page (0x01)
@@ -124,21 +126,7 @@ enum desktop_usages {
// clang-format on
-#define NKRO_SHARED_EP
-/* key report size(NKRO or boot mode) */
-#if defined(NKRO_ENABLE)
-# if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
-# include "protocol/usb_descriptor.h"
-# define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2)
-# elif defined(PROTOCOL_ARM_ATSAM)
-# include "protocol/arm_atsam/usb/udi_device_epsize.h"
-# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
-# undef NKRO_SHARED_EP
-# undef MOUSE_SHARED_EP
-# else
-# error "NKRO not supported with this protocol"
-# endif
-#endif
+#define NKRO_REPORT_BITS 30
#ifdef KEYBOARD_SHARED_EP
# define KEYBOARD_REPORT_SIZE 9
@@ -172,36 +160,30 @@ extern "C" {
* desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui
*
*/
-typedef union {
- uint8_t raw[KEYBOARD_REPORT_SIZE];
- struct {
+typedef struct {
#ifdef KEYBOARD_SHARED_EP
- uint8_t report_id;
-#endif
- uint8_t mods;
- uint8_t reserved;
- uint8_t keys[KEYBOARD_REPORT_KEYS];
- };
-#ifdef NKRO_ENABLE
- struct nkro_report {
-# ifdef NKRO_SHARED_EP
- uint8_t report_id;
-# endif
- uint8_t mods;
- uint8_t bits[KEYBOARD_REPORT_BITS];
- } nkro;
+ uint8_t report_id;
#endif
-} __attribute__((packed)) report_keyboard_t;
+ uint8_t mods;
+ uint8_t reserved;
+ uint8_t keys[KEYBOARD_REPORT_KEYS];
+} PACKED report_keyboard_t;
+
+typedef struct {
+ uint8_t report_id;
+ uint8_t mods;
+ uint8_t bits[NKRO_REPORT_BITS];
+} PACKED report_nkro_t;
typedef struct {
uint8_t report_id;
uint16_t usage;
-} __attribute__((packed)) report_extra_t;
+} PACKED report_extra_t;
typedef struct {
uint8_t report_id;
uint32_t usage;
-} __attribute__((packed)) report_programmable_button_t;
+} PACKED report_programmable_button_t;
#ifdef MOUSE_EXTENDED_REPORT
typedef int16_t mouse_xy_report_t;
@@ -222,7 +204,7 @@ typedef struct {
mouse_xy_report_t y;
int8_t v;
int8_t h;
-} __attribute__((packed)) report_mouse_t;
+} PACKED report_mouse_t;
typedef struct {
#ifdef DIGITIZER_SHARED_EP
@@ -234,24 +216,26 @@ typedef struct {
uint8_t reserved : 5;
uint16_t x;
uint16_t y;
-} __attribute__((packed)) report_digitizer_t;
+} PACKED report_digitizer_t;
+
+#if JOYSTICK_AXIS_RESOLUTION > 8
+typedef int16_t joystick_axis_t;
+#else
+typedef int8_t joystick_axis_t;
+#endif
typedef struct {
#ifdef JOYSTICK_SHARED_EP
uint8_t report_id;
#endif
#if JOYSTICK_AXIS_COUNT > 0
-# if JOYSTICK_AXIS_RESOLUTION > 8
- int16_t axes[JOYSTICK_AXIS_COUNT];
-# else
- int8_t axes[JOYSTICK_AXIS_COUNT];
-# endif
+ joystick_axis_t axes[JOYSTICK_AXIS_COUNT];
#endif
#if JOYSTICK_BUTTON_COUNT > 0
uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1];
#endif
-} __attribute__((packed)) report_joystick_t;
+} PACKED report_joystick_t;
/* keycode to system usage */
static inline uint16_t KEYCODE2SYSTEM(uint8_t key) {
@@ -321,28 +305,28 @@ static inline uint16_t KEYCODE2CONSUMER(uint8_t key) {
case KC_WWW_FAVORITES:
return AC_BOOKMARKS;
case KC_MISSION_CONTROL:
- return AC_MISSION_CONTROL;
+ return AC_DESKTOP_SHOW_ALL_WINDOWS;
case KC_LAUNCHPAD:
- return AC_LAUNCHPAD;
+ return AC_SOFT_KEY_LEFT;
default:
return 0;
}
}
-uint8_t has_anykey(report_keyboard_t* keyboard_report);
-uint8_t get_first_key(report_keyboard_t* keyboard_report);
-bool is_key_pressed(report_keyboard_t* keyboard_report, uint8_t key);
+uint8_t has_anykey(void);
+uint8_t get_first_key(void);
+bool is_key_pressed(uint8_t key);
void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code);
void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code);
#ifdef NKRO_ENABLE
-void add_key_bit(report_keyboard_t* keyboard_report, uint8_t code);
-void del_key_bit(report_keyboard_t* keyboard_report, uint8_t code);
+void add_key_bit(report_nkro_t* nkro_report, uint8_t code);
+void del_key_bit(report_nkro_t* nkro_report, uint8_t code);
#endif
-void add_key_to_report(report_keyboard_t* keyboard_report, uint8_t key);
-void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key);
-void clear_keys_from_report(report_keyboard_t* keyboard_report);
+void add_key_to_report(uint8_t key);
+void del_key_from_report(uint8_t key);
+void clear_keys_from_report(void);
#ifdef MOUSE_ENABLE
bool has_mouse_report_changed(report_mouse_t* new_report, report_mouse_t* old_report);
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index e215c90900..eb214c0492 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -359,10 +359,10 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
// Keycodes
HID_RI_USAGE_PAGE(8, 0x07), // Keyboard/Keypad
HID_RI_USAGE_MINIMUM(8, 0x00),
- HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS * 8 - 1),
+ HID_RI_USAGE_MAXIMUM(8, NKRO_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_COUNT(8, NKRO_REPORT_BITS * 8),
HID_RI_REPORT_SIZE(8, 0x01),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h
index ed84f4c9ab..1268bdae73 100644
--- a/tmk_core/protocol/usb_descriptor.h
+++ b/tmk_core/protocol/usb_descriptor.h
@@ -299,7 +299,7 @@ enum usb_endpoints {
#define KEYBOARD_EPSIZE 8
#define SHARED_EPSIZE 32
-#define MOUSE_EPSIZE 8
+#define MOUSE_EPSIZE 16
#define RAW_EPSIZE 32
#define CONSOLE_EPSIZE 32
#define MIDI_STREAM_EPSIZE 64
diff --git a/tmk_core/protocol/usb_types.h b/tmk_core/protocol/usb_types.h
new file mode 100644
index 0000000000..019775a1c4
--- /dev/null
+++ b/tmk_core/protocol/usb_types.h
@@ -0,0 +1,23 @@
+// Copyright 2023 Stefan Kerkmann
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "util.h"
+
+/**
+ * @brief Common USB 2.0 control request structure
+ */
+typedef struct {
+ uint8_t bmRequestType; // [0] (Bitmask)
+ uint8_t bRequest; // [1]
+ union {
+ struct {
+ uint8_t lbyte; // [2] (LSB)
+ uint8_t hbyte; // [3] (MSB)
+ };
+ uint16_t word; // [2,3] (LSB,MSB)
+ } wValue;
+ uint16_t wIndex; // [4,5] (LSB,MSB)
+ uint16_t wLength; // [6,7] (LSB,MSB)
+} PACKED usb_control_request_t;
diff --git a/tmk_core/protocol/vusb/protocol.c b/tmk_core/protocol/vusb/protocol.c
index ae99680ce4..1f64561274 100644
--- a/tmk_core/protocol/vusb/protocol.c
+++ b/tmk_core/protocol/vusb/protocol.c
@@ -153,7 +153,6 @@ void protocol_task(void) {
if (usbConfiguration && usbInterruptIsReady()) {
keyboard_task();
}
- vusb_transfer_keyboard();
#ifdef RAW_ENABLE
usbPoll();
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index d74f375f66..d09b2f19b7 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -48,16 +48,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "os_detection.h"
#endif
-#define NEXT_INTERFACE __COUNTER__
-
/*
* Interface indexes
*/
enum usb_interfaces {
#ifndef KEYBOARD_SHARED_EP
- KEYBOARD_INTERFACE = NEXT_INTERFACE,
+ KEYBOARD_INTERFACE,
#else
- SHARED_INTERFACE = NEXT_INTERFACE,
+ SHARED_INTERFACE,
# define KEYBOARD_INTERFACE SHARED_INTERFACE
#endif
@@ -65,67 +63,77 @@ enum usb_interfaces {
// interface number, to support Linux/OSX platforms and chrome.hid
// If Raw HID is enabled, let it be always 1.
#ifdef RAW_ENABLE
- RAW_INTERFACE = NEXT_INTERFACE,
+ RAW_INTERFACE,
#endif
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
- SHARED_INTERFACE = NEXT_INTERFACE,
+ SHARED_INTERFACE,
#endif
#ifdef CONSOLE_ENABLE
- CONSOLE_INTERFACE = NEXT_INTERFACE,
+ CONSOLE_INTERFACE,
#endif
- TOTAL_INTERFACES = NEXT_INTERFACE
+ TOTAL_INTERFACES
};
#define MAX_INTERFACES 3
-#if (NEXT_INTERFACE - 1) > MAX_INTERFACES
-# error There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console
-#endif
+_Static_assert(TOTAL_INTERFACES <= MAX_INTERFACES, "There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console.");
#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && CONSOLE_ENABLE
# error Mouse/Extra Keys share an endpoint with Console. Please disable one of the two.
#endif
static uint8_t keyboard_led_state = 0;
-static uint8_t vusb_idle_rate = 0;
-
-/* Keyboard report send buffer */
-#define KBUF_SIZE 16
-static report_keyboard_t kbuf[KBUF_SIZE];
-static uint8_t kbuf_head = 0;
-static uint8_t kbuf_tail = 0;
+uint8_t keyboard_idle = 0;
+uint8_t keyboard_protocol = 1;
static report_keyboard_t keyboard_report_sent;
-#define VUSB_TRANSFER_KEYBOARD_MAX_TRIES 10
-
-/* transfer keyboard report from buffer */
-void vusb_transfer_keyboard(void) {
- for (int i = 0; i < VUSB_TRANSFER_KEYBOARD_MAX_TRIES; i++) {
- if (usbInterruptIsReady()) {
- if (kbuf_head != kbuf_tail) {
-#ifndef KEYBOARD_SHARED_EP
- usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
-#else
- // Ugly hack! :(
- usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t) - 1);
- while (!usbInterruptIsReady()) {
- usbPoll();
+static void send_report_fragment(uint8_t endpoint, void *data, size_t size) {
+ for (uint8_t retries = 5; retries > 0; retries--) {
+ switch (endpoint) {
+ case 1:
+ if (usbInterruptIsReady()) {
+ usbSetInterrupt(data, size);
+ return;
}
- usbSetInterrupt((void *)(&(kbuf[kbuf_tail].keys[5])), 1);
-#endif
- kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
- if (debug_keyboard) {
- dprintf("V-USB: kbuf[%d->%d](%02X)\n", kbuf_tail, kbuf_head, (kbuf_head < kbuf_tail) ? (KBUF_SIZE - kbuf_tail + kbuf_head) : (kbuf_head - kbuf_tail));
+ break;
+ case USB_CFG_EP3_NUMBER:
+ if (usbInterruptIsReady3()) {
+ usbSetInterrupt3(data, size);
+ return;
}
- }
- break;
+ break;
+ case USB_CFG_EP4_NUMBER:
+ if (usbInterruptIsReady4()) {
+ usbSetInterrupt4(data, size);
+ return;
+ }
+ break;
+ default:
+ return;
}
+
usbPoll();
- wait_ms(1);
+ wait_ms(5);
+ }
+}
+
+static void send_report(uint8_t endpoint, void *report, size_t size) {
+ uint8_t *temp = (uint8_t *)report;
+
+ // Send as many full packets as possible
+ for (uint8_t i = 0; i < size / 8; i++) {
+ send_report_fragment(endpoint, temp, 8);
+ temp += 8;
+ }
+
+ // Send any data left over
+ uint8_t remainder = size % 8;
+ if (remainder) {
+ send_report_fragment(endpoint, temp, remainder);
}
}
@@ -144,18 +152,7 @@ void raw_hid_send(uint8_t *data, uint8_t length) {
return;
}
- uint8_t *temp = data;
- for (uint8_t i = 0; i < 4; i++) {
- while (!usbInterruptIsReady4()) {
- usbPoll();
- }
- usbSetInterrupt4(temp, 8);
- temp += 8;
- }
- while (!usbInterruptIsReady4()) {
- usbPoll();
- }
- usbSetInterrupt4(0, 0);
+ send_report(4, data, 32);
}
__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) {
@@ -184,19 +181,6 @@ int8_t sendchar(uint8_t c) {
return 0;
}
-static inline bool usbSendData3(char *data, uint8_t len) {
- uint8_t retries = 5;
- while (!usbInterruptIsReady3()) {
- if (!(retries--)) {
- return false;
- }
- usbPoll();
- }
-
- usbSetInterrupt3((unsigned char *)data, len);
- return true;
-}
-
void console_task(void) {
if (!usbConfiguration) {
return;
@@ -213,16 +197,7 @@ void console_task(void) {
send_buf[send_buf_count++] = rbuf_dequeue();
}
- char *temp = send_buf;
- for (uint8_t i = 0; i < 4; i++) {
- if (!usbSendData3(temp, 8)) {
- break;
- }
- temp += 8;
- }
-
- usbSendData3(0, 0);
- usbPoll();
+ send_report(3, send_buf, CONSOLE_BUFFER_SIZE);
}
#endif
@@ -231,10 +206,11 @@ void console_task(void) {
*------------------------------------------------------------------*/
static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report);
+static void send_nkro(report_nkro_t *report);
static void send_mouse(report_mouse_t *report);
static void send_extra(report_extra_t *report);
-static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_extra};
+static host_driver_t driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
host_driver_t *vusb_driver(void) {
return &driver;
@@ -245,65 +221,56 @@ static uint8_t keyboard_leds(void) {
}
static void send_keyboard(report_keyboard_t *report) {
- uint8_t next = (kbuf_head + 1) % KBUF_SIZE;
- if (next != kbuf_tail) {
- kbuf[kbuf_head] = *report;
- kbuf_head = next;
+ if (!keyboard_protocol) {
+ send_report(1, &report->mods, 8);
} else {
- dprint("kbuf: full\n");
+ send_report(1, report, sizeof(report_keyboard_t));
}
- // NOTE: send key strokes of Macro
- usbPoll();
- vusb_transfer_keyboard();
keyboard_report_sent = *report;
}
#ifndef KEYBOARD_SHARED_EP
-# define usbInterruptIsReadyShared usbInterruptIsReady3
-# define usbSetInterruptShared usbSetInterrupt3
+# define MOUSE_IN_EPNUM 3
+# define SHARED_IN_EPNUM 3
#else
-# define usbInterruptIsReadyShared usbInterruptIsReady
-# define usbSetInterruptShared usbSetInterrupt
+# define MOUSE_IN_EPNUM 1
+# define SHARED_IN_EPNUM 1
+#endif
+
+static void send_nkro(report_nkro_t *report) {
+#ifdef NKRO_ENABLE
+ send_report(3, report, sizeof(report_nkro_t));
#endif
+}
static void send_mouse(report_mouse_t *report) {
#ifdef MOUSE_ENABLE
- if (usbInterruptIsReadyShared()) {
- usbSetInterruptShared((void *)report, sizeof(report_mouse_t));
- }
+ send_report(MOUSE_IN_EPNUM, report, sizeof(report_mouse_t));
#endif
}
static void send_extra(report_extra_t *report) {
#ifdef EXTRAKEY_ENABLE
- if (usbInterruptIsReadyShared()) {
- usbSetInterruptShared((void *)report, sizeof(report_extra_t));
- }
+ send_report(SHARED_IN_EPNUM, report, sizeof(report_extra_t));
#endif
}
void send_joystick(report_joystick_t *report) {
#ifdef JOYSTICK_ENABLE
- if (usbInterruptIsReadyShared()) {
- usbSetInterruptShared((void *)report, sizeof(report_joystick_t));
- }
+ send_report(SHARED_IN_EPNUM, report, sizeof(report_joystick_t));
#endif
}
void send_digitizer(report_digitizer_t *report) {
#ifdef DIGITIZER_ENABLE
- if (usbInterruptIsReadyShared()) {
- usbSetInterruptShared((void *)report, sizeof(report_digitizer_t));
- }
+ send_report(SHARED_IN_EPNUM, report, sizeof(report_digitizer_t));
#endif
}
void send_programmable_button(report_programmable_button_t *report) {
#ifdef PROGRAMMABLE_BUTTON_ENABLE
- if (usbInterruptIsReadyShared()) {
- usbSetInterruptShared((void *)report, sizeof(report_programmable_button_t));
- }
+ send_report(SHARED_IN_EPNUM, report, sizeof(report_programmable_button_t));
#endif
}
@@ -319,30 +286,44 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
usbRequest_t *rq = (void *)data;
if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { /* class request type */
- if (rq->bRequest == USBRQ_HID_GET_REPORT) {
- dprint("GET_REPORT:");
- if (rq->wIndex.word == KEYBOARD_INTERFACE) {
- usbMsgPtr = (usbMsgPtr_t)&keyboard_report_sent;
- return sizeof(keyboard_report_sent);
- }
- } else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
- dprint("GET_IDLE:");
- usbMsgPtr = (usbMsgPtr_t)&vusb_idle_rate;
- return 1;
- } else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
- vusb_idle_rate = rq->wValue.bytes[1];
- dprintf("SET_IDLE: %02X", vusb_idle_rate);
- } else if (rq->bRequest == USBRQ_HID_SET_REPORT) {
- dprint("SET_REPORT:");
- // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard)
- if (rq->wValue.word == 0x0200 && rq->wIndex.word == KEYBOARD_INTERFACE) {
- dprint("SET_LED:");
- last_req.kind = SET_LED;
- last_req.len = rq->wLength.word;
- }
- return USB_NO_MSG; // to get data in usbFunctionWrite
- } else {
- dprint("UNKNOWN:");
+ switch (rq->bRequest) {
+ case USBRQ_HID_GET_REPORT:
+ dprint("GET_REPORT:");
+ if (rq->wIndex.word == KEYBOARD_INTERFACE) {
+ usbMsgPtr = (usbMsgPtr_t)&keyboard_report_sent;
+ return sizeof(keyboard_report_sent);
+ }
+ break;
+ case USBRQ_HID_GET_IDLE:
+ dprint("GET_IDLE:");
+ usbMsgPtr = (usbMsgPtr_t)&keyboard_idle;
+ return 1;
+ case USBRQ_HID_GET_PROTOCOL:
+ dprint("GET_PROTOCOL:");
+ usbMsgPtr = (usbMsgPtr_t)&keyboard_protocol;
+ return 1;
+ case USBRQ_HID_SET_REPORT:
+ dprint("SET_REPORT:");
+ // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard)
+ if (rq->wValue.word == 0x0200 && rq->wIndex.word == KEYBOARD_INTERFACE) {
+ dprint("SET_LED:");
+ last_req.kind = SET_LED;
+ last_req.len = rq->wLength.word;
+ }
+ return USB_NO_MSG; // to get data in usbFunctionWrite
+ case USBRQ_HID_SET_IDLE:
+ keyboard_idle = (rq->wValue.word & 0xFF00) >> 8;
+ dprintf("SET_IDLE: %02X", keyboard_idle);
+ break;
+ case USBRQ_HID_SET_PROTOCOL:
+ if (rq->wIndex.word == KEYBOARD_INTERFACE) {
+ keyboard_protocol = rq->wValue.word & 0xFF;
+ dprintf("SET_PROTOCOL: %02X", keyboard_protocol);
+ }
+ break;
+ default:
+ dprint("UNKNOWN:");
+ break;
}
} else {
dprint("VENDOR:");
@@ -454,6 +435,45 @@ const PROGMEM uchar shared_hid_report[] = {
# define SHARED_REPORT_STARTED
#endif
+#ifdef NKRO_ENABLE
+ // NKRO report descriptor
+ 0x05, 0x01, // Usage Page (Generic Desktop)
+ 0x09, 0x06, // Usage (Keyboard)
+ 0xA1, 0x01, // Collection (Application)
+ 0x85, REPORT_ID_NKRO, // Report ID
+ // Modifiers (8 bits)
+ 0x05, 0x07, // Usage Page (Keyboard/Keypad)
+ 0x19, 0xE0, // Usage Minimum (Keyboard Left Control)
+ 0x29, 0xE7, // Usage Maximum (Keyboard Right GUI)
+ 0x15, 0x00, // Logical Minimum (0)
+ 0x25, 0x01, // Logical Maximum (1)
+ 0x95, 0x08, // Report Count (8)
+ 0x75, 0x01, // Report Size (1)
+ 0x81, 0x02, // Input (Data, Variable, Absolute)
+ // Keycodes
+ 0x05, 0x07, // Usage Page (Keyboard/Keypad)
+ 0x19, 0x00, // Usage Minimum (0)
+ 0x29, NKRO_REPORT_BITS * 8 - 1, // Usage Maximum
+ 0x15, 0x00, // Logical Minimum (0)
+ 0x25, 0x01, // Logical Maximum (1)
+ 0x95, NKRO_REPORT_BITS * 8, // Report Count
+ 0x75, 0x01, // Report Size (1)
+ 0x81, 0x02, // Input (Data, Variable, Absolute)
+
+ // Status LEDs (5 bits)
+ 0x05, 0x08, // Usage Page (LED)
+ 0x19, 0x01, // Usage Minimum (Num Lock)
+ 0x29, 0x05, // Usage Maximum (Kana)
+ 0x95, 0x05, // Report Count (5)
+ 0x75, 0x01, // Report Size (1)
+ 0x91, 0x02, // Output (Data, Variable, Absolute)
+ // LED padding (3 bits)
+ 0x95, 0x01, // Report Count (1)
+ 0x75, 0x03, // Report Size (3)
+ 0x91, 0x03, // Output (Constant)
+ 0xC0, // End Collection
+#endif
+
#ifdef MOUSE_ENABLE
// Mouse report descriptor
0x05, 0x01, // Usage Page (Generic Desktop)
@@ -1024,7 +1044,7 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
#endif
break;
case USBDESCR_HID:
- switch (rq->wValue.bytes[0]) {
+ switch (rq->wIndex.word) {
#ifndef KEYBOARD_SHARED_EP
case KEYBOARD_INTERFACE:
usbMsgPtr = (usbMsgPtr_t)&usbConfigurationDescriptor.keyboardHID;
diff --git a/tmk_core/protocol/vusb/vusb.h b/tmk_core/protocol/vusb/vusb.h
index c5cb27ded6..ae17e5e014 100644
--- a/tmk_core/protocol/vusb/vusb.h
+++ b/tmk_core/protocol/vusb/vusb.h
@@ -121,4 +121,3 @@ typedef struct usbConfigurationDescriptor {
extern bool vusb_suspended;
host_driver_t *vusb_driver(void);
-void vusb_transfer_keyboard(void);