]> sigrok.org Git - libsigrok.git/commitdiff
Revise SCPI read API to allow backend-independent data handling.
authorMartin Ling <redacted>
Sun, 29 Dec 2013 01:36:49 +0000 (02:36 +0100)
committerUwe Hermann <redacted>
Sun, 29 Dec 2013 03:26:36 +0000 (04:26 +0100)
hardware/common/scpi.c
hardware/common/scpi_serial.c
hardware/common/scpi_tcp.c
hardware/common/scpi_usbtmc.c
hardware/rigol-ds/protocol.c
libsigrok-internal.h

index a29f31b77085e916e3b2ae11219d15c3ce2a0a98..7329b294683b12db4b792976689c0eb7316130e3 100644 (file)
@@ -165,20 +165,15 @@ SR_PRIV int sr_scpi_send_variadic(struct sr_scpi_dev_inst *scpi,
 }
 
 /**
- * Receive an SCPI reply and store the reply in scpi_response.
+ * Begin receiving an SCPI reply.
  *
  * @param scpi Previously initialised SCPI device structure.
- * @param scpi_response Pointer where to store the SCPI response.
  *
- * @return SR_OK upon fetching a full SCPI response, SR_ERR upon fetching an
- *         incomplete or no response. The allocated response must be freed by
- *         the caller in the case of a full response as well in the case of
- *         an incomplete.
+ * @return SR_OK on success, SR_ERR on failure.
  */
-SR_PRIV int sr_scpi_receive(struct sr_scpi_dev_inst *scpi,
-                       char **scpi_response)
+SR_PRIV int sr_scpi_read_begin(struct sr_scpi_dev_inst *scpi)
 {
-       return scpi->receive(scpi->priv, scpi_response);
+       return scpi->read_begin(scpi->priv);
 }
 
 /**
@@ -190,10 +185,22 @@ SR_PRIV int sr_scpi_receive(struct sr_scpi_dev_inst *scpi,
  *
  * @return Number of bytes read, or SR_ERR upon failure.
  */
-SR_PRIV int sr_scpi_read(struct sr_scpi_dev_inst *scpi,
+SR_PRIV int sr_scpi_read_data(struct sr_scpi_dev_inst *scpi,
                        char *buf, int maxlen)
 {
-       return scpi->read(scpi->priv, buf, maxlen);
+       return scpi->read_data(scpi->priv, buf, maxlen);
+}
+
+/**
+ * Check whether a complete SCPI response has been received.
+ *
+ * @param scpi Previously initialised SCPI device structure.
+ *
+ * @return 1 if complete, 0 otherwise.
+ */
+SR_PRIV int sr_scpi_read_complete(struct sr_scpi_dev_inst *scpi)
+{
+       return scpi->read_complete(scpi->priv);
 }
 
 /**
@@ -228,19 +235,39 @@ SR_PRIV void sr_scpi_free(struct sr_scpi_dev_inst *scpi)
  * @param command The SCPI command to send to the device (can be NULL).
  * @param scpi_response Pointer where to store the SCPI response.
  *
- * @return SR_OK upon fetching a full SCPI response, SR_ERR upon fetching an
- *         incomplete or no response. The allocated response must be freed by
- *         the caller in the case of a full response as well in the case of
- *         an incomplete.
+ * @return SR_OK on success, SR_ERR on failure.
  */
 SR_PRIV int sr_scpi_get_string(struct sr_scpi_dev_inst *scpi,
                               const char *command, char **scpi_response)
 {
+       char buf[256];
+       int len;
+       GString *response;
+
        if (command)
                if (sr_scpi_send(scpi, command) != SR_OK)
                        return SR_ERR;
 
-       return sr_scpi_receive(scpi, scpi_response);
+       if (sr_scpi_read_begin(scpi) != SR_OK)
+               return SR_ERR;
+
+       response = g_string_new("");
+
+       *scpi_response = NULL;
+
+       while (!sr_scpi_read_complete(scpi)) {
+               len = sr_scpi_read_data(scpi, buf, sizeof(buf));
+               if (len < 0) {
+                       g_string_free(response, TRUE);
+                       return SR_ERR;
+               }
+               g_string_append_len(response, buf, len);
+       }
+
+       *scpi_response = response->str;
+       g_string_free(response, FALSE);
+
+       return SR_OK;
 }
 
 /**
index dc0996349937a181aef67b71012ed23abe61fddc..0ee5894742629833e20fbe4526afa53460cb6b41 100644 (file)
 #define SCPI_READ_RETRIES 100
 #define SCPI_READ_RETRY_TIMEOUT 10000
 
+struct scpi_serial {
+       struct sr_serial_dev_inst *serial;
+       char last_character;
+};
+
 SR_PRIV int scpi_serial_open(void *priv)
 {
-       struct sr_serial_dev_inst *serial = priv;
+       struct scpi_serial *sscpi = priv;
+       struct sr_serial_dev_inst *serial = sscpi->serial;
 
        if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
                return SR_ERR;
@@ -45,14 +51,16 @@ SR_PRIV int scpi_serial_open(void *priv)
 SR_PRIV int scpi_serial_source_add(void *priv, int events, int timeout,
                        sr_receive_data_callback_t cb, void *cb_data)
 {
-       struct sr_serial_dev_inst *serial = priv;
+       struct scpi_serial *sscpi = priv;
+       struct sr_serial_dev_inst *serial = sscpi->serial;
 
        return serial_source_add(serial, events, timeout, cb, cb_data);
 }
 
 SR_PRIV int scpi_serial_source_remove(void *priv)
 {
-       struct sr_serial_dev_inst *serial = priv;
+       struct scpi_serial *sscpi = priv;
+       struct sr_serial_dev_inst *serial = sscpi->serial;
 
        return serial_source_remove(serial);
 }
@@ -61,7 +69,8 @@ SR_PRIV int scpi_serial_send(void *priv, const char *command)
 {
        int len, result, written;
        gchar *terminated_command;
-       struct sr_serial_dev_inst *serial = priv;
+       struct scpi_serial *sscpi = priv;
+       struct sr_serial_dev_inst *serial = sscpi->serial;
 
        terminated_command = g_strconcat(command, "\n", NULL);
        len = strlen(terminated_command);
@@ -89,7 +98,8 @@ SR_PRIV int scpi_serial_receive(void *priv, char **scpi_response)
        char buf[256];
        unsigned int i;
        GString *response;
-       struct sr_serial_dev_inst *serial = priv;
+       struct scpi_serial *sscpi = priv;
+       struct sr_serial_dev_inst *serial = sscpi->serial;
 
        response = g_string_sized_new(1024);
 
@@ -136,43 +146,84 @@ SR_PRIV int scpi_serial_receive(void *priv, char **scpi_response)
        return ret;
 }
 
-/* Some stubs to keep the compiler from whining. */
-static int scpi_serial_read(void *priv, char *buf, int maxlen)
+SR_PRIV int scpi_serial_read_begin(void *priv)
+{
+       struct scpi_serial *sscpi = priv;
+
+       sscpi->last_character = '\0';
+
+       return SR_OK;
+}
+
+SR_PRIV int scpi_serial_read_data(void *priv, char *buf, int maxlen)
 {
-       return serial_read(priv, buf, maxlen);
+       struct scpi_serial *sscpi = priv;
+       int ret;
+
+       ret = serial_read(sscpi->serial, buf, maxlen);
+
+       if (ret < 0)
+               return ret;
+
+       if (ret > 0) {
+               sscpi->last_character = buf[ret - 1];
+               if (sscpi->last_character == '\n')
+                       ret--;
+       }
+
+       return ret;
 }
+
+SR_PRIV int scpi_serial_read_complete(void *priv)
+{
+       struct scpi_serial *sscpi = priv;
+
+       return (sscpi->last_character == '\n');
+}
+
 static int scpi_serial_close(void *priv)
 {
-       return serial_close(priv);
+       struct scpi_serial *sscpi = priv;
+       struct sr_serial_dev_inst *serial = sscpi->serial;
+
+       return serial_close(serial);
 }
+
 static void scpi_serial_free(void *priv)
 {
-       return sr_serial_dev_inst_free(priv);
+       struct scpi_serial *sscpi = priv;
+       struct sr_serial_dev_inst *serial = sscpi->serial;
+
+       sr_serial_dev_inst_free(serial);
+       g_free(sscpi);
 }
 
 SR_PRIV struct sr_scpi_dev_inst *scpi_serial_dev_inst_new(const char *port,
                const char *serialcomm)
 {
        struct sr_scpi_dev_inst *scpi;
+       struct scpi_serial *sscpi;
        struct sr_serial_dev_inst *serial;
 
-       scpi = g_try_malloc(sizeof(struct sr_scpi_dev_inst));
-
        if (!(serial = sr_serial_dev_inst_new(port, serialcomm)))
-       {
-               g_free(scpi);
                return NULL;
-       }
+
+       sscpi = g_malloc(sizeof(struct scpi_serial));
+
+       sscpi->serial = serial;
+
+       scpi = g_malloc(sizeof(struct sr_scpi_dev_inst));
 
        scpi->open = scpi_serial_open;
        scpi->source_add = scpi_serial_source_add;
        scpi->source_remove = scpi_serial_source_remove;
        scpi->send = scpi_serial_send;
-       scpi->receive = scpi_serial_receive;
-       scpi->read = scpi_serial_read;
+       scpi->read_begin = scpi_serial_read_begin;
+       scpi->read_data = scpi_serial_read_data;
+       scpi->read_complete = scpi_serial_read_complete;
        scpi->close = scpi_serial_close;
        scpi->free = scpi_serial_free;
-       scpi->priv = serial;
+       scpi->priv = sscpi;
 
        return scpi;
 }
index af2db140661ce99c04d77f79f92872723c4de8c5..44557937ef06af77a88d333973544f57c56587f5 100644 (file)
 
 #define LOG_PREFIX "scpi_tcp"
 
+#define LENGTH_BYTES 4
+
 struct scpi_tcp {
        char *address;
        char *port;
        int socket;
+       char length_buf[LENGTH_BYTES];
+       int length_bytes_read;
+       int response_length;
+       int response_bytes_read;
 };
 
 SR_PRIV int scpi_tcp_open(void *priv)
@@ -129,40 +135,40 @@ SR_PRIV int scpi_tcp_send(void *priv, const char *command)
        return SR_OK;
 }
 
-SR_PRIV int scpi_tcp_receive(void *priv, char **scpi_response)
+SR_PRIV int scpi_tcp_read_begin(void *priv)
 {
        struct scpi_tcp *tcp = priv;
-       GString *response;
-       char buf[256];
-       int len;
 
-       response = g_string_sized_new(1024);
-
-       len = recv(tcp->socket, buf, sizeof(buf), 0);
-
-       if (len < 0) {
-               sr_err("Receive error: %s", strerror(errno));
-               g_string_free(response, TRUE);
-               return SR_ERR;
-       }
-
-       response = g_string_append_len(response, buf + 4, len - 4);
-
-       *scpi_response = response->str;
-
-       sr_dbg("SCPI response received (length %d): '%.50s'",
-              response->len, response->str);
-
-       g_string_free(response, FALSE);
+       tcp->response_bytes_read = 0;
+       tcp->length_bytes_read = 0;
 
        return SR_OK;
 }
 
-SR_PRIV int scpi_tcp_read(void *priv, char *buf, int maxlen)
+SR_PRIV int scpi_tcp_read_data(void *priv, char *buf, int maxlen)
 {
        struct scpi_tcp *tcp = priv;
        int len;
 
+       if (tcp->length_bytes_read < LENGTH_BYTES) {
+               len = recv(tcp->socket, tcp->length_buf + tcp->length_bytes_read,
+                               LENGTH_BYTES - tcp->length_bytes_read, 0);
+               if (len < 0) {
+                       sr_err("Receive error: %s", strerror(errno));
+                       return SR_ERR;
+               }
+
+               tcp->length_bytes_read += len;
+
+               if (tcp->length_bytes_read < LENGTH_BYTES)
+                       return 0;
+               else
+                       tcp->response_length = RL32(tcp->length_buf);
+       }
+
+       if (tcp->response_bytes_read >= tcp->response_length)
+               return SR_ERR;
+
        len = recv(tcp->socket, buf, maxlen, 0);
 
        if (len < 0) {
@@ -170,9 +176,19 @@ SR_PRIV int scpi_tcp_read(void *priv, char *buf, int maxlen)
                return SR_ERR;
        }
 
+       tcp->response_bytes_read += len;
+
        return len;
 }
 
+SR_PRIV int scpi_tcp_read_complete(void *priv)
+{
+       struct scpi_tcp *tcp = priv;
+
+       return (tcp->length_bytes_read == LENGTH_BYTES &&
+                       tcp->response_bytes_read >= tcp->response_length);
+}
+
 SR_PRIV int scpi_tcp_close(void *priv)
 {
        struct scpi_tcp *tcp = priv;
@@ -209,8 +225,9 @@ SR_PRIV struct sr_scpi_dev_inst *scpi_tcp_dev_inst_new(const char *address,
        scpi->source_add = scpi_tcp_source_add;
        scpi->source_remove = scpi_tcp_source_remove;
        scpi->send = scpi_tcp_send;
-       scpi->receive = scpi_tcp_receive;
-       scpi->read = scpi_tcp_read;
+       scpi->read_begin = scpi_tcp_read_begin;
+       scpi->read_data = scpi_tcp_read_data;
+       scpi->read_complete = scpi_tcp_read_complete;
        scpi->close = scpi_tcp_close;
        scpi->free = scpi_tcp_free;
        scpi->priv = tcp;
index 298e3ab52012a7ade0ce810658dddc3c4372c56a..5aa0dbbd335d323dd20615984a59f9294069f7c5 100644 (file)
 
 #define LOG_PREFIX "scpi_usbtmc"
 
+#define MAX_READ_LENGTH 2048
+
+struct usbtmc_scpi {
+       struct sr_usbtmc_dev_inst *usbtmc;
+       char response_buffer[MAX_READ_LENGTH];
+       int response_length;
+       int response_bytes_read;
+};
+
 SR_PRIV int scpi_usbtmc_open(void *priv)
 {
-       struct sr_usbtmc_dev_inst *usbtmc = priv;
+       struct usbtmc_scpi *uscpi = priv;
+       struct sr_usbtmc_dev_inst *usbtmc = uscpi->usbtmc;
 
        if ((usbtmc->fd = open(usbtmc->device, O_RDWR)) < 0)
                return SR_ERR;
@@ -41,21 +51,24 @@ SR_PRIV int scpi_usbtmc_open(void *priv)
 SR_PRIV int scpi_usbtmc_source_add(void *priv, int events, int timeout,
                        sr_receive_data_callback_t cb, void *cb_data)
 {
-       struct sr_usbtmc_dev_inst *usbtmc = priv;
+       struct usbtmc_scpi *uscpi = priv;
+       struct sr_usbtmc_dev_inst *usbtmc = uscpi->usbtmc;
 
        return sr_source_add(usbtmc->fd, events, timeout, cb, cb_data);
 }
 
 SR_PRIV int scpi_usbtmc_source_remove(void *priv)
 {
-       struct sr_usbtmc_dev_inst *usbtmc = priv;
+       struct usbtmc_scpi *uscpi = priv;
+       struct sr_usbtmc_dev_inst *usbtmc = uscpi->usbtmc;
 
        return sr_source_remove(usbtmc->fd);
 }
 
 SR_PRIV int scpi_usbtmc_send(void *priv, const char *command)
 {
-       struct sr_usbtmc_dev_inst *usbtmc = priv;
+       struct usbtmc_scpi *uscpi = priv;
+       struct sr_usbtmc_dev_inst *usbtmc = uscpi->usbtmc;
        int len, out;
 
        len = strlen(command);
@@ -76,53 +89,56 @@ SR_PRIV int scpi_usbtmc_send(void *priv, const char *command)
        return SR_OK;
 }
 
-SR_PRIV int scpi_usbtmc_receive(void *priv, char **scpi_response)
+SR_PRIV int scpi_usbtmc_read_begin(void *priv)
 {
-       struct sr_usbtmc_dev_inst *usbtmc = priv;
-       GString *response;
-       char buf[256];
+       struct usbtmc_scpi *uscpi = priv;
+       struct sr_usbtmc_dev_inst *usbtmc = uscpi->usbtmc;
        int len;
 
-       response = g_string_sized_new(1024);
-
-       len = read(usbtmc->fd, buf, sizeof(buf));
+       len = read(usbtmc->fd, uscpi->response_buffer, MAX_READ_LENGTH);
 
        if (len < 0) {
                sr_err("Read error: %s", strerror(errno));
-               g_string_free(response, TRUE);
                return SR_ERR;
        }
 
-       response = g_string_append_len(response, buf, len);
-
-       *scpi_response = response->str;
-
-       sr_dbg("SCPI response received (length %d): '%.50s'",
-              response->len, response->str);
-
-       g_string_free(response, FALSE);
+       uscpi->response_length = len;
+       uscpi->response_bytes_read = 0;
 
        return SR_OK;
 }
 
-SR_PRIV int scpi_usbtmc_read(void *priv, char *buf, int maxlen)
+SR_PRIV int scpi_usbtmc_read_data(void *priv, char *buf, int maxlen)
 {
-       struct sr_usbtmc_dev_inst *usbtmc = priv;
-       int len;
-
-       len = read(usbtmc->fd, buf, maxlen);
+       struct usbtmc_scpi *uscpi = priv;
+       int read_length;
 
-       if (len < 0) {
-               sr_err("Read error: %s", strerror(errno));
+       if (uscpi->response_bytes_read >= uscpi->response_length)
                return SR_ERR;
-       }
 
-       return len;
+       read_length = uscpi->response_length - uscpi->response_bytes_read;
+
+       if (read_length > maxlen)
+               read_length = maxlen;
+
+       memcpy(buf, uscpi->response_buffer + uscpi->response_bytes_read, read_length);
+
+       uscpi->response_bytes_read += read_length;
+
+       return read_length;
+}
+
+SR_PRIV int scpi_usbtmc_read_complete(void *priv)
+{
+       struct usbtmc_scpi *uscpi = priv;
+
+       return (uscpi->response_bytes_read >= uscpi->response_length);
 }
 
 SR_PRIV int scpi_usbtmc_close(void *priv)
 {
-       struct sr_usbtmc_dev_inst *usbtmc = priv;
+       struct usbtmc_scpi *uscpi = priv;
+       struct sr_usbtmc_dev_inst *usbtmc = uscpi->usbtmc;
 
        if (close(usbtmc->fd) < 0)
                return SR_ERR;
@@ -132,31 +148,38 @@ SR_PRIV int scpi_usbtmc_close(void *priv)
 
 static void scpi_usbtmc_free(void *priv)
 {
-       return sr_usbtmc_dev_inst_free(priv);
+       struct usbtmc_scpi *uscpi = priv;
+       struct sr_usbtmc_dev_inst *usbtmc = uscpi->usbtmc;
+
+       g_free(uscpi);
+       sr_usbtmc_dev_inst_free(usbtmc);
 }
 
 SR_PRIV struct sr_scpi_dev_inst *scpi_usbtmc_dev_inst_new(const char *device)
 {
        struct sr_scpi_dev_inst *scpi;
+       struct usbtmc_scpi *uscpi;
        struct sr_usbtmc_dev_inst *usbtmc;
 
-       scpi = g_try_malloc(sizeof(struct sr_scpi_dev_inst));
-
        if (!(usbtmc = sr_usbtmc_dev_inst_new(device)))
-       {
-               g_free(scpi);
                return NULL;
-       }
+
+       uscpi = g_malloc(sizeof(struct usbtmc_scpi));
+
+       uscpi->usbtmc = usbtmc;
+
+       scpi = g_malloc(sizeof(struct sr_scpi_dev_inst));
 
        scpi->open = scpi_usbtmc_open;
        scpi->source_add = scpi_usbtmc_source_add;
        scpi->source_remove = scpi_usbtmc_source_remove;
        scpi->send = scpi_usbtmc_send;
-       scpi->receive = scpi_usbtmc_receive;
-       scpi->read = scpi_usbtmc_read;
+       scpi->read_begin = scpi_usbtmc_read_begin;
+       scpi->read_data = scpi_usbtmc_read_data;
+       scpi->read_complete = scpi_usbtmc_read_complete;
        scpi->close = scpi_usbtmc_close;
        scpi->free = scpi_usbtmc_free;
-       scpi->priv = usbtmc;
+       scpi->priv = uscpi;
 
        return scpi;
 }
index 4dec85b4fdcc90e26734c1f5fb83cd5dc2555c0a..fc938e9d93763ff95dfc9ff00c4198a145201fed 100644 (file)
@@ -368,7 +368,7 @@ static int rigol_ds_read_header(struct sr_scpi_dev_inst *scpi)
        int len, tmp;
 
        /* Read the hashsign and length digit. */
-       tmp = sr_scpi_read(scpi, start, 2);
+       tmp = sr_scpi_read_data(scpi, start, 2);
        start[2] = '\0';
        if (tmp != 2)
        {
@@ -383,7 +383,7 @@ static int rigol_ds_read_header(struct sr_scpi_dev_inst *scpi)
        len = atoi(start + 1);
 
        /* Read the data length. */
-       tmp = sr_scpi_read(scpi, length, len);
+       tmp = sr_scpi_read_data(scpi, length, len);
        length[len] = '\0';
        if (tmp != len)
        {
@@ -458,6 +458,8 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                probe = devc->channel_entry->data;
                
                if (devc->num_block_bytes == 0) {
+                       if (sr_scpi_read_begin(scpi) != SR_OK)
+                               return TRUE;
                        if (devc->model->protocol == PROTOCOL_IEEE488_2) {
                                sr_dbg("New block header expected");
                                if (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK)
@@ -474,7 +476,7 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                                if (devc->data_source == DATA_SOURCE_LIVE
                                                && (unsigned)len < devc->num_frame_samples) {
                                        sr_dbg("Discarding short data block");
-                                       sr_scpi_read(scpi, (char *)devc->buffer, len + 1);
+                                       sr_scpi_read_data(scpi, (char *)devc->buffer, len + 1);
                                        return TRUE;
                                }
                                devc->num_block_bytes = len;
@@ -489,7 +491,7 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                }
 
                len = devc->num_block_bytes - devc->num_block_read;
-               len = sr_scpi_read(scpi, (char *)devc->buffer,
+               len = sr_scpi_read_data(scpi, (char *)devc->buffer,
                                len < ACQ_BUFFER_SIZE ? len : ACQ_BUFFER_SIZE);
 
                sr_dbg("Received %d bytes.", len);
@@ -538,7 +540,7 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data)
                        if (devc->model->protocol == PROTOCOL_IEEE488_2) {
                                /* Discard the terminating linefeed and prepare for
                                   possible next block */
-                               sr_scpi_read(scpi, (char *)devc->buffer, 1);
+                               sr_scpi_read_data(scpi, (char *)devc->buffer, 1);
                                devc->num_block_bytes = 0;
                                if (devc->data_source != DATA_SOURCE_LIVE)
                                        rigol_ds_set_wait_event(devc, WAIT_BLOCK);
@@ -613,10 +615,7 @@ static int get_cfg(const struct sr_dev_inst *sdi, char *cmd, char *reply, size_t
        struct sr_scpi_dev_inst *scpi = sdi->conn;
        char *response;
 
-       if (sr_scpi_send(scpi, cmd) != SR_OK)
-               return SR_ERR;
-
-       if (sr_scpi_receive(scpi, &response) != SR_OK)
+       if (sr_scpi_get_string(scpi, cmd, &response) != SR_OK)
                return SR_ERR;
 
        g_strlcpy(reply, response, maxlen);
index 61978c297911b73a91c4f7bce4f98058d06eadf6..646164cf8b2d2cc46f2082ca636ea09064fa5881 100644 (file)
@@ -371,8 +371,9 @@ struct sr_scpi_dev_inst {
                int timeout, sr_receive_data_callback_t cb, void *cb_data);
        int (*source_remove)(void *priv);
        int (*send)(void *priv, const char *command);
-       int (*receive)(void *priv, char **scpi_response);
-       int (*read)(void *priv, char *buf, int maxlen);
+       int (*read_begin)(void *priv);
+       int (*read_data)(void *priv, char *buf, int maxlen);
+       int (*read_complete)(void *priv);
        int (*close)(void *priv);
        void (*free)(void *priv);
        void *priv;
@@ -386,9 +387,9 @@ SR_PRIV int sr_scpi_send(struct sr_scpi_dev_inst *scpi,
                const char *format, ...);
 SR_PRIV int sr_scpi_send_variadic(struct sr_scpi_dev_inst *scpi,
                const char *format, va_list args);
-SR_PRIV int sr_scpi_receive(struct sr_scpi_dev_inst *scpi,
-                       char **scpi_response);
-SR_PRIV int sr_scpi_read(struct sr_scpi_dev_inst *scpi, char *buf, int maxlen);
+SR_PRIV int sr_scpi_read_begin(struct sr_scpi_dev_inst *scpi);
+SR_PRIV int sr_scpi_read_data(struct sr_scpi_dev_inst *scpi, char *buf, int maxlen);
+SR_PRIV int sr_scpi_read_complete(struct sr_scpi_dev_inst *scpi);
 SR_PRIV int sr_scpi_close(struct sr_scpi_dev_inst *scpi);
 SR_PRIV void sr_scpi_free(struct sr_scpi_dev_inst *scpi);