/* Check that a single shot acquisition actually succeeded on the DS2000 */ static int rigol_ds_check_stop(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_channel *ch; int tmp; if (!(devc = sdi->priv)) return SR_ERR; ch = devc->channel_entry->data; if (devc->model->series->protocol != PROTOCOL_V3) return SR_OK; if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", ch->index + 1) != SR_OK) return SR_ERR; /* Check that the number of samples will be accepted */ if (rigol_ds_config_set(sdi, ":WAV:POIN %d", devc->analog_frame_size) != SR_OK) return SR_ERR; if (sr_scpi_get_int(sdi->conn, "*ESR?", &tmp) != SR_OK) return SR_ERR; /* * If we get an "Execution error" the scope went from "Single" to * "Stop" without actually triggering. There is no waveform * displayed and trying to download one will fail - the scope thinks * it has 1400 samples (like display memory) and the driver thinks * it has a different number of samples. * * In that case just try to capture something again. Might still * fail in interesting ways. * * Ain't firmware fun? */ if (tmp & 0x10) { sr_warn("Single shot acquisition failed, retrying..."); /* Sleep a bit, otherwise the single shot will often fail */ g_usleep(500 * 1000); rigol_ds_config_set(sdi, ":SING"); rigol_ds_set_wait_event(devc, WAIT_STOP); return SR_ERR; } return SR_OK; }
static int dev_close(struct sr_dev_inst *sdi) { struct sr_scpi_dev_inst *scpi; struct dev_context *devc; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; scpi = sdi->conn; devc = sdi->priv; if (devc->model->series->protocol == PROTOCOL_V2) rigol_ds_config_set(sdi, ":KEY:LOCK DISABLE"); if (scpi) { if (sr_scpi_close(scpi) < 0) return SR_ERR; sdi->status = SR_ST_INACTIVE; } return SR_OK; }
SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; struct sr_scpi_dev_inst *scpi; struct dev_context *devc; struct sr_datafeed_packet packet; struct sr_datafeed_analog_old analog; struct sr_datafeed_logic logic; double vdiv, offset; int len, i, vref; struct sr_channel *ch; gsize expected_data_bytes; (void)fd; if (!(sdi = cb_data)) return TRUE; if (!(devc = sdi->priv)) return TRUE; scpi = sdi->conn; if (!(revents == G_IO_IN || revents == 0)) return TRUE; switch (devc->wait_event) { case WAIT_NONE: break; case WAIT_TRIGGER: if (rigol_ds_trigger_wait(sdi) != SR_OK) return TRUE; if (rigol_ds_channel_start(sdi) != SR_OK) return TRUE; return TRUE; case WAIT_BLOCK: if (rigol_ds_block_wait(sdi) != SR_OK) return TRUE; break; case WAIT_STOP: if (rigol_ds_stop_wait(sdi) != SR_OK) return TRUE; if (rigol_ds_check_stop(sdi) != SR_OK) return TRUE; if (rigol_ds_channel_start(sdi) != SR_OK) return TRUE; return TRUE; default: sr_err("BUG: Unknown event target encountered"); break; } ch = devc->channel_entry->data; expected_data_bytes = ch->type == SR_CHANNEL_ANALOG ? devc->analog_frame_size : devc->digital_frame_size; if (devc->num_block_bytes == 0) { if (devc->model->series->protocol >= PROTOCOL_V4) { if (sr_scpi_send(sdi->conn, ":WAV:START %d", devc->num_channel_bytes + 1) != SR_OK) return TRUE; if (sr_scpi_send(sdi->conn, ":WAV:STOP %d", MIN(devc->num_channel_bytes + ACQ_BLOCK_SIZE, devc->analog_frame_size)) != SR_OK) return TRUE; } if (devc->model->series->protocol >= PROTOCOL_V3) if (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK) return TRUE; if (sr_scpi_read_begin(scpi) != SR_OK) return TRUE; if (devc->format == FORMAT_IEEE488_2) { sr_dbg("New block header expected"); len = rigol_ds_read_header(sdi); if (len == 0) /* Still reading the header. */ return TRUE; if (len == -1) { sr_err("Read error, aborting capture."); packet.type = SR_DF_FRAME_END; sr_session_send(cb_data, &packet); sdi->driver->dev_acquisition_stop(sdi, cb_data); return TRUE; } /* At slow timebases in live capture the DS2072 * sometimes returns "short" data blocks, with * apparently no way to get the rest of the data. * Discard these, the complete data block will * appear eventually. */ if (devc->data_source == DATA_SOURCE_LIVE && (unsigned)len < expected_data_bytes) { sr_dbg("Discarding short data block"); sr_scpi_read_data(scpi, (char *)devc->buffer, len + 1); return TRUE; } devc->num_block_bytes = len; } else { devc->num_block_bytes = expected_data_bytes; } devc->num_block_read = 0; } len = devc->num_block_bytes - devc->num_block_read; if (len > ACQ_BUFFER_SIZE) len = ACQ_BUFFER_SIZE; sr_dbg("Requesting read of %d bytes", len); len = sr_scpi_read_data(scpi, (char *)devc->buffer, len); if (len == -1) { sr_err("Read error, aborting capture."); packet.type = SR_DF_FRAME_END; sr_session_send(cb_data, &packet); sdi->driver->dev_acquisition_stop(sdi, cb_data); return TRUE; } sr_dbg("Received %d bytes.", len); devc->num_block_read += len; if (ch->type == SR_CHANNEL_ANALOG) { vref = devc->vert_reference[ch->index]; vdiv = devc->vdiv[ch->index] / 25.6; offset = devc->vert_offset[ch->index]; if (devc->model->series->protocol >= PROTOCOL_V3) for (i = 0; i < len; i++) devc->data[i] = ((int)devc->buffer[i] - vref) * vdiv - offset; else for (i = 0; i < len; i++) devc->data[i] = (128 - devc->buffer[i]) * vdiv - offset; analog.channels = g_slist_append(NULL, ch); analog.num_samples = len; analog.data = devc->data; analog.mq = SR_MQ_VOLTAGE; analog.unit = SR_UNIT_VOLT; analog.mqflags = 0; packet.type = SR_DF_ANALOG_OLD; packet.payload = &analog; sr_session_send(cb_data, &packet); g_slist_free(analog.channels); } else { logic.length = len; // TODO: For the MSO1000Z series, we need a way to express that // this data is in fact just for a single channel, with the valid // data for that channel in the LSB of each byte. logic.unitsize = devc->model->series->protocol == PROTOCOL_V4 ? 1 : 2; logic.data = devc->buffer; packet.type = SR_DF_LOGIC; packet.payload = &logic; sr_session_send(cb_data, &packet); } if (devc->num_block_read == devc->num_block_bytes) { sr_dbg("Block has been completed"); if (devc->model->series->protocol >= PROTOCOL_V3) { /* Discard the terminating linefeed */ sr_scpi_read_data(scpi, (char *)devc->buffer, 1); } if (devc->format == FORMAT_IEEE488_2) { /* Prepare for possible next block */ devc->num_header_bytes = 0; devc->num_block_bytes = 0; if (devc->data_source != DATA_SOURCE_LIVE) rigol_ds_set_wait_event(devc, WAIT_BLOCK); } if (!sr_scpi_read_complete(scpi)) { sr_err("Read should have been completed"); packet.type = SR_DF_FRAME_END; sr_session_send(cb_data, &packet); sdi->driver->dev_acquisition_stop(sdi, cb_data); return TRUE; } devc->num_block_read = 0; } else { sr_dbg("%" PRIu64 " of %" PRIu64 " block bytes read", devc->num_block_read, devc->num_block_bytes); } devc->num_channel_bytes += len; if (devc->num_channel_bytes < expected_data_bytes) /* Don't have the full data for this channel yet, re-run. */ return TRUE; /* End of data for this channel. */ if (devc->model->series->protocol == PROTOCOL_V3) { /* Signal end of data download to scope */ if (devc->data_source != DATA_SOURCE_LIVE) /* * This causes a query error, without it switching * to the next channel causes an error. Fun with * firmware... */ rigol_ds_config_set(sdi, ":WAV:END"); } if (devc->channel_entry->next) { /* We got the frame for this channel, now get the next channel. */ devc->channel_entry = devc->channel_entry->next; rigol_ds_channel_start(sdi); } else { /* Done with this frame. */ packet.type = SR_DF_FRAME_END; sr_session_send(cb_data, &packet); if (++devc->num_frames == devc->limit_frames) { /* Last frame, stop capture. */ sdi->driver->dev_acquisition_stop(sdi, cb_data); } else { /* Get the next frame, starting with the first channel. */ devc->channel_entry = devc->enabled_channels; rigol_ds_capture_start(sdi); /* Start of next frame. */ packet.type = SR_DF_FRAME_BEGIN; sr_session_send(cb_data, &packet); } } return TRUE; }
/* Start reading data from the current channel */ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_channel *ch; if (!(devc = sdi->priv)) return SR_ERR; ch = devc->channel_entry->data; sr_dbg("Starting reading data from channel %d", ch->index + 1); switch (devc->model->series->protocol) { case PROTOCOL_V1: case PROTOCOL_V2: if (ch->type == SR_CHANNEL_LOGIC) { if (sr_scpi_send(sdi->conn, ":WAV:DATA? DIG") != SR_OK) return SR_ERR; } else { if (sr_scpi_send(sdi->conn, ":WAV:DATA? CHAN%d", ch->index + 1) != SR_OK) return SR_ERR; } rigol_ds_set_wait_event(devc, WAIT_NONE); break; case PROTOCOL_V3: if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", ch->index + 1) != SR_OK) return SR_ERR; if (devc->data_source != DATA_SOURCE_LIVE) { if (rigol_ds_config_set(sdi, ":WAV:RES") != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":WAV:BEG") != SR_OK) return SR_ERR; } break; case PROTOCOL_V4: if (ch->type == SR_CHANNEL_ANALOG) { if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", ch->index + 1) != SR_OK) return SR_ERR; } else { if (rigol_ds_config_set(sdi, ":WAV:SOUR D%d", ch->index) != SR_OK) return SR_ERR; } if (rigol_ds_config_set(sdi, devc->data_source == DATA_SOURCE_LIVE ? ":WAV:MODE NORM" :":WAV:MODE RAW") != SR_OK) return SR_ERR; break; } if (devc->model->series->protocol >= PROTOCOL_V3 && ch->type == SR_CHANNEL_ANALOG) { /* Vertical reference. */ if (sr_scpi_get_int(sdi->conn, ":WAV:YREF?", &devc->vert_reference[ch->index]) != SR_OK) return SR_ERR; } rigol_ds_set_wait_event(devc, WAIT_BLOCK); devc->num_channel_bytes = 0; devc->num_header_bytes = 0; devc->num_block_bytes = 0; return SR_OK; }
/* Start capturing a new frameset */ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi) { struct dev_context *devc; gchar *trig_mode; unsigned int num_channels, i, j; if (!(devc = sdi->priv)) return SR_ERR; sr_dbg("Starting data capture for frameset %" PRIu64 " of %" PRIu64, devc->num_frames + 1, devc->limit_frames); switch (devc->model->series->protocol) { case PROTOCOL_V1: rigol_ds_set_wait_event(devc, WAIT_TRIGGER); break; case PROTOCOL_V2: if (devc->data_source == DATA_SOURCE_LIVE) { if (rigol_ds_config_set(sdi, ":WAV:POIN:MODE NORMAL") != SR_OK) return SR_ERR; rigol_ds_set_wait_event(devc, WAIT_TRIGGER); } else { if (rigol_ds_config_set(sdi, ":STOP") != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":WAV:POIN:MODE RAW") != SR_OK) return SR_ERR; if (sr_scpi_get_string(sdi->conn, ":TRIG:MODE?", &trig_mode) != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":TRIG:%s:SWE SING", trig_mode) != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) return SR_ERR; rigol_ds_set_wait_event(devc, WAIT_STOP); } break; case PROTOCOL_V3: case PROTOCOL_V4: if (rigol_ds_config_set(sdi, ":WAV:FORM BYTE") != SR_OK) return SR_ERR; if (devc->data_source == DATA_SOURCE_LIVE) { if (rigol_ds_config_set(sdi, ":WAV:MODE NORM") != SR_OK) return SR_ERR; devc->analog_frame_size = devc->model->series->live_samples; devc->digital_frame_size = devc->model->series->live_samples; rigol_ds_set_wait_event(devc, WAIT_TRIGGER); } else { if (devc->model->series->protocol == PROTOCOL_V3) { if (rigol_ds_config_set(sdi, ":WAV:MODE RAW") != SR_OK) return SR_ERR; } else if (devc->model->series->protocol == PROTOCOL_V4) { num_channels = 0; /* Channels 3 and 4 are multiplexed with D0-7 and D8-15 */ for (i = 0; i < devc->model->analog_channels; i++) { if (devc->analog_channels[i]) { num_channels++; } else if (i >= 2 && devc->model->has_digital) { for (j = 0; j < 8; j++) { if (devc->digital_channels[8 * (i - 2) + j]) { num_channels++; break; } } } } devc->analog_frame_size = devc->digital_frame_size = num_channels == 1 ? devc->model->series->buffer_samples : num_channels == 2 ? devc->model->series->buffer_samples / 2 : devc->model->series->buffer_samples / 4; } if (rigol_ds_config_set(sdi, ":SING") != SR_OK) return SR_ERR; rigol_ds_set_wait_event(devc, WAIT_STOP); } break; } return SR_OK; }
static int dev_acquisition_start(const struct sr_dev_inst *sdi) { struct sr_scpi_dev_inst *scpi; struct dev_context *devc; struct sr_channel *ch; struct sr_datafeed_packet packet; gboolean some_digital; GSList *l; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; scpi = sdi->conn; devc = sdi->priv; devc->num_frames = 0; some_digital = FALSE; for (l = sdi->channels; l; l = l->next) { ch = l->data; sr_dbg("handling channel %s", ch->name); if (ch->type == SR_CHANNEL_ANALOG) { if (ch->enabled) devc->enabled_channels = g_slist_append( devc->enabled_channels, ch); if (ch->enabled != devc->analog_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; devc->analog_channels[ch->index] = ch->enabled; } } else if (ch->type == SR_CHANNEL_LOGIC) { /* Only one list entry for DS1000D series. All channels are retrieved * together when this entry is processed. */ if (ch->enabled && ( devc->model->series->protocol > PROTOCOL_V2 || !some_digital)) devc->enabled_channels = g_slist_append( devc->enabled_channels, ch); if (ch->enabled) { some_digital = TRUE; /* Turn on LA module if currently off. */ if (!devc->la_enabled) { if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:STAT ON" : ":LA:DISP ON") != SR_OK) return SR_ERR; devc->la_enabled = TRUE; } } if (ch->enabled != devc->digital_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:DIG%d:DISP %s" : ":DIG%d:TURN %s", ch->index, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; devc->digital_channels[ch->index] = ch->enabled; } } } if (!devc->enabled_channels) return SR_ERR; /* Turn off LA module if on and no digital channels selected. */ if (devc->la_enabled && !some_digital) if (rigol_ds_config_set(sdi, devc->model->series->protocol >= PROTOCOL_V4 ? ":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK) return SR_ERR; /* Set memory mode. */ if (devc->data_source == DATA_SOURCE_SEGMENTED) { sr_err("Data source 'Segmented' not yet supported"); return SR_ERR; } devc->analog_frame_size = analog_frame_size(sdi); devc->digital_frame_size = digital_frame_size(sdi); switch (devc->model->series->protocol) { case PROTOCOL_V2: if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK) return SR_ERR; break; case PROTOCOL_V3: /* Apparently for the DS2000 the memory * depth can only be set in Running state - * this matches the behaviour of the UI. */ if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d", devc->analog_frame_size) != SR_OK) return SR_ERR; if (rigol_ds_config_set(sdi, ":STOP") != SR_OK) return SR_ERR; break; default: break; } if (devc->data_source == DATA_SOURCE_LIVE) if (rigol_ds_config_set(sdi, ":RUN") != SR_OK) return SR_ERR; sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi); std_session_send_df_header(sdi); devc->channel_entry = devc->enabled_channels; if (rigol_ds_capture_start(sdi) != SR_OK) return SR_ERR; /* Start of first frame. */ packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); return SR_OK; }
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; uint64_t p, q; double t_dbl; unsigned int i, j; int ret; const char *tmp_str; char buffer[16]; devc = sdi->priv; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; /* If a channel group is specified, it must be a valid one. */ if (cg && !g_slist_find(sdi->channel_groups, cg)) { sr_err("Invalid channel group specified."); return SR_ERR; } ret = SR_OK; switch (key) { case SR_CONF_LIMIT_FRAMES: devc->limit_frames = g_variant_get_uint64(data); break; case SR_CONF_TRIGGER_SLOPE: tmp_str = g_variant_get_string(data, NULL); if (!tmp_str || !(tmp_str[0] == 'f' || tmp_str[0] == 'r')) { sr_err("Unknown trigger slope: '%s'.", (tmp_str) ? tmp_str : "NULL"); return SR_ERR_ARG; } g_free(devc->trigger_slope); devc->trigger_slope = g_strdup((tmp_str[0] == 'r') ? "POS" : "NEG"); ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope); break; case SR_CONF_HORIZ_TRIGGERPOS: t_dbl = g_variant_get_double(data); if (t_dbl < 0.0 || t_dbl > 1.0) { sr_err("Invalid horiz. trigger position: %g.", t_dbl); return SR_ERR; } devc->horiz_triggerpos = t_dbl; /* We have the trigger offset as a percentage of the frame, but * need to express this in seconds. */ t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases; g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl); ret = rigol_ds_config_set(sdi, ":TIM:OFFS %s", buffer); break; case SR_CONF_TRIGGER_LEVEL: t_dbl = g_variant_get_double(data); g_ascii_formatd(buffer, sizeof(buffer), "%.3f", t_dbl); ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:LEV %s", buffer); if (ret == SR_OK) devc->trigger_level = t_dbl; break; case SR_CONF_TIMEBASE: g_variant_get(data, "(tt)", &p, &q); for (i = 0; i < devc->num_timebases; i++) { if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) { devc->timebase = (float)p / q; g_ascii_formatd(buffer, sizeof(buffer), "%.9f", devc->timebase); ret = rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer); break; } } if (i == devc->num_timebases) { sr_err("Invalid timebase index: %d.", i); ret = SR_ERR_ARG; } break; case SR_CONF_TRIGGER_SOURCE: tmp_str = g_variant_get_string(data, NULL); for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) { if (!strcmp(trigger_sources[i], tmp_str)) { g_free(devc->trigger_source); devc->trigger_source = g_strdup(trigger_sources[i]); if (!strcmp(devc->trigger_source, "AC Line")) tmp_str = "ACL"; else if (!strcmp(devc->trigger_source, "CH1")) tmp_str = "CHAN1"; else if (!strcmp(devc->trigger_source, "CH2")) tmp_str = "CHAN2"; else if (!strcmp(devc->trigger_source, "CH3")) tmp_str = "CHAN3"; else if (!strcmp(devc->trigger_source, "CH4")) tmp_str = "CHAN4"; else tmp_str = (char *)devc->trigger_source; ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str); break; } } if (i == ARRAY_SIZE(trigger_sources)) { sr_err("Invalid trigger source index: %d.", i); ret = SR_ERR_ARG; } break; case SR_CONF_VDIV: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } g_variant_get(data, "(tt)", &p, &q); for (i = 0; i < devc->model->analog_channels; i++) { if (cg == devc->analog_groups[i]) { for (j = 0; j < ARRAY_SIZE(vdivs); j++) { if (vdivs[j][0] != p || vdivs[j][1] != q) continue; devc->vdiv[i] = (float)p / q; g_ascii_formatd(buffer, sizeof(buffer), "%.3f", devc->vdiv[i]); return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1, buffer); } sr_err("Invalid vdiv index: %d.", j); return SR_ERR_ARG; } } sr_dbg("Didn't set vdiv, unknown channel(group)."); return SR_ERR_NA; case SR_CONF_COUPLING: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } tmp_str = g_variant_get_string(data, NULL); for (i = 0; i < devc->model->analog_channels; i++) { if (cg == devc->analog_groups[i]) { for (j = 0; j < ARRAY_SIZE(coupling); j++) { if (!strcmp(tmp_str, coupling[j])) { g_free(devc->coupling[i]); devc->coupling[i] = g_strdup(coupling[j]); return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1, devc->coupling[i]); } } sr_err("Invalid coupling index: %d.", j); return SR_ERR_ARG; } } sr_dbg("Didn't set coupling, unknown channel(group)."); return SR_ERR_NA; case SR_CONF_PROBE_FACTOR: if (!cg) { sr_err("No channel group specified."); return SR_ERR_CHANNEL_GROUP; } p = g_variant_get_uint64(data); for (i = 0; i < devc->model->analog_channels; i++) { if (cg == devc->analog_groups[i]) { for (j = 0; j < ARRAY_SIZE(probe_factor); j++) { if (p == probe_factor[j]) { devc->attenuation[i] = p; ret = rigol_ds_config_set(sdi, ":CHAN%d:PROB %"PRIu64, i + 1, p); if (ret == SR_OK) rigol_ds_get_dev_cfg_vertical(sdi); return ret; } } sr_err("Invalid probe factor: %"PRIu64".", p); return SR_ERR_ARG; } } sr_dbg("Didn't set probe factor, unknown channel(group)."); return SR_ERR_NA; case SR_CONF_DATA_SOURCE: tmp_str = g_variant_get_string(data, NULL); if (!strcmp(tmp_str, "Live")) devc->data_source = DATA_SOURCE_LIVE; else if (devc->model->series->protocol >= PROTOCOL_V2 && !strcmp(tmp_str, "Memory")) devc->data_source = DATA_SOURCE_MEMORY; else if (devc->model->series->protocol >= PROTOCOL_V3 && !strcmp(tmp_str, "Segmented")) devc->data_source = DATA_SOURCE_SEGMENTED; else { sr_err("Unknown data source: '%s'.", tmp_str); return SR_ERR; } break; default: return SR_ERR_NA; } return ret; }