2222 */
2323
2424#include <unistd.h>
25+ #include <stdlib.h>
26+ #include <fcntl.h>
27+ #include <time.h>
28+ #include <sys/ioctl.h>
29+
30+ int tcdrain (int fd );
31+
2532#include "bs_types.h"
2633#include "bs_tracing.h"
2734#include "bs_oswrap.h"
@@ -47,6 +54,7 @@ struct upty_st_t {
4754 bool auto_attach ;
4855 char * attach_cmd ;
4956 bool respect_RTS ;
57+ bool wait_for_readers ;
5058
5159 int out_fd ; /* File descriptor used for output */
5260 int in_fd ; /* File descriptor used for input */
@@ -206,18 +214,51 @@ static void nhw_upty_timer_triggered(void) {
206214
207215NSI_HW_EVENT (Timer_UPTY , nhw_upty_timer_triggered , 900 ); /* Let's let as many timers as possible evaluate before this one */
208216
217+ static void nhw_upty_wait_for_fionread_empty (int fd ) {
218+ int bytes_left = 0 ;
219+ const struct timespec sleep_time = { .tv_sec = 0 , .tv_nsec = 1000000 }; // 1ms
220+
221+ while (1 ) {
222+ if (ioctl (fd , FIONREAD , & bytes_left ) != 0 ) {
223+ return ;
224+ }
225+
226+ if (bytes_left == 0 ) {
227+ return ;
228+ }
229+
230+ (void )nanosleep (& sleep_time , NULL );
231+ }
232+ }
233+
209234static void nhw_upty_cleanup (void ) {
210235 for (int i = 0 ; i < NHW_UARTE_TOTAL_INST ; i ++ ) {
211236 struct upty_st_t * u_el = & upty_st [i ];
212237
213- if (u_el -> in_fd != -1 ) {
214- close (u_el -> in_fd );
215- u_el -> in_fd = -1 ;
216- }
217238 if (u_el -> out_fd != -1 ) {
239+ if (u_el -> wait_for_readers ) {
240+ (void )tcdrain (u_el -> out_fd );
241+
242+ char * slave_name = ptsname (u_el -> out_fd );
243+ if (slave_name != NULL ) {
244+ int slave_fd = open (slave_name , O_RDWR | O_NOCTTY );
245+ if (slave_fd != -1 ) {
246+ nhw_upty_wait_for_fionread_empty (slave_fd );
247+ close (slave_fd );
248+ }
249+ }
250+ }
251+
218252 close (u_el -> out_fd );
253+ if (u_el -> in_fd == u_el -> out_fd ) {
254+ u_el -> in_fd = -1 ;
255+ }
219256 u_el -> out_fd = -1 ;
220257 }
258+ if (u_el -> in_fd != -1 ) {
259+ close (u_el -> in_fd );
260+ u_el -> in_fd = -1 ;
261+ }
221262 }
222263}
223264
@@ -234,15 +275,17 @@ static void parse_poll_period(char *argv, int offset) {
234275}
235276
236277static void nhw_upty_backend_register_cmdline (void ) {
237- #define OPT_PER_UART 4
278+ #define OPT_PER_UART 5
238279 static bs_args_struct_t args [OPT_PER_UART * NHW_UARTE_TOTAL_INST + 1 /* End marker */ ];
239280 static char descr_connect [] = "Connect this UART to a pseudoterminal" ;
240281 static char descr_auto [] = "Automatically attach to the UART terminal (implies uartx_pty)" ;
241282 static char descr_cmd [] = "Command used to automatically attach to the terminal (implies "
242283 "uartx_pty_attach), by default: '" DEFAULT_CMD "'" ;
243284 static char descr_ignoreRTS [] = "Hold feeding data from the PTY if RTS is high (note: "
244285 "If HW flow control is disabled the UART never lowers RTS)" ;
245- #define OPTION_LEN (4 + 2 + 15 + 1)
286+ static char descr_wait_readers [] = "At exit, wait for this UART's PTY slave FIONREAD counter "
287+ "to reach 0 before closing" ;
288+ #define OPTION_LEN (4 + 2 + 21 + 1)
246289 static char options [NHW_UARTE_TOTAL_INST ][OPT_PER_UART ][OPTION_LEN ];
247290 static char opt_cmd []= "cmd" ;
248291
@@ -251,6 +294,7 @@ static void nhw_upty_backend_register_cmdline(void) {
251294 snprintf (options [i ][1 ], OPTION_LEN , "uart%i_pty_attach" , i );
252295 snprintf (options [i ][2 ], OPTION_LEN , "uart%i_pty_attach_cmd" , i );
253296 snprintf (options [i ][3 ], OPTION_LEN , "uart%i_pty_respect_RTS" , i );
297+ snprintf (options [i ][4 ], OPTION_LEN , "uart%i_pty_wait_for_readers" , i );
254298
255299 args [OPT_PER_UART * i ].option = options [i ][0 ];
256300 args [OPT_PER_UART * i ].is_switch = true;
@@ -275,6 +319,12 @@ static void nhw_upty_backend_register_cmdline(void) {
275319 args [OPT_PER_UART * i + 3 ].type = 'b' ;
276320 args [OPT_PER_UART * i + 3 ].dest = & upty_st [i ].respect_RTS ;
277321 args [OPT_PER_UART * i + 3 ].descript = descr_ignoreRTS ;
322+
323+ args [OPT_PER_UART * i + 4 ].option = options [i ][4 ];
324+ args [OPT_PER_UART * i + 4 ].is_switch = true;
325+ args [OPT_PER_UART * i + 4 ].type = 'b' ;
326+ args [OPT_PER_UART * i + 4 ].dest = & upty_st [i ].wait_for_readers ;
327+ args [OPT_PER_UART * i + 4 ].descript = descr_wait_readers ;
278328 }
279329
280330 bs_add_extra_dynargs (args );
0 commit comments