Browse Source

More preparation for NKRO USB for arm

- Added NKRO descriptor
- Added NKRO HID descriptor
- Updated boot HID descriptor
- Fixed many bugs with the pjrc ARM usb stack (with USB HID)
simple
Jacob Alexander 9 years ago
parent
commit
4255a99fcc

+ 288
- 144
Output/pjrcUSB/arm/usb_desc.c View File

@@ -29,34 +29,21 @@
* SOFTWARE.
*/

// ----- Includes -----

// Local Includes
#include "usb_desc.h"


// USB Descriptors are binary data which the USB host reads to
// automatically detect a USB device's capabilities. The format
// and meaning of every field is documented in numerous USB
// standards. When working with USB descriptors, despite the
// complexity of the standards and poor writing quality in many
// of those documents, remember descriptors are nothing more
// than constant binary data that tells the USB host what the
// device can do. Computers will load drivers based on this data.
// Those drivers then communicate on the endpoints specified by
// the descriptors.

// To configure a new combination of interfaces or make minor
// changes to existing configuration (eg, change the name or ID
// numbers), usually you would edit "usb_desc.h". This file
// is meant to be configured by the header, so generally it is
// only edited to add completely new USB interfaces or features.
// ----- Macros -----

#define LSB(n) ((n) & 255)
#define MSB(n) (((n) >> 8) & 255)


// **************************************************************
// USB Device
// **************************************************************

#define LSB(n) ((n) & 255)
#define MSB(n) (((n) >> 8) & 255)
// ----- USB Device Descriptor -----

// USB Device Descriptor. The USB host reads this first, to learn
// what type of device is connected.
@@ -64,21 +51,9 @@ static uint8_t device_descriptor[] = {
18, // bLength
1, // bDescriptorType
0x00, 0x02, // bcdUSB
#ifdef DEVICE_CLASS
DEVICE_CLASS, // bDeviceClass
#else
0,
#endif
#ifdef DEVICE_SUBCLASS
DEVICE_SUBCLASS, // bDeviceSubClass
#else
0,
#endif
#ifdef DEVICE_PROTOCOL
DEVICE_PROTOCOL, // bDeviceProtocol
#else
0,
#endif
EP0_SIZE, // bMaxPacketSize0
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
@@ -89,69 +64,202 @@ static uint8_t device_descriptor[] = {
1 // bNumConfigurations
};

// USB Device Qualifier Descriptor
static uint8_t device_qualifier_descriptor[] = {
0 // Indicate only single speed
/* Device qualifier example (used for specifying multiple USB speeds)
10, // bLength
6, // bDescriptorType
0x00, 0x02, // bcdUSB
DEVICE_CLASS, // bDeviceClass
DEVICE_SUBCLASS, // bDeviceSubClass
DEVICE_PROTOCOL, // bDeviceProtocol
EP0_SIZE, // bMaxPacketSize0
1, // bNumOtherSpeedConfigurations
0 // bReserved
*/
};

// USB Debug Descriptor
// XXX Not sure of exact use, lsusb requests it
static uint8_t usb_debug_descriptor[] = {
0
};

// XXX
// These descriptors must NOT be "const", because the USB DMA
// has trouble accessing flash memory with enough bandwidth
// while the processor is executing from flash.
// XXX



// **************************************************************
// HID Report Descriptors
// **************************************************************
// ----- USB HID Report Descriptsors -----

// Each HID interface needs a special report descriptor that tells
// the meaning and format of the data.

#ifdef KEYBOARD_INTERFACE
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
static uint8_t keyboard_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
0xA1, 0x01, // Collection (Application),
0x75, 0x01, // Report Size (1),
0x95, 0x08, // Report Count (8),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0xE0, // Usage Minimum (224),
0x29, 0xE7, // Usage Maximum (231),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
0x95, 0x08, // Report Count (8),
0x75, 0x01, // Report Size (1),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x05, 0x0C, // Usage Page (Consumer),
0x09, 0xE9, // Usage (Volume Increment),
0x09, 0xEA, // Usage (Volume Decrement),
0x09, 0xE2, // Usage (Mute),
0x09, 0xCD, // Usage (Play/Pause),
0x09, 0xB5, // Usage (Scan Next Track),
0x09, 0xB6, // Usage (Scan Previous Track),
0x09, 0xB7, // Usage (Stop),
0x09, 0xB8, // Usage (Eject),
0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys
0x95, 0x05, // Report Count (5),
0x75, 0x01, // Report Size (1),
0x05, 0x08, // Usage Page (LEDs),
0x19, 0x01, // Usage Minimum (1),
0x29, 0x05, // Usage Maximum (5),
0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
0x95, 0x01, // Report Count (1),
0x75, 0x03, // Report Size (3),
0x91, 0x03, // Output (Constant), ;LED report padding
0x95, 0x06, // Report Count (6),
0x75, 0x08, // Report Size (8),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x7F, // Logical Maximum(104),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x00, // Usage Minimum (0),
0x29, 0x7F, // Usage Maximum (104),
0x81, 0x00, // Input (Data, Array), ;Normal keys
0xc0 // End Collection
// Keyboard Collection
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
0xA1, 0x01, // Collection (Application) - Keyboard,

// Modifier Byte
0x75, 0x01, // Report Size (1),
0x95, 0x08, // Report Count (8),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0xE0, // Usage Minimum (224),
0x29, 0xE7, // Usage Maximum (231),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x81, 0x02, // Input (Data, Variable, Absolute),

// Reserved Byte
0x75, 0x08, // Report Size (8),
0x95, 0x01, // Report Count (1),
0x81, 0x03, // Output (Constant),

// LED Report
0x75, 0x01, // Report Size (1),
0x95, 0x05, // Report Count (5),
0x05, 0x08, // Usage Page (LEDs),
0x19, 0x01, // Usage Minimum (1),
0x29, 0x05, // Usage Maximum (5),
0x91, 0x02, // Output (Data, Variable, Absolute),

// LED Report Padding
0x75, 0x03, // Report Size (3),
0x95, 0x01, // Report Count (1),
0x91, 0x03, // Output (Constant),

// Normal Keys
0x75, 0x08, // Report Size (8),
0x95, 0x06, // Report Count (6),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x7F, // Logical Maximum(104),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x00, // Usage Minimum (0),
0x29, 0x7F, // Usage Maximum (104),
0x81, 0x00, // Input (Data, Array),
0xc0, // End Collection - Keyboard
};

// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
static uint8_t nkro_keyboard_report_desc[] = {
// Keyboard Collection
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
0xA1, 0x01, // Collection (Application) - Keyboard,

// Modifier Byte
0x85, 0x01, // Report ID (1),
0x75, 0x01, // Report Size (1),
0x95, 0x08, // Report Count (8),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0xE0, // Usage Minimum (224),
0x29, 0xE7, // Usage Maximum (231),
0x81, 0x02, // Input (Data, Variable, Absolute),

// LED Report
0x85, 0x02, // Report ID (2),
0x75, 0x01, // Report Size (1),
0x95, 0x05, // Report Count (5),
0x05, 0x08, // Usage Page (LEDs),
0x19, 0x01, // Usage Minimum (1),
0x29, 0x05, // Usage Maximum (5),
0x91, 0x02, // Output (Data, Variable, Absolute),

// LED Report Padding
0x75, 0x03, // Report Size (3),
0x95, 0x01, // Report Count (1),
0x91, 0x03, // Output (Constant),

// Normal Keys - Using an NKRO Bitmap
//
// NOTES:
// Supports all keys defined by the spec, except 1-3 which define error events
// and 0 which is "no keys pressed"
// See http://www.usb.org/developers/hidpage/Hut1_12v2.pdf Chapter 10
// Or Macros/PartialMap/usb_hid.h
//
// 165-175 are reserved/unused as well as 222-223 and 232-65535
// 224-231 are used for modifiers (see above)
//
// Packing of bitmaps are as follows:
// 4-164 : 20 bytes + 1 Report ID byte (0x04-0xA4)
// 176-221 : 6 bytes + 1 Report ID byte (0xB0-0xDD) (45 bits + 3 padding bits for 6 bytes total)
//
// 4-164 (20 bytes/160 bits)
0x85, 0x03, // Report ID (3),
0x75, 0x01, // Report Size (1),
0x95, 0xA0, // Report Count (160),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x04, // Usage Minimum (4),
0x29, 0xA4, // Usage Maximum (164),
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield),

// 176-221 (45 bits)
0x85, 0x04, // Report ID (4),
0x75, 0x01, // Report Size (1),
0x95, 0x2D, // Report Count (45),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum (1),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0xB0, // Usage Minimum (176),
0x29, 0xDD, // Usage Maximum (221),
0x81, 0x02, // Input (Data, Variable, Absolute, Bitfield),

// 176-221 Padding (3 bits)
0x75, 0x03, // Report Size (3),
0x95, 0x01, // Report Count (1),
0x81, 0x03, // Input (Constant),
0xc0, // End Collection - Keyboard

// System Control Collection
//
// NOTES:
// Not bothering with NKRO for this table. If there's need, I can implement it. -HaaTa
// Using a 1KRO scheme
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x80, // Usage (System Control),
0xA1, 0x01, // Collection (Application),
0x85, 0x05, // Report ID (5),
0x75, 0x08, // Report Size (8),
0x95, 0x01, // Report Count (1),
0x16, 0x81, 0x00, // Logical Minimum (129),
0x26, 0xB7, 0x00, // Logical Maximum (183),
0x19, 0x81, // Usage Minimum (129),
0x29, 0xB7, // Usage Maximum (183),
0x81, 0x00, // Input (Data, Array),
0xc0, // End Collection - System Control

// Consumer Control Collection - Media Keys
//
// NOTES:
// Not bothering with NKRO for this table. If there's a need, I can implement it. -HaaTa
// Using a 1KRO scheme
0x05, 0x0c, // Usage Page (Consumer),
0x09, 0x01, // Usage (Consumer Control),
0xA1, 0x01, // Collection (Application),
0x85, 0x06, // Report ID (6),
0x75, 0x10, // Report Size (16),
0x95, 0x01, // Report Count (1),
0x16, 0x20, 0x00, // Logical Minimum (32),
0x26, 0x9C, 0x02, // Logical Maximum (668),
0x05, 0x0C, // Usage Page (Consumer),
0x19, 0x20, // Usage Minimum (32),
0x2A, 0x9C, 0x02, // Usage Maximum (668),
0x81, 0x00, // Input (Data, Array),
0xc0, // End Collection - Consumer Control
};
#endif

#ifdef MOUSE_INTERFACE
/* MOUSE
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
static uint8_t mouse_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop)
@@ -184,29 +292,92 @@ static uint8_t mouse_report_desc[] = {
0x81, 0x06, // Input (Data, Variable, Relative)
0xC0 // End Collection
};
#endif
*/



// **************************************************************
// USB Configuration
// **************************************************************
// ----- USB Configuration -----

// USB Configuration Descriptor. This huge descriptor tells all
// of the devices capbilities.
static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
// --- 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
LSB(CONFIG_DESC_SIZE), // wTotalLength
MSB(CONFIG_DESC_SIZE),
NUM_INTERFACE, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0xC0, // bmAttributes
50, // bMaxPower
250, // bMaxPower

#ifdef CDC_IAD_DESCRIPTOR
// --- Keyboard HID --- Boot Mode Keyboard Interface
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
KEYBOARD_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x01, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot)
0x01, // bInterfaceProtocol (0x01 = Keyboard)
0, // iInterface
// - 9 bytes -
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
LSB(sizeof(keyboard_report_desc)), // wDescriptorLength
MSB(sizeof(keyboard_report_desc)),
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
KEYBOARD_SIZE, 0, // wMaxPacketSize
KEYBOARD_INTERVAL, // bInterval

// --- NKRO Keyboard HID --- OS Mode Keyboard Interface
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
NKRO_KEYBOARD_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x00, // bInterfaceSubClass (0x00 = Non-Boot, 0x01 = Boot)
0x01, // bInterfaceProtocol (0x01 = Keyboard)
0, // iInterface
// - 9 bytes -
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
LSB(sizeof(nkro_keyboard_report_desc)), // wDescriptorLength
MSB(sizeof(nkro_keyboard_report_desc)),
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
NKRO_KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
NKRO_KEYBOARD_SIZE, 0, // wMaxPacketSize
NKRO_KEYBOARD_INTERVAL, // bInterval

// --- Serial CDC --- CDC IAD Descriptor
// - 8 bytes -
// interface association descriptor, USB ECN, Table 9-Z
8, // bLength
11, // bDescriptorType
@@ -216,9 +387,9 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x02, // bFunctionSubClass
0x01, // bFunctionProtocol
4, // iFunction
#endif

#ifdef CDC_DATA_INTERFACE
// --- Serial CDC --- CDC Data Interface
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
@@ -229,28 +400,33 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x02, // bInterfaceSubClass
0x01, // bInterfaceProtocol
0, // iInterface
// - 5 bytes -
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
5, // bFunctionLength
0x24, // bDescriptorType
0x00, // bDescriptorSubtype
0x10, 0x01, // bcdCDC
// - 5 bytes -
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
5, // bFunctionLength
0x24, // bDescriptorType
0x01, // bDescriptorSubtype
0x01, // bmCapabilities
1, // bDataInterface
// - 4 bytes -
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
4, // bFunctionLength
0x24, // bDescriptorType
0x02, // bDescriptorSubtype
0x06, // bmCapabilities
// - 5 bytes -
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
5, // bFunctionLength
0x24, // bDescriptorType
0x06, // bDescriptorSubtype
CDC_STATUS_INTERFACE, // bMasterInterface
CDC_DATA_INTERFACE, // bSlaveInterface0
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
@@ -258,6 +434,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x03, // bmAttributes (0x03=intr)
CDC_ACM_SIZE, 0, // wMaxPacketSize
64, // bInterval
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
@@ -268,6 +445,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0, // iInterface
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
@@ -275,6 +453,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x02, // bmAttributes (0x02=bulk)
CDC_RX_SIZE, 0, // wMaxPacketSize
0, // bInterval
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
@@ -282,38 +461,10 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x02, // bmAttributes (0x02=bulk)
CDC_TX_SIZE, 0, // wMaxPacketSize
0, // bInterval
#endif // CDC_DATA_INTERFACE

#ifdef KEYBOARD_INTERFACE
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
KEYBOARD_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x01, // bInterfaceSubClass (0x01 = Boot)
0x01, // bInterfaceProtocol (0x01 = Keyboard)
0, // iInterface
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
LSB(sizeof(keyboard_report_desc)), // wDescriptorLength
MSB(sizeof(keyboard_report_desc)),
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
KEYBOARD_SIZE, 0, // wMaxPacketSize
KEYBOARD_INTERVAL, // bInterval
#endif // KEYBOARD_INTERFACE

#ifdef MOUSE_INTERFACE
/*
// Mouse Interface
// - 9 bytes -
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
@@ -324,6 +475,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x00, // bInterfaceSubClass (0x01 = Boot)
0x00, // bInterfaceProtocol (0x02 = Mouse)
0, // iInterface
// - 9 bytes -
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
@@ -333,6 +485,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
0x22, // bDescriptorType
LSB(sizeof(mouse_report_desc)), // wDescriptorLength
MSB(sizeof(mouse_report_desc)),
// - 7 bytes -
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
@@ -341,13 +494,12 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
MOUSE_SIZE, 0, // wMaxPacketSize
MOUSE_INTERVAL, // bInterval
#endif // MOUSE_INTERFACE
*/
};



// **************************************************************
// String Descriptors
// **************************************************************
// ----- String Descriptors -----

// The descriptors above can provide human readable strings,
// referenced by index numbers. These descriptors are the
@@ -389,9 +541,8 @@ struct usb_string_descriptor_struct usb_string_serial_number_default = {
};


// **************************************************************
// Descriptors List
// **************************************************************

// ----- Descriptors List -----

// This table provides access to all the descriptor data above.

@@ -399,14 +550,16 @@ const usb_descriptor_list_t usb_descriptor_list[] = {
//wValue, wIndex, address, length
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
{0x0200, 0x0000, config_descriptor, sizeof(config_descriptor)},
#ifdef KEYBOARD_INTERFACE
{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},
#endif
#ifdef MOUSE_INTERFACE
{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},
/* MOUSE
{0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)},
{0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9},
#endif
*/
{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},
@@ -415,24 +568,15 @@ const usb_descriptor_list_t usb_descriptor_list[] = {
};


// **************************************************************
// Endpoint Configuration
// **************************************************************

#if 0
// ----- Endpoint Configuration -----

// See usb_desc.h for Endpoint configuration
// 0x00 = not used
// 0x19 = Recieve only
// 0x15 = Transmit only
// 0x1D = Transmit & Recieve
//
const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS] =
{
0x00, 0x15, 0x19, 0x15, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif


const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS] =
{
#if (defined(ENDPOINT1_CONFIG) && NUM_ENDPOINTS >= 1)

+ 52
- 67
Output/pjrcUSB/arm/usb_desc.h View File

@@ -32,105 +32,83 @@
#ifndef _usb_desc_h_
#define _usb_desc_h_

// This header is NOT meant to be included when compiling
// user sketches in Arduino. The low-level functions
// provided by usb_dev.c are meant to be called only by
// code which provides higher-level interfaces to the user.
// ----- Includes -----

// Compiler Includes
#include <stdint.h>
#include <stddef.h>
#include "output_com.h"

#define ENDPOINT_UNUSED 0x00
#define ENDPOINT_TRANSIMIT_ONLY 0x15
#define ENDPOINT_RECEIVE_ONLY 0x19
#define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D

/*
To modify a USB Type to have different interfaces, start in this
file. Delete the XYZ_INTERFACE lines for any interfaces you
wish to remove, and copy them from another USB Type for any you
want to add.

Give each interface a unique number, and edit NUM_INTERFACE to
reflect the number of interfaces.

Within each interface, make sure it uses a unique set of endpoints.
Edit NUM_ENDPOINTS to be at least the largest endpoint number used.
Then edit the ENDPOINT*_CONFIG lines so each endpoint is configured
the proper way (transmit, receive, or both).

The CONFIG_DESC_SIZE and any XYZ_DESC_OFFSET numbers must be
edited to the correct sizes. See usb_desc.c for the giant array
of bytes. Someday these may be done automatically..... (but how?)
// Local Includes
#include <output_com.h>

If you are using existing interfaces, the code in each file should
automatically adapt to the changes you specify. If you need to
create a new type of interface, you'll need to write the code which
sends and receives packets, and presents an API to the user.

Finally, edit usb_inst.cpp, which creats instances of the C++
objects for each combination.

Some operating systems, especially Windows, may cache USB device
info. Changes to the device name may not update on the same
computer unless the vendor or product ID numbers change, or the
"bcdDevice" revision code is increased.

If these instructions are missing steps or could be improved, please
let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports
*/
// ----- Defines -----

#define ENDPOINT_UNUSED 0x00
#define ENDPOINT_TRANSIMIT_ONLY 0x15
#define ENDPOINT_RECEIVE_ONLY 0x19
#define ENDPOINT_TRANSMIT_AND_RECEIVE 0x1D


#define DEVICE_CLASS 0xEF
#define DEVICE_SUBCLASS 0x02
#define DEVICE_PROTOCOL 0x01
#define DEVICE_CLASS 0x03 // 0x03 = HID Class
#define DEVICE_SUBCLASS 0x00
#define DEVICE_PROTOCOL 0x00
#define EP0_SIZE 64
#define NUM_ENDPOINTS 6
#define NUM_ENDPOINTS 5
#define NUM_USB_BUFFERS 30
#define NUM_INTERFACE 4

#define KEYBOARD_INTERFACE 0 // Keyboard
#define KEYBOARD_ENDPOINT 1
#define KEYBOARD_SIZE 8
#define KEYBOARD_INTERVAL 1

#define NKRO_KEYBOARD_INTERFACE 1 // NKRO Keyboard
#define NKRO_KEYBOARD_ENDPOINT 2
#define NKRO_KEYBOARD_SIZE 128
#define NKRO_KEYBOARD_INTERVAL 1

#define CDC_IAD_DESCRIPTOR 1
#define CDC_STATUS_INTERFACE 0
#define CDC_DATA_INTERFACE 1 // Serial
#define CDC_ACM_ENDPOINT 2
#define CDC_RX_ENDPOINT 3
#define CDC_TX_ENDPOINT 4
#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_ACM_SIZE 16
#define CDC_RX_SIZE 64
#define CDC_TX_SIZE 64

#define KEYBOARD_INTERFACE 2 // Keyboard
#define KEYBOARD_ENDPOINT 1
#define KEYBOARD_SIZE 8
#define KEYBOARD_INTERVAL 1

#define MOUSE_INTERFACE 3 // Mouse
#define MOUSE_ENDPOINT 5
#define MOUSE_INTERFACE 4 // Mouse
#define MOUSE_ENDPOINT 6
#define MOUSE_SIZE 8
#define MOUSE_INTERVAL 2

#define JOYSTICK_INTERFACE 4 // Joystick
#define JOYSTICK_ENDPOINT 6
#define JOYSTICK_INTERFACE 5 // Joystick
#define JOYSTICK_ENDPOINT 7
#define JOYSTICK_SIZE 16
#define JOYSTICK_INTERVAL 1

#define KEYBOARD_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9)
#define MOUSE_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9)
#define JOYSTICK_DESC_OFFSET (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9)
#define CONFIG_DESC_SIZE (9+8 + 9+5+5+4+5+7+9+7+7 + 9+9+7 + 9+9+7 + 9+9+7)
#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 CONFIG_DESC_SIZE (9 + 9+9+7 + 9+9+7 + 8+9+5+5+4+5+7+9+7+7)

// XXX Unused
#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 ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT2_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT3_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT4_CONFIG ENDPOINT_RECEIVE_ONLY
#define ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT6_CONFIG ENDPOINT_TRANSIMIT_ONLY
#define ENDPOINT7_CONFIG ENDPOINT_TRANSIMIT_ONLY


// NUM_ENDPOINTS = number of non-zero endpoints (0 to 15)
extern const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS];
// ----- Enumerations -----

typedef struct {
uint16_t wValue;
@@ -139,6 +117,13 @@ typedef struct {
uint16_t length;
} usb_descriptor_list_t;



// ----- Variables -----

// NUM_ENDPOINTS = number of non-zero endpoints (0 to 15)
extern const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS];

extern const usb_descriptor_list_t usb_descriptor_list[];



+ 462
- 291
Output/pjrcUSB/arm/usb_dev.c
File diff suppressed because it is too large
View File


+ 29
- 27
Output/pjrcUSB/arm/usb_dev.h View File

@@ -11,10 +11,10 @@
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
@@ -32,16 +32,34 @@
#ifndef _usb_dev_h_
#define _usb_dev_h_

// This header is NOT meant to be included when compiling
// user sketches in Arduino. The low-level functions
// provided by usb_dev.c are meant to be called only by
// code which provides higher-level interfaces to the user.
// ----- Includes -----

// Local Includes
#include "usb_mem.h"
#include "usb_desc.h"



// ----- Defines -----

#define usb_device_software_reset() SOFTWARE_RESET()



// ----- Variables -----

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 -----

uint8_t usb_configured(); // is the USB port configured

void usb_init();
@@ -54,35 +72,19 @@ uint32_t usb_tx_packet_count( uint32_t endpoint );

usb_packet_t *usb_rx( uint32_t endpoint );

void usb_device_reload();

extern volatile uint8_t usb_configuration;

extern uint16_t usb_rx_byte_count_data[NUM_ENDPOINTS];
static inline uint32_t usb_rx_byte_count(uint32_t endpoint) __attribute__((always_inline));
static inline uint32_t usb_rx_byte_count(uint32_t endpoint)
{
endpoint--;
if (endpoint >= NUM_ENDPOINTS) return 0;
return usb_rx_byte_count_data[endpoint];
if ( endpoint >= NUM_ENDPOINTS )
return 0;
return usb_rx_byte_count_data[ endpoint ];
}

#ifdef CDC_DATA_INTERFACE
extern uint32_t usb_cdc_line_coding[2];
extern volatile uint8_t usb_cdc_line_rtsdtr;
extern volatile uint8_t usb_cdc_transmit_flush_timer;
extern void usb_serial_flush_callback(void);
#endif
void usb_device_reload();

extern void usb_serial_flush_callback();

#ifdef KEYBOARD_INTERFACE
extern uint8_t keyboard_modifier_keys;
extern uint8_t keyboard_keys[6];
extern uint8_t keyboard_protocol;
extern uint8_t keyboard_idle_config;
extern uint8_t keyboard_idle_count;
extern volatile uint8_t keyboard_leds;
#endif


#endif

+ 38
- 31
Output/pjrcUSB/arm/usb_mem.c View File

@@ -1,6 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modifications by Jacob Alexander (2013-2014)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -10,10 +11,10 @@
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
@@ -28,68 +29,78 @@
* SOFTWARE.
*/

// ----- Includes -----

// Project Includes
#include <Lib/OutputLib.h>

// Local Includes
#include "usb_dev.h"
#include "usb_mem.h"



// ----- Variables -----

__attribute__ ((section(".usbbuffers"), used))
unsigned char usb_buffer_memory[NUM_USB_BUFFERS * sizeof(usb_packet_t)];
unsigned char usb_buffer_memory[ NUM_USB_BUFFERS * sizeof(usb_packet_t) ];

static uint32_t usb_buffer_available = 0xFFFFFFFF;



// ----- Externs -----

extern void usb_rx_memory( usb_packet_t *packet );

// for the receive endpoints to request memory
extern uint8_t usb_rx_memory_needed;



// ----- Functions -----

// use bitmask and CLZ instruction to implement fast free list
// http://www.archivum.info/gnu.gcc.help/2006-08/00148/Re-GCC-Inline-Assembly.html
// http://gcc.gnu.org/ml/gcc/2012-06/msg00015.html
// __builtin_clz()

usb_packet_t * usb_malloc(void)
usb_packet_t *usb_malloc()
{
unsigned int n, avail;
uint8_t *p;

__disable_irq();
avail = usb_buffer_available;
n = __builtin_clz(avail); // clz = count leading zeros
if (n >= NUM_USB_BUFFERS) {
n = __builtin_clz( avail ); // clz = count leading zeros
if ( n >= NUM_USB_BUFFERS )
{
__enable_irq();
return NULL;
}
//serial_print("malloc:");
//serial_phex(n);
//serial_print("\n");

usb_buffer_available = avail & ~(0x80000000 >> n);
__enable_irq();
p = usb_buffer_memory + (n * sizeof(usb_packet_t));
//serial_print("malloc:");
//serial_phex32((int)p);
//serial_print("\n");
p = usb_buffer_memory + ( n * sizeof(usb_packet_t) );
*(uint32_t *)p = 0;
*(uint32_t *)(p + 4) = 0;
return (usb_packet_t *)p;
}

// for the receive endpoints to request memory
extern uint8_t usb_rx_memory_needed;
extern void usb_rx_memory(usb_packet_t *packet);

void usb_free(usb_packet_t *p)
void usb_free( usb_packet_t *p )
{
unsigned int n, mask;

//serial_print("free:");
n = ((uint8_t *)p - usb_buffer_memory) / sizeof(usb_packet_t);
if (n >= NUM_USB_BUFFERS) return;
//serial_phex(n);
//serial_print("\n");
n = ( (uint8_t *)p - usb_buffer_memory ) / sizeof(usb_packet_t);
if ( n >= NUM_USB_BUFFERS )
return;

// if any endpoints are starving for memory to receive
// packets, give this memory to them immediately!
if (usb_rx_memory_needed && usb_configuration) {
//serial_print("give to rx:");
//serial_phex32((int)p);
//serial_print("\n");
usb_rx_memory(p);
if ( usb_rx_memory_needed && usb_configuration )
{
usb_rx_memory( p );
return;
}

@@ -97,9 +108,5 @@ void usb_free(usb_packet_t *p)
__disable_irq();
usb_buffer_available |= mask;
__enable_irq();

//serial_print("free:");
//serial_phex32((int)p);
//serial_print("\n");
}


+ 16
- 2
Output/pjrcUSB/arm/usb_mem.h View File

@@ -1,6 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modifications by Jacob Alexander (2013-2014)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -31,8 +32,15 @@
#ifndef _usb_mem_h_
#define _usb_mem_h_

// ----- Includes -----

// Compiler Includes
#include <stdint.h>



// ----- Structs -----

typedef struct usb_packet_struct {
uint16_t len;
uint16_t index;
@@ -40,8 +48,14 @@ typedef struct usb_packet_struct {
uint8_t buf[64];
} usb_packet_t;

usb_packet_t * usb_malloc(void);
void usb_free(usb_packet_t *p);


// ----- Functions -----

usb_packet_t *usb_malloc();
void usb_free( usb_packet_t *p );



#endif


+ 163
- 106
Output/pjrcUSB/arm/usb_serial.c View File

@@ -29,93 +29,150 @@
* SOFTWARE.
*/

// ----- Includes -----

// Compiler Includes
#include <string.h> // For memcpy

// Project Includes
#include <Lib/OutputLib.h>

// Local Includes
#include "usb_dev.h"
#include "usb_serial.h"
#include <Lib/OutputLib.h>
#include <string.h> // For memcpy

// defined by usb_dev.h -> usb_desc.h
#if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)

uint32_t usb_cdc_line_coding[2];
volatile uint8_t usb_cdc_line_rtsdtr=0;
volatile uint8_t usb_cdc_transmit_flush_timer=0;

static usb_packet_t *rx_packet=NULL;
static usb_packet_t *tx_packet=NULL;
static volatile uint8_t tx_noautoflush=0;
// ----- Defines -----

#define TRANSMIT_FLUSH_TIMEOUT 5 /* in milliseconds */

// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
#define TX_PACKET_LIMIT 8

// When the PC isn't listening, how long do we wait before discarding data? If this is
// too short, we risk losing data during the stalls that are common with ordinary desktop
// software. If it's too long, we stall the user's program when no software is running.
#define TX_TIMEOUT_MSEC 70

#if F_CPU == 96000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
#elif F_CPU == 48000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
#elif F_CPU == 24000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
#endif



// ----- Variables -----

// serial port settings (baud rate, control signals, etc) set
// by the PC. These are ignored, but kept in RAM.
volatile uint8_t usb_cdc_line_coding[7] = { 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x08 };
volatile uint8_t usb_cdc_line_rtsdtr = 0;
volatile uint8_t usb_cdc_transmit_flush_timer = 0;

static usb_packet_t *rx_packet = NULL;
static usb_packet_t *tx_packet = NULL;
static volatile uint8_t tx_noautoflush = 0;

// When we've suffered the transmit timeout, don't wait again until the computer
// begins accepting data. If no software is running to receive, we'll just discard
// data as rapidly as Serial.print() can generate it, until there's something to
// actually receive it.
static uint8_t transmit_previous_timeout = 0;



// ----- Functions -----

// get the next character, or -1 if nothing received
int usb_serial_getchar(void)
int usb_serial_getchar()
{
unsigned int i;
int c;

if (!rx_packet) {
if (!usb_configuration) return -1;
rx_packet = usb_rx(CDC_RX_ENDPOINT);
if (!rx_packet) return -1;
if ( !rx_packet )
{
if ( !usb_configuration )
return -1;
rx_packet = usb_rx( CDC_RX_ENDPOINT );
if ( !rx_packet )
return -1;
}
i = rx_packet->index;
c = rx_packet->buf[i++];
if (i >= rx_packet->len) {
usb_free(rx_packet);
if ( i >= rx_packet->len )
{
usb_free( rx_packet );
rx_packet = NULL;
} else {
}
else
{
rx_packet->index = i;
}
return c;
}

// peek at the next character, or -1 if nothing received
int usb_serial_peekchar(void)
int usb_serial_peekchar()
{
if (!rx_packet) {
if (!usb_configuration) return -1;
rx_packet = usb_rx(CDC_RX_ENDPOINT);
if (!rx_packet) return -1;
if ( !rx_packet )
{
if ( !usb_configuration )
return -1;
rx_packet = usb_rx( CDC_RX_ENDPOINT );
if ( !rx_packet )
return -1;
}
if (!rx_packet) return -1;
return rx_packet->buf[rx_packet->index];
if ( !rx_packet )
return -1;
return rx_packet->buf[ rx_packet->index ];
}

// number of bytes available in the receive buffer
int usb_serial_available(void)
int usb_serial_available()
{
int count;
count = usb_rx_byte_count(CDC_RX_ENDPOINT);
if (rx_packet) count += rx_packet->len - rx_packet->index;
int count = usb_rx_byte_count( CDC_RX_ENDPOINT );
if ( rx_packet )
count += rx_packet->len - rx_packet->index;
return count;
}

// read a block of bytes to a buffer
int usb_serial_read(void *buffer, uint32_t size)
int usb_serial_read( void *buffer, uint32_t size )
{
uint8_t *p = (uint8_t *)buffer;
uint32_t qty, count=0;

while (size) {
if (!usb_configuration) break;
if (!rx_packet) {
while ( size )
{
if ( !usb_configuration )
break;
if ( !rx_packet )
{
rx:
rx_packet = usb_rx(CDC_RX_ENDPOINT);
if (!rx_packet) break;
if (rx_packet->len == 0) {
usb_free(rx_packet);
goto rx;
}
rx_packet = usb_rx(CDC_RX_ENDPOINT);
if ( !rx_packet )
break;
if ( rx_packet->len == 0 )
{
usb_free(rx_packet);
goto rx;
}
}
qty = rx_packet->len - rx_packet->index;
if (qty > size) qty = size;
memcpy(p, rx_packet->buf + rx_packet->index, qty);
if ( qty > size )
qty = size;
memcpy( p, rx_packet->buf + rx_packet->index, qty );
p += qty;
count += qty;
size -= qty;
rx_packet->index += qty;
if (rx_packet->index >= rx_packet->len) {
usb_free(rx_packet);
if ( rx_packet->index >= rx_packet->len )
{
usb_free( rx_packet );
rx_packet = NULL;
}
}
@@ -123,53 +180,33 @@ int usb_serial_read(void *buffer, uint32_t size)
}

// discard any buffered input
void usb_serial_flush_input(void)
void usb_serial_flush_input()
{
usb_packet_t *rx;

if (!usb_configuration) return;
if (rx_packet) {
usb_free(rx_packet);
if ( !usb_configuration )
return;
if ( rx_packet )
{
usb_free( rx_packet );
rx_packet = NULL;
}
while (1) {
rx = usb_rx(CDC_RX_ENDPOINT);
if (!rx) break;
usb_free(rx);
while (1)
{
rx = usb_rx( CDC_RX_ENDPOINT );
if ( !rx )
break;
usb_free( rx );
}
}

// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
#define TX_PACKET_LIMIT 8

// When the PC isn't listening, how long do we wait before discarding data? If this is
// too short, we risk losing data during the stalls that are common with ordinary desktop
// software. If it's too long, we stall the user's program when no software is running.
#define TX_TIMEOUT_MSEC 70

#if F_CPU == 96000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596)
#elif F_CPU == 48000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428)
#elif F_CPU == 24000000
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262)
#endif

// When we've suffered the transmit timeout, don't wait again until the computer
// begins accepting data. If no software is running to receive, we'll just discard
// data as rapidly as Serial.print() can generate it, until there's something to
// actually receive it.
static uint8_t transmit_previous_timeout=0;


// transmit a character. 0 returned on success, -1 on error
int usb_serial_putchar(uint8_t c)
int usb_serial_putchar( uint8_t c )
{
return usb_serial_write(&c, 1);
return usb_serial_write( &c, 1 );
}


int usb_serial_write(const void *buffer, uint32_t size)
int usb_serial_write( const void *buffer, uint32_t size )
{
uint32_t len;
uint32_t wait_count;
@@ -177,21 +214,28 @@ int usb_serial_write(const void *buffer, uint32_t size)
uint8_t *dest;

tx_noautoflush = 1;
while (size > 0) {
if (!tx_packet) {
while ( size > 0 )
{
if ( !tx_packet )
{
wait_count = 0;
while (1) {
if (!usb_configuration) {
while ( 1 )
{
if ( !usb_configuration )
{
tx_noautoflush = 0;
return -1;
}
if (usb_tx_packet_count(CDC_TX_ENDPOINT) < TX_PACKET_LIMIT) {
if ( usb_tx_packet_count( CDC_TX_ENDPOINT ) < TX_PACKET_LIMIT )
{
tx_noautoflush = 1;
tx_packet = usb_malloc();
if (tx_packet) break;
if ( tx_packet )
break;
tx_noautoflush = 0;
}
if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) {
if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout )
{
transmit_previous_timeout = 1;
return -1;
}
@@ -200,14 +244,17 @@ int usb_serial_write(const void *buffer, uint32_t size)
}
transmit_previous_timeout = 0;
len = CDC_TX_SIZE - tx_packet->index;
if (len > size) len = size;
if ( len > size )
len = size;
dest = tx_packet->buf + tx_packet->index;
tx_packet->index += len;
size -= len;
while (len-- > 0) *dest++ = *src++;
if (tx_packet->index >= CDC_TX_SIZE) {
while ( len-- > 0 )
*dest++ = *src++;
if ( tx_packet->index >= CDC_TX_SIZE )
{
tx_packet->len = CDC_TX_SIZE;
usb_tx(CDC_TX_ENDPOINT, tx_packet);
usb_tx( CDC_TX_ENDPOINT, tx_packet );
tx_packet = NULL;
}
usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT;
@@ -216,43 +263,53 @@ int usb_serial_write(const void *buffer, uint32_t size)
return 0;
}

void usb_serial_flush_output(void)
void usb_serial_flush_output()
{
if (!usb_configuration) return;
if ( !usb_configuration )
return;
tx_noautoflush = 1;
if (tx_packet) {
if ( tx_packet )
{
usb_cdc_transmit_flush_timer = 0;
tx_packet->len = tx_packet->index;
usb_tx(CDC_TX_ENDPOINT, tx_packet);
usb_tx( CDC_TX_ENDPOINT, tx_packet );
tx_packet = NULL;
} else {
}
else
{
usb_packet_t *tx = usb_malloc();
if (tx) {
if ( tx )
{
usb_cdc_transmit_flush_timer = 0;
usb_tx(CDC_TX_ENDPOINT, tx);
} else {
usb_tx( CDC_TX_ENDPOINT, tx );
}
else
{
usb_cdc_transmit_flush_timer = 1;
}
}
tx_noautoflush = 0;
}

void usb_serial_flush_callback(void)
void usb_serial_flush_callback()
{
if (tx_noautoflush) return;
if (tx_packet) {
if ( tx_noautoflush )
return;
if ( tx_packet )
{
tx_packet->len = tx_packet->index;
usb_tx(CDC_TX_ENDPOINT, tx_packet);
usb_tx( CDC_TX_ENDPOINT, tx_packet );
tx_packet = NULL;
} else {
usb_packet_t *tx = usb_malloc();
if (tx) {
usb_tx(CDC_TX_ENDPOINT, tx);
} else {
if ( tx )
{
usb_tx( CDC_TX_ENDPOINT, tx );
}
else
{
usb_cdc_transmit_flush_timer = 1;
}
}
}

#endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE


+ 31
- 11
Output/pjrcUSB/arm/usb_serial.h View File

@@ -1,6 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modifications by Jacob Alexander (2013-2014)
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -31,29 +32,48 @@
#ifndef USBserial_h_
#define USBserial_h_

// ----- Includes -----

// Compiler Includes
#include <inttypes.h>



// ----- Defines -----

// Compatibility defines from AVR
#define PROGMEM
#define PGM_P const char *
#define PSTR(str) (str)

#define USB_SERIAL_DTR 0x01
#define USB_SERIAL_RTS 0x02



// ----- Variables -----

extern volatile uint8_t usb_cdc_line_coding[7];

int usb_serial_getchar(void);
int usb_serial_peekchar(void);
int usb_serial_available(void);
int usb_serial_read(void *buffer, uint32_t size);
void usb_serial_flush_input(void);
int usb_serial_putchar(uint8_t c);
int usb_serial_write(const void *buffer, uint32_t size);
void usb_serial_flush_output(void);
extern uint32_t usb_cdc_line_coding[2];
extern volatile uint8_t usb_cdc_line_rtsdtr;
extern volatile uint8_t usb_cdc_transmit_flush_timer;
extern volatile uint8_t usb_configuration;

#define USB_SERIAL_DTR 0x01
#define USB_SERIAL_RTS 0x02


// ----- Functions -----

int usb_serial_available();
int usb_serial_getchar();
int usb_serial_peekchar();
int usb_serial_putchar( uint8_t c );
int usb_serial_read( void *buffer, uint32_t size );
int usb_serial_write( const void *buffer, uint32_t size );

void usb_serial_flush_input();
void usb_serial_flush_output();



#endif // USBserial_h_