diff --git a/.gitmodules b/.gitmodules
index 3ae861fb..c688aa84 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
-[submodule "tmk_core/protocol/usb_hid/USB_Host_Shield_2.0-git"]
- path = tmk_core/protocol/usb_hid/USB_Host_Shield_2.0-git
- url = https://github.com/felis/USB_Host_Shield_2.0.git
+[submodule "tmk_core/protocol/usb_hid/USB_Host_Shield_2.0-tmk"]
+ path = tmk_core/protocol/usb_hid/USB_Host_Shield_2.0-tmk
+ url = https://github.com/tmk/USB_Host_Shield_2.0.git
diff --git a/converter/usb_usb/Makefile.debug b/converter/usb_usb/Makefile.debug
index e229cd78..830995b4 100644
--- a/converter/usb_usb/Makefile.debug
+++ b/converter/usb_usb/Makefile.debug
@@ -1,6 +1,20 @@
TARGET = usb_usb_debug
-UNIMAP_ENABLE = yes
+
+#UNIMAP_ENABLE = yes
#KEYMAP_SECTION_ENABLE = yes
-#LUFA_DEBUG = yes
-OPT_DEFS += -DDEBUG_USB_HOST
+
+# LUFA debug print
+# This may prevent USB enumeration and keyboard init
+LUFA_DEBUG = yes
+# Select one of outputs for debug print
+LUFA_DEBUG_UART = yes
+#LUFA_DEBUG_SUART = yes
+
+# USB_Host_Shield_2.0 debug print
+# This may prevent USB enumeration and keyboard init
+#OPT_DEFS += -DDEBUG_USB_HOST
+
+CONSOLE_ENABLE = yes
+MOUSEKEY_ENABLE = no
+EXTRAKEY_ENABLE = no
include Makefile
diff --git a/converter/usb_usb/config.h b/converter/usb_usb/config.h
index 87da4a45..7b80fc21 100644
--- a/converter/usb_usb/config.h
+++ b/converter/usb_usb/config.h
@@ -36,4 +36,17 @@ along with this program. If not, see .
/* key combination for command */
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
+
+// Disable power saving in USB suspend loop but remote wakeup is still valid.
+// This allows keep USB::Task() going during suspend without power down time delay.
+//#define NO_SUSPEND_POWER_DOWN
+
+
+// Disable USB startup wait, which can delays starting UHS2 Task() for 350-600ms.
+//#define NO_USB_STARTUP_WAIT_LOOP
+
+// Disable USB suspend loop, which blocks UHS2 Task() while power saving.
+// Note that this also disables power saving and remote wakeup from keyboard completely.
+//#define NO_USB_SUSPEND_LOOP
+
#endif
diff --git a/converter/usb_usb/usb_usb.cpp b/converter/usb_usb/usb_usb.cpp
index 086c90ae..50d2578e 100644
--- a/converter/usb_usb/usb_usb.cpp
+++ b/converter/usb_usb/usb_usb.cpp
@@ -35,6 +35,10 @@ along with this program. If not, see .
#include "host.h"
#include "keyboard.h"
+#include "hook.h"
+#include "suspend.h"
+#include "lufa.h"
+
/* KEY CODE to Matrix
*
@@ -71,8 +75,6 @@ static bool matrix_is_mod =false;
* This supports two cascaded hubs and four keyboards
*/
USB usb_host;
-USBHub hub1(&usb_host);
-USBHub hub2(&usb_host);
HIDBoot kbd1(&usb_host);
HIDBoot kbd2(&usb_host);
HIDBoot kbd3(&usb_host);
@@ -81,6 +83,8 @@ KBDReportParser kbd_parser1;
KBDReportParser kbd_parser2;
KBDReportParser kbd_parser3;
KBDReportParser kbd_parser4;
+USBHub hub1(&usb_host);
+USBHub hub2(&usb_host);
uint8_t matrix_rows(void) { return MATRIX_ROWS; }
@@ -233,3 +237,28 @@ void led_set(uint8_t usb_led)
if (kbd3.isReady()) kbd3.SetReport(0, 0, 2, 0, 1, &usb_led);
if (kbd4.isReady()) kbd4.SetReport(0, 0, 2, 0, 1, &usb_led);
}
+
+// We need to keep doing UHS2 USB::Task() to initialize keyboard
+// even before USB is not configured.
+void hook_usb_startup_wait_loop(void)
+{
+ matrix_scan();
+}
+
+// We need to keep doing UHS2 USB::Task() to initialize keyboard
+// even during USB bus is suspended and remote wakeup is not enabled yet on LUFA side.
+// This situation can happen just after pluging converter into USB port.
+void hook_usb_suspend_loop(void)
+{
+#ifndef LUFA_DEBUG_UART
+ // This corrupts debug print when suspend
+ suspend_power_down();
+#endif
+ if (USB_Device_RemoteWakeupEnabled) {
+ if (suspend_wakeup_condition()) {
+ USB_Device_SendRemoteWakeup();
+ }
+ } else {
+ matrix_scan();
+ }
+}
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
index 14951ec8..06507ecf 100644
--- a/tmk_core/common.mk
+++ b/tmk_core/common.mk
@@ -50,8 +50,12 @@ endif
ifeq (yes,$(strip $(CONSOLE_ENABLE)))
OPT_DEFS += -DCONSOLE_ENABLE
else
- OPT_DEFS += -DNO_PRINT
- OPT_DEFS += -DNO_DEBUG
+ # Remove print functions when console is disabled and
+ # no other print method like UART is available
+ ifneq (yes, $(strip $(DEBUG_PRINT_AVAILABLE)))
+ OPT_DEFS += -DNO_PRINT
+ OPT_DEFS += -DNO_DEBUG
+ endif
endif
ifeq (yes,$(strip $(COMMAND_ENABLE)))
diff --git a/tmk_core/common/uart.c b/tmk_core/common/avr/uart.c
similarity index 66%
rename from tmk_core/common/uart.c
rename to tmk_core/common/avr/uart.c
index c17649b0..0fec705f 100644
--- a/tmk_core/common/uart.c
+++ b/tmk_core/common/avr/uart.c
@@ -1,4 +1,3 @@
-// TODO: Teensy support(ATMega32u4/AT90USB128)
// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
/* UART Example for Teensy USB Development Board
* http://www.pjrc.com/teensy/
@@ -32,9 +31,42 @@
#include "uart.h"
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
+# define UDRn UDR0
+# define UBRRn UBRR0
+# define UCSRnA UCSR0A
+# define UCSRnB UCSR0B
+# define UCSRnC UCSR0C
+# define U2Xn U2X0
+# define RXENn RXEN0
+# define TXENn TXEN0
+# define RXCIEn RXCIE0
+# define UCSZn1 UCSZ01
+# define UCSZn0 UCSZ00
+# define UDRIEn UDRIE0
+# define UDRE_vect USART_UDRE_vect
+# define RX_vect USART_RX_vect
+#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega32U2__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
+# define UDRn UDR1
+# define UBRRn UBRR1
+# define UCSRnA UCSR1A
+# define UCSRnB UCSR1B
+# define UCSRnC UCSR1C
+# define U2Xn U2X1
+# define RXENn RXEN1
+# define TXENn TXEN1
+# define RXCIEn RXCIE1
+# define UCSZn1 UCSZ11
+# define UCSZn0 UCSZ10
+# define UDRIEn UDRIE1
+# define UDRE_vect USART1_UDRE_vect
+# define RX_vect USART1_RX_vect
+#endif
+
+
// These buffers may be any size from 2 to 256 bytes.
#define RX_BUFFER_SIZE 64
-#define TX_BUFFER_SIZE 40
+#define TX_BUFFER_SIZE 256
static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
static volatile uint8_t tx_buffer_head;
@@ -47,10 +79,10 @@ static volatile uint8_t rx_buffer_tail;
void uart_init(uint32_t baud)
{
cli();
- UBRR0 = (F_CPU / 4 / baud - 1) / 2;
- UCSR0A = (1<= TX_BUFFER_SIZE) i = 0;
+ // return immediately to avoid deadlock when interrupt is disabled(called from ISR)
+ if (tx_buffer_tail == i && (SREG & (1<= TX_BUFFER_SIZE) i = 0;
- UDR0 = tx_buffer[i];
+ UDRn = tx_buffer[i];
tx_buffer_tail = i;
}
}
// Receive Interrupt
-ISR(USART_RX_vect)
+ISR(RX_vect)
{
uint8_t c, i;
- c = UDR0;
+ c = UDRn;
i = rx_buffer_head + 1;
if (i >= RX_BUFFER_SIZE) i = 0;
if (i != rx_buffer_tail) {
diff --git a/tmk_core/common/hook.h b/tmk_core/common/hook.h
index 56fe5677..140e2779 100644
--- a/tmk_core/common/hook.h
+++ b/tmk_core/common/hook.h
@@ -21,6 +21,10 @@ along with this program. If not, see .
#include "keyboard.h"
#include "led.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* -------------------------------------
* Protocol hooks
* ------------------------------------- */
@@ -47,6 +51,10 @@ void hook_usb_suspend_loop(void);
* the "normal" indicator LED status by default. */
void hook_usb_wakeup(void);
+/* Called repeatedly until getting to CONFIGURED state */
+/* Default behaviour: do nothing. */
+void hook_usb_startup_wait_loop(void);
+
/* -------------------------------------
* Keyboard hooks
@@ -76,5 +84,8 @@ void hook_keyboard_leds_change(uint8_t led_status);
/* Default behaviour: do nothing. */
void hook_bootmagic(void);
+#ifdef __cplusplus
+}
+#endif
#endif /* _HOOKS_H_ */
diff --git a/tmk_core/common/suspend.h b/tmk_core/common/suspend.h
index 80617a82..f0a668cf 100644
--- a/tmk_core/common/suspend.h
+++ b/tmk_core/common/suspend.h
@@ -5,9 +5,17 @@
#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void suspend_idle(uint8_t timeout);
void suspend_power_down(void);
bool suspend_wakeup_condition(void);
void suspend_wakeup_init(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/tmk_core/doc/hook.txt b/tmk_core/doc/hook.txt
index 1689034e..acd77cce 100644
--- a/tmk_core/doc/hook.txt
+++ b/tmk_core/doc/hook.txt
@@ -9,6 +9,8 @@ Hook function | Timing
`hook_early_init(void)` | Early in the boot process, before the matrix is initialized and before a connection is made with the host. Thus, this hook has access to very few parameters, but it is a good place to define any custom parameters needed by other early processes.
`hook_late_init(void)` | Near the end of the boot process, after Boot Magic has run and LEDs have been initialized.
`hook_bootmagic(void)` | During the Boot Magic window, after EEPROM and Bootloader checks are made, but before any other built-in Boot Magic checks are made.
+`hook_usb_startup_wait_loop(void)` | Continuously, until the device gets ready and into USB configured state.
+
`hook_usb_wakeup(void)` | When the device wakes up from USB suspend state.
`hook_usb_suspend_entry(void)` | When the device enters USB suspend state.
`hook_usb_suspend_loop(void)` | Continuously, while the device is in USB suspend state. *Default action:* power down and periodically check the matrix, causing wakeup if needed.
diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk
index 1b529bde..19fc80d4 100644
--- a/tmk_core/protocol/lufa.mk
+++ b/tmk_core/protocol/lufa.mk
@@ -49,7 +49,20 @@ OPT_DEFS += $(LUFA_OPTS)
# This indicates using LUFA stack
OPT_DEFS += -DPROTOCOL_LUFA
+ifeq (yes,$(strip $(LUFA_DEBUG)))
+ LUFA_OPTS += -DLUFA_DEBUG
+endif
+
ifeq (yes,$(strip $(LUFA_DEBUG_SUART)))
SRC += common/avr/suart.S
LUFA_OPTS += -DLUFA_DEBUG_SUART
+ # Keep print/debug lines when disabling HID console. See common.mk.
+ DEBUG_PRINT_AVAILABLE = yes
+endif
+
+ifeq (yes,$(strip $(LUFA_DEBUG_UART)))
+ SRC += common/avr/uart.c
+ LUFA_OPTS += -DLUFA_DEBUG_UART
+ # Keep print/debug lines when disabling HID console. See common.mk.
+ DEBUG_PRINT_AVAILABLE = yes
endif
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index b5d0b50e..9dadd572 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -56,6 +56,10 @@
#include "avr/suart.h"
#endif
+#ifdef LUFA_DEBUG_UART
+#include "uart.h"
+#endif
+
#include "matrix.h"
#include "descriptor.h"
#include "lufa.h"
@@ -218,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();
@@ -229,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.
@@ -575,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
/*******************************************************************************
@@ -629,11 +634,15 @@ int main(void)
SUART_OUT_PORT |= (1<