X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fcommon%2Fscpi_serial.c;h=0ee5894742629833e20fbe4526afa53460cb6b41;hb=a7c01629f6e96a79912977ed7262841cedf4ddfa;hp=c56e524ff052dff694481be86c06b72704d6843e;hpb=9dfeb81b09377cd5413c7ccd448fca2e77615084;p=libsigrok.git diff --git a/hardware/common/scpi_serial.c b/hardware/common/scpi_serial.c index c56e524f..0ee58947 100644 --- a/hardware/common/scpi_serial.c +++ b/hardware/common/scpi_serial.c @@ -24,20 +24,20 @@ #include #include -/* Message logging helpers with subsystem-specific prefix string. */ -#define LOG_PREFIX "scpi_serial: " -#define sr_log(l, s, args...) sr_log(l, LOG_PREFIX s, ## args) -#define sr_spew(s, args...) sr_spew(LOG_PREFIX s, ## args) -#define sr_dbg(s, args...) sr_dbg(LOG_PREFIX s, ## args) -#define sr_info(s, args...) sr_info(LOG_PREFIX s, ## args) -#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args) +#define LOG_PREFIX "scpi_serial" #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; @@ -51,35 +51,42 @@ 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 sr_source_add(serial->fd, events, timeout, cb, cb_data); + 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 sr_source_remove(serial->fd); + return serial_source_remove(serial); } SR_PRIV int scpi_serial_send(void *priv, const char *command) { - int len, out; + 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); - out = serial_write(serial, terminated_command, len); - g_free(terminated_command); - - if (out != len) { - sr_dbg("Only sent %d/%d bytes of SCPI command: '%s'.", out, - len, command); - return SR_ERR; + written = 0; + while (written < len) { + result = serial_write(serial, terminated_command + written, len - written); + if (result < 0) { + sr_err("Error while sending SCPI command: '%s'.", command); + g_free(terminated_command); + return SR_ERR; + } + written += result; } + g_free(terminated_command); + sr_spew("Successfully sent SCPI command: '%s'.", command); return SR_OK; @@ -91,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); @@ -138,29 +146,84 @@ SR_PRIV int scpi_serial_receive(void *priv, char **scpi_response) return ret; } +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) +{ + 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) +{ + struct scpi_serial *sscpi = priv; + struct sr_serial_dev_inst *serial = sscpi->serial; + + return serial_close(serial); +} + +static void scpi_serial_free(void *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 = serial_read; - scpi->close = serial_close; - scpi->free = sr_serial_dev_inst_free; - scpi->priv = serial; + 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 = sscpi; return scpi; }