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<