Initial driver for IKALOGIC Scanalogic-2
This commit is contained in:
parent
16e76baec9
commit
e52e712d05
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue