11/*
2- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33 *
44 * SPDX-License-Identifier: Unlicense OR CC0-1.0
55 */
1111#include "esp_private/usb_console.h"
1212#include "esp_vfs_cdcacm.h"
1313
14- static int read_bytes_with_select (FILE * stream , void * buf , size_t buf_len , struct timeval tv )
14+ static void flush_write (void )
15+ {
16+ fflush (stdout );
17+ fsync (fileno (stdout ));
18+ }
19+
20+ static void test_setup (const char * func_name , const size_t func_name_size )
21+ {
22+ /* write the name of the test back to the pytest environment to start the test */
23+ write (fileno (stdout ), func_name , func_name_size );
24+ write (fileno (stdout ), "\n" , 1 );
25+ flush_write ();
26+ }
27+
28+ static int read_bytes_with_select (FILE * stream , void * buf , size_t buf_len , struct timeval * tv )
1529{
1630 int fd = fileno (stream );
1731 fd_set read_fds ;
1832 FD_ZERO (& read_fds );
1933 FD_SET (fd , & read_fds );
20-
21- /* call select with to wait for either a read ready or timeout to happen */
22- int nread = select (fd + 1 , & read_fds , NULL , NULL , & tv );
34+ /* call select to wait for either a read ready or an except to happen */
35+ int nread = select (fd + 1 , & read_fds , NULL , NULL , tv );
2336 if (nread < 0 ) {
2437 return -1 ;
2538 } else if (FD_ISSET (fd , & read_fds )) {
2639 int read_count = 0 ;
2740 int total_read = 0 ;
2841
2942 do {
30- read_count = read (fileno ( stream ) , buf + total_read , 1 );
43+ read_count = read (fd , buf + total_read , buf_len - total_read );
3144 if (read_count < 0 && errno != EWOULDBLOCK ) {
3245 return -1 ;
3346 } else if (read_count > 0 ) {
@@ -41,12 +54,31 @@ static int read_bytes_with_select(FILE *stream, void *buf, size_t buf_len, struc
4154
4255 return total_read ;
4356 } else {
57+ /* select timed out */
4458 return -2 ;
4559 }
60+ return nread ;
4661}
4762
48- void app_main (void )
63+ static bool wait_for_read_ready (FILE * stream )
64+ {
65+ int fd = fileno (stream );
66+ fd_set read_fds ;
67+ FD_ZERO (& read_fds );
68+ FD_SET (fd , & read_fds );
69+ /* call select to wait for either a read ready or an except to happen */
70+ int nread = select (fd + 1 , & read_fds , NULL , NULL , NULL );
71+ if ((nread >= 0 ) && (FD_ISSET (fd , & read_fds ))) {
72+ return true;
73+ } else {
74+ return false;
75+ }
76+ }
77+
78+ static void test_usb_cdc_select (void )
4979{
80+ test_setup (__func__ , sizeof (__func__ ));
81+
5082 struct timeval tv ;
5183 tv .tv_sec = 1 ;
5284 tv .tv_usec = 0 ;
@@ -70,7 +102,7 @@ void app_main(void)
70102 bool message_received = false;
71103 size_t char_read = 0 ;
72104 while (!message_received && out_buffer_len > char_read ) {
73- int nread = read_bytes_with_select (stdin , out_buffer + char_read , out_buffer_len - char_read , tv );
105+ int nread = read_bytes_with_select (stdin , out_buffer + char_read , out_buffer_len - char_read , & tv );
74106 if (nread > 0 ) {
75107 char_read += nread ;
76108 if (out_buffer [char_read - 1 ] == '\n' ) {
@@ -83,6 +115,7 @@ void app_main(void)
83115 // function since the string is expected as is by the test environment
84116 char timeout_msg [] = "select timed out\n" ;
85117 write (fileno (stdout ), timeout_msg , sizeof (timeout_msg ));
118+ flush_write ();
86119 } else {
87120 break ;
88121 }
@@ -91,6 +124,59 @@ void app_main(void)
91124 // write the received message back to the test environment. The test
92125 // environment will check that the message received matches the one sent
93126 write (fileno (stdout ), out_buffer , char_read );
127+ flush_write ();
94128
95129 vTaskDelay (10 ); // wait for the string to send
96130}
131+
132+ static void test_usb_cdc_read_non_blocking (void )
133+ {
134+ test_setup (__func__ , sizeof (__func__ ));
135+
136+ const size_t max_read_bytes = 16 ;
137+ char read_data_buffer [max_read_bytes ];
138+
139+ memset (read_data_buffer , 0x00 , max_read_bytes );
140+
141+ /* reset errno to 0 for the purpose of the test to make sure it is no
142+ * longer set to EWOULDBLOCK later in the test. */
143+ errno = 0 ;
144+
145+ /* make sure to read in non blocking mode */
146+ int stdin_fd = fileno (stdin );
147+ int flags = fcntl (stdin_fd , F_GETFL );
148+ flags |= O_NONBLOCK ;
149+ int res = fcntl (stdin_fd , F_SETFL , flags );
150+ TEST_ASSERT (res == 0 );
151+
152+ /* call read when no data is available for reading.
153+ * expected result:
154+ * - read returns -1 and errno has been set to EWOULDBLOCK */
155+ int nread = read (stdin_fd , read_data_buffer , max_read_bytes );
156+ TEST_ASSERT (nread == -1 );
157+ TEST_ASSERT (errno == EWOULDBLOCK );
158+
159+ /* reset errno to 0 for the purpose of the test to make sure it is no
160+ * longer set to EWOULDBLOCK later in the test. */
161+ errno = 0 ;
162+
163+ /* call read X number of bytes when less than X number of
164+ * bytes are available for reading (Y bytes).
165+ * expected result:
166+ * - read returns at least 1 bytes errno is not set to EWOULDBLOCK */
167+ char message_8 [] = "send_bytes\n" ;
168+ write (fileno (stdout ), message_8 , sizeof (message_8 ));
169+ flush_write ();
170+
171+ const bool is_ready = wait_for_read_ready (stdin );
172+ TEST_ASSERT (is_ready );
173+ nread = read (stdin_fd , read_data_buffer , max_read_bytes );
174+ TEST_ASSERT (nread >= 1 );
175+ TEST_ASSERT (errno != EWOULDBLOCK );
176+ }
177+
178+ void app_main (void )
179+ {
180+ test_usb_cdc_select ();
181+ test_usb_cdc_read_non_blocking ();
182+ }
0 commit comments