+
+static int receive_data(int fd, int revents, void *cb_data)
+{
+ struct timeval tv;
+ struct drv_context *drvc;
+
+ (void)fd;
+ (void)revents;
+
+ drvc = (struct drv_context *)cb_data;
+
+ tv.tv_sec = tv.tv_usec = 0;
+ libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
+
+ return TRUE;
+}
+
+static int start_transfers(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ struct sr_usb_dev_inst *usb;
+ struct sr_trigger *trigger;
+ struct libusb_transfer *transfer;
+ unsigned int i, num_transfers;
+ int timeout, ret;
+ unsigned char *buf;
+ size_t size;
+
+ devc = sdi->priv;
+ usb = sdi->conn;
+
+ devc->sent_samples = 0;
+ devc->acq_aborted = FALSE;
+ devc->empty_transfer_count = 0;
+
+ if ((trigger = sr_session_trigger_get(sdi->session))) {
+ int pre_trigger_samples = 0;
+ if (devc->limit_samples > 0)
+ pre_trigger_samples = (devc->capture_ratio * devc->limit_samples) / 100;
+ devc->stl = soft_trigger_logic_new(sdi, trigger, pre_trigger_samples);
+ if (!devc->stl)
+ return SR_ERR_MALLOC;
+ devc->trigger_fired = FALSE;
+ } else
+ devc->trigger_fired = TRUE;
+
+ num_transfers = get_number_of_transfers(devc);
+
+ size = get_buffer_size(devc);
+ devc->submitted_transfers = 0;
+
+ devc->transfers = g_try_malloc0(sizeof(*devc->transfers) * num_transfers);
+ if (!devc->transfers) {
+ sr_err("USB transfers malloc failed.");
+ return SR_ERR_MALLOC;
+ }
+
+ timeout = get_timeout(devc);
+ devc->num_transfers = num_transfers;
+ for (i = 0; i < num_transfers; i++) {
+ if (!(buf = g_try_malloc(size))) {
+ sr_err("USB transfer buffer malloc failed.");
+ return SR_ERR_MALLOC;
+ }
+ transfer = libusb_alloc_transfer(0);
+ libusb_fill_bulk_transfer(transfer, usb->devhdl,
+ 2 | LIBUSB_ENDPOINT_IN, buf, size,
+ receive_transfer, (void *)sdi, timeout);
+ sr_info("submitting transfer: %d", i);
+ if ((ret = libusb_submit_transfer(transfer)) != 0) {
+ sr_err("Failed to submit transfer: %s.",
+ libusb_error_name(ret));
+ libusb_free_transfer(transfer);
+ g_free(buf);
+ fx2lafw_abort_acquisition(devc);
+ return SR_ERR;
+ }
+ devc->transfers[i] = transfer;
+ devc->submitted_transfers++;
+ }
+
+ /*
+ * 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);
+
+ return SR_OK;
+}
+
+SR_PRIV int fx2lafw_start_acquisition(const struct sr_dev_inst *sdi)
+{
+ struct sr_dev_driver *di;
+ struct drv_context *drvc;
+ struct dev_context *devc;
+ int timeout, ret;
+ size_t size;
+
+ di = sdi->driver;
+ drvc = di->context;
+ devc = sdi->priv;
+
+ devc->ctx = drvc->sr_ctx;
+ devc->sent_samples = 0;
+ devc->empty_transfer_count = 0;
+ devc->acq_aborted = FALSE;
+
+ if (configure_channels(sdi) != SR_OK) {
+ sr_err("Failed to configure channels.");
+ return SR_ERR;
+ }
+
+ timeout = get_timeout(devc);
+ usb_source_add(sdi->session, devc->ctx, timeout, receive_data, drvc);
+
+ size = get_buffer_size(devc);
+ /* Prepare for analog sampling. */
+ 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(
+ sizeof(float) * size / 2);
+ }
+ start_transfers(sdi);
+ if ((ret = command_start_acquisition(sdi)) != SR_OK) {
+ fx2lafw_abort_acquisition(devc);
+ return ret;
+ }
+
+ return SR_OK;
+}