示例#1
0
/**
 * Process received line. It consists of 20 hex digits + \\r\\n,
 * e.g. '08100400018100400000'.
 */
static void nma_process_line(const struct sr_dev_inst *sdi)
{
	struct dev_context *devc;
	int pos, flags;
	int vt, range;	/* Measurement value type, range in device format */
	int mmode, devstat;	/* Measuring mode, device status */
	float value;	/* Measured value */
	float scale;	/* Scaling factor depending on range and function */
	struct sr_datafeed_analog analog;
	struct sr_datafeed_packet packet;

	devc = sdi->priv;

	devc->buf[LINE_LENGTH] = '\0';

	sr_spew("Received line '%s'.", devc->buf);

	/* Check line. */
	if (strlen((const char *)devc->buf) != LINE_LENGTH) {
		sr_err("line: Invalid status '%s', must be 20 hex digits.",
		       devc->buf);
		devc->buflen = 0;
		return;
	}

	for (pos = 0; pos < LINE_LENGTH; pos++) {
		if (!isxdigit(devc->buf[pos])) {
			sr_err("line: Expected hex digit in '%s' at pos %d!",
				devc->buf, pos);
			devc->buflen = 0;
			return;
		}
	}

	/* Start decoding. */
	value = 0.0;
	scale = 1.0;
	memset(&analog, 0, sizeof(struct sr_datafeed_analog));

	/*
	 * The numbers are hex digits, starting from 0.
	 * 0: Keyboard status, currently not interesting.
	 * 1: Central switch status, currently not interesting.
	 * 2: Type of measured value.
	 */
	vt = xgittoint(devc->buf[2]);
	switch (vt) {
	case 0:
		analog.mq = SR_MQ_VOLTAGE;
		break;
	case 1:
		analog.mq = SR_MQ_CURRENT;	/* 2A */
		break;
	case 2:
		analog.mq = SR_MQ_RESISTANCE;
		break;
	case 3:
		analog.mq = SR_MQ_CAPACITANCE;
		break;
	case 4:
		analog.mq = SR_MQ_TEMPERATURE;
		break;
	case 5:
		analog.mq = SR_MQ_FREQUENCY;
		break;
	case 6:
		analog.mq = SR_MQ_CURRENT;	/* 10A */
		break;
	case 7:
		analog.mq = SR_MQ_GAIN;		/* TODO: Scale factor */
		break;
	case 8:
		analog.mq = SR_MQ_GAIN;		/* Percentage */
		scale /= 100.0;
		break;
	case 9:
		analog.mq = SR_MQ_GAIN;		/* dB */
		scale /= 100.0;
		break;
	default:
		sr_err("Unknown value type: 0x%02x.", vt);
		break;
	}

	/* 3: Measurement range for measured value */
	range = xgittoint(devc->buf[3]);
	switch (vt) {
	case 0: /* V */
		scale *= pow(10.0, range - 5);
		break;
	case 1: /* A */
		scale *= pow(10.0, range - 7);
		break;
	case 2: /* Ω */
		scale *= pow(10.0, range - 2);
		break;
	case 3: /* F */
		scale *= pow(10.0, range - 12);
		break;
	case 4: /* °C */
		scale *= pow(10.0, range - 1);
		break;
	case 5: /* Hz */
		scale *= pow(10.0, range - 2);
		break;
	// No default, other value types have fixed display format.
	}

	/* 5: Sign and 1st digit */
	flags = xgittoint(devc->buf[5]);
	value = (flags & 0x03);
	if (flags & 0x04)
		scale *= -1;

	/* 6-9: 2nd-4th digit */
	for (pos = 6; pos < 10; pos++)
		value = value * 10 + xgittoint(devc->buf[pos]);
	value *= scale;

	/* 10: Display counter */
	mmode = xgittoint(devc->buf[10]);
	switch (mmode) {
	case 0: /* Frequency */
		analog.unit = SR_UNIT_HERTZ;
		break;
	case 1: /* V TRMS, only type 5 */
		analog.unit = SR_UNIT_VOLT;
		analog.mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS);
		break;
	case 2: /* V AC */
		analog.unit = SR_UNIT_VOLT;
		analog.mqflags |= SR_MQFLAG_AC;
		if (devc->type >= 3)
			analog.mqflags |= SR_MQFLAG_RMS;
		break;
	case 3: /* V DC */
		analog.unit = SR_UNIT_VOLT;
		analog.mqflags |= SR_MQFLAG_DC;
		break;
	case 4: /* Ohm */
		analog.unit = SR_UNIT_OHM;
		break;
	case 5: /* Continuity */
		analog.unit = SR_UNIT_BOOLEAN;
		analog.mq = SR_MQ_CONTINUITY;
		/* TODO: Continuity handling is a bit odd in libsigrok. */
		break;
	case 6: /* Degree Celsius */
		analog.unit = SR_UNIT_CELSIUS;
		break;
	case 7: /* Capacity */
		analog.unit = SR_UNIT_FARAD;
		break;
	case 8: /* Current DC */
		analog.unit = SR_UNIT_AMPERE;
		analog.mqflags |= SR_MQFLAG_DC;
		break;
	case 9: /* Current AC */
		analog.unit = SR_UNIT_AMPERE;
		analog.mqflags |= SR_MQFLAG_AC;
		if (devc->type >= 3)
			analog.mqflags |= SR_MQFLAG_RMS;
		break;
	case 0xa: /* Current TRMS, only type 5 */
		analog.unit = SR_UNIT_AMPERE;
		analog.mqflags |= (SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS);
		break;
	case 0xb: /* Diode */
		analog.unit = SR_UNIT_VOLT;
		analog.mqflags |= (SR_MQFLAG_DIODE | SR_MQFLAG_DC);
		break;
	default:
		sr_err("Unknown mmode: 0x%02x.", mmode);
		break;
	}

	/* 11: Device status */
	devstat = xgittoint(devc->buf[11]);

	switch (devstat) {
	case 1: /* Normal measurement */
		break;
	case 2: /* Input loop (limit, reference values) */
		break;
	case 3: /* TRANS/SENS */
		break;
	case 4: /* Error */
		sr_err("Device error. Fuse?"); /* TODO: Really abort? */
		devc->buflen = 0;
		return;	/* Cannot continue. */
	default:
		sr_err("Unknown device status: 0x%02x", devstat);
		break;
	}

	/* 12-19: Flags and display symbols */
	/* 12, 13 */
	flags = (xgittoint(devc->buf[12]) << 8) | xgittoint(devc->buf[13]);
	/* 0x80: PRINT TODO: Stop polling when discovered? */
	/* 0x40: EXTR */
	if (analog.mq == SR_MQ_CONTINUITY) {
		if (flags & 0x20)
			value = 1.0; /* Beep */
		else
			value = 0.0;
	}
	/* 0x10: AVG */
	/* 0x08: Diode */
	if (flags & 0x04) /* REL */
		analog.mqflags |= SR_MQFLAG_RELATIVE;
	/* 0x02: SHIFT	*/
	if (flags & 0x01) /* % */
		analog.unit = SR_UNIT_PERCENTAGE;

	/* 14, 15 */
	flags = (xgittoint(devc->buf[14]) << 8) | xgittoint(devc->buf[15]);
	if (!(flags & 0x80))	/* MAN: Manual range */
		analog.mqflags |= SR_MQFLAG_AUTORANGE;
	if (flags & 0x40) /* LOBATT1: Low battery, measurement still within specs */
		devc->lowbatt = 1;
	/* 0x20: PEAK */
	/* 0x10: COUNT */
	if (flags & 0x08)	/* HOLD */
		analog.mqflags |= SR_MQFLAG_HOLD;
	/* 0x04: LIMIT	*/
	if (flags & 0x02) 	/* MAX */
		analog.mqflags |= SR_MQFLAG_MAX;
	if (flags & 0x01) 	/* MIN */
		analog.mqflags |= SR_MQFLAG_MIN;

	/* 16, 17 */
	flags = (xgittoint(devc->buf[16]) << 8) | xgittoint(devc->buf[17]);
	/* 0xe0: undefined */
	if (flags & 0x10) { /* LOBATT2: Low battery, measurement inaccurate */
		devc->lowbatt = 2;
		sr_warn("Low battery, measurement quality degraded!");
	}
	/* 0x08: SCALED */
	/* 0x04: RATE (=lower resolution, allows higher data rate up to 10/s. */
	/* 0x02: Current clamp */
	if (flags & 0x01) { /* dB */
		/*
		 * TODO: The Norma has an adjustable dB reference value. If
		 * changed from default, this is not correct.
		 */
		if (analog.unit == SR_UNIT_VOLT)
			analog.unit = SR_UNIT_DECIBEL_VOLT;
		else
			analog.unit = SR_UNIT_UNITLESS;
	}

	/* 18, 19 */
	/* flags = (xgittoint(devc->buf[18]) << 8) | xgittoint(devc->buf[19]); */
	/* 0x80: Undefined. */
	/* 0x40: Remote mode, keyboard locked */
	/* 0x38: Undefined. */
	/* 0x04: MIN > MAX */
	/* 0x02: Measured value < Min */
	/* 0x01: Measured value > Max */

	/* 4: Flags. Evaluating this after setting value! */
	flags = xgittoint(devc->buf[4]);
	if (flags & 0x04) /* Invalid value */
	    value = NAN;
	else if (flags & 0x01) /* Overload */
	    value =  INFINITY;
	if (flags & 0x02) { /* Duplicate value, has been sent before. */
	    sr_spew("Duplicate value, dismissing!");
	    devc->buflen = 0;
	    return;
	}

	sr_spew("range=%d/scale=%f/value=%f", range,
		(double)scale, (double)value);

	/* Finish and send packet. */
	analog.channels = sdi->channels;
	analog.num_samples = 1;
	analog.data = &value;

	memset(&packet, 0, sizeof(struct sr_datafeed_packet));
	packet.type = SR_DF_ANALOG;
	packet.payload = &analog;
	sr_session_send(devc->cb_data, &packet);

	/* Finish processing. */
	devc->num_samples++;
	devc->buflen = 0;
}
示例#2
0
文件: api.c 项目: abraxa/libsigrok
static GSList *scan(struct sr_dev_driver *di, GSList *options)
{
	struct drv_context *drvc;
	struct dev_context *devc;
	struct sr_dev_inst *sdi;
	struct sr_usb_dev_inst *usb;
	struct sr_channel *ch;
	struct sr_channel_group *cg;
	struct sr_config *src;
	const struct fx2lafw_profile *prof;
	GSList *l, *devices, *conn_devices;
	gboolean has_firmware;
	struct libusb_device_descriptor des;
	libusb_device **devlist;
	struct libusb_device_handle *hdl;
	int ret, i, j;
	int num_logic_channels = 0, num_analog_channels = 0;
	const char *conn;
	char manufacturer[64], product[64], serial_num[64], connection_id[64];
	char channel_name[16];

	drvc = di->context;

	conn = NULL;
	for (l = options; l; l = l->next) {
		src = l->data;
		switch (src->key) {
		case SR_CONF_CONN:
			conn = g_variant_get_string(src->data, NULL);
			break;
		}
	}
	if (conn)
		conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
	else
		conn_devices = NULL;

	/* Find all fx2lafw compatible devices and upload firmware to them. */
	devices = NULL;
	libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
	for (i = 0; devlist[i]; i++) {
		if (conn) {
			usb = NULL;
			for (l = conn_devices; l; l = l->next) {
				usb = l->data;
				if (usb->bus == libusb_get_bus_number(devlist[i])
					&& usb->address == libusb_get_device_address(devlist[i]))
					break;
			}
			if (!l)
				/* This device matched none of the ones that
				 * matched the conn specification. */
				continue;
		}

		libusb_get_device_descriptor( devlist[i], &des);

		if (!is_plausible(&des))
			continue;

		if ((ret = libusb_open(devlist[i], &hdl)) < 0) {
			sr_warn("Failed to open potential device with "
				"VID:PID %04x:%04x: %s.", des.idVendor,
				des.idProduct, libusb_error_name(ret));
			continue;
		}

		if (des.iManufacturer == 0) {
			manufacturer[0] = '\0';
		} else if ((ret = libusb_get_string_descriptor_ascii(hdl,
				des.iManufacturer, (unsigned char *) manufacturer,
				sizeof(manufacturer))) < 0) {
			sr_warn("Failed to get manufacturer string descriptor: %s.",
				libusb_error_name(ret));
			continue;
		}

		if (des.iProduct == 0) {
			product[0] = '\0';
		} else if ((ret = libusb_get_string_descriptor_ascii(hdl,
				des.iProduct, (unsigned char *) product,
				sizeof(product))) < 0) {
			sr_warn("Failed to get product string descriptor: %s.",
				libusb_error_name(ret));
			continue;
		}

		if (des.iSerialNumber == 0) {
			serial_num[0] = '\0';
		} else if ((ret = libusb_get_string_descriptor_ascii(hdl,
				des.iSerialNumber, (unsigned char *) serial_num,
				sizeof(serial_num))) < 0) {
			sr_warn("Failed to get serial number string descriptor: %s.",
				libusb_error_name(ret));
			continue;
		}

		libusb_close(hdl);

		if (usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)) < 0)
			continue;

		prof = NULL;
		for (j = 0; supported_fx2[j].vid; j++) {
			if (des.idVendor == supported_fx2[j].vid &&
					des.idProduct == supported_fx2[j].pid &&
					(!supported_fx2[j].usb_manufacturer ||
					 !strcmp(manufacturer, supported_fx2[j].usb_manufacturer)) &&
					(!supported_fx2[j].usb_product ||
					 !strcmp(product, supported_fx2[j].usb_product))) {
				prof = &supported_fx2[j];
				break;
			}
		}

		if (!prof)
			continue;

		sdi = g_malloc0(sizeof(struct sr_dev_inst));
		sdi->status = SR_ST_INITIALIZING;
		sdi->vendor = g_strdup(prof->vendor);
		sdi->model = g_strdup(prof->model);
		sdi->version = g_strdup(prof->model_version);
		sdi->serial_num = g_strdup(serial_num);
		sdi->connection_id = g_strdup(connection_id);

		/* Fill in channellist according to this device's profile. */
		num_logic_channels = prof->dev_caps & DEV_CAPS_16BIT ? 16 : 8;
		num_analog_channels = prof->dev_caps & DEV_CAPS_AX_ANALOG ? 1 : 0;

		/* Logic channels, all in one channel group. */
		cg = g_malloc0(sizeof(struct sr_channel_group));
		cg->name = g_strdup("Logic");
		for (j = 0; j < num_logic_channels; j++) {
			sprintf(channel_name, "D%d", j);
			ch = sr_channel_new(sdi, j, SR_CHANNEL_LOGIC,
						TRUE, channel_name);
			cg->channels = g_slist_append(cg->channels, ch);
		}
		sdi->channel_groups = g_slist_append(NULL, cg);

		for (j = 0; j < num_analog_channels; j++) {
			snprintf(channel_name, 16, "A%d", j);
			ch = sr_channel_new(sdi, j + num_logic_channels,
					SR_CHANNEL_ANALOG, TRUE, channel_name);

			/* Every analog channel gets its own channel group. */
			cg = g_malloc0(sizeof(struct sr_channel_group));
			cg->name = g_strdup(channel_name);
			cg->channels = g_slist_append(NULL, ch);
			sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
		}

		devc = fx2lafw_dev_new();
		devc->profile = prof;
		sdi->priv = devc;
		devices = g_slist_append(devices, sdi);

		devc->samplerates = samplerates;
		devc->num_samplerates = ARRAY_SIZE(samplerates);
		has_firmware = usb_match_manuf_prod(devlist[i],
				"sigrok", "fx2lafw");

		if (has_firmware) {
			/* Already has the firmware, so fix the new address. */
			sr_dbg("Found an fx2lafw device.");
			sdi->status = SR_ST_INACTIVE;
			sdi->inst_type = SR_INST_USB;
			sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
					libusb_get_device_address(devlist[i]), NULL);
		} else {
			if (ezusb_upload_firmware(drvc->sr_ctx, devlist[i],
					USB_CONFIGURATION, prof->firmware) == SR_OK) {
				/* Store when this device's FW was updated. */
				devc->fw_updated = g_get_monotonic_time();
			} else {
				sr_err("Firmware upload failed for "
				       "device %d.%d (logical), name %s.",
				       libusb_get_bus_number(devlist[i]),
				       libusb_get_device_address(devlist[i]),
				       prof->firmware);
			}
			sdi->inst_type = SR_INST_USB;
			sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
					0xff, NULL);
		}
	}
	libusb_free_device_list(devlist, 1);
	g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);

	return std_scan_complete(di, devices);
}
示例#3
0
static int loadfile(struct sr_input *in, const char *filename)
{
	struct sr_datafeed_header header;
	struct sr_datafeed_packet packet;
	struct sr_datafeed_logic logic;
	uint8_t buf[PACKET_SIZE], divcount;
	int i, fd, size, num_probes;
	uint64_t samplerate;

	/* TODO: Use glib functions! GIOChannel, g_fopen, etc. */
	if ((fd = open(filename, O_RDONLY)) == -1) {
		sr_warn("la8input: %s: file open failed", __func__);
		return SR_ERR;
	}

	num_probes = g_slist_length(in->vdevice->probes);

	/* Seek to the end of the file, and read the divcount byte. */
	divcount = 0x00; /* TODO: Don't hardcode! */

	/* Convert the divcount value to a samplerate. */
	samplerate = divcount_to_samplerate(divcount);
	if (samplerate == 0xffffffffffffffffULL) {
		close(fd); /* FIXME */
		return SR_ERR;
	}
	sr_dbg("la8input: %s: samplerate is %" PRIu64, __func__, samplerate);

	/* Send header packet to the session bus. */
	sr_dbg("la8input: %s: sending SR_DF_HEADER packet", __func__);
	packet.type = SR_DF_HEADER;
	packet.payload = &header;
	header.feed_version = 1;
	gettimeofday(&header.starttime, NULL);
	header.num_logic_probes = num_probes;
	header.num_analog_probes = 0;
	header.samplerate = samplerate;
	sr_session_bus(in->vdevice, &packet);

	/* TODO: Handle trigger point. */

	/* Send data packets to the session bus. */
	sr_dbg("la8input: %s: sending SR_DF_LOGIC data packets", __func__);
	packet.type = SR_DF_LOGIC;
	packet.payload = &logic;
	logic.unitsize = (num_probes + 7) / 8;
	logic.data = buf;

	/* Send 8MB of total data to the session bus in small chunks. */
	for (i = 0; i < NUM_PACKETS; i++) {
		/* TODO: Handle errors, handle incomplete reads. */
		size = read(fd, buf, PACKET_SIZE);
		logic.length = PACKET_SIZE;
		sr_session_bus(in->vdevice, &packet);
	}
	close(fd); /* FIXME */

	/* Send end packet to the session bus. */
	sr_dbg("la8input: %s: sending SR_DF_END", __func__);
	packet.type = SR_DF_END;
	packet.payload = NULL;
	sr_session_bus(in->vdevice, &packet);

	return SR_OK;
}
示例#4
0
文件: api.c 项目: jfrkuska/sigrok
static GSList *scan(const char *conn, const char *serialcomm, int dmm)
{
	struct sr_dev_inst *sdi;
	struct drv_context *drvc;
	struct dev_context *devc;
	struct sr_probe *probe;
	struct sr_serial_dev_inst *serial;
	GSList *devices;
	int dropped, ret;
	size_t len;
	uint8_t buf[128];

	if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
		return NULL;

	if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
		return NULL;

	sr_info("Probing serial port %s.", conn);

	drvc = dmms[dmm].di->priv;
	devices = NULL;
	serial_flush(serial);

	/* Request a packet if the DMM requires this. */
	if (dmms[dmm].packet_request) {
		if ((ret = dmms[dmm].packet_request(serial)) < 0) {
			sr_err("Failed to request packet: %d.", ret);
			return FALSE;
		}
	}

	/*
	 * There's no way to get an ID from the multimeter. It just sends data
	 * periodically (or upon request), so the best we can do is check if
	 * the packets match the expected format.
	 */

	/* Let's get a bit of data and see if we can find a packet. */
	len = sizeof(buf);
	ret = serial_stream_detect(serial, buf, &len, dmms[dmm].packet_size,
				   dmms[dmm].packet_valid, 1000,
				   dmms[dmm].baudrate);
	if (ret != SR_OK)
		goto scan_cleanup;

	/*
	 * If we dropped more than two packets worth of data, something is
	 * wrong. We shouldn't quit however, since the dropped bytes might be
	 * just zeroes at the beginning of the stream. Those can occur as a
	 * combination of the nonstandard cable that ships with some devices
	 * and the serial port or USB to serial adapter.
	 */
	dropped = len - dmms[dmm].packet_size;
	if (dropped > 2 * dmms[dmm].packet_size)
		sr_warn("Had to drop too much data.");

	sr_info("Found device on port %s.", conn);

	if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, dmms[dmm].vendor,
				    dmms[dmm].device, "")))
		goto scan_cleanup;

	if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
		sr_err("Device context malloc failed.");
		goto scan_cleanup;
	}

	devc->serial = serial;

	sdi->priv = devc;
	sdi->driver = dmms[dmm].di;
	if (!(probe = sr_probe_new(0, SR_PROBE_ANALOG, TRUE, "P1")))
		goto scan_cleanup;
	sdi->probes = g_slist_append(sdi->probes, probe);
	drvc->instances = g_slist_append(drvc->instances, sdi);
	devices = g_slist_append(devices, sdi);

scan_cleanup:
	serial_close(serial);

	return devices;
}
示例#5
0
SR_PRIV int bl_acme_receive_data(int fd, int revents, void *cb_data)
{
	uint32_t cur_time, elapsed_time;
	uint64_t nrexpiration;
	struct sr_datafeed_packet packet, framep;
	struct sr_datafeed_analog_old analog;
	struct sr_dev_inst *sdi;
	struct sr_channel *ch;
	struct channel_priv *chp;
	struct dev_context *devc;
	GSList *chl, chonly;
	unsigned i;

	(void)fd;
	(void)revents;

	sdi = cb_data;
	if (!sdi)
		return TRUE;

	devc = sdi->priv;
	if (!devc)
		return TRUE;

	packet.type = SR_DF_ANALOG_OLD;
	packet.payload = &analog;
	memset(&analog, 0, sizeof(struct sr_datafeed_analog_old));

	if (read(devc->timer_fd, &nrexpiration, sizeof(nrexpiration)) < 0) {
		sr_warn("Failed to read timer information");
		return TRUE;
	}

	/*
	 * We were not able to process the previous timer expiration, we are
	 * overloaded.
	 */
	if (nrexpiration > 1)
		devc->samples_missed += nrexpiration - 1;

	/*
	 * XXX This is a nasty workaround...
	 *
	 * At high sampling rates and maximum channels we are not able to
	 * acquire samples fast enough, even though frontends still think
	 * that samples arrive on time. This causes shifts in frontend
	 * plots.
	 *
	 * To compensate for the delay we check if any clock events were
	 * missed and - if so - don't really read the next value, but send
	 * the same sample as fast as possible. We do it until we are back
	 * on schedule.
	 *
	 * At high sampling rate this doesn't seem to visibly reduce the
	 * accuracy.
	 */
	for (i = 0; i < nrexpiration; i++) {
		framep.type = SR_DF_FRAME_BEGIN;
		sr_session_send(cb_data, &framep);

		/*
		 * Due to different units used in each channel we're sending
		 * samples one-by-one.
		 */
		for (chl = sdi->channels; chl; chl = chl->next) {
			ch = chl->data;
			chp = ch->priv;

			if (!ch->enabled)
				continue;
			chonly.next = NULL;
			chonly.data = ch;
			analog.channels = &chonly;
			analog.num_samples = 1;
			analog.mq = channel_to_mq(chl->data);
			analog.unit = channel_to_unit(ch);

			if (i < 1)
				chp->val = read_sample(ch);

			analog.data = &chp->val;
			sr_session_send(cb_data, &packet);
		}

		framep.type = SR_DF_FRAME_END;
		sr_session_send(cb_data, &framep);
	}

	devc->samples_read++;
	if (devc->limit_samples > 0 &&
	    devc->samples_read >= devc->limit_samples) {
		sr_info("Requested number of samples reached.");
		sdi->driver->dev_acquisition_stop(sdi, cb_data);
		devc->last_sample_fin = g_get_monotonic_time();
		return TRUE;
	} else if (devc->limit_msec > 0) {
		cur_time = g_get_monotonic_time();
		elapsed_time = cur_time - devc->start_time;

		if (elapsed_time >= devc->limit_msec) {
			sr_info("Sampling time limit reached.");
			sdi->driver->dev_acquisition_stop(sdi, cb_data);
			devc->last_sample_fin = g_get_monotonic_time();
			return TRUE;
		}
	}

	devc->last_sample_fin = g_get_monotonic_time();
	return TRUE;
}
示例#6
0
static GSList *scan(struct sr_dev_driver *di, GSList *options)
{
	GSList *usb_devices, *devices, *l;
	struct drv_context *drvc;
	struct sr_dev_inst *sdi;
	struct dev_context *devc;
	struct sr_usb_dev_inst *usb;
	struct device_info dev_info;
	unsigned int i;
	int ret;

	(void)options;

	devices = NULL;
	drvc = di->context;
	drvc->instances = NULL;

	usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, USB_VID_PID);

	if (!usb_devices)
		return NULL;

	for (l = usb_devices; l; l = l->next) {
		usb = l->data;

		if ((ret = sl2_get_device_info(*usb, &dev_info)) < 0) {
			sr_warn("Failed to get device information: %d.", ret);
			sr_usb_dev_inst_free(usb);
			continue;
		}

		devc = g_malloc0(sizeof(struct dev_context));

		if (!(devc->xfer_in = libusb_alloc_transfer(0))) {
			sr_err("Transfer malloc failed.");
			sr_usb_dev_inst_free(usb);
			g_free(devc);
			continue;
		}

		if (!(devc->xfer_out = libusb_alloc_transfer(0))) {
			sr_err("Transfer malloc failed.");
			sr_usb_dev_inst_free(usb);
			libusb_free_transfer(devc->xfer_in);
			g_free(devc);
			continue;
		}

		sdi = g_malloc0(sizeof(struct sr_dev_inst));
		sdi->status = SR_ST_INACTIVE;
		sdi->vendor = g_strdup(VENDOR_NAME);
		sdi->model = g_strdup(MODEL_NAME);
		sdi->version = g_strdup_printf("%u.%u", dev_info.fw_ver_major, dev_info.fw_ver_minor);
		sdi->serial_num = g_strdup_printf("%d", dev_info.serial);
		sdi->priv = devc;
		sdi->driver = di;
		sdi->inst_type = SR_INST_USB;
		sdi->conn = usb;

		for (i = 0; i < ARRAY_SIZE(channel_names); i++)
			devc->channels[i] = sr_channel_new(sdi, i,
				SR_CHANNEL_LOGIC, TRUE, channel_names[i]);

		devc->state = STATE_IDLE;
		devc->next_state = STATE_IDLE;

		/* Set default samplerate. */
		sl2_set_samplerate(sdi, DEFAULT_SAMPLERATE);

		/* Set default capture ratio. */
		devc->capture_ratio = 0;

		/* Set default after trigger delay. */
		devc->after_trigger_delay = 0;

		memset(devc->xfer_buf_in, 0, LIBUSB_CONTROL_SETUP_SIZE +
			PACKET_LENGTH);
		memset(devc->xfer_buf_out, 0, LIBUSB_CONTROL_SETUP_SIZE +
			PACKET_LENGTH);

		libusb_fill_control_setup(devc->xfer_buf_in,
			USB_REQUEST_TYPE_IN, USB_HID_GET_REPORT,
			USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE,
			PACKET_LENGTH);
		libusb_fill_control_setup(devc->xfer_buf_out,
			USB_REQUEST_TYPE_OUT, USB_HID_SET_REPORT,
			USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE,
			PACKET_LENGTH);

		devc->xfer_data_in = devc->xfer_buf_in +
			LIBUSB_CONTROL_SETUP_SIZE;
		devc->xfer_data_out = devc->xfer_buf_out +
			LIBUSB_CONTROL_SETUP_SIZE;

		drvc->instances = g_slist_append(drvc->instances, sdi);
		devices = g_slist_append(devices, sdi);
	}

	g_slist_free(usb_devices);

	return devices;
}
示例#7
0
文件: api.c 项目: BayLibre/libsigrok
static GSList *scan(struct sr_dev_driver *di, GSList *options)
{
	struct dmm_info *dmm;
	struct sr_config *src;
	GSList *l, *devices;
	const char *conn, *serialcomm;
	struct sr_dev_inst *sdi;
	struct dev_context *devc;
	struct sr_serial_dev_inst *serial;
	int dropped, ret;
	size_t len;
	uint8_t buf[128];

	dmm = (struct dmm_info *)di;

	conn = serialcomm = NULL;
	for (l = options; l; l = l->next) {
		src = l->data;
		switch (src->key) {
		case SR_CONF_CONN:
			conn = g_variant_get_string(src->data, NULL);
			break;
		case SR_CONF_SERIALCOMM:
			serialcomm = g_variant_get_string(src->data, NULL);
			break;
		}
	}
	if (!conn)
		return NULL;

	if (!serialcomm)
		serialcomm = dmm->conn;

	serial = sr_serial_dev_inst_new(conn, serialcomm);

	if (serial_open(serial, SERIAL_RDWR) != SR_OK)
		return NULL;

	sr_info("Probing serial port %s.", conn);

	devices = NULL;
	serial_flush(serial);

	/* Request a packet if the DMM requires this. */
	if (dmm->packet_request) {
		if ((ret = dmm->packet_request(serial)) < 0) {
			sr_err("Failed to request packet: %d.", ret);
			return FALSE;
		}
	}

	/*
	 * There's no way to get an ID from the multimeter. It just sends data
	 * periodically (or upon request), so the best we can do is check if
	 * the packets match the expected format.
	 */

	/* Let's get a bit of data and see if we can find a packet. */
	len = sizeof(buf);
	ret = serial_stream_detect(serial, buf, &len, dmm->packet_size,
				   dmm->packet_valid, 3000,
				   dmm->baudrate);
	if (ret != SR_OK)
		goto scan_cleanup;

	/*
	 * If we dropped more than two packets worth of data, something is
	 * wrong. We shouldn't quit however, since the dropped bytes might be
	 * just zeroes at the beginning of the stream. Those can occur as a
	 * combination of the nonstandard cable that ships with some devices
	 * and the serial port or USB to serial adapter.
	 */
	dropped = len - dmm->packet_size;
	if (dropped > 2 * dmm->packet_size)
		sr_warn("Had to drop too much data.");

	sr_info("Found device on port %s.", conn);

	sdi = g_malloc0(sizeof(struct sr_dev_inst));
	sdi->status = SR_ST_INACTIVE;
	sdi->vendor = g_strdup(dmm->vendor);
	sdi->model = g_strdup(dmm->device);
	devc = g_malloc0(sizeof(struct dev_context));
	sr_sw_limits_init(&devc->limits);
	sdi->inst_type = SR_INST_SERIAL;
	sdi->conn = serial;
	sdi->priv = devc;
	sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "P1");
	devices = g_slist_append(devices, sdi);

scan_cleanup:
	serial_close(serial);

	return std_scan_complete(di, devices);
}
示例#8
0
文件: api.c 项目: anatol/libsigrok
static GSList *scan(struct sr_dev_driver *di, GSList *options)
{
	struct drv_context *drvc;
	struct dev_context *devc;
	struct sr_dev_inst *sdi;
	struct sr_usb_dev_inst *usb;
	struct sr_config *src;
	GSList *l, *devices, *conn_devices;
	struct libusb_device_descriptor des;
	libusb_device **devlist;
	int ret;
	unsigned int i, j;
	const char *conn;
	char connection_id[64];

	drvc = di->priv;

	conn = NULL;
	for (l = options; l; l = l->next) {
		src = l->data;
		switch (src->key) {
		case SR_CONF_CONN:
			conn = g_variant_get_string(src->data, NULL);
			break;
		}
	}
	if (conn)
		conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
	else
		conn_devices = NULL;

	/* Find all Logic16 devices and upload firmware to them. */
	devices = NULL;
	libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
	for (i = 0; devlist[i]; i++) {
		if (conn) {
			usb = NULL;
			for (l = conn_devices; l; l = l->next) {
				usb = l->data;
				if (usb->bus == libusb_get_bus_number(devlist[i])
				    && usb->address == libusb_get_device_address(devlist[i]))
					break;
			}
			if (!l)
				/* This device matched none of the ones that
				 * matched the conn specification. */
				continue;
		}

		if ((ret = libusb_get_device_descriptor(devlist[i], &des)) != 0) {
			sr_warn("Failed to get device descriptor: %s.",
				libusb_error_name(ret));
			continue;
		}

		usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));

		if (des.idVendor != LOGIC16_VID || des.idProduct != LOGIC16_PID)
			continue;

		sdi = g_malloc0(sizeof(struct sr_dev_inst));
		sdi->status = SR_ST_INITIALIZING;
		sdi->vendor = g_strdup("Saleae");
		sdi->model = g_strdup("Logic16");
		sdi->driver = di;
		sdi->connection_id = g_strdup(connection_id);

		for (j = 0; j < ARRAY_SIZE(channel_names); j++)
			sr_channel_new(sdi, j, SR_CHANNEL_LOGIC, TRUE,
					    channel_names[j]);

		devc = g_malloc0(sizeof(struct dev_context));
		devc->selected_voltage_range = VOLTAGE_RANGE_18_33_V;
		sdi->priv = devc;
		drvc->instances = g_slist_append(drvc->instances, sdi);
		devices = g_slist_append(devices, sdi);

		if (check_conf_profile(devlist[i])) {
			/* Already has the firmware, so fix the new address. */
			sr_dbg("Found a Logic16 device.");
			sdi->status = SR_ST_INACTIVE;
			sdi->inst_type = SR_INST_USB;
			sdi->conn = sr_usb_dev_inst_new(
				libusb_get_bus_number(devlist[i]),
				libusb_get_device_address(devlist[i]), NULL);
		} else {
			if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION,
						  FX2_FIRMWARE) == SR_OK)
				/* Store when this device's FW was updated. */
				devc->fw_updated = g_get_monotonic_time();
			else
				sr_err("Firmware upload failed.");
			sdi->inst_type = SR_INST_USB;
			sdi->conn = sr_usb_dev_inst_new(
				libusb_get_bus_number(devlist[i]), 0xff, NULL);
		}
	}
	libusb_free_device_list(devlist, 1);
	g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);

	return devices;
}
示例#9
0
文件: in_vcd.c 项目: ticpu/DSView
/* Parse the data section of VCD */
static void parse_contents(FILE *file, const struct sr_dev_inst *sdi, struct context *ctx)
{
    GString *token = g_string_sized_new(32);

    uint64_t prev_timestamp = 0;
    uint64_t prev_values = 0;

    /* Read one space-delimited token at a time. */
    while (read_until(file, NULL, 'N') && read_until(file, token, 'W'))
    {
        if (token->str[0] == '#' && g_ascii_isdigit(token->str[1]))
        {
            /* Numeric value beginning with # is a new timestamp value */
            uint64_t timestamp;
            timestamp = strtoull(token->str + 1, NULL, 10);

            if (ctx->downsample > 1)
                timestamp /= ctx->downsample;

            /* Skip < 0 => skip until first timestamp.
             * Skip = 0 => don't skip
             * Skip > 0 => skip until timestamp >= skip.
             */
            if (ctx->skip < 0)
            {
                ctx->skip = timestamp;
                prev_timestamp = timestamp;
            }
            else if (ctx->skip > 0 && timestamp < (uint64_t)ctx->skip)
            {
                prev_timestamp = ctx->skip;
            }
            else if (timestamp == prev_timestamp)
            {
                /* Ignore repeated timestamps (e.g. sigrok outputs these) */
            }
            else
            {
                if (ctx->compress != 0 && timestamp - prev_timestamp > ctx->compress)
                {
                    /* Compress long idle periods */
                    prev_timestamp = timestamp - ctx->compress;
                }

                sr_dbg("New timestamp: %" PRIu64, timestamp);

                /* Generate samples from prev_timestamp up to timestamp - 1. */
                send_samples(sdi, prev_values, timestamp - prev_timestamp);
                prev_timestamp = timestamp;
            }
        }
        else if (token->str[0] == '$' && token->len > 1)
        {
            /* This is probably a $dumpvars, $comment or similar.
             * $dump* contain useful data, but other tags will be skipped until $end. */
            if (g_strcmp0(token->str, "$dumpvars") == 0 ||
                    g_strcmp0(token->str, "$dumpon") == 0 ||
                    g_strcmp0(token->str, "$dumpoff") == 0 ||
                    g_strcmp0(token->str, "$end") == 0)
            {
                /* Ignore, parse contents as normally. */
            }
            else
            {
                /* Skip until $end */
                read_until(file, NULL, '$');
            }
        }
        else if (strchr("bBrR", token->str[0]) != NULL)
        {
            /* A vector value. Skip it and also the following identifier. */
            read_until(file, NULL, 'N');
            read_until(file, NULL, 'W');
        }
        else if (strchr("01xXzZ", token->str[0]) != NULL)
        {
            /* A new 1-bit sample value */
            int i, bit;
            GSList *l;
            struct probe *probe;

            bit = (token->str[0] == '1');

            g_string_erase(token, 0, 1);
            if (token->len == 0)
            {
                /* There was a space between value and identifier.
                 * Read in the rest.
                 */
                read_until(file, NULL, 'N');
                read_until(file, token, 'W');
            }

            for (i = 0, l = ctx->probes; i < ctx->probecount && l; i++, l = l->next)
            {
                probe = l->data;

                if (g_strcmp0(token->str, probe->identifier) == 0)
                {
                    sr_dbg("Probe %d new value %d.", i, bit);

                    /* Found our probe */
                    if (bit)
                        prev_values |= (1 << i);
                    else
                        prev_values &= ~(1 << i);

                    break;
                }
            }

            if (i == ctx->probecount)
            {
                sr_dbg("Did not find probe for identifier '%s'.", token->str);
            }
        }
        else
        {
            sr_warn("Skipping unknown token '%s'.", token->str);
        }

        g_string_truncate(token, 0);
    }

    g_string_free(token, TRUE);
}
示例#10
0
文件: in_vcd.c 项目: ticpu/DSView
/* Parse VCD header to get values for context structure.
 * The context structure should be zeroed before calling this.
 */
static gboolean parse_header(FILE *file, struct context *ctx)
{
    uint64_t p, q;
    gchar *name = NULL, *contents = NULL;
    gboolean status = FALSE;
    struct probe *probe;

    while (parse_section(file, &name, &contents))
    {
        sr_dbg("Section '%s', contents '%s'.", name, contents);

        if (g_strcmp0(name, "enddefinitions") == 0)
        {
            status = TRUE;
            break;
        }
        else if (g_strcmp0(name, "timescale") == 0)
        {
            /* The standard allows for values 1, 10 or 100
             * and units s, ms, us, ns, ps and fs. */
            if (sr_parse_period(contents, &p, &q) == SR_OK)
            {
                ctx->samplerate = q / p;
                if (q % p != 0)
                {
                    /* Does not happen unless time value is non-standard */
                    sr_warn("Inexact rounding of samplerate, %" PRIu64 " / %" PRIu64 " to %" PRIu64 " Hz.",
                            q, p, ctx->samplerate);
                }

                sr_dbg("Samplerate: %" PRIu64, ctx->samplerate);
            }
            else
            {
                sr_err("Parsing timescale failed.");
            }
        }
        else if (g_strcmp0(name, "var") == 0)
        {
            /* Format: $var type size identifier reference $end */
            gchar **parts = g_strsplit_set(contents, " \r\n\t", 0);
            remove_empty_parts(parts);

            if (g_strv_length(parts) != 4)
            {
                sr_warn("$var section should have 4 items");
            }
            else if (g_strcmp0(parts[0], "reg") != 0 && g_strcmp0(parts[0], "wire") != 0)
            {
                sr_info("Unsupported signal type: '%s'", parts[0]);
            }
            else if (strtol(parts[1], NULL, 10) != 1)
            {
                sr_info("Unsupported signal size: '%s'", parts[1]);
            }
            else if (ctx->probecount >= ctx->maxprobes)
            {
                sr_warn("Skipping '%s' because only %d probes requested.", parts[3], ctx->maxprobes);
            }
            else
            {
                sr_info("Probe %d is '%s' identified by '%s'.", ctx->probecount, parts[3], parts[2]);
                probe = g_malloc(sizeof(struct probe));
                probe->identifier = g_strdup(parts[2]);
                probe->name = g_strdup(parts[3]);
                ctx->probes = g_slist_append(ctx->probes, probe);
                ctx->probecount++;
            }

            g_strfreev(parts);
        }

        g_free(name);
        name = NULL;
        g_free(contents);
        contents = NULL;
    }

    g_free(name);
    g_free(contents);

    return status;
}
示例#11
0
文件: api.c 项目: DeeJay/libsigrok
static GSList *scan(GSList *options)
{
	struct drv_context *drvc;
	struct dev_context *devc;
	struct sr_dev_inst *sdi;
	struct sr_usb_dev_inst *usb;
	struct sr_channel *ch;
	struct sr_config *src;
	const struct fx2lafw_profile *prof;
	GSList *l, *devices, *conn_devices;
	struct libusb_device_descriptor des;
	libusb_device **devlist;
	struct libusb_device_handle *hdl;
	int devcnt, num_logic_channels, ret, i, j;
	const char *conn;
	char manufacturer[64], product[64];

	drvc = di->priv;

	conn = NULL;
	for (l = options; l; l = l->next) {
		src = l->data;
		switch (src->key) {
		case SR_CONF_CONN:
			conn = g_variant_get_string(src->data, NULL);
			break;
		}
	}
	if (conn)
		conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
	else
		conn_devices = NULL;

	/* Find all fx2lafw compatible devices and upload firmware to them. */
	devices = NULL;
	libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
	for (i = 0; devlist[i]; i++) {
		if (conn) {
			usb = NULL;
			for (l = conn_devices; l; l = l->next) {
				usb = l->data;
				if (usb->bus == libusb_get_bus_number(devlist[i])
					&& usb->address == libusb_get_device_address(devlist[i]))
					break;
			}
			if (!l)
				/* This device matched none of the ones that
				 * matched the conn specification. */
				continue;
		}

		if ((ret = libusb_get_device_descriptor( devlist[i], &des)) != 0) {
			sr_warn("Failed to get device descriptor: %s.",
				libusb_error_name(ret));
			continue;
		}

		if ((ret = libusb_open(devlist[i], &hdl)) < 0)
			continue;

		if (des.iManufacturer == 0) {
			manufacturer[0] = '\0';
		} else if ((ret = libusb_get_string_descriptor_ascii(hdl,
				des.iManufacturer, (unsigned char *) manufacturer,
				sizeof(manufacturer))) < 0) {
			sr_warn("Failed to get manufacturer string descriptor: %s.",
				libusb_error_name(ret));
			continue;
		}

		if (des.iProduct == 0) {
			product[0] = '\0';
		} else if ((ret = libusb_get_string_descriptor_ascii(hdl,
				des.iProduct, (unsigned char *) product,
				sizeof(product))) < 0) {
			sr_warn("Failed to get product string descriptor: %s.",
				libusb_error_name(ret));
			continue;
		}

		libusb_close(hdl);

		prof = NULL;
		for (j = 0; supported_fx2[j].vid; j++) {
			if (des.idVendor == supported_fx2[j].vid &&
					des.idProduct == supported_fx2[j].pid &&
					(!supported_fx2[j].usb_manufacturer ||
					 !strcmp(manufacturer, supported_fx2[j].usb_manufacturer)) &&
					(!supported_fx2[j].usb_manufacturer ||
					 !strcmp(product, supported_fx2[j].usb_product))) {
				prof = &supported_fx2[j];
				break;
			}
		}

		/* Skip if the device was not found. */
		if (!prof)
			continue;

		devcnt = g_slist_length(drvc->instances);
		sdi = sr_dev_inst_new(devcnt, SR_ST_INITIALIZING,
			prof->vendor, prof->model, prof->model_version);
		if (!sdi)
			return NULL;
		sdi->driver = di;

		/* Fill in channellist according to this device's profile. */
		num_logic_channels = prof->dev_caps & DEV_CAPS_16BIT ? 16 : 8;
		for (j = 0; j < num_logic_channels; j++) {
			if (!(ch = sr_channel_new(j, SR_CHANNEL_LOGIC, TRUE,
					channel_names[j])))
				return NULL;
			sdi->channels = g_slist_append(sdi->channels, ch);
		}

		devc = fx2lafw_dev_new();
		devc->profile = prof;
		sdi->priv = devc;
		drvc->instances = g_slist_append(drvc->instances, sdi);
		devices = g_slist_append(devices, sdi);

		if (fx2lafw_check_conf_profile(devlist[i])) {
			/* Already has the firmware, so fix the new address. */
			sr_dbg("Found an fx2lafw device.");
			sdi->status = SR_ST_INACTIVE;
			sdi->inst_type = SR_INST_USB;
			sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
					libusb_get_device_address(devlist[i]), NULL);
		} else {
			if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION,
				prof->firmware) == SR_OK)
				/* Store when this device's FW was updated. */
				devc->fw_updated = g_get_monotonic_time();
			else
				sr_err("Firmware upload failed for "
				       "device %d.", devcnt);
			sdi->inst_type = SR_INST_USB;
			sdi->conn = sr_usb_dev_inst_new(libusb_get_bus_number(devlist[i]),
					0xff, NULL);
		}
	}
	libusb_free_device_list(devlist, 1);
	g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);

	return devices;
}
示例#12
0
/**
 * Attempts to query sample data from the oscilloscope in order to send it
 * to the session bus for further processing.
 *
 * @param fd The file descriptor used as the event source.
 * @param revents The received events.
 * @param cb_data Callback data, in this case our device instance.
 *
 * @return TRUE in case of success or a recoverable error,
 *         FALSE when a fatal error was encountered.
 */
SR_PRIV int dlm_data_receive(int fd, int revents, void *cb_data)
{
	struct sr_dev_inst *sdi;
	struct scope_state *model_state;
	struct dev_context *devc;
	struct sr_channel *ch;
	struct sr_datafeed_packet packet;
	int chunk_len, num_bytes;
	static GArray *data = NULL;

	(void)fd;
	(void)revents;

	if (!(sdi = cb_data))
		return FALSE;

	if (!(devc = sdi->priv))
		return FALSE;

	if (!(model_state = (struct scope_state*)devc->model_state))
		return FALSE;

	/* Are we waiting for a response from the device? */
	if (!devc->data_pending)
		return TRUE;

	/* Check if a new query response is coming our way. */
	if (!data) {
		if (sr_scpi_read_begin(sdi->conn) == SR_OK)
			/* The 16 here accounts for the header and EOL. */
			data = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t),
					16 + model_state->samples_per_frame);
		else
			return TRUE;
	}

	/* Store incoming data. */
	chunk_len = sr_scpi_read_data(sdi->conn, devc->receive_buffer,
			RECEIVE_BUFFER_SIZE);
	if (chunk_len < 0) {
		sr_err("Error while reading data: %d", chunk_len);
		goto fail;
	}
	g_array_append_vals(data, devc->receive_buffer, chunk_len);

	/* Read the entire query response before processing. */
	if (!sr_scpi_read_complete(sdi->conn))
		return TRUE;

	/* We finished reading and are no longer waiting for data. */
	devc->data_pending = FALSE;

	/* Signal the beginning of a new frame if this is the first channel. */
	if (devc->current_channel == devc->enabled_channels) {
		packet.type = SR_DF_FRAME_BEGIN;
		sr_session_send(sdi, &packet);
	}

	if (dlm_block_data_header_process(data, &num_bytes) != SR_OK) {
		sr_err("Encountered malformed block data header.");
		goto fail;
	}

	if (num_bytes == 0) {
		sr_warn("Zero-length waveform data packet received. " \
				"Live mode not supported yet, stopping " \
				"acquisition and retrying.");
		/* Don't care about return value here. */
		dlm_acquisition_stop(sdi->conn);
		g_array_free(data, TRUE);
		dlm_channel_data_request(sdi);
		return TRUE;
	}

	ch = devc->current_channel->data;
	switch (ch->type) {
	case SR_CHANNEL_ANALOG:
		if (dlm_analog_samples_send(data,
				&model_state->analog_states[ch->index],
				sdi) != SR_OK)
			goto fail;
		break;
	case SR_CHANNEL_LOGIC:
		if (dlm_digital_samples_send(data, sdi) != SR_OK)
			goto fail;
		break;
	default:
		sr_err("Invalid channel type encountered.");
		break;
	}

	g_array_free(data, TRUE);
	data = NULL;

	/*
	 * Signal the end of this frame if this was the last enabled channel
	 * and set the next enabled channel. Then, request its data.
	 */
	if (!devc->current_channel->next) {
		packet.type = SR_DF_FRAME_END;
		sr_session_send(sdi, &packet);
		devc->current_channel = devc->enabled_channels;

		/*
		 * As of now we only support importing the current acquisition
		 * data so we're going to stop at this point.
		 */
		sdi->driver->dev_acquisition_stop(sdi, cb_data);
		return TRUE;
	} else
		devc->current_channel = devc->current_channel->next;

	if (dlm_channel_data_request(sdi) != SR_OK) {
		sr_err("Failed to request acquisition data.");
		goto fail;
	}

	return TRUE;

fail:
	if (data) {
		g_array_free(data, TRUE);
		data = NULL;
	}

	return FALSE;
}