Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ChibiOS: Decouple USB events from the USB interrupt handler #10437

Merged
merged 1 commit into from
Jan 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions tmk_core/protocol/chibios/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ int main(void) {
keyboard_setup();

/* Init USB */
usb_event_queue_init();
init_usb_driver(&USB_DRIVER);

#ifdef MIDI_ENABLE
Expand Down Expand Up @@ -221,6 +222,8 @@ int main(void) {

/* Main loop */
while (true) {
usb_event_queue_task();

#if !defined(NO_USB_STARTUP_CHECK)
if (USB_DRIVER.state == USB_SUSPENDED) {
print("[s]");
Expand Down
75 changes: 66 additions & 9 deletions tmk_core/protocol/chibios/usb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include <ch.h>
#include <hal.h>
#include <string.h>

#include "usb_main.h"

Expand Down Expand Up @@ -368,6 +369,69 @@ static usb_driver_configs_t drivers = {
* ---------------------------------------------------------
*/

#define USB_EVENT_QUEUE_SIZE 16
usbevent_t event_queue[USB_EVENT_QUEUE_SIZE];
uint8_t event_queue_head;
uint8_t event_queue_tail;

void usb_event_queue_init(void) {
// Initialise the event queue
memset(&event_queue, 0, sizeof(event_queue));
event_queue_head = 0;
event_queue_tail = 0;
}

static inline bool usb_event_queue_enqueue(usbevent_t event) {
uint8_t next = (event_queue_head + 1) % USB_EVENT_QUEUE_SIZE;
if (next == event_queue_tail) {
return false;
}
event_queue[event_queue_head] = event;
event_queue_head = next;
return true;
}

static inline bool usb_event_queue_dequeue(usbevent_t *event) {
if (event_queue_head == event_queue_tail) {
return false;
}
*event = event_queue[event_queue_tail];
event_queue_tail = (event_queue_tail + 1) % USB_EVENT_QUEUE_SIZE;
return true;
}

static inline void usb_event_suspend_handler(void) {
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif /* SLEEP_LED_ENABLE */
}

static inline void usb_event_wakeup_handler(void) {
suspend_wakeup_init();
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
// NOTE: converters may not accept this
led_set(host_keyboard_leds());
#endif /* SLEEP_LED_ENABLE */
}

void usb_event_queue_task(void) {
usbevent_t event;
while (usb_event_queue_dequeue(&event)) {
switch (event) {
case USB_EVENT_SUSPEND:
usb_event_suspend_handler();
break;
case USB_EVENT_WAKEUP:
usb_event_wakeup_handler();
break;
default:
// Nothing to do, we don't handle it.
break;
}
}
}

/* Handles the USB driver global events
* TODO: maybe disable some things when connection is lost? */
static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
Expand Down Expand Up @@ -402,9 +466,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
osalSysUnlockFromISR();
return;
case USB_EVENT_SUSPEND:
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif /* SLEEP_LED_ENABLE */
usb_event_queue_enqueue(USB_EVENT_SUSPEND);
/* Falls into.*/
case USB_EVENT_UNCONFIGURED:
/* Falls into.*/
Expand All @@ -425,12 +487,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
qmkusbWakeupHookI(&drivers.array[i].driver);
chSysUnlockFromISR();
}
suspend_wakeup_init();
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
// NOTE: converters may not accept this
led_set(host_keyboard_leds());
#endif /* SLEEP_LED_ENABLE */
usb_event_queue_enqueue(USB_EVENT_WAKEUP);
return;

case USB_EVENT_STALLED:
Expand Down
11 changes: 11 additions & 0 deletions tmk_core/protocol/chibios/usb_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ void init_usb_driver(USBDriver *usbp);
/* Restart the USB driver and bus */
void restart_usb_driver(USBDriver *usbp);

/* ---------------
* USB Event queue
* ---------------
*/

/* Initialisation of the FIFO */
void usb_event_queue_init(void);

/* Task to dequeue and execute any handlers for the USB events on the main thread */
void usb_event_queue_task(void);

/* ---------------
* Keyboard header
* ---------------
Expand Down