Merge upstream QMK Firmware at '0.12.52~1'
This commit is contained in:
@@ -167,6 +167,7 @@ int main(void) {
|
||||
keyboard_setup();
|
||||
|
||||
/* Init USB */
|
||||
usb_event_queue_init();
|
||||
init_usb_driver(&USB_DRIVER);
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
@@ -225,6 +226,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]");
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "usb_main.h"
|
||||
|
||||
@@ -50,6 +51,7 @@ extern keymap_config_t keymap_config;
|
||||
#ifdef WEBUSB_ENABLE
|
||||
# include "webusb.h"
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
# include "joystick.h"
|
||||
#endif
|
||||
@@ -168,6 +170,7 @@ static const USBEndpointConfig shared_ep_config = {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WEBUSB_ENABLE
|
||||
/** Microsoft OS 2.0 Descriptor. This is used by Windows to select the USB driver for the device.
|
||||
*
|
||||
@@ -397,6 +400,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) {
|
||||
@@ -431,9 +497,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.*/
|
||||
@@ -454,12 +518,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:
|
||||
@@ -575,7 +634,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||
if (!keymap_config.nkro && keyboard_idle) {
|
||||
#else /* NKRO_ENABLE */
|
||||
if (keyboard_idle) {
|
||||
#endif /* NKRO_ENABLE */
|
||||
#endif /* NKRO_ENABLE */
|
||||
/* arm the idle timer if boot protocol & idle */
|
||||
osalSysLockFromISR();
|
||||
chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
|
||||
@@ -867,7 +926,7 @@ void send_mouse(report_mouse_t *report) {
|
||||
}
|
||||
|
||||
#else /* MOUSE_ENABLE */
|
||||
void send_mouse(report_mouse_t *report) { (void)report; }
|
||||
void send_mouse(report_mouse_t *report) { (void)report; }
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
@@ -923,9 +982,32 @@ void send_consumer(uint16_t data) {
|
||||
#ifdef CONSOLE_ENABLE
|
||||
|
||||
int8_t sendchar(uint8_t c) {
|
||||
// The previous implmentation had timeouts, but I think it's better to just slow down
|
||||
// and make sure that everything is transferred, rather than dropping stuff
|
||||
return chnWrite(&drivers.console_driver.driver, &c, 1);
|
||||
static bool timed_out = false;
|
||||
/* The `timed_out` state is an approximation of the ideal `is_listener_disconnected?` state.
|
||||
*
|
||||
* When a 5ms timeout write has timed out, hid_listen is most likely not running, or not
|
||||
* listening to this keyboard, so we go into the timed_out state. In this state we assume
|
||||
* that hid_listen is most likely not gonna be connected to us any time soon, so it would
|
||||
* be wasteful to write follow-up characters with a 5ms timeout, it would all add up and
|
||||
* unncecessarily slow down the firmware. However instead of just dropping the characters,
|
||||
* we write them with a TIME_IMMEDIATE timeout, which is a zero timeout,
|
||||
* and this will succeed only if hid_listen gets connected again. When a write with
|
||||
* TIME_IMMEDIATE timeout succeeds, we know that hid_listen is listening to us again, and
|
||||
* we can go back to the timed_out = false state, and following writes will be executed
|
||||
* with a 5ms timeout. The reason we don't just send all characters with the TIME_IMMEDIATE
|
||||
* timeout is that this could cause bytes to be lost even if hid_listen is running, if there
|
||||
* is a lot of data being sent over the console.
|
||||
*
|
||||
* This logic will work correctly as long as hid_listen is able to receive at least 200
|
||||
* bytes per second. On a heavily overloaded machine that's so overloaded that it's
|
||||
* unusable, and constantly swapping, hid_listen might have trouble receiving 200 bytes per
|
||||
* second, so some bytes might be lost on the console.
|
||||
*/
|
||||
|
||||
const sysinterval_t timeout = timed_out ? TIME_IMMEDIATE : TIME_MS2I(5);
|
||||
const size_t result = chnWriteTimeout(&drivers.console_driver.driver, &c, 1, timeout);
|
||||
timed_out = (result == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Just a dummy function for now, this could be exposed as a weak function
|
||||
@@ -946,15 +1028,8 @@ void console_task(void) {
|
||||
} while (size > 0);
|
||||
}
|
||||
|
||||
#else /* CONSOLE_ENABLE */
|
||||
int8_t sendchar(uint8_t c) {
|
||||
(void)c;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONSOLE_ENABLE */
|
||||
|
||||
void _putchar(char character) { sendchar(character); }
|
||||
|
||||
#ifdef RAW_ENABLE
|
||||
void raw_hid_send(uint8_t *data, uint8_t length) {
|
||||
// TODO: implement variable size packet
|
||||
|
||||
@@ -37,6 +37,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
|
||||
* ---------------
|
||||
|
||||
Reference in New Issue
Block a user