From 8943049cd411e194c77ca4ffed434a43af525f03 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 22 Jan 2014 07:41:34 +0000 Subject: [PATCH] scpi_serial: Reimplement to allow scpi_read_complete() to work correctly. --- hardware/common/scpi_serial.c | 63 ++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/hardware/common/scpi_serial.c b/hardware/common/scpi_serial.c index 9711c010..cf962af7 100644 --- a/hardware/common/scpi_serial.c +++ b/hardware/common/scpi_serial.c @@ -26,12 +26,13 @@ #define LOG_PREFIX "scpi_serial" -#define SCPI_READ_RETRIES 100 -#define SCPI_READ_RETRY_TIMEOUT 10000 +#define BUFFER_SIZE 1024 struct scpi_serial { struct sr_serial_dev_inst *serial; - char last_character; + char buffer[BUFFER_SIZE]; + size_t count; + size_t read; }; static int scpi_serial_dev_inst_new(void *priv, const char *resource, @@ -58,6 +59,9 @@ static int scpi_serial_open(void *priv) if (serial_flush(serial) != SR_OK) return SR_ERR; + sscpi->count = 0; + sscpi->read = 0; + return SR_OK; } @@ -107,9 +111,7 @@ static int scpi_serial_send(void *priv, const char *command) static int scpi_serial_read_begin(void *priv) { - struct scpi_serial *sscpi = priv; - - sscpi->last_character = '\0'; + (void) priv; return SR_OK; } @@ -117,27 +119,56 @@ static int scpi_serial_read_begin(void *priv) static int scpi_serial_read_data(void *priv, char *buf, int maxlen) { struct scpi_serial *sscpi = priv; - int ret; + int len, ret; - ret = serial_read(sscpi->serial, buf, maxlen); + len = BUFFER_SIZE - sscpi->count; - if (ret < 0) - return ret; + /* Try to read new data into the buffer if there is space. */ + if (len > 0) { + ret = serial_read(sscpi->serial, sscpi->buffer + sscpi->read, + BUFFER_SIZE - sscpi->count); - if (ret > 0) { - sscpi->last_character = buf[ret - 1]; - if (sscpi->last_character == '\n') - ret--; + if (ret < 0) + return ret; + + sscpi->count += ret; + + if (ret > 0) + sr_spew("Read %d bytes into buffer.", ret); } - return ret; + /* Return as many bytes as possible from buffer, excluding any trailing newline. */ + if (sscpi->read < sscpi->count) { + len = sscpi->count - sscpi->read; + if (len > maxlen) + len = maxlen; + if (sscpi->buffer[sscpi->read + len - 1] == '\n') + len--; + sr_spew("Returning %d bytes from buffer.", len); + memcpy(buf, sscpi->buffer + sscpi->read, len); + sscpi->read += len; + if (sscpi->read == BUFFER_SIZE) { + sr_spew("Resetting buffer."); + sscpi->count = 0; + sscpi->read = 0; + } + return len; + } + + return 0; } static int scpi_serial_read_complete(void *priv) { struct scpi_serial *sscpi = priv; - return (sscpi->last_character == '\n'); + /* If the next character is a newline, discard it and report complete. */ + if (sscpi->read < sscpi->count && sscpi->buffer[sscpi->read] == '\n') { + sscpi->read++; + return 1; + } else { + return 0; + } } static int scpi_serial_close(void *priv)