]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/fx2lafw/protocol.c
fx2lafw: Replace obsoleted strncmp() calls.
[libsigrok.git] / src / hardware / fx2lafw / protocol.c
index 433f9075c03c2d9cf804ec8d02962ebfef28e466..fae80b72171df38fa02e30325a2841f856ef98e7 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <glib.h>
+#include <glib/gstdio.h>
 #include "protocol.h"
-
-/* Protocol commands */
-#define CMD_GET_FW_VERSION             0xb0
-#define CMD_START                      0xb1
-#define CMD_GET_REVID_VERSION          0xb2
-
-#define CMD_START_FLAGS_WIDE_POS       5
-#define CMD_START_FLAGS_CLK_SRC_POS    6
-
-#define CMD_START_FLAGS_SAMPLE_8BIT    (0 << CMD_START_FLAGS_WIDE_POS)
-#define CMD_START_FLAGS_SAMPLE_16BIT   (1 << CMD_START_FLAGS_WIDE_POS)
-
-#define CMD_START_FLAGS_CLK_30MHZ      (0 << CMD_START_FLAGS_CLK_SRC_POS)
-#define CMD_START_FLAGS_CLK_48MHZ      (1 << CMD_START_FLAGS_CLK_SRC_POS)
+#include "dslogic.h"
 
 #pragma pack(push, 1)
 
@@ -69,13 +58,14 @@ static int command_get_fw_version(libusb_device_handle *devhdl,
 
 static int command_get_revid_version(struct sr_dev_inst *sdi, uint8_t *revid)
 {
+       struct dev_context *devc = sdi->priv;
        struct sr_usb_dev_inst *usb = sdi->conn;
        libusb_device_handle *devhdl = usb->devhdl;
-       int ret;
+       int cmd, ret;
 
+       cmd = devc->dslogic ? DS_CMD_GET_REVID_VERSION : CMD_GET_REVID_VERSION;
        ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
-               LIBUSB_ENDPOINT_IN, CMD_GET_REVID_VERSION, 0x0000, 0x0000,
-               revid, 1, 100);
+               LIBUSB_ENDPOINT_IN, cmd, 0x0000, 0x0000, revid, 1, 100);
 
        if (ret < 0) {
                sr_err("Unable to get REVID: %s.", libusb_error_name(ret));
@@ -87,21 +77,25 @@ static int command_get_revid_version(struct sr_dev_inst *sdi, uint8_t *revid)
 
 SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi)
 {
-       struct dev_context *devc = sdi->priv;
-       struct sr_usb_dev_inst *usb = sdi->conn;
-       libusb_device_handle *devhdl = usb->devhdl;
-       uint64_t samplerate = devc->cur_samplerate;
-       gboolean samplewide = devc->sample_wide;
-       struct cmd_start_acquisition cmd = { 0 };
-       int delay = 0, ret;
+       struct dev_context *devc;
+       struct sr_usb_dev_inst *usb;
+       uint64_t samplerate;
+       struct cmd_start_acquisition cmd;
+       int delay, ret;
+
+       devc = sdi->priv;
+       usb = sdi->conn;
+       samplerate = devc->cur_samplerate;
 
        /* Compute the sample rate. */
-       if (samplewide && samplerate > MAX_16BIT_SAMPLE_RATE) {
+       if (devc->sample_wide && samplerate > MAX_16BIT_SAMPLE_RATE) {
                sr_err("Unable to sample at %" PRIu64 "Hz "
                       "when collecting 16-bit samples.", samplerate);
                return SR_ERR;
        }
 
+       delay = 0;
+       cmd.flags = cmd.sample_delay_h = cmd.sample_delay_l = 0;
        if ((SR_MHZ(48) % samplerate) == 0) {
                cmd.flags = CMD_START_FLAGS_CLK_48MHZ;
                delay = SR_MHZ(48) / samplerate - 1;
@@ -114,7 +108,7 @@ SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi)
                delay = SR_MHZ(30) / samplerate - 1;
        }
 
-       sr_info("GPIF delay = %d, clocksource = %sMHz.", delay,
+       sr_dbg("GPIF delay = %d, clocksource = %sMHz.", delay,
                (cmd.flags & CMD_START_FLAGS_CLK_48MHZ) ? "48" : "30");
 
        if (delay <= 0 || delay > MAX_SAMPLE_DELAY) {
@@ -126,11 +120,11 @@ SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi)
        cmd.sample_delay_l = delay & 0xff;
 
        /* Select the sampling width. */
-       cmd.flags |= samplewide ? CMD_START_FLAGS_SAMPLE_16BIT :
+       cmd.flags |= devc->sample_wide ? CMD_START_FLAGS_SAMPLE_16BIT :
                CMD_START_FLAGS_SAMPLE_8BIT;
 
        /* Send the control message. */
-       ret = libusb_control_transfer(devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
+       ret = libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
                        LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
                        (unsigned char *)&cmd, sizeof(cmd), 100);
        if (ret < 0) {
@@ -145,10 +139,11 @@ SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi)
 /**
  * Check the USB configuration to determine if this is an fx2lafw device.
  *
- * @return TRUE if the device's configuration profile match fx2lafw
+ * @return TRUE if the device's configuration profile matches fx2lafw
  *         configuration, FALSE otherwise.
  */
-SR_PRIV gboolean fx2lafw_check_conf_profile(libusb_device *dev)
+SR_PRIV gboolean match_manuf_prod(libusb_device *dev, const char *manufacturer,
+               const char *product)
 {
        struct libusb_device_descriptor des;
        struct libusb_device_handle *hdl;
@@ -166,18 +161,17 @@ SR_PRIV gboolean fx2lafw_check_conf_profile(libusb_device *dev)
                        break;
 
                if (libusb_get_string_descriptor_ascii(hdl,
-                   des.iManufacturer, strdesc, sizeof(strdesc)) < 0)
+                               des.iManufacturer, strdesc, sizeof(strdesc)) < 0)
                        break;
-               if (strncmp((const char *)strdesc, "sigrok", 6))
+               if (strcmp((const char *)strdesc, manufacturer))
                        break;
 
                if (libusb_get_string_descriptor_ascii(hdl,
                                des.iProduct, strdesc, sizeof(strdesc)) < 0)
                        break;
-               if (strncmp((const char *)strdesc, "fx2lafw", 7))
+               if (strcmp((const char *)strdesc, product))
                        break;
 
-               /* If we made it here, it must be an fx2lafw. */
                ret = TRUE;
        }
        if (hdl)
@@ -194,8 +188,9 @@ SR_PRIV int fx2lafw_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
        struct dev_context *devc;
        struct drv_context *drvc;
        struct version_info vi;
-       int ret, skip, i, device_count;
+       int ret, i, device_count;
        uint8_t revid;
+       char connection_id[64];
 
        drvc = di->priv;
        devc = sdi->priv;
@@ -205,7 +200,6 @@ SR_PRIV int fx2lafw_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
                /* Device is already in use. */
                return SR_ERR;
 
-       skip = 0;
        device_count = libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist);
        if (device_count < 0) {
                sr_err("Failed to get device list: %s.",
@@ -224,19 +218,13 @@ SR_PRIV int fx2lafw_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
                    || des.idProduct != devc->profile->pid)
                        continue;
 
-               if (sdi->status == SR_ST_INITIALIZING) {
-                       if (skip != sdi->index) {
-                               /* Skip devices of this type that aren't the one we want. */
-                               skip += 1;
-                               continue;
-                       }
-               } else if (sdi->status == SR_ST_INACTIVE) {
+               if ((sdi->status == SR_ST_INITIALIZING) ||
+                               (sdi->status == SR_ST_INACTIVE)) {
                        /*
-                        * This device is fully enumerated, so we need to find
-                        * this device by vendor, product, bus and address.
+                        * Check device by its physical USB bus/port address.
                         */
-                       if (libusb_get_bus_number(devlist[i]) != usb->bus
-                               || libusb_get_device_address(devlist[i]) != usb->address)
+                       usb_get_port_path(devlist[i], connection_id, sizeof(connection_id));
+                       if (strcmp(sdi->connection_id, connection_id))
                                /* This is not the one. */
                                continue;
                }
@@ -279,9 +267,9 @@ SR_PRIV int fx2lafw_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di)
                }
 
                sdi->status = SR_ST_ACTIVE;
-               sr_info("Opened device %d on %d.%d, "
+               sr_info("Opened device on %d.%d (logical) / %s (physical), "
                        "interface %d, firmware %d.%d.",
-                       sdi->index, usb->bus, usb->address,
+                       usb->bus, usb->address, connection_id,
                        USB_INTERFACE, vi.major, vi.minor);
 
                sr_info("Detected REVID=%d, it's a Cypress CY7C68013%s.",
@@ -301,15 +289,12 @@ SR_PRIV struct dev_context *fx2lafw_dev_new(void)
 {
        struct dev_context *devc;
 
-       if (!(devc = g_try_malloc(sizeof(struct dev_context)))) {
-               sr_err("Device context malloc failed.");
-               return NULL;
-       }
-
+       devc = g_malloc0(sizeof(struct dev_context));
        devc->profile = NULL;
        devc->fw_updated = 0;
        devc->cur_samplerate = 0;
        devc->limit_samples = 0;
+       devc->capture_ratio = 0;
        devc->sample_wide = FALSE;
        devc->stl = NULL;
 
@@ -397,6 +382,7 @@ SR_PRIV void fx2lafw_receive_transfer(struct libusb_transfer *transfer)
        struct sr_datafeed_logic logic;
        unsigned int num_samples;
        int trigger_offset, cur_sample_count, unitsize;
+       int pre_trigger_samples;
 
        sdi = transfer->user_data;
        devc = sdi->priv;
@@ -410,7 +396,7 @@ SR_PRIV void fx2lafw_receive_transfer(struct libusb_transfer *transfer)
                return;
        }
 
-       sr_info("receive_transfer(): status %d received %d bytes.",
+       sr_dbg("receive_transfer(): status %d received %d bytes.",
                transfer->status, transfer->actual_length);
 
        /* Save incoming transfer before reusing the transfer struct. */
@@ -448,11 +434,11 @@ SR_PRIV void fx2lafw_receive_transfer(struct libusb_transfer *transfer)
        }
 
        if (devc->trigger_fired) {
-               if (devc->sent_samples < devc->limit_samples) {
+               if (!devc->limit_samples || devc->sent_samples < devc->limit_samples) {
                        /* Send the incoming transfer to the session bus. */
                        packet.type = SR_DF_LOGIC;
                        packet.payload = &logic;
-                       if (devc->sent_samples + cur_sample_count > devc->limit_samples)
+                       if (devc->limit_samples && devc->sent_samples + cur_sample_count > devc->limit_samples)
                                num_samples = devc->limit_samples - devc->sent_samples;
                        else
                                num_samples = cur_sample_count;
@@ -464,8 +450,9 @@ SR_PRIV void fx2lafw_receive_transfer(struct libusb_transfer *transfer)
                }
        } else {
                trigger_offset = soft_trigger_logic_check(devc->stl,
-                               transfer->buffer, transfer->actual_length);
+                       transfer->buffer, transfer->actual_length, &pre_trigger_samples);
                if (trigger_offset > -1) {
+                       devc->sent_samples += pre_trigger_samples;
                        packet.type = SR_DF_LOGIC;
                        packet.payload = &logic;
                        num_samples = cur_sample_count - trigger_offset;