diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 6f71cb781..56cc94abc 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -353,6 +353,16 @@ bool cdcd_control_request(uint8_t rhport, tusb_control_request_t const * request bool const dtr = tu_bit_test(request->wValue, 0); bool const rts = tu_bit_test(request->wValue, 1); +#if CFG_TUD_CDC_CLEAR_AT_CONNECTION + // DTE connected event (if DTE supports DTR bit) + if ( dtr && !tu_bit_test(p_cdc->line_state, 0) ) + { + // Clear not transmitted data + usbd_edpt_xfer_abort(rhport, p_cdc->ep_in); + tu_fifo_clear(&p_cdc->tx_ff); + } +#endif + p_cdc->line_state = (uint8_t) request->wValue; // Disable fifo overwriting if DTR bit is set diff --git a/src/device/dcd.h b/src/device/dcd.h index a4635346b..ee41fefd0 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -133,6 +133,9 @@ void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK; // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Abort a ongoing transfer +TU_ATTR_WEAK bool dcd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); + // Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 6b91048b6..04ae31ce7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1100,6 +1100,33 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t } } +bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_LOG2(" Abort XFER EP %02X ... ", ep_addr); + + // Abort API is optional for DCD + if ( dcd_edpt_xfer_abort ) + { + if ( dcd_edpt_xfer_abort(rhport, ep_addr) ) + { + _usbd_dev.ep_status[epnum][dir].busy = false; + TU_LOG2("OK\r\n"); + return true; + }else + { + TU_LOG2("failed\r\n"); + return false; + } + }else + { + TU_LOG2("no DCD support\r\n"); + return false; + } +} + bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { (void) rhport; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index a5d223329..d87c07c01 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -70,6 +70,9 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr); // Submit a usb transfer bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); +// Abort a scheduled transfer +bool usbd_edpt_xfer_abort(uint8_t rhport, uint8_t ep_addr); + // Check if endpoint transferring is complete bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr);