V-USB: Add generic send_report() function (#22323)

This commit is contained in:
Ryan 2023-11-26 22:50:21 +11:00 committed by GitHub
parent 3a74fa5bf7
commit cbf538aaaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 92 deletions

View file

@ -153,7 +153,6 @@ void protocol_task(void) {
if (usbConfiguration && usbInterruptIsReady()) { if (usbConfiguration && usbInterruptIsReady()) {
keyboard_task(); keyboard_task();
} }
vusb_transfer_keyboard();
#ifdef RAW_ENABLE #ifdef RAW_ENABLE
usbPoll(); usbPoll();

View file

@ -89,40 +89,51 @@ static uint8_t keyboard_led_state = 0;
uint8_t keyboard_idle = 0; uint8_t keyboard_idle = 0;
uint8_t keyboard_protocol = 1; uint8_t keyboard_protocol = 1;
/* 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;
static report_keyboard_t keyboard_report_sent; static report_keyboard_t keyboard_report_sent;
#define VUSB_TRANSFER_KEYBOARD_MAX_TRIES 10 static void send_report_fragment(uint8_t endpoint, void *data, size_t size) {
for (uint8_t retries = 5; retries > 0; retries--) {
/* transfer keyboard report from buffer */ switch (endpoint) {
void vusb_transfer_keyboard(void) { case 1:
for (int i = 0; i < VUSB_TRANSFER_KEYBOARD_MAX_TRIES; i++) { if (usbInterruptIsReady()) {
if (usbInterruptIsReady()) { usbSetInterrupt(data, size);
if (kbuf_head != kbuf_tail) { return;
#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();
} }
usbSetInterrupt((void *)(&(kbuf[kbuf_tail].keys[5])), 1); break;
#endif case USB_CFG_EP3_NUMBER:
kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; if (usbInterruptIsReady3()) {
if (debug_keyboard) { usbSetInterrupt3(data, size);
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)); return;
} }
} break;
break; case USB_CFG_EP4_NUMBER:
if (usbInterruptIsReady4()) {
usbSetInterrupt4(data, size);
return;
}
break;
default:
return;
} }
usbPoll(); 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);
} }
} }
@ -141,18 +152,7 @@ void raw_hid_send(uint8_t *data, uint8_t length) {
return; return;
} }
uint8_t *temp = data; send_report(4, data, 32);
for (uint8_t i = 0; i < 4; i++) {
while (!usbInterruptIsReady4()) {
usbPoll();
}
usbSetInterrupt4(temp, 8);
temp += 8;
}
while (!usbInterruptIsReady4()) {
usbPoll();
}
usbSetInterrupt4(0, 0);
} }
__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) { __attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) {
@ -181,19 +181,6 @@ int8_t sendchar(uint8_t c) {
return 0; 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) { void console_task(void) {
if (!usbConfiguration) { if (!usbConfiguration) {
return; return;
@ -210,16 +197,7 @@ void console_task(void) {
send_buf[send_buf_count++] = rbuf_dequeue(); send_buf[send_buf_count++] = rbuf_dequeue();
} }
char *temp = send_buf; send_report(3, send_buf, CONSOLE_BUFFER_SIZE);
for (uint8_t i = 0; i < 4; i++) {
if (!usbSendData3(temp, 8)) {
break;
}
temp += 8;
}
usbSendData3(0, 0);
usbPoll();
} }
#endif #endif
@ -243,17 +221,12 @@ static uint8_t keyboard_leds(void) {
} }
static void send_keyboard(report_keyboard_t *report) { static void send_keyboard(report_keyboard_t *report) {
uint8_t next = (kbuf_head + 1) % KBUF_SIZE; if (!keyboard_protocol) {
if (next != kbuf_tail) { send_report(1, &report->mods, 8);
kbuf[kbuf_head] = *report;
kbuf_head = next;
} else { } 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; keyboard_report_sent = *report;
} }
@ -262,50 +235,40 @@ static void send_nkro(report_nkro_t *report) {
} }
#ifndef KEYBOARD_SHARED_EP #ifndef KEYBOARD_SHARED_EP
# define usbInterruptIsReadyShared usbInterruptIsReady3 # define MOUSE_IN_EPNUM 3
# define usbSetInterruptShared usbSetInterrupt3 # define SHARED_IN_EPNUM 3
#else #else
# define usbInterruptIsReadyShared usbInterruptIsReady # define MOUSE_IN_EPNUM 1
# define usbSetInterruptShared usbSetInterrupt # define SHARED_IN_EPNUM 1
#endif #endif
static void send_mouse(report_mouse_t *report) { static void send_mouse(report_mouse_t *report) {
#ifdef MOUSE_ENABLE #ifdef MOUSE_ENABLE
if (usbInterruptIsReadyShared()) { send_report(MOUSE_IN_EPNUM, report, sizeof(report_mouse_t));
usbSetInterruptShared((void *)report, sizeof(report_mouse_t));
}
#endif #endif
} }
static void send_extra(report_extra_t *report) { static void send_extra(report_extra_t *report) {
#ifdef EXTRAKEY_ENABLE #ifdef EXTRAKEY_ENABLE
if (usbInterruptIsReadyShared()) { send_report(SHARED_IN_EPNUM, report, sizeof(report_extra_t));
usbSetInterruptShared((void *)report, sizeof(report_extra_t));
}
#endif #endif
} }
void send_joystick(report_joystick_t *report) { void send_joystick(report_joystick_t *report) {
#ifdef JOYSTICK_ENABLE #ifdef JOYSTICK_ENABLE
if (usbInterruptIsReadyShared()) { send_report(SHARED_IN_EPNUM, report, sizeof(report_joystick_t));
usbSetInterruptShared((void *)report, sizeof(report_joystick_t));
}
#endif #endif
} }
void send_digitizer(report_digitizer_t *report) { void send_digitizer(report_digitizer_t *report) {
#ifdef DIGITIZER_ENABLE #ifdef DIGITIZER_ENABLE
if (usbInterruptIsReadyShared()) { send_report(SHARED_IN_EPNUM, report, sizeof(report_digitizer_t));
usbSetInterruptShared((void *)report, sizeof(report_digitizer_t));
}
#endif #endif
} }
void send_programmable_button(report_programmable_button_t *report) { void send_programmable_button(report_programmable_button_t *report) {
#ifdef PROGRAMMABLE_BUTTON_ENABLE #ifdef PROGRAMMABLE_BUTTON_ENABLE
if (usbInterruptIsReadyShared()) { send_report(SHARED_IN_EPNUM, report, sizeof(report_programmable_button_t));
usbSetInterruptShared((void *)report, sizeof(report_programmable_button_t));
}
#endif #endif
} }

View file

@ -121,4 +121,3 @@ typedef struct usbConfigurationDescriptor {
extern bool vusb_suspended; extern bool vusb_suspended;
host_driver_t *vusb_driver(void); host_driver_t *vusb_driver(void);
void vusb_transfer_keyboard(void);