Adding auto-restart support whenever USB gets into an odd state
- Somewhat aggresive, may cause restarts if the keyboard/OS hasn't fully intialized the keyboard - Added GET_IDLE handling and correct usage of SET_IDLE - Initial implementation of idle send, commented out as it causes issues on Mac OSX for sleeping (keyboard has been working without it) - MacOSX seems to have some sort of data corruption on the USB link, not sure why (other OSs have no issues) - Cleaned up some code - Added a longer sleep after the resume sequence to prevent possible issues sending keys too soon (may need to be increased more) Ipad support now seems flaky, though Mac, Windows seems solid. Init sequence on Linux seems slow, even though there are no errors.
This commit is contained in:
parent
9a7364b14a
commit
92b3b5081b
@ -193,6 +193,15 @@ static void endpoint0_transmit( const void *data, uint32_t len )
|
|||||||
ep0_tx_bdt_bank ^= 1;
|
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
|
// 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
|
// Called once per scan loop, should take minimal processing time or it may affect other modules
|
||||||
void usb_device_check()
|
void usb_device_check()
|
||||||
@ -212,11 +221,7 @@ void usb_device_check()
|
|||||||
*usb_bMaxPower = 50;
|
*usb_bMaxPower = 50;
|
||||||
|
|
||||||
// Re-initialize USB
|
// Re-initialize USB
|
||||||
power_neg_delay = 0;
|
usb_reinit();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +550,7 @@ static void usb_setup()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
goto send;
|
||||||
|
|
||||||
case 0x01A1: // HID GET_REPORT
|
case 0x01A1: // HID GET_REPORT
|
||||||
#ifdef UART_DEBUG
|
#ifdef UART_DEBUG
|
||||||
@ -574,12 +579,27 @@ static void usb_setup()
|
|||||||
#ifdef UART_DEBUG
|
#ifdef UART_DEBUG
|
||||||
print("SET_IDLE - ");
|
print("SET_IDLE - ");
|
||||||
printHex( setup.wValue );
|
printHex( setup.wValue );
|
||||||
|
print(" - ");
|
||||||
|
printHex( setup.wValue >> 8 );
|
||||||
print(NL);
|
print(NL);
|
||||||
#endif
|
#endif
|
||||||
USBKeys_Idle_Config = (setup.wValue >> 8);
|
USBKeys_Idle_Config = (setup.wValue >> 8);
|
||||||
USBKeys_Idle_Count = 0;
|
USBKeys_Idle_Expiry = 0;
|
||||||
goto send;
|
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
|
case 0x0B21: // HID SET_PROTOCOL
|
||||||
#ifdef UART_DEBUG
|
#ifdef UART_DEBUG
|
||||||
print("SET_PROTOCOL - ");
|
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 )
|
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 we have been sleeping, try to wake up host
|
||||||
if ( usb_dev_sleep )
|
if ( usb_dev_sleep )
|
||||||
{
|
{
|
||||||
@ -987,6 +1010,8 @@ void usb_tx( uint32_t endpoint, usb_packet_t *packet )
|
|||||||
USB0_CTL |= USB_CTL_RESUME;
|
USB0_CTL |= USB_CTL_RESUME;
|
||||||
delay(10);
|
delay(10);
|
||||||
USB0_CTL &= ~(USB_CTL_RESUME);
|
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
|
// Since we are transmitting data, USB will be brought out of sleep/suspend
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* Teensyduino Core Library
|
/* Teensyduino Core Library
|
||||||
* http://www.pjrc.com/teensy/
|
* http://www.pjrc.com/teensy/
|
||||||
* Copyright (c) 2013 PJRC.COM, LLC.
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* 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_configured(); // is the USB port configured
|
||||||
uint8_t usb_init(); // Returns 1 on success, 0 if no cable is attached
|
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_isr();
|
||||||
void usb_tx( uint32_t endpoint, usb_packet_t *packet );
|
void usb_tx( uint32_t endpoint, usb_packet_t *packet );
|
||||||
|
@ -126,13 +126,16 @@ void usb_keyboard_send()
|
|||||||
if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout )
|
if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout )
|
||||||
{
|
{
|
||||||
transmit_previous_timeout = 1;
|
transmit_previous_timeout = 1;
|
||||||
warn_print("USB Transmit Timeout...");
|
warn_print("USB Transmit Timeout...restarting device");
|
||||||
USBKeys_Changed = USBKeyChangeState_None; // Indicate packet lost
|
USBKeys_Changed = USBKeyChangeState_None; // Indicate packet lost
|
||||||
|
usb_device_software_reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transmit_previous_timeout = 0;
|
||||||
|
|
||||||
// Pointer to USB tx packet buffer
|
// Pointer to USB tx packet buffer
|
||||||
uint8_t *tx_buf = tx_packet->buf;
|
uint8_t *tx_buf = tx_packet->buf;
|
||||||
|
|
||||||
|
@ -137,9 +137,11 @@ USBMouseChangeState USBMouse_Changed = 0;
|
|||||||
|
|
||||||
// the idle configuration, how often we send the report to the
|
// the idle configuration, how often we send the report to the
|
||||||
// host (ms * 4) even when it hasn't changed
|
// 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;
|
uint8_t USBKeys_Idle_Count = 0;
|
||||||
|
|
||||||
// Indicates whether the Output module is fully functional
|
// 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++ )
|
for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ )
|
||||||
USBKeys_Keys[c] = 0;
|
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
|
// Process mouse actions
|
||||||
while ( USBMouse_Changed )
|
while ( USBMouse_Changed )
|
||||||
usb_mouse_send();
|
usb_mouse_send();
|
||||||
|
@ -62,6 +62,7 @@ typedef enum USBMouseChangeState {
|
|||||||
USBMouseChangeState_None = 0x00,
|
USBMouseChangeState_None = 0x00,
|
||||||
USBMouseChangeState_Buttons = 0x01,
|
USBMouseChangeState_Buttons = 0x01,
|
||||||
USBMouseChangeState_Relative = 0x02,
|
USBMouseChangeState_Relative = 0x02,
|
||||||
|
USBMouseChangeState_All = 0x03,
|
||||||
} USBMouseChangeState;
|
} 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_x;
|
||||||
extern volatile uint16_t USBMouse_Relative_y;
|
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_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 USBKeyChangeState USBKeys_Changed;
|
||||||
extern USBMouseChangeState USBMouse_Changed;
|
extern USBMouseChangeState USBMouse_Changed;
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <arm/usb_dev.h>
|
#include <arm/usb_dev.h>
|
||||||
#include <arm/usb_keyboard.h>
|
#include <arm/usb_keyboard.h>
|
||||||
#include <arm/usb_serial.h>
|
#include <arm/usb_serial.h>
|
||||||
|
#include "arm/usb_mouse.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// KLL
|
// KLL
|
||||||
@ -141,9 +142,11 @@ USBMouseChangeState USBMouse_Changed = 0;
|
|||||||
|
|
||||||
// the idle configuration, how often we send the report to the
|
// the idle configuration, how often we send the report to the
|
||||||
// host (ms * 4) even when it hasn't changed
|
// 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;
|
uint8_t USBKeys_Idle_Count = 0;
|
||||||
|
|
||||||
// Indicates whether the Output module is fully functional
|
// 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++ )
|
for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ )
|
||||||
USBKeys_Keys[c] = 0;
|
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
|
// Send keypresses while there are pending changes
|
||||||
while ( USBKeys_Changed )
|
while ( USBKeys_Changed )
|
||||||
usb_keyboard_send();
|
usb_keyboard_send();
|
||||||
|
Reference in New Issue
Block a user