Add support for a dual serial port configuration (USB_DUAL_SERIAL), providing a composite USB device, comprised of two serial ports. The second serial port is called usb_serial2 (C) or SerialA (C++). Note that no dummy C++ class is created if USB_DISABLED is defined, unlike for the first port. This increases binary size by ca. 1.2 KiB (720 bytes for USB buffers). Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>teensy4-core
#include "avr_emulation.h" | #include "avr_emulation.h" | ||||
#include "usb_serial.h" | #include "usb_serial.h" | ||||
#include "usb_serial2.h" | |||||
#include "usb_seremu.h" | #include "usb_seremu.h" | ||||
#include "usb_keyboard.h" | #include "usb_keyboard.h" | ||||
#include "usb_mouse.h" | #include "usb_mouse.h" |
#define CDC_DATA_INTERFACE_DESC_SIZE 0 | #define CDC_DATA_INTERFACE_DESC_SIZE 0 | ||||
#endif | #endif | ||||
#define MIDI_INTERFACE_DESC_POS CDC_DATA_INTERFACE_DESC_POS+CDC_DATA_INTERFACE_DESC_SIZE | |||||
#define CDC2_DATA_INTERFACE_DESC_POS CDC_DATA_INTERFACE_DESC_POS+CDC_DATA_INTERFACE_DESC_SIZE | |||||
#ifdef CDC2_DATA_INTERFACE | |||||
#define CDC2_DATA_INTERFACE_DESC_SIZE 8 + 9+5+5+4+5+7+9+7+7 | |||||
#else | |||||
#define CDC2_DATA_INTERFACE_DESC_SIZE 0 | |||||
#endif | |||||
#define MIDI_INTERFACE_DESC_POS CDC2_DATA_INTERFACE_DESC_POS+CDC2_DATA_INTERFACE_DESC_SIZE | |||||
#ifdef MIDI_INTERFACE | #ifdef MIDI_INTERFACE | ||||
#if !defined(MIDI_NUM_CABLES) || MIDI_NUM_CABLES < 1 || MIDI_NUM_CABLES > 16 | #if !defined(MIDI_NUM_CABLES) || MIDI_NUM_CABLES < 1 || MIDI_NUM_CABLES > 16 | ||||
#error "MIDI_NUM_CABLES must be defined between 1 to 16" | #error "MIDI_NUM_CABLES must be defined between 1 to 16" | ||||
EMIT_CDC_DESCRIPTORS(CDC), | EMIT_CDC_DESCRIPTORS(CDC), | ||||
#endif // CDC_DATA_INTERFACE | #endif // CDC_DATA_INTERFACE | ||||
#ifdef CDC2_DATA_INTERFACE | |||||
EMIT_CDC_IAD_DESCRIPTOR(CDC2), | |||||
EMIT_CDC_DESCRIPTORS(CDC2), | |||||
#endif // CDC2_DATA_INTERFACE | |||||
#ifdef MIDI_INTERFACE | #ifdef MIDI_INTERFACE | ||||
// Standard MS Interface Descriptor, | // Standard MS Interface Descriptor, | ||||
9, // bLength | 9, // bLength |
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY | #define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY | ||||
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY | #define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY | ||||
#elif defined(USB_DUAL_SERIAL) | |||||
#define VENDOR_ID 0x16C0 | |||||
#define PRODUCT_ID 0x0483 | |||||
#define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'} | |||||
#define MANUFACTURER_NAME_LEN 11 | |||||
#define PRODUCT_NAME {'D','u','a','l',' ','S','e','r','i','a','l'} | |||||
#define PRODUCT_NAME_LEN 11 | |||||
#define EP0_SIZE 64 | |||||
#define NUM_ENDPOINTS 7 | |||||
#define NUM_USB_BUFFERS 22 | |||||
#define NUM_INTERFACE 4 | |||||
#define CDC_IAD_DESCRIPTOR 1 // Serial | |||||
#define CDC_STATUS_INTERFACE 0 | |||||
#define CDC_DATA_INTERFACE 1 | |||||
#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 CDC2_STATUS_INTERFACE 2 // SerialA | |||||
#define CDC2_DATA_INTERFACE 3 | |||||
#define CDC2_ACM_ENDPOINT 5 | |||||
#define CDC2_RX_ENDPOINT 6 | |||||
#define CDC2_TX_ENDPOINT 7 | |||||
#define CDC2_ACM_SIZE 16 | |||||
#define CDC2_RX_SIZE 64 | |||||
#define CDC2_TX_SIZE 64 | |||||
#define ENDPOINT2_CONFIG ENDPOINT_TRANSMIT_ONLY | |||||
#define ENDPOINT3_CONFIG ENDPOINT_RECEIVE_ONLY | |||||
#define ENDPOINT4_CONFIG ENDPOINT_TRANSMIT_ONLY | |||||
#define ENDPOINT5_CONFIG ENDPOINT_TRANSMIT_ONLY | |||||
#define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_ONLY | |||||
#define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY | |||||
#elif defined(USB_KEYBOARDONLY) | #elif defined(USB_KEYBOARDONLY) | ||||
#define VENDOR_ID 0x16C0 | #define VENDOR_ID 0x16C0 | ||||
#define PRODUCT_ID 0x04D0 | #define PRODUCT_ID 0x04D0 |
usb_cdc_line_rtsdtr_millis = systick_millis_count; | usb_cdc_line_rtsdtr_millis = systick_millis_count; | ||||
usb_cdc_line_rtsdtr = setup.wValue; | usb_cdc_line_rtsdtr = setup.wValue; | ||||
break; | break; | ||||
#endif | |||||
#ifdef CDC2_STATUS_INTERFACE | |||||
case CDC2_STATUS_INTERFACE: | |||||
usb_cdc2_line_rtsdtr_millis = systick_millis_count; | |||||
usb_cdc2_line_rtsdtr = setup.wValue; | |||||
break; | |||||
#endif | #endif | ||||
} | } | ||||
//serial_print("set control line state\n"); | //serial_print("set control line state\n"); | ||||
case CDC_STATUS_INTERFACE: | case CDC_STATUS_INTERFACE: | ||||
dst = (uint8_t *)usb_cdc_line_coding; | dst = (uint8_t *)usb_cdc_line_coding; | ||||
break; | break; | ||||
#endif | |||||
#ifdef CDC2_STATUS_INTERFACE | |||||
case CDC2_STATUS_INTERFACE: | |||||
dst = (uint8_t *)usb_cdc2_line_coding; | |||||
break; | |||||
#endif | #endif | ||||
} | } | ||||
if (!dst) | if (!dst) | ||||
if (t == 0) usb_serial_flush_callback(); | if (t == 0) usb_serial_flush_callback(); | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef CDC2_DATA_INTERFACE | |||||
t = usb_cdc2_transmit_flush_timer; | |||||
if (t) { | |||||
usb_cdc2_transmit_flush_timer = --t; | |||||
if (t == 0) usb_serial2_flush_callback(); | |||||
} | |||||
#endif | |||||
#ifdef SEREMU_INTERFACE | #ifdef SEREMU_INTERFACE | ||||
t = usb_seremu_transmit_flush_timer; | t = usb_seremu_transmit_flush_timer; | ||||
if (t) { | if (t) { |
#include "usb_serial.h" | #include "usb_serial.h" | ||||
#endif | #endif | ||||
#ifdef CDC2_DATA_INTERFACE | |||||
#include "usb_serial2.h" | |||||
#endif | |||||
#else // F_CPU < 20000000 | #else // F_CPU < 20000000 | ||||
#ifdef __cplusplus | #ifdef __cplusplus |
#endif | #endif | ||||
#endif | #endif | ||||
#ifdef CDC2_DATA_INTERFACE | |||||
#ifdef CDC2_STATUS_INTERFACE | |||||
usb_serial2_class SerialA; | |||||
#endif | |||||
#endif | |||||
#ifdef MIDI_INTERFACE | #ifdef MIDI_INTERFACE | ||||
usb_midi_class usbMIDI; | usb_midi_class usbMIDI; | ||||
#endif | #endif | ||||
#else // F_CPU < 20 MHz | #else // F_CPU < 20 MHz | ||||
#if defined(USB_SERIAL) || defined(USB_SERIAL_HID) | |||||
#if defined(USB_SERIAL) || defined(USB_DUAL_SERIAL) || defined(USB_SERIAL_HID) | |||||
usb_serial_class Serial; | usb_serial_class Serial; | ||||
#elif (USB_DISABLED) | #elif (USB_DISABLED) | ||||
usb_serial_class Serial; | usb_serial_class Serial; | ||||
void serialEvent() __attribute__((weak)); | void serialEvent() __attribute__((weak)); | ||||
void serialEvent() {} | void serialEvent() {} | ||||
void serialEventA() __attribute__((weak)); | |||||
void serialEventA() {} |
/* Teensyduino Core Library | |||||
* http://www.pjrc.com/teensy/ | |||||
* Copyright (c) 2017 PJRC.COM, LLC. | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining | |||||
* a copy of this software and associated documentation files (the | |||||
* "Software"), to deal in the Software without restriction, including | |||||
* without limitation the rights to use, copy, modify, merge, publish, | |||||
* distribute, sublicense, and/or sell copies of the Software, and to | |||||
* 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 | |||||
* included in all copies or substantial portions of the Software. | |||||
* | |||||
* 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. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#include "usb_dev.h" | |||||
// defined by usb_dev.h -> usb_desc.h | |||||
#if defined(CDC2_STATUS_INTERFACE) && defined(CDC2_DATA_INTERFACE) | |||||
#if F_CPU >= 20000000 | |||||
#include "usb_serial_port.h" | |||||
struct usb_serial_port usb_serial2_instance = { | |||||
.cdc_rx_endpoint = CDC2_RX_ENDPOINT, | |||||
.cdc_tx_endpoint = CDC2_TX_ENDPOINT, | |||||
.cdc_tx_size = CDC2_TX_SIZE, | |||||
}; | |||||
#endif | |||||
#endif // CDC2_STATUS_INTERFACE && CDC2_DATA_INTERFACE |
/* Teensyduino Core Library | |||||
* http://www.pjrc.com/teensy/ | |||||
* Copyright (c) 2017 PJRC.COM, LLC. | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining | |||||
* a copy of this software and associated documentation files (the | |||||
* "Software"), to deal in the Software without restriction, including | |||||
* without limitation the rights to use, copy, modify, merge, publish, | |||||
* distribute, sublicense, and/or sell copies of the Software, and to | |||||
* 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 | |||||
* included in all copies or substantial portions of the Software. | |||||
* | |||||
* 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. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
*/ | |||||
#ifndef USBserial2_h_ | |||||
#define USBserial2_h_ | |||||
#include "usb_desc.h" | |||||
#if defined(CDC2_STATUS_INTERFACE) && defined(CDC2_DATA_INTERFACE) | |||||
#define USB_SERIAL_SUFFIX 2 | |||||
#define SERIAL_CLASS_SUFFIX A | |||||
#include "usb_serial_template.h" | |||||
#define usb_cdc2_line_coding usb_serial2_instance.cdc_line_coding | |||||
#define usb_cdc2_line_rtsdtr_millis usb_serial2_instance.cdc_line_rtsdtr_millis | |||||
#define usb_cdc2_line_rtsdtr usb_serial2_instance.cdc_line_rtsdtr | |||||
#define usb_cdc2_transmit_flush_timer usb_serial2_instance.cdc_transmit_flush_timer | |||||
#endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE | |||||
#endif // USBserial2_h_ |
#ifdef CDC_TX_SIZE | #ifdef CDC_TX_SIZE | ||||
#undef CDC_TX_SIZE | #undef CDC_TX_SIZE | ||||
#endif | #endif | ||||
#ifdef CDC2_STATUS_INTERFACE | |||||
#undef CDC2_STATUS_INTERFACE | |||||
#endif | |||||
#ifdef CDC2_DATA_INTERFACE | |||||
#undef CDC2_DATA_INTERFACE | |||||
#endif | |||||
#ifdef CDC2_ACM_ENDPOINT | |||||
#undef CDC2_ACM_ENDPOINT | |||||
#endif | |||||
#ifdef CDC2_RX_ENDPOINT | |||||
#undef CDC2_RX_ENDPOINT | |||||
#endif | |||||
#ifdef CDC2_TX_ENDPOINT | |||||
#undef CDC2_TX_ENDPOINT | |||||
#endif | |||||
#ifdef CDC2_ACM_SIZE | |||||
#undef CDC2_ACM_SIZE | |||||
#endif | |||||
#ifdef CDC2_RX_SIZE | |||||
#undef CDC2_RX_SIZE | |||||
#endif | |||||
#ifdef CDC2_TX_SIZE | |||||
#undef CDC2_TX_SIZE | |||||
#endif | |||||
#ifdef SEREMU_INTERFACE | #ifdef SEREMU_INTERFACE | ||||
#undef SEREMU_INTERFACE | #undef SEREMU_INTERFACE | ||||
#endif | #endif |
if (running) return; // TODO: does this need to be atomic? | if (running) return; // TODO: does this need to be atomic? | ||||
running = 1; | running = 1; | ||||
if (Serial.available()) serialEvent(); | if (Serial.available()) serialEvent(); | ||||
#ifdef USB_DUAL_SERIAL | |||||
if (SerialA.available()) serialEventA(); | |||||
#endif | |||||
if (Serial1.available()) serialEvent1(); | if (Serial1.available()) serialEvent1(); | ||||
if (Serial2.available()) serialEvent2(); | if (Serial2.available()) serialEvent2(); | ||||
if (Serial3.available()) serialEvent3(); | if (Serial3.available()) serialEvent3(); |