X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fcommon%2Fscpi_usbtmc.c;h=3c98c06bc8c87bfa2eeb38cf962f821c271cd675;hb=2cfd16a31672be2ef8227dcda407e8cc5a24607f;hp=f7f0958eadeb9bcce3f3e6207d149f0d5c408726;hpb=a1ff9c1897262faa3b284ea5bb82593c45de70d0;p=libsigrok.git diff --git a/hardware/common/scpi_usbtmc.c b/hardware/common/scpi_usbtmc.c index f7f0958e..3c98c06b 100644 --- a/hardware/common/scpi_usbtmc.c +++ b/hardware/common/scpi_usbtmc.c @@ -26,17 +26,35 @@ #include #include -/* Message logging helpers with subsystem-specific prefix string. */ -#define LOG_PREFIX "scpi_usbtmc: " -#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) - -SR_PRIV int scpi_usbtmc_open(void *priv) +#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; +}; + +static int scpi_usbtmc_dev_inst_new(void *priv, const char *resource, + char **params, const char *serialcomm) { - struct sr_usbtmc_dev_inst *usbtmc = priv; + struct usbtmc_scpi *uscpi = priv; + + (void)params; + (void)serialcomm; + + if (!(uscpi->usbtmc = sr_usbtmc_dev_inst_new(resource))) + return SR_ERR; + + return SR_OK; +} + +static int scpi_usbtmc_open(void *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; @@ -44,24 +62,27 @@ SR_PRIV int scpi_usbtmc_open(void *priv) return SR_OK; } -SR_PRIV int scpi_usbtmc_source_add(void *priv, int events, int timeout, +static 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) +static 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) +static 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); @@ -82,82 +103,90 @@ 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) +static 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, unsigned char *buf, int maxlen) +static int scpi_usbtmc_read_data(void *priv, char *buf, int maxlen) { - struct sr_usbtmc_dev_inst *usbtmc = priv; - int len; + struct usbtmc_scpi *uscpi = priv; + int read_length; - len = read(usbtmc->fd, buf, maxlen); + if (uscpi->response_length == MAX_READ_LENGTH + && uscpi->response_bytes_read == uscpi->response_length) + if (scpi_usbtmc_read_begin(uscpi) != SR_OK) + return SR_ERR; - 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_close(void *priv) +static int scpi_usbtmc_read_complete(void *priv) { - struct sr_usbtmc_dev_inst *usbtmc = priv; + struct usbtmc_scpi *uscpi = priv; - if (close(usbtmc->fd) < 0) - return SR_ERR; + if (uscpi->response_length == MAX_READ_LENGTH + && uscpi->response_bytes_read == uscpi->response_length) + scpi_usbtmc_read_begin(uscpi); - return SR_OK; + return (uscpi->response_bytes_read >= uscpi->response_length); } -SR_PRIV struct sr_scpi_dev_inst *scpi_usbtmc_dev_inst_new(const char *device) +static int scpi_usbtmc_close(void *priv) { - struct sr_scpi_dev_inst *scpi; - struct sr_usbtmc_dev_inst *usbtmc; + struct usbtmc_scpi *uscpi = priv; - scpi = g_try_malloc(sizeof(struct sr_scpi_dev_inst)); + if (close(uscpi->usbtmc->fd) < 0) + return SR_ERR; - if (!(usbtmc = sr_usbtmc_dev_inst_new(device))) - { - g_free(scpi); - return NULL; - } + return SR_OK; +} + +static void scpi_usbtmc_free(void *priv) +{ + struct usbtmc_scpi *uscpi = priv; - 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->close = scpi_usbtmc_close; - scpi->free = sr_usbtmc_dev_inst_free; - scpi->priv = usbtmc; - - return scpi; + sr_usbtmc_dev_inst_free(uscpi->usbtmc); } + +SR_PRIV const struct sr_scpi_dev_inst scpi_usbtmc_dev = { + .name = "USBTMC", + .prefix = "/dev/usbtmc", + .priv_size = sizeof(struct usbtmc_scpi), + .dev_inst_new = scpi_usbtmc_dev_inst_new, + .open = scpi_usbtmc_open, + .source_add = scpi_usbtmc_source_add, + .source_remove = scpi_usbtmc_source_remove, + .send = scpi_usbtmc_send, + .read_begin = scpi_usbtmc_read_begin, + .read_data = scpi_usbtmc_read_data, + .read_complete = scpi_usbtmc_read_complete, + .close = scpi_usbtmc_close, + .free = scpi_usbtmc_free, +};