diff options
Diffstat (limited to 'src/class/cdc')
| -rw-r--r-- | src/class/cdc/cdc.h | 22 | ||||
| -rw-r--r-- | src/class/cdc/cdc_device.c | 483 | ||||
| -rw-r--r-- | src/class/cdc/cdc_device.h | 117 | ||||
| -rw-r--r-- | src/class/cdc/cdc_host.c | 668 | ||||
| -rw-r--r-- | src/class/cdc/cdc_host.h | 79 | ||||
| -rw-r--r-- | src/class/cdc/cdc_rndis.h | 6 | ||||
| -rw-r--r-- | src/class/cdc/cdc_rndis_host.c | 289 | ||||
| -rw-r--r-- | src/class/cdc/cdc_rndis_host.h | 63 | ||||
| -rw-r--r-- | src/class/cdc/serial/ftdi_sio.h | 13 |
9 files changed, 701 insertions, 1039 deletions
diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 10ba16a7c..679723ba6 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -29,8 +29,8 @@ * Currently only Abstract Control Model subclass is supported * @{ */ -#ifndef _TUSB_CDC_H__ -#define _TUSB_CDC_H__ +#ifndef TUSB_CDC_H__ +#define TUSB_CDC_H__ #include "common/tusb_common.h" @@ -192,10 +192,10 @@ typedef enum { CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits } cdc_line_coding_stopbits_t; -#define CDC_LINE_CODING_STOP_BITS_TEXT(STOP_BITS) ( \ - STOP_BITS == CDC_LINE_CODING_STOP_BITS_1 ? "1" : \ - STOP_BITS == CDC_LINE_CODING_STOP_BITS_1_5 ? "1.5" : \ - STOP_BITS == CDC_LINE_CODING_STOP_BITS_2 ? "2" : "?" ) +#define CDC_LINE_CODING_STOP_BITS_TEXT(STOP_BITS) ( \ + (STOP_BITS) == CDC_LINE_CODING_STOP_BITS_1 ? "1" : \ + (STOP_BITS) == CDC_LINE_CODING_STOP_BITS_1_5 ? "1.5" : \ + (STOP_BITS) == CDC_LINE_CODING_STOP_BITS_2 ? "2" : "?" ) // TODO Backward compatible for typos. Maybe removed in the future release #define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1 @@ -211,11 +211,11 @@ typedef enum { } cdc_line_coding_parity_t; #define CDC_LINE_CODING_PARITY_CHAR(PARITY) ( \ - PARITY == CDC_LINE_CODING_PARITY_NONE ? 'N' : \ - PARITY == CDC_LINE_CODING_PARITY_ODD ? 'O' : \ - PARITY == CDC_LINE_CODING_PARITY_EVEN ? 'E' : \ - PARITY == CDC_LINE_CODING_PARITY_MARK ? 'M' : \ - PARITY == CDC_LINE_CODING_PARITY_SPACE ? 'S' : '?' ) + (PARITY) == CDC_LINE_CODING_PARITY_NONE ? 'N' : \ + (PARITY) == CDC_LINE_CODING_PARITY_ODD ? 'O' : \ + (PARITY) == CDC_LINE_CODING_PARITY_EVEN ? 'E' : \ + (PARITY) == CDC_LINE_CODING_PARITY_MARK ? 'M' : \ + (PARITY) == CDC_LINE_CODING_PARITY_SPACE ? 'S' : '?' ) //--------------------------------------------------------------------+ // Management Element Notification (Notification Endpoint) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f1c4a3bbf..c499756b9 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -43,181 +43,143 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - typedef struct { uint8_t rhport; uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - uint8_t ep_notify; uint8_t line_state; // Bit 0: DTR, Bit 1: RTS /*------------- From this point, data is not cleared by bus reset -------------*/ - char wanted_char; TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; + char wanted_char; - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; + tu_edpt_stream_t tx_stream; + tu_edpt_stream_t rx_stream; - uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; - - OSAL_MUTEX_DEF(rx_ff_mutex); - OSAL_MUTEX_DEF(tx_ff_mutex); + uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; } cdcd_interface_t; -#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) +#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, line_coding) +// Skip local EP buffer if dedicated hw FIFO is supported +#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 typedef struct { - TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE); - TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE); + TUD_EPBUF_DEF(epout, CFG_TUD_CDC_RX_EPSIZE); + TUD_EPBUF_DEF(epin, CFG_TUD_CDC_TX_EPSIZE); #if CFG_TUD_CDC_NOTIFY TUD_EPBUF_TYPE_DEF(cdc_notify_msg_t, epnotify); #endif } cdcd_epbuf_t; -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; - -static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT(); - -static bool _prep_out_transaction(uint8_t itf) { - const uint8_t rhport = 0; - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY(tud_ready() && p_cdc->ep_out); - - uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_out)); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_cdc->rx_ff); - - if (available >= CFG_TUD_CDC_EP_BUFSIZE) { - return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE); - } else { - // Release endpoint since we don't make any transfer - usbd_edpt_release(p_cdc->rhport, p_cdc->ep_out); - return false; - } -} +#endif //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { - (void) itf; - (void) wanted_char; + (void)itf; + (void)wanted_char; } TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_notify_complete_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - (void) itf; - (void) dtr; - (void) rts; + (void)itf; + (void)dtr; + (void)rts; } -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) { - (void) itf; - (void) p_line_coding; +TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, const cdc_line_coding_t *p_line_coding) { + (void)itf; + (void)p_line_coding; } TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { - (void) itf; - (void) duration_ms; + (void)itf; + (void)duration_ms; } //--------------------------------------------------------------------+ -// APPLICATION API +// INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) { - TU_VERIFY(driver_cfg); - _cdcd_cfg = *driver_cfg; - return true; +static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; + +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_cdc_itf(uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUD_CDC; idx++) { + const cdcd_interface_t *p_cdc = &_cdcd_itf[idx]; + if (ep_addr == p_cdc->rx_stream.ep_addr || ep_addr == p_cdc->tx_stream.ep_addr || + (ep_addr == p_cdc->ep_notify && ep_addr != 0)) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; } +//--------------------------------------------------------------------+ +// APPLICATION API +//--------------------------------------------------------------------+ bool tud_cdc_n_ready(uint8_t itf) { - return tud_ready() && _cdcd_itf[itf].ep_in != 0 && _cdcd_itf[itf].ep_out != 0; + TU_VERIFY(itf < CFG_TUD_CDC); + TU_VERIFY(tud_ready()); + const cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + + const bool in_opened = tu_edpt_stream_is_opened(&p_cdc->tx_stream); + const bool out_opened = tu_edpt_stream_is_opened(&p_cdc->rx_stream); + return in_opened && out_opened; } bool tud_cdc_n_connected(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_CDC); + TU_VERIFY(tud_ready()); // DTR (bit 0) active is considered as connected - return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); + return tu_bit_test(_cdcd_itf[itf].line_state, 0); } uint8_t tud_cdc_n_get_line_state(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_CDC, 0); return _cdcd_itf[itf].line_state; } -void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) { +void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t *coding) { + TU_VERIFY(itf < CFG_TUD_CDC, ); (*coding) = _cdcd_itf[itf].line_coding; } #if CFG_TUD_CDC_NOTIFY -bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *state) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; +bool tud_cdc_n_notify_msg(uint8_t itf, cdc_notify_msg_t *msg) { + TU_VERIFY(itf < CFG_TUD_CDC); + const cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); - cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify; - notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF; - notify_msg->request.bRequest = CDC_NOTIF_SERIAL_STATE; - notify_msg->request.wValue = 0; - notify_msg->request.wIndex = p_cdc->itf_num; - notify_msg->request.wLength = sizeof(cdc_notify_uart_state_t); - notify_msg->serial_state = *state; - - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t)); -} - -bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); + #if CFG_TUD_EDPT_DEDICATED_HWFIFO + cdc_notify_msg_t *msg_epbuf = msg; + #else + cdc_notify_msg_t *msg_epbuf = &_cdcd_epbuf[itf].epnotify; + *msg_epbuf = *msg; + #endif - cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify; - notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF; - notify_msg->request.bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE; - notify_msg->request.wValue = 0; - notify_msg->request.wIndex = p_cdc->itf_num; - notify_msg->request.wLength = sizeof(cdc_notify_conn_speed_change_t); - notify_msg->conn_speed_change = *conn_speed_change; + msg_epbuf->request.wIndex = p_cdc->itf_num; - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t)); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)msg_epbuf, 8 + msg_epbuf->request.wLength, false); } #endif void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { + TU_VERIFY(itf < CFG_TUD_CDC, ); _cdcd_itf[itf].wanted_char = wanted; } @@ -225,77 +187,54 @@ void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { // READ API //--------------------------------------------------------------------+ uint32_t tud_cdc_n_available(uint8_t itf) { - return tu_fifo_count(&_cdcd_itf[itf].rx_ff); + TU_VERIFY(itf < CFG_TUD_CDC, 0); + return tu_edpt_stream_read_available(&_cdcd_itf[itf].rx_stream); } uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - _prep_out_transaction(itf); - return num_read; + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_read(&p_cdc->rx_stream, buffer, bufsize); } -bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { - return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); +bool tud_cdc_n_peek(uint8_t itf, uint8_t *chr) { + TU_VERIFY(itf < CFG_TUD_CDC); + return tu_edpt_stream_peek(&_cdcd_itf[itf].rx_stream, chr); } void tud_cdc_n_read_flush(uint8_t itf) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(itf); + TU_VERIFY(itf < CFG_TUD_CDC, ); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + tu_edpt_stream_clear(&p_cdc->rx_stream); + tu_edpt_stream_read_xfer(&p_cdc->rx_stream); } //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t wr_count = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - - // flush if queue more than packet size - if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE - #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE - || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size - #endif - ) { - tud_cdc_n_write_flush(itf); - } - - return wr_count; + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write(&p_cdc->tx_stream, buffer, bufsize); } uint32_t tud_cdc_n_write_flush(uint8_t itf) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - TU_VERIFY(tud_ready(), 0); // Skip if usb is not ready yet - - // No data to send - if (!tu_fifo_count(&p_cdc->tx_ff)) { - return 0; - } - - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_in), 0); // Claim the endpoint - - // Pull data from FIFO - const uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); - - if (count) { - TU_ASSERT(usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_in, p_epbuf->epin, count), 0); - return count; - } else { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(p_cdc->rhport, p_cdc->ep_in); - return 0; - } + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write_xfer(&p_cdc->tx_stream); } uint32_t tud_cdc_n_write_available(uint8_t itf) { - return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write_available(&p_cdc->tx_stream); } bool tud_cdc_n_write_clear(uint8_t itf) { - return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + tu_edpt_stream_clear(&p_cdc->tx_stream); + return true; } //--------------------------------------------------------------------+ @@ -304,8 +243,7 @@ bool tud_cdc_n_write_clear(uint8_t itf) { void cdcd_init(void) { tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { - cdcd_interface_t* p_cdc = &_cdcd_itf[i]; - + cdcd_interface_t *p_cdc = &_cdcd_itf[i]; p_cdc->wanted_char = (char) -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 @@ -314,44 +252,30 @@ void cdcd_init(void) { p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; - // Config RX fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + #if CFG_TUD_EDPT_DEDICATED_HWFIFO + uint8_t *epout_buf = NULL; + uint8_t *epin_buf = NULL; + #else + uint8_t *epout_buf = _cdcd_epbuf[i].epout; + uint8_t *epin_buf = _cdcd_epbuf[i].epin; + #endif + + tu_edpt_stream_init(&p_cdc->rx_stream, false, false, false, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, epout_buf); // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not // know if data is actually polled by terminal. This way the most current data is prioritized. // Default: is overwritable - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, _cdcd_cfg.tx_overwritabe_if_not_connected); - - #if OSAL_MUTEX_REQUIRED - osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex); - osal_mutex_t mutex_wr = osal_mutex_create(&p_cdc->tx_ff_mutex); - TU_ASSERT(mutex_rd != NULL && mutex_wr != NULL, ); - - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, mutex_rd); - tu_fifo_config_mutex(&p_cdc->tx_ff, mutex_wr, NULL); - #endif + tu_edpt_stream_init(&p_cdc->tx_stream, false, true, CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED, p_cdc->tx_ff_buf, + CFG_TUD_CDC_TX_BUFSIZE, epin_buf); } } bool cdcd_deinit(void) { - #if OSAL_MUTEX_REQUIRED - for(uint8_t i=0; i<CFG_TUD_CDC; i++) { + for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; - osal_mutex_t mutex_rd = p_cdc->rx_ff.mutex_rd; - osal_mutex_t mutex_wr = p_cdc->tx_ff.mutex_wr; - - if (mutex_rd) { - osal_mutex_delete(mutex_rd); - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, NULL); - } - - if (mutex_wr) { - osal_mutex_delete(mutex_wr); - tu_fifo_config_mutex(&p_cdc->tx_ff, NULL, NULL); - } + tu_edpt_stream_deinit(&p_cdc->rx_stream); + tu_edpt_stream_deinit(&p_cdc->tx_stream); } - #endif - return true; } @@ -360,74 +284,92 @@ void cdcd_reset(uint8_t rhport) { for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; - tu_memclr(p_cdc, ITF_MEM_RESET_SIZE); - if (!_cdcd_cfg.rx_persistent) { - tu_fifo_clear(&p_cdc->rx_ff); - } - if (!_cdcd_cfg.tx_persistent) { - tu_fifo_clear(&p_cdc->tx_ff); - } - tu_fifo_set_overwritable(&p_cdc->tx_ff, _cdcd_cfg.tx_overwritabe_if_not_connected); + + tu_fifo_set_overwritable(&p_cdc->tx_stream.ff, CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED); // back to default + tu_edpt_stream_close(&p_cdc->rx_stream); + tu_edpt_stream_close(&p_cdc->tx_stream); } } uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) { // Only support ACM subclass - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); + TU_VERIFY(TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, + 0); - // Find available interface - cdcd_interface_t* p_cdc; - uint8_t cdc_id; - for (cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) { - p_cdc = &_cdcd_itf[cdc_id]; - if (p_cdc->ep_in == 0) { - break; - } - } + const uint8_t cdc_id = find_cdc_itf(0); // Find available interface TU_ASSERT(cdc_id < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[cdc_id]; //------------- Control Interface -------------// p_cdc->rhport = rhport; p_cdc->itf_num = itf_desc->bInterfaceNumber; - uint16_t drv_len = sizeof(tusb_desc_interface_t); - const uint8_t* p_desc = tu_desc_next(itf_desc); + const uint8_t *p_desc = (const uint8_t *)itf_desc; + const uint8_t *desc_end = p_desc + max_len; - // Communication Functional Descriptors - while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) { - drv_len += tu_desc_len(p_desc); + // Skip all class-specific descriptor + p_desc = tu_desc_next(itf_desc); + while (tu_desc_in_bounds(p_desc, desc_end) && TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) { p_desc = tu_desc_next(p_desc); } + // notification endpoint (optional) if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { - // notification endpoint const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); p_cdc->ep_notify = desc_ep->bEndpointAddress; - drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - //------------- Data Interface (if any) -------------// - if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((const tusb_desc_interface_t*) p_desc)->bInterfaceClass)) { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + //------------- Data Interface (optional) -------------// + if (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) { + const tusb_desc_interface_t *data_itf_desc = (const tusb_desc_interface_t *)p_desc; + if (TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass) { + for (uint8_t e = 0; e < data_itf_desc->bNumEndpoints; e++) { + if (!tu_desc_in_bounds(p_desc, desc_end)) { + break; + } + p_desc = tu_desc_next(p_desc); - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); - drv_len += 2 * sizeof(tusb_desc_endpoint_t); - } + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { + tu_edpt_stream_t *stream_tx = &p_cdc->tx_stream; + tu_edpt_stream_open(stream_tx, rhport, desc_ep, CFG_TUD_CDC_TX_EPSIZE); + + #if CFG_TUD_CDC_TX_PERSISTENT + tu_edpt_stream_write_xfer(stream_tx); // flush pending data + #else + tu_edpt_stream_clear(stream_tx); + #endif + } else { + tu_edpt_stream_t *stream_rx = &p_cdc->rx_stream; + #if CFG_TUD_CDC_RX_NEED_ZLP + const uint16_t xfer_len = CFG_TUD_CDC_RX_EPSIZE; + #else + const uint16_t xfer_len = tu_edpt_packet_size(desc_ep); + #endif - // Prepare for incoming data - _prep_out_transaction(cdc_id); + tu_edpt_stream_open(stream_rx, rhport, desc_ep, xfer_len); - return drv_len; + #if !CFG_TUD_CDC_RX_PERSISTENT + tu_edpt_stream_clear(stream_rx); + #endif + + TU_ASSERT(tu_edpt_stream_read_xfer(stream_rx) > 0, 0); // prepare for incoming data + } + } + + p_desc = tu_desc_next(p_desc); + } + } + + return (uint16_t)(p_desc - (const uint8_t *)itf_desc); } // Invoked when a control transfer occurred on an interface of this class @@ -456,6 +398,8 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); } else if (stage == CONTROL_STAGE_ACK) { tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); + } else { + // nothing to do } break; @@ -481,16 +425,17 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ p_cdc->line_state = (uint8_t) request->wValue; // If enabled: fifo overwriting is disabled if DTR bit is set and vice versa - if (_cdcd_cfg.tx_overwritabe_if_not_connected) { - tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); - } else { - tu_fifo_set_overwritable(&p_cdc->tx_ff, false); - } + #if CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED + const bool is_overwritable = !dtr; + #else + const bool is_overwritable = false; + #endif + tu_fifo_set_overwritable(&p_cdc->tx_stream.ff, is_overwritable); TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - - // Invoke callback - tud_cdc_line_state_cb(itf, dtr, rts); + tud_cdc_line_state_cb(itf, dtr, rts); // invoke callback + } else { + // nothing to do } break; @@ -500,6 +445,8 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } else if (stage == CONTROL_STAGE_ACK) { TU_LOG_DRV(" Send Break\r\n"); tud_cdc_send_break_cb(itf, request->wValue); + } else { + // nothing to do } break; @@ -511,58 +458,68 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) result; + (void)rhport; + (void)result; - uint8_t itf; - cdcd_interface_t* p_cdc; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_CDC; itf++) { - p_cdc = &_cdcd_itf[itf]; - if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in) || (ep_addr == p_cdc->ep_notify)) { - break; - } - } + uint8_t itf = find_cdc_itf(ep_addr); TU_ASSERT(itf < CFG_TUD_CDC); - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + tu_edpt_stream_t *stream_rx = &p_cdc->rx_stream; + tu_edpt_stream_t *stream_tx = &p_cdc->tx_stream; - // Received new data - if (ep_addr == p_cdc->ep_out) { - tu_fifo_write_n(&p_cdc->rx_ff, p_epbuf->epout, (uint16_t) xferred_bytes); + // Received new data, move to fifo + if (ep_addr == stream_rx->ep_addr) { + tu_edpt_stream_read_xfer_complete(stream_rx, xferred_bytes); - // Check for wanted char and invoke callback if needed - if (((signed char) p_cdc->wanted_char) != -1) { - for (uint32_t i = 0; i < xferred_bytes; i++) { - if ((p_cdc->wanted_char == p_epbuf->epout[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) { - tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + // Check for wanted char and invoke wanted callback + if (((signed char)p_cdc->wanted_char) != -1) { + tu_fifo_buffer_info_t buf_info; + tu_fifo_get_read_info(&stream_rx->ff, &buf_info); + + // find backward + uint8_t *ptr; + if (buf_info.wrapped.len > 0) { + ptr = buf_info.wrapped.ptr + buf_info.wrapped.len - 1; // last byte of wrap buffer + } else if (buf_info.linear.len > 0) { + ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer + } else { + ptr = NULL; // no data + } + + if (ptr != NULL) { + for (uint32_t i = 0; i < xferred_bytes; i++) { + if (p_cdc->wanted_char == (char)*ptr) { + tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); + break; // only invoke once per transfer, even if multiple wanted chars are present + } + + if (ptr == buf_info.wrapped.ptr) { + ptr = buf_info.linear.ptr + buf_info.linear.len - 1; // last byte of linear buffer + } else if (ptr == buf_info.linear.ptr) { + break; // reached the beginning + } else { + ptr--; + } } } } - // invoke receive callback (if there is still data) - if (!tu_fifo_empty(&p_cdc->rx_ff)) { + // invoke receive callback if there is still data + if (!tu_edpt_stream_empty(stream_rx)) { tud_cdc_rx_cb(itf); } - // prepare for OUT transaction - _prep_out_transaction(itf); + tu_edpt_stream_read_xfer(stream_rx); // prepare for more data } // Data sent to host, we continue to fetch from tx fifo to send. - // Note: This will cause incorrect baudrate set in line coding. - // Though maybe the baudrate is not really important !!! - if (ep_addr == p_cdc->ep_in) { - // invoke transmit callback to possibly refill tx fifo - tud_cdc_tx_complete_cb(itf); + // Note: This will cause incorrect baudrate set in line coding. Though maybe the baudrate is not really important! + if (ep_addr == stream_tx->ep_addr) { + tud_cdc_tx_complete_cb(itf); // invoke callback to possibly refill tx fifo - if (0 == tud_cdc_n_write_flush(itf)) { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP Packet size and not zero - if (!tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) { - if (usbd_edpt_claim(rhport, p_cdc->ep_in)) { - TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0)); - } - } + if (0 == tu_edpt_stream_write_xfer(stream_tx)) { + // If there is no data left, a ZLP should be sent if needed + tu_edpt_stream_write_zlp_if_needed(stream_tx, xferred_bytes); } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 9673b9807..9ac6bc58a 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -29,6 +29,10 @@ #include "cdc.h" +#ifdef __cplusplus + extern "C" { +#endif + //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ @@ -36,52 +40,74 @@ #define CFG_TUD_CDC_NOTIFY 0 #endif -#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) - #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE +#ifndef CFG_TUD_CDC_TX_BUFSIZE + #define CFG_TUD_CDC_TX_BUFSIZE TUD_EPSIZE_BULK_MAX #endif -#ifndef CFG_TUD_CDC_EP_BUFSIZE - #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#ifndef CFG_TUD_CDC_RX_BUFSIZE + #define CFG_TUD_CDC_RX_BUFSIZE TUD_EPSIZE_BULK_MAX #endif -#ifdef __cplusplus - extern "C" { +// EP_BUFSIZE is separated to RX_EPSIZE and TX_EPSIZE +#ifndef CFG_TUD_CDC_RX_EPSIZE + #ifdef CFG_TUD_CDC_EP_BUFSIZE + #define CFG_TUD_CDC_RX_EPSIZE CFG_TUD_CDC_EP_BUFSIZE + #else + #define CFG_TUD_CDC_RX_EPSIZE TUD_EPSIZE_BULK_MAX + #endif #endif -//--------------------------------------------------------------------+ -// Driver Configuration -//--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED { - uint8_t rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect - uint8_t tx_persistent : 1; // keep tx fifo data even with reset or disconnect - uint8_t tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten -} tud_cdc_configure_t; +#ifndef CFG_TUD_CDC_TX_EPSIZE + #ifdef CFG_TUD_CDC_EP_BUFSIZE + #define CFG_TUD_CDC_TX_EPSIZE CFG_TUD_CDC_EP_BUFSIZE + #else + #define CFG_TUD_CDC_TX_EPSIZE TUD_EPSIZE_BULK_MAX + #endif +#endif -#define TUD_CDC_CONFIGURE_DEFAULT() { \ - .rx_persistent = 0, \ - .tx_persistent = 0, \ - .tx_overwritabe_if_not_connected = 1, \ -} +// Enable multi-packet RX transfer with ZLP termination for better throughput. Requires host support for ZLP. +#ifndef CFG_TUD_CDC_RX_NEED_ZLP + #define CFG_TUD_CDC_RX_NEED_ZLP 0 +#endif -// Configure CDC driver behavior -bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg); +// Keep rx fifo data even with bus reset or disconnect +#ifndef CFG_TUD_CDC_RX_PERSISTENT + #define CFG_TUD_CDC_RX_PERSISTENT 0 +#endif -// Backward compatible -#define tud_cdc_configure_fifo_t tud_cdc_configure_t -#define tud_cdc_configure_fifo tud_cdc_configure +// Keep tx fifo data even with bus reset or disconnect +#ifndef CFG_TUD_CDC_TX_PERSISTENT + #define CFG_TUD_CDC_TX_PERSISTENT 0 +#endif + +// If not connected, tx fifo can be overwritten +#ifndef CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED + #define CFG_TUD_CDC_TX_OVERWRITABLE_IF_NOT_CONNECTED 1 +#endif + +// Backward compatible: tud_cdc_configure_t and tud_cdc_configure() are no longer used. +// Configuration is now done via compile-time macros above. +typedef struct { + bool rx_persistent; + bool tx_persistent; + bool tx_overwritabe_if_not_connected; +} tud_cdc_configure_t; + +#define tud_cdc_configure(_cfg) ((void)(_cfg)) +#define tud_cdc_configure_fifo_t tud_cdc_configure_t +#define tud_cdc_configure_fifo(_cfg) ((void)(_cfg)) //--------------------------------------------------------------------+ // Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ -// Check if interface is ready +// Check if the interface is ready bool tud_cdc_n_ready(uint8_t itf); -// Check if terminal is connected to this port +// Check if the terminal is connected to this port bool tud_cdc_n_connected(uint8_t itf); -// Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) +// Get the current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) uint8_t tud_cdc_n_get_line_state(uint8_t itf); // Get current line encoding: bit rate, stop bits parity etc .. @@ -127,16 +153,41 @@ uint32_t tud_cdc_n_write_flush(uint8_t itf); // Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. uint32_t tud_cdc_n_write_available(uint8_t itf); -// Clear the transmit FIFO +// Clear the TX FIFO bool tud_cdc_n_write_clear(uint8_t itf); - #if CFG_TUD_CDC_NOTIFY +bool tud_cdc_n_notify_msg(uint8_t itf, cdc_notify_msg_t *msg); + // Send UART status notification: DCD, DSR etc .. -bool tud_cdc_n_notify_uart_state(uint8_t itf, const cdc_notify_uart_state_t *state); +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_n_notify_uart_state(uint8_t itf, + const cdc_notify_uart_state_t *state) { + cdc_notify_msg_t notify_msg; + notify_msg.request.bmRequestType = CDC_REQ_TYPE_NOTIF; + notify_msg.request.bRequest = CDC_NOTIF_SERIAL_STATE; + notify_msg.request.wValue = 0; + notify_msg.request.wIndex = 0; // filled later + notify_msg.request.wLength = sizeof(cdc_notify_uart_state_t); + notify_msg.serial_state = *state; + return tud_cdc_n_notify_msg(itf, ¬ify_msg); +} // Send connection speed change notification -bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change); +TU_ATTR_ALWAYS_INLINE static inline bool +tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t *conn_speed_change) { + cdc_notify_msg_t notify_msg; + notify_msg.request.bmRequestType = CDC_REQ_TYPE_NOTIF; + notify_msg.request.bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE; + notify_msg.request.wValue = 0; + notify_msg.request.wIndex = 0; // filled later + notify_msg.request.wLength = sizeof(cdc_notify_conn_speed_change_t); + notify_msg.conn_speed_change = *conn_speed_change; + return tud_cdc_n_notify_msg(itf, ¬ify_msg); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_msg(cdc_notify_msg_t *msg) { + return tud_cdc_n_notify_msg(0, msg); +} TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_uart_state(const cdc_notify_uart_state_t* state) { return tud_cdc_n_notify_uart_state(0, state); @@ -257,4 +308,4 @@ bool cdcd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t re } #endif -#endif /* _TUSB_CDC_DEVICE_H_ */ +#endif /* TUSB_CDC_DEVICE_H_ */ diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index beef03eff..4441222c8 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -29,6 +29,8 @@ #include "tusb_option.h" +#include <stdint.h> + #if (CFG_TUH_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" @@ -41,13 +43,14 @@ #include "serial/pl2303.h" // Level where CFG_TUSB_DEBUG must be at least for this driver is logged -#ifndef CFG_TUH_CDC_LOG_LEVEL - #define CFG_TUH_CDC_LOG_LEVEL 2 -#endif + #ifndef CFG_TUH_CDC_LOG_LEVEL + #define CFG_TUH_CDC_LOG_LEVEL 2 + #endif -#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_CDC(_cdc, _format, ...) TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ - serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) + #define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) + #define TU_LOG_CDC(_cdc, _format, ...) \ + TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ + serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) //--------------------------------------------------------------------+ // Host CDC Interface @@ -96,6 +99,7 @@ typedef struct { typedef struct { TUH_EPBUF_DEF(tx, CFG_TUH_CDC_TX_EPSIZE); TUH_EPBUF_DEF(rx, CFG_TUH_CDC_RX_EPSIZE); + TUH_EPBUF_DEF(ctrl, 8); } cdch_epbuf_t; static cdch_interface_t cdch_data[CFG_TUH_CDC]; @@ -113,63 +117,59 @@ static void cdch_set_line_coding_stage1_baudrate_complete(tuh_xfer_t *xfer); static void cdch_set_line_coding_stage2_data_format_complete(tuh_xfer_t *xfer); //------------- ACM prototypes -------------// -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -//------------- FTDI prototypes -------------// -#if CFG_TUH_CDC_FTDI + //------------- FTDI prototypes -------------// + #if CFG_TUH_CDC_FTDI static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); -static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t *xfer); -static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool ftdi_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void ftdi_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif -//------------- CP210X prototypes -------------// -#if CFG_TUH_CDC_CP210X + //------------- CP210X prototypes -------------// + #if CFG_TUH_CDC_CP210X static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t cp210x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif -//------------- CH34x prototypes -------------// -#if CFG_TUH_CDC_CH34X + //------------- CH34x prototypes -------------// + #if CFG_TUH_CDC_CH34X static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; -static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t ch34x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif -//------------- PL2303 prototypes -------------// -#if CFG_TUH_CDC_PL2303 + //------------- PL2303 prototypes -------------// + #if CFG_TUH_CDC_PL2303 static uint16_t const pl2303_vid_pid_list[][2] = {CFG_TUH_CDC_PL2303_VID_PID_LIST}; static const pl2303_type_data_t pl2303_type_data[PL2303_TYPE_COUNT] = {PL2303_TYPE_DATA}; -static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool pl2303_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool pl2303_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t pl2303_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif //------------- Common -------------// enum { @@ -197,11 +197,12 @@ enum { typedef bool (*serial_driver_func_t)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); typedef struct { - uint16_t const (*vid_pid_list)[2]; - uint16_t const vid_pid_count; - bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); - bool (*const process_set_config)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); - void (*const request_complete)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); // internal request complete handler to update line state + const uint16_t (*vid_pid_list)[2]; + const uint16_t vid_pid_count; + uint16_t (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); + bool (*const process_set_config)(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); + // internal request complete handler to update line state + void (*const request_complete)(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); serial_driver_func_t set_control_line_state, set_baudrate, set_data_format, set_line_coding; @@ -216,88 +217,91 @@ typedef struct { #define DRIVER_NAME_DECLARE(_str) #endif +// clang-format off // Note driver list must be in the same order as SERIAL_DRIVER enum static const cdch_serial_driver_t serial_drivers[] = { { - .vid_pid_list = NULL, - .vid_pid_count = 0, - .open = acm_open, - .process_set_config = acm_process_set_config, - .request_complete = acm_internal_control_complete, - .set_control_line_state = acm_set_control_line_state, - .set_baudrate = acm_set_line_coding, - .set_data_format = acm_set_line_coding, - .set_line_coding = acm_set_line_coding, - DRIVER_NAME_DECLARE("ACM") + .vid_pid_list = NULL, + .vid_pid_count = 0, + .open = acm_open, + .process_set_config = acm_process_set_config, + .request_complete = acm_internal_control_complete, + .set_control_line_state = acm_set_control_line_state, + .set_baudrate = acm_set_line_coding, + .set_data_format = acm_set_line_coding, + .set_line_coding = acm_set_line_coding, + DRIVER_NAME_DECLARE("ACM") }, #if CFG_TUH_CDC_FTDI { - .vid_pid_list = ftdi_vid_pid_list, - .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), - .open = ftdi_open, - .process_set_config = ftdi_proccess_set_config, - .request_complete = ftdi_internal_control_complete, - .set_control_line_state = ftdi_set_modem_ctrl, - .set_baudrate = ftdi_set_baudrate, - .set_data_format = ftdi_set_data_format, - .set_line_coding = NULL, // 2 stage set line coding - DRIVER_NAME_DECLARE("FTDI") + .vid_pid_list = ftdi_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), + .open = ftdi_open, + .process_set_config = ftdi_process_set_config, + .request_complete = ftdi_internal_control_complete, + .set_control_line_state = ftdi_set_modem_ctrl, + .set_baudrate = ftdi_set_baudrate, + .set_data_format = ftdi_set_data_format, + .set_line_coding = NULL, // 2 stage set line coding + DRIVER_NAME_DECLARE("FTDI") }, #endif #if CFG_TUH_CDC_CP210X { - .vid_pid_list = cp210x_vid_pid_list, - .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), - .open = cp210x_open, - .process_set_config = cp210x_process_set_config, - .request_complete = cp210x_internal_control_complete, - .set_control_line_state = cp210x_set_modem_ctrl, - .set_baudrate = cp210x_set_baudrate, - .set_data_format = cp210x_set_data_format, - .set_line_coding = NULL, // 2 stage set line coding - DRIVER_NAME_DECLARE("CP210x") + .vid_pid_list = cp210x_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), + .open = cp210x_open, + .process_set_config = cp210x_process_set_config, + .request_complete = cp210x_internal_control_complete, + .set_control_line_state = cp210x_set_modem_ctrl, + .set_baudrate = cp210x_set_baudrate, + .set_data_format = cp210x_set_data_format, + .set_line_coding = NULL, // 2 stage set line coding + DRIVER_NAME_DECLARE("CP210x") }, #endif #if CFG_TUH_CDC_CH34X { - .vid_pid_list = ch34x_vid_pid_list, - .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), - .open = ch34x_open, - .process_set_config = ch34x_process_set_config, - .request_complete = ch34x_internal_control_complete, + .vid_pid_list = ch34x_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), + .open = ch34x_open, + .process_set_config = ch34x_process_set_config, + .request_complete = ch34x_internal_control_complete, - .set_control_line_state = ch34x_set_modem_ctrl, - .set_baudrate = ch34x_set_baudrate, - .set_data_format = ch34x_set_data_format, - .set_line_coding = NULL, // 2 stage set line coding - DRIVER_NAME_DECLARE("CH34x") + .set_control_line_state = ch34x_set_modem_ctrl, + .set_baudrate = ch34x_set_baudrate, + .set_data_format = ch34x_set_data_format, + .set_line_coding = NULL, // 2 stage set line coding + DRIVER_NAME_DECLARE("CH34x") }, #endif #if CFG_TUH_CDC_PL2303 { - .vid_pid_list = pl2303_vid_pid_list, - .vid_pid_count = TU_ARRAY_SIZE(pl2303_vid_pid_list), - .open = pl2303_open, - .process_set_config = pl2303_process_set_config, - .request_complete = pl2303_internal_control_complete, - .set_control_line_state = pl2303_set_modem_ctrl, - .set_baudrate = pl2303_set_line_coding, - .set_data_format = pl2303_set_line_coding, - .set_line_coding = pl2303_set_line_coding, - DRIVER_NAME_DECLARE("PL2303") + .vid_pid_list = pl2303_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(pl2303_vid_pid_list), + .open = pl2303_open, + .process_set_config = pl2303_process_set_config, + .request_complete = pl2303_internal_control_complete, + .set_control_line_state = pl2303_set_modem_ctrl, + .set_baudrate = pl2303_set_line_coding, + .set_data_format = pl2303_set_line_coding, + .set_line_coding = pl2303_set_line_coding, + DRIVER_NAME_DECLARE("PL2303") } #endif }; +// clang-format on TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial driver count mismatch"); //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static bool open_ep_stream_pair(cdch_interface_t *p_cdc, const tusb_desc_endpoint_t *desc_ep); TU_ATTR_ALWAYS_INLINE static inline cdch_interface_t * get_itf(uint8_t idx) { TU_ASSERT(idx < CFG_TUH_CDC, NULL); @@ -364,7 +368,7 @@ static cdch_interface_t* get_itf_by_xfer(const tuh_xfer_t * xfer) { #endif default: - break; + break; // unknown driver } } } @@ -389,8 +393,6 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons return NULL; } -static bool open_ep_stream_pair(cdch_interface_t * p_cdc , tusb_desc_endpoint_t const *desc_ep); - //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ @@ -471,25 +473,26 @@ bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding) uint32_t tuh_cdc_write(uint8_t idx, void const * buffer, uint32_t bufsize) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write(p_cdc->daddr, &p_cdc->stream.tx, buffer, bufsize); + return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize); } uint32_t tuh_cdc_write_flush(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_xfer(p_cdc->daddr, &p_cdc->stream.tx); + return tu_edpt_stream_write_xfer(&p_cdc->stream.tx); } bool tuh_cdc_write_clear(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_clear(&p_cdc->stream.tx); + tu_edpt_stream_clear(&p_cdc->stream.tx); + return true; } uint32_t tuh_cdc_write_available(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_available(p_cdc->daddr, &p_cdc->stream.tx); + return tu_edpt_stream_write_available(&p_cdc->stream.tx); } //--------------------------------------------------------------------+ @@ -499,7 +502,7 @@ uint32_t tuh_cdc_write_available(uint8_t idx) { uint32_t tuh_cdc_read (uint8_t idx, void * buffer, uint32_t bufsize) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_read(p_cdc->daddr, &p_cdc->stream.rx, buffer, bufsize); + return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize); } uint32_t tuh_cdc_read_available(uint8_t idx) { @@ -518,9 +521,9 @@ bool tuh_cdc_read_clear (uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx); - tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); - return ret; + tu_edpt_stream_clear(&p_cdc->stream.rx); + (void)tu_edpt_stream_read_xfer(&p_cdc->stream.rx); + return true; } //--------------------------------------------------------------------+ @@ -602,7 +605,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, p_cdc->requested_line.coding = *line_coding; p_cdc->user_complete_cb = complete_cb; - if (driver->set_line_coding) { + if (driver->set_line_coding != NULL) { // driver support set_line_coding request TU_VERIFY(driver->set_line_coding(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -611,7 +614,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, } } else { // driver does not support set_line_coding and need 2 stage to set baudrate and data format separately - if (complete_cb) { + if (complete_cb != NULL) { // non-blocking TU_VERIFY(driver->set_baudrate(p_cdc, cdch_set_line_coding_stage1_baudrate_complete, user_data)); } else { @@ -619,7 +622,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, xfer_result_t result = XFER_RESULT_INVALID; TU_VERIFY(driver->set_baudrate(p_cdc, NULL, (uintptr_t) &result)); - if (user_data) { + if (user_data != 0) { *((xfer_result_t *) user_data) = result; } TU_VERIFY(result == XFER_RESULT_SUCCESS); @@ -627,7 +630,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, result = XFER_RESULT_INVALID; TU_VERIFY(driver->set_data_format(p_cdc, NULL, (uintptr_t) &result)); - if (user_data) { + if (user_data != 0) { *((xfer_result_t *) user_data) = result; } TU_VERIFY(result == XFER_RESULT_SUCCESS); @@ -648,13 +651,10 @@ bool cdch_init(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t *p_cdc = &cdch_data[i]; cdch_epbuf_t *epbuf = &cdch_epbuf[i]; - tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, - p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, - epbuf->tx, CFG_TUH_CDC_TX_EPSIZE); - - tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, - p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, - epbuf->rx, CFG_TUH_CDC_RX_EPSIZE); + TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, + CFG_TUH_CDC_TX_BUFSIZE, epbuf->tx)); + TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, p_cdc->stream.rx_ff_buf, + CFG_TUH_CDC_RX_BUFSIZE, epbuf->rx)); } return true; @@ -663,8 +663,8 @@ bool cdch_init(void) { bool cdch_deinit(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t *p_cdc = &cdch_data[i]; - tu_edpt_stream_deinit(&p_cdc->stream.tx); - tu_edpt_stream_deinit(&p_cdc->stream.rx); + (void)tu_edpt_stream_deinit(&p_cdc->stream.tx); + (void)tu_edpt_stream_deinit(&p_cdc->stream.rx); } return true; } @@ -674,11 +674,9 @@ void cdch_close(uint8_t daddr) { cdch_interface_t *p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { TU_LOG_CDC(p_cdc, "close"); + tuh_cdc_umount_cb(idx); // invoke callback - // Invoke application callback - tuh_cdc_umount_cb(idx); - - p_cdc->daddr = 0; + p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; p_cdc->mounted = false; tu_edpt_stream_close(&p_cdc->stream.tx); @@ -696,13 +694,12 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT(p_cdc); if (ep_addr == p_cdc->stream.tx.ep_addr) { - // invoke tx complete callback to possibly refill tx fifo - tuh_cdc_tx_complete_cb(idx); + tuh_cdc_tx_complete_cb(idx); // invoke transmit complete callback - if (0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx)) { + if (0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx)) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero - tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); + (void)tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); } } else if (ep_addr == p_cdc->stream.rx.ep_addr) { #if CFG_TUH_CDC_FTDI @@ -718,16 +715,15 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t #endif { tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - tuh_cdc_rx_cb(idx); // invoke receive callback } // prepare for next transfer if needed - tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx); + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); } else if (ep_addr == p_cdc->ep_notif) { // TODO handle notification endpoint } else { - TU_ASSERT(false); + return false; } return true; @@ -736,27 +732,23 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ - static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t const *desc_ep) { for (size_t i = 0; i < 2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && - TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); + const uint8_t ep_dir = tu_edpt_dir(desc_ep->bEndpointAddress); + tu_edpt_stream_t *stream = (ep_dir == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx; + tu_edpt_stream_open(stream, p_cdc->daddr, desc_ep, tu_edpt_packet_size(desc_ep)); + tu_edpt_stream_clear(stream); - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - tu_edpt_stream_open(&p_cdc->stream.rx, desc_ep); - } else { - tu_edpt_stream_open(&p_cdc->stream.tx, desc_ep); - } - - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep); + desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(desc_ep); } return true; } -bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - (void) rhport; +uint16_t cdch_open(uint8_t rhport, uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { + (void)rhport; // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && @@ -765,52 +757,36 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d } else if (SERIAL_DRIVER_COUNT > 1 && TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { uint16_t vid, pid; - TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); + TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid), 0); - for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { - const cdch_serial_driver_t *driver = &serial_drivers[dr]; + for (size_t drv = 1; drv < SERIAL_DRIVER_COUNT; drv++) { + const cdch_serial_driver_t *driver = &serial_drivers[drv]; for (size_t i = 0; i < driver->vid_pid_count; i++) { if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { - const bool ret = driver->open(daddr, itf_desc, max_len); - TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver->name, ret ? "OK" : "FAILED"); - return ret; + const uint16_t drv_len = driver->open(daddr, itf_desc, max_len); + TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver->name, + drv_len > 0 ? "OK" : "FAILED"); + return drv_len; } } } + } else { + // not supported class } - return false; -} - -bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { - tusb_control_request_t request; - request.wIndex = tu_htole16((uint16_t) itf_num); - uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_CDC(p_cdc, "set config"); - - // fake transfer to kick-off process_set_config() - tuh_xfer_t xfer; - xfer.daddr = daddr; - xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; - xfer.user_data = 0; // initial state 0 - cdch_process_set_config(&xfer); - - return true; + return 0; } static void set_config_complete(cdch_interface_t *p_cdc, bool success) { if (success) { const uint8_t idx = get_idx_by_ptr(p_cdc); - p_cdc->mounted = true; + p_cdc->mounted = true; tuh_cdc_mount_cb(idx); // Prepare for incoming data - tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); } else { // clear the interface entry - p_cdc->daddr = 0; + p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; } @@ -819,6 +795,33 @@ static void set_config_complete(cdch_interface_t *p_cdc, bool success) { usbh_driver_set_config_complete(p_cdc->daddr, p_cdc->bInterfaceNumber + itf_offset); } +bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { + const uint8_t idx = tuh_cdc_itf_get_index(daddr, itf_num); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_CDC(p_cdc, "set config"); + + // fake transfer to kick-off process_set_config() + tusb_control_request_t request; + request.wIndex = tu_htole16((uint16_t)itf_num); + + tuh_xfer_t xfer; + xfer.daddr = daddr; + xfer.ep_addr = 0; + xfer.result = XFER_RESULT_SUCCESS; + xfer.setup = &request; + xfer.complete_cb = NULL; + xfer.buffer = NULL; + xfer.user_data = 0; // initial state 0 + + const cdch_serial_driver_t *driver = &serial_drivers[p_cdc->serial_drid]; + if (!driver->process_set_config(p_cdc, &xfer)) { + set_config_complete(p_cdc, false); + } + + return true; +} + static void cdch_process_set_config(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); @@ -830,13 +833,16 @@ static void cdch_process_set_config(tuh_xfer_t *xfer) { } } +// return false if there is no active transfer static bool set_line_state_on_enum(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { enum { ENUM_SET_LINE_CODING = 0, ENUM_SET_LINE_CONTROL, ENUM_SET_LINE_COMPLETE, }; + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM const uint8_t idx = get_idx_by_ptr(p_cdc); + #endif const uintptr_t state = xfer->user_data; switch (state) { @@ -894,7 +900,7 @@ static void cdch_internal_control_complete(tuh_xfer_t *xfer) { // Invoke application callback xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -910,7 +916,7 @@ static void cdch_set_line_coding_stage1_baudrate_complete(tuh_xfer_t *xfer) { TU_ASSERT(driver->set_data_format(p_cdc, cdch_set_line_coding_stage2_data_format_complete, xfer->user_data),); } else { xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -926,7 +932,7 @@ static void cdch_set_line_coding_stage2_data_format_complete(tuh_xfer_t *xfer) { } xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -950,12 +956,12 @@ static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *x break; default: - break; + break; // unknown request } } static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm.capability.support_line_request); + TU_VERIFY(p_cdc->acm.capability.support_line_request != 0); const tusb_control_request_t request = { .bmRequestType_bit = { @@ -982,7 +988,7 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co } static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm.capability.support_line_request); + TU_VERIFY(p_cdc->acm.capability.support_line_request != 0); TU_VERIFY((p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8) || p_cdc->requested_line.coding.data_bits == 16); @@ -998,15 +1004,16 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ .wLength = tu_htole16((uint16_t) sizeof(cdc_line_coding_t)) }; - // use usbh enum buf to hold line coding since user line_coding variable does not live long enough - uint8_t *enum_buf = usbh_get_enum_buf(); - memcpy(enum_buf, &p_cdc->requested_line.coding, sizeof(cdc_line_coding_t)); + // use local ctrl buf to hold line coding since user line_coding variable does not live long enough + uint8_t const idx = get_idx_by_ptr(p_cdc); + uint8_t *ctrl_buf = cdch_epbuf[idx].ctrl; + memcpy(ctrl_buf, &p_cdc->requested_line.coding, sizeof(cdc_line_coding_t)); tuh_xfer_t xfer = { .daddr = p_cdc->daddr, .ep_addr = 0, .setup = &request, - .buffer = enum_buf, + .buffer = ctrl_buf, .complete_cb = complete_cb, .user_data = user_data }; @@ -1019,19 +1026,19 @@ enum { CONFIG_ACM_COMPLETE = 0 }; -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - uint8_t const *p_desc_end = ((uint8_t const *) itf_desc) + max_len; +static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { + const uint8_t *p_desc = (const uint8_t *)itf_desc; + const uint8_t *desc_end = p_desc + max_len; cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_ACM; //------------- Control Interface -------------// - uint8_t const *p_desc = tu_desc_next(itf_desc); + p_desc = tu_desc_next(p_desc); // Communication Functional Descriptors - while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { + while ((p_desc < desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) { // save ACM bmCapabilities p_cdc->acm.capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; @@ -1042,26 +1049,27 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint1 // Open notification endpoint of control interface if any if (itf_desc->bNumEndpoints == 1) { - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; + TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0); p_cdc->ep_notif = desc_ep->bEndpointAddress; p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass)) { - // next to endpoint descriptor - p_desc = tu_desc_next(p_desc); + if (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) { + const tusb_desc_interface_t *data_itf = (const tusb_desc_interface_t *)p_desc; + if (data_itf->bInterfaceClass == TUSB_CLASS_CDC_DATA) { + p_desc = tu_desc_next(p_desc); // next to endpoint descriptor - // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); + // data endpoints expected to be in pairs + TU_ASSERT(open_ep_stream_pair(p_cdc, (const tusb_desc_endpoint_t *)p_desc), 0); + p_desc += data_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + } } - return true; + return (uint16_t)((uintptr_t)p_desc - (uintptr_t)itf_desc); } static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { @@ -1136,7 +1144,6 @@ static inline bool ftdi_sio_reset(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet // internal control complete to update state such as line state, line_coding static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t *xfer) { - TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); const tusb_control_request_t * setup = xfer->setup; if (xfer->result == XFER_RESULT_SUCCESS) { if (setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && @@ -1168,10 +1175,10 @@ static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint32_t index_value = ftdi_get_divisor(p_cdc); - TU_VERIFY(index_value); + TU_VERIFY(index_value != 0); uint16_t value = (uint16_t) index_value; uint16_t index = (uint16_t) (index_value >> 16); - if (p_cdc->ftdi.channel) { + if (p_cdc->ftdi.channel != 0) { index = (uint16_t) ((index << 8) | p_cdc->ftdi.channel); } @@ -1195,46 +1202,40 @@ enum { CONFIG_FTDI_COMPLETE }; -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { +static uint16_t ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // FTDI Interface includes 1 vendor interface + 2 bulk endpoints TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && - itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t) <= max_len); + itf_desc->bNumEndpoints == 2, + 0); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_FTDI; // endpoint pair - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(itf_desc); - /* - * NOTE: Some customers have programmed FT232R/FT245R devices - * with an endpoint size of 0 - not good. - */ - TU_ASSERT(desc_ep->wMaxPacketSize != 0); + /* NOTE: Some users have programmed FT232R/FT245R devices + * with an endpoint size of 0 !!! */ + TU_ASSERT(desc_ep->wMaxPacketSize != 0, 0); - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep), 0); + + return drv_len; } -static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { +static bool ftdi_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); const uintptr_t state = xfer->user_data; switch (state) { // from here sequence overtaken from Linux Kernel function ftdi_port_probe() case CONFIG_FTDI_DETERMINE_TYPE: // determine type - if (p_cdc->bInterfaceNumber == 0) { - TU_ASSERT(ftdi_determine_type(p_cdc)); - } else { - // other interfaces have same type as interface 0 - uint8_t const idx_itf0 = tuh_cdc_itf_get_index(xfer->daddr, 0); - cdch_interface_t const *p_cdc_itf0 = get_itf(idx_itf0); - TU_ASSERT(p_cdc_itf0); - p_cdc->ftdi.chip_type = p_cdc_itf0->ftdi.chip_type; - } + TU_ASSERT(ftdi_determine_type(p_cdc)); TU_ATTR_FALLTHROUGH; case CONFIG_FTDI_WRITE_LATENCY: @@ -1365,7 +1366,7 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { uint8_t divfrac[8] = {0, 3, 2, 4, 1, 5, 6, 7}; uint32_t divisor; /* divisor shifted 3 bits to the left */ - uint32_t divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); + uint32_t divisor3 = tu_div_round_nearest(base, 2 * baud); divisor = divisor3 >> 3; divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; /* Deal with special cases for highest baud rates. */ @@ -1373,6 +1374,8 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { divisor = 0; } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } else { + // nothing to do } return divisor; } @@ -1387,7 +1390,7 @@ static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) { uint32_t divisor3; /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ - divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud); + divisor3 = tu_div_round_nearest(8 * base, 10 * baud); divisor = divisor3 >> 3; divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; @@ -1396,12 +1399,13 @@ static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) { divisor = 0; } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } else { + // nothing to do } - /* - * Set this bit to turn off a divide by 2.5 on baud rate generator + + /* Set this bit to turn off a divide by 2.5 on baud rate generator * This enables baud rates up to 12Mbaud but cannot reach below 1200 - * baud with this bit set - */ + * baud with this bit set */ divisor |= 0x00020000; return divisor; } @@ -1413,7 +1417,7 @@ static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) { static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { uint32_t baud = p_cdc->requested_line.coding.bit_rate; uint32_t div_value = 0; - TU_VERIFY(baud); + TU_VERIFY(baud != 0); switch (p_cdc->ftdi.chip_type) { case FTDI_UNKNOWN: @@ -1489,7 +1493,7 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { //------------- Control Request -------------// static bool cp210x_set_request(cdch_interface_t * p_cdc, uint8_t command, uint16_t value, - uint8_t * buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t const * buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, @@ -1502,19 +1506,20 @@ static bool cp210x_set_request(cdch_interface_t * p_cdc, uint8_t command, uint16 .wLength = tu_htole16(length) }; - // use usbh enum buf since application variable does not live long enough - uint8_t * enum_buf = NULL; + // use local ctrl buf since application variable does not live long enough + uint8_t * ctrl_buf = NULL; if (buffer && length > 0) { - enum_buf = usbh_get_enum_buf(); - tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length); + uint8_t const idx = get_idx_by_ptr(p_cdc); + ctrl_buf = cdch_epbuf[idx].ctrl; + tu_memcpy_s(ctrl_buf, sizeof(cdch_epbuf[idx].ctrl), buffer, length); } tuh_xfer_t xfer = { .daddr = p_cdc->daddr, .ep_addr = 0, .setup = &request, - .buffer = enum_buf, + .buffer = ctrl_buf, .complete_cb = complete_cb, .user_data = user_data }; @@ -1553,14 +1558,15 @@ static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; break; - default: break; + default: + break; // unsupported request } } static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support" uint32_t baud_le = tu_htole32(p_cdc->requested_line.coding.bit_rate); - return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); + return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t const *) &baud_le, 4, complete_cb, user_data); } static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -1583,21 +1589,23 @@ enum { CONFIG_CP210X_COMPLETE }; -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +static uint16_t cp210x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // CP210x Interface includes 1 vendor interface + 2 bulk endpoints - TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2, 0); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_CP210X; - // endpoint pair - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(itf_desc); + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); + + return drv_len; } static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { @@ -1635,7 +1643,7 @@ static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc); //------------- Control Request -------------// static bool ch34x_set_request(cdch_interface_t *p_cdc, uint8_t direction, uint8_t request, - uint16_t value, uint16_t index, uint8_t *buffer, uint16_t length, + uint16_t value, uint16_t index, uint8_t const *buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request_setup = { .bmRequestType_bit = { @@ -1649,13 +1657,14 @@ static bool ch34x_set_request(cdch_interface_t *p_cdc, uint8_t direction, uint8_ .wLength = tu_htole16(length) }; - // use usbh enum buf since application variable does not live long enough - uint8_t *enum_buf = NULL; + // use local ctrl buf since application variable does not live long enough + uint8_t *ctrl_buf = NULL; - if (buffer && length > 0) { - enum_buf = usbh_get_enum_buf(); - if (direction == TUSB_DIR_OUT) { - tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length); + if (length > 0) { + uint8_t const idx = get_idx_by_ptr(p_cdc); + ctrl_buf = cdch_epbuf[idx].ctrl; + if (buffer && direction == TUSB_DIR_OUT) { + tu_memcpy_s(ctrl_buf, sizeof(cdch_epbuf[idx].ctrl), buffer, length); } } @@ -1663,7 +1672,7 @@ static bool ch34x_set_request(cdch_interface_t *p_cdc, uint8_t direction, uint8_ .daddr = p_cdc->daddr, .ep_addr = 0, .setup = &request_setup, - .buffer = enum_buf, + .buffer = ctrl_buf, .complete_cb = complete_cb, .user_data = user_data }; @@ -1677,8 +1686,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool ch34x_control_out(cdch_interface_t *p_c } TU_ATTR_ALWAYS_INLINE static inline bool ch34x_control_in(cdch_interface_t *p_cdc, uint8_t request, uint16_t value, uint16_t index, - uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize, + uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, NULL, buffersize, complete_cb, user_data); } @@ -1687,12 +1696,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool ch34x_write_reg(cdch_interface_t *p_cdc return ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, reg, reg_value, complete_cb, user_data); } -//static bool ch34x_read_reg_request ( cdch_interface_t * p_cdc, uint16_t reg, -// uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) -//{ -// return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); -//} - //------------- Driver API -------------// // internal control complete to update state such as line state, encoding @@ -1714,7 +1717,8 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; break; - default: break; + default: + break; // unsupported } break; @@ -1722,19 +1726,20 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.control_state = p_cdc->requested_line.control_state; break; - default: break; + default: + break; // unsupported request } } static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { const uint8_t lcr = ch34x_get_lcr(p_cdc); - TU_VERIFY(lcr); + TU_VERIFY(lcr > 0); return ch34x_write_reg(p_cdc, CH32X_REG16_LCR2_LCR, lcr, complete_cb, user_data); } static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { const uint16_t div_ps = ch34x_get_divisor_prescaler(p_cdc); - TU_VERIFY(div_ps); + TU_VERIFY(div_ps > 0); return ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data); } @@ -1755,29 +1760,30 @@ enum { CONFIG_CH34X_COMPLETE }; -static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { +static uint16_t ch34x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // CH34x Interface includes 1 vendor interface + 2 bulk + 1 interrupt endpoints - TU_VERIFY(itf_desc->bNumEndpoints == 3); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(itf_desc->bNumEndpoints == 3, 0); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_CH34X; - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(itf_desc); // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); - desc_ep += 2; + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep), 0); + desc_ep = (const tusb_desc_endpoint_t *)((uintptr_t)desc_ep + 2 * sizeof(tusb_desc_endpoint_t)); // Interrupt endpoint: not used for now - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && - TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0); p_cdc->ep_notif = desc_ep->bEndpointAddress; - return true; + return drv_len; } static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { @@ -1786,8 +1792,7 @@ static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) switch (state) { case CONFIG_CH34X_READ_VERSION: { - uint8_t* enum_buf = usbh_get_enum_buf(); - TU_ASSERT(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, enum_buf, 2, + TU_ASSERT(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, 2, cdch_process_set_config, CONFIG_CH34X_SERIAL_INIT)); break; } @@ -1917,7 +1922,8 @@ static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE | CH34X_LCR_PAR_EVEN; break; - default: break; + default: + break; // invalid parity } // 1.5 stop bits not supported @@ -1941,7 +1947,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ //------------- Control Request -------------// static bool pl2303_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t requesttype, - uint16_t value, uint16_t index, uint8_t *buffer, uint16_t length, + uint16_t value, uint16_t index, uint8_t const *buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request_setup = { .bmRequestType = requesttype, @@ -1951,13 +1957,14 @@ static bool pl2303_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t .wLength = tu_htole16(length) }; - // use usbh enum buf since application variable does not live long enough - uint8_t *enum_buf = NULL; + // use local ctrl buf since application variable does not live long enough + uint8_t *ctrl_buf = NULL; - if (buffer && length > 0) { - enum_buf = usbh_get_enum_buf(); - if (request_setup.bmRequestType_bit.direction == TUSB_DIR_OUT) { - tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length); + if (length > 0) { + uint8_t const idx = get_idx_by_ptr(p_cdc); + ctrl_buf = cdch_epbuf[idx].ctrl; + if (buffer && request_setup.bmRequestType_bit.direction == TUSB_DIR_OUT) { + tu_memcpy_s(ctrl_buf, sizeof(cdch_epbuf[idx].ctrl), buffer, length); } } @@ -1965,7 +1972,7 @@ static bool pl2303_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t .daddr = p_cdc->daddr, .ep_addr = 0, .setup = &request_setup, - .buffer = enum_buf, + .buffer = ctrl_buf, .complete_cb = complete_cb, .user_data = user_data }; @@ -1973,10 +1980,10 @@ static bool pl2303_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t return tuh_control_xfer(&xfer); } -static bool pl2303_vendor_read(cdch_interface_t *p_cdc, uint16_t value, uint8_t *buf, +static bool pl2303_vendor_read(cdch_interface_t *p_cdc, uint16_t value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint8_t request = p_cdc->pl2303.type == PL2303_TYPE_HXN ? PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; - return pl2303_set_request(p_cdc, request, PL2303_VENDOR_READ_REQUEST_TYPE, value, 0, buf, 1, complete_cb, user_data); + return pl2303_set_request(p_cdc, request, PL2303_VENDOR_READ_REQUEST_TYPE, value, 0, NULL, 1, complete_cb, user_data); } static bool pl2303_vendor_write(cdch_interface_t *p_cdc, uint16_t value, uint16_t index, @@ -1986,9 +1993,8 @@ static bool pl2303_vendor_write(cdch_interface_t *p_cdc, uint16_t value, uint16_ } static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t buf = 0; return pl2303_set_request(p_cdc, PL2303_VENDOR_READ_REQUEST, PL2303_VENDOR_READ_REQUEST_TYPE, PL2303_READ_TYPE_HX_STATUS, 0, - &buf, 1, complete_cb, user_data); + NULL, 1, complete_cb, user_data); } //static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) { @@ -2000,13 +2006,15 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_c // return pl2303_set_request(p_cdc, PL2303_BREAK_REQUEST, PL2303_BREAK_REQUEST_TYPE, state, 0, NULL, 0); //} -static inline int pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool +pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { /* we don't care if it wasn't halted first. in fact some devices * (like some ibmcam model 1 units) seem to expect hosts to make * this request for iso endpoints, which can't halt! */ - return pl2303_set_request(p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, - NULL, 0, complete_cb, user_data); + return pl2303_set_request( + p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, NULL, 0, + complete_cb, user_data); } //------------- Driver API -------------// @@ -2088,13 +2096,15 @@ enum { CONFIG_PL2303_COMPLETE }; -static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +static uint16_t pl2303_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // PL2303 Interface includes 1 vendor interface + 1 interrupt endpoints + 2 bulk - TU_VERIFY(itf_desc->bNumEndpoints == 3); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(itf_desc->bNumEndpoints == 3, 0); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_PL2303; p_cdc->pl2303.quirks = 0; @@ -2103,23 +2113,21 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); // Interrupt endpoint: not used for now - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && - TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0); p_cdc->ep_notif = desc_ep->bEndpointAddress; desc_ep += 1; // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep), 0); - return true; + return drv_len; } static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { // state CONFIG_PL2303_READ1 may have no success due to expected stall by pl2303_supports_hx_status() const uintptr_t state = xfer->user_data; TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1); - uint8_t* enum_buf = usbh_get_enum_buf(); pl2303_type_t type; switch (state) { @@ -2131,10 +2139,9 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) if (type == PL2303_TYPE_NEED_SUPPORTS_HX_STATUS) { TU_ASSERT(pl2303_supports_hx_status(p_cdc, cdch_process_set_config, CONFIG_PL2303_READ1)); break; - } else { - // no transfer triggered and continue with CONFIG_PL2303_READ1 - TU_ATTR_FALLTHROUGH; } + // no transfer triggered and continue with CONFIG_PL2303_READ1 + TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ1: // get supports_hx_status, type and quirks (step 2), do special read @@ -2151,7 +2158,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_WRITE1)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, cdch_process_set_config, CONFIG_PL2303_WRITE1)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2167,7 +2174,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ2: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_READ3)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, cdch_process_set_config, CONFIG_PL2303_READ3)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2175,7 +2182,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ3: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, enum_buf, cdch_process_set_config, CONFIG_PL2303_READ4)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, cdch_process_set_config, CONFIG_PL2303_READ4)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2183,7 +2190,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ4: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_WRITE2)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, cdch_process_set_config, CONFIG_PL2303_WRITE2)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2199,7 +2206,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ5: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_READ6)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, cdch_process_set_config, CONFIG_PL2303_READ6)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2207,7 +2214,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ6: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, enum_buf, cdch_process_set_config, CONFIG_PL2303_WRITE3)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, cdch_process_set_config, CONFIG_PL2303_WRITE3)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2379,10 +2386,12 @@ static pl2303_type_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { return PL2303_TYPE_HXN; default: - break; + break; // unknown device } break; - default: break; + + default: + break; // unknown device } TU_LOG_CDC(p_cdc, "unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); @@ -2444,8 +2453,9 @@ static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_B */ baseline = 12000000 * 32; mantissa = baseline / baud; - if (mantissa == 0) + if (mantissa == 0) { mantissa = 1; /* Avoid dividing by zero if baud > 32 * 12M. */ + } exponent = 0; while (mantissa >= 512) { if (exponent < 7) { @@ -2517,7 +2527,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ * Use direct method for supported baud rates, otherwise use divisors. * Newer chip types do not support divisor encoding. */ - if (type_data->no_divisors) { + if (type_data->no_divisors != 0) { baud_sup = baud; } else { baud_sup = pl2303_get_supported_baud_rate(baud); @@ -2525,7 +2535,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ if (baud == baud_sup) { baud = pl2303_encode_baud_rate_direct(buf, baud); - } else if (type_data->alt_divisors) { + } else if (type_data->alt_divisors != 0) { baud = pl2303_encode_baud_rate_divisor_alt(buf, baud); } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index bf6711d7e..1b1709b18 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -24,13 +24,13 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_CDC_HOST_H_ -#define _TUSB_CDC_HOST_H_ +#ifndef TUSB_CDC_HOST_H_ +#define TUSB_CDC_HOST_H_ #include "cdc.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif //--------------------------------------------------------------------+ @@ -39,22 +39,22 @@ // RX FIFO size #ifndef CFG_TUH_CDC_RX_BUFSIZE -#define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MAX #endif // RX Endpoint size #ifndef CFG_TUH_CDC_RX_EPSIZE -#define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MAX #endif // TX FIFO size #ifndef CFG_TUH_CDC_TX_BUFSIZE -#define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MAX #endif // TX Endpoint size #ifndef CFG_TUH_CDC_TX_EPSIZE -#define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MAX #endif //--------------------------------------------------------------------+ @@ -67,7 +67,7 @@ uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num); // Get Interface information // return true if index is correct and interface is currently mounted -bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info); +bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t *info); // Check if an interface is mounted bool tuh_cdc_mounted(uint8_t idx); @@ -75,7 +75,7 @@ bool tuh_cdc_mounted(uint8_t idx); // Get local (cached) line state // This function should return correct values if tuh_cdc_set_control_line_state() / tuh_cdc_get_control_line_state() // are invoked previously or CFG_TUH_CDC_LINE_STATE_ON_ENUM is defined. -bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state); +bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t *line_state); // Get current DTR status TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_dtr(uint8_t idx) { @@ -100,7 +100,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) { // This function should return correct values if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() // are invoked previously or CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined. // NOTE: This function does not make any USB transfer request to device. -bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t* line_coding); +bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t *line_coding); #define tuh_cdc_get_local_line_coding tuh_cdc_get_line_coding_local // backward compatibility @@ -112,7 +112,7 @@ bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t* line_coding); uint32_t tuh_cdc_write_available(uint8_t idx); // Write to cdc interface -uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize); +uint32_t tuh_cdc_write(uint8_t idx, const void *buffer, uint32_t bufsize); // Force sending data if possible, return number of forced bytes uint32_t tuh_cdc_write_flush(uint8_t idx); @@ -128,13 +128,13 @@ bool tuh_cdc_write_clear(uint8_t idx); uint32_t tuh_cdc_read_available(uint8_t idx); // Read from cdc interface -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize); +uint32_t tuh_cdc_read(uint8_t idx, void *buffer, uint32_t bufsize); // Get a byte from RX FIFO without removing it -bool tuh_cdc_peek(uint8_t idx, uint8_t* ch); +bool tuh_cdc_peek(uint8_t idx, uint8_t *ch); // Clear the received FIFO -bool tuh_cdc_read_clear (uint8_t idx); +bool tuh_cdc_read_clear(uint8_t idx); //--------------------------------------------------------------------+ // Control Request API @@ -149,16 +149,18 @@ bool tuh_cdc_read_clear (uint8_t idx); bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set DTR -TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdc_line_control_state_t line_state = { .dtr = dtr_state }; - line_state.rts = tuh_cdc_get_rts(idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, + uintptr_t user_data) { + cdc_line_control_state_t line_state = {.dtr = dtr_state}; + line_state.rts = tuh_cdc_get_rts(idx); return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); } // Request to Set RTS -TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdc_line_control_state_t line_state = { .rts = rts_state }; - line_state.dtr = tuh_cdc_get_dtr(idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, + uintptr_t user_data) { + cdc_line_control_state_t line_state = {.rts = rts_state}; + line_state.dtr = tuh_cdc_get_dtr(idx); return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); } @@ -166,11 +168,13 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_s bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to set data format -bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set Line Coding = baudrate + data format // Note: only implemented by ACM and CH34x, not supported by FTDI and CP210x yet -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool tuh_cdc_set_line_coding(uint8_t idx, const cdc_line_coding_t *line_coding, tuh_xfer_cb_t complete_cb, + uintptr_t user_data); // Request to Get Line Coding (ACM only) // Should only use if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() never got invoked and @@ -179,11 +183,13 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // Connect by set both DTR, RTS TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data); + return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, + user_data); } // Disconnect by clear both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, + uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data); } @@ -192,7 +198,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfe // Each Function will make a USB control transfer request to/from device the function will block until request is // complete. The function will return the transfer request result //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_control_line_state_sync(uint8_t idx, uint16_t line_state) { +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_control_line_state_sync(uint8_t idx, + uint16_t line_state) { TU_API_SYNC(tuh_cdc_set_control_line_state, idx, line_state); } @@ -208,11 +215,13 @@ TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_baudrate_sync TU_API_SYNC(tuh_cdc_set_baudrate, idx, baudrate); } -TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_data_format_sync(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits) { +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_data_format_sync(uint8_t idx, uint8_t stop_bits, + uint8_t parity, uint8_t data_bits) { TU_API_SYNC(tuh_cdc_set_data_format, idx, stop_bits, parity, data_bits); } -TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_line_coding_sync(uint8_t idx, cdc_line_coding_t const* line_coding) { +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t +tuh_cdc_set_line_coding_sync(uint8_t idx, const cdc_line_coding_t *line_coding) { TU_API_SYNC(tuh_cdc_set_line_coding, idx, line_coding); } @@ -244,15 +253,15 @@ extern void tuh_cdc_tx_complete_cb(uint8_t idx); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -bool cdch_init (void); -bool cdch_deinit (void); -bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close (uint8_t dev_addr); +bool cdch_init(void); +bool cdch_deinit(void); +uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close(uint8_t dev_addr); #ifdef __cplusplus - } +} #endif -#endif /* _TUSB_CDC_HOST_H_ */ +#endif /* TUSB_CDC_HOST_H_ */ diff --git a/src/class/cdc/cdc_rndis.h b/src/class/cdc/cdc_rndis.h index ad153e0ac..fbbd43206 100644 --- a/src/class/cdc/cdc_rndis.h +++ b/src/class/cdc/cdc_rndis.h @@ -30,8 +30,8 @@ * \defgroup CDC_RNDIS_Common Common Definitions * @{ */ -#ifndef _TUSB_CDC_RNDIS_H_ -#define _TUSB_CDC_RNDIS_H_ +#ifndef TUSB_CDC_RNDIS_H_ +#define TUSB_CDC_RNDIS_H_ #include "cdc.h" @@ -295,7 +295,7 @@ typedef enum } #endif -#endif /* _TUSB_CDC_RNDIS_H_ */ +#endif /* TUSB_CDC_RNDIS_H_ */ /** @} */ /** @} */ diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c deleted file mode 100644 index e975ea440..000000000 --- a/src/class/cdc/cdc_rndis_host.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * 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: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "cdc_host.h" -#include "cdc_rndis_host.h" - -#if 0 // TODO remove subtask related macros later -// Sub Task -#define OSAL_SUBTASK_BEGIN -#define OSAL_SUBTASK_END return TUSB_ERROR_NONE; - -#define STASK_RETURN(_error) return _error; -#define STASK_INVOKE(_subtask, _status) (_status) = _subtask -#define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define RNDIS_MSG_PAYLOAD_MAX (1024*4) - -CFG_TUH_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; - -static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX]; - -// TODO Microsoft requires message length for any get command must be at least 4096 bytes - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static tusb_error_t rndis_body_subtask(void); -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response ); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) -{ - TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); - TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); - - memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ - -// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper -// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with -// forever loop cannot have any return at all. -OSAL_TASK_FUNCTION(cdch_rndis_task) (void* param;) -{ - OSAL_TASK_BEGIN - rndis_body_subtask(); - OSAL_TASK_END -} - -static tusb_error_t rndis_body_subtask(void) -{ - static uint8_t relative_addr; - - OSAL_SUBTASK_BEGIN - - for (relative_addr = 0; relative_addr < CFG_TUH_DEVICE_MAX; relative_addr++) - { - - } - - tusb_time_delay_ms_api(100); - - OSAL_SUBTASK_END -} - -//--------------------------------------------------------------------+ -// RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -void rndish_init(void) -{ - tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUH_DEVICE_MAX); - - //------------- Task creation -------------// - - //------------- semaphore creation for notification pipe -------------// - for(uint8_t i=0; i<CFG_TUH_DEVICE_MAX; i++) - { - rndish_data[i].sem_notification_hdl = osal_semaphore_create( OSAL_SEM_REF(rndish_data[i].semaphore_notification) ); - } -} - -void rndish_close(uint8_t dev_addr) -{ - osal_semaphore_reset( rndish_data[dev_addr-1].sem_notification_hdl ); -// tu_memclr(&rndish_data[dev_addr-1], sizeof(rndish_data_t)); TODO need to move semaphore & its handle out before memclr -} - - -static rndis_msg_initialize_t const msg_init = -{ - .type = RNDIS_MSG_INITIALIZE, - .length = sizeof(rndis_msg_initialize_t), - .request_id = 1, // TODO should use some magic number - .major_version = 1, - .minor_version = 0, - .max_xfer_size = 0x4000 // TODO mimic windows -}; - -static rndis_msg_query_t const msg_query_permanent_addr = -{ - .type = RNDIS_MSG_QUERY, - .length = sizeof(rndis_msg_query_t)+6, - .request_id = 1, - .oid = RNDIS_OID_802_3_PERMANENT_ADDRESS, - .buffer_length = 6, - .buffer_offset = 20, -}; - -static rndis_msg_set_t const msg_set_packet_filter = -{ - .type = RNDIS_MSG_SET, - .length = sizeof(rndis_msg_set_t)+4, - .request_id = 1, - .oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER, - .buffer_length = 4, - .buffer_offset = 20, -}; - -tusb_error_t rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - //------------- Message Initialize -------------// - memcpy(msg_payload, &msg_init, sizeof(rndis_msg_initialize_t)); - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_initialize_t), - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - // TODO currently not support multiple data packets per xfer - rndis_msg_initialize_cmplt_t * const p_init_cmpt = (rndis_msg_initialize_cmplt_t *) msg_payload; - STASK_ASSERT(p_init_cmpt->type == RNDIS_MSG_INITIALIZE_CMPLT && p_init_cmpt->status == RNDIS_STATUS_SUCCESS && - p_init_cmpt->max_packet_per_xfer == 1 && p_init_cmpt->max_xfer_size <= RNDIS_MSG_PAYLOAD_MAX); - rndish_data[dev_addr-1].max_xfer_size = p_init_cmpt->max_xfer_size; - - //------------- Message Query 802.3 Permanent Address -------------// - memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_query_t) + 6, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_query_cmplt_t * const p_query_cmpt = (rndis_msg_query_cmplt_t *) msg_payload; - STASK_ASSERT(p_query_cmpt->type == RNDIS_MSG_QUERY_CMPLT && p_query_cmpt->status == RNDIS_STATUS_SUCCESS); - memcpy(rndish_data[dev_addr-1].mac_address, msg_payload + 8 + p_query_cmpt->buffer_offset, 6); - - //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// - memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags - ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_set_t) + 4, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_set_cmplt_t * const p_set_cmpt = (rndis_msg_set_cmplt_t *) msg_payload; - STASK_ASSERT(p_set_cmpt->type == RNDIS_MSG_SET_CMPLT && p_set_cmpt->status == RNDIS_STATUS_SUCCESS); - - tusbh_cdc_rndis_mounted_cb(dev_addr); - - OSAL_SUBTASK_END -} - -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) -{ - if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) ) - { - osal_semaphore_post( rndish_data[pipe_hdl.dev_addr-1].sem_notification_hdl ); - } -} - -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - //------------- Send RNDIS Control Message -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, - mess_length, p_mess), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - //------------- waiting for Response Available notification -------------// - (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); - osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); - - //------------- Get RNDIS Message Initialize Complete -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE, 0, p_cdc->interface_number, - RNDIS_MSG_PAYLOAD_MAX, p_response), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - OSAL_SUBTASK_END -} - -//static tusb_error_t send_process_msg_initialize_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) -//{ -// tusb_error_t error; -// -// OSAL_SUBTASK_BEGIN -// -// *((rndis_msg_initialize_t*) msg_payload) = (rndis_msg_initialize_t) -// { -// .type = RNDIS_MSG_INITIALIZE, -// .length = sizeof(rndis_msg_initialize_t), -// .request_id = 1, // TODO should use some magic number -// .major_version = 1, -// .minor_version = 0, -// .max_xfer_size = 0x4000 // TODO mimic windows -// }; -// -// -// -// OSAL_SUBTASK_END -//} -#endif diff --git a/src/class/cdc/cdc_rndis_host.h b/src/class/cdc/cdc_rndis_host.h deleted file mode 100644 index bb431ec1f..000000000 --- a/src/class/cdc/cdc_rndis_host.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * 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: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup CDC_RNDIS - * \defgroup CDC_RNSID_Host Host - * @{ */ - -#ifndef _TUSB_CDC_RNDIS_HOST_H_ -#define _TUSB_CDC_RNDIS_HOST_H_ - -#include "common/tusb_common.h" -#include "host/usbh.h" -#include "cdc_rndis.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// INTERNAL RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -typedef struct { - OSAL_SEM_DEF(semaphore_notification); - osal_semaphore_handle_t sem_notification_hdl; // used to wait on notification pipe - uint32_t max_xfer_size; // got from device's msg initialize complete - uint8_t mac_address[6]; -}rndish_data_t; - -void rndish_init(void); -bool rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); -void rndish_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_CDC_RNDIS_HOST_H_ */ - -/** @} */ diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h index 8abf74f11..9bd56cef4 100644 --- a/src/class/cdc/serial/ftdi_sio.h +++ b/src/class/cdc/serial/ftdi_sio.h @@ -215,17 +215,4 @@ typedef struct ftdi_private { #define FTDI_NOT_POSSIBLE -1 #define FTDI_REQUESTED -2 -// division and round function overtaken from math.h -#define DIV_ROUND_CLOSEST(x, divisor)( \ -{ \ - typeof(x) __x = x; \ - typeof(divisor) __d = divisor; \ - (((typeof(x))-1) > 0 || \ - ((typeof(divisor))-1) > 0 || \ - (((__x) > 0) == ((__d) > 0))) ? \ - (((__x) + ((__d) / 2)) / (__d)) : \ - (((__x) - ((__d) / 2)) / (__d)); \ -} \ -) - #endif //TUSB_FTDI_SIO_H |
