Initial driver for IKALOGIC Scanalogic-2

This commit is contained in:
Marc Schink 2013-06-10 10:10:13 +02:00 committed by Uwe Hermann
parent 16e76baec9
commit e52e712d05
3 changed files with 1370 additions and 56 deletions

View File

@ -19,28 +19,176 @@
#include "protocol.h"
static const int hwcaps[] = {
SR_CONF_LOGIC_ANALYZER,
SR_CONF_SAMPLERATE,
SR_CONF_LIMIT_SAMPLES,
SR_CONF_TRIGGER_TYPE,
SR_CONF_CAPTURE_RATIO
};
SR_PRIV const uint64_t ikalogic_scanalogic2_samplerates[NUM_SAMPLERATES] = {
SR_KHZ(1.25),
SR_KHZ(10),
SR_KHZ(50),
SR_KHZ(100),
SR_KHZ(250),
SR_KHZ(500),
SR_MHZ(1),
SR_MHZ(2.5),
SR_MHZ(5),
SR_MHZ(10),
SR_MHZ(20)
};
static const char *probe_names[NUM_PROBES + 1] = {
"0", "1", "2", "3",
NULL
};
SR_PRIV struct sr_dev_driver ikalogic_scanalogic2_driver_info;
static struct sr_dev_driver *di = &ikalogic_scanalogic2_driver_info;
static int init(struct sr_context *sr_ctx)
{
return std_hw_init(sr_ctx, di, LOG_PREFIX);
return std_init(sr_ctx, di, LOG_PREFIX);
}
static GSList *scan(GSList *options)
{
GSList *usb_devices, *devices, *l;
struct drv_context *drvc;
GSList *devices;
struct sr_dev_inst *sdi;
struct sr_probe *probe;
struct dev_context *devc;
struct sr_usb_dev_inst *usb;
struct device_info dev_info;
int ret, device_index, i;
char *fw_ver_str;
(void)options;
devices = NULL;
drvc = di->priv;
drvc->instances = NULL;
device_index = 0;
/* TODO: scan for devices, either based on a SR_CONF_CONN option
* or on a USB scan. */
usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, USB_VID_PID);
if (usb_devices == NULL)
return NULL;
for (l = usb_devices; l; l = l->next)
{
usb = l->data;
ret = ikalogic_scanalogic2_get_device_info(*usb, &dev_info);
if (ret != SR_OK) {
sr_warn("Failed to get device information.\n");
sr_usb_dev_inst_free(usb);
continue;
}
devc = g_try_malloc(sizeof(struct dev_context));
if (!devc) {
sr_err("Device instance malloc failed.");
sr_usb_dev_inst_free(usb);
continue;
}
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;
}
fw_ver_str = g_strdup_printf("%u.%u", dev_info.fw_ver_major,
dev_info.fw_ver_minor);
if (!fw_ver_str) {
sr_err("Firmware string malloc failed.");
sr_usb_dev_inst_free(usb);
libusb_free_transfer(devc->xfer_in);
libusb_free_transfer(devc->xfer_out);
g_free(devc);
continue;
}
sdi = sr_dev_inst_new(device_index, SR_ST_INACTIVE, VENDOR_NAME,
MODEL_NAME, fw_ver_str);
g_free(fw_ver_str);
if (!sdi) {
sr_err("sr_dev_inst_new failed.");
sr_usb_dev_inst_free(usb);
libusb_free_transfer(devc->xfer_in);
libusb_free_transfer(devc->xfer_out);
g_free(devc);
continue;
}
sdi->priv = devc;
sdi->driver = di;
sdi->inst_type = SR_INST_USB;
sdi->conn = usb;
for (i = 0; probe_names[i]; i++) {
probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
probe_names[i]);
sdi->probes = g_slist_append(sdi->probes, probe);
devc->probes[i] = probe;
}
devc->state = STATE_IDLE;
devc->next_state = STATE_IDLE;
/* Set default samplerate. */
ikalogic_scanalogic2_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_SET_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);
device_index++;
}
g_slist_free(usb_devices);
return devices;
}
@ -54,16 +202,94 @@ static GSList *dev_list(void)
return drvc->instances;
}
static void clear_dev_context(void *priv)
{
struct dev_context *devc = priv;
sr_dbg("Device context cleard.");
libusb_free_transfer(devc->xfer_in);
libusb_free_transfer(devc->xfer_out);
g_free(devc);
}
static int dev_clear(void)
{
return std_dev_clear(di, NULL);
return std_dev_clear(di, &clear_dev_context);
}
static int dev_open(struct sr_dev_inst *sdi)
{
(void)sdi;
struct drv_context *drvc;
struct dev_context *devc;
struct sr_usb_dev_inst *usb;
uint8_t buffer[PACKET_LENGTH];
int ret;
/* TODO: get handle from sdi->conn and open it. */
if (!(drvc = di->priv)) {
sr_err("Driver was not initialized.");
return SR_ERR;
}
usb = sdi->conn;
devc = sdi->priv;
if (sr_usb_open(drvc->sr_ctx->libusb_ctx, usb) != SR_OK)
return SR_ERR;
/*
* Determine if a kernel driver is active on this interface and, if so,
* detach it.
*/
if (libusb_kernel_driver_active(usb->devhdl, USB_INTERFACE) == 1) {
ret = libusb_detach_kernel_driver(usb->devhdl, USB_INTERFACE);
if (ret < 0) {
sr_err("Failed to detach kernel driver: %i.",
libusb_error_name(ret));
return SR_ERR;
}
}
ret = libusb_claim_interface(usb->devhdl, USB_INTERFACE);
if (ret) {
sr_err("Failed to claim interface: %s.",
libusb_error_name(ret));
return SR_ERR;
}
libusb_fill_control_transfer(devc->xfer_in, usb->devhdl,
devc->xfer_buf_in, ikalogic_scanalogic2_receive_transfer_in,
sdi, USB_TIMEOUT);
libusb_fill_control_transfer(devc->xfer_out, usb->devhdl,
devc->xfer_buf_out, ikalogic_scanalogic2_receive_transfer_out,
sdi, USB_TIMEOUT);
memset(buffer, 0, sizeof(buffer));
buffer[0] = CMD_RESET;
ret = ikalogic_scanalogic2_transfer_out(usb->devhdl, buffer);
if (ret != PACKET_LENGTH) {
sr_err("Device reset failed: %s.", libusb_error_name(ret));
return SR_ERR;
}
/*
* Set the device to idle state. If the device is not in idle state it
* possibly will reset itself after a few seconds without being used and
* thereby close the connection.
*/
buffer[0] = CMD_IDLE;
ret = ikalogic_scanalogic2_transfer_out(usb->devhdl, buffer);
if (ret != PACKET_LENGTH) {
sr_err("Failed to set device in idle state: %s.",
libusb_error_name(ret));
return SR_ERR;
}
sdi->status = SR_ST_ACTIVE;
@ -72,10 +298,22 @@ static int dev_open(struct sr_dev_inst *sdi)
static int dev_close(struct sr_dev_inst *sdi)
{
(void)sdi;
struct sr_usb_dev_inst *usb;
/* TODO: get handle from sdi->conn and close it. */
if (!di->priv) {
sr_err("Driver was not initialized.");
return SR_ERR;
}
usb = sdi->conn;
if (!usb->devhdl)
return SR_OK;
libusb_release_interface(usb->devhdl, USB_INTERFACE);
libusb_close(usb->devhdl);
usb->devhdl = NULL;
sdi->status = SR_ST_INACTIVE;
return SR_OK;
@ -85,21 +323,24 @@ static int cleanup(void)
{
dev_clear();
/* TODO: free other driver resources, if any. */
return SR_OK;
}
static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
int ret;
(void)sdi;
(void)data;
ret = SR_OK;
devc = sdi->priv;
switch (key) {
/* TODO */
case SR_CONF_SAMPLERATE:
*data = g_variant_new_uint64(devc->samplerate);
break;
case SR_CONF_CAPTURE_RATIO:
*data = g_variant_new_uint64(devc->capture_ratio);
break;
default:
return SR_ERR_NA;
}
@ -109,33 +350,29 @@ static int config_get(int key, GVariant **data, const struct sr_dev_inst *sdi)
static int config_set(int key, GVariant *data, const struct sr_dev_inst *sdi)
{
uint64_t samplerate, limit_samples, capture_ratio;
int ret;
(void)data;
if (sdi->status != SR_ST_ACTIVE)
return SR_ERR_DEV_CLOSED;
ret = SR_OK;
switch (key) {
/* TODO */
default:
ret = SR_ERR_NA;
}
return ret;
}
static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
{
int ret;
(void)sdi;
(void)data;
ret = SR_OK;
switch (key) {
/* TODO */
case SR_CONF_LIMIT_SAMPLES:
limit_samples = g_variant_get_uint64(data);
ret = ikalogic_scanalogic2_set_limit_samples(sdi,
limit_samples);
break;
case SR_CONF_SAMPLERATE:
samplerate = g_variant_get_uint64(data);
ret = ikalogic_scanalogic2_set_samplerate(sdi, samplerate);
break;
case SR_CONF_CAPTURE_RATIO:
capture_ratio = g_variant_get_uint64(data);
ret = ikalogic_scanalogic2_set_capture_ratio(sdi,
capture_ratio);
break;
default:
return SR_ERR_NA;
}
@ -143,17 +380,149 @@ static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
return ret;
}
static int dev_acquisition_start(const struct sr_dev_inst *sdi,
void *cb_data)
static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
{
GVariant *gvar;
GVariantBuilder gvb;
int ret;
(void)sdi;
(void)cb_data;
ret = SR_OK;
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_SAMPLERATE:
g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}"));
gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"),
ikalogic_scanalogic2_samplerates,
ARRAY_SIZE(ikalogic_scanalogic2_samplerates),
sizeof(uint64_t));
g_variant_builder_add(&gvb, "{sv}", "samplerates", gvar);
*data = g_variant_builder_end(&gvb);
break;
case SR_CONF_TRIGGER_TYPE:
*data = g_variant_new_string(TRIGGER_TYPES);
break;
default:
return SR_ERR_NA;
}
return ret;
}
static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
{
const struct libusb_pollfd **pfd;
struct drv_context *drvc;
struct dev_context *devc;
uint16_t trigger_bytes, tmp;
unsigned int i, j;
int ret;
if (sdi->status != SR_ST_ACTIVE)
return SR_ERR_DEV_CLOSED;
/* TODO: configure hardware, reset acquisition state, set up
* callbacks and send header packet. */
devc = sdi->priv;
drvc = di->priv;
devc->cb_data = cb_data;
devc->wait_data_ready_locked = TRUE;
devc->stopping_in_progress = FALSE;
devc->transfer_error = FALSE;
devc->samples_processed = 0;
devc->channel = 0;
devc->sample_packet = 0;
/*
* The trigger must be configured first because the calculation of the
* pre and post trigger samples depends on a configured trigger.
*/
ikalogic_scanalogic2_configure_trigger(sdi);
ikalogic_scanalogic2_calculate_trigger_samples(sdi);
trigger_bytes = devc->pre_trigger_bytes + devc->post_trigger_bytes;
/* Calculate the number of expected sample packets. */
devc->num_sample_packets = trigger_bytes / PACKET_NUM_SAMPLE_BYTES;
/* Round up the number of expected sample packets. */
if (trigger_bytes % PACKET_NUM_SAMPLE_BYTES != 0)
devc->num_sample_packets++;
devc->num_enabled_probes = 0;
/*
* Count the number of enabled probes and number them for a sequential
* access.
*/
for (i = 0, j = 0; i < NUM_PROBES; i++) {
if (devc->probes[i]->enabled) {
devc->num_enabled_probes++;
devc->probe_map[j] = i;
j++;
}
}
sr_dbg("Number of enabled probes: %i.", devc->num_enabled_probes);
/* Set up the transfer buffer for the acquisition. */
devc->xfer_data_out[0] = CMD_SAMPLE;
devc->xfer_data_out[1] = 0x00;
tmp = GUINT16_TO_LE(devc->pre_trigger_bytes);
memcpy(devc->xfer_data_out + 2, &tmp, sizeof(tmp));
tmp = GUINT16_TO_LE(devc->post_trigger_bytes);
memcpy(devc->xfer_data_out + 4, &tmp, sizeof(tmp));
devc->xfer_data_out[6] = devc->samplerate_id;
devc->xfer_data_out[7] = devc->trigger_type;
devc->xfer_data_out[8] = devc->trigger_channel;
devc->xfer_data_out[9] = 0x00;
tmp = GUINT16_TO_LE(devc->after_trigger_delay);
memcpy(devc->xfer_data_out + 10, &tmp, sizeof(tmp));
if (!(pfd = libusb_get_pollfds(drvc->sr_ctx->libusb_ctx))) {
sr_err("libusb_get_pollfds failed.");
return SR_ERR;
}
/* Count the number of file descriptors. */
for (devc->num_usbfd = 0; pfd[devc->num_usbfd]; devc->num_usbfd++);
if (!(devc->usbfd = g_try_malloc(devc->num_usbfd * sizeof(int)))) {
sr_err("File descriptor array malloc failed.");
free(pfd);
return SR_ERR_MALLOC;
}
if ((ret = libusb_submit_transfer(devc->xfer_out)) != 0) {
sr_err("Submit transfer failed: %s", libusb_error_name(ret));
g_free(devc->usbfd);
return SR_ERR;
}
for (i = 0; i < devc->num_usbfd; i++) {
sr_source_add(pfd[i]->fd, pfd[i]->events, 100,
ikalogic_scanalogic2_receive_data, (void *)sdi);
devc->usbfd[i] = pfd[i]->fd;
}
free(pfd);
sr_dbg("Acquisition started successfully.");
/* Send header packet to the session bus. */
std_session_send_df_header(cb_data, LOG_PREFIX);
devc->next_state = STATE_SAMPLE;
return SR_OK;
}
@ -165,14 +534,16 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
if (sdi->status != SR_ST_ACTIVE)
return SR_ERR_DEV_CLOSED;
/* TODO: stop acquisition. */
sr_dbg("Stopping acquisition.");
sdi->status = SR_ST_STOPPING;
return SR_OK;
}
SR_PRIV struct sr_dev_driver ikalogic_scanalogic2_driver_info = {
.name = "ikalogic-scanalogic2",
.longname = "IKALOGIC Scanalogic2",
.longname = "IKALOGIC Scanalogic-2",
.api_version = 1,
.init = init,
.cleanup = cleanup,

View File

@ -19,12 +19,202 @@
#include "protocol.h"
SR_PRIV int ikalogic_scanalogic2_receive_data(int fd, int revents, void *cb_data)
{
(void)fd;
extern struct sr_dev_driver ikalogic_scanalogic2_driver_info;
static struct sr_dev_driver *di = &ikalogic_scanalogic2_driver_info;
const struct sr_dev_inst *sdi;
extern uint64_t ikalogic_scanalogic2_samplerates[NUM_SAMPLERATES];
static void stop_acquisition(struct sr_dev_inst *sdi)
{
struct dev_context *devc;
struct sr_datafeed_packet packet;
unsigned int i;
devc = sdi->priv;
/* Remove USB file descriptors from polling. */
for (i = 0; i < devc->num_usbfd; i++)
sr_source_remove(devc->usbfd[i]);
g_free(devc->usbfd);
packet.type = SR_DF_END;
sr_session_send(devc->cb_data, &packet);
sdi->status = SR_ST_ACTIVE;
}
static void abort_acquisition(struct sr_dev_inst *sdi)
{
struct dev_context *devc;
struct sr_datafeed_packet packet;
unsigned int i;
devc = sdi->priv;
/* Remove USB file descriptors from polling. */
for (i = 0; i < devc->num_usbfd; i++)
sr_source_remove(devc->usbfd[i]);
g_free(devc->usbfd);
packet.type = SR_DF_END;
sr_session_send(devc->cb_data, &packet);
sdi->driver->dev_close(sdi);
}
static void buffer_sample_data(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
unsigned int offset, packet_length;
devc = sdi->priv;
if (devc->probes[devc->channel]->enabled) {
offset = devc->sample_packet * PACKET_NUM_SAMPLE_BYTES;
/*
* Determine the packet length to ensure that the last packet
* will not exceed the buffer size.
*/
packet_length = MIN(PACKET_NUM_SAMPLE_BYTES,
MAX_DEV_SAMPLE_BYTES - offset);
/*
* Skip the first 4 bytes of the source buffer because they
* contain channel and packet information only.
*/
memcpy(devc->sample_buffer[devc->channel] + offset,
devc->xfer_data_in + 4, packet_length);
}
}
static void process_sample_data(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
struct sr_datafeed_packet packet;
struct sr_datafeed_logic logic;
uint8_t i, j, tmp, buffer[PACKET_NUM_SAMPLES], *ptr[NUM_PROBES];
uint16_t offset, n = 0;
int8_t k;
devc = sdi->priv;
offset = devc->sample_packet * PACKET_NUM_SAMPLE_BYTES;
/*
* Array of pointers to the sample data of all channels up to the last
* enabled one for an uniform access to them. Note that the currently
* received samples always belong to the last enabled channel.
*/
for (i = 0; i < devc->num_enabled_probes - 1; i++)
ptr[i] = devc->sample_buffer[devc->probe_map[i]] + offset;
/*
* Skip the first 4 bytes of the buffer because they contain channel and
* packet information only.
*/
ptr[i] = devc->xfer_data_in + 4;
for (i = 0; i < PACKET_NUM_SAMPLE_BYTES; i++) {
/* Stop processing if all requested samples are processed. */
if (devc->samples_processed == devc->limit_samples)
break;
k = 7;
if (devc->samples_processed == 0) {
/*
* Adjust the position of the first sample to be
* processed because possibly more samples than
* necessary might have been aquired. This is because
* the number of aquired samples is always rounded up to
* a multiple of 8.
*/
k = k - (devc->pre_trigger_bytes * 8) +
devc->pre_trigger_samples;
sr_dbg("Start processing at sample: %" PRIu8 ".",
7 - k);
/*
* Send the trigger before the first sample is processed
* if no pre trigger samples were calculated through the
* capture ratio.
*/
if (devc->trigger_type != TRIGGER_TYPE_NONE &&
devc->pre_trigger_samples == 0) {
packet.type = SR_DF_TRIGGER;
sr_session_send(devc->cb_data, &packet);
}
}
for (; k >= 0; k--) {
/*
* Stop processing if all requested samples are
* processed.
*/
if (devc->samples_processed == devc->limit_samples)
break;
buffer[n] = 0;
/*
* Extract the current sample for each enabled channel
* and store them in the buffer.
*/
for (j = 0; j < devc->num_enabled_probes; j++) {
tmp = (ptr[j][i] & (1 << k)) >> k;
buffer[n] |= tmp << devc->probe_map[j];
}
n++;
devc->samples_processed++;
/*
* Send all processed samples and the trigger if the
* number of processed samples reaches the calculated
* number of pre trigger samples.
*/
if (devc->samples_processed == devc->pre_trigger_samples &&
devc->trigger_type != TRIGGER_TYPE_NONE) {
packet.type = SR_DF_LOGIC;
packet.payload = &logic;
logic.length = n;
logic.unitsize = 1;
logic.data = buffer;
sr_session_send(devc->cb_data, &packet);
packet.type = SR_DF_TRIGGER;
sr_session_send(devc->cb_data, &packet);
n = 0;
}
}
}
if (n > 0) {
packet.type = SR_DF_LOGIC;
packet.payload = &logic;
logic.length = n;
logic.unitsize = 1;
logic.data = buffer;
sr_session_send(devc->cb_data, &packet);
}
}
SR_PRIV int ikalogic_scanalogic2_receive_data(int fd, int revents,
void *cb_data)
{
struct sr_dev_inst *sdi;
struct dev_context *devc;
struct drv_context *drvc;
struct timeval tv;
int64_t current_time, time_elapsed;
int ret = 0;
(void)fd;
(void)revents;
if (!(sdi = cb_data))
return TRUE;
@ -32,9 +222,558 @@ SR_PRIV int ikalogic_scanalogic2_receive_data(int fd, int revents, void *cb_data
if (!(devc = sdi->priv))
return TRUE;
if (revents == G_IO_IN) {
/* TODO */
drvc = di->priv;
current_time = g_get_monotonic_time();
if (devc->state == STATE_WAIT_DATA_READY &&
!devc->wait_data_ready_locked) {
time_elapsed = current_time - devc->wait_data_ready_time;
/*
* Check here for stopping in addition to the transfer callback
* functions to avoid waiting until the WAIT_DATA_READY_INTERVAL
* has expired.
*/
if (sdi->status == SR_ST_STOPPING) {
if (!devc->stopping_in_progress) {
devc->next_state = STATE_RESET_AND_IDLE;
devc->stopping_in_progress = TRUE;
ret = libusb_submit_transfer(devc->xfer_in);
}
} else if (time_elapsed >= WAIT_DATA_READY_INTERVAL) {
devc->wait_data_ready_locked = TRUE;
ret = libusb_submit_transfer(devc->xfer_in);
}
}
if (ret != 0) {
sr_err("Submit transfer failed: %s", libusb_error_name(ret));
abort_acquisition(sdi);
return TRUE;
}
tv.tv_sec = 0;
tv.tv_usec = 0;
libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &tv,
NULL);
/* Check if an error occurred on a transfer. */
if (devc->transfer_error) {
abort_acquisition(sdi);
}
return TRUE;
}
SR_PRIV void ikalogic_scanalogic2_receive_transfer_in(
struct libusb_transfer *transfer)
{
struct sr_dev_inst *sdi;
struct dev_context *devc;
uint8_t last_channel;
int ret = 0;
sdi = transfer->user_data;
devc = sdi->priv;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
sr_err("Transfer to device failed: %i", transfer->status);
devc->transfer_error = TRUE;
return;
}
if (sdi->status == SR_ST_STOPPING && !devc->stopping_in_progress) {
devc->next_state = STATE_RESET_AND_IDLE;
devc->stopping_in_progress = TRUE;
if (libusb_submit_transfer(devc->xfer_in) != 0) {
sr_err("Submit transfer failed: %s",
libusb_error_name(ret));
devc->transfer_error = TRUE;
}
return;
}
sr_dbg("State changed from %i to %i.", devc->state, devc->next_state);
devc->state = devc->next_state;
if (devc->state == STATE_WAIT_DATA_READY) {
/* Check if the received data are a valid device status. */
if (devc->xfer_data_in[0] == 0x05) {
if (devc->xfer_data_in[1] == STATUS_WAITING_FOR_TRIGGER)
sr_dbg("Waiting for trigger.");
else if (devc->xfer_data_in[1] == STATUS_SAMPLING)
sr_dbg("Sampling in progress.");
}
/*
* Check if the received data are a valid device status and the
* sample data are ready.
*/
if (devc->xfer_data_in[0] == 0x05 &&
devc->xfer_data_in[1] == STATUS_DATA_READY) {
devc->next_state = STATE_RECEIVE_DATA;
ret = libusb_submit_transfer(transfer);
} else {
devc->wait_data_ready_locked = FALSE;
devc->wait_data_ready_time = g_get_monotonic_time();
}
} else if (devc->state == STATE_RECEIVE_DATA) {
last_channel = devc->probe_map[devc->num_enabled_probes - 1];
if (devc->channel < last_channel) {
buffer_sample_data(sdi);
} else if (devc->channel == last_channel) {
process_sample_data(sdi);
} else {
/*
* Stop acquisition because all samples of enabled
* probes are processed.
*/
devc->next_state = STATE_RESET_AND_IDLE;
}
devc->sample_packet++;
devc->sample_packet %= devc->num_sample_packets;
if (devc->sample_packet == 0)
devc->channel++;
ret = libusb_submit_transfer(transfer);
} else if (devc->state == STATE_RESET_AND_IDLE) {
/* Check if the received data are a valid device status. */
if (devc->xfer_data_in[0] == 0x05) {
if (devc->xfer_data_in[1] == STATUS_DEVICE_READY) {
devc->next_state = STATE_IDLE;
devc->xfer_data_out[0] = CMD_IDLE;
} else {
devc->next_state = STATE_WAIT_DEVICE_READY;
devc->xfer_data_out[0] = CMD_RESET;
}
ret = libusb_submit_transfer(devc->xfer_out);
} else {
/*
* The received device status is invalid which indicates
* that the device is not ready to accept commands.
* Request a new device status until a valid device
* status is received.
*/
ret = libusb_submit_transfer(transfer);
}
} else if (devc->state == STATE_WAIT_DEVICE_READY) {
/* Check if the received data are a valid device status. */
if (devc->xfer_data_in[0] == 0x05) {
if (devc->xfer_data_in[1] == STATUS_DEVICE_READY) {
devc->next_state = STATE_IDLE;
devc->xfer_data_out[0] = CMD_IDLE;
} else {
/*
* The received device status is valid but the
* device is not ready. Probably the device did
* not recognize the last reset. Reset the
* device again.
*/
devc->xfer_data_out[0] = CMD_RESET;
}
ret = libusb_submit_transfer(devc->xfer_out);
} else {
/*
* The device is not ready and therefore not able to
* change to the idle state. Request a new device status
* until the device is ready.
*/
ret = libusb_submit_transfer(transfer);
}
}
if (ret != 0) {
sr_err("Submit transfer failed: %s", libusb_error_name(ret));
devc->transfer_error = TRUE;
}
}
SR_PRIV void ikalogic_scanalogic2_receive_transfer_out(
struct libusb_transfer *transfer)
{
struct sr_dev_inst *sdi;
struct dev_context *devc;
int ret = 0;
sdi = transfer->user_data;
devc = sdi->priv;
if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
sr_err("Transfer to device failed: %i", transfer->status);
devc->transfer_error = TRUE;
return;
}
if (sdi->status == SR_ST_STOPPING && !devc->stopping_in_progress) {
devc->next_state = STATE_RESET_AND_IDLE;
devc->stopping_in_progress = TRUE;
if (libusb_submit_transfer(devc->xfer_in) != 0) {
sr_err("Submit transfer failed: %s",
libusb_error_name(ret));
devc->transfer_error = TRUE;
}
return;
}
sr_dbg("State changed from %i to %i.", devc->state, devc->next_state);
devc->state = devc->next_state;
if (devc->state == STATE_IDLE) {
stop_acquisition(sdi);
} else if (devc->state == STATE_SAMPLE) {
devc->next_state = STATE_WAIT_DATA_READY;
ret = libusb_submit_transfer(devc->xfer_in);
} else if (devc->state == STATE_WAIT_DEVICE_READY) {
ret = libusb_submit_transfer(devc->xfer_in);
}
if (ret != 0) {
sr_err("Submit transfer failed: %s", libusb_error_name(ret));
devc->transfer_error = TRUE;
}
}
SR_PRIV int ikalogic_scanalogic2_set_samplerate(const struct sr_dev_inst *sdi,
uint64_t samplerate)
{
struct dev_context *devc;
unsigned int i;
devc = sdi->priv;
for (i = 0; i < NUM_SAMPLERATES; i++) {
if (ikalogic_scanalogic2_samplerates[i] == samplerate) {
devc->samplerate = samplerate;
devc->samplerate_id = NUM_SAMPLERATES - i - 1;
return SR_OK;
}
}
return SR_ERR_ARG;
}
SR_PRIV int ikalogic_scanalogic2_set_limit_samples(
const struct sr_dev_inst *sdi, uint64_t limit_samples)
{
struct dev_context *devc;
devc = sdi->priv;
if (limit_samples == 0) {
sr_err("Invalid number of limit samples: %" PRIu64 ".",
limit_samples);
return SR_ERR_ARG;
}
if (limit_samples > MAX_SAMPLES)
limit_samples = MAX_SAMPLES;
sr_info("Limit samples set to %" PRIu64 ".", limit_samples);
devc->limit_samples = limit_samples;
return SR_OK;
}
SR_PRIV void ikalogic_scanalogic2_configure_trigger(
const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
struct sr_probe *probe;
uint8_t trigger_type;
int probe_index, num_triggers_anyedge;
char *trigger;
GSList *l;
devc = sdi->priv;
/* Disable the trigger by default. */
devc->trigger_channel = TRIGGER_CHANNEL_0;
devc->trigger_type = TRIGGER_TYPE_NONE;
num_triggers_anyedge = 0;
for (l = sdi->probes, probe_index = 0; l; l = l->next, probe_index++) {
probe = l->data;
trigger = probe->trigger;
if (!trigger || !probe->enabled)
continue;
switch (*trigger) {
case 'r':
trigger_type = TRIGGER_TYPE_POSEDGE;
break;
case 'f':
trigger_type = TRIGGER_TYPE_NEGEDGE;
break;
case 'c':
trigger_type = TRIGGER_TYPE_ANYEDGE;
num_triggers_anyedge++;
break;
default:
continue;
}
devc->trigger_channel = probe_index + 1;
devc->trigger_type = trigger_type;
}
/*
* Set trigger to any edge on all channels if the trigger for each
* channel is set to any edge.
*/
if (num_triggers_anyedge == NUM_PROBES) {
devc->trigger_channel = TRIGGER_CHANNEL_ALL;
devc->trigger_type = TRIGGER_TYPE_ANYEDGE;
}
sr_dbg("Trigger set to channel %" PRIu8 " and type %" PRIu8 ".",
devc->trigger_channel, devc->trigger_type);
}
SR_PRIV int ikalogic_scanalogic2_set_capture_ratio(
const struct sr_dev_inst *sdi, uint64_t capture_ratio)
{
struct dev_context *devc;
devc = sdi->priv;
if (capture_ratio > 100) {
sr_err("Invalid capture ratio: %" PRIu64 " %%.", capture_ratio);
return SR_ERR_ARG;
}
sr_info("Capture ratio set to %" PRIu64 " %%.", capture_ratio);
devc->capture_ratio = capture_ratio;
return SR_OK;
}
SR_PRIV int ikaloigc_scanalogic2_set_after_trigger_delay(
const struct sr_dev_inst *sdi, uint64_t after_trigger_delay)
{
struct dev_context *devc;
devc = sdi->priv;
if (after_trigger_delay > MAX_AFTER_TRIGGER_DELAY) {
sr_err("Invalid after trigger delay: %" PRIu64 " ms.",
after_trigger_delay);
return SR_ERR_ARG;
}
sr_info("After trigger delay set to %" PRIu64 " ms.",
after_trigger_delay);
devc->after_trigger_delay = after_trigger_delay;
return SR_OK;
}
SR_PRIV void ikalogic_scanalogic2_calculate_trigger_samples(
const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
uint64_t pre_trigger_samples, post_trigger_samples;
uint16_t pre_trigger_bytes, post_trigger_bytes;
uint8_t cr;
devc = sdi->priv;
cr = devc->capture_ratio;
/* Ignore the capture ratio if no trigger is enabled. */
if (devc->trigger_type == TRIGGER_TYPE_NONE)
cr = 0;
pre_trigger_samples = (devc->limit_samples * cr) / 100;
post_trigger_samples = (devc->limit_samples * (100 - cr)) / 100;
/*
* Increase the number of post trigger samples by one to compensate the
* possible loss of a sample through integer rounding.
*/
if (pre_trigger_samples + post_trigger_samples != devc->limit_samples)
post_trigger_samples++;
/*
* The device requires the number of samples in multiples of 8 which
* will also be called sample bytes in the following.
*/
pre_trigger_bytes = pre_trigger_samples / 8;
post_trigger_bytes = post_trigger_samples / 8;
/*
* Round up the number of sample bytes to ensure that at least the
* requested number of samples will be acquired. Note that due to this
* rounding the buffer to store these sample bytes needs to be at least
* one sample byte larger than the minimal number of sample bytes needed
* to store the requested samples.
*/
if (pre_trigger_samples % 8 != 0)
pre_trigger_bytes++;
if (post_trigger_samples % 8 != 0)
post_trigger_bytes++;
sr_info("Pre trigger samples: %" PRIu64 ".", pre_trigger_samples);
sr_info("Post trigger samples: %" PRIu64 ".", post_trigger_samples);
sr_dbg("Pre trigger sample bytes: %" PRIu16 ".", pre_trigger_bytes);
sr_dbg("Post trigger sample bytes: %" PRIu16 ".", post_trigger_bytes);
devc->pre_trigger_samples = pre_trigger_samples;
devc->pre_trigger_bytes = pre_trigger_bytes;
devc->post_trigger_bytes = post_trigger_bytes;
}
SR_PRIV int ikalogic_scanalogic2_get_device_info(struct sr_usb_dev_inst usb,
struct device_info *dev_info)
{
struct drv_context *drvc;
uint8_t buffer[PACKET_LENGTH];
int ret;
drvc = di->priv;
if (!dev_info)
return SR_ERR_ARG;
if (sr_usb_open(drvc->sr_ctx->libusb_ctx, &usb) != SR_OK)
return SR_ERR;
/*
* Determine if a kernel driver is active on this interface and, if so,
* detach it.
*/
if (libusb_kernel_driver_active(usb.devhdl, USB_INTERFACE) == 1) {
ret = libusb_detach_kernel_driver(usb.devhdl,
USB_INTERFACE);
if (ret < 0) {
sr_err("Failed to detach kernel driver: %i.",
libusb_error_name(ret));
libusb_close(usb.devhdl);
return SR_ERR;
}
}
ret = libusb_claim_interface(usb.devhdl, USB_INTERFACE);
if (ret) {
sr_err("Failed to claim interface: %s.",
libusb_error_name(ret));
libusb_close(usb.devhdl);
return SR_ERR;
}
memset(buffer, 0, sizeof(buffer));
/*
* Reset the device to ensure it is in a proper state to request the
* device information.
*/
buffer[0] = CMD_RESET;
ret = ikalogic_scanalogic2_transfer_out(usb.devhdl, buffer);
if (ret != PACKET_LENGTH) {
sr_err("Resetting of device failed: %s.",
libusb_error_name(ret));
libusb_release_interface(usb.devhdl, USB_INTERFACE);
libusb_close(usb.devhdl);
return SR_ERR;
}
buffer[0] = CMD_INFO;
ret = ikalogic_scanalogic2_transfer_out(usb.devhdl, buffer);
if (ret != PACKET_LENGTH) {
sr_err("Requesting of device information failed: %s.",
libusb_error_name(ret));
libusb_release_interface(usb.devhdl, USB_INTERFACE);
libusb_close(usb.devhdl);
return SR_ERR;
}
ret = ikalogic_scanalogic2_transfer_in(usb.devhdl, buffer);
if (ret != PACKET_LENGTH) {
sr_err("Receiving of device information failed: %s.",
libusb_error_name(ret));
libusb_release_interface(usb.devhdl, USB_INTERFACE);
libusb_close(usb.devhdl);
return SR_ERR;
}
memcpy(&(dev_info->serial), buffer + 1, sizeof(uint32_t));
dev_info->serial = GUINT32_FROM_LE(dev_info->serial);
dev_info->fw_ver_major = buffer[5];
dev_info->fw_ver_minor = buffer[6];
buffer[0] = CMD_RESET;
ret = ikalogic_scanalogic2_transfer_out(usb.devhdl, buffer);
if (ret != PACKET_LENGTH) {
sr_err("Device reset failed: %s.", libusb_error_name(ret));
libusb_release_interface(usb.devhdl, USB_INTERFACE);
libusb_close(usb.devhdl);
return SR_ERR;
}
/*
* Set the device to idle state. If the device is not in idle state it
* possibly will reset itself after a few seconds without being used and
* thereby close the connection.
*/
buffer[0] = CMD_IDLE;
ret = ikalogic_scanalogic2_transfer_out(usb.devhdl, buffer);
if (ret != PACKET_LENGTH) {
sr_err("Failed to set device in idle state: %s.",
libusb_error_name(ret));
libusb_release_interface(usb.devhdl, USB_INTERFACE);
libusb_close(usb.devhdl);
return SR_ERR;
}
ret = libusb_release_interface(usb.devhdl, USB_INTERFACE);
if (ret < 0) {
sr_err("Failed to release interface: %i.",
libusb_error_name(ret));
libusb_close(usb.devhdl);
return SR_ERR;
}
libusb_close(usb.devhdl);
return SR_OK;
}
SR_PRIV int ikalogic_scanalogic2_transfer_in(libusb_device_handle *dev_handle,
unsigned char *data)
{
return libusb_control_transfer(dev_handle, USB_REQUEST_TYPE_IN,
USB_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE,
data, PACKET_LENGTH, USB_TIMEOUT);
}
SR_PRIV int ikalogic_scanalogic2_transfer_out(libusb_device_handle *dev_handle,
unsigned char *data)
{
return libusb_control_transfer(dev_handle, USB_REQUEST_TYPE_OUT,
USB_HID_SET_REPORT, USB_HID_REPORT_TYPE_FEATURE, USB_INTERFACE,
data, PACKET_LENGTH, USB_TIMEOUT);
}

View File

@ -20,6 +20,8 @@
#ifndef LIBSIGROK_HARDWARE_IKALOGIC_SCANALOGIC2_PROTOCOL_H
#define LIBSIGROK_HARDWARE_IKALOGIC_SCANALOGIC2_PROTOCOL_H
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <glib.h>
#include "libsigrok.h"
@ -34,18 +36,220 @@
#define sr_warn(s, args...) sr_warn(LOG_PREFIX s, ## args)
#define sr_err(s, args...) sr_err(LOG_PREFIX s, ## args)
/** Private, per-device-instance driver context. */
struct dev_context {
/* Model-specific information */
#define VENDOR_NAME "IKALOGIC"
#define MODEL_NAME "Scanalogic-2"
/* Acquisition settings */
#define USB_VID_PID "20a0.4123"
#define USB_INTERFACE 0
#define USB_TIMEOUT 5000
/* Operational state */
#define USB_REQUEST_TYPE_IN (LIBUSB_REQUEST_TYPE_CLASS | \
LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN)
/* Temporary state across callbacks */
#define USB_REQUEST_TYPE_OUT (LIBUSB_REQUEST_TYPE_CLASS | \
LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT)
#define USB_HID_SET_REPORT 0x09
#define USB_HID_REPORT_TYPE_FEATURE 0x300
#define NUM_SAMPLERATES 11
#define NUM_PROBES 4
#define TRIGGER_TYPES "rfc"
/*
* Number of sample bytes and samples the device can acquire. Note that the
* vendor software can acquire 32736 sample bytes only but the device is capable
* to acquire up to 32766 sample bytes.
*/
#define MAX_DEV_SAMPLE_BYTES 32766
#define MAX_DEV_SAMPLES (MAX_INT_SAMPLE_BYTES * 8)
/* Number of sample bytes and samples the driver can acquire. */
#define MAX_SAMPLE_BYTES (MAX_DEV_SAMPLE_BYTES - 1)
#define MAX_SAMPLES (MAX_SAMPLE_BYTES * 8)
/* Maximum time that the trigger can be delayed in milliseconds. */
#define MAX_AFTER_TRIGGER_DELAY 65000
#define PACKET_LENGTH 128
/* Number of sample bytes per packet where a sample byte contains 8 samples. */
#define PACKET_NUM_SAMPLE_BYTES 124
/* Number of samples per packet. */
#define PACKET_NUM_SAMPLES (PACKET_NUM_SAMPLE_BYTES * 8)
#define DEFAULT_SAMPLERATE SR_KHZ(1.25)
/*
* Time interval between the last status of available data received and the
* moment when the next status request will be sent in microseconds.
*/
#define WAIT_DATA_READY_INTERVAL 1500000
#define CMD_SAMPLE 0x01
#define CMD_RESET 0x02
#define CMD_IDLE 0x07
#define CMD_INFO 0x0a
#define TRIGGER_CHANNEL_ALL 0x00
#define TRIGGER_CHANNEL_0 0x01
#define TRIGGER_CHANNEL_1 0x02
#define TRIGGER_CHANNEL_2 0x03
#define TRIGGER_TYPE_NEGEDGE 0x00
#define TRIGGER_TYPE_POSEDGE 0x01
#define TRIGGER_TYPE_ANYEDGE 0x02
#define TRIGGER_TYPE_NONE 0x03
#define STATUS_DATA_READY 0x60
#define STATUS_WAITING_FOR_TRIGGER 0x61
#define STATUS_SAMPLING 0x62
#define STATUS_DEVICE_READY 0x63
struct device_info {
/* Serial number of the device. */
uint32_t serial;
/* Major version of the firmware. */
uint8_t fw_ver_major;
/* Minor version of the firmware. */
uint8_t fw_ver_minor;
};
SR_PRIV int ikalogic_scanalogic2_receive_data(int fd, int revents, void *cb_data);
enum {
STATE_IDLE = 0,
STATE_SAMPLE,
STATE_WAIT_DATA_READY,
STATE_RECEIVE_DATA,
STATE_RESET_AND_IDLE,
STATE_WAIT_DEVICE_READY
};
/** Private, per-device-instance driver context. */
struct dev_context {
/* Current selected samplerate. */
uint64_t samplerate;
/* Device specific identifier for the current samplerate. */
uint8_t samplerate_id;
/* Current sampling limit. */
uint64_t limit_samples;
/* Calculated number of pre-trigger samples. */
uint64_t pre_trigger_samples;
/* Number of pre- and post-trigger sample bytes to acquire. */
uint16_t pre_trigger_bytes;
uint16_t post_trigger_bytes;
/* Device specific settings for the trigger. */
uint8_t trigger_channel;
uint8_t trigger_type;
unsigned int capture_ratio;
/* Time that the trigger will be delayed in milliseconds. */
uint16_t after_trigger_delay;
void *cb_data;
/* Array to provide an index based access to all probes. */
const struct sr_probe *probes[NUM_PROBES];
unsigned int num_usbfd;
int *usbfd;
struct libusb_transfer *xfer_in, *xfer_out;
/*
* Buffer to store setup and payload data for incoming and outgoing
* transfers.
*/
uint8_t xfer_buf_in[LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH];
uint8_t xfer_buf_out[LIBUSB_CONTROL_SETUP_SIZE + PACKET_LENGTH];
/* Pointers to the payload of incoming and outgoing transfers. */
uint8_t *xfer_data_in, *xfer_data_out;
/* Current state of the state machine */
unsigned int state;
/* Next state of the state machine. */
unsigned int next_state;
/*
* Locking variable to ensure that no status about available data will
* be requested until the last status was received.
*/
gboolean wait_data_ready_locked;
/*
* Time when the last response about the status of available data was
* received.
*/
int64_t wait_data_ready_time;
/*
* Indicates that stopping of the acquisition is currently in progress.
*/
gboolean stopping_in_progress;
/*
* Buffer which contains the samples received from the device for each
* channel except the last one. The samples of the last channel will be
* processed directly after they will be received.
*/
uint8_t sample_buffer[NUM_PROBES - 1][MAX_DEV_SAMPLE_BYTES];
/* Expected number of sample packets for each channel. */
uint16_t num_sample_packets;
/* Number of samples already processed. */
uint64_t samples_processed;
/* Sample packet number that is currently processed. */
uint16_t sample_packet;
/* Channel number that is currently processed. */
uint8_t channel;
/* Number of enabled probes. */
unsigned int num_enabled_probes;
/* Array to provide a sequential access to all enabled probe indices. */
uint8_t probe_map[NUM_PROBES];
/* Indicates whether a transfer failed. */
gboolean transfer_error;
};
SR_PRIV int ikalogic_scanalogic2_receive_data(int fd, int revents,
void *cb_data);
SR_PRIV void ikalogic_scanalogic2_receive_transfer_in(
struct libusb_transfer *transfer);
SR_PRIV void ikalogic_scanalogic2_receive_transfer_out(
struct libusb_transfer *transfer);
SR_PRIV int ikalogic_scanalogic2_set_samplerate(const struct sr_dev_inst *sdi,
uint64_t samplerate);
SR_PRIV int ikalogic_scanalogic2_set_limit_samples(
const struct sr_dev_inst *sdi, uint64_t limit_samples);
SR_PRIV void ikalogic_scanalogic2_configure_trigger(
const struct sr_dev_inst *sdi);
SR_PRIV int ikalogic_scanalogic2_set_capture_ratio(
const struct sr_dev_inst *sdi, uint64_t capture_ratio);
SR_PRIV int ikaloigc_scanalogic2_set_after_trigger_delay(
const struct sr_dev_inst *sdi, uint64_t after_trigger_delay);
SR_PRIV void ikalogic_scanalogic2_calculate_trigger_samples(
const struct sr_dev_inst *sdi);
SR_PRIV int ikalogic_scanalogic2_get_device_info(struct sr_usb_dev_inst usb,
struct device_info *dev_info);
SR_PRIV int ikalogic_scanalogic2_transfer_in(libusb_device_handle *dev_handle,
unsigned char *data);
SR_PRIV int ikalogic_scanalogic2_transfer_out(libusb_device_handle *dev_handle,
unsigned char *data);
#endif