Archived
1
0

Major USB update, fixes most (if not all) known issues

USB - General
- Refactored descriptors
- Enabled/Disable USB endpoints
- Added debug flags for special features
- Code cleanup
- Interface count calculation based off of enabled endpoints
- Delayed wTotalLength calculation to simplify descriptor offsets
- Re-ordered endpoints and interfaces
- Added more debug output
- Added usbInitTime to show how long keyboard initialization took
  (Useful when debugging bad init sequences)
- Added function for usb_resume() which takes care of the resume sequence
  * Resume is now only called if packets are starting to timeout

USB - Special Options
- Added enableDeviceRestartOnUSBTimeout
  * A last resort hammer for bad USB Chipsets/OSs, don't use if you can help it
  * Disabled
- Added enableUSBResume
  * Enables host resume wake-up signalling, required to wake a computer from sleep
  * Enabled
- Added enableUSBLowPowerNegotiation
  * Enables power negotiation hack
  * Required to use firmware with an IPad and other hard-limit low-power USB hosts
  * Hasn't been tested with the recent changes
  * Disabled
- Added enableUSBSuspend
  * Enables power down events on host USB bus suspend
  * Enabled

USB - Keyboard
- Attempted to cleanup HID SET_REPORT
  * Works much better
  * Still has an issue under Linux which generates *a lot* of NAKs (initializes quickly regardless)
    + Not present on other keyboards
    + SETUP -> OUT -> IN : This sequence is the problem
    + Specifically during the OUT phase
- Enabled

USB - CDC Virtual Serial Port
- Code cleanup
- Added convenience struct USBCDCLineCoding for easier debugging
- Attempted to cleanup CDC_SET_LING_CODING
  * Works much better
  * Still has an issue under Linux which generates *a lot* of NAKs (initializes quickly regardless)
    + SETUP -> OUT -> IN : This sequence is the problem
    + Specifically during the OUT phase
    + Likely the same issues as HID SET_REPORT
- Enabled

USB - Mouse
- Enabled

USB - Joystick
- Disabled

USB - RawIO
- Initial code, API not used yet
- Disabled

DFU
- Updated load script, now faster
This commit is contained in:
Jacob Alexander 2016-05-31 00:19:45 -07:00
parent 8a96e70b4b
commit 358d480ea9
18 changed files with 1097 additions and 259 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2011-2014 by Jacob Alexander
/* Copyright (C) 2011-2016 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -127,7 +127,7 @@ void printHex32_op( uint32_t in, uint8_t op )
// With an op of 1, the max number of characters is 6 + 1 for null
// e.g. "0xFFFF\0"
// op 2 and 4 require fewer characters (2+1 and 4+1 respectively)
char tmpStr[7];
char tmpStr[11];
// Convert number
hex32ToStr_op( in, tmpStr, op );
@ -259,6 +259,7 @@ void hex32ToStr_op( uint32_t in, char* out, uint8_t op )
break;
case 2: // 8-bit padding
case 4: // 16-bit padding
case 8: // 32-bit padding
while ( pos < op )
out[pos++] = '0';
break;

View File

@ -2,8 +2,9 @@
# Convenience script for loading firmware onto a dfu type device
# By default, initiates dfu-util
SERIAL_PORT=""
AUTO_SCREEN_SESSION=""
SERIAL_PORT="/dev/kiibohd"
AUTO_SCREEN_SESSION="/dev/kiibohd"
NOSCREEN=0
PROG_NAME=$(basename $0)
# Parse all the command line arguments
@ -19,6 +20,10 @@ while (( "$#" >= "1" )); do
SERIAL_PORT="$2"
shift
;;
-n|--noscreen)
NOSCREEN=1
shift
;;
-h|--help)
echo "Usage: $PROG_NAME [options...]"
echo ""
@ -49,12 +54,19 @@ done
if [[ "$SERIAL_PORT" != "" ]] && [[ -e "$SERIAL_PORT" ]]; then
echo "NOTE: This may fail if the uC is in a bad state or does not support remote flashing"
printf "reload\r" > $SERIAL_PORT
sleep 2
fi
# Load via dfu-util
# Used for McHCK based uCs
if type dfu-util &>/dev/null; then
# Wait for device to appear
while true; do
dfu-util -l | grep -q "Kiibohd DFU"
if [ $? -eq 0 ]; then
break
fi
sleep 0.1
done
dfu-util -D @TARGET_BIN@
EXIT_STATUS=$?
else
@ -63,9 +75,12 @@ else
fi
# Load Screen Session if specified
if (( "$EXIT_STATUS" == "0" )) && [[ "$AUTO_SCREEN_SESSION" != "" ]]; then
if (( "$EXIT_STATUS" == "0" )) && [[ "$AUTO_SCREEN_SESSION" != "" ]] && [[ $NOSCREEN -ne 1 ]]; then
if type screen &>/dev/null; then
sleep 0.1
# Wait for interface
while [ ! -e $AUTO_SCREEN_SESSION ]; do
sleep 0.1
done
screen $AUTO_SCREEN_SESSION
else
echo "screen is not installed"

View File

@ -103,6 +103,7 @@ static uint8_t usb_debug_descriptor[] = {
// the meaning and format of the data.
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
#if enableKeyboard_define == 1
static uint8_t keyboard_report_desc[] = {
// Keyboard Collection
0x05, 0x01, // Usage Page (Generic Desktop),
@ -304,8 +305,11 @@ static uint8_t sys_ctrl_report_desc[] = {
0x81, 0x00, // Input (Data, Array),
0xc0, // End Collection - Consumer Control
};
#endif
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
#if enableMouse_define == 1
static uint8_t mouse_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
@ -383,73 +387,117 @@ static uint8_t mouse_report_desc[] = {
0xc0, // End Collection - Mouse Logical
0xc0 // End Collection - Mouse Application
};
#endif
// Joystick Protocol, HID 1.11 spec, Apendix D, page 64-65
#if enableJoystick_define == 1
static uint8_t joystick_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x04, // Usage (Joystick)
0xA1, 0x01, // Collection (Application)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x20, // Report Count (32)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button #1)
0x29, 0x20, // Usage Maximum (Button #32)
0x81, 0x02, // Input (variable,absolute)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x07, // Logical Maximum (7)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x3B, 0x01, // Physical Maximum (315)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x65, 0x14, // Unit (20)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x39, // Usage (Hat switch)
0x81, 0x42, // Input (variable,absolute,null_state)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection ()
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x03, // Logical Maximum (1023)
0x75, 0x0A, // Report Size (10)
0x95, 0x04, // Report Count (4)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x09, 0x35, // Usage (Rz)
0x81, 0x02, // Input (variable,absolute)
0xC0, // End Collection
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x03, // Logical Maximum (1023)
0x75, 0x0A, // Report Size (10)
0x95, 0x02, // Report Count (2)
0x09, 0x36, // Usage (Slider)
0x09, 0x36, // Usage (Slider)
0x81, 0x02, // Input (variable,absolute)
0xC0 // End Collection
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x04, // Usage (Joystick)
0xA1, 0x01, // Collection (Application)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x20, // Report Count (32)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button #1)
0x29, 0x20, // Usage Maximum (Button #32)
0x81, 0x02, // Input (variable,absolute)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x07, // Logical Maximum (7)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x3B, 0x01, // Physical Maximum (315)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x65, 0x14, // Unit (20)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x39, // Usage (Hat switch)
0x81, 0x42, // Input (variable,absolute,null_state)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection ()
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x03, // Logical Maximum (1023)
0x75, 0x0A, // Report Size (10)
0x95, 0x04, // Report Count (4)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x09, 0x35, // Usage (Rz)
0x81, 0x02, // Input (variable,absolute)
0xC0, // End Collection
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x03, // Logical Maximum (1023)
0x75, 0x0A, // Report Size (10)
0x95, 0x02, // Report Count (2)
0x09, 0x36, // Usage (Slider)
0x09, 0x36, // Usage (Slider)
0x81, 0x02, // Input (variable,absolute)
0xC0 // End Collection
};
#endif
// ----- USB Configuration -----
// Check for non-selected USB descriptors to update the total interface count
// XXX This must be correct or some OSs/Init sequences will not initialize the keyboard/device
#if enableKeyboard_define != 1
#undef KEYBOARD_INTERFACES
#define KEYBOARD_INTERFACES 0
#endif
#if enableMouse_define != 1
#undef MOUSE_INTERFACES
#define MOUSE_INTERFACES 0
#endif
#if enableJoystick_define != 1
#undef JOYSTICK_INTERFACES
#define JOYSTICK_INTERFACES 0
#endif
#if enableVirtualSerialPort_define != 1
#undef CDC_INTERFACES
#define CDC_INTERFACES 0
#endif
#if enableRawIO_define != 1
#undef RAWIO_INTERFACES
#define RAWIO_INTERFACES 0
#endif
// Determine number of interfaces
#define NUM_INTERFACE (KEYBOARD_INTERFACES + CDC_INTERFACES + MOUSE_INTERFACES + JOYSTICK_INTERFACES + RAWIO_INTERFACES)
// USB Configuration Descriptor. This huge descriptor tells all
// of the devices capbilities.
static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
static uint8_t config_descriptor[] = {
// --- Configuration ---
// - 9 bytes -
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
9, // bLength;
2, // bDescriptorType;
LSB(CONFIG_DESC_SIZE), // wTotalLength
MSB(CONFIG_DESC_SIZE),
0xFF, // wTotalLength - XXX Set in usb_init (simplifies defines)
0xFF,
NUM_INTERFACE, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0xA0, // bmAttributes
250, // bMaxPower - Entry Index 8
//
// --- Keyboard Endpoint Descriptors ---
//
#if enableKeyboard_define == 1
#define KEYBOARD_DESC_TOTAL_OFFSET (KEYBOARD_DESC_SIZE + NKRO_KEYBOARD_DESC_SIZE + SYS_CTRL_DESC_SIZE)
#define NKRO_KEYBOARD_DESC_BASE_OFFSET (KEYBOARD_DESC_BASE_OFFSET + KEYBOARD_DESC_SIZE)
#define SYS_CTRL_DESC_BASE_OFFSET (KEYBOARD_DESC_BASE_OFFSET + KEYBOARD_DESC_SIZE + NKRO_KEYBOARD_DESC_SIZE)
// --- Keyboard HID --- Boot Mode Keyboard Interface
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
@ -512,6 +560,47 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
NKRO_KEYBOARD_SIZE, 0, // wMaxPacketSize
NKRO_KEYBOARD_INTERVAL, // bInterval
// --- System/Consumer Control ---
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
SYS_CTRL_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot)
0x00, // bInterfaceProtocol (0x00 = None)
SYS_CTRL_INTERFACE + 4, // iInterface
// - 9 bytes -
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
KeyboardLocale_define, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
LSB(sizeof(sys_ctrl_report_desc)), // wDescriptorLength
MSB(sizeof(sys_ctrl_report_desc)),
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
SYS_CTRL_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
SYS_CTRL_SIZE, 0, // wMaxPacketSize
SYS_CTRL_INTERVAL, // bInterval
#else
#define KEYBOARD_DESC_TOTAL_OFFSET (0)
#endif
//
// --- CDC / Serial Port Endpoint Descriptors ---
//
#if enableVirtualSerialPort_define == 1
#define SERIAL_CDC_DESC_TOTAL_OFFSET (SERIAL_CDC_DESC_SIZE)
// --- Serial CDC --- CDC IAD Descriptor
// - 8 bytes -
// interface association descriptor, USB ECN, Table 9-Z
@ -522,7 +611,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x02, // bFunctionClass
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
CDC_STATUS_INTERFACE + 4, // iFunction
0, // iFunction (XXX No interface index, don't give string -HaaTa)
// --- Serial CDC --- CDC Data Interface
// - 9 bytes -
@ -597,6 +686,57 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x02, // bmAttributes (0x02=bulk)
CDC_TX_SIZE, 0, // wMaxPacketSize
0, // bInterval
#else
#define SERIAL_CDC_DESC_TOTAL_OFFSET (0)
#endif
//
// --- Raw IO Endpoint Descriptors ---
//
#if enableRawIO_define == 1
#define RAWIO_DESC_TOTAL_OFFSET (RAWIO_DESC_SIZE)
// --- Vendor Specific / RAW I/O ---
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
RAWIO_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
2, // bNumEndpoints
0xFF, // bInterfaceClass (0xFF)
0xFF, // bInterfaceSubClass
0xFF, // bInterfaceProtocol
RAWIO_INTERFACE + 4, // iInterface
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
RAWIO_TX_ENDPOINT | 0x80, // bEndpointAddress
0x02, // bmAttributes (0x02=bulk)
RAWIO_TX_SIZE, 0, // wMaxPacketSize
RAWIO_TX_INTERVAL, // bInterval
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
RAWIO_RX_ENDPOINT, // bEndpointAddress
0x02, // bmAttributes (0x02=bulk)
RAWIO_RX_SIZE, 0, // wMaxPacketSize
RAWIO_RX_INTERVAL, // bInterval
#else
#define RAWIO_DESC_TOTAL_OFFSET (0)
#endif
//
// --- Mouse Endpoint Descriptors ---
//
#if enableMouse_define == 1
#define MOUSE_DESC_TOTAL_OFFSET (MOUSE_DESC_SIZE)
// --- Mouse Interface ---
// - 9 bytes -
@ -628,6 +768,16 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x03, // bmAttributes (0x03=intr)
MOUSE_SIZE, 0, // wMaxPacketSize
MOUSE_INTERVAL, // bInterval
#else
#define MOUSE_DESC_TOTAL_OFFSET (0)
#endif
//
// --- Joystick Endpoint Descriptors ---
//
#if enableJoystick_define == 1
#define JOYSTICK_DESC_TOTAL_OFFSET (JOYSTICK_DESC_SIZE)
// --- Joystick Interface ---
// - 9 bytes -
@ -659,37 +809,10 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x03, // bmAttributes (0x03=intr)
JOYSTICK_SIZE, 0, // wMaxPacketSize
JOYSTICK_INTERVAL, // bInterval
#else
#define JOYSTICK_DESC_TOTAL_OFFSET (0)
#endif
// --- System/Consumer Control ---
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
SYS_CTRL_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot)
0x00, // bInterfaceProtocol (0x00 = None)
SYS_CTRL_INTERFACE + 4, // iInterface
// - 9 bytes -
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
KeyboardLocale_define, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
LSB(sizeof(sys_ctrl_report_desc)), // wDescriptorLength
MSB(sizeof(sys_ctrl_report_desc)),
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
SYS_CTRL_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
SYS_CTRL_SIZE, 0, // wMaxPacketSize
SYS_CTRL_INTERVAL, // bInterval
};
uint8_t *usb_bMaxPower = &config_descriptor[8];
@ -731,18 +854,37 @@ struct usb_string_descriptor_struct string0 = {
usb_string_descriptor( usb_string_manufacturer_name_default, STR_MANUFACTURER );
usb_string_descriptor( usb_string_product_name_default, STR_PRODUCT );
usb_string_descriptor( usb_string_serial_number_default, STR_SERIAL );
#if enableKeyboard_define == 1
usb_string_descriptor( usb_string_keyboard_name, KEYBOARD_NAME );
usb_string_descriptor( usb_string_nkro_keyboard_name, NKRO_KEYBOARD_NAME );
usb_string_descriptor( usb_string_sys_ctrl_name, SYS_CTRL_NAME );
#endif
#if enableVirtualSerialPort_define == 1
usb_string_descriptor( usb_string_cdc_status_name, CDC_STATUS_NAME );
usb_string_descriptor( usb_string_cdc_data_name, CDC_DATA_NAME );
#endif
#if enableRawIO_define == 1
usb_string_descriptor( usb_string_rawio_name, RAWIO_NAME );
#endif
#if enableMouse_define == 1
usb_string_descriptor( usb_string_mouse_name, MOUSE_NAME );
#endif
#if enableJoystick_define == 1
usb_string_descriptor( usb_string_joystick_name, JOYSTICK_NAME );
usb_string_descriptor( usb_string_sys_ctrl_name, SYS_CTRL_NAME );
#endif
// ----- Descriptors List -----
#define iInterfaceString(num, var) \
{0x0300 + 4 + num, 0x0409, (const uint8_t *)&var, 0 }
// This table provides access to all the descriptor data above.
const usb_descriptor_list_t usb_descriptor_list[] = {
@ -752,38 +894,57 @@ const usb_descriptor_list_t usb_descriptor_list[] = {
{0x0600, 0x0000, device_qualifier_descriptor, sizeof(device_qualifier_descriptor)},
{0x0A00, 0x0000, usb_debug_descriptor, sizeof(usb_debug_descriptor)},
{0x2200, KEYBOARD_INTERFACE, keyboard_report_desc, sizeof(keyboard_report_desc)},
{0x2100, KEYBOARD_INTERFACE, config_descriptor + KEYBOARD_DESC_OFFSET, 9},
{0x2200, NKRO_KEYBOARD_INTERFACE, nkro_keyboard_report_desc, sizeof(nkro_keyboard_report_desc)},
{0x2100, NKRO_KEYBOARD_INTERFACE, config_descriptor + NKRO_KEYBOARD_DESC_OFFSET, 9},
{0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)},
{0x2100, MOUSE_INTERFACE, config_descriptor + MOUSE_DESC_OFFSET, 9},
{0x2200, JOYSTICK_INTERFACE, joystick_report_desc, sizeof(joystick_report_desc)},
{0x2100, JOYSTICK_INTERFACE, config_descriptor + JOYSTICK_DESC_OFFSET, 9},
{0x2200, SYS_CTRL_INTERFACE, sys_ctrl_report_desc, sizeof(sys_ctrl_report_desc)},
{0x2100, SYS_CTRL_INTERFACE, config_descriptor + SYS_CTRL_DESC_OFFSET, 9},
#define iInterfaceString(num, var) \
{0x0300 + 4 + num, 0x409, (const uint8_t *)&var, 0 }
{0x0300, 0x0000, (const uint8_t *)&string0, 0},
{0x0301, 0x0409, (const uint8_t *)&usb_string_manufacturer_name, 0},
{0x0302, 0x0409, (const uint8_t *)&usb_string_product_name, 0},
{0x0303, 0x0409, (const uint8_t *)&usb_string_serial_number, 0},
#if enableKeyboard_define == 1
{0x2200, KEYBOARD_INTERFACE, keyboard_report_desc, sizeof(keyboard_report_desc)},
{0x2100, KEYBOARD_INTERFACE, config_descriptor + KEYBOARD_DESC_BASE_OFFSET, 9},
{0x2200, NKRO_KEYBOARD_INTERFACE, nkro_keyboard_report_desc, sizeof(nkro_keyboard_report_desc)},
{0x2100, NKRO_KEYBOARD_INTERFACE, config_descriptor + NKRO_KEYBOARD_DESC_BASE_OFFSET, 9},
{0x2200, SYS_CTRL_INTERFACE, sys_ctrl_report_desc, sizeof(sys_ctrl_report_desc)},
{0x2100, SYS_CTRL_INTERFACE, config_descriptor + SYS_CTRL_DESC_BASE_OFFSET, 9},
iInterfaceString( KEYBOARD_INTERFACE, usb_string_keyboard_name ),
iInterfaceString( NKRO_KEYBOARD_INTERFACE, usb_string_nkro_keyboard_name ),
iInterfaceString( SYS_CTRL_INTERFACE, usb_string_sys_ctrl_name ),
#endif
#if enableVirtualSerialPort_define == 1
iInterfaceString( CDC_STATUS_INTERFACE, usb_string_cdc_status_name ),
iInterfaceString( CDC_DATA_INTERFACE, usb_string_cdc_data_name ),
#endif
#if enableRawIO_define == 1
iInterfaceString( RAWIO_INTERFACE, usb_string_rawio_name ),
#endif
#if enableMouse_define == 1
{0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)},
{0x2100, MOUSE_INTERFACE, config_descriptor + MOUSE_DESC_BASE_OFFSET, 9},
iInterfaceString( MOUSE_INTERFACE, usb_string_mouse_name ),
#endif
#if enableJoystick_define == 1
{0x2200, JOYSTICK_INTERFACE, joystick_report_desc, sizeof(joystick_report_desc)},
{0x2100, JOYSTICK_INTERFACE, config_descriptor + JOYSTICK_DESC_BASE_OFFSET, 9},
iInterfaceString( JOYSTICK_INTERFACE, usb_string_joystick_name ),
iInterfaceString( SYS_CTRL_INTERFACE, usb_string_sys_ctrl_name ),
#endif
{0, 0, NULL, 0}
};
// Simplifies defines for USB descriptors
void usb_set_config_descriptor_size()
{
config_descriptor[2] = LSB( sizeof( config_descriptor ) );
config_descriptor[3] = MSB( sizeof( config_descriptor ) );
}
// ----- Endpoint Configuration -----

View File

@ -54,9 +54,18 @@
#define DEVICE_SUBCLASS 0x00
#define DEVICE_PROTOCOL 0x00
#define EP0_SIZE 64
#define NUM_ENDPOINTS 8
#define NUM_ENDPOINTS 10 // XXX Can save some space if this can be calculated using KLL
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 7
// XXX Remember to update total interface count, if it isn't correct some OSs will not initialize USB
// Linux warns in dmesg
// Mac OSX login screen will not initialize
#define KEYBOARD_INTERFACES 3 // Boot, NKRO, SysCtrl
#define CDC_INTERFACES 2
#define MOUSE_INTERFACES 1
#define JOYSTICK_INTERFACES 1
#define RAWIO_INTERFACES 1
#define KEYBOARD_INTERFACE 0 // Keyboard
#define KEYBOARD_ENDPOINT 1
@ -70,52 +79,97 @@
#define NKRO_KEYBOARD_INTERVAL 1
#define NKRO_KEYBOARD_NAME L"NKRO Keyboard"
#define SYS_CTRL_INTERFACE 2 // Media Keys
#define SYS_CTRL_ENDPOINT 3
#define SYS_CTRL_SIZE 8
#define SYS_CTRL_INTERVAL 1
#define SYS_CTRL_NAME L"Media Keys"
#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 2
#define CDC_DATA_INTERFACE 3 // Serial
#define CDC_ACM_ENDPOINT 3
#define CDC_RX_ENDPOINT 4
#define CDC_TX_ENDPOINT 5
#define CDC_STATUS_INTERFACE 3
#define CDC_DATA_INTERFACE 4 // Serial
#define CDC_ACM_ENDPOINT 4
#define CDC_RX_ENDPOINT 5
#define CDC_TX_ENDPOINT 6
#define CDC_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64
#define CDC_STATUS_NAME L"Virtual Serial Port - Status"
#define CDC_DATA_NAME L"Virtual Serial Port - Data"
#define MOUSE_INTERFACE 4 // Mouse
#define MOUSE_ENDPOINT 6
#define RAWIO_INTERFACE 5 // RawIO
#define RAWIO_TX_ENDPOINT 7
#define RAWIO_TX_SIZE 64
#define RAWIO_TX_INTERVAL 1
#define RAWIO_RX_ENDPOINT 8
#define RAWIO_RX_SIZE 64
#define RAWIO_RX_INTERVAL 1
#define RAWIO_NAME L"API Interface"
#define MOUSE_INTERFACE 6 // Mouse
#define MOUSE_ENDPOINT 9
#define MOUSE_SIZE 8
#define MOUSE_INTERVAL 1
#define MOUSE_NAME L"Mouse"
#define JOYSTICK_INTERFACE 5 // Joystick
#define JOYSTICK_ENDPOINT 7
#define JOYSTICK_INTERFACE 7 // Joystick
#define JOYSTICK_ENDPOINT 10
#define JOYSTICK_SIZE 16
#define JOYSTICK_INTERVAL 1
#define JOYSTICK_NAME L"Joystick"
#define SYS_CTRL_INTERFACE 6 // Media Keys
#define SYS_CTRL_ENDPOINT 8
#define SYS_CTRL_SIZE 8
#define SYS_CTRL_INTERVAL 1
#define SYS_CTRL_NAME L"Media Keys"
#define KEYBOARD_DESC_OFFSET (9 + 9)
#define NKRO_KEYBOARD_DESC_OFFSET (9 + 9+9+7 + 9)
#define SERIAL_CDC_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8)
#define MOUSE_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9)
#define JOYSTICK_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
#define SYS_CTRL_DESC_OFFSET (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
#define CONFIG_DESC_SIZE (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)
// Descriptor sizes
#define BASE_DESC_SIZE (9)
#define KEYBOARD_DESC_SIZE (9+9+7)
#define NKRO_KEYBOARD_DESC_SIZE (9+9+7)
#define SYS_CTRL_DESC_SIZE (9+9+7)
#define SERIAL_CDC_DESC_SIZE (8+9+5+5+4+5+7+9+7+7)
#define RAWIO_DESC_SIZE (9+7+7)
#define MOUSE_DESC_SIZE (9+9+7)
#define JOYSTICK_DESC_SIZE (9+9+7)
// Descriptor offsets
#define KEYBOARD_DESC_BASE_OFFSET ( \
BASE_DESC_SIZE + \
9 \
)
#define SERIAL_CDC_DESC_BASE_OFFSET ( \
BASE_DESC_SIZE + \
KEYBOARD_DESC_TOTAL_OFFSET + \
8 \
)
#define RAWIO_DESC_BASE_OFFSET ( \
BASE_DESC_SIZE + \
KEYBOARD_DESC_TOTAL_OFFSET + \
SERIAL_CDC_DESC_TOTAL_OFFSET + \
9 \
)
#define MOUSE_DESC_BASE_OFFSET ( \
BASE_DESC_SIZE + \
KEYBOARD_DESC_TOTAL_OFFSET + \
SERIAL_CDC_DESC_TOTAL_OFFSET + \
9 \
)
#define JOYSTICK_DESC_BASE_OFFSET ( \
BASE_DESC_SIZE + \
KEYBOARD_DESC_TOTAL_OFFSET + \
SERIAL_CDC_DESC_TOTAL_OFFSET + \
MOUSE_DESC_TOTAL_OFFSET + \
9 \
)
#define ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT8_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT8_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT9_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT10_CONFIG ENDPOINT_TRANSIMIT_ONLY
@ -139,3 +193,8 @@ extern const usb_descriptor_list_t usb_descriptor_list[];
extern uint8_t *usb_bMaxPower;
// ----- Functions -----
void usb_set_config_descriptor_size();

View File

@ -40,6 +40,10 @@
#include "usb_dev.h"
#include "usb_mem.h"
#if enableVirtualSerialPort_define == 1
#include "usb_serial.h"
#endif
// ----- Defines -----
@ -180,7 +184,10 @@ static uint8_t usb_dev_sleep = 0;
static void endpoint0_stall()
{
#ifdef UART_DEBUG_UNKNOWN
print("STALL" NL );
print("STALL : ");
printInt32( systick_millis_count - USBInit_TimeStart );
print(" ms");
print(NL);
#endif
USB0_ENDPT0 = USB_ENDPT_EPSTALL | USB_ENDPT_EPRXEN | USB_ENDPT_EPTXEN | USB_ENDPT_EPHSHK;
}
@ -195,7 +202,6 @@ static void endpoint0_transmit( const void *data, uint32_t len )
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
@ -213,6 +219,18 @@ void usb_device_check()
// Check if 100 ms has elapsed
if ( systick_millis_count - power_neg_time > 100 )
{
power_neg_delay = 0;
// USB Low Power Negotiation
#if enableUSBLowPowerNegotiation_define == 1
// Check to see if bMaxPower has already be lowered
// This generally points to a USB bug (host or device?)
if ( *usb_bMaxPower == 50 )
{
warn_msg("Power negotiation delay detected again, likely a system/device USB bug");
return;
}
// Update bMaxPower
// The value set is in increments of 2 mA
// So 50 * 2 mA = 100 mA
@ -222,6 +240,9 @@ void usb_device_check()
// Re-initialize USB
usb_reinit();
#else
warn_msg("USB Low Power Negotation Disabled, condition detected.");
#endif
}
}
}
@ -237,6 +258,10 @@ static void usb_setup()
const uint8_t *cfg;
int i;
// Reset USB Init timer
USBInit_TimeEnd = systick_millis_count;
USBInit_Ticks++;
// If another request is made, disable the power negotiation check
// See GET_DESCRIPTOR - Configuration
if ( power_neg_delay )
@ -517,22 +542,40 @@ static void usb_setup()
endpoint0_stall();
return;
#if enableVirtualSerialPort_define == 1
case 0x2221: // CDC_SET_CONTROL_LINE_STATE
usb_cdc_line_rtsdtr = setup.wValue;
//serial_print("set control line state\n");
//info_print("set control line state");
goto send;
case 0x21A1: // CDC_GET_LINE_CODING
data = (uint8_t*)usb_cdc_line_coding;
data = (uint8_t*)&usb_cdc_line_coding;
datalen = sizeof( usb_cdc_line_coding );
goto send;
case 0x2021: // CDC_SET_LINE_CODING
// XXX Needed?
//serial_print("set coding, waiting...\n");
return;
// ZLP Reply
// Settings are applied in PID=OUT
goto send;
#endif
case 0x0921: // HID SET_REPORT
// ZLP Reply
// Settings are applied in PID=OUT
#ifdef UART_DEBUG
print("report_type(");
printHex( setup.wValue >> 8 );
print(")report_id(");
printHex( setup.wValue & 0xFF );
print(")interface(");
printHex( setup.wIndex );
print(")len(");
printHex( setup.wLength );
print(")");
print( NL );
#endif
// Interface
switch ( setup.wIndex & 0xFF )
{
@ -547,7 +590,7 @@ static void usb_setup()
printHex( setup.wIndex );
print( NL );
endpoint0_stall();
break;
return;
}
goto send;
@ -571,9 +614,9 @@ static void usb_setup()
datalen = list->length;
goto send;
}
}
endpoint0_stall();
return;
}
endpoint0_stall();
return;
case 0x0A21: // HID SET_IDLE
#ifdef UART_DEBUG
@ -596,6 +639,7 @@ static void usb_setup()
print(NL);
#endif
reply_buffer[0] = USBKeys_Idle_Config;
data = reply_buffer;
datalen = 1;
goto send;
@ -620,13 +664,16 @@ static void usb_setup()
print(NL);
#endif
reply_buffer[0] = USBKeys_Protocol;
data = reply_buffer;
datalen = 1;
goto send;
// case 0xC940:
default:
#ifdef UART_DEBUG_UNKNOWN
print("UNKNOWN");
print("UNKNOWN: ");
printInt32( systick_millis_count - USBInit_TimeStart );
print(" ms");
print(NL);
#endif
endpoint0_stall();
@ -655,7 +702,7 @@ send:
if ( size > EP0_SIZE )
size = EP0_SIZE;
endpoint0_transmit(data, size);
endpoint0_transmit( data, size );
data += size;
datalen -= size;
@ -666,7 +713,7 @@ send:
size = datalen;
if ( size > EP0_SIZE )
size = EP0_SIZE;
endpoint0_transmit(data, size);
endpoint0_transmit( data, size );
data += size;
datalen -= size;
@ -689,9 +736,9 @@ send:
//to be set to their default values. This includes setting the data toggle of
//any endpoint using data toggles to the value DATA0.
//For endpoints using data toggle, regardless of whether an endpoint has the
//Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the
//data toggle being reinitialized to DATA0.
// For endpoints using data toggle, regardless of whether an endpoint has the
// Halt feature set, a ClearFeature(ENDPOINT_HALT) request always results in the
// data toggle being reinitialized to DATA0.
static void usb_control( uint32_t stat )
{
@ -714,11 +761,9 @@ static void usb_control( uint32_t stat )
print(" - ");
#endif
switch (pid)
switch ( pid )
{
case 0x0D: // Setup received from host
//serial_print("PID=Setup\n");
//if (count != 8) ; // panic?
// grab the 8 byte setup info
setup.word1 = *(uint32_t *)(buf);
setup.word2 = *(uint32_t *)(buf + 4);
@ -741,36 +786,13 @@ static void usb_control( uint32_t stat )
//}
table[index(0, TX, EVEN)].desc = 0;
table[index(0, TX, ODD)].desc = 0;
// first IN after Setup is always DATA1
ep0_tx_data_toggle = 1;
#ifdef UART_DEBUG_UNKNOWN
print("bmRequestType:");
printHex(setup.bmRequestType);
print(", bRequest:");
printHex(setup.bRequest);
print(", wValue:");
printHex(setup.wValue);
print(", wIndex:");
printHex(setup.wIndex);
print(", len:");
printHex(setup.wLength);
print(" -- ");
printHex32(setup.word1);
print(" ");
printHex32(setup.word2);
print(NL);
#endif
// actually "do" the setup request
usb_setup();
// unfreeze the USB, now that we're ready
USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
break;
case 0x01: // OUT transaction received from host
case 0x02:
#ifdef UART_DEBUG_UNKNOWN
print("PID=OUT wRequestAndType:");
printHex( stat );
print(" PID=SETUP wRequestAndType:");
printHex(setup.wRequestAndType);
print(", wValue:");
printHex(setup.wValue);
@ -782,43 +804,105 @@ static void usb_control( uint32_t stat )
printHex32(setup.word1);
print(" ");
printHex32(setup.word2);
print(": ");
printInt32( systick_millis_count - USBInit_TimeStart );
print(" ms");
print(NL);
#endif
// actually "do" the setup request
usb_setup();
// unfreeze the USB, now that we're ready
USB0_CTL = USB_CTL_USBENSOFEN; // clear TXSUSPENDTOKENBUSY bit
break;
case 0x01: // OUT transaction received from host
case 0x02:
#ifdef UART_DEBUG_UNKNOWN
printHex( stat );
print(" PID=OUT wRequestAndType:");
printHex(setup.wRequestAndType);
print(", wValue:");
printHex(setup.wValue);
print(", wIndex:");
printHex(setup.wIndex);
print(", len:");
printHex(setup.wLength);
print(" -- ");
printHex32(setup.word1);
print(" ");
printHex32(setup.word2);
print(": ");
printInt32( systick_millis_count - USBInit_TimeStart );
print(" ms");
print(NL);
#endif
// CDC Interface
if ( setup.wRequestAndType == 0x2021 /*CDC_SET_LINE_CODING*/ )
#if enableVirtualSerialPort_define == 1
// CDC_SET_LINE_CODING - PID=OUT
// XXX - Getting lots of NAKs in Linux
if ( setup.wRequestAndType == 0x2021 )
{
int i;
uint8_t *dst = (uint8_t *)usb_cdc_line_coding;
//serial_print("set line coding ");
for ( i = 0; i < 7; i++ )
{
//serial_phex(*buf);
*dst++ = *buf++;
}
//serial_phex32(usb_cdc_line_coding[0]);
//serial_print("\n");
if ( usb_cdc_line_coding[0] == 134 )
usb_reboot_timer = 15;
endpoint0_transmit( NULL, 0 );
}
// Copy over new line coding
memcpy( (void*)&usb_cdc_line_coding, buf, 7 );
// Keyboard SET_REPORT
if ( setup.wRequestAndType == 0x921 && setup.wValue & 0x200 )
#ifdef UART_DEBUG
// - Unused, but for the readers info -
print("dwDTERate(");
printInt32( usb_cdc_line_coding.dwDTERate );
print(")bCharFormat(");
printHex( usb_cdc_line_coding.bCharFormat );
print(")bParityType(");
printHex( usb_cdc_line_coding.bParityType );
print(")bDataBits(");
printHex( usb_cdc_line_coding.bDataBits );
print(")");
print( NL );
#endif
// XXX ZLP causes timeout/delay, why? -HaaTa
//endpoint0_transmit( NULL, 0 );
}
#endif
// Keyboard HID SET_REPORT - PID=OUT
#if enableKeyboard_define == 1
// XXX - Getting lots of NAKs in Linux
if ( setup.wRequestAndType == 0x0921 && setup.wValue & 0x200 )
{
#ifdef UART_DEBUG
print("report_type(");
printHex( setup.wValue >> 8 );
print(")report_id(");
printHex( setup.wValue & 0xFF );
print(")interface(");
printHex( setup.wIndex );
print(")len(");
printHex( setup.wLength );
print(")[");
for ( size_t len = 0; len < setup.wLength; len++ )
{
printHex( buf[ len ] );
print(" ");
}
print("]");
print( NL );
#endif
// Interface
switch ( setup.wIndex & 0xFF )
{
// Keyboard Interface
case KEYBOARD_INTERFACE:
USBKeys_LEDs = buf[0];
endpoint0_transmit( NULL, 0 );
break;
// NKRO Keyboard Interface
case NKRO_KEYBOARD_INTERFACE:
// Already set with the control sequence
// Only use 2nd byte, first byte is the report id
USBKeys_LEDs = buf[1];
endpoint0_transmit( NULL, 0 );
break;
default:
warn_msg("Unknown interface - ");
@ -827,34 +911,48 @@ static void usb_control( uint32_t stat )
break;
}
#ifdef UART_DEBUG
for ( size_t len = 0; len < setup.wLength; len++ )
{
printHex( buf[ len ] );
print(" ");
}
print( NL );
#endif
// XXX ZLP causes timeout/delay, why? -HaaTa
//endpoint0_transmit( NULL, 0 );
}
#endif
// give the buffer back
b->desc = BDT_DESC( EP0_SIZE, DATA1 );
break;
case 0x09: // IN transaction completed to host
#ifdef UART_DEBUG
print("PID=IN:");
printHex(stat);
data = ep0_tx_ptr;
#ifdef UART_DEBUG_UNKNOWN
printHex( stat );
print(" PID=IN wRequestAndType:");
printHex(setup.wRequestAndType);
print(", wValue:");
printHex(setup.wValue);
print(", wIndex:");
printHex(setup.wIndex);
print(", len:");
printHex(setup.wLength);
print(" -- ");
printHex32(setup.word1);
print(" ");
printHex32(setup.word2);
print(": ");
printInt32( systick_millis_count - USBInit_TimeStart );
print(" ms");
if ( data ) print(" DATA ");
print(NL);
#endif
// send remaining data, if any...
data = ep0_tx_ptr;
if ( data )
{
size = ep0_tx_len;
if (size > EP0_SIZE) size = EP0_SIZE;
endpoint0_transmit(data, size);
if (size > EP0_SIZE)
{
size = EP0_SIZE;
}
endpoint0_transmit( data, size );
data += size;
ep0_tx_len -= size;
ep0_tx_ptr = (ep0_tx_len > 0 || size == EP0_SIZE) ? data : NULL;
@ -871,12 +969,34 @@ static void usb_control( uint32_t stat )
USB0_ADDR = setup.wValue;
}
// CDC_SET_LINE_CODING - PID=IN
#if enableVirtualSerialPort_define == 1
if ( setup.wRequestAndType == 0x2021 )
{
// XXX ZLP causes timeout/delay, why? -HaaTa
//endpoint0_transmit( NULL, 0 );
}
#endif
// Keyboard HID SET_REPORT - PID=IN
#if enableKeyboard_define == 1
// XXX - Getting lots of NAKs in Linux
if ( setup.wRequestAndType == 0x0921 && setup.wValue & 0x200 )
{
// XXX ZLP causes timeout/delay, why? -HaaTa
//endpoint0_transmit( NULL, 0 );
}
#endif
break;
default:
#ifdef UART_DEBUG
print("PID=unknown:");
#ifdef UART_DEBUG_UNKNOWN
print("PID=unknown: ");
printHex(pid);
print(": ");
printInt32( systick_millis_count - USBInit_TimeStart );
print(" ms");
print(NL);
#endif
break;
@ -889,14 +1009,25 @@ usb_packet_t *usb_rx( uint32_t endpoint )
//print("USB RX");
usb_packet_t *ret;
endpoint--;
// Make sure this is a valid endpoint
if ( endpoint >= NUM_ENDPOINTS )
{
return NULL;
}
__disable_irq();
// Receive packet, check pointer
ret = rx_first[endpoint];
if ( ret )
{
rx_first[ endpoint ] = ret->next;
usb_rx_byte_count_data[ endpoint ] -= ret->len;
usb_rx_byte_count_data[ endpoint ] -= ret->len;
}
__enable_irq();
//serial_print("rx, epidx=");
//serial_phex(endpoint);
//serial_print(", packet=");
@ -994,17 +1125,16 @@ void usb_rx_memory( usb_packet_t *packet )
return;
}
//#define index(endpoint, tx, odd) (((endpoint) << 2) | ((tx) << 1) | (odd))
//#define stat2bufferdescriptor(stat) (table + ((stat) >> 2))
void usb_tx( uint32_t endpoint, usb_packet_t *packet )
// Call whenever there's an action that may wake the host device
void usb_resume()
{
// Update expiry counter
USBKeys_Idle_Expiry = systick_millis_count;
// If we have been sleeping, try to wake up host
if ( usb_dev_sleep )
if ( usb_dev_sleep && usb_configured() )
{
#if enableUSBResume_define == 1
#if enableVirtualSerialPort_define != 1
info_print("Attempting to resume the host");
#endif
// Force wake-up for 10 ms
// According to the USB Spec a device must hold resume for at least 1 ms but no more than 15 ms
USB0_CTL |= USB_CTL_RESUME;
@ -1012,8 +1142,18 @@ void usb_tx( uint32_t endpoint, usb_packet_t *packet )
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
#else
warn_print("Host Resume Disabled");
#endif
}
}
void usb_tx( uint32_t endpoint, usb_packet_t *packet )
{
// Update expiry counter
USBKeys_Idle_Expiry = systick_millis_count;
// Since we are transmitting data, USB will be brought out of sleep/suspend
// if it's in that state
// Use the currently set descriptor value
@ -1087,16 +1227,12 @@ void usb_isr()
{
uint8_t status, stat, t;
//serial_print("isr");
//status = USB0_ISTAT;
//serial_phex(status);
//serial_print("\n");
restart:
status = USB0_ISTAT;
/*
print("USB ISR STATUS: ");
print(" ISR(");
printHex( status );
print( NL );
print(") ");
*/
if ( (status & USB_INTEN_SOFTOKEN /* 04 */ ) )
@ -1112,6 +1248,7 @@ restart:
}
// CDC Interface
#if enableVirtualSerialPort_define == 1
t = usb_cdc_transmit_flush_timer;
if ( t )
{
@ -1119,6 +1256,7 @@ restart:
if ( t == 0 )
usb_serial_flush_callback();
}
#endif
}
USB0_ISTAT = USB_INTEN_SOFTOKEN;
@ -1323,16 +1461,26 @@ restart:
// The USB Module triggers this interrupt when it detects the bus has been idle for 3 ms
if ( (status & USB_ISTAT_SLEEP /* 10 */ ) )
{
//info_print("Host has requested USB sleep/suspend state");
#if enableUSBSuspend_define == 1
// Can cause issues with the virtual serial port
#if enableVirtualSerialPort_define != 1
info_print("Host has requested USB sleep/suspend state");
#endif
Output_update_usb_current( 100 ); // Set to 100 mA
usb_dev_sleep = 1;
#else
info_print("USB Suspend Detected - Firmware USB Suspend Disabled");
#endif
USB0_ISTAT |= USB_ISTAT_SLEEP;
}
// On USB Resume, unset the usb_dev_sleep so we don't keep sending resume signals
if ( (status & USB_ISTAT_RESUME /* 20 */ ) )
{
//info_print("Host has woken-up/resumed from sleep/suspend state");
// Can cause issues with the virtual serial port
#if enableVirtualSerialPort_define != 1
info_print("Host has woken-up/resumed from sleep/suspend state");
#endif
Output_update_usb_current( *usb_bMaxPower * 2 );
usb_dev_sleep = 0;
USB0_ISTAT |= USB_ISTAT_RESUME;
@ -1347,6 +1495,13 @@ uint8_t usb_init()
print("USB INIT"NL);
#endif
USBInit_TimeStart = systick_millis_count;
USBInit_Ticks = 0;
// XXX Set wTotalLength here instead of using defines
// Simplifies defines considerably
usb_set_config_descriptor_size();
// Clear out endpoints table
for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ )
{

View File

@ -51,10 +51,6 @@ extern volatile uint8_t usb_configuration;
extern uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS];
extern volatile uint8_t usb_cdc_line_coding[7];
extern volatile uint8_t usb_cdc_line_rtsdtr;
extern volatile uint8_t usb_cdc_transmit_flush_timer;
// ----- Functions -----
@ -67,6 +63,8 @@ void usb_isr();
void usb_tx( uint32_t endpoint, usb_packet_t *packet );
void usb_tx_isr( uint32_t endpoint, usb_packet_t *packet );
void usb_resume();
uint32_t usb_tx_byte_count( uint32_t endpoint );
uint32_t usb_tx_packet_count( uint32_t endpoint );

View File

@ -1,7 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modified by Jacob Alexander (2015)
* Modified by Jacob Alexander (2015-2016)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -29,6 +29,8 @@
* SOFTWARE.
*/
#if enableJoystick_define == 1
// ----- Includes -----
// Compiler Includes
@ -112,3 +114,5 @@ int usb_joystick_send()
return 0;
}
#endif

View File

@ -1,7 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modifications by Jacob Alexander 2013-2015
* Modifications by Jacob Alexander 2013-2016
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@ -29,6 +29,9 @@
* SOFTWARE.
*/
#include <kll_defs.h>
#if enableKeyboard_define == 1
// ----- Includes -----
// Compiler Includes
@ -123,14 +126,25 @@ void usb_keyboard_send()
}
}
// USB Timeout, drop the packet, and potentially try something more drastic to re-enable the bus
if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout )
{
transmit_previous_timeout = 1;
warn_print("USB Transmit Timeout...restarting device");
USBKeys_Changed = USBKeyChangeState_None; // Indicate packet lost
#if enableDeviceRestartOnUSBTimeout == 1
warn_print("USB Transmit Timeout...restarting device");
usb_device_software_reset();
#else
warn_print("USB Transmit Timeout...auto-restart disabled");
#endif
// Try to wakeup
return;
}
// Try to wake up the device if we can't allocate a packet for some reason
// XXX This is a bit aggressive, but seems to work well. Unfortunately, not as quick as I'd like it -HaaTa
usb_resume();
yield();
}
@ -277,3 +291,5 @@ void usb_keyboard_send()
return;
}
#endif