diff --git a/Output/pjrcUSB/arm/usb_dev.c b/Output/pjrcUSB/arm/usb_dev.c index 27059b5..f46f10b 100644 --- a/Output/pjrcUSB/arm/usb_dev.c +++ b/Output/pjrcUSB/arm/usb_dev.c @@ -193,6 +193,15 @@ static void endpoint0_transmit( const void *data, uint32_t len ) ep0_tx_bdt_bank ^= 1; } +void usb_reinit() +{ + power_neg_delay = 0; + usb_configuration = 0; // Clear USB configuration if we have one + USB0_CONTROL = 0; // Disable D+ Pullup to simulate disconnect + delay(10); // Delay is necessary to simulate disconnect + usb_init(); +} + // Used to check any USB state changes that may not have a proper interrupt // Called once per scan loop, should take minimal processing time or it may affect other modules void usb_device_check() @@ -212,11 +221,7 @@ void usb_device_check() *usb_bMaxPower = 50; // Re-initialize USB - power_neg_delay = 0; - usb_configuration = 0; // Clear USB configuration if we have one - USB0_CONTROL = 0; // Disable D+ Pullup to simulate disconnect - delay(10); // Delay is necessary to simulate disconnect - usb_init(); + usb_reinit(); } } } @@ -545,7 +550,7 @@ static void usb_setup() break; } - return; + goto send; case 0x01A1: // HID GET_REPORT #ifdef UART_DEBUG @@ -574,12 +579,27 @@ static void usb_setup() #ifdef UART_DEBUG print("SET_IDLE - "); printHex( setup.wValue ); + print(" - "); + printHex( setup.wValue >> 8 ); print(NL); #endif USBKeys_Idle_Config = (setup.wValue >> 8); - USBKeys_Idle_Count = 0; + USBKeys_Idle_Expiry = 0; goto send; + case 0x02A1: // HID GET_IDLE + #ifdef UART_DEBUG + print("SET_IDLE - "); + printHex( setup.wValue ); + print(" - "); + printHex( USBKeys_Idle_Config ); + print(NL); + #endif + reply_buffer[0] = USBKeys_Idle_Config; + datalen = 1; + goto send; + + case 0x0B21: // HID SET_PROTOCOL #ifdef UART_DEBUG print("SET_PROTOCOL - "); @@ -979,6 +999,9 @@ void usb_rx_memory( usb_packet_t *packet ) void usb_tx( uint32_t endpoint, usb_packet_t *packet ) { + // Update expiry counter + USBKeys_Idle_Expiry = systick_millis_count; + // If we have been sleeping, try to wake up host if ( usb_dev_sleep ) { @@ -987,6 +1010,8 @@ void usb_tx( uint32_t endpoint, usb_packet_t *packet ) USB0_CTL |= USB_CTL_RESUME; delay(10); USB0_CTL &= ~(USB_CTL_RESUME); + delay(50); // Wait for at least 50 ms to make sure the bus is clear + usb_dev_sleep = 0; // Make sure we don't call this again, may crash system } // Since we are transmitting data, USB will be brought out of sleep/suspend diff --git a/Output/pjrcUSB/arm/usb_dev.h b/Output/pjrcUSB/arm/usb_dev.h index 827f843..4593396 100644 --- a/Output/pjrcUSB/arm/usb_dev.h +++ b/Output/pjrcUSB/arm/usb_dev.h @@ -1,7 +1,7 @@ /* Teensyduino Core Library * http://www.pjrc.com/teensy/ * Copyright (c) 2013 PJRC.COM, LLC. - * Modifications by Jacob Alexander 2014-2015 + * Modifications by Jacob Alexander 2014-2016 * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -61,6 +61,7 @@ extern volatile uint8_t usb_cdc_transmit_flush_timer; uint8_t usb_configured(); // is the USB port configured uint8_t usb_init(); // Returns 1 on success, 0 if no cable is attached +void usb_reinit(); // Force restart USB interface, simulates disconnect void usb_isr(); void usb_tx( uint32_t endpoint, usb_packet_t *packet ); diff --git a/Output/pjrcUSB/arm/usb_keyboard.c b/Output/pjrcUSB/arm/usb_keyboard.c index 040ef25..ec4aae6 100644 --- a/Output/pjrcUSB/arm/usb_keyboard.c +++ b/Output/pjrcUSB/arm/usb_keyboard.c @@ -126,13 +126,16 @@ void usb_keyboard_send() if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout ) { transmit_previous_timeout = 1; - warn_print("USB Transmit Timeout..."); + warn_print("USB Transmit Timeout...restarting device"); USBKeys_Changed = USBKeyChangeState_None; // Indicate packet lost + usb_device_software_reset(); return; } yield(); } + transmit_previous_timeout = 0; + // Pointer to USB tx packet buffer uint8_t *tx_buf = tx_packet->buf; diff --git a/Output/pjrcUSB/output_com.c b/Output/pjrcUSB/output_com.c index 6a9e64d..b156e1f 100644 --- a/Output/pjrcUSB/output_com.c +++ b/Output/pjrcUSB/output_com.c @@ -137,9 +137,11 @@ USBMouseChangeState USBMouse_Changed = 0; // the idle configuration, how often we send the report to the // host (ms * 4) even when it hasn't changed -uint8_t USBKeys_Idle_Config = 125; +// 0 - Disables +uint8_t USBKeys_Idle_Config = 0; -// count until idle timeout +// Count until idle timeout +uint32_t USBKeys_Idle_Expiry = 0; uint8_t USBKeys_Idle_Count = 0; // Indicates whether the Output module is fully functional @@ -646,6 +648,19 @@ inline void Output_send() for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) USBKeys_Keys[c] = 0; + // XXX - Behaves oddly on Mac OSX, might help with corrupted packets specific to OSX? -HaaTa + /* + // Check if idle count has been exceed, this forces usb_keyboard_send and usb_mouse_send to update + // TODO Add joystick as well (may be endpoint specific, currently not kept track of) + if ( usb_configuration && USBKeys_Idle_Config && ( + USBKeys_Idle_Expiry < systick_millis_count || + USBKeys_Idle_Expiry + USBKeys_Idle_Config * 4 >= systick_millis_count ) ) + { + USBKeys_Changed = USBKeyChangeState_All; + USBMouse_Changed = USBMouseChangeState_All; + } + */ + // Process mouse actions while ( USBMouse_Changed ) usb_mouse_send(); diff --git a/Output/pjrcUSB/output_com.h b/Output/pjrcUSB/output_com.h index 36369eb..7008943 100644 --- a/Output/pjrcUSB/output_com.h +++ b/Output/pjrcUSB/output_com.h @@ -62,6 +62,7 @@ typedef enum USBMouseChangeState { USBMouseChangeState_None = 0x00, USBMouseChangeState_Buttons = 0x01, USBMouseChangeState_Relative = 0x02, + USBMouseChangeState_All = 0x03, } USBMouseChangeState; @@ -84,9 +85,10 @@ extern volatile uint16_t USBMouse_Buttons; // Bitmask for mouse buttons extern volatile uint16_t USBMouse_Relative_x; extern volatile uint16_t USBMouse_Relative_y; -// Misc variables (XXX Some are only properly utilized using AVR) +// Keeps track of the idle timeout refresh (used on Mac OSX) extern uint8_t USBKeys_Idle_Config; -extern uint8_t USBKeys_Idle_Count; +extern uint32_t USBKeys_Idle_Expiry; +extern uint8_t USBKeys_Idle_Count; // AVR only extern USBKeyChangeState USBKeys_Changed; extern USBMouseChangeState USBMouse_Changed; diff --git a/Output/usbMuxUart/output_com.c b/Output/usbMuxUart/output_com.c index 1d41a9b..9de4212 100644 --- a/Output/usbMuxUart/output_com.c +++ b/Output/usbMuxUart/output_com.c @@ -37,6 +37,7 @@ #include #include #include +#include "arm/usb_mouse.h" #endif // KLL @@ -141,9 +142,11 @@ USBMouseChangeState USBMouse_Changed = 0; // the idle configuration, how often we send the report to the // host (ms * 4) even when it hasn't changed -uint8_t USBKeys_Idle_Config = 125; +// 0 - Disables +uint8_t USBKeys_Idle_Config = 0; -// count until idle timeout +// Count until idle timeout +uint32_t USBKeys_Idle_Expiry = 0; uint8_t USBKeys_Idle_Count = 0; // Indicates whether the Output module is fully functional @@ -653,6 +656,23 @@ inline void Output_send() for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) USBKeys_Keys[c] = 0; + // XXX - Behaves oddly on Mac OSX, might help with corrupted packets specific to OSX? -HaaTa + /* + // Check if idle count has been exceed, this forces usb_keyboard_send and usb_mouse_send to update + // TODO Add joystick as well (may be endpoint specific, currently not kept track of) + if ( usb_configuration && USBKeys_Idle_Config && ( + USBKeys_Idle_Expiry < systick_millis_count || + USBKeys_Idle_Expiry + USBKeys_Idle_Config * 4 >= systick_millis_count ) ) + { + USBKeys_Changed = USBKeyChangeState_All; + USBMouse_Changed = USBMouseChangeState_All; + } + */ + + // Process mouse actions + while ( USBMouse_Changed ) + usb_mouse_send(); + // Send keypresses while there are pending changes while ( USBKeys_Changed ) usb_keyboard_send();