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)
This commit is contained in:
parent
55892cedc1
commit
4255a99fcc
@ -29,56 +29,31 @@
|
||||
* 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.
|
||||
|
||||
|
||||
|
||||
// **************************************************************
|
||||
// USB Device
|
||||
// **************************************************************
|
||||
// ----- Macros -----
|
||||
|
||||
#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.
|
||||
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
|
||||
};
|
||||
#endif
|
||||
// Keyboard Collection
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x06, // Usage (Keyboard),
|
||||
0xA1, 0x01, // Collection (Application) - Keyboard,
|
||||
|
||||
#ifdef MOUSE_INTERFACE
|
||||
// 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
|
||||
};
|
||||
|
||||
/* 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)
|
||||
|
@ -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"
|
||||
|
||||
// Local Includes
|
||||
#include <output_com.h>
|
||||
|
||||
|
||||
|
||||
// ----- Defines -----
|
||||
|
||||
#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?)
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#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 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_ACM_SIZE 16
|
||||
#define CDC_RX_SIZE 64
|
||||
#define CDC_TX_SIZE 64
|
||||
|
||||
#define KEYBOARD_INTERFACE 2 // Keyboard
|
||||
#define KEYBOARD_INTERFACE 0 // Keyboard
|
||||
#define KEYBOARD_ENDPOINT 1
|
||||
#define KEYBOARD_SIZE 8
|
||||
#define KEYBOARD_INTERVAL 1
|
||||
|
||||
#define MOUSE_INTERFACE 3 // Mouse
|
||||
#define MOUSE_ENDPOINT 5
|
||||
#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 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 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[];
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -29,116 +29,24 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "usb_dev.h"
|
||||
#include "usb_serial.h"
|
||||
#include <Lib/OutputLib.h>
|
||||
// ----- Includes -----
|
||||
|
||||
// Compiler Includes
|
||||
#include <string.h> // For memcpy
|
||||
|
||||
// defined by usb_dev.h -> usb_desc.h
|
||||
#if defined(CDC_STATUS_INTERFACE) && defined(CDC_DATA_INTERFACE)
|
||||
// Project Includes
|
||||
#include <Lib/OutputLib.h>
|
||||
|
||||
uint32_t usb_cdc_line_coding[2];
|
||||
volatile uint8_t usb_cdc_line_rtsdtr=0;
|
||||
volatile uint8_t usb_cdc_transmit_flush_timer=0;
|
||||
// Local Includes
|
||||
#include "usb_dev.h"
|
||||
#include "usb_serial.h"
|
||||
|
||||
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 */
|
||||
|
||||
// get the next character, or -1 if nothing received
|
||||
int usb_serial_getchar(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
i = rx_packet->index;
|
||||
c = rx_packet->buf[i++];
|
||||
if (i >= rx_packet->len) {
|
||||
usb_free(rx_packet);
|
||||
rx_packet = NULL;
|
||||
} else {
|
||||
rx_packet->index = i;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// peek at the next character, or -1 if nothing received
|
||||
int usb_serial_peekchar(void)
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
// number of bytes available in the receive buffer
|
||||
int usb_serial_available(void)
|
||||
{
|
||||
int count;
|
||||
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)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)buffer;
|
||||
uint32_t qty, count=0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
qty = rx_packet->len - rx_packet->index;
|
||||
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);
|
||||
rx_packet = NULL;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// discard any buffered input
|
||||
void usb_serial_flush_input(void)
|
||||
{
|
||||
usb_packet_t *rx;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum number of transmit packets to queue so we don't starve other endpoints for memory
|
||||
#define TX_PACKET_LIMIT 8
|
||||
|
||||
@ -155,21 +63,150 @@ void usb_serial_flush_input(void)
|
||||
#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;
|
||||
static uint8_t transmit_previous_timeout = 0;
|
||||
|
||||
|
||||
// transmit a character. 0 returned on success, -1 on error
|
||||
int usb_serial_putchar(uint8_t c)
|
||||
|
||||
// ----- Functions -----
|
||||
|
||||
// get the next character, or -1 if nothing received
|
||||
int usb_serial_getchar()
|
||||
{
|
||||
return usb_serial_write(&c, 1);
|
||||
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;
|
||||
}
|
||||
i = rx_packet->index;
|
||||
c = rx_packet->buf[i++];
|
||||
if ( i >= rx_packet->len )
|
||||
{
|
||||
usb_free( rx_packet );
|
||||
rx_packet = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
rx_packet->index = i;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// peek at the next character, or -1 if nothing received
|
||||
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 )
|
||||
return -1;
|
||||
return rx_packet->buf[ rx_packet->index ];
|
||||
}
|
||||
|
||||
int usb_serial_write(const void *buffer, uint32_t size)
|
||||
// number of bytes available in the receive buffer
|
||||
int usb_serial_available()
|
||||
{
|
||||
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 )
|
||||
{
|
||||
uint8_t *p = (uint8_t *)buffer;
|
||||
uint32_t qty, count=0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
qty = rx_packet->len - rx_packet->index;
|
||||
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 );
|
||||
rx_packet = NULL;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// discard any buffered input
|
||||
void usb_serial_flush_input()
|
||||
{
|
||||
usb_packet_t *rx;
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
// transmit a character. 0 returned on success, -1 on error
|
||||
int usb_serial_putchar( uint8_t c )
|
||||
{
|
||||
return usb_serial_write( &c, 1 );
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
@ -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_
|
||||
|
||||
|
Reference in New Issue
Block a user