X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Frigol-ds1xx2%2Fapi.c;h=61b3dbe141a4a81c840f2b0f8604f96e34fade7c;hb=2efa699fda95b6d2d722d41407ca741cdbfe709c;hp=4023ecca1ef4d2a4bd705d442f5af799cf87736c;hpb=512bb890df8363e800025b3b63ebac429c139aa0;p=libsigrok.git diff --git a/hardware/rigol-ds1xx2/api.c b/hardware/rigol-ds1xx2/api.c index 4023ecca..61b3dbe1 100644 --- a/hardware/rigol-ds1xx2/api.c +++ b/hardware/rigol-ds1xx2/api.c @@ -26,26 +26,18 @@ #include "libsigrok-internal.h" #include "protocol.h" -#define NUM_PROBES 2 - -static const int hwcaps[] = { - SR_HWCAP_OSCILLOSCOPE, - SR_HWCAP_LIMIT_SAMPLES, - SR_HWCAP_TIMEBASE, - SR_HWCAP_TRIGGER_SOURCE, - SR_HWCAP_TRIGGER_SLOPE, - SR_HWCAP_HORIZ_TRIGGERPOS, - SR_HWCAP_VDIV, - SR_HWCAP_COUPLING, - 0, +static const int32_t hwcaps[] = { + SR_CONF_OSCILLOSCOPE, + SR_CONF_LIMIT_SAMPLES, + SR_CONF_TIMEBASE, + SR_CONF_TRIGGER_SOURCE, + SR_CONF_TRIGGER_SLOPE, + SR_CONF_HORIZ_TRIGGERPOS, + SR_CONF_VDIV, + SR_CONF_COUPLING, }; -static const char *probe_names[] = { - "CH1", "CH2", - NULL, -}; - -static const struct sr_rational timebases[] = { +static const uint64_t timebases[][2] = { /* nanoseconds */ { 2, 1000000000 }, { 5, 1000000000 }, @@ -81,10 +73,9 @@ static const struct sr_rational timebases[] = { { 10, 1 }, { 20, 1 }, { 50, 1 }, - { 0, 0}, }; -static const struct sr_rational vdivs[] = { +static const uint64_t vdivs[][2] = { /* millivolts */ { 2, 1000 }, { 5, 1000 }, @@ -99,7 +90,6 @@ static const struct sr_rational vdivs[] = { { 2, 1 }, { 5, 1 }, { 10, 1 }, - { 0, 0 }, }; static const char *trigger_sources[] = { @@ -107,21 +97,19 @@ static const char *trigger_sources[] = { "CH2", "EXT", "AC Line", - NULL, }; static const char *coupling[] = { "AC", "DC", "GND", - NULL, }; static const char *supported_models[] = { "DS1052E", "DS1102E", "DS1052D", - "DS1102D" + "DS1102D", }; SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info; @@ -145,6 +133,7 @@ static int clear_instances(void) continue; g_free(devc->device); + g_slist_free(devc->enabled_probes); close(devc->fd); sr_dev_inst_free(sdi); @@ -158,17 +147,7 @@ static int clear_instances(void) static int hw_init(struct sr_context *sr_ctx) { - struct drv_context *drvc; - (void)sr_ctx; - - if (!(drvc = g_try_malloc0(sizeof(struct drv_context)))) { - sr_err("Driver context malloc failed."); - return SR_ERR_MALLOC; - } - - di->priv = drvc; - - return SR_OK; + return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN); } static GSList *hw_scan(GSList *options) @@ -184,20 +163,21 @@ static GSList *hw_scan(GSList *options) const gchar *prefix = "usbtmc"; gchar *device; const gchar *idn_query = "*IDN?"; - int len, num_tokens, fd, i; + unsigned int i; + int len, num_tokens, fd; const gchar *delimiter = ","; gchar **tokens; const char *manufacturer, *model, *version; - int num_models; gboolean matched = FALSE; char buf[256]; (void)options; - devices = NULL; drvc = di->priv; drvc->instances = NULL; + devices = NULL; + dir = g_dir_open("/sys/class/usb/", 0, NULL); if (dir == NULL) @@ -241,9 +221,7 @@ static GSList *hw_scan(GSList *options) return NULL; } - num_models = sizeof(supported_models) / sizeof(supported_models[0]); - - for (i = 0; i < num_models; i++) { + for (i = 0; i < ARRAY_SIZE(supported_models); i++) { if (!strcmp(model, supported_models[i])) { matched = 1; break; @@ -288,11 +266,7 @@ static GSList *hw_scan(GSList *options) static GSList *hw_dev_list(void) { - struct drv_context *drvc; - - drvc = di->priv; - - return drvc->instances; + return ((struct drv_context *)(di->priv))->instances; } static int hw_dev_open(struct sr_dev_inst *sdi) @@ -330,50 +304,14 @@ static int hw_cleanup(void) return SR_OK; } -static int hw_info_get(int info_id, const void **data, - const struct sr_dev_inst *sdi) -{ - (void)sdi; - - switch (info_id) { - case SR_DI_HWCAPS: - *data = hwcaps; - break; - case SR_DI_NUM_PROBES: - *data = GINT_TO_POINTER(NUM_PROBES); - break; - case SR_DI_PROBE_NAMES: - *data = probe_names; - break; - case SR_DI_TIMEBASES: - *data = timebases; - break; - case SR_DI_TRIGGER_SOURCES: - *data = trigger_sources; - break; - case SR_DI_VDIVS: - *data = vdivs; - break; - case SR_DI_COUPLING: - *data = coupling; - break; - default: - sr_err("Unknown info_id: %d.", info_id); - return SR_ERR_ARG; - } - - return SR_OK; -} - -static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, - const void *value) +static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi) { struct dev_context *devc; - uint64_t tmp_u64; - float tmp_float; - struct sr_rational tmp_rat; - int ret, i, j; - char *channel; + uint64_t tmp_u64, p, q; + double tmp_double; + unsigned int i; + int tmp_int, ret; + const char *tmp_str, *channel; devc = sdi->priv; @@ -383,32 +321,41 @@ static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, } ret = SR_OK; - switch (hwcap) { - case SR_HWCAP_LIMIT_FRAMES: - devc->limit_frames = *(const uint64_t *)value; + switch (id) { + case SR_CONF_LIMIT_FRAMES: + devc->limit_frames = g_variant_get_uint64(data); break; - case SR_HWCAP_TRIGGER_SLOPE: - tmp_u64 = *(const int *)value; + case SR_CONF_TRIGGER_SLOPE: + tmp_u64 = g_variant_get_uint64(data); rigol_ds1xx2_send_data(devc->fd, ":TRIG:EDGE:SLOP %s\n", tmp_u64 ? "POS" : "NEG"); break; - case SR_HWCAP_HORIZ_TRIGGERPOS: - tmp_float = *(const float *)value; - rigol_ds1xx2_send_data(devc->fd, ":TIM:OFFS %.9f\n", tmp_float); + case SR_CONF_HORIZ_TRIGGERPOS: + tmp_double = g_variant_get_double(data); + rigol_ds1xx2_send_data(devc->fd, ":TIM:OFFS %.9f\n", tmp_double); break; - case SR_HWCAP_TIMEBASE: - tmp_rat = *(const struct sr_rational *)value; - rigol_ds1xx2_send_data(devc->fd, ":TIM:SCAL %.9f\n", - (float)tmp_rat.p / tmp_rat.q); + case SR_CONF_TIMEBASE: + g_variant_get(data, "(tt)", &p, &q); + tmp_int = -1; + for (i = 0; i < ARRAY_SIZE(timebases); i++) { + if (timebases[i][0] == p && timebases[i][1] == q) { + tmp_int = i; + break; + } + } + if (tmp_int >= 0) + rigol_ds1xx2_send_data(devc->fd, ":TIM:SCAL %.9f\n", + (float)timebases[i][0] / timebases[i][1]); break; - case SR_HWCAP_TRIGGER_SOURCE: - if (!strcmp(value, "CH1")) + case SR_CONF_TRIGGER_SOURCE: + tmp_str = g_variant_get_string(data, NULL); + if (!strcmp(tmp_str, "CH1")) channel = "CHAN1"; - else if (!strcmp(value, "CH2")) + else if (!strcmp(tmp_str, "CH2")) channel = "CHAN2"; - else if (!strcmp(value, "EXT")) + else if (!strcmp(tmp_str, "EXT")) channel = "EXT"; - else if (!strcmp(value, "AC Line")) + else if (!strcmp(tmp_str, "AC Line")) channel = "ACL"; else { ret = SR_ERR_ARG; @@ -416,37 +363,39 @@ static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, } rigol_ds1xx2_send_data(devc->fd, ":TRIG:EDGE:SOUR %s\n", channel); break; - case SR_HWCAP_VDIV: - /* TODO: Not supporting vdiv per channel yet. */ - tmp_rat = *(const struct sr_rational *)value; - for (i = 0; vdivs[i].p && vdivs[i].q; i++) { - if (vdivs[i].p == tmp_rat.p - && vdivs[i].q == tmp_rat.q) { - devc->scale = (float)tmp_rat.p / tmp_rat.q; - for (j = 0; j < 2; j++) - rigol_ds1xx2_send_data(devc->fd, - ":CHAN%d:SCAL %.3f\n", j, devc->scale); - break; - } + case SR_CONF_VDIV: + g_variant_get(data, "(tt)", &p, &q); + tmp_int = -1; + for (i = 0; i < ARRAY_SIZE(vdivs); i++) { + if (vdivs[i][0] != p || vdivs[i][1] != q) + continue; + devc->scale = (float)vdivs[i][0] / vdivs[i][1]; + rigol_ds1xx2_send_data(devc->fd, ":CHAN0:SCAL %.3f\n", + devc->scale); + rigol_ds1xx2_send_data(devc->fd, ":CHAN1:SCAL %.3f\n", + devc->scale); + break; } - if (vdivs[i].p == 0 && vdivs[i].q == 0) + if (i == ARRAY_SIZE(vdivs)) ret = SR_ERR_ARG; break; - case SR_HWCAP_COUPLING: + case SR_CONF_COUPLING: /* TODO: Not supporting coupling per channel yet. */ - for (i = 0; coupling[i]; i++) { - if (!strcmp(value, coupling[i])) { - for (j = 0; j < 2; j++) - rigol_ds1xx2_send_data(devc->fd, - ":CHAN%d:COUP %s\n", j, coupling[i]); + tmp_str = g_variant_get_string(data, NULL); + for (i = 0; i < ARRAY_SIZE(coupling); i++) { + if (!strcmp(tmp_str, coupling[i])) { + rigol_ds1xx2_send_data(devc->fd, ":CHAN0:COUP %s\n", + coupling[i]); + rigol_ds1xx2_send_data(devc->fd, ":CHAN1:COUP %s\n", + coupling[i]); break; } } - if (coupling[i] == 0) + if (i == ARRAY_SIZE(coupling)) ret = SR_ERR_ARG; break; default: - sr_err("Unknown hardware capability: %d.", hwcap); + sr_err("Unknown hardware capability: %d.", id); ret = SR_ERR_ARG; break; } @@ -454,13 +403,57 @@ static int hw_dev_config_set(const struct sr_dev_inst *sdi, int hwcap, return ret; } +static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi) +{ + GVariant *tuple, *rational[2]; + GVariantBuilder gvb; + unsigned int i; + + (void)sdi; + + switch (key) { + case SR_CONF_DEVICE_OPTIONS: + *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32, + hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t)); + break; + case SR_CONF_COUPLING: + *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling)); + break; + case SR_CONF_VDIV: + g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); + for (i = 0; i < ARRAY_SIZE(vdivs); i++) { + rational[0] = g_variant_new_uint64(vdivs[i][0]); + rational[1] = g_variant_new_uint64(vdivs[i][1]); + tuple = g_variant_new_tuple(rational, 2); + g_variant_builder_add_value(&gvb, tuple); + } + *data = g_variant_builder_end(&gvb); + break; + case SR_CONF_TIMEBASE: + g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY); + for (i = 0; i < ARRAY_SIZE(timebases); i++) { + rational[0] = g_variant_new_uint64(timebases[i][0]); + rational[1] = g_variant_new_uint64(timebases[i][1]); + tuple = g_variant_new_tuple(rational, 2); + g_variant_builder_add_value(&gvb, tuple); + } + *data = g_variant_builder_end(&gvb); + break; + case SR_CONF_TRIGGER_SOURCE: + *data = g_variant_new_strv(trigger_sources, + ARRAY_SIZE(trigger_sources)); + break; + default: + return SR_ERR_ARG; + } + + return SR_OK; +} + static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; - struct sr_datafeed_packet packet; - struct sr_datafeed_header header; - struct sr_datafeed_meta_analog meta; char buf[256]; int len; @@ -473,18 +466,10 @@ static int hw_dev_acquisition_start(const struct sr_dev_inst *sdi, sr_source_add(devc->fd, G_IO_IN, 50, rigol_ds1xx2_receive_data, (void *)sdi); /* Send header packet to the session bus. */ - packet.type = SR_DF_HEADER; - packet.payload = (unsigned char *)&header; - header.feed_version = 1; - gettimeofday(&header.starttime, NULL); - sr_session_send(cb_data, &packet); - - /* Send metadata about the SR_DF_ANALOG packets to come. */ - packet.type = SR_DF_META_ANALOG; - packet.payload = &meta; - meta.num_probes = NUM_PROBES; - sr_session_send(cb_data, &packet); + std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN); + /* Hardcoded to CH1 only. */ + devc->enabled_probes = g_slist_append(NULL, sdi->probes->data); rigol_ds1xx2_send_data(devc->fd, ":CHAN1:SCAL?\n"); len = read(devc->fd, buf, sizeof(buf)); buf[len] = 0; @@ -527,10 +512,11 @@ SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = { .scan = hw_scan, .dev_list = hw_dev_list, .dev_clear = clear_instances, + .config_get = NULL, + .config_set = config_set, + .config_list = config_list, .dev_open = hw_dev_open, .dev_close = hw_dev_close, - .info_get = hw_info_get, - .dev_config_set = hw_dev_config_set, .dev_acquisition_start = hw_dev_acquisition_start, .dev_acquisition_stop = hw_dev_acquisition_stop, .priv = NULL,