| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | #include "USB.h"
 | 
					
						
							| 
									
										
										
										
											2021-08-23 17:27:34 +03:00
										 |  |  | #if CONFIG_TINYUSB_CDC_ENABLED
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | #include "USBCDC.h"
 | 
					
						
							| 
									
										
										
										
											2021-08-23 17:27:34 +03:00
										 |  |  | #include "esp32-hal-tinyusb.h"
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS); | 
					
						
							|  |  |  | esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait); | 
					
						
							|  |  |  | esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, int32_t event_id, esp_event_handler_t event_handler, void *event_handler_arg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MAX_USB_CDC_DEVICES 2
 | 
					
						
							|  |  |  | USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint16_t load_cdc_descriptor(uint8_t * dst, uint8_t * itf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC"); | 
					
						
							|  |  |  |     uint8_t descriptor[TUD_CDC_DESC_LEN] = { | 
					
						
							|  |  |  |             // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
 | 
					
						
							|  |  |  |             TUD_CDC_DESCRIPTOR(*itf, str_index, 0x85, 64, 0x03, 0x84, 64) | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     *itf+=2; | 
					
						
							|  |  |  |     memcpy(dst, descriptor, TUD_CDC_DESC_LEN); | 
					
						
							|  |  |  |     return TUD_CDC_DESC_LEN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  | // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){ | 
					
						
							|  |  |  |         devices[itf]->_onLineState(dtr, rts); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  | // Invoked when line coding is change via SET_LINE_CODING
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){ | 
					
						
							|  |  |  |         devices[itf]->_onLineCoding(p_line_coding->bit_rate, p_line_coding->stop_bits, p_line_coding->parity, p_line_coding->data_bits); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  | // Invoked when received new data
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | void tud_cdc_rx_cb(uint8_t itf) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){ | 
					
						
							|  |  |  |         devices[itf]->_onRX(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  | // Invoked when received send break
 | 
					
						
							|  |  |  | void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms){ | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     //log_v("itf: %u, duration_ms: %u", itf, duration_ms);
 | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Invoked when space becomes available in TX buffer
 | 
					
						
							|  |  |  | void tud_cdc_tx_complete_cb(uint8_t itf){ | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     if(itf < MAX_USB_CDC_DEVICES && devices[itf] != NULL){ | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  |         devices[itf]->_onTX(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  | static void ARDUINO_ISR_ATTR cdc0_write_char(char c){ | 
					
						
							|  |  |  |     if(devices[0] != NULL){ | 
					
						
							|  |  |  |         devices[0]->write(c); | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void usb_unplugged_cb(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data){ | 
					
						
							|  |  |  |     ((USBCDC*)arg)->_onUnplugged(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  | USBCDC::USBCDC(uint8_t itfn)  | 
					
						
							|  |  |  | : itf(itfn) | 
					
						
							|  |  |  | , bit_rate(0) | 
					
						
							|  |  |  | , stop_bits(0) | 
					
						
							|  |  |  | , parity(0) | 
					
						
							|  |  |  | , data_bits(0) | 
					
						
							|  |  |  | , dtr(false) | 
					
						
							|  |  |  | , rts(false) | 
					
						
							|  |  |  | , connected(false) | 
					
						
							|  |  |  | , reboot_enable(true) | 
					
						
							|  |  |  | , rx_queue(NULL) | 
					
						
							|  |  |  | , tx_lock(NULL) | 
					
						
							|  |  |  | , tx_timeout_ms(250) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |     tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor); | 
					
						
							|  |  |  |     if(itf < MAX_USB_CDC_DEVICES){ | 
					
						
							|  |  |  |         arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  | USBCDC::~USBCDC(){ | 
					
						
							|  |  |  |     end(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | void USBCDC::onEvent(esp_event_handler_t callback){ | 
					
						
							|  |  |  |     onEvent(ARDUINO_USB_CDC_ANY_EVENT, callback); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void USBCDC::onEvent(arduino_usb_cdc_event_t event, esp_event_handler_t callback){ | 
					
						
							|  |  |  |     arduino_usb_event_handler_register_with(ARDUINO_USB_CDC_EVENTS, event, callback, this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t USBCDC::setRxBufferSize(size_t rx_queue_len){ | 
					
						
							|  |  |  |     if(rx_queue){ | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  |         if(!rx_queue_len){ | 
					
						
							|  |  |  |             vQueueDelete(rx_queue); | 
					
						
							|  |  |  |             rx_queue = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     rx_queue = xQueueCreate(rx_queue_len, sizeof(uint8_t)); | 
					
						
							|  |  |  |     if(!rx_queue){ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return rx_queue_len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void USBCDC::begin(unsigned long baud) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     if(tx_lock == NULL) { | 
					
						
							|  |  |  |         tx_lock = xSemaphoreCreateMutex(); | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  |     setRxBufferSize(256);//default if not preset
 | 
					
						
							|  |  |  |     devices[itf] = this; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void USBCDC::end() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  |     connected = false; | 
					
						
							|  |  |  |     devices[itf] = NULL; | 
					
						
							|  |  |  |     setRxBufferSize(0); | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     if(tx_lock != NULL) { | 
					
						
							|  |  |  |         vSemaphoreDelete(tx_lock); | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  | void USBCDC::setTxTimeoutMs(uint32_t timeout){ | 
					
						
							|  |  |  |     tx_timeout_ms = timeout; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | void USBCDC::_onUnplugged(void){ | 
					
						
							|  |  |  |     if(connected){ | 
					
						
							|  |  |  |         connected = false; | 
					
						
							|  |  |  |         dtr = false; | 
					
						
							|  |  |  |         rts = false; | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |         arduino_usb_cdc_event_data_t p; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |         arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { CDC_LINE_IDLE, CDC_LINE_1, CDC_LINE_2, CDC_LINE_3 }; | 
					
						
							|  |  |  | void USBCDC::_onLineState(bool _dtr, bool _rts){ | 
					
						
							|  |  |  |     static uint8_t lineState = CDC_LINE_IDLE; | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if(dtr == _dtr && rts == _rts){ | 
					
						
							|  |  |  |         return; // Skip duplicate events
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |     dtr = _dtr; | 
					
						
							|  |  |  |     rts = _rts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(reboot_enable){ | 
					
						
							|  |  |  |         if(!dtr && rts){ | 
					
						
							|  |  |  |             if(lineState == CDC_LINE_IDLE){ | 
					
						
							|  |  |  |                 lineState++; | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  |                 if(connected){ | 
					
						
							|  |  |  |                     connected = false; | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |                     arduino_usb_cdc_event_data_t p; | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  |                     arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 lineState = CDC_LINE_IDLE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if(dtr && rts){ | 
					
						
							|  |  |  |             if(lineState == CDC_LINE_1){ | 
					
						
							|  |  |  |                 lineState++; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 lineState = CDC_LINE_IDLE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if(dtr && !rts){ | 
					
						
							|  |  |  |             if(lineState == CDC_LINE_2){ | 
					
						
							|  |  |  |                 lineState++; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 lineState = CDC_LINE_IDLE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if(!dtr && !rts){ | 
					
						
							|  |  |  |             if(lineState == CDC_LINE_3){ | 
					
						
							|  |  |  |                 usb_persist_restart(RESTART_BOOTLOADER); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 lineState = CDC_LINE_IDLE; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     if(lineState == CDC_LINE_IDLE){ | 
					
						
							|  |  |  |         if(dtr && rts && !connected){ | 
					
						
							|  |  |  |             connected = true; | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |             arduino_usb_cdc_event_data_t p; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |             arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_CONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  |         } else if(!dtr && connected){ | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |             connected = false; | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |             arduino_usb_cdc_event_data_t p; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |             arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_DISCONNECTED_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |         arduino_usb_cdc_event_data_t l; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |         l.line_state.dtr = dtr; | 
					
						
							|  |  |  |         l.line_state.rts = rts; | 
					
						
							|  |  |  |         arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_STATE_EVENT, &l, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void USBCDC::_onLineCoding(uint32_t _bit_rate, uint8_t _stop_bits, uint8_t _parity, uint8_t _data_bits){ | 
					
						
							|  |  |  |     if(bit_rate != _bit_rate || data_bits != _data_bits || stop_bits != _stop_bits || parity != _parity){ | 
					
						
							| 
									
										
										
										
											2021-07-20 13:36:27 +03:00
										 |  |  |         // ArduinoIDE sends LineCoding with 1200bps baud to reset the device
 | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  |         if(reboot_enable && _bit_rate == 1200){ | 
					
						
							| 
									
										
										
										
											2021-04-05 20:24:46 +03:00
										 |  |  |             usb_persist_restart(RESTART_BOOTLOADER); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             bit_rate = _bit_rate; | 
					
						
							|  |  |  |             data_bits = _data_bits; | 
					
						
							|  |  |  |             stop_bits = _stop_bits; | 
					
						
							|  |  |  |             parity = _parity; | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |             arduino_usb_cdc_event_data_t p; | 
					
						
							| 
									
										
										
										
											2021-04-05 20:24:46 +03:00
										 |  |  |             p.line_coding.bit_rate = bit_rate; | 
					
						
							|  |  |  |             p.line_coding.data_bits = data_bits; | 
					
						
							|  |  |  |             p.line_coding.stop_bits = stop_bits; | 
					
						
							|  |  |  |             p.line_coding.parity = parity; | 
					
						
							|  |  |  |             arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_CODING_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void USBCDC::_onRX(){ | 
					
						
							|  |  |  |     uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE+1]; | 
					
						
							|  |  |  |     uint32_t count = tud_cdc_n_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE); | 
					
						
							|  |  |  |     for(uint32_t i=0; i<count; i++){ | 
					
						
							|  |  |  |         if(rx_queue == NULL || !xQueueSend(rx_queue, buf+i, 0)){ | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |     arduino_usb_cdc_event_data_t p; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |     p.rx.len = count; | 
					
						
							|  |  |  |     arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_RX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  | void USBCDC::_onTX(){ | 
					
						
							| 
									
										
										
										
											2021-10-01 17:52:29 +03:00
										 |  |  |     arduino_usb_cdc_event_data_t p; | 
					
						
							| 
									
										
										
										
											2021-07-20 11:59:13 +03:00
										 |  |  |     arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_TX_EVENT, &p, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | void  USBCDC::enableReboot(bool enable){ | 
					
						
							|  |  |  |     reboot_enable = enable; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | bool  USBCDC::rebootEnabled(void){ | 
					
						
							|  |  |  |     return reboot_enable; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int USBCDC::available(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){ | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return uxQueueMessagesWaiting(rx_queue); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int USBCDC::peek(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){ | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     uint8_t c; | 
					
						
							|  |  |  |     if(xQueuePeek(rx_queue, &c, 0)) { | 
					
						
							|  |  |  |         return c; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int USBCDC::read(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){ | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     uint8_t c = 0; | 
					
						
							|  |  |  |     if(xQueueReceive(rx_queue, &c, 0)) { | 
					
						
							|  |  |  |         return c; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t USBCDC::read(uint8_t *buffer, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf >= MAX_USB_CDC_DEVICES || rx_queue == NULL){ | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     uint8_t c = 0; | 
					
						
							|  |  |  |     size_t count = 0; | 
					
						
							|  |  |  |     while(count < size && xQueueReceive(rx_queue, &c, 0)){ | 
					
						
							|  |  |  |         buffer[count++] = c; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void USBCDC::flush(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     if(itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)){ | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){ | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     tud_cdc_n_write_flush(itf); | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     xSemaphoreGive(tx_lock); | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int USBCDC::availableForWrite(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     if(itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || !tud_cdc_n_connected(itf)){ | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     size_t a = tud_cdc_n_write_available(itf); | 
					
						
							|  |  |  |     xSemaphoreGive(tx_lock); | 
					
						
							|  |  |  |     return a; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t USBCDC::write(const uint8_t *buffer, size_t size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-15 15:23:11 +03:00
										 |  |  |     if(itf >= MAX_USB_CDC_DEVICES || tx_lock == NULL || buffer == NULL || size == 0 || !tud_cdc_n_connected(itf)){ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if(xPortInIsrContext()){ | 
					
						
							|  |  |  |         BaseType_t taskWoken = false; | 
					
						
							|  |  |  |         if(xSemaphoreTakeFromISR(tx_lock, &taskWoken) != pdPASS){ | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if(xSemaphoreTake(tx_lock, tx_timeout_ms / portTICK_PERIOD_MS) != pdPASS){ | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     size_t to_send = size, so_far = 0; | 
					
						
							|  |  |  |     while(to_send){ | 
					
						
							|  |  |  |         if(!tud_cdc_n_connected(itf)){ | 
					
						
							|  |  |  |             size = so_far; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         size_t space = tud_cdc_n_write_available(itf); | 
					
						
							|  |  |  |         if(!space){ | 
					
						
							|  |  |  |             tud_cdc_n_write_flush(itf); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if(space > to_send){ | 
					
						
							|  |  |  |             space = to_send; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         size_t sent = tud_cdc_n_write(itf, buffer+so_far, space); | 
					
						
							|  |  |  |         if(sent){ | 
					
						
							|  |  |  |             so_far += sent; | 
					
						
							|  |  |  |             to_send -= sent; | 
					
						
							|  |  |  |             tud_cdc_n_write_flush(itf); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             size = so_far; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if(xPortInIsrContext()){ | 
					
						
							|  |  |  |         BaseType_t taskWoken = false; | 
					
						
							|  |  |  |         xSemaphoreGiveFromISR(tx_lock, &taskWoken); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         xSemaphoreGive(tx_lock); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return size; | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t USBCDC::write(uint8_t c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return write(&c, 1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t  USBCDC::baudRate() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return bit_rate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void USBCDC::setDebugOutput(bool en) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(en) { | 
					
						
							|  |  |  |         uartSetDebug(NULL); | 
					
						
							|  |  |  |         ets_install_putc1((void (*)(char)) &cdc0_write_char); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ets_install_putc1(NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | USBCDC::operator bool() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(itf >= MAX_USB_CDC_DEVICES){ | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return connected; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-02 15:35:13 +03:00
										 |  |  | #if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
 | 
					
						
							| 
									
										
										
										
											2021-04-05 14:23:58 +03:00
										 |  |  | USBCDC Serial(0); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* CONFIG_TINYUSB_CDC_ENABLED */
 |