]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - tmk_core/protocol/lufa/lufa.c
Merge pull request #355 from papodaca/XT
[max/tmk_keyboard.git] / tmk_core / protocol / lufa / lufa.c
index 391064c9b29db008dbc59d0f02d699af9bf8b1cf..beec6b2be31d3f30d926f0fbcc652f4bce839473 100644 (file)
 #include "sleep_led.h"
 #endif
 #include "suspend.h"
+#include "hook.h"
 
 #include "descriptor.h"
 #include "lufa.h"
 
 uint8_t keyboard_idle = 0;
+/* 0: Boot Protocol, 1: Report Protocol(default) */
 uint8_t keyboard_protocol = 1;
 static uint8_t keyboard_led_stats = 0;
 
@@ -179,31 +181,39 @@ void EVENT_USB_Device_Reset(void)
 void EVENT_USB_Device_Suspend()
 {
     print("[S]");
-    matrix_power_down();
-#ifdef SLEEP_LED_ENABLE
-    sleep_led_enable();
-#endif
+    hook_usb_suspend_entry();
 }
 
 void EVENT_USB_Device_WakeUp()
 {
     print("[W]");
-    suspend_wakeup_init();
-
-#ifdef SLEEP_LED_ENABLE
-    sleep_led_disable();
-    // NOTE: converters may not accept this
-    led_set(host_keyboard_leds());
-#endif
+    hook_usb_wakeup();
 }
 
+#ifdef CONSOLE_ENABLE
+static bool console_flush = false;
+#define CONSOLE_FLUSH_SET(b)   do { \
+    uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
+} while (0)
+
+// called every 1ms
 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
 
 /** Event handler for the USB_ConfigurationChanged event.
  * This is fired when the host sets the current configuration of the USB device after enumeration.
+ *
+ * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
+ * it is safe to use singl bank for all endpoints.
  */
 void EVENT_USB_Device_ConfigurationChanged(void)
 {
@@ -228,7 +238,7 @@ void EVENT_USB_Device_ConfigurationChanged(void)
 #ifdef CONSOLE_ENABLE
     /* Setup Console HID Report Endpoints */
     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
-                                     CONSOLE_EPSIZE, ENDPOINT_BANK_DOUBLE);
+                                     CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
 #if 0
     ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
                                      CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
@@ -333,10 +343,7 @@ void EVENT_USB_Device_ControlRequest(void)
                     Endpoint_ClearSETUP();
                     Endpoint_ClearStatusStage();
 
-                    keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
-#ifdef NKRO_ENABLE
-                    keyboard_nkro = !!keyboard_protocol;
-#endif
+                    keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
                     clear_keyboard();
                 }
             }
@@ -383,7 +390,7 @@ static void send_keyboard(report_keyboard_t *report)
 
     /* Select the Keyboard Report Endpoint */
 #ifdef NKRO_ENABLE
-    if (keyboard_nkro) {
+    if (keyboard_protocol && keyboard_nkro) {
         /* Report protocol - NKRO */
         Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
 
@@ -491,6 +498,10 @@ int8_t sendchar(uint8_t c)
     // Because sendchar() is called so many times, waiting each call causes big lag.
     static bool timeouted = false;
 
+    // prevents Console_Task() from running during sendchar() runs.
+    // or char will be lost. These two function is mutually exclusive.
+    CONSOLE_FLUSH_SET(false);
+
     if (USB_DeviceState != DEVICE_STATE_Configured)
         return -1;
 
@@ -524,8 +535,12 @@ int8_t sendchar(uint8_t c)
     Endpoint_Write_8(c);
 
     // send when bank is full
-    if (!Endpoint_IsReadWriteAllowed())
+    if (!Endpoint_IsReadWriteAllowed()) {
+        while (!(Endpoint_IsINReady()));
         Endpoint_ClearIN();
+    } else {
+        CONSOLE_FLUSH_SET(true);
+    }
 
     Endpoint_SelectEndpoint(ep);
     return 0;
@@ -570,6 +585,7 @@ int main(void)  __attribute__ ((weak));
 int main(void)
 {
     setup_mcu();
+    hook_early_init();
     keyboard_setup();
     setup_usb();
     sei();
@@ -592,13 +608,11 @@ int main(void)
 #endif
 
     print("Keyboard start.\n");
+    hook_late_init();
     while (1) {
         while (USB_DeviceState == DEVICE_STATE_Suspended) {
             print("[s]");
-            suspend_power_down();
-            if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
-                    USB_Device_SendRemoteWakeup();
-            }
+            hook_usb_suspend_loop();
         }
 
         keyboard_task();
@@ -608,3 +622,39 @@ int main(void)
 #endif
     }
 }
+
+
+/* hooks */
+__attribute__((weak))
+void hook_early_init(void) {}
+
+__attribute__((weak))
+void hook_late_init(void) {}
+
+ __attribute__((weak))
+void hook_usb_suspend_entry(void)
+{
+#ifdef SLEEP_LED_ENABLE
+    sleep_led_enable();
+#endif
+}
+
+__attribute__((weak))
+void hook_usb_suspend_loop(void)
+{
+    suspend_power_down();
+    if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
+            USB_Device_SendRemoteWakeup();
+    }
+}
+
+__attribute__((weak))
+void hook_usb_wakeup(void)
+{
+    suspend_wakeup_init();
+#ifdef SLEEP_LED_ENABLE
+    sleep_led_disable();
+    // NOTE: converters may not accept this
+    led_set(host_keyboard_leds());
+#endif
+}