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>main
| #include "avr_emulation.h" | #include "avr_emulation.h" | ||||
| #include "usb_serial.h" | #include "usb_serial.h" | ||||
| #include "usb_serial2.h" | #include "usb_serial2.h" | ||||
| #include "usb_serial3.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 CDC2_DATA_INTERFACE_DESC_SIZE 0 | #define CDC2_DATA_INTERFACE_DESC_SIZE 0 | ||||
| #endif | #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 | #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(CDC2), | EMIT_CDC_DESCRIPTORS(CDC2), | ||||
| #endif // CDC2_DATA_INTERFACE | #endif // CDC2_DATA_INTERFACE | ||||
| #ifdef CDC3_DATA_INTERFACE | |||||
| EMIT_CDC_IAD_DESCRIPTOR(CDC3), | |||||
| EMIT_CDC_DESCRIPTORS(CDC3), | |||||
| #endif // CDC3_DATA_INTERFACE | |||||
| #ifdef MIDI_INTERFACE | #ifdef MIDI_INTERFACE | ||||
| // Standard MS Interface Descriptor, | // Standard MS Interface Descriptor, | ||||
| 9, // bLength | 9, // bLength |
| #define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_ONLY | #define ENDPOINT6_CONFIG ENDPOINT_RECEIVE_ONLY | ||||
| #define ENDPOINT7_CONFIG ENDPOINT_TRANSMIT_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) | #elif defined(USB_KEYBOARDONLY) | ||||
| #define VENDOR_ID 0x16C0 | #define VENDOR_ID 0x16C0 | ||||
| #define PRODUCT_ID 0x04D0 | #define PRODUCT_ID 0x04D0 |
| usb_cdc2_line_rtsdtr_millis = systick_millis_count; | usb_cdc2_line_rtsdtr_millis = systick_millis_count; | ||||
| usb_cdc2_line_rtsdtr = setup.wValue; | usb_cdc2_line_rtsdtr = setup.wValue; | ||||
| break; | 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 | #endif | ||||
| } | } | ||||
| //serial_print("set control line state\n"); | //serial_print("set control line state\n"); | ||||
| case CDC2_STATUS_INTERFACE: | case CDC2_STATUS_INTERFACE: | ||||
| dst = (uint8_t *)usb_cdc2_line_coding; | dst = (uint8_t *)usb_cdc2_line_coding; | ||||
| break; | break; | ||||
| #endif | |||||
| #ifdef CDC3_STATUS_INTERFACE | |||||
| case CDC3_STATUS_INTERFACE: | |||||
| dst = (uint8_t *)usb_cdc3_line_coding; | |||||
| break; | |||||
| #endif | #endif | ||||
| } | } | ||||
| if (!dst) | if (!dst) | ||||
| if (t == 0) usb_serial2_flush_callback(); | if (t == 0) usb_serial2_flush_callback(); | ||||
| } | } | ||||
| #endif | #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 | #ifdef SEREMU_INTERFACE | ||||
| t = usb_seremu_transmit_flush_timer; | t = usb_seremu_transmit_flush_timer; | ||||
| if (t) { | if (t) { |
| #include "usb_serial2.h" | #include "usb_serial2.h" | ||||
| #endif | #endif | ||||
| #ifdef CDC3_DATA_INTERFACE | |||||
| #include "usb_serial3.h" | |||||
| #endif | |||||
| #else // F_CPU < 20000000 | #else // F_CPU < 20000000 | ||||
| #ifdef __cplusplus | #ifdef __cplusplus |
| #endif | #endif | ||||
| #endif | #endif | ||||
| #ifdef CDC3_DATA_INTERFACE | |||||
| #ifdef CDC3_STATUS_INTERFACE | |||||
| usb_serial3_class SerialB; | |||||
| #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_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; | usb_serial_class Serial; | ||||
| #elif (USB_DISABLED) | #elif (USB_DISABLED) | ||||
| usb_serial_class Serial; | usb_serial_class Serial; | ||||
| void serialEvent() {} | void serialEvent() {} | ||||
| void serialEventA() __attribute__((weak)); | void serialEventA() __attribute__((weak)); | ||||
| void serialEventA() {} | void serialEventA() {} | ||||
| void serialEventB() __attribute__((weak)); | |||||
| void serialEventB() {} |
| /* 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 |
| /* 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_ |
| #ifdef CDC2_TX_SIZE | #ifdef CDC2_TX_SIZE | ||||
| #undef CDC2_TX_SIZE | #undef CDC2_TX_SIZE | ||||
| #endif | #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 | #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 defined(USB_DUAL_SERIAL) || defined(USB_TRIPLE_SERIAL) | |||||
| if (SerialA.available()) serialEventA(); | if (SerialA.available()) serialEventA(); | ||||
| #endif | |||||
| #ifdef USB_TRIPLE_SERIAL | |||||
| if (SerialB.available()) serialEventB(); | |||||
| #endif | #endif | ||||
| if (Serial1.available()) serialEvent1(); | if (Serial1.available()) serialEvent1(); | ||||
| if (Serial2.available()) serialEvent2(); | if (Serial2.available()) serialEvent2(); |