]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/hantek-4032l/protocol.c
hantek-4032l: Emit FPGA version log message.
[libsigrok.git] / src / hardware / hantek-4032l / protocol.c
index 7b0a5798bbb27cfe72ca98445a8c39d3e8d4cc18..fb18e8978a47cd0269a21bcda0851261361f762d 100644 (file)
 #define H4032L_USB_TIMEOUT 500
 
 enum h4032l_cmd {
-       CMD_CONFIGURE = 0x2b1a, /* Also arms the logic analyzer. */
+       CMD_RESET = 0x00b3, /* Also arms the logic analyzer. */
+       CMD_CONFIGURE = 0x2b1a,
        CMD_STATUS = 0x4b3a,
        CMD_GET = 0x6b5a
 };
 
-struct __attribute__((__packed__)) h4032l_status_packet {
+struct h4032l_status_packet {
        uint32_t magic;
        uint32_t values;
        uint32_t status;
+       uint32_t usbxi_data;
+       uint32_t fpga_version;
 };
 
+static void finish_acquisition(struct sr_dev_inst *sdi)
+{
+       struct drv_context *drvc = sdi->driver->context;
+
+       std_session_send_df_end(sdi);
+       usb_source_remove(sdi->session, drvc->sr_ctx);
+}
+
+static void free_transfer(struct libusb_transfer *transfer)
+{
+       struct sr_dev_inst *sdi = transfer->user_data;
+       struct dev_context *devc = sdi->priv;
+
+       transfer->buffer = NULL;
+       libusb_free_transfer(transfer);
+       devc->usb_transfer = NULL;
+
+       finish_acquisition(sdi);
+}
+
 SR_PRIV int h4032l_receive_data(int fd, int revents, void *cb_data)
 {
        struct timeval tv;
@@ -67,11 +90,18 @@ void LIBUSB_CALL h4032l_usb_callback(struct libusb_transfer *transfer)
        uint32_t number_samples;
        int ret;
 
-       if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
-               sr_err("%s error: %d.", __func__, transfer->status);
+       /*
+        * If acquisition has already ended, just free any queued up
+        * transfers that come in.
+        */
+       if (devc->acq_aborted) {
+               free_transfer(transfer);
                return;
        }
 
+       if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
+               sr_dbg("%s error: %d.", __func__, transfer->status);
+
        buffer = (uint32_t *)transfer->buffer;
 
        switch (devc->status) {
@@ -94,10 +124,9 @@ void LIBUSB_CALL h4032l_usb_callback(struct libusb_transfer *transfer)
                 * First Transfer as next.
                 */
                status = (struct h4032l_status_packet *)transfer->buffer;
+               sr_dbg("FPGA version: 0x%x.", status->fpga_version);
                if (status->magic != H4032L_STATUS_PACKET_MAGIC) {
-                       devc->status = H4032L_STATUS_CMD_STATUS;
-                       devc->cmd_pkt.cmd = CMD_STATUS;
-                       cmd = TRUE;
+                       devc->status = H4032L_STATUS_RESPONSE_STATUS;
                } else if (status->status == 2) {
                        devc->status = H4032L_STATUS_RESPONSE_STATUS_CONTINUE;
                } else {
@@ -118,9 +147,9 @@ void LIBUSB_CALL h4032l_usb_callback(struct libusb_transfer *transfer)
                devc->status = H4032L_STATUS_FIRST_TRANSFER;
                break;
        case H4032L_STATUS_FIRST_TRANSFER:
+               /* Drop packets until H4032L_START_PACKET_MAGIC. */
                if (buffer[0] != H4032L_START_PACKET_MAGIC) {
-                       sr_err("Mismatch magic number of start poll.");
-                       devc->status = H4032L_STATUS_IDLE;
+                       sr_dbg("Mismatch magic number of start poll.");
                        break;
                }
                devc->status = H4032L_STATUS_TRANSFER;
@@ -178,7 +207,7 @@ void LIBUSB_CALL h4032l_usb_callback(struct libusb_transfer *transfer)
        }
 
        if (devc->status == H4032L_STATUS_IDLE)
-               libusb_free_transfer(transfer);
+               free_transfer(transfer);
 }
 
 uint16_t h4032l_voltage2pwm(double voltage)
@@ -209,9 +238,21 @@ SR_PRIV int h4032l_start(const struct sr_dev_inst *sdi)
        struct dev_context *devc = sdi->priv;
        struct sr_usb_dev_inst *usb = sdi->conn;
        struct libusb_transfer *transfer;
+       unsigned char buffer[] = {0x0f, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
        int ret;
 
-       /* Send configure command to arm the logic analyzer. */
+       /* Send reset command to arm the logic analyzer. */
+       if ((ret = libusb_control_transfer(usb->devhdl,
+               LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_RESET,
+               0x00, 0x00, buffer, ARRAY_SIZE(buffer), H4032L_USB_TIMEOUT)) < 0) {
+               sr_err("Failed to send vendor request %s.", libusb_error_name(ret));
+               return SR_ERR;
+       }
+
+       /* Wait for reset vendor request. */
+       g_usleep(20 * 1000);
+
+       /* Send configure command. */
        devc->cmd_pkt.cmd = CMD_CONFIGURE;
        devc->status = H4032L_STATUS_CMD_CONFIGURE;
        devc->remaining_samples = devc->cmd_pkt.sample_size;