+ struct sr_datafeed_packet packet;
+ struct sr_datafeed_meta meta;
+ struct sr_config *src;
+ struct dev_context *devc;
+ struct drv_context *drvc;
+ struct sr_usb_dev_inst *usb;
+ struct libusb_transfer *xfer_in, *xfer_out;
+ const struct libusb_pollfd **pfd;
+ struct timeval tv;
+ uint64_t interval;
+ int ret, i;
+ unsigned char cmd[3], resp[4], *buf;
+
+ if (sdi->status != SR_ST_ACTIVE)
+ return SR_ERR_DEV_CLOSED;
+
+ if (!di->priv) {
+ sr_err("Driver was not initialized.");
+ return SR_ERR;
+ }
+
+ drvc = di->priv;
+ devc = sdi->priv;
+ usb = sdi->conn;
+ devc->cb_data = cb_data;
+
+ if (lascar_proc_config(sdi) != SR_OK)
+ return SR_ERR;
+
+ sr_dbg("Starting log retrieval.");
+
+ /* Send header packet to the session bus. */
+ std_session_send_df_header(cb_data, LOG_PREFIX);
+
+ interval = (devc->config[0x1c] | (devc->config[0x1d] << 8)) * 1000;
+ packet.type = SR_DF_META;
+ packet.payload = &meta;
+ src = sr_config_new(SR_CONF_SAMPLE_INTERVAL, g_variant_new_uint64(interval));
+ meta.config = g_slist_append(NULL, src);
+ sr_session_send(devc->cb_data, &packet);
+ g_free(src);
+
+ if (devc->logged_samples == 0) {
+ /* This ensures the frontend knows the session is done. */
+ packet.type = SR_DF_END;
+ sr_session_send(devc->cb_data, &packet);
+ return SR_OK;
+ }
+
+ if (!(xfer_in = libusb_alloc_transfer(0)) ||
+ !(xfer_out = libusb_alloc_transfer(0)))
+ return SR_ERR;
+
+ libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR,
+ 0x00, 0xffff, 0x00, NULL, 0, 50);
+ libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR,
+ 0x02, 0x0002, 0x00, NULL, 0, 50);
+ libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR,
+ 0x02, 0x0001, 0x00, NULL, 0, 50);
+
+
+ /* Flush input. The F321 requires this. */
+ while (libusb_bulk_transfer(usb->devhdl, LASCAR_EP_IN, resp,
+ 256, &ret, 5) == 0 && ret > 0)
+ ;
+
+ libusb_fill_bulk_transfer(xfer_in, usb->devhdl, LASCAR_EP_IN,
+ resp, sizeof(resp), mark_xfer, 0, 10000);
+ if (libusb_submit_transfer(xfer_in) != 0) {
+ libusb_free_transfer(xfer_in);
+ libusb_free_transfer(xfer_out);
+ return SR_ERR;
+ }
+
+ cmd[0] = 0x03;
+ cmd[1] = 0xff;
+ cmd[2] = 0xff;
+ libusb_fill_bulk_transfer(xfer_out, usb->devhdl, LASCAR_EP_OUT,
+ cmd, 3, mark_xfer, 0, 100);
+ if (libusb_submit_transfer(xfer_out) != 0) {
+ libusb_free_transfer(xfer_in);
+ libusb_free_transfer(xfer_out);
+ return SR_ERR;
+ }
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ while (!xfer_in->user_data || !xfer_out->user_data) {
+ g_usleep(5000);
+ libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
+ }
+ if (xfer_in->user_data != GINT_TO_POINTER(1) ||
+ xfer_in->user_data != GINT_TO_POINTER(1)) {
+ sr_dbg("no response to log transfer request");
+ libusb_free_transfer(xfer_in);
+ libusb_free_transfer(xfer_out);
+ return SR_ERR;
+ }
+ if (xfer_in->actual_length != 3 || xfer_in->buffer[0] != 2) {
+ sr_dbg("invalid response to log transfer request");
+ libusb_free_transfer(xfer_in);
+ libusb_free_transfer(xfer_out);
+ return SR_ERR;
+ }
+ devc->log_size = xfer_in->buffer[1] + (xfer_in->buffer[2] << 8);
+ libusb_free_transfer(xfer_out);
+
+ pfd = libusb_get_pollfds(drvc->sr_ctx->libusb_ctx);
+ for (i = 0; pfd[i]; i++) {
+ /* Handle USB events every 100ms, for decent latency. */
+ sr_source_add(pfd[i]->fd, pfd[i]->events, 100,
+ lascar_el_usb_handle_events, (void *)sdi);
+ /* We'll need to remove this fd later. */
+ devc->usbfd[i] = pfd[i]->fd;
+ }
+ devc->usbfd[i] = -1;
+
+ buf = g_try_malloc(4096);
+ libusb_fill_bulk_transfer(xfer_in, usb->devhdl, LASCAR_EP_IN,
+ buf, 4096, lascar_el_usb_receive_transfer, cb_data, 100);
+ if ((ret = libusb_submit_transfer(xfer_in) != 0)) {
+ sr_err("Unable to submit transfer: %s.", libusb_error_name(ret));
+ libusb_free_transfer(xfer_in);
+ g_free(buf);
+ return SR_ERR;
+ }