Anastasia Klimchuk has submitted this change. ( https://review.coreboot.org/c/flashrom/+/79112?usp=email )
Change subject: serial: Fix sp_flush_incoming for serprog TCP connections ......................................................................
serial: Fix sp_flush_incoming for serprog TCP connections
During the development of an esp32 serprog-compatible SPI programmer, and implementation of the TCP over Wi-Fi for serprog, I discovered that sp_flush_incoming() silently fails if the underlying sp_fd descriptor is a TCP socket.
This patch adds a check for this case - tcflush returns ENOTTY, meaning tcflush is not supported for not terminal objects, in this case a fallback serialport_read_nonblock loop is used.
TESTED=esp32-serprog, TCP-over-WiFi mode, ~90% connection attempts fail to synchronize without patch; no synchronization issues with patch applied.
Signed-off-by: Stanislav Ponomarev me@stasponomarev.com
Change-Id: I9724a2fcd4a41dede2c15f83877efa6c3b0b7fae Reviewed-on: https://review.coreboot.org/c/flashrom/+/79112 Reviewed-by: Anastasia Klimchuk aklm@chromium.org Tested-by: build bot (Jenkins) no-reply@coreboot.org --- M serial.c 1 file changed, 19 insertions(+), 3 deletions(-)
Approvals: Anastasia Klimchuk: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/serial.c b/serial.c index 10d739a..577ccf4 100644 --- a/serial.c +++ b/serial.c @@ -377,10 +377,26 @@ #if IS_WINDOWS PurgeComm(sp_fd, PURGE_RXCLEAR); #else - /* FIXME: error handling */ - tcflush(sp_fd, TCIFLUSH); + if (!tcflush(sp_fd, TCIFLUSH)) + return; + + if (errno == ENOTTY) { // TCP socket case: sp_fd is not a terminal descriptor - tcflush is not supported + unsigned char c; + int ret; + + do { + ret = serialport_read_nonblock(&c, 1, 1, NULL); + } while (ret == 0); + + // positive error code indicates no data available immediately - similar to EAGAIN/EWOULDBLOCK + // i.e. all buffered data was read + // negative error code indicates a permanent error + if (ret < 0) + msg_perr("Could not flush serial port incoming buffer: read has failed"); + } else { // any other errno indicates an unrecoverable sp_fd state + msg_perr_strerror("Could not flush serial port incoming buffer: "); + } #endif - return; }
int serialport_shutdown(void *data)