usb: device: cdc_acm: suspend transfers when RX path runs out of buffer

Suspend CDC ACM class OUT transfers when RX path runs out
of ring buffer.

Signed-off-by: Pawel Osypiuk <pawelosyp@gmail.com>
This commit is contained in:
Pawel Osypiuk 2022-05-20 14:25:29 +02:00 committed by Carles Cufí
parent 47ea15edcd
commit 7fcfd54423

View file

@ -119,6 +119,8 @@ struct cdc_acm_dev_data_t {
bool configured;
/* CDC ACM suspended flag */
bool suspended;
/* CDC ACM paused flag */
bool rx_paused;
struct usb_dev_data common;
};
@ -287,10 +289,14 @@ static void cdc_acm_read_cb(uint8_t ep, int size, void *priv)
k_work_submit_to_queue(&USB_WORK_Q, &dev_data->cb_work);
}
if (ring_buf_space_get(dev_data->rx_ringbuf) < sizeof(dev_data->rx_buf)) {
dev_data->rx_paused = true;
return;
}
done:
usb_transfer(ep, dev_data->rx_buf, sizeof(dev_data->rx_buf),
USB_TRANS_READ, cdc_acm_read_cb, dev_data);
}
/**
@ -328,6 +334,7 @@ static void cdc_acm_reset_port(struct cdc_acm_dev_data_t *dev_data)
CDC_ACM_DEFAULT_BAUDRATE;
dev_data->serial_state = 0;
dev_data->line_state = 0;
dev_data->rx_paused = false;
memset(&dev_data->rx_buf, 0, CDC_ACM_BUFFER_SIZE);
}
@ -537,6 +544,17 @@ static int cdc_acm_fifo_read(const struct device *dev, uint8_t *rx_data,
dev_data->rx_ready = false;
}
if (dev_data->rx_paused == true) {
if (ring_buf_space_get(dev_data->rx_ringbuf) >= CDC_ACM_BUFFER_SIZE) {
struct usb_cfg_data *cfg = (void *)dev->config;
if (dev_data->configured && !dev_data->suspended) {
cdc_acm_read_cb(cfg->endpoint[ACM_OUT_EP_IDX].ep_addr, 0, dev_data);
}
dev_data->rx_paused = false;
}
}
return len;
}