Exemplo n.º 1
0
/**
 * Write data of a certain length to the LA8's FTDI device.
 *
 * @param devc The struct containing private per-device-instance data. Must not
 *            be NULL. devc->ftdic must not be NULL either.
 * @param buf The buffer containing the data to write. Must not be NULL.
 * @param size The number of bytes to write. Must be >= 0.
 * @return The number of bytes written, or a negative value upon errors.
 */
SR_PRIV int la8_write(struct dev_context *devc, uint8_t *buf, int size)
{
	int bytes_written;

	/* Note: Caller checked that devc and devc->ftdic != NULL. */

	if (!buf) {
		sr_err("%s: buf was NULL.", __func__);
		return SR_ERR_ARG;
	}

	if (size < 0) {
		sr_err("%s: size was < 0.", __func__);
		return SR_ERR_ARG;
	}

	bytes_written = ftdi_write_data(devc->ftdic, buf, size);

	if (bytes_written < 0) {
		sr_err("%s: ftdi_write_data: (%d) %s.", __func__,
		       bytes_written, ftdi_get_error_string(devc->ftdic));
		(void) la8_close_usb_reset_sequencer(devc); /* Ignore errors. */
	} else if (bytes_written != size) {
		sr_err("%s: bytes to write: %d, bytes written: %d.",
		       __func__, size, bytes_written);
		(void) la8_close_usb_reset_sequencer(devc); /* Ignore errors. */
	}

	return bytes_written;
}
Exemplo n.º 2
0
static int dev_open(struct sr_dev_inst *sdi)
{
	struct dev_context *devc;
	int ret;

	if (!(devc = sdi->priv)) {
		sr_err("%s: sdi->priv was NULL.", __func__);
		return SR_ERR_BUG;
	}

	sr_dbg("Opening LA8 device (%04x:%04x).", USB_VENDOR_ID,
	       devc->usb_pid);

	/* Open the device. */
	if ((ret = ftdi_usb_open_desc(devc->ftdic, USB_VENDOR_ID,
			devc->usb_pid, USB_DESCRIPTION, NULL)) < 0) {
		sr_err("%s: ftdi_usb_open_desc: (%d) %s",
		       __func__, ret, ftdi_get_error_string(devc->ftdic));
		(void) la8_close_usb_reset_sequencer(devc); /* Ignore errors. */
		return SR_ERR;
	}
	sr_dbg("Device opened successfully.");

	/* Purge RX/TX buffers in the FTDI chip. */
	if ((ret = ftdi_usb_purge_buffers(devc->ftdic)) < 0) {
		sr_err("%s: ftdi_usb_purge_buffers: (%d) %s",
		       __func__, ret, ftdi_get_error_string(devc->ftdic));
		(void) la8_close_usb_reset_sequencer(devc); /* Ignore errors. */
		goto err_dev_open_close_ftdic;
	}
	sr_dbg("FTDI buffers purged successfully.");

	/* Enable flow control in the FTDI chip. */
	if ((ret = ftdi_setflowctrl(devc->ftdic, SIO_RTS_CTS_HS)) < 0) {
		sr_err("%s: ftdi_setflowcontrol: (%d) %s",
		       __func__, ret, ftdi_get_error_string(devc->ftdic));
		(void) la8_close_usb_reset_sequencer(devc); /* Ignore errors. */
		goto err_dev_open_close_ftdic;
	}
	sr_dbg("FTDI flow control enabled successfully.");

	/* Wait 100ms. */
	g_usleep(100 * 1000);

	sdi->status = SR_ST_ACTIVE;

	return SR_OK;

err_dev_open_close_ftdic:
	(void) la8_close(devc); /* Log, but ignore errors. */
	return SR_ERR;
}
Exemplo n.º 3
0
static int dev_close(struct sr_dev_inst *sdi)
{
	struct dev_context *devc;

	devc = sdi->priv;

	if (sdi->status == SR_ST_ACTIVE) {
		sr_dbg("Status ACTIVE, closing device.");
		(void) la8_close_usb_reset_sequencer(devc); /* Ignore errors. */
	} else {
		sr_spew("Status not ACTIVE, nothing to do.");
	}

	sdi->status = SR_ST_INACTIVE;

	return SR_OK;
}
Exemplo n.º 4
0
/**
 * Reset the ChronoVu LA8.
 *
 * The LA8 must be reset after a failed read/write operation or upon timeouts.
 *
 * @param devc The struct containing private per-device-instance data.
 * @return SR_OK upon success, SR_ERR upon failure.
 */
SR_PRIV int la8_reset(struct dev_context *devc)
{
	uint8_t buf[BS];
	time_t done, now;
	int bytes_read;

	if (!devc) {
		sr_err("%s: devc was NULL.", __func__);
		return SR_ERR_ARG;
	}

	if (!devc->ftdic) {
		sr_err("%s: devc->ftdic was NULL.", __func__);
		return SR_ERR_ARG;
	}

	sr_dbg("Resetting the device.");

	/*
	 * Purge pending read data from the FTDI hardware FIFO until
	 * no more data is left, or a timeout occurs (after 20s).
	 */
	done = 20 + time(NULL);
	do {
		/* TODO: Ignore errors? Check for < 0 at least! */
		bytes_read = la8_read(devc, (uint8_t *)&buf, BS);
		now = time(NULL);
	} while ((done > now) && (bytes_read > 0));

	/* Reset the LA8 sequencer logic and close the USB port. */
	(void) la8_close_usb_reset_sequencer(devc); /* Ignore errors. */

	sr_dbg("Device reset finished.");

	return SR_OK;
}