fix(esp_vfs_console): USB CDC read when non blocking

In non blocking mode, the read function is expected
to return weather data is available for reading or not.

In case data are available but the size does not match
the expected size, the function read should return whatever
data is available.

Previously, the function was returning -1 with errno set
to EWOULDBLOCK even if the size of data in the buffer was
less than the requested size. It would only return the
available data if the size in the buffer was greater or equal
to the requested size.

The implementation of cdcacm_read is modified to return the avilable
data from the buffer even is the size is lesser than the requested
size.
This commit is contained in:
Guillaume Souchere
2025-01-17 07:45:12 +01:00
parent 6ac45b2559
commit ae7c8691d9
4 changed files with 122 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -181,15 +181,15 @@ static ssize_t cdcacm_read(int fd, void *data, size_t size)
ssize_t received = 0;
_lock_acquire_recursive(&s_read_lock);
while (cdcacm_data_length_in_buffer() < size) {
if (!s_blocking) {
errno = EWOULDBLOCK;
_lock_release_recursive(&s_read_lock);
return -1;
if (s_blocking) {
while (cdcacm_data_length_in_buffer() < size) {
xSemaphoreTake(s_rx_semaphore, portMAX_DELAY);
}
xSemaphoreTake(s_rx_semaphore, portMAX_DELAY);
} else {
/* process pending interrupts before requesting available data */
esp_usb_console_poll_interrupts();
size = MIN(size, cdcacm_data_length_in_buffer());
}
if (s_rx_mode == ESP_LINE_ENDINGS_CR || s_rx_mode == ESP_LINE_ENDINGS_LF) {
/* This is easy. Just receive, and if needed replace \r by \n. */
received = esp_usb_console_read_buf(data_c, size);
@@ -443,6 +443,9 @@ static esp_err_t cdcacm_start_select(int nfds, fd_set *readfds, fd_set *writefds
return ret;
}
/* make sure the driver processes any pending interrupts before checking read or write
* readiness */
esp_usb_console_poll_interrupts();
bool trigger_select = false;
if (FD_ISSET(USB_CDC_LOCAL_FD, &args->readfds_orig) &&
esp_usb_console_available_for_read() > 0) {