Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
/* 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;
}
Ejemplo n.º 5
0
/* 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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}