#include "host.h"
#include "debug.h"
+#include "suspend.h"
#ifdef SLEEP_LED_ENABLE
#include "sleep_led.h"
#include "led.h"
#endif /* NKRO_ENABLE */
report_keyboard_t keyboard_report_sent = {{0}};
+#ifdef MOUSE_ENABLE
+report_mouse_t mouse_report_blank = {0};
+#endif /* MOUSE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+uint8_t extra_report_blank[3] = {0};
+#endif /* EXTRAKEY_ENABLE */
#ifdef CONSOLE_ENABLE
/* The emission queue */
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
case USB_EVENT_SUSPEND:
//TODO: from ISR! print("[S]");
- //TODO: signal suspend?
#ifdef SLEEP_LED_ENABLE
sleep_led_enable();
#endif /* SLEEP_LED_ENABLE */
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
return TRUE;
break;
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
+ return TRUE;
+ break;
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ usbSetupTransfer(usbp, console_queue_buffer, CONSOLE_EPSIZE, NULL);
+ return TRUE;
+ break;
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+ case EXTRA_INTERFACE:
+ if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
+ switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
+ case REPORT_ID_SYSTEM:
+ extra_report_blank[0] = REPORT_ID_SYSTEM;
+ usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
+ return TRUE;
+ break;
+ case REPORT_ID_CONSUMER:
+ extra_report_blank[0] = REPORT_ID_CONSUMER;
+ usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ break;
+#endif /* EXTRAKEY_ENABLE */
+
default:
usbSetupTransfer(usbp, NULL, 0, NULL);
return TRUE;
#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) || defined(STM32F1XX) /* K20x || KL2x */
+ STM32_USB->CNTR |= CNTR_RESUME;
+ chThdSleepMilliseconds(15);
+ STM32_USB->CNTR &= ~CNTR_RESUME;
+#else /* STM32F0XX || STM32F1XX */
+#warning Sending remote wakeup packet not implemented for your platform.
+#endif /* K20x || KL2x */
+}
+
/* ---------------------------------------------------------
* Keyboard functions
* ---------------------------------------------------------
}
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;
}
return 0;
}
osalSysUnlock();
- /* should get suspended and wait if the queue is full
- * but it's not blocking even if noone is listening,
- * because the USB packets are sent anyway */
- return(chOQPut(&console_queue, c));
+ /* Timeout after 5us if the queue is full.
+ * Increase this timeout if too much stuff is getting
+ * dropped (i.e. the buffer is getting full too fast
+ * for USB/HIDRAW to dequeue). Another possibility
+ * for fixing this kind of thing is to increase
+ * CONSOLE_QUEUE_CAPACITY. */
+ return(chOQPutTimeout(&console_queue, c, US2ST(5)));
}
#else /* CONSOLE_ENABLE */