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:
parent
c702ca0f1b
commit
e16be98224
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user