mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 20:24:32 +02:00
feat(usb_serial_jtag): Update vfs read to be POSIX compliant
The function now returns with available data in blocking mode instead of waiting for the requested size to be available before returning.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -27,6 +27,13 @@ typedef void (*usj_select_notif_callback_t)(usj_select_notif_t usb_serial_jtag_s
|
||||
*/
|
||||
void usb_serial_jtag_set_select_notif_callback(usj_select_notif_callback_t usb_serial_jtag_select_notif_callback);
|
||||
|
||||
/**
|
||||
* @brief Return the number of bytes available for reading
|
||||
*
|
||||
* @return the number of bytes available for reading in the buffer
|
||||
*/
|
||||
size_t usb_serial_jtag_get_read_bytes_available(void);
|
||||
|
||||
/**
|
||||
* @brief Return the readiness status of the driver for read operation
|
||||
*
|
||||
|
@@ -366,12 +366,23 @@ void usb_serial_jtag_set_select_notif_callback(usj_select_notif_callback_t usj_s
|
||||
}
|
||||
}
|
||||
|
||||
bool usb_serial_jtag_read_ready(void)
|
||||
size_t usb_serial_jtag_get_read_bytes_available(void)
|
||||
{
|
||||
// sign the the driver is read ready is that data is waiting in the RX ringbuffer
|
||||
UBaseType_t items_waiting = 0;
|
||||
vRingbufferGetInfo(p_usb_serial_jtag_obj->rx_ring_buf, NULL, NULL, NULL, NULL, &items_waiting);
|
||||
return items_waiting != 0;
|
||||
UBaseType_t bytes_available = 0;
|
||||
if (usb_serial_jtag_is_driver_installed()) {
|
||||
vRingbufferGetInfo(p_usb_serial_jtag_obj->rx_ring_buf, NULL, NULL, NULL, NULL, &bytes_available);
|
||||
if (bytes_available <= 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (size_t)bytes_available;
|
||||
}
|
||||
|
||||
bool usb_serial_jtag_read_ready(void)
|
||||
{
|
||||
return usb_serial_jtag_get_read_bytes_available() != 0;
|
||||
}
|
||||
|
||||
bool usb_serial_jtag_write_ready(void)
|
||||
|
@@ -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
|
||||
*/
|
||||
@@ -229,36 +229,66 @@ static ssize_t usb_serial_jtag_read(int fd, void* data, size_t size)
|
||||
assert(fd == USJ_LOCAL_FD);
|
||||
char *data_c = (char *) data;
|
||||
size_t received = 0;
|
||||
size_t available_size = 0;
|
||||
int c = NONE; // store the read char
|
||||
_lock_acquire_recursive(&s_ctx.read_lock);
|
||||
|
||||
while (received < size) {
|
||||
int c = usb_serial_jtag_read_char(fd);
|
||||
if (c == '\r') {
|
||||
if (s_ctx.rx_mode == ESP_LINE_ENDINGS_CR) {
|
||||
c = '\n';
|
||||
} else if (s_ctx.rx_mode == ESP_LINE_ENDINGS_CRLF) {
|
||||
/* look ahead */
|
||||
int c2 = usb_serial_jtag_read_char(fd);
|
||||
if (c2 == NONE) {
|
||||
/* could not look ahead, put the current character back */
|
||||
usb_serial_jtag_return_char(fd, c);
|
||||
break;
|
||||
}
|
||||
if (c2 == '\n') {
|
||||
/* this was \r\n sequence. discard \r, return \n */
|
||||
// if blocking read, wait for data to be available
|
||||
if (!s_ctx.non_blocking) {
|
||||
c = usb_serial_jtag_read_char(fd);
|
||||
}
|
||||
|
||||
// find the actual fetch size
|
||||
available_size += usb_serial_jtag_get_read_bytes_available();
|
||||
if (c != NONE) {
|
||||
available_size++;
|
||||
}
|
||||
if (s_ctx.peek_char != NONE) {
|
||||
available_size++;
|
||||
}
|
||||
size_t fetch_size = MIN(available_size, size);
|
||||
|
||||
if (fetch_size > 0) {
|
||||
do {
|
||||
if (c == NONE) { // for non-O_NONBLOCK mode, there is already a pre-fetched char
|
||||
c = usb_serial_jtag_read_char(fd);
|
||||
}
|
||||
assert(c != NONE);
|
||||
|
||||
if (c == '\r') {
|
||||
if (s_ctx.rx_mode == ESP_LINE_ENDINGS_CR) {
|
||||
c = '\n';
|
||||
} else {
|
||||
/* \r followed by something else. put the second char back,
|
||||
* it will be processed on next iteration. return \r now.
|
||||
*/
|
||||
usb_serial_jtag_return_char(fd, c2);
|
||||
} else if (s_ctx.rx_mode == ESP_LINE_ENDINGS_CRLF) {
|
||||
/* look ahead */
|
||||
int c2 = usb_serial_jtag_read_char(fd);
|
||||
fetch_size--;
|
||||
if (c2 == NONE) {
|
||||
/* could not look ahead, put the current character back */
|
||||
usb_serial_jtag_return_char(fd, c);
|
||||
c = NONE;
|
||||
break;
|
||||
}
|
||||
if (c2 == '\n') {
|
||||
/* this was \r\n sequence. discard \r, return \n */
|
||||
c = '\n';
|
||||
} else {
|
||||
/* \r followed by something else. put the second char back,
|
||||
* it will be processed on next iteration. return \r now.
|
||||
*/
|
||||
usb_serial_jtag_return_char(fd, c2);
|
||||
fetch_size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (c == NONE) {
|
||||
break;
|
||||
}
|
||||
data_c[received] = (char) c;
|
||||
++received;
|
||||
|
||||
data_c[received] = (char) c;
|
||||
++received;
|
||||
c = NONE;
|
||||
} while (received < fetch_size);
|
||||
}
|
||||
|
||||
if (c != NONE) { // fetched, but not used
|
||||
usb_serial_jtag_return_char(fd, c);
|
||||
}
|
||||
_lock_release_recursive(&s_ctx.read_lock);
|
||||
if (received > 0) {
|
||||
@@ -454,7 +484,7 @@ static esp_err_t usb_serial_jtag_start_select(int nfds, fd_set *readfds, fd_set
|
||||
bool trigger_select = false;
|
||||
|
||||
// check if the select should return instantly if the bus is read ready
|
||||
if (FD_ISSET(USJ_LOCAL_FD, &args->readfds_orig) && usb_serial_jtag_read_ready()) {
|
||||
if (FD_ISSET(USJ_LOCAL_FD, &args->readfds_orig) && (usb_serial_jtag_get_read_bytes_available() > 0)) {
|
||||
// signal immediately when data is buffered
|
||||
FD_SET(USJ_LOCAL_FD, readfds);
|
||||
trigger_select = true;
|
||||
|
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- | --------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@@ -2,6 +2,7 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.esp32s3
|
||||
@@ -36,7 +37,7 @@ def test_usj_vfs_select(dut: Dut, test_message: list) -> None:
|
||||
)
|
||||
@pytest.mark.parametrize('test_message', ['!(@*#&(!*@&#((SDasdkjhad\nce'])
|
||||
@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target'])
|
||||
def test_usj_vfs_read(dut: Dut, test_message: list) -> None:
|
||||
def test_usj_vfs_read_return(dut: Dut, test_message: list) -> None:
|
||||
dut.expect_exact('Press ENTER to see the list of tests')
|
||||
dut.write('"read does not return on new line character"')
|
||||
dut.expect_exact('ready to receive', timeout=2)
|
||||
@@ -54,7 +55,7 @@ def test_usj_vfs_read(dut: Dut, test_message: list) -> None:
|
||||
)
|
||||
@pytest.mark.parametrize('test_message', ['testdata'])
|
||||
@idf_parametrize('target', ['esp32s3', 'esp32c3', 'esp32c6', 'esp32h2'], indirect=['target'])
|
||||
def test_usj_vfs_read(dut: Dut, test_message: list) -> None:
|
||||
def test_usj_vfs_read_blocking(dut: Dut, test_message: list) -> None:
|
||||
dut.expect_exact('Press ENTER to see the list of tests')
|
||||
dut.write('"blocking read returns with available data"')
|
||||
dut.expect_exact('ready to receive', timeout=2)
|
||||
|
Reference in New Issue
Block a user