#include "sleep_led.h"
#include "led.h"
#endif
+#include "hook.h"
+
+/* TMK hooks */
+__attribute__((weak))
+void hook_usb_wakeup(void) {
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_disable();
+ // NOTE: converters may not accept this
+ led_set(host_keyboard_leds());
+#endif /* SLEEP_LED_ENABLE */
+}
+
+ __attribute__((weak))
+void hook_usb_suspend_entry(void) {
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_enable();
+#endif /* SLEEP_LED_ENABLE */
+}
+
/* ---------------------------------------------------------
* Global interface variables and declarations
* ---------------------------------------------------------
*/
-uint8_t keyboard_idle = 0;
-uint8_t keyboard_protocol = 1;
-uint16_t keyboard_led_stats = 0;
+uint8_t keyboard_idle __attribute__((aligned(2))) = 0;
+uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
+uint16_t keyboard_led_stats __attribute__((aligned(2))) = 0;
volatile uint16_t keyboard_idle_count = 0;
static virtual_timer_t keyboard_idle_timer;
static void keyboard_idle_timer_cb(void *arg);
0x95, KBD_REPORT_KEYS, // Report Count (),
0x75, 0x08, // Report Size (8),
0x15, 0x00, // Logical Minimum (0),
- 0x25, 0xFF, // Logical Maximum(255),
+ 0x26, 0xFF, 0x00, // Logical Maximum(255),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x00, // Usage Minimum (0),
0x29, 0xFF, // Usage Maximum (255),
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
- 0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
+ 0x26, 0xb7, 0x00, // LOGICAL_MAXIMUM (0xb7)
0x19, 0x01, // USAGE_MINIMUM (0x1)
0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
0x75, 0x10, // REPORT_SIZE (16)
case USB_EVENT_SUSPEND:
//TODO: from ISR! print("[S]");
-#ifdef SLEEP_LED_ENABLE
- sleep_led_enable();
-#endif /* SLEEP_LED_ENABLE */
+ hook_usb_suspend_entry();
return;
case USB_EVENT_WAKEUP:
//TODO: from ISR! print("[W]");
suspend_wakeup_init();
-#ifdef SLEEP_LED_ENABLE
- sleep_led_disable();
- // NOTE: converters may not accept this
- led_set(host_keyboard_leds());
-#endif /* SLEEP_LED_ENABLE */
+ hook_usb_wakeup();
return;
case USB_EVENT_STALLED:
#endif /* NKRO_ENABLE */
/* arm the idle timer if boot protocol & idle */
osalSysLockFromISR();
- chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ chVTSetI(&keyboard_idle_timer, 4*TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
osalSysUnlockFromISR();
}
}
if(keyboard_idle) {
#endif /* NKRO_ENABLE */
osalSysLockFromISR();
- chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ chVTSetI(&keyboard_idle_timer, 4*TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
osalSysUnlockFromISR();
}
usbSetupTransfer(usbp, NULL, 0, NULL);
chVTObjectInit(&keyboard_idle_timer);
#ifdef CONSOLE_ENABLE
- obqObjectInit(&console_buf_queue, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
+ obqObjectInit(&console_buf_queue, true, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
chVTObjectInit(&console_flush_timer);
#endif
}
if(keyboard_idle) {
#endif /* NKRO_ENABLE */
/* TODO: are we sure we want the KBD_ENDPOINT? */
- usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent));
+ if(!usbGetTransmitStatusI(usbp, KBD_ENDPOINT)) {
+ usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, KBD_EPSIZE);
+ }
/* rearm the timer */
- chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ chVTSetI(&keyboard_idle_timer, 4*TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
}
/* do not rearm the timer if the condition above fails
* this is more efficient */
/* busy wait, should be short and not very common */
osalSysLock();
- while(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT))
- ;
+ if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT)) {
+ /* Need to either suspend, or loop and call unlock/lock during
+ * every iteration - otherwise the system will remain locked,
+ * no interrupts served, so USB not going through as well.
+ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
+ osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_ENDPOINT]->in_state->thread);
+ }
usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
osalSysUnlock();
} else
/* need to wait until the previous packet has made it through */
/* busy wait, should be short and not very common */
osalSysLock();
- while(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT))
- ;
+ if(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT)) {
+ /* Need to either suspend, or loop and call unlock/lock during
+ * every iteration - otherwise the system will remain locked,
+ * no interrupts served, so USB not going through as well.
+ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
+ osalThreadSuspendS(&(&USB_DRIVER)->epc[KBD_ENDPOINT]->in_state->thread);
+ }
usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
osalSysUnlock();
}
osalSysLockFromISR();
/* rearm the timer */
- chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ chVTSetI(&console_flush_timer, TIME_MS2I(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
/* Freeing the buffer just transmitted, if it was not a zero size packet.*/
if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) {
/* check that the states of things are as they're supposed to */
if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
/* rearm the timer */
- chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ chVTSetI(&console_flush_timer, TIME_MS2I(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
osalSysUnlockFromISR();
return;
}
started.*/
if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
/* rearm the timer */
- chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ chVTSetI(&console_flush_timer, TIME_MS2I(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
osalSysUnlockFromISR();
return;
}
}
/* rearm the timer */
- chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ chVTSetI(&console_flush_timer, TIME_MS2I(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
osalSysUnlockFromISR();
}
return 0;
}
osalSysUnlock();
- /* Timeout after 5us if the queue is full.
+ /* Timeout after 100us 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