}
/**
- * 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);
}
/**
*
* @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);
}
/**
* @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;
}
/**
#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;
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);
}
{
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);
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);
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;
}
#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)
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) {
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;
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;
#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;
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);
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;
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;
}
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)
{
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)
{
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)
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;
}
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);
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);
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);
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;
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);