Add support for a triple serial port configuration (USB_TRIPLE_SERIAL), providing a composite USB device, comprised of three serial ports. The third serial port is called usb_serial3 (C) or SerialB (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. 0.5 KiB (despite needing 720 more bytes for USB buffers, as gcc-5.4.1 no longer decides to unroll a loop over all endpoints in usb_isr()). Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>teensy4-core
| @@ -53,6 +53,7 @@ | |||
| #include "avr_emulation.h" | |||
| #include "usb_serial.h" | |||
| #include "usb_serial2.h" | |||
| #include "usb_serial3.h" | |||
| #include "usb_seremu.h" | |||
| #include "usb_keyboard.h" | |||
| #include "usb_mouse.h" | |||
| @@ -491,7 +491,14 @@ static uint8_t flightsim_report_desc[] = { | |||
| #define CDC2_DATA_INTERFACE_DESC_SIZE 0 | |||
| #endif | |||
| #define MIDI_INTERFACE_DESC_POS CDC2_DATA_INTERFACE_DESC_POS+CDC2_DATA_INTERFACE_DESC_SIZE | |||
| #define CDC3_DATA_INTERFACE_DESC_POS CDC2_DATA_INTERFACE_DESC_POS+CDC2_DATA_INTERFACE_DESC_SIZE | |||
| #ifdef CDC3_DATA_INTERFACE | |||
| #define CDC3_DATA_INTERFACE_DESC_SIZE 8 + 9+5+5+4+5+7+9+7+7 | |||
| #else | |||
| #define CDC3_DATA_INTERFACE_DESC_SIZE 0 | |||
| #endif | |||
| #define MIDI_INTERFACE_DESC_POS CDC3_DATA_INTERFACE_DESC_POS+CDC3_DATA_INTERFACE_DESC_SIZE | |||
| #ifdef MIDI_INTERFACE | |||
| #if !defined(MIDI_NUM_CABLES) || MIDI_NUM_CABLES < 1 || MIDI_NUM_CABLES > 16 | |||
| #error "MIDI_NUM_CABLES must be defined between 1 to 16" | |||
| @@ -690,6 +697,11 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { | |||
| EMIT_CDC_DESCRIPTORS(CDC2), | |||
| #endif // CDC2_DATA_INTERFACE | |||
| #ifdef CDC3_DATA_INTERFACE | |||
| EMIT_CDC_IAD_DESCRIPTOR(CDC3), | |||
| EMIT_CDC_DESCRIPTORS(CDC3), | |||
| #endif // CDC3_DATA_INTERFACE | |||
| #ifdef MIDI_INTERFACE | |||
| // Standard MS Interface Descriptor, | |||
| 9, // bLength | |||
| @@ -175,6 +175,52 @@ let me know? http://forum.pjrc.com/forums/4-Suggestions-amp-Bug-Reports | |||
| #define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_ONLY | |||
| #define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
| #elif defined(USB_TRIPLE_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 {'T','r','i','p','l','e',' ','S','e','r','i','a','l'} | |||
| #define PRODUCT_NAME_LEN 13 | |||
| #define EP0_SIZE 64 | |||
| #define NUM_ENDPOINTS 10 | |||
| #define NUM_USB_BUFFERS 32 | |||
| #define NUM_INTERFACE 6 | |||
| #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 CDC3_STATUS_INTERFACE 4 // SerialB | |||
| #define CDC3_DATA_INTERFACE 5 | |||
| #define CDC3_ACM_ENDPOINT 8 | |||
| #define CDC3_RX_ENDPOINT 9 | |||
| #define CDC3_TX_ENDPOINT 10 | |||
| #define CDC3_ACM_SIZE 16 | |||
| #define CDC3_RX_SIZE 64 | |||
| #define CDC3_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 | |||
| #define ENDPOINT8_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
| #define ENDPOINT9_CONFIG ENDPOINT_RECEIVE_ONLY | |||
| #define ENDPOINT10_CONFIG ENDPOINT_TRANSMIT_ONLY | |||
| #elif defined(USB_KEYBOARDONLY) | |||
| #define VENDOR_ID 0x16C0 | |||
| #define PRODUCT_ID 0x04D0 | |||
| @@ -366,6 +366,12 @@ static void usb_setup(void) | |||
| usb_cdc2_line_rtsdtr_millis = systick_millis_count; | |||
| usb_cdc2_line_rtsdtr = setup.wValue; | |||
| break; | |||
| #endif | |||
| #ifdef CDC3_STATUS_INTERFACE | |||
| case CDC3_STATUS_INTERFACE: | |||
| usb_cdc3_line_rtsdtr_millis = systick_millis_count; | |||
| usb_cdc3_line_rtsdtr = setup.wValue; | |||
| break; | |||
| #endif | |||
| } | |||
| //serial_print("set control line state\n"); | |||
| @@ -619,6 +625,11 @@ static void usb_control(uint32_t stat) | |||
| case CDC2_STATUS_INTERFACE: | |||
| dst = (uint8_t *)usb_cdc2_line_coding; | |||
| break; | |||
| #endif | |||
| #ifdef CDC3_STATUS_INTERFACE | |||
| case CDC3_STATUS_INTERFACE: | |||
| dst = (uint8_t *)usb_cdc3_line_coding; | |||
| break; | |||
| #endif | |||
| } | |||
| if (!dst) | |||
| @@ -925,6 +936,13 @@ void usb_isr(void) | |||
| if (t == 0) usb_serial2_flush_callback(); | |||
| } | |||
| #endif | |||
| #ifdef CDC3_DATA_INTERFACE | |||
| t = usb_cdc3_transmit_flush_timer; | |||
| if (t) { | |||
| usb_cdc3_transmit_flush_timer = --t; | |||
| if (t == 0) usb_serial3_flush_callback(); | |||
| } | |||
| #endif | |||
| #ifdef SEREMU_INTERFACE | |||
| t = usb_seremu_transmit_flush_timer; | |||
| if (t) { | |||
| @@ -118,6 +118,10 @@ extern void usb_touchscreen_update_callback(void); | |||
| #include "usb_serial2.h" | |||
| #endif | |||
| #ifdef CDC3_DATA_INTERFACE | |||
| #include "usb_serial3.h" | |||
| #endif | |||
| #else // F_CPU < 20000000 | |||
| #ifdef __cplusplus | |||
| @@ -45,6 +45,12 @@ usb_serial2_class SerialA; | |||
| #endif | |||
| #endif | |||
| #ifdef CDC3_DATA_INTERFACE | |||
| #ifdef CDC3_STATUS_INTERFACE | |||
| usb_serial3_class SerialB; | |||
| #endif | |||
| #endif | |||
| #ifdef MIDI_INTERFACE | |||
| usb_midi_class usbMIDI; | |||
| #endif | |||
| @@ -81,7 +87,8 @@ usb_serial_class Serial; | |||
| #else // F_CPU < 20 MHz | |||
| #if defined(USB_SERIAL) || defined(USB_DUAL_SERIAL) || defined(USB_SERIAL_HID) | |||
| #if defined(USB_SERIAL) || defined(USB_DUAL_SERIAL) || \ | |||
| defined(USB_TRIPLE_SERIAL) || defined(USB_SERIAL_HID) | |||
| usb_serial_class Serial; | |||
| #elif (USB_DISABLED) | |||
| usb_serial_class Serial; | |||
| @@ -95,3 +102,5 @@ void serialEvent() __attribute__((weak)); | |||
| void serialEvent() {} | |||
| void serialEventA() __attribute__((weak)); | |||
| void serialEventA() {} | |||
| void serialEventB() __attribute__((weak)); | |||
| void serialEventB() {} | |||
| @@ -0,0 +1,46 @@ | |||
| /* 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(CDC3_STATUS_INTERFACE) && defined(CDC3_DATA_INTERFACE) | |||
| #if F_CPU >= 20000000 | |||
| #include "usb_serial_port.h" | |||
| struct usb_serial_port usb_serial3_instance = { | |||
| .cdc_rx_endpoint = CDC3_RX_ENDPOINT, | |||
| .cdc_tx_endpoint = CDC3_TX_ENDPOINT, | |||
| .cdc_tx_size = CDC3_TX_SIZE, | |||
| }; | |||
| #endif | |||
| #endif // CDC3_STATUS_INTERFACE && CDC3_DATA_INTERFACE | |||
| @@ -0,0 +1,48 @@ | |||
| /* 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 USBserial3_h_ | |||
| #define USBserial3_h_ | |||
| #include "usb_desc.h" | |||
| #if defined(CDC3_STATUS_INTERFACE) && defined(CDC3_DATA_INTERFACE) | |||
| #define USB_SERIAL_SUFFIX 3 | |||
| #define SERIAL_CLASS_SUFFIX B | |||
| #include "usb_serial_template.h" | |||
| #define usb_cdc3_line_coding usb_serial3_instance.cdc_line_coding | |||
| #define usb_cdc3_line_rtsdtr_millis usb_serial3_instance.cdc_line_rtsdtr_millis | |||
| #define usb_cdc3_line_rtsdtr usb_serial3_instance.cdc_line_rtsdtr | |||
| #define usb_cdc3_transmit_flush_timer usb_serial3_instance.cdc_transmit_flush_timer | |||
| #endif // CDC_STATUS_INTERFACE && CDC_DATA_INTERFACE | |||
| #endif // USBserial3_h_ | |||
| @@ -134,6 +134,30 @@ | |||
| #ifdef CDC2_TX_SIZE | |||
| #undef CDC2_TX_SIZE | |||
| #endif | |||
| #ifdef CDC3_STATUS_INTERFACE | |||
| #undef CDC3_STATUS_INTERFACE | |||
| #endif | |||
| #ifdef CDC3_DATA_INTERFACE | |||
| #undef CDC3_DATA_INTERFACE | |||
| #endif | |||
| #ifdef CDC3_ACM_ENDPOINT | |||
| #undef CDC3_ACM_ENDPOINT | |||
| #endif | |||
| #ifdef CDC3_RX_ENDPOINT | |||
| #undef CDC3_RX_ENDPOINT | |||
| #endif | |||
| #ifdef CDC3_TX_ENDPOINT | |||
| #undef CDC3_TX_ENDPOINT | |||
| #endif | |||
| #ifdef CDC3_ACM_SIZE | |||
| #undef CDC3_ACM_SIZE | |||
| #endif | |||
| #ifdef CDC3_RX_SIZE | |||
| #undef CDC3_RX_SIZE | |||
| #endif | |||
| #ifdef CDC3_TX_SIZE | |||
| #undef CDC3_TX_SIZE | |||
| #endif | |||
| #ifdef SEREMU_INTERFACE | |||
| #undef SEREMU_INTERFACE | |||
| #endif | |||
| @@ -39,8 +39,11 @@ void yield(void) | |||
| if (running) return; // TODO: does this need to be atomic? | |||
| running = 1; | |||
| if (Serial.available()) serialEvent(); | |||
| #ifdef USB_DUAL_SERIAL | |||
| #if defined(USB_DUAL_SERIAL) || defined(USB_TRIPLE_SERIAL) | |||
| if (SerialA.available()) serialEventA(); | |||
| #endif | |||
| #ifdef USB_TRIPLE_SERIAL | |||
| if (SerialB.available()) serialEventB(); | |||
| #endif | |||
| if (Serial1.available()) serialEvent1(); | |||
| if (Serial2.available()) serialEvent2(); | |||