diff --git a/cores/arduino/USBSerial.cpp b/cores/arduino/USBSerial.cpp index 92ba1b60da..256b5a1df8 100644 --- a/cores/arduino/USBSerial.cpp +++ b/cores/arduino/USBSerial.cpp @@ -66,7 +66,7 @@ size_t USBSerial::write(uint8_t ch) size_t USBSerial::write(const uint8_t *buffer, size_t size) { size_t rest = size; - while (rest > 0) { + while (rest > 0 && CDC_connected()) { // Determine buffer size available for write auto portion = (size_t)CDC_TransmitQueue_WriteSize(&TransmitQueue); // Truncate it to content size (if rest is greater) @@ -85,7 +85,7 @@ size_t USBSerial::write(const uint8_t *buffer, size_t size) CDC_continue_transmit(); } } - return size; + return size - rest; } int USBSerial::available(void) diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index f55b74aea2..3e57ed27e5 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -32,6 +32,15 @@ #define CDC_MAX_PACKET_SIZE USB_MAX_EP0_SIZE #endif +/* + * The value USB_CDC_TRANSMIT_TIMEOUT is defined in terms of HAL_GetTick() units. + * Typically it is 1ms value. The timeout determines when we would consider the + * host "too slow" and threat the USB CDC port as disconnected. + */ +#ifndef USB_CDC_TRANSMIT_TIMEOUT +#define USB_CDC_TRANSMIT_TIMEOUT 3 +#endif + /* USBD_CDC Private Variables */ /* USB Device Core CDC handle declaration */ USBD_HandleTypeDef hUSBD_Device_CDC; @@ -43,6 +52,7 @@ CDC_TransmitQueue_TypeDef TransmitQueue; CDC_ReceiveQueue_TypeDef ReceiveQueue; __IO uint32_t lineState = 0; __IO bool receivePended = true; +static uint32_t transmitStart = 0; /** USBD_CDC Private Function Prototypes */ @@ -169,6 +179,9 @@ static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) case CDC_SET_CONTROL_LINE_STATE: lineState = (((USBD_SetupReqTypedef *)pbuf)->wValue & 0x01) != 0; // Check DTR state + if (lineState) { // Reset the transmit timeout when the port is connected + transmitStart = 0; + } break; case CDC_SEND_BREAK: @@ -212,6 +225,7 @@ static int8_t USBD_CDC_Receive(uint8_t *Buf, uint32_t *Len) static int8_t USBD_CDC_Transferred(void) { + transmitStart = 0; CDC_TransmitQueue_CommitRead(&TransmitQueue); CDC_continue_transmit(); return (USBD_OK); @@ -245,6 +259,17 @@ void CDC_deInit(void) } } +bool CDC_connected() +{ + uint32_t transmitTime = 0; + if (transmitStart) { + transmitTime = HAL_GetTick() - transmitStart; + } + return hUSBD_Device_CDC.dev_state == USBD_STATE_CONFIGURED + && transmitTime < USB_CDC_TRANSMIT_TIMEOUT + && lineState; +} + void CDC_continue_transmit(void) { uint16_t size; @@ -261,6 +286,7 @@ void CDC_continue_transmit(void) if (hcdc->TxState == 0U) { buffer = CDC_TransmitQueue_ReadBlock(&TransmitQueue, &size); if (size > 0) { + transmitStart = HAL_GetTick(); USBD_CDC_SetTxBuffer(&hUSBD_Device_CDC, buffer, size); /* * size never exceed PMA buffer and USBD_CDC_TransmitPacket make full diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h index 155b61b973..32f47e6beb 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.h @@ -50,6 +50,7 @@ void CDC_continue_transmit(void); void CDC_resume_receive(void); void CDC_init(void); void CDC_deInit(void); +bool CDC_connected(); #ifdef __cplusplus }