]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - tmk_core/protocol/lufa/lufa.c
lufa: Fix for freeze at re/boot time problem
[max/tmk_keyboard.git] / tmk_core / protocol / lufa / lufa.c
index 4dce8adc9993822cd3ccf7627bf5b44338218871..48034dbeab18ef9af9a668db43d740406be9e6c2 100644 (file)
 #endif
 #include "suspend.h"
 #include "hook.h"
+#include "timer.h"
 
 #ifdef LUFA_DEBUG_SUART
 #include "avr/suart.h"
 #endif
 
+#ifdef LUFA_DEBUG_UART
+#include "uart.h"
+#endif
+
 #include "matrix.h"
 #include "descriptor.h"
 #include "lufa.h"
@@ -99,14 +104,31 @@ static ringbuf_t sendbuf = {
     .size_mask = SENDBUF_SIZE - 1
 };
 
+// TODO: Around 2500ms delay often works anyhoo but proper startup would be better
+// 1000ms delay of hid_listen affects this probably
+/* wait for Console startup */
+static bool console_is_ready(void)
+{
+    static bool hid_listen_ready = false;
+    if (!hid_listen_ready) {
+        if (timer_read32() < 2500)
+            return false;
+        hid_listen_ready = true;
+    }
+    return true;
+}
+
 static bool console_putc(uint8_t c)
 {
+    if (!console_is_ready())
+        goto EXIT;
+
     // return immediately if called while interrupt
     if (!(SREG & (1<<SREG_I)))
-        goto EXIT;;
+        goto EXIT;
 
     if (USB_DeviceState != DEVICE_STATE_Configured)
-        goto EXIT;;
+        goto EXIT;
 
     uint8_t ep = Endpoint_GetCurrentEndpoint();
 
@@ -140,6 +162,9 @@ EXIT:
 
 static void console_flush(void)
 {
+    if (!console_is_ready())
+        return;
+
     if (USB_DeviceState != DEVICE_STATE_Configured)
         return;
 
@@ -197,7 +222,9 @@ static void console_task(void)
 */
 void EVENT_USB_Device_Connect(void)
 {
+#ifdef LUFA_DEBUG
     print("[C]");
+#endif
     /* For battery powered device */
     if (!USB_IsInitialized) {
         USB_Disable();
@@ -208,7 +235,9 @@ void EVENT_USB_Device_Connect(void)
 
 void EVENT_USB_Device_Disconnect(void)
 {
+#ifdef LUFA_DEBUG
     print("[D]");
+#endif
     /* For battery powered device */
     USB_IsInitialized = false;
 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
@@ -468,7 +497,7 @@ static void send_keyboard(report_keyboard_t *report)
         Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
 
         /* Check if write ready for a polling interval around 10ms */
-        while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+        while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(80);
         if (!Endpoint_IsReadWriteAllowed()) return;
 
         /* Write Keyboard Report Data */
@@ -514,7 +543,7 @@ static void send_system(uint16_t data)
 
     report_extra_t r = {
         .report_id = REPORT_ID_SYSTEM,
-        .usage = data
+        .usage = data - SYSTEM_POWER_DOWN + 1
     };
     Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
 
@@ -554,25 +583,22 @@ static void send_consumer(uint16_t data)
 /*******************************************************************************
  * sendchar
  ******************************************************************************/
-#ifdef CONSOLE_ENABLE
 int8_t sendchar(uint8_t c)
 {
     #ifdef LUFA_DEBUG_SUART
     xmit(c);
     #endif
 
-    bool r = console_putc(c);
-    return (r ? 0 : -1);
-}
-#else
-int8_t sendchar(uint8_t c)
-{
-    #ifdef LUFA_DEBUG_SUART
-    xmit(c);
+    #ifdef LUFA_DEBUG_UART
+    uart_putchar(c);
+    #endif
+
+    #ifdef CONSOLE_ENABLE
+    console_putc(c);
     #endif
+
     return 0;
 }
-#endif
 
 
 /*******************************************************************************
@@ -608,11 +634,15 @@ int main(void)
     SUART_OUT_PORT |= (1<<SUART_OUT_BIT);
 #endif
 
+#ifdef LUFA_DEBUG_UART
+    uart_init(115200);
+#endif
+
     // setup sendchar: DO NOT USE print functions before this line
     print_set_sendchar(sendchar);
     host_set_driver(&lufa_driver);
 
-    print("Keyboard init.\n");
+    print("\n\nKeyboard init.\n");
     hook_early_init();
     keyboard_setup();
     setup_usb();
@@ -622,6 +652,8 @@ int main(void)
 
     sei();
 
+    keyboard_init();
+
     /* wait for USB startup */
     while (USB_DeviceState != DEVICE_STATE_Configured) {
 #if defined(INTERRUPT_CONTROL_ENDPOINT)
@@ -629,29 +661,15 @@ int main(void)
 #else
         USB_USBTask();
 #endif
+        matrix_scan();
     }
-
-    keyboard_init();
-
-    /* wait for Console startup */
-    // TODO: long delay often works anyhoo but proper startup would be better
-    // 1000ms delay of hid_listen may affect this
-    uint16_t delay = 2000;
-    while (delay--) {
-#ifndef INTERRUPT_CONTROL_ENDPOINT
-        USB_USBTask();
-#endif
-        _delay_ms(1);
-    }
+    print("\nUSB configured.\n");
 
     hook_late_init();
 
-    print("Keyboard start.\n");
+    print("\nKeyboard start.\n");
     while (1) {
         while (USB_DeviceState == DEVICE_STATE_Suspended) {
-#ifdef LUFA_DEBUG
-            print("[s]");
-#endif
             hook_usb_suspend_loop();
         }
 
@@ -679,12 +697,12 @@ static uint8_t _led_stats = 0;
  __attribute__((weak))
 void hook_usb_suspend_entry(void)
 {
-    // Turn LED off to save power
-    // Set 0 with putting aside status before suspend and restore
-    // it after wakeup, then LED is updated at keyboard_task() in main loop
+    // Turn off LED to save power and keep its status to resotre it later.
+    // LED status will be updated by keyboard_task() in main loop hopefully.
     _led_stats = keyboard_led_stats;
     keyboard_led_stats = 0;
-    led_set(keyboard_led_stats);
+
+    // Calling long task here can prevent USB state transition
 
     matrix_clear();
     clear_keyboard();
@@ -696,7 +714,10 @@ void hook_usb_suspend_entry(void)
 __attribute__((weak))
 void hook_usb_suspend_loop(void)
 {
+#ifndef LUFA_DEBUG_UART
+    // This corrupts debug print when suspend
     suspend_power_down();
+#endif
     if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
         USB_Device_SendRemoteWakeup();
     }
@@ -710,10 +731,8 @@ void hook_usb_wakeup(void)
     sleep_led_disable();
 #endif
 
-    // Restore LED status
-    // BIOS/grub won't recognize/enumerate if led_set() takes long(around 40ms?)
-    // Converters fall into the case and miss wakeup event(timeout to reply?) in the end.
-    //led_set(host_keyboard_leds());
-    // Instead, restore stats and update at keyboard_task() in main loop
+    // Restore LED status and update at keyboard_task() in main loop
     keyboard_led_stats = _led_stats;
+
+    // Calling long task here can prevent USB state transition
 }