#include "report.h"
#include "host.h"
#include "host_driver.h"
#include "keyboard.h"
#include "action.h"
#include "led.h"
#include "sendchar.h"
#include "debug.h"
#ifdef SLEEP_LED_ENABLE
# include "sleep_led.h"
#endif
#include "suspend.h"
#include "usb_descriptor.h"
#include "lufa.h"
#include "quantum.h"
#include <util/atomic.h>
#ifdef NKRO_ENABLE
# include "keycode_config.h"
extern keymap_config_t keymap_config;
#endif
#ifdef AUDIO_ENABLE
# include "audio.h"
#endif
#ifdef BLUETOOTH_ENABLE
# include "outputselect.h"
# ifdef MODULE_ADAFRUIT_BLE
# include "adafruit_ble.h"
# else
# include "../serial.h"
# endif
#endif
#ifdef VIRTSER_ENABLE
# include "virtser.h"
#endif
#ifdef MIDI_ENABLE
# include "qmk_midi.h"
#endif
#ifdef RAW_ENABLE
# include "raw_hid.h"
#endif
#ifdef JOYSTICK_ENABLE
# include "joystick.h"
#endif
static inline uint16_t CONSUMER2RN42(uint16_t usage) {
switch (usage) {
case AC_HOME:
return 0x0001;
case AL_EMAIL:
return 0x0002;
case AC_SEARCH:
return 0x0004;
case AL_KEYBOARD_LAYOUT:
return 0x0008;
case AUDIO_VOL_UP:
return 0x0010;
case AUDIO_VOL_DOWN:
return 0x0020;
case AUDIO_MUTE:
return 0x0040;
case TRANSPORT_PLAY_PAUSE:
return 0x0080;
case TRANSPORT_NEXT_TRACK:
return 0x0100;
case TRANSPORT_PREV_TRACK:
return 0x0200;
case TRANSPORT_STOP:
return 0x0400;
case TRANSPORT_EJECT:
return 0x0800;
case TRANSPORT_FAST_FORWARD:
return 0x1000;
case TRANSPORT_REWIND:
return 0x2000;
case TRANSPORT_STOP_EJECT:
return 0x4000;
case AL_LOCAL_BROWSER:
return 0x8000;
default:
return 0;
}
}
uint8_t keyboard_idle = 0;
uint8_t keyboard_protocol = 1;
static uint8_t keyboard_led_state = 0;
static report_keyboard_t keyboard_report_sent;
static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report);
static void send_mouse(report_mouse_t *report);
static void send_system(uint16_t data);
static void send_consumer(uint16_t data);
host_driver_t lufa_driver = {
keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer,
};
#ifdef VIRTSER_ENABLE
USB_ClassInfo_CDC_Device_t cdc_device = {
.Config = {
.ControlInterfaceNumber = CCI_INTERFACE,
.DataINEndpoint = {
.Address = (CDC_IN_EPNUM | ENDPOINT_DIR_IN),
.Size = CDC_EPSIZE,
.Banks = 1
},
.DataOUTEndpoint = {
.Address = (CDC_OUT_EPNUM | ENDPOINT_DIR_OUT),
.Size = CDC_EPSIZE,
.Banks = 1
},
.NotificationEndpoint = {
.Address = (CDC_NOTIFICATION_EPNUM | ENDPOINT_DIR_IN),
.Size = CDC_NOTIFICATION_EPSIZE,
.Banks = 1
}
}
};
#endif
#ifdef RAW_ENABLE
void raw_hid_send(uint8_t *data, uint8_t length) {
if (length != RAW_EPSIZE) {
return;
}
if (USB_DeviceState != DEVICE_STATE_Configured) {
return;
}
uint8_t ep = Endpoint_GetCurrentEndpoint();
Endpoint_SelectEndpoint(RAW_IN_EPNUM);
if (Endpoint_IsINReady()) {
Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL);
Endpoint_ClearIN();
}
Endpoint_SelectEndpoint(ep);
}
__attribute__((weak)) void raw_hid_receive(uint8_t *data, uint8_t length) {
}
static void raw_hid_task(void) {
uint8_t data[RAW_EPSIZE];
bool data_read = false;
if (USB_DeviceState != DEVICE_STATE_Configured) return;
Endpoint_SelectEndpoint(RAW_OUT_EPNUM);
if (Endpoint_IsOUTReceived()) {
if (Endpoint_IsReadWriteAllowed()) {
Endpoint_Read_Stream_LE(data, sizeof(data), NULL);
data_read = true;
}
Endpoint_ClearOUT();
if (data_read) {
raw_hid_receive(data, sizeof(data));
}
}
}
#endif
#ifdef CONSOLE_ENABLE
static void Console_Task(void) {
if (USB_DeviceState != DEVICE_STATE_Configured) return;
uint8_t ep = Endpoint_GetCurrentEndpoint();
# if 0
Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
if (Endpoint_IsOUTReceived())
{
if (Endpoint_IsReadWriteAllowed())
{
uint8_t ConsoleData[CONSOLE_EPSIZE];
Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
}
Endpoint_ClearOUT();
}
# endif
Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
Endpoint_SelectEndpoint(ep);
return;
}
while (Endpoint_IsReadWriteAllowed()) Endpoint_Write_8(0);
if (Endpoint_IsINReady()) {
Endpoint_ClearIN();
}
Endpoint_SelectEndpoint(ep);
}
#endif
#ifdef JOYSTICK_ENABLE
void send_joystick_packet(joystick_t *joystick) {
uint8_t timeout = 255;
joystick_report_t r = {
# if JOYSTICK_AXES_COUNT > 0
.axes =
{
joystick->axes[0],
# if JOYSTICK_AXES_COUNT >= 2
joystick->axes[1],
# endif
# if JOYSTICK_AXES_COUNT >= 3
joystick->axes[2],
# endif
# if JOYSTICK_AXES_COUNT >= 4
joystick->axes[3],
# endif
# if JOYSTICK_AXES_COUNT >= 5
joystick->axes[4],
# endif
# if JOYSTICK_AXES_COUNT >= 6
joystick->axes[5],
# endif
},
# endif
# if JOYSTICK_BUTTON_COUNT > 0
.buttons =
{
joystick->buttons[0],
# if JOYSTICK_BUTTON_COUNT > 8
joystick->buttons[1],
# endif
# if JOYSTICK_BUTTON_COUNT > 16
joystick->buttons[2],
# endif
# if JOYSTICK_BUTTON_COUNT > 24
joystick->buttons[3],
# endif
}
# endif };
Endpoint_SelectEndpoint(JOYSTICK_IN_EPNUM);
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
Endpoint_Write_Stream_LE(&r, sizeof(joystick_report_t), NULL);
Endpoint_ClearIN();
}
#endif
void EVENT_USB_Device_Connect(void) {
print("[C]");
if (!USB_IsInitialized) {
USB_Disable();
USB_Init();
USB_Device_EnableSOFEvents();
}
}
void EVENT_USB_Device_Disconnect(void) {
print("[D]");
USB_IsInitialized = false;
}
void EVENT_USB_Device_Reset(void) { print("[R]"); }
void EVENT_USB_Device_Suspend() {
print("[S]");
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif
}
void EVENT_USB_Device_WakeUp() {
print("[W]");
#if defined(NO_USB_STARTUP_CHECK)
suspend_wakeup_init();
#endif
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
led_set(host_keyboard_leds());
#endif
}
#ifdef CONSOLE_ENABLE
static bool console_flush = false;
# define CONSOLE_FLUSH_SET(b) \
do { \
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { console_flush = b; } \
} while (0)
void EVENT_USB_Device_StartOfFrame(void) {
static uint8_t count;
if (++count % 50) return;
count = 0;
if (!console_flush) return;
Console_Task();
console_flush = false;
}
#endif
void EVENT_USB_Device_ConfigurationChanged(void) {
bool ConfigSuccess = true;
#ifndef KEYBOARD_SHARED_EP
ConfigSuccess &= Endpoint_ConfigureEndpoint((KEYBOARD_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, KEYBOARD_EPSIZE, 1);
#endif
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
ConfigSuccess &= Endpoint_ConfigureEndpoint((MOUSE_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, MOUSE_EPSIZE, 1);
#endif
#ifdef SHARED_EP_ENABLE
ConfigSuccess &= Endpoint_ConfigureEndpoint((SHARED_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, SHARED_EPSIZE, 1);
#endif
#ifdef RAW_ENABLE
ConfigSuccess &= Endpoint_ConfigureEndpoint((RAW_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, RAW_EPSIZE, 1);
ConfigSuccess &= Endpoint_ConfigureEndpoint((RAW_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_INTERRUPT, RAW_EPSIZE, 1);
#endif
#ifdef CONSOLE_ENABLE
ConfigSuccess &= Endpoint_ConfigureEndpoint((CONSOLE_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, CONSOLE_EPSIZE, 1);
# if 0
ConfigSuccess &= Endpoint_ConfigureEndpoint((CONSOLE_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_INTERRUPT, CONSOLE_EPSIZE, 1);
# endif
#endif
#ifdef MIDI_ENABLE
ConfigSuccess &= Endpoint_ConfigureEndpoint((MIDI_STREAM_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_BULK, MIDI_STREAM_EPSIZE, 1);
ConfigSuccess &= Endpoint_ConfigureEndpoint((MIDI_STREAM_OUT_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_BULK, MIDI_STREAM_EPSIZE, 1);
#endif
#ifdef VIRTSER_ENABLE
ConfigSuccess &= Endpoint_ConfigureEndpoint((CDC_NOTIFICATION_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, 1);
ConfigSuccess &= Endpoint_ConfigureEndpoint((CDC_OUT_EPNUM | ENDPOINT_DIR_OUT), EP_TYPE_BULK, CDC_EPSIZE, 1);
ConfigSuccess &= Endpoint_ConfigureEndpoint((CDC_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_BULK, CDC_EPSIZE, 1);
#endif
#ifdef JOYSTICK_ENABLE
ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
#endif
}
void EVENT_USB_Device_ControlRequest(void) {
uint8_t *ReportData = NULL;
uint8_t ReportSize = 0;
switch (USB_ControlRequest.bRequest) {
case HID_REQ_GetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) {
Endpoint_ClearSETUP();
switch (USB_ControlRequest.wIndex) {
case KEYBOARD_INTERFACE:
ReportData = (uint8_t *)&keyboard_report_sent;
ReportSize = sizeof(keyboard_report_sent);
break;
}
Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
Endpoint_ClearOUT();
}
break;
case HID_REQ_SetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) {
switch (USB_ControlRequest.wIndex) {
case KEYBOARD_INTERFACE:
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
case SHARED_INTERFACE:
#endif
Endpoint_ClearSETUP();
while (!(Endpoint_IsOUTReceived())) {
if (USB_DeviceState == DEVICE_STATE_Unattached) return;
}
if (Endpoint_BytesInEndpoint() == 2) {
uint8_t report_id = Endpoint_Read_8();
if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
keyboard_led_state = Endpoint_Read_8();
}
} else {
keyboard_led_state = Endpoint_Read_8();
}
Endpoint_ClearOUT();
Endpoint_ClearStatusStage();
break;
}
}
break;
case HID_REQ_GetProtocol:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) {
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()))
;
Endpoint_Write_8(keyboard_protocol);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
}
break;
case HID_REQ_SetProtocol:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) {
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
clear_keyboard();
}
}
break;
case HID_REQ_SetIdle:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) {
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
}
break;
case HID_REQ_GetIdle:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) {
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()))
;
Endpoint_Write_8(keyboard_idle);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
break;
}
#ifdef VIRTSER_ENABLE
CDC_Device_ProcessControlRequest(&cdc_device);
#endif
}
static uint8_t keyboard_leds(void) { return keyboard_led_state; }
static void send_keyboard(report_keyboard_t *report) {
uint8_t timeout = 255;
#ifdef BLUETOOTH_ENABLE
if (where_to_send() == OUTPUT_BLUETOOTH) {
# ifdef MODULE_ADAFRUIT_BLE
adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
# elif MODULE_RN42
serial_send(0xFD);
serial_send(0x09);
serial_send(0x01);
serial_send(report->mods);
serial_send(report->reserved);
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
serial_send(report->keys[i]);
}
# endif
return;
}
#endif
uint8_t ep = KEYBOARD_IN_EPNUM;
uint8_t size = KEYBOARD_REPORT_SIZE;
#ifdef NKRO_ENABLE
if (keyboard_protocol && keymap_config.nkro) {
ep = SHARED_IN_EPNUM;
size = sizeof(struct nkro_report);
}
#endif
Endpoint_SelectEndpoint(ep);
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
if (!keyboard_protocol) {
Endpoint_Write_Stream_LE(&report->mods, 8, NULL);
} else {
Endpoint_Write_Stream_LE(report, size, NULL);
}
Endpoint_ClearIN();
keyboard_report_sent = *report;
}
static void send_mouse(report_mouse_t *report) {
#ifdef MOUSE_ENABLE
uint8_t timeout = 255;
# ifdef BLUETOOTH_ENABLE
if (where_to_send() == OUTPUT_BLUETOOTH) {
# ifdef MODULE_ADAFRUIT_BLE
adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h, report->buttons);
# else
serial_send(0xFD);
serial_send(0x00);
serial_send(0x03);
serial_send(report->buttons);
serial_send(report->x);
serial_send(report->y);
serial_send(report->v); serial_send(report->h); serial_send(0x00);
# endif
return;
}
# endif
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
Endpoint_ClearIN();
#endif
}
#ifdef EXTRAKEY_ENABLE
static void send_extra(uint8_t report_id, uint16_t data) {
uint8_t timeout = 255;
if (USB_DeviceState != DEVICE_STATE_Configured) return;
report_extra_t r = {.report_id = report_id, .usage = data};
Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
if (!Endpoint_IsReadWriteAllowed()) return;
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
Endpoint_ClearIN();
}
#endif
static void send_system(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
send_extra(REPORT_ID_SYSTEM, data);
#endif
}
static void send_consumer(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
# ifdef BLUETOOTH_ENABLE
if (where_to_send() == OUTPUT_BLUETOOTH) {
# ifdef MODULE_ADAFRUIT_BLE
adafruit_ble_send_consumer_key(data);
# elif MODULE_RN42
static uint16_t last_data = 0;
if (data == last_data) return;
last_data = data;
uint16_t bitmap = CONSUMER2RN42(data);
serial_send(0xFD);
serial_send(0x03);
serial_send(0x03);
serial_send(bitmap & 0xFF);
serial_send((bitmap >> 8) & 0xFF);
# endif
return;
}
# endif
send_extra(REPORT_ID_CONSUMER, data);
#endif
}
#ifdef CONSOLE_ENABLE
# define SEND_TIMEOUT 5
int8_t sendchar(uint8_t c) {
static bool timed_out = false;
CONSOLE_FLUSH_SET(false);
if (USB_DeviceState != DEVICE_STATE_Configured) return -1;
uint8_t ep = Endpoint_GetCurrentEndpoint();
Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
goto ERROR_EXIT;
}
if (timed_out && !Endpoint_IsReadWriteAllowed()) {
goto ERROR_EXIT;
}
timed_out = false;
uint8_t timeout = SEND_TIMEOUT;
while (!Endpoint_IsReadWriteAllowed()) {
if (USB_DeviceState != DEVICE_STATE_Configured) {
goto ERROR_EXIT;
}
if (Endpoint_IsStalled()) {
goto ERROR_EXIT;
}
if (!(timeout--)) {
timed_out = true;
goto ERROR_EXIT;
}
_delay_ms(1);
}
Endpoint_Write_8(c);
if (!Endpoint_IsReadWriteAllowed()) {
while (!(Endpoint_IsINReady()))
;
Endpoint_ClearIN();
} else {
CONSOLE_FLUSH_SET(true);
}
Endpoint_SelectEndpoint(ep);
return 0;
ERROR_EXIT:
Endpoint_SelectEndpoint(ep);
return -1;
}
#endif
#ifdef MIDI_ENABLE
USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface = {
.Config = {
.StreamingInterfaceNumber = AS_INTERFACE,
.DataINEndpoint = {
.Address = (MIDI_STREAM_IN_EPNUM | ENDPOINT_DIR_IN),
.Size = MIDI_STREAM_EPSIZE,
.Banks = 1
},
.DataOUTEndpoint = {
.Address = (MIDI_STREAM_OUT_EPNUM | ENDPOINT_DIR_OUT),
.Size = MIDI_STREAM_EPSIZE,
.Banks = 1
}
}
};
void send_midi_packet(MIDI_EventPacket_t *event) { MIDI_Device_SendEventPacket(&USB_MIDI_Interface, event); }
bool recv_midi_packet(MIDI_EventPacket_t *const event) { return MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, event); }
#endif
#ifdef VIRTSER_ENABLE
void virtser_init(void) {
cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR;
CDC_Device_SendControlLineStateChange(&cdc_device);
}
void virtser_recv(uint8_t c) __attribute__((weak));
void virtser_recv(uint8_t c) {
}
void virtser_task(void) {
uint16_t count = CDC_Device_BytesReceived(&cdc_device);
uint8_t ch;
for (; count; --count) {
ch = CDC_Device_ReceiveByte(&cdc_device);
virtser_recv(ch);
}
}
void virtser_send(const uint8_t byte) {
uint8_t timeout = 255;
uint8_t ep = Endpoint_GetCurrentEndpoint();
if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR) {
Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address);
if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
Endpoint_SelectEndpoint(ep);
return;
}
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
Endpoint_Write_8(byte);
CDC_Device_Flush(&cdc_device);
if (Endpoint_IsINReady()) {
Endpoint_ClearIN();
}
Endpoint_SelectEndpoint(ep);
}
}
#endif
static void setup_mcu(void) {
MCUSR &= ~_BV(WDRF);
wdt_disable();
clock_prescale_set(clock_div_1);
}
static void setup_usb(void) {
USB_Disable();
USB_Init();
USB_Device_EnableSOFEvents();
}
int main(void) __attribute__((weak));
int main(void) {
#ifdef MIDI_ENABLE
setup_midi();
#endif
setup_mcu();
keyboard_setup();
setup_usb();
sei();
#if defined(MODULE_RN42)
serial_init();
#endif
#ifdef WAIT_FOR_USB
while (USB_DeviceState != DEVICE_STATE_Configured) {
# if defined(INTERRUPT_CONTROL_ENDPOINT)
;
# else
USB_USBTask();
# endif
}
print("USB configured.\n");
#else
USB_USBTask();
#endif
keyboard_init();
host_set_driver(&lufa_driver);
#ifdef SLEEP_LED_ENABLE
sleep_led_init();
#endif
#ifdef VIRTSER_ENABLE
virtser_init();
#endif
print("Keyboard start.\n");
while (1) {
#if !defined(NO_USB_STARTUP_CHECK)
if (USB_DeviceState == DEVICE_STATE_Suspended) {
print("[s]");
while (USB_DeviceState == DEVICE_STATE_Suspended) {
suspend_power_down();
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
USB_Device_SendRemoteWakeup();
clear_keyboard();
# if USB_SUSPEND_WAKEUP_DELAY > 0
wait_ms(USB_SUSPEND_WAKEUP_DELAY);
# endif
}
}
suspend_wakeup_init();
}
#endif
keyboard_task();
#ifdef MIDI_ENABLE
MIDI_Device_USBTask(&USB_MIDI_Interface);
#endif
#ifdef MODULE_ADAFRUIT_BLE
adafruit_ble_task();
#endif
#ifdef VIRTSER_ENABLE
virtser_task();
CDC_Device_USBTask(&cdc_device);
#endif
#ifdef RAW_ENABLE
raw_hid_task();
#endif
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();
#endif
housekeeping_task();
}
}
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint16_t wIndex, const void **const DescriptorAddress) { return get_usb_descriptor(wValue, wIndex, DescriptorAddress); }