diff options
author | Nick Brassel <[email protected]> | 2023-11-28 16:39:48 +1100 |
---|---|---|
committer | Nick Brassel <[email protected]> | 2023-11-28 16:40:47 +1100 |
commit | 0115951de12bd4c798a43a380651c34552552e85 (patch) | |
tree | 62999011ae782d93aa6dc9c889615db2a840cafc /tmk_core/protocol/vusb | |
parent | 0379d1f59e58cefa18cdb72ba1b77507d1108ae6 (diff) | |
parent | 4d99e0a23cff02f4c6e55e093b5de08a9be0df7c (diff) | |
download | qmk_firmware-0.23.0.tar.gz qmk_firmware-0.23.0.zip |
`develop` -> `master`, 2023q4 edition0.23.0
Diffstat (limited to 'tmk_core/protocol/vusb')
-rw-r--r-- | tmk_core/protocol/vusb/protocol.c | 1 | ||||
-rw-r--r-- | tmk_core/protocol/vusb/vusb.c | 276 | ||||
-rw-r--r-- | tmk_core/protocol/vusb/vusb.h | 1 |
3 files changed, 148 insertions, 130 deletions
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); |