- Added NKRO descriptor - Added NKRO HID descriptor - Updated boot HID descriptor - Fixed many bugs with the pjrc ARM usb stack (with USB HID)simple
* SOFTWARE. | * SOFTWARE. | ||||
*/ | */ | ||||
// ----- Includes ----- | |||||
// Local Includes | |||||
#include "usb_desc.h" | #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 | // USB Device Descriptor. The USB host reads this first, to learn | ||||
// what type of device is connected. | // what type of device is connected. | ||||
18, // bLength | 18, // bLength | ||||
1, // bDescriptorType | 1, // bDescriptorType | ||||
0x00, 0x02, // bcdUSB | 0x00, 0x02, // bcdUSB | ||||
#ifdef DEVICE_CLASS | |||||
DEVICE_CLASS, // bDeviceClass | DEVICE_CLASS, // bDeviceClass | ||||
#else | |||||
0, | |||||
#endif | |||||
#ifdef DEVICE_SUBCLASS | |||||
DEVICE_SUBCLASS, // bDeviceSubClass | DEVICE_SUBCLASS, // bDeviceSubClass | ||||
#else | |||||
0, | |||||
#endif | |||||
#ifdef DEVICE_PROTOCOL | |||||
DEVICE_PROTOCOL, // bDeviceProtocol | DEVICE_PROTOCOL, // bDeviceProtocol | ||||
#else | |||||
0, | |||||
#endif | |||||
EP0_SIZE, // bMaxPacketSize0 | EP0_SIZE, // bMaxPacketSize0 | ||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor | ||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct | ||||
1 // bNumConfigurations | 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 | // These descriptors must NOT be "const", because the USB DMA | ||||
// has trouble accessing flash memory with enough bandwidth | // has trouble accessing flash memory with enough bandwidth | ||||
// while the processor is executing from flash. | // 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 | // Each HID interface needs a special report descriptor that tells | ||||
// the meaning and format of the data. | // the meaning and format of the data. | ||||
#ifdef KEYBOARD_INTERFACE | |||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | // Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 | ||||
static uint8_t keyboard_report_desc[] = { | 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 | // Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension | ||||
static uint8_t mouse_report_desc[] = { | static uint8_t mouse_report_desc[] = { | ||||
0x05, 0x01, // Usage Page (Generic Desktop) | 0x05, 0x01, // Usage Page (Generic Desktop) | ||||
0x81, 0x06, // Input (Data, Variable, Relative) | 0x81, 0x06, // Input (Data, Variable, Relative) | ||||
0xC0 // End Collection | 0xC0 // End Collection | ||||
}; | }; | ||||
#endif | |||||
*/ | |||||
// ************************************************************** | |||||
// USB Configuration | |||||
// ************************************************************** | |||||
// ----- USB Configuration ----- | |||||
// USB Configuration Descriptor. This huge descriptor tells all | // USB Configuration Descriptor. This huge descriptor tells all | ||||
// of the devices capbilities. | // of the devices capbilities. | ||||
static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { | static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { | ||||
// --- Configuration --- | |||||
// - 9 bytes - | |||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | ||||
9, // bLength; | 9, // bLength; | ||||
2, // bDescriptorType; | 2, // bDescriptorType; | ||||
LSB(CONFIG_DESC_SIZE), // wTotalLength | |||||
LSB(CONFIG_DESC_SIZE), // wTotalLength | |||||
MSB(CONFIG_DESC_SIZE), | MSB(CONFIG_DESC_SIZE), | ||||
NUM_INTERFACE, // bNumInterfaces | NUM_INTERFACE, // bNumInterfaces | ||||
1, // bConfigurationValue | 1, // bConfigurationValue | ||||
0, // iConfiguration | 0, // iConfiguration | ||||
0xC0, // bmAttributes | 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 | // interface association descriptor, USB ECN, Table 9-Z | ||||
8, // bLength | 8, // bLength | ||||
11, // bDescriptorType | 11, // bDescriptorType | ||||
0x02, // bFunctionSubClass | 0x02, // bFunctionSubClass | ||||
0x01, // bFunctionProtocol | 0x01, // bFunctionProtocol | ||||
4, // iFunction | 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 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||||
9, // bLength | 9, // bLength | ||||
4, // bDescriptorType | 4, // bDescriptorType | ||||
0x02, // bInterfaceSubClass | 0x02, // bInterfaceSubClass | ||||
0x01, // bInterfaceProtocol | 0x01, // bInterfaceProtocol | ||||
0, // iInterface | 0, // iInterface | ||||
// - 5 bytes - | |||||
// CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 | // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 | ||||
5, // bFunctionLength | 5, // bFunctionLength | ||||
0x24, // bDescriptorType | 0x24, // bDescriptorType | ||||
0x00, // bDescriptorSubtype | 0x00, // bDescriptorSubtype | ||||
0x10, 0x01, // bcdCDC | 0x10, 0x01, // bcdCDC | ||||
// - 5 bytes - | |||||
// Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 | // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 | ||||
5, // bFunctionLength | 5, // bFunctionLength | ||||
0x24, // bDescriptorType | 0x24, // bDescriptorType | ||||
0x01, // bDescriptorSubtype | 0x01, // bDescriptorSubtype | ||||
0x01, // bmCapabilities | 0x01, // bmCapabilities | ||||
1, // bDataInterface | 1, // bDataInterface | ||||
// - 4 bytes - | |||||
// Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 | // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 | ||||
4, // bFunctionLength | 4, // bFunctionLength | ||||
0x24, // bDescriptorType | 0x24, // bDescriptorType | ||||
0x02, // bDescriptorSubtype | 0x02, // bDescriptorSubtype | ||||
0x06, // bmCapabilities | 0x06, // bmCapabilities | ||||
// - 5 bytes - | |||||
// Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 | // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 | ||||
5, // bFunctionLength | 5, // bFunctionLength | ||||
0x24, // bDescriptorType | 0x24, // bDescriptorType | ||||
0x06, // bDescriptorSubtype | 0x06, // bDescriptorSubtype | ||||
CDC_STATUS_INTERFACE, // bMasterInterface | CDC_STATUS_INTERFACE, // bMasterInterface | ||||
CDC_DATA_INTERFACE, // bSlaveInterface0 | CDC_DATA_INTERFACE, // bSlaveInterface0 | ||||
// - 7 bytes - | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | 7, // bLength | ||||
5, // bDescriptorType | 5, // bDescriptorType | ||||
0x03, // bmAttributes (0x03=intr) | 0x03, // bmAttributes (0x03=intr) | ||||
CDC_ACM_SIZE, 0, // wMaxPacketSize | CDC_ACM_SIZE, 0, // wMaxPacketSize | ||||
64, // bInterval | 64, // bInterval | ||||
// - 9 bytes - | |||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||||
9, // bLength | 9, // bLength | ||||
4, // bDescriptorType | 4, // bDescriptorType | ||||
0x00, // bInterfaceSubClass | 0x00, // bInterfaceSubClass | ||||
0x00, // bInterfaceProtocol | 0x00, // bInterfaceProtocol | ||||
0, // iInterface | 0, // iInterface | ||||
// - 7 bytes - | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | 7, // bLength | ||||
5, // bDescriptorType | 5, // bDescriptorType | ||||
0x02, // bmAttributes (0x02=bulk) | 0x02, // bmAttributes (0x02=bulk) | ||||
CDC_RX_SIZE, 0, // wMaxPacketSize | CDC_RX_SIZE, 0, // wMaxPacketSize | ||||
0, // bInterval | 0, // bInterval | ||||
// - 7 bytes - | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | 7, // bLength | ||||
5, // bDescriptorType | 5, // bDescriptorType | ||||
0x02, // bmAttributes (0x02=bulk) | 0x02, // bmAttributes (0x02=bulk) | ||||
CDC_TX_SIZE, 0, // wMaxPacketSize | CDC_TX_SIZE, 0, // wMaxPacketSize | ||||
0, // bInterval | 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 | // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | ||||
9, // bLength | 9, // bLength | ||||
4, // bDescriptorType | 4, // bDescriptorType | ||||
0x00, // bInterfaceSubClass (0x01 = Boot) | 0x00, // bInterfaceSubClass (0x01 = Boot) | ||||
0x00, // bInterfaceProtocol (0x02 = Mouse) | 0x00, // bInterfaceProtocol (0x02 = Mouse) | ||||
0, // iInterface | 0, // iInterface | ||||
// - 9 bytes - | |||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | // HID interface descriptor, HID 1.11 spec, section 6.2.1 | ||||
9, // bLength | 9, // bLength | ||||
0x21, // bDescriptorType | 0x21, // bDescriptorType | ||||
0x22, // bDescriptorType | 0x22, // bDescriptorType | ||||
LSB(sizeof(mouse_report_desc)), // wDescriptorLength | LSB(sizeof(mouse_report_desc)), // wDescriptorLength | ||||
MSB(sizeof(mouse_report_desc)), | MSB(sizeof(mouse_report_desc)), | ||||
// - 7 bytes - | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | ||||
7, // bLength | 7, // bLength | ||||
5, // bDescriptorType | 5, // bDescriptorType | ||||
MOUSE_SIZE, 0, // wMaxPacketSize | MOUSE_SIZE, 0, // wMaxPacketSize | ||||
MOUSE_INTERVAL, // bInterval | MOUSE_INTERVAL, // bInterval | ||||
#endif // MOUSE_INTERFACE | #endif // MOUSE_INTERFACE | ||||
*/ | |||||
}; | }; | ||||
// ************************************************************** | |||||
// String Descriptors | |||||
// ************************************************************** | |||||
// ----- String Descriptors ----- | |||||
// The descriptors above can provide human readable strings, | // The descriptors above can provide human readable strings, | ||||
// referenced by index numbers. These descriptors are the | // referenced by index numbers. These descriptors are the | ||||
}; | }; | ||||
// ************************************************************** | |||||
// Descriptors List | |||||
// ************************************************************** | |||||
// ----- Descriptors List ----- | |||||
// This table provides access to all the descriptor data above. | // This table provides access to all the descriptor data above. | ||||
//wValue, wIndex, address, length | //wValue, wIndex, address, length | ||||
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, | {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, | ||||
{0x0200, 0x0000, config_descriptor, sizeof(config_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)}, | {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)}, | {0x2200, MOUSE_INTERFACE, mouse_report_desc, sizeof(mouse_report_desc)}, | ||||
{0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9}, | {0x2100, MOUSE_INTERFACE, config_descriptor+MOUSE_DESC_OFFSET, 9}, | ||||
#endif | |||||
*/ | |||||
{0x0300, 0x0000, (const uint8_t *)&string0, 0}, | {0x0300, 0x0000, (const uint8_t *)&string0, 0}, | ||||
{0x0301, 0x0409, (const uint8_t *)&usb_string_manufacturer_name, 0}, | {0x0301, 0x0409, (const uint8_t *)&usb_string_manufacturer_name, 0}, | ||||
{0x0302, 0x0409, (const uint8_t *)&usb_string_product_name, 0}, | {0x0302, 0x0409, (const uint8_t *)&usb_string_product_name, 0}, | ||||
}; | }; | ||||
// ************************************************************** | |||||
// Endpoint Configuration | |||||
// ************************************************************** | |||||
#if 0 | |||||
// ----- Endpoint Configuration ----- | |||||
// See usb_desc.h for Endpoint configuration | |||||
// 0x00 = not used | // 0x00 = not used | ||||
// 0x19 = Recieve only | // 0x19 = Recieve only | ||||
// 0x15 = Transmit only | // 0x15 = Transmit only | ||||
// 0x1D = Transmit & Recieve | // 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] = | const uint8_t usb_endpoint_config_table[NUM_ENDPOINTS] = | ||||
{ | { | ||||
#if (defined(ENDPOINT1_CONFIG) && NUM_ENDPOINTS >= 1) | #if (defined(ENDPOINT1_CONFIG) && NUM_ENDPOINTS >= 1) |
#ifndef _usb_desc_h_ | #ifndef _usb_desc_h_ | ||||
#define _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 <stdint.h> | ||||
#include <stddef.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 EP0_SIZE 64 | ||||
#define NUM_ENDPOINTS 6 | |||||
#define NUM_ENDPOINTS 5 | |||||
#define NUM_USB_BUFFERS 30 | #define NUM_USB_BUFFERS 30 | ||||
#define NUM_INTERFACE 4 | #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_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_ACM_SIZE 16 | ||||
#define CDC_RX_SIZE 64 | #define CDC_RX_SIZE 64 | ||||
#define CDC_TX_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_SIZE 8 | ||||
#define MOUSE_INTERVAL 2 | #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_SIZE 16 | ||||
#define JOYSTICK_INTERVAL 1 | #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 ENDPOINT1_CONFIG ENDPOINT_TRANSIMIT_ONLY | ||||
#define ENDPOINT2_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 ENDPOINT5_CONFIG ENDPOINT_TRANSIMIT_ONLY | ||||
#define ENDPOINT6_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 { | typedef struct { | ||||
uint16_t wValue; | uint16_t wValue; | ||||
uint16_t length; | uint16_t length; | ||||
} usb_descriptor_list_t; | } 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[]; | extern const usb_descriptor_list_t usb_descriptor_list[]; | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * 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. | * 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 | * selection among a list of target devices, then similar target | ||||
* devices manufactured by PJRC.COM must be included in the list of | * devices manufactured by PJRC.COM must be included in the list of | ||||
* target devices and selectable in the same manner. | * target devices and selectable in the same manner. | ||||
#ifndef _usb_dev_h_ | #ifndef _usb_dev_h_ | ||||
#define _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_mem.h" | ||||
#include "usb_desc.h" | #include "usb_desc.h" | ||||
// ----- Defines ----- | |||||
#define usb_device_software_reset() SOFTWARE_RESET() | #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 | uint8_t usb_configured(); // is the USB port configured | ||||
void usb_init(); | void usb_init(); | ||||
usb_packet_t *usb_rx( 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) __attribute__((always_inline)); | ||||
static inline uint32_t usb_rx_byte_count(uint32_t endpoint) | static inline uint32_t usb_rx_byte_count(uint32_t endpoint) | ||||
{ | { | ||||
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 | #endif |
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * Copyright (c) 2013 PJRC.COM, LLC. | ||||
* Modifications by Jacob Alexander (2013-2014) | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* permit persons to whom the Software is furnished to do so, subject to | * permit persons to whom the Software is furnished to do so, subject to | ||||
* the following conditions: | * 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. | * 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 | * selection among a list of target devices, then similar target | ||||
* devices manufactured by PJRC.COM must be included in the list of | * devices manufactured by PJRC.COM must be included in the list of | ||||
* target devices and selectable in the same manner. | * target devices and selectable in the same manner. | ||||
* SOFTWARE. | * SOFTWARE. | ||||
*/ | */ | ||||
// ----- Includes ----- | |||||
// Project Includes | |||||
#include <Lib/OutputLib.h> | #include <Lib/OutputLib.h> | ||||
// Local Includes | |||||
#include "usb_dev.h" | #include "usb_dev.h" | ||||
#include "usb_mem.h" | #include "usb_mem.h" | ||||
// ----- Variables ----- | |||||
__attribute__ ((section(".usbbuffers"), used)) | __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; | 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 | // 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://www.archivum.info/gnu.gcc.help/2006-08/00148/Re-GCC-Inline-Assembly.html | ||||
// http://gcc.gnu.org/ml/gcc/2012-06/msg00015.html | // http://gcc.gnu.org/ml/gcc/2012-06/msg00015.html | ||||
// __builtin_clz() | // __builtin_clz() | ||||
usb_packet_t * usb_malloc(void) | |||||
usb_packet_t *usb_malloc() | |||||
{ | { | ||||
unsigned int n, avail; | unsigned int n, avail; | ||||
uint8_t *p; | uint8_t *p; | ||||
__disable_irq(); | __disable_irq(); | ||||
avail = usb_buffer_available; | 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(); | __enable_irq(); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
//serial_print("malloc:"); | |||||
//serial_phex(n); | |||||
//serial_print("\n"); | |||||
usb_buffer_available = avail & ~(0x80000000 >> n); | usb_buffer_available = avail & ~(0x80000000 >> n); | ||||
__enable_irq(); | __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 = 0; | ||||
*(uint32_t *)(p + 4) = 0; | *(uint32_t *)(p + 4) = 0; | ||||
return (usb_packet_t *)p; | 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; | 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 | // if any endpoints are starving for memory to receive | ||||
// packets, give this memory to them immediately! | // 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; | return; | ||||
} | } | ||||
__disable_irq(); | __disable_irq(); | ||||
usb_buffer_available |= mask; | usb_buffer_available |= mask; | ||||
__enable_irq(); | __enable_irq(); | ||||
//serial_print("free:"); | |||||
//serial_phex32((int)p); | |||||
//serial_print("\n"); | |||||
} | } | ||||
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * Copyright (c) 2013 PJRC.COM, LLC. | ||||
* Modifications by Jacob Alexander (2013-2014) | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
#ifndef _usb_mem_h_ | #ifndef _usb_mem_h_ | ||||
#define _usb_mem_h_ | #define _usb_mem_h_ | ||||
// ----- Includes ----- | |||||
// Compiler Includes | |||||
#include <stdint.h> | #include <stdint.h> | ||||
// ----- Structs ----- | |||||
typedef struct usb_packet_struct { | typedef struct usb_packet_struct { | ||||
uint16_t len; | uint16_t len; | ||||
uint16_t index; | uint16_t index; | ||||
uint8_t buf[64]; | uint8_t buf[64]; | ||||
} usb_packet_t; | } 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 | #endif | ||||
* SOFTWARE. | * SOFTWARE. | ||||
*/ | */ | ||||
// ----- Includes ----- | |||||
// Compiler Includes | |||||
#include <string.h> // For memcpy | |||||
// Project Includes | |||||
#include <Lib/OutputLib.h> | |||||
// Local Includes | |||||
#include "usb_dev.h" | #include "usb_dev.h" | ||||
#include "usb_serial.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 */ | #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 | // get the next character, or -1 if nothing received | ||||
int usb_serial_getchar(void) | |||||
int usb_serial_getchar() | |||||
{ | { | ||||
unsigned int i; | unsigned int i; | ||||
int c; | 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; | i = rx_packet->index; | ||||
c = rx_packet->buf[i++]; | 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; | rx_packet = NULL; | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
rx_packet->index = i; | rx_packet->index = i; | ||||
} | } | ||||
return c; | return c; | ||||
} | } | ||||
// peek at the next character, or -1 if nothing received | // 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 | // 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; | return count; | ||||
} | } | ||||
// read a block of bytes to a buffer | // 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; | uint8_t *p = (uint8_t *)buffer; | ||||
uint32_t qty, count=0; | 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: | ||||
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; | 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; | p += qty; | ||||
count += qty; | count += qty; | ||||
size -= qty; | size -= qty; | ||||
rx_packet->index += 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; | rx_packet = NULL; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// discard any buffered input | // discard any buffered input | ||||
void usb_serial_flush_input(void) | |||||
void usb_serial_flush_input() | |||||
{ | { | ||||
usb_packet_t *rx; | 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; | 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 | // 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 len; | ||||
uint32_t wait_count; | uint32_t wait_count; | ||||
uint8_t *dest; | uint8_t *dest; | ||||
tx_noautoflush = 1; | tx_noautoflush = 1; | ||||
while (size > 0) { | |||||
if (!tx_packet) { | |||||
while ( size > 0 ) | |||||
{ | |||||
if ( !tx_packet ) | |||||
{ | |||||
wait_count = 0; | wait_count = 0; | ||||
while (1) { | |||||
if (!usb_configuration) { | |||||
while ( 1 ) | |||||
{ | |||||
if ( !usb_configuration ) | |||||
{ | |||||
tx_noautoflush = 0; | tx_noautoflush = 0; | ||||
return -1; | 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_noautoflush = 1; | ||||
tx_packet = usb_malloc(); | tx_packet = usb_malloc(); | ||||
if (tx_packet) break; | |||||
if ( tx_packet ) | |||||
break; | |||||
tx_noautoflush = 0; | tx_noautoflush = 0; | ||||
} | } | ||||
if (++wait_count > TX_TIMEOUT || transmit_previous_timeout) { | |||||
if ( ++wait_count > TX_TIMEOUT || transmit_previous_timeout ) | |||||
{ | |||||
transmit_previous_timeout = 1; | transmit_previous_timeout = 1; | ||||
return -1; | return -1; | ||||
} | } | ||||
} | } | ||||
transmit_previous_timeout = 0; | transmit_previous_timeout = 0; | ||||
len = CDC_TX_SIZE - tx_packet->index; | len = CDC_TX_SIZE - tx_packet->index; | ||||
if (len > size) len = size; | |||||
if ( len > size ) | |||||
len = size; | |||||
dest = tx_packet->buf + tx_packet->index; | dest = tx_packet->buf + tx_packet->index; | ||||
tx_packet->index += len; | tx_packet->index += len; | ||||
size -= 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; | tx_packet->len = CDC_TX_SIZE; | ||||
usb_tx(CDC_TX_ENDPOINT, tx_packet); | |||||
usb_tx( CDC_TX_ENDPOINT, tx_packet ); | |||||
tx_packet = NULL; | tx_packet = NULL; | ||||
} | } | ||||
usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT; | usb_cdc_transmit_flush_timer = TRANSMIT_FLUSH_TIMEOUT; | ||||
return 0; | return 0; | ||||
} | } | ||||
void usb_serial_flush_output(void) | |||||
void usb_serial_flush_output() | |||||
{ | { | ||||
if (!usb_configuration) return; | |||||
if ( !usb_configuration ) | |||||
return; | |||||
tx_noautoflush = 1; | tx_noautoflush = 1; | ||||
if (tx_packet) { | |||||
if ( tx_packet ) | |||||
{ | |||||
usb_cdc_transmit_flush_timer = 0; | usb_cdc_transmit_flush_timer = 0; | ||||
tx_packet->len = tx_packet->index; | tx_packet->len = tx_packet->index; | ||||
usb_tx(CDC_TX_ENDPOINT, tx_packet); | |||||
usb_tx( CDC_TX_ENDPOINT, tx_packet ); | |||||
tx_packet = NULL; | tx_packet = NULL; | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
usb_packet_t *tx = usb_malloc(); | usb_packet_t *tx = usb_malloc(); | ||||
if (tx) { | |||||
if ( tx ) | |||||
{ | |||||
usb_cdc_transmit_flush_timer = 0; | 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; | usb_cdc_transmit_flush_timer = 1; | ||||
} | } | ||||
} | } | ||||
tx_noautoflush = 0; | 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; | tx_packet->len = tx_packet->index; | ||||
usb_tx(CDC_TX_ENDPOINT, tx_packet); | |||||
usb_tx( CDC_TX_ENDPOINT, tx_packet ); | |||||
tx_packet = NULL; | tx_packet = NULL; | ||||
} else { | } else { | ||||
usb_packet_t *tx = usb_malloc(); | 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; | usb_cdc_transmit_flush_timer = 1; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE | |||||
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * Copyright (c) 2013 PJRC.COM, LLC. | ||||
* Modifications by Jacob Alexander (2013-2014) | |||||
* | * | ||||
* Permission is hereby granted, free of charge, to any person obtaining | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
#ifndef USBserial_h_ | #ifndef USBserial_h_ | ||||
#define USBserial_h_ | #define USBserial_h_ | ||||
// ----- Includes ----- | |||||
// Compiler Includes | |||||
#include <inttypes.h> | #include <inttypes.h> | ||||
// ----- Defines ----- | |||||
// Compatibility defines from AVR | // Compatibility defines from AVR | ||||
#define PROGMEM | #define PROGMEM | ||||
#define PGM_P const char * | #define PGM_P const char * | ||||
#define PSTR(str) (str) | #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_line_rtsdtr; | ||||
extern volatile uint8_t usb_cdc_transmit_flush_timer; | extern volatile uint8_t usb_cdc_transmit_flush_timer; | ||||
extern volatile uint8_t usb_configuration; | 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_ | #endif // USBserial_h_ | ||||