#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"
+
+#ifdef SERIAL_MOUSE_ENABLE
+#include "serial_mouse.h"
+#endif
#include "descriptor.h"
#include "lufa.h"
-static uint8_t idle_duration = 0;
-static uint8_t protocol_report = 1;
+uint8_t keyboard_idle = 0;
+uint8_t keyboard_protocol = 1;
static uint8_t keyboard_led_stats = 0;
static report_keyboard_t keyboard_report_sent;
/*******************************************************************************
* USB Events
******************************************************************************/
-/** Event handler for the USB_Connect event. */
+/*
+ * Event Order of Plug in:
+ * 0) EVENT_USB_Device_Connect
+ * 1) EVENT_USB_Device_Suspend
+ * 2) EVENT_USB_Device_Reset
+ * 3) EVENT_USB_Device_Wake
+*/
void EVENT_USB_Device_Connect(void)
{
}
-/** Event handler for the USB_Disconnect event. */
void EVENT_USB_Device_Disconnect(void)
{
}
+void EVENT_USB_Device_Reset(void)
+{
+}
+
+void EVENT_USB_Device_Suspend()
+{
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_enable();
+#endif
+}
+
+void EVENT_USB_Device_WakeUp()
+{
+ suspend_wakeup_init();
+
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_disable();
+ // NOTE: converters may not accept this
+ led_set(host_keyboard_leds());
+#endif
+}
+
void EVENT_USB_Device_StartOfFrame(void)
{
Console_Task();
bool ConfigSuccess = true;
/* Setup Keyboard HID Report Endpoints */
- ConfigSuccess &= Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
- KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
#ifdef MOUSE_ENABLE
/* Setup Mouse HID Report Endpoint */
- ConfigSuccess &= Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
- MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
#ifdef EXTRAKEY_ENABLE
/* Setup Extra HID Report Endpoint */
- ConfigSuccess &= Endpoint_ConfigureEndpoint(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
- EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
#ifdef CONSOLE_ENABLE
/* Setup Console HID Report Endpoints */
- ConfigSuccess &= Endpoint_ConfigureEndpoint(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
- CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
- ConfigSuccess &= Endpoint_ConfigureEndpoint(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
- CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
+#if 0
+ ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
+ CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
+#endif
+#endif
+
+#ifdef NKRO_ENABLE
+ /* Setup NKRO HID Report Endpoints */
+ ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
}
// Interface
switch (USB_ControlRequest.wIndex) {
case KEYBOARD_INTERFACE:
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+#endif
Endpoint_ClearSETUP();
while (!(Endpoint_IsOUTReceived())) {
case HID_REQ_GetProtocol:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
- Endpoint_ClearSETUP();
- while (!(Endpoint_IsINReady()));
- Endpoint_Write_8(protocol_report);
- Endpoint_ClearIN();
- Endpoint_ClearStatusStage();
+ 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))
{
- Endpoint_ClearSETUP();
- Endpoint_ClearStatusStage();
+ if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
- protocol_report = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
+ keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
+#ifdef NKRO_ENABLE
+ keyboard_nkro = !!keyboard_protocol;
+#endif
+ clear_keyboard();
+ }
}
break;
Endpoint_ClearSETUP();
Endpoint_ClearStatusStage();
- idle_duration = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
+ keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
}
break;
{
Endpoint_ClearSETUP();
while (!(Endpoint_IsINReady()));
- Endpoint_Write_8(idle_duration);
+ Endpoint_Write_8(keyboard_idle);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
static void send_keyboard(report_keyboard_t *report)
{
- uint8_t timeout = 0;
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
- // TODO: handle NKRO report
/* Select the Keyboard Report Endpoint */
- Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
+#ifdef NKRO_ENABLE
+ if (keyboard_nkro) {
+ /* Report protocol - NKRO */
+ Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
- /* Check if Keyboard Endpoint Ready for Read/Write */
- while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
+ /* Check if write ready for a polling interval around 1ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
+ if (!Endpoint_IsReadWriteAllowed()) return;
- /* Write Keyboard Report Data */
- Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
+ /* Write Keyboard Report Data */
+ Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
+ }
+ else
+#endif
+ {
+ /* Boot protocol */
+ Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
+
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
+ /* Write Keyboard Report Data */
+ Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
+ }
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
static void send_mouse(report_mouse_t *report)
{
#ifdef MOUSE_ENABLE
- uint8_t timeout = 0;
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
/* Select the Mouse Report Endpoint */
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
- /* Check if Mouse Endpoint Ready for Read/Write */
- while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
/* Write Mouse Report Data */
Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
static void send_system(uint16_t data)
{
- uint8_t timeout = 0;
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
report_extra_t r = {
.report_id = REPORT_ID_SYSTEM,
.usage = data
};
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
- while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
+
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
Endpoint_ClearIN();
}
static void send_consumer(uint16_t data)
{
- uint8_t timeout = 0;
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
report_extra_t r = {
.report_id = REPORT_ID_CONSUMER,
.usage = data
};
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
- while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
+
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
Endpoint_ClearIN();
}
// for Console_Task
USB_Device_EnableSOFEvents();
+ print_set_sendchar(sendchar);
}
int main(void) __attribute__ ((weak));
SetupHardware();
sei();
- print_enable = true;
- debug_enable = true;
- debug_matrix = true;
- debug_keyboard = true;
- debug_mouse = true;
-
- // TODO: can't print here
- debug("LUFA init\n");
+ /* wait for USB startup & debug output */
+ while (USB_DeviceState != DEVICE_STATE_Configured) {
+#if defined(INTERRUPT_CONTROL_ENDPOINT)
+ ;
+#else
+ USB_USBTask();
+#endif
+ }
+ print("USB configured.\n");
+ /* init modules */
keyboard_init();
host_set_driver(&lufa_driver);
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+
+#ifdef SERIAL_MOUSE_ENABLE
+ serial_mouse_init();
+#endif
+
+ print("Keyboard start.\n");
while (1) {
- keyboard_proc();
+ while (USB_DeviceState == DEVICE_STATE_Suspended) {
+ suspend_power_down();
+ if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
+ USB_Device_SendRemoteWakeup();
+ }
+ }
+
+ keyboard_task();
+
+#ifdef SERIAL_MOUSE_ENABLE
+ serial_mouse_task();
+#endif
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();