X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fscpi%2Fscpi.c;h=8d24ceea97e29c88de244fae03600a8cf52b6507;hb=HEAD;hp=0f767f2a2de1c6862b61620d6e2dc0b9178c2f7d;hpb=9b915e3a41311bff4d7089f564f3b2716f2004a7;p=libsigrok.git diff --git a/src/scpi/scpi.c b/src/scpi/scpi.c index 0f767f2a..8d24ceea 100644 --- a/src/scpi/scpi.c +++ b/src/scpi/scpi.c @@ -38,6 +38,7 @@ static const char *scpi_vendors[][2] = { { "Keysight Technologies", "Keysight" }, { "PHILIPS", "Philips" }, { "RIGOL TECHNOLOGIES", "Rigol" }, + { "Siglent Technologies", "Siglent" }, }; /** @@ -315,33 +316,32 @@ SR_PRIV GSList *sr_scpi_scan(struct drv_context *drvc, GSList *options, { GSList *resources, *l, *devices; struct sr_dev_inst *sdi; - const char *resource = NULL; - const char *serialcomm = NULL; + const char *resource, *conn; + const char *serialcomm, *comm; gchar **res; unsigned i; - for (l = options; l; l = l->next) { - struct sr_config *src = l->data; - switch (src->key) { - case SR_CONF_CONN: - resource = g_variant_get_string(src->data, NULL); - break; - case SR_CONF_SERIALCOMM: - serialcomm = g_variant_get_string(src->data, NULL); - break; - } - } + resource = NULL; + serialcomm = NULL; + (void)sr_serial_extract_options(options, &resource, &serialcomm); devices = NULL; for (i = 0; i < ARRAY_SIZE(scpi_devs); i++) { - if ((resource && strcmp(resource, scpi_devs[i]->prefix)) - || !scpi_devs[i]->scan) + if (resource && strcmp(resource, scpi_devs[i]->prefix) != 0) + continue; + if (!scpi_devs[i]->scan) continue; resources = scpi_devs[i]->scan(drvc); for (l = resources; l; l = l->next) { res = g_strsplit(l->data, ":", 2); - if (res[0] && (sdi = sr_scpi_scan_resource(drvc, res[0], - serialcomm ? serialcomm : res[1], probe_device))) { + if (!res[0]) { + g_strfreev(res); + continue; + } + conn = res[0]; + comm = serialcomm ? : res[1]; + sdi = sr_scpi_scan_resource(drvc, conn, comm, probe_device); + if (sdi) { devices = g_slist_append(devices, sdi); sdi->connection_id = g_strdup(l->data); } @@ -863,28 +863,30 @@ SR_PRIV int sr_scpi_get_floatv(struct sr_scpi_dev_inst *scpi, float tmp; char *response; gchar **ptr, **tokens; + size_t token_count; GArray *response_array; *scpi_response = NULL; - response = NULL; - tokens = NULL; + response = NULL; ret = sr_scpi_get_string(scpi, command, &response); if (ret != SR_OK && !response) return ret; tokens = g_strsplit(response, ",", 0); - ptr = tokens; + token_count = g_strv_length(tokens); - response_array = g_array_sized_new(TRUE, FALSE, sizeof(float), 256); + response_array = g_array_sized_new(TRUE, FALSE, + sizeof(float), token_count + 1); + ptr = tokens; while (*ptr) { - if (sr_atof_ascii(*ptr, &tmp) == SR_OK) - response_array = g_array_append_val(response_array, - tmp); - else + ret = sr_atof_ascii(*ptr, &tmp); + if (ret != SR_OK) { ret = SR_ERR_DATA; - + break; + } + response_array = g_array_append_val(response_array, tmp); ptr++; } g_strfreev(tokens); @@ -920,28 +922,30 @@ SR_PRIV int sr_scpi_get_uint8v(struct sr_scpi_dev_inst *scpi, int tmp, ret; char *response; gchar **ptr, **tokens; + size_t token_count; GArray *response_array; *scpi_response = NULL; - response = NULL; - tokens = NULL; + response = NULL; ret = sr_scpi_get_string(scpi, command, &response); if (ret != SR_OK && !response) return ret; tokens = g_strsplit(response, ",", 0); - ptr = tokens; + token_count = g_strv_length(tokens); - response_array = g_array_sized_new(TRUE, FALSE, sizeof(uint8_t), 256); + response_array = g_array_sized_new(TRUE, FALSE, + sizeof(uint8_t), token_count + 1); + ptr = tokens; while (*ptr) { - if (sr_atoi(*ptr, &tmp) == SR_OK) - response_array = g_array_append_val(response_array, - tmp); - else + ret = sr_atoi(*ptr, &tmp); + if (ret != SR_OK) { ret = SR_ERR_DATA; - + break; + } + response_array = g_array_append_val(response_array, tmp); ptr++; } g_strfreev(tokens); @@ -1034,7 +1038,29 @@ SR_PRIV int sr_scpi_get_block(struct sr_scpi_dev_inst *scpi, buf[0] = response->str[1]; buf[1] = '\0'; ret = sr_atol(buf, &llen); - if ((ret != SR_OK) || (llen == 0)) { + /* + * The form "#0..." is legal, and does not mean "empty response", + * but means that the number of data bytes is not known (or was + * not communicated) at this time. Instead the block ends at an + * "END MESSAGE" termination sequence. Which translates to active + * EOI while a text line termination is sent (CR or LF, and this + * text line termination is not part of the block's data value). + * Since this kind of #0... response is considered rare, and + * depends on specific support in physical transports underneath + * the SCPI layer, let's flag the condition and bail out with an + * error here, until it's found to be a genuine issue in the field. + * + * The SCPI 1999.0 specification (see page 220 and following in + * the "HCOPy" description) references IEEE 488.2, especially + * section 8.7.9 for DEFINITE LENGTH and section 8.7.10 for + * INDEFINITE LENGTH ARBITRARY BLOCK RESPONSE DATA. The latter + * with a leading "#0" length and a trailing "NL^END" marker. + */ + if (ret == SR_OK && !llen) { + sr_err("unsupported INDEFINITE LENGTH ARBITRARY BLOCK RESPONSE"); + ret = SR_ERR_NA; + } + if (ret != SR_OK) { g_mutex_unlock(&scpi->scpi_mutex); g_string_free(response, TRUE); return ret; @@ -1151,7 +1177,7 @@ SR_PRIV int sr_scpi_get_hw_id(struct sr_scpi_dev_inst *scpi, } g_free(response); - hw_info = g_malloc0(sizeof(struct sr_scpi_hw_info)); + hw_info = g_malloc0(sizeof(*hw_info)); idn_substr = g_strstr_len(tokens[0], -1, "IDN "); if (idn_substr == NULL)