]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - tmk_core/protocol/chibios/usb_main.c
Merge branch 'master' into chibios
[max/tmk_keyboard.git] / tmk_core / protocol / chibios / usb_main.c
index 2625c42575d6c64d35fe7b05882cb307b96c5526..1ce5b4aedaffb33aa5b7a555b8086d7764d0971f 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "host.h"
 #include "debug.h"
+#include "suspend.h"
 #ifdef SLEEP_LED_ENABLE
 #include "sleep_led.h"
 #include "led.h"
@@ -356,8 +357,8 @@ static const uint8_t hid_configuration_descriptor_data[] = {
                          NUM_INTERFACES,    // bNumInterfaces
                          1,    // bConfigurationValue
                          0,    // iConfiguration
-                         0xA0, // bmAttributes
-                         50),  // bMaxPower (100mA)
+                         0xA0, // bmAttributes (RESERVED|REMOTEWAKEUP)
+                         50),  // bMaxPower (50mA)
 
   /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
   USB_DESC_INTERFACE(KBD_INTERFACE,        // bInterfaceNumber
@@ -793,7 +794,6 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
 
   case USB_EVENT_SUSPEND:
     //TODO: from ISR! print("[S]");
-    //TODO: signal suspend?
 #ifdef SLEEP_LED_ENABLE
     sleep_led_enable();
 #endif /* SLEEP_LED_ENABLE */
@@ -801,7 +801,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
 
   case USB_EVENT_WAKEUP:
     //TODO: from ISR! print("[W]");
-    //TODO: suspend_wakeup_init();
+    suspend_wakeup_init();
 #ifdef SLEEP_LED_ENABLE
     sleep_led_disable();
     // NOTE: converters may not accept this
@@ -1024,6 +1024,27 @@ void init_usb_driver(USBDriver *usbp) {
 #endif
 }
 
+/*
+ * Send remote wakeup packet
+ * Note: should not be called from ISR
+ */
+void send_remote_wakeup(USBDriver *usbp) {
+  (void)usbp;
+#if defined(K20x) || defined(KL2x)
+#if KINETIS_USB_USE_USB0
+  USB0->CTL |= USBx_CTL_RESUME;
+  chThdSleepMilliseconds(15);
+  USB0->CTL &= ~USBx_CTL_RESUME;
+#endif /* KINETIS_USB_USE_USB0 */
+#elif defined(STM32F0XX) /* K20x || KL2x */
+  STM32_USB->CNTR |= CNTR_RESUME;
+  chThdSleepMilliseconds(15);
+  STM32_USB->CNTR &= ~CNTR_RESUME;
+#else /* STM32F0XX */
+#warning Sending remote wakeup packet not implemented for your platform.
+#endif /* K20x || KL2x */
+}
+
 /* ---------------------------------------------------------
  *                  Keyboard functions
  * ---------------------------------------------------------
@@ -1100,19 +1121,26 @@ void send_keyboard(report_keyboard_t *report) {
   }
   osalSysUnlock();
 
+  bool ep_not_ready;
 #ifdef NKRO_ENABLE
   if(keyboard_nkro) {  /* NKRO protocol */
     usbPrepareTransmit(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
-    osalSysLock();
-    usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT);
-    osalSysUnlock();
+    /* need to wait until the previous packet has made it through */
+    do {
+        osalSysLock();
+        ep_not_ready = usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT);
+        osalSysUnlock();
+    } while (ep_not_ready);
   } else
 #endif /* NKRO_ENABLE */
   { /* boot protocol */
-    usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
-    osalSysLock();
-    usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT);
-    osalSysUnlock();
+    usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
+    /* need to wait until the previous packet has made it through */
+    do {
+        osalSysLock();
+        ep_not_ready = usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT);
+        osalSysUnlock();
+    } while (ep_not_ready);
   }
   keyboard_report_sent = *report;
 }