support for multiple FX2 devices
This commit is contained in:
parent
e53c830f33
commit
6d754b6d3a
|
@ -31,6 +31,7 @@
|
|||
#include <string.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
int ezusb_reset(struct libusb_device_handle *hdl, int set_clear)
|
||||
{
|
||||
int err;
|
||||
|
@ -56,10 +57,11 @@ int ezusb_install_firmware(libusb_device_handle *hdl, const char *filename)
|
|||
if ((fw = g_fopen(filename, "rb")) == NULL) {
|
||||
sr_warn("Unable to open firmware file %s for reading: %s",
|
||||
filename, strerror(errno));
|
||||
return 1;
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
result = offset = 0;
|
||||
result = SR_OK;
|
||||
offset = 0;
|
||||
while (1) {
|
||||
chunksize = fread(buf, 1, 4096, fw);
|
||||
if (chunksize == 0)
|
||||
|
@ -69,7 +71,7 @@ int ezusb_install_firmware(libusb_device_handle *hdl, const char *filename)
|
|||
0x0000, buf, chunksize, 100);
|
||||
if (err < 0) {
|
||||
sr_warn("Unable to send firmware to device: %d", err);
|
||||
result = 1;
|
||||
result = SR_ERR;
|
||||
break;
|
||||
}
|
||||
sr_info("Uploaded %d bytes", chunksize);
|
||||
|
@ -90,36 +92,33 @@ int ezusb_upload_firmware(libusb_device *dev, int configuration,
|
|||
sr_info("uploading firmware to device on %d.%d",
|
||||
libusb_get_bus_number(dev), libusb_get_device_address(dev));
|
||||
|
||||
err = libusb_open(dev, &hdl);
|
||||
if (err != 0) {
|
||||
if ((err = libusb_open(dev, &hdl)) < 0) {
|
||||
sr_warn("failed to open device: %d", err);
|
||||
return 1;
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
if (libusb_kernel_driver_active(hdl, 0)) {
|
||||
err = libusb_detach_kernel_driver(hdl, 0);
|
||||
if (err != 0) {
|
||||
g_warning("failed to detach kernel driver: %d", err);
|
||||
return 1;
|
||||
if ((err = libusb_detach_kernel_driver(hdl, 0)) < 0) {
|
||||
sr_warn("failed to detach kernel driver: %d", err);
|
||||
return SR_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
err = libusb_set_configuration(hdl, configuration);
|
||||
if (err != 0) {
|
||||
if ((err = libusb_set_configuration(hdl, configuration)) < 0) {
|
||||
sr_warn("Unable to set configuration: %d", err);
|
||||
return 1;
|
||||
return SR_ERR;
|
||||
}
|
||||
|
||||
if ((ezusb_reset(hdl, 1)) < 0)
|
||||
return 1;
|
||||
return SR_ERR;
|
||||
|
||||
if (ezusb_install_firmware(hdl, filename) != 0)
|
||||
return 1;
|
||||
if (ezusb_install_firmware(hdl, filename) < 0)
|
||||
return SR_ERR;
|
||||
|
||||
if ((ezusb_reset(hdl, 0)) < 0)
|
||||
return 1;
|
||||
return SR_ERR;
|
||||
|
||||
libusb_close(hdl);
|
||||
|
||||
return 0;
|
||||
return SR_OK;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,8 @@ AM_CPPFLAGS = -DFIRMWARE_DIR='"$(FIRMWARE_DIR)"'
|
|||
noinst_LTLIBRARIES = libsigrokhwsaleaelogic.la
|
||||
|
||||
libsigrokhwsaleaelogic_la_SOURCES = \
|
||||
saleae-logic.c
|
||||
saleae-logic.c \
|
||||
saleae-logic.h
|
||||
|
||||
libsigrokhwsaleaelogic_la_CFLAGS = \
|
||||
-I$(top_srcdir)/libsigrok
|
||||
|
|
|
@ -26,44 +26,16 @@
|
|||
#include <libusb.h>
|
||||
#include <sigrok.h>
|
||||
#include <sigrok-internal.h>
|
||||
#include "saleae-logic.h"
|
||||
|
||||
#define USB_INTERFACE 0
|
||||
#define USB_CONFIGURATION 1
|
||||
#define NUM_TRIGGER_STAGES 4
|
||||
#define TRIGGER_TYPES "01"
|
||||
#define FIRMWARE FIRMWARE_DIR "/saleae-logic.fw"
|
||||
#define GTV_TO_MSEC(gtv) (gtv.tv_sec * 1000 + gtv.tv_usec / 1000)
|
||||
|
||||
/* delay in ms */
|
||||
#define MAX_RENUM_DELAY 3000
|
||||
#define NUM_SIMUL_TRANSFERS 10
|
||||
#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
|
||||
|
||||
/* Software trigger implementation: positive values indicate trigger stage. */
|
||||
#define TRIGGER_FIRED -1
|
||||
|
||||
struct fx2_device {
|
||||
/* VID/PID when first found */
|
||||
uint16_t orig_vid;
|
||||
uint16_t orig_pid;
|
||||
/* VID/PID after firmware upload */
|
||||
uint16_t fw_vid;
|
||||
uint16_t fw_pid;
|
||||
char *vendor;
|
||||
char *model;
|
||||
char *model_version;
|
||||
int num_probes;
|
||||
};
|
||||
|
||||
static struct fx2_device supported_fx2[] = {
|
||||
static struct fx2_profile supported_fx2[] = {
|
||||
/* Saleae Logic */
|
||||
{ 0x0925, 0x3881, 0x0925, 0x3881, "Saleae", "Logic", NULL, 8 },
|
||||
/* default Cypress FX2 without EEPROM */
|
||||
{ 0x04b4, 0x8613, 0x0925, 0x3881, "Cypress", "FX2", NULL, 16 },
|
||||
{ 0, 0, 0, 0, NULL, NULL, NULL, 0 }
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* There is only one model Saleae Logic, and this is what it supports: */
|
||||
static int capabilities[] = {
|
||||
SR_HWCAP_LOGIC_ANALYZER,
|
||||
SR_HWCAP_SAMPLERATE,
|
||||
|
@ -74,19 +46,6 @@ static int capabilities[] = {
|
|||
0,
|
||||
};
|
||||
|
||||
/* List of struct sr_device_instance, maintained by opendev()/closedev(). */
|
||||
static GSList *device_instances = NULL;
|
||||
|
||||
/*
|
||||
* Since we can't keep track of a Saleae Logic device after upgrading the
|
||||
* firmware -- it re-enumerates into a different device address after the
|
||||
* upgrade -- this is like a global lock. No device will open until a proper
|
||||
* delay after the last device was upgraded.
|
||||
*/
|
||||
static GTimeVal fw_updated = { 0, 0 };
|
||||
|
||||
static libusb_context *usb_context = NULL;
|
||||
|
||||
static uint64_t supported_samplerates[] = {
|
||||
SR_KHZ(200),
|
||||
SR_KHZ(250),
|
||||
|
@ -108,15 +67,9 @@ static struct sr_samplerates samplerates = {
|
|||
supported_samplerates,
|
||||
};
|
||||
|
||||
/* TODO: All of these should go in a device-specific struct. */
|
||||
static uint64_t cur_samplerate = 0;
|
||||
static uint64_t limit_samples = 0;
|
||||
static uint8_t probe_mask = 0;
|
||||
static uint8_t trigger_mask[NUM_TRIGGER_STAGES] = { 0 };
|
||||
static uint8_t trigger_value[NUM_TRIGGER_STAGES] = { 0 };
|
||||
static uint8_t trigger_buffer[NUM_TRIGGER_STAGES] = { 0 };
|
||||
static struct fx2_device *fx2 = NULL;
|
||||
static int trigger_stage = TRIGGER_FIRED;
|
||||
/* List of struct sr_device_instance, maintained by opendev()/closedev(). */
|
||||
static GSList *device_instances = NULL;
|
||||
static libusb_context *usb_context = NULL;
|
||||
|
||||
static int hw_set_configuration(int device_index, int capability, void *value);
|
||||
static void hw_stop_acquisition(int device_index, gpointer session_device_id);
|
||||
|
@ -181,19 +134,21 @@ static int check_conf_profile(libusb_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct sr_device_instance *sl_open_device(int device_index)
|
||||
static int sl_open_device(int device_index)
|
||||
{
|
||||
libusb_device **devlist;
|
||||
struct libusb_device_descriptor des;
|
||||
struct sr_device_instance *sdi;
|
||||
struct fx2_device *fx2;
|
||||
int err, skip, i;
|
||||
|
||||
if (!(sdi = sr_get_device_instance(device_instances, device_index)))
|
||||
return NULL;
|
||||
return SR_ERR;
|
||||
fx2 = sdi->priv;
|
||||
|
||||
if (sdi->status == SR_ST_ACTIVE)
|
||||
/* already in use */
|
||||
return NULL;
|
||||
return SR_ERR;
|
||||
|
||||
skip = 0;
|
||||
libusb_get_device_list(usb_context, &devlist);
|
||||
|
@ -203,7 +158,7 @@ static struct sr_device_instance *sl_open_device(int device_index)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (des.idVendor != fx2->fw_vid || des.idProduct != fx2->fw_pid)
|
||||
if (des.idVendor != fx2->profile->fw_vid || des.idProduct != fx2->profile->fw_pid)
|
||||
continue;
|
||||
|
||||
if (sdi->status == SR_ST_INITIALIZING) {
|
||||
|
@ -237,29 +192,17 @@ static struct sr_device_instance *sl_open_device(int device_index)
|
|||
sdi->usb->address, USB_INTERFACE);
|
||||
} else {
|
||||
sr_warn("failed to open device: %d", err);
|
||||
sdi = NULL;
|
||||
}
|
||||
|
||||
/* if we made it here, we handled the device one way or another */
|
||||
break;
|
||||
}
|
||||
libusb_free_device_list(devlist, 1);
|
||||
|
||||
if (sdi && sdi->status != SR_ST_ACTIVE)
|
||||
sdi = NULL;
|
||||
if (sdi->status != SR_ST_ACTIVE)
|
||||
return SR_ERR;
|
||||
|
||||
return sdi;
|
||||
}
|
||||
|
||||
static int upload_firmware(libusb_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ezusb_upload_firmware(dev, USB_CONFIGURATION, FIRMWARE);
|
||||
if (ret != 0)
|
||||
return 1;
|
||||
|
||||
/* Remember when the last firmware update was done. */
|
||||
g_get_current_time(&fw_updated);
|
||||
|
||||
return 0;
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
static void close_device(struct sr_device_instance *sdi)
|
||||
|
@ -275,17 +218,17 @@ static void close_device(struct sr_device_instance *sdi)
|
|||
sdi->status = SR_ST_INACTIVE;
|
||||
}
|
||||
|
||||
static int configure_probes(GSList *probes)
|
||||
static int configure_probes(struct fx2_device *fx2, GSList *probes)
|
||||
{
|
||||
struct sr_probe *probe;
|
||||
GSList *l;
|
||||
int probe_bit, stage, i;
|
||||
char *tc;
|
||||
|
||||
probe_mask = 0;
|
||||
fx2->probe_mask = 0;
|
||||
for (i = 0; i < NUM_TRIGGER_STAGES; i++) {
|
||||
trigger_mask[i] = 0;
|
||||
trigger_value[i] = 0;
|
||||
fx2->trigger_mask[i] = 0;
|
||||
fx2->trigger_value[i] = 0;
|
||||
}
|
||||
|
||||
stage = -1;
|
||||
|
@ -294,15 +237,15 @@ static int configure_probes(GSList *probes)
|
|||
if (probe->enabled == FALSE)
|
||||
continue;
|
||||
probe_bit = 1 << (probe->index - 1);
|
||||
probe_mask |= probe_bit;
|
||||
fx2->probe_mask |= probe_bit;
|
||||
if (!(probe->trigger))
|
||||
continue;
|
||||
|
||||
stage = 0;
|
||||
for (tc = probe->trigger; *tc; tc++) {
|
||||
trigger_mask[stage] |= probe_bit;
|
||||
fx2->trigger_mask[stage] |= probe_bit;
|
||||
if (*tc == '1')
|
||||
trigger_value[stage] |= probe_bit;
|
||||
fx2->trigger_value[stage] |= probe_bit;
|
||||
stage++;
|
||||
if (stage > NUM_TRIGGER_STAGES)
|
||||
return SR_ERR;
|
||||
|
@ -314,13 +257,27 @@ static int configure_probes(GSList *probes)
|
|||
* We didn't configure any triggers, make sure acquisition
|
||||
* doesn't wait for any.
|
||||
*/
|
||||
trigger_stage = TRIGGER_FIRED;
|
||||
fx2->trigger_stage = TRIGGER_FIRED;
|
||||
else
|
||||
trigger_stage = 0;
|
||||
fx2->trigger_stage = 0;
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
||||
static struct fx2_device *fx2_device_new(void)
|
||||
{
|
||||
struct fx2_device *fx2;
|
||||
|
||||
if (!(fx2 = g_try_malloc0(sizeof(struct fx2_device)))) {
|
||||
sr_err("saleae: %s: saleae malloc failed", __func__);
|
||||
return NULL;
|
||||
}
|
||||
fx2->trigger_stage = TRIGGER_FIRED;
|
||||
|
||||
return fx2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* API callbacks
|
||||
*/
|
||||
|
@ -329,6 +286,8 @@ static int hw_init(const char *deviceinfo)
|
|||
{
|
||||
struct sr_device_instance *sdi;
|
||||
struct libusb_device_descriptor des;
|
||||
struct fx2_profile *fx2_prof;
|
||||
struct fx2_device *fx2;
|
||||
libusb_device **devlist;
|
||||
int err, devcnt, i, j;
|
||||
|
||||
|
@ -341,10 +300,10 @@ static int hw_init(const char *deviceinfo)
|
|||
}
|
||||
|
||||
/* Find all Saleae Logic devices and upload firmware to all of them. */
|
||||
fx2 = NULL;
|
||||
devcnt = 0;
|
||||
libusb_get_device_list(usb_context, &devlist);
|
||||
for (i = 0; devlist[i]; i++) {
|
||||
fx2_prof = NULL;
|
||||
err = libusb_get_device_descriptor(devlist[i], &des);
|
||||
if (err != 0) {
|
||||
sr_warn("failed to get device descriptor: %d", err);
|
||||
|
@ -354,43 +313,39 @@ static int hw_init(const char *deviceinfo)
|
|||
for (j = 0; supported_fx2[j].orig_vid; j++) {
|
||||
if (des.idVendor == supported_fx2[j].orig_vid
|
||||
&& des.idProduct == supported_fx2[j].orig_pid) {
|
||||
fx2 = &supported_fx2[j];
|
||||
fx2_prof = &supported_fx2[j];
|
||||