From: Bert Vermeulen Date: Tue, 25 Dec 2012 18:09:12 +0000 (+0100) Subject: nexus-osciprime: basic scanning functionality X-Git-Tag: dsupstream~412 X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=523dfc2497c8e7c765ea423ec9d638feba9ed73d nexus-osciprime: basic scanning functionality Unfortunately the device doesn't have an EEPROM on board at all, and so initially enumerates with the default Cypress FX2 VID:PID (04b4:8613). Since we already support using plain FX2* as basic logic analyzers using the fx2lafw firmware, we cannot support that same VID:PID for the OsciPrime. Therefore a USB conn is required for the initial scan. However, once the firmware is uploaded the device re-enumerates as 04b4:1004, which we do detect for scanning automatically. Thus, the OsciPrime driver requires one scan with conn parameter to get the firmware uploaded, but it will then keep working until powered off. --- diff --git a/hardware/nexus-osciprime/Makefile.am b/hardware/nexus-osciprime/Makefile.am index a8d74c5e..01f313e2 100644 --- a/hardware/nexus-osciprime/Makefile.am +++ b/hardware/nexus-osciprime/Makefile.am @@ -19,6 +19,8 @@ if HW_NEXUS_OSCIPRIME +AM_CPPFLAGS = -DFIRMWARE_DIR='"$(FIRMWARE_DIR)"' + # Local lib, this is NOT meant to be installed! noinst_LTLIBRARIES = libsigrok_hw_nexus_osciprime.la diff --git a/hardware/nexus-osciprime/api.c b/hardware/nexus-osciprime/api.c index 4c9a1da6..100fb3ba 100644 --- a/hardware/nexus-osciprime/api.c +++ b/hardware/nexus-osciprime/api.c @@ -17,13 +17,98 @@ * along with this program. If not, see . */ +#include #include #include "libsigrok.h" #include "libsigrok-internal.h" #include "protocol.h" +#define OSCI_VENDOR "Nexus Computing" +#define OSCI_MODEL "OsciPrime" +#define OSCI_VERSION "1.0" +#define OSCI_FIRMWARE FIRMWARE_DIR "/nexus-osciprime.fw" +#define OSCI_VIDPID "04b4.1004" + +static const int hwopts[] = { + SR_HWOPT_CONN, + SR_HWOPT_SERIALCOMM, + 0, +}; + +static const int hwcaps[] = { + SR_HWCAP_OSCILLOSCOPE, + SR_HWCAP_LIMIT_SAMPLES, + SR_HWCAP_CONTINUOUS, + SR_HWCAP_TIMEBASE, + SR_HWCAP_VDIV, + 0, +}; + +static const struct sr_rational timebases[] = { + /* 24 MHz */ + { 42, 1e9 }, + /* 12 MHz */ + { 83, 1e9 }, + /* 6 MHz */ + { 167, 1e9 }, + /* 3 MHz */ + { 333, 1e9 }, + /* 1.5 MHz */ + { 667, 1e9 }, + /* 750 kHz */ + { 1333, 1e9 }, + /* 375 kHz */ + { 2667, 1e9 }, + /* 187.5 kHz */ + { 5333, 1e9 }, + /* 93.25 kHz */ + { 10724, 1e9 }, + /* 46.875 kHz */ + { 21333, 1e9 }, + /* 23.4375 kHz */ + { 42666, 1e9 }, + /* 11.718 kHz */ + { 85339, 1e9 }, + /* 5.859 kHz */ + { 170678, 1e9 }, + /* 2.929 kHz */ + { 341413, 1e9 }, + /* 1.465 kHz */ + { 682594, 1e9 }, + /* 732 Hz */ + { 1366, 1e6 }, + /* 366 Hz */ + { 2732, 1e6 }, + /* 183 Hz */ + { 5464, 1e6 }, + /* 91 Hz */ + { 10989, 1e6 }, + /* 46 Hz */ + { 21739, 1e6 }, + /* 23 Hz */ + { 43478, 1e6 }, + /* 12 Hz */ + { 83333, 1e6 }, +}; + +static const char *probe_names[] = { + "CHA", + "CHB", + NULL, +}; + +static const struct sr_rational vdivs[] = { + { 1, 1 }, + { 2, 1 }, + { 5, 2 }, + { 5, 1 }, + { 10, 1 }, +}; + + SR_PRIV struct sr_dev_driver nexus_osciprime_driver_info; static struct sr_dev_driver *di = &nexus_osciprime_driver_info; +static int hw_dev_close(struct sr_dev_inst *sdi); /* Properly close and free all devices. */ static int clear_instances(void) @@ -42,8 +127,8 @@ static int clear_instances(void) if (!(devc = sdi->priv)) continue; - /* TODO */ - + hw_dev_close(sdi); + sr_usb_dev_inst_free(devc->usb); sr_dev_inst_free(sdi); } @@ -53,7 +138,7 @@ static int clear_instances(void) return SR_OK; } -static int hw_init(void) +static int hw_init(struct sr_context *sr_ctx) { struct drv_context *drvc; @@ -62,8 +147,7 @@ static int hw_init(void) return SR_ERR_MALLOC; } - /* TODO */ - + drvc->sr_ctx = sr_ctx; di->priv = drvc; return SR_OK; @@ -72,15 +156,76 @@ static int hw_init(void) static GSList *hw_scan(GSList *options) { struct drv_context *drvc; - GSList *devices; + struct dev_context *devc; + struct sr_dev_inst *sdi; + struct sr_usb_dev_inst *usb; + struct sr_hwopt *opt; + struct sr_probe *probe; + libusb_device *dev; + GSList *usb_devices, *devices, *l; + int i; + const char *conn; (void)options; - devices = NULL; - drvc = di->priv; - drvc->instances = NULL; + if (!(drvc = di->priv)) { + sr_err("Driver was not initialized."); + return NULL; + } - /* TODO */ + /* USB scan is always authoritative. */ + clear_instances(); + + conn = NULL; + for (l = options; l; l = l->next) { + opt = l->data; + switch (opt->hwopt) { + case SR_HWOPT_CONN: + conn = opt->value; + break; + } + } + if (!conn) + conn = OSCI_VIDPID; + + devices = NULL; + if ((usb_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn))) { + for (l = usb_devices; l; l = l->next) { + usb = l->data; + if (!(sdi = sr_dev_inst_new(0, SR_ST_INACTIVE, + OSCI_VENDOR, OSCI_MODEL, OSCI_VERSION))) + return NULL; + sdi->driver = di; + for (i = 0; probe_names[i]; i++) { + if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, + probe_names[i]))) + return NULL; + sdi->probes = g_slist_append(sdi->probes, probe); + } + + if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) + return NULL; + sdi->priv = devc; + devc->usb = usb; + + if (strcmp(conn, OSCI_VIDPID)) { + if (sr_usb_open(drvc->sr_ctx->libusb_ctx, usb) != SR_OK) + break; + dev = libusb_get_device(usb->devhdl); + if (ezusb_upload_firmware(dev, 0, OSCI_FIRMWARE) == SR_OK) + /* Remember when the firmware on this device was updated */ + devc->fw_updated = g_get_monotonic_time(); + else + sr_err("Firmware upload failed for device " + "at bus %d address %d.", usb->bus, usb->address); + } + + drvc->instances = g_slist_append(drvc->instances, sdi); + devices = g_slist_append(devices, sdi); + } + g_slist_free(usb_devices); + } else + g_slist_free_full(usb_devices, g_free); return devices; } @@ -175,7 +320,7 @@ static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) SR_PRIV struct sr_dev_driver nexus_osciprime_driver_info = { .name = "nexus-osciprime", - .longname = "Nexus Osciprime", + .longname = "Nexus OsciPrime", .api_version = 1, .init = hw_init, .cleanup = hw_cleanup, diff --git a/hardware/nexus-osciprime/protocol.h b/hardware/nexus-osciprime/protocol.h index 539924c3..f7cec237 100644 --- a/hardware/nexus-osciprime/protocol.h +++ b/hardware/nexus-osciprime/protocol.h @@ -46,6 +46,9 @@ struct dev_context { /** The current number of already received samples. */ uint64_t num_samples; + struct sr_usb_dev_inst *usb; + int usbfd[10]; + int64_t fw_updated; }; SR_PRIV int nexus_osciprime_receive_data(int fd, int revents, void *cb_data);