1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-17 02:52:12 +01:00

usb cdc: ensure com buffer is drained when no DTE is attached

The CDC layer on F1, F3 and F4 now always acts like an
infinte data sink whenever *either* there is no DTE present
(ie. no terminal program listening) *or* the USB cable is
disconnected.

F1 and F4 were previously checking the cable but not the DTE.
F3 didn't check anything.  The COM layer didn't even ask the
lower layers.

All of this used to mean that any time a caller did a blocking
send to a CDC device without a DTE, it would eventually block
for up to a 5s timeout waiting for space in the Tx buffer.

Conflicts:
	flight/PiOS/STM32F30x/pios_usb_cdc.c
This commit is contained in:
Stacey Sheldon 2013-03-12 22:53:43 -04:00 committed by Alessio Morale
parent c702ca0f1b
commit e16be98224
4 changed files with 41 additions and 2 deletions

View File

@ -279,6 +279,18 @@ int32_t PIOS_COM_SendBufferNonBlocking(uint32_t com_id, const uint8_t *buffer, u
PIOS_Assert(com_dev->has_tx);
if (com_dev->driver->available && !com_dev->driver->available(com_dev->lower_id)) {
/*
* Underlying device is down/unconnected.
* Dump our fifo contents and act like an infinite data sink.
* Failure to do this results in stale data in the fifo as well as
* possibly having the caller block trying to send to a device that's
* no longer accepting data.
*/
fifoBuf_clearData(&com_dev->tx);
return len;
}
if (len > fifoBuf_getFree(&com_dev->tx)) {
/* Buffer cannot accept all requested bytes (retry) */
return -2;

View File

@ -44,6 +44,9 @@ extern const struct pios_com_driver pios_usb_cdc_com_driver;
extern int32_t PIOS_USB_CDC_Init(uint32_t * usbcdc_id, const struct pios_usb_cdc_cfg * cfg, uint32_t lower_id);
/* From USB CDC Spec Section 6.2.14 SetControlLineState */
#define USB_CDC_CONTROL_LINE_STATE_DTE_PRESENT 0x01
#endif /* PIOS_USB_CDC_PRIV_H */
/**

View File

@ -43,13 +43,14 @@ static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id, pios_com_callbac
static void PIOS_USB_CDC_RegisterRxCallback(uint32_t usbcdc_id, pios_com_callback rx_in_cb, uint32_t context);
static void PIOS_USB_CDC_TxStart(uint32_t usbcdc_id, uint16_t tx_bytes_avail);
static void PIOS_USB_CDC_RxStart(uint32_t usbcdc_id, uint16_t rx_bytes_avail);
static bool PIOS_USB_CDC_Available (uint32_t usbcdc_id);
const struct pios_com_driver pios_usb_cdc_com_driver = {
.tx_start = PIOS_USB_CDC_TxStart,
.rx_start = PIOS_USB_CDC_RxStart,
.bind_tx_cb = PIOS_USB_CDC_RegisterTxCallback,
.bind_rx_cb = PIOS_USB_CDC_RegisterRxCallback,
.available = PIOS_USB_CheckAvailable,
.available = PIOS_USB_CDC_Available,
};
enum pios_usb_cdc_dev_magic {
@ -333,6 +334,17 @@ RESULT PIOS_USB_CDC_SetControlLineState(void)
return USB_SUCCESS;
}
static bool PIOS_USB_CDC_Available (uint32_t usbcdc_id)
{
struct pios_usb_cdc_dev * usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id;
bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
PIOS_Assert(valid);
return (PIOS_USB_CheckAvailable(usb_cdc_dev->lower_id) &&
(control_line_state & USB_CDC_CONTROL_LINE_STATE_DTE_PRESENT));
}
static struct usb_cdc_line_coding line_coding = {
.dwDTERate = htousbl(57600),
.bCharFormat = USB_CDC_LINE_CODING_STOP_1,

View File

@ -42,13 +42,14 @@ static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id, pios_com_callbac
static void PIOS_USB_CDC_RegisterRxCallback(uint32_t usbcdc_id, pios_com_callback rx_in_cb, uint32_t context);
static void PIOS_USB_CDC_TxStart(uint32_t usbcdc_id, uint16_t tx_bytes_avail);
static void PIOS_USB_CDC_RxStart(uint32_t usbcdc_id, uint16_t rx_bytes_avail);
static bool PIOS_USB_CDC_Available (uint32_t usbcdc_id);
const struct pios_com_driver pios_usb_cdc_com_driver = {
.tx_start = PIOS_USB_CDC_TxStart,
.rx_start = PIOS_USB_CDC_RxStart,
.bind_tx_cb = PIOS_USB_CDC_RegisterTxCallback,
.bind_rx_cb = PIOS_USB_CDC_RegisterRxCallback,
.available = PIOS_USB_CheckAvailable,
.available = PIOS_USB_CDC_Available,
};
enum pios_usb_cdc_dev_magic {
@ -399,6 +400,17 @@ static bool PIOS_USB_CDC_CTRL_IF_Setup(uint32_t usb_cdc_id, struct usb_setup_req
return true;
}
static bool PIOS_USB_CDC_Available (uint32_t usbcdc_id)
{
struct pios_usb_cdc_dev * usb_cdc_dev = (struct pios_usb_cdc_dev *)usbcdc_id;
bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
PIOS_Assert(valid);
return (PIOS_USB_CheckAvailable(usb_cdc_dev->lower_id) &&
(control_line_state & USB_CDC_CONTROL_LINE_STATE_DTE_PRESENT));
}
/**
* Called *after* the data has been written to the buffer provided in the setup stage. The
* setup request is passed in here again so we know *which* EP0 data out has just completed.