X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Ffx2lafw%2Fapi.c;h=c3a819b459121966e9e7715d23358e439aff655e;hb=c33f32a9225dcc7cad0577e15d477645baf654cc;hp=262f3cd662ce2a3d6c32f52ac445780bc2ffdaf7;hpb=dd5c48a6d567a3cac62c4b0058588273bbeea171;p=libsigrok.git diff --git a/src/hardware/fx2lafw/api.c b/src/hardware/fx2lafw/api.c index 262f3cd6..c3a819b4 100644 --- a/src/hardware/fx2lafw/api.c +++ b/src/hardware/fx2lafw/api.c @@ -47,32 +47,57 @@ static const struct fx2lafw_profile supported_fx2[] = { "fx2lafw-cwav-usbeesx.fw", 0, NULL, NULL}, + /* + * CWAV USBee ZX + */ + { 0x08a9, 0x0005, "CWAV", "USBee ZX", NULL, + "fx2lafw-cwav-usbeezx.fw", + 0, NULL, NULL}, + /* DreamSourceLab DSLogic (before FW upload) */ { 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL, "dreamsourcelab-dslogic-fx2.fw", - DEV_CAPS_16BIT, NULL, NULL}, + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, NULL, NULL}, /* DreamSourceLab DSLogic (after FW upload) */ { 0x2a0e, 0x0001, "DreamSourceLab", "DSLogic", NULL, "dreamsourcelab-dslogic-fx2.fw", - DEV_CAPS_16BIT, "DreamSourceLab", "DSLogic"}, + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, "DreamSourceLab", "DSLogic"}, /* DreamSourceLab DSCope (before FW upload) */ { 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL, "dreamsourcelab-dscope-fx2.fw", - DEV_CAPS_16BIT, NULL, NULL}, + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, NULL, NULL}, /* DreamSourceLab DSCope (after FW upload) */ { 0x2a0e, 0x0002, "DreamSourceLab", "DSCope", NULL, "dreamsourcelab-dscope-fx2.fw", - DEV_CAPS_16BIT, "DreamSourceLab", "DSCope"}, + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, "DreamSourceLab", "DSCope"}, /* DreamSourceLab DSLogic Pro (before FW upload) */ { 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL, "dreamsourcelab-dslogic-pro-fx2.fw", - DEV_CAPS_16BIT, NULL, NULL}, + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, NULL, NULL}, /* DreamSourceLab DSLogic Pro (after FW upload) */ { 0x2a0e, 0x0003, "DreamSourceLab", "DSLogic Pro", NULL, "dreamsourcelab-dslogic-pro-fx2.fw", - DEV_CAPS_16BIT, "DreamSourceLab", "DSLogic"}, + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, "DreamSourceLab", "DSLogic"}, + + /* DreamSourceLab DSLogic Plus (before FW upload) */ + { 0x2a0e, 0x0020, "DreamSourceLab", "DSLogic Plus", NULL, + "dreamsourcelab-dslogic-plus-fx2.fw", + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, NULL, NULL}, + /* DreamSourceLab DSLogic Plus (after FW upload) */ + { 0x2a0e, 0x0020, "DreamSourceLab", "DSLogic Plus", NULL, + "dreamsourcelab-dslogic-plus-fx2.fw", + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, "DreamSourceLab", "DSLogic"}, + + /* DreamSourceLab DSLogic Basic (before FW upload) */ + { 0x2a0e, 0x0021, "DreamSourceLab", "DSLogic Basic", NULL, + "dreamsourcelab-dslogic-basic-fx2.fw", + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, NULL, NULL}, + /* DreamSourceLab DSLogic Basic (after FW upload) */ + { 0x2a0e, 0x0021, "DreamSourceLab", "DSLogic Basic", NULL, + "dreamsourcelab-dslogic-basic-fx2.fw", + DEV_CAPS_16BIT | DEV_CAPS_DSLOGIC_FW, "DreamSourceLab", "DSLogic"}, /* * Saleae Logic @@ -207,6 +232,20 @@ static const uint64_t dslogic_samplerates[] = { SR_MHZ(400), }; +static gboolean is_plausible(const struct libusb_device_descriptor *des) +{ + int i; + + for (i = 0; supported_fx2[i].vid; i++) { + if (des->idVendor != supported_fx2[i].vid) + continue; + if (des->idProduct == supported_fx2[i].pid) + return TRUE; + } + + return FALSE; +} + static GSList *scan(struct sr_dev_driver *di, GSList *options) { struct drv_context *drvc; @@ -264,9 +303,16 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) libusb_get_device_descriptor( devlist[i], &des); - if ((ret = libusb_open(devlist[i], &hdl)) < 0) + if (!is_plausible(&des)) continue; + if ((ret = libusb_open(devlist[i], &hdl)) < 0) { + sr_warn("Failed to open potential device with " + "VID:PID %04x:%04x: %s.", des.idVendor, + des.idProduct, libusb_error_name(ret)); + continue; + } + if (des.iManufacturer == 0) { manufacturer[0] = '\0'; } else if ((ret = libusb_get_string_descriptor_ascii(hdl, @@ -307,7 +353,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) des.idProduct == supported_fx2[j].pid && (!supported_fx2[j].usb_manufacturer || !strcmp(manufacturer, supported_fx2[j].usb_manufacturer)) && - (!supported_fx2[j].usb_manufacturer || + (!supported_fx2[j].usb_product || !strcmp(product, supported_fx2[j].usb_product))) { prof = &supported_fx2[j]; break; @@ -323,7 +369,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) sdi->vendor = g_strdup(prof->vendor); sdi->model = g_strdup(prof->model); sdi->version = g_strdup(prof->model_version); - sdi->driver = di; sdi->serial_num = g_strdup(serial_num); sdi->connection_id = g_strdup(connection_id); @@ -356,14 +401,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) devc = fx2lafw_dev_new(); devc->profile = prof; - if ((prof->dev_caps & DEV_CAPS_16BIT) || (prof->dev_caps & DEV_CAPS_AX_ANALOG)) - devc->sample_wide = TRUE; sdi->priv = devc; - drvc->instances = g_slist_append(drvc->instances, sdi); devices = g_slist_append(devices, sdi); if (!strcmp(prof->model, "DSLogic") || !strcmp(prof->model, "DSLogic Pro") + || !strcmp(prof->model, "DSLogic Plus") + || !strcmp(prof->model, "DSLogic Basic") || !strcmp(prof->model, "DSCope")) { devc->dslogic = TRUE; devc->samplerates = dslogic_samplerates; @@ -403,7 +447,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) libusb_free_device_list(devlist, 1); g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free); - return devices; + return std_scan_complete(di, devices); } static void clear_dev_context(void *priv) @@ -493,6 +537,10 @@ static int dev_open(struct sr_dev_inst *sdi) fpga_firmware = DSLOGIC_FPGA_FIRMWARE_5V; } else if (!strcmp(devc->profile->model, "DSLogic Pro")){ fpga_firmware = DSLOGIC_PRO_FPGA_FIRMWARE; + } else if (!strcmp(devc->profile->model, "DSLogic Plus")){ + fpga_firmware = DSLOGIC_PLUS_FPGA_FIRMWARE; + } else if (!strcmp(devc->profile->model, "DSLogic Basic")){ + fpga_firmware = DSLOGIC_BASIC_FPGA_FIRMWARE; } else if (!strcmp(devc->profile->model, "DSCope")) { fpga_firmware = DSCOPE_FPGA_FIRMWARE; } @@ -671,6 +719,10 @@ static int config_set(uint32_t key, GVariant *data, ret = dslogic_fpga_firmware_upload(sdi, DSLOGIC_FPGA_FIRMWARE_3V3); } else if (!strcmp(devc->profile->model, "DSLogic Pro")) { ret = dslogic_fpga_firmware_upload(sdi, DSLOGIC_PRO_FPGA_FIRMWARE); + } else if (!strcmp(devc->profile->model, "DSLogic Plus")) { + ret = dslogic_fpga_firmware_upload(sdi, DSLOGIC_PLUS_FPGA_FIRMWARE); + } else if (!strcmp(devc->profile->model, "DSLogic Basic")) { + ret = dslogic_fpga_firmware_upload(sdi, DSLOGIC_BASIC_FPGA_FIRMWARE); } break; case SR_CONF_EXTERNAL_CLOCK: @@ -685,7 +737,7 @@ static int config_set(uint32_t key, GVariant *data, if (i < 0) return SR_ERR_ARG; devc->dslogic_clock_edge = i; - break; + break; default: ret = SR_ERR_NA; } @@ -854,12 +906,17 @@ static int start_transfers(const struct sr_dev_inst *sdi) devc->submitted_transfers++; } - if (devc->profile->dev_caps & DEV_CAPS_AX_ANALOG) + /* + * If this device has analog channels and at least one of them is + * enabled, use mso_send_data_proc() to properly handle the analog + * data. Otherwise use la_send_data_proc(). + */ + if (g_slist_length(devc->enabled_analog_channels) > 0) devc->send_data_proc = mso_send_data_proc; else devc->send_data_proc = la_send_data_proc; - std_session_send_df_header(sdi, LOG_PREFIX); + std_session_send_df_header(sdi); return SR_OK; } @@ -875,7 +932,7 @@ static void LIBUSB_CALL dslogic_trigger_receive(struct libusb_transfer *transfer if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { sr_dbg("Trigger transfer canceled."); /* Terminate session. */ - std_session_send_df_end(sdi, LOG_PREFIX); + std_session_send_df_end(sdi); usb_source_remove(sdi->session, devc->ctx); devc->num_transfers = 0; g_free(devc->transfers); @@ -955,22 +1012,34 @@ static int configure_channels(const struct sr_dev_inst *sdi) const GSList *l; int p; struct sr_channel *ch; + uint32_t channel_mask = 0, num_analog = 0; devc = sdi->priv; g_slist_free(devc->enabled_analog_channels); devc->enabled_analog_channels = NULL; - memset(devc->ch_enabled, 0, sizeof(devc->ch_enabled)); for (l = sdi->channels, p = 0; l; l = l->next, p++) { ch = l->data; - if ((p <= NUM_CHANNELS) && (ch->type == SR_CHANNEL_ANALOG)) { - devc->ch_enabled[p] = ch->enabled; + if ((p <= NUM_CHANNELS) && (ch->type == SR_CHANNEL_ANALOG) + && (ch->enabled)) { + num_analog++; devc->enabled_analog_channels = g_slist_append(devc->enabled_analog_channels, ch); + } else { + channel_mask |= ch->enabled << p; } } + /* + * Use wide sampling if either any of the LA channels 8..15 is enabled, + * and/or at least one analog channel is enabled, and/or the device + * is running DSLogic firmware (not fx2lafw). + */ + devc->sample_wide = (channel_mask > 0xff + || num_analog > 0 + || (devc->profile->dev_caps & DEV_CAPS_DSLOGIC_FW)); + return SR_OK; } @@ -1007,7 +1076,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) } else { size = fx2lafw_get_buffer_size(devc); /* Prepare for analog sampling. */ - if (devc->profile->dev_caps & DEV_CAPS_AX_ANALOG) { + if (g_slist_length(devc->enabled_analog_channels) > 0) { /* We need a buffer half the size of a transfer. */ devc->logic_buffer = g_try_malloc(size / 2); devc->analog_buffer = g_try_malloc(