diff --git a/src/hardware/fx2lafw/api.c b/src/hardware/fx2lafw/api.c index b6e708b9..6c7d776f 100644 --- a/src/hardware/fx2lafw/api.c +++ b/src/hardware/fx2lafw/api.c @@ -581,180 +581,6 @@ static int config_list(uint32_t key, GVariant **data, return SR_OK; } -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 = fx2lafw_get_number_of_transfers(devc); - - size = fx2lafw_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 = fx2lafw_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, - fx2lafw_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; -} - -static int configure_channels(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - 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; - - for (l = sdi->channels, p = 0; l; l = l->next, p++) { - ch = l->data; - 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. - */ - devc->sample_wide = channel_mask > 0xff || num_analog > 0; - - return SR_OK; -} - -static int dev_acquisition_start(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; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - 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 = fx2lafw_get_timeout(devc); - usb_source_add(sdi->session, devc->ctx, timeout, receive_data, drvc); - - size = fx2lafw_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 = fx2lafw_command_start_acquisition(sdi)) != SR_OK) { - fx2lafw_abort_acquisition(devc); - return ret; - } - - return SR_OK; -} - static int dev_acquisition_stop(struct sr_dev_inst *sdi) { fx2lafw_abort_acquisition(sdi->priv); @@ -776,7 +602,7 @@ static struct sr_dev_driver fx2lafw_driver_info = { .config_list = config_list, .dev_open = dev_open, .dev_close = dev_close, - .dev_acquisition_start = dev_acquisition_start, + .dev_acquisition_start = fx2lafw_start_acquisition, .dev_acquisition_stop = dev_acquisition_stop, .context = NULL, }; diff --git a/src/hardware/fx2lafw/protocol.c b/src/hardware/fx2lafw/protocol.c index 9ca749a5..95ce4bd3 100644 --- a/src/hardware/fx2lafw/protocol.c +++ b/src/hardware/fx2lafw/protocol.c @@ -76,7 +76,7 @@ static int command_get_revid_version(struct sr_dev_inst *sdi, uint8_t *revid) return SR_OK; } -SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi) +static int command_start_acquisition(const struct sr_dev_inst *sdi) { struct dev_context *devc; struct sr_usb_dev_inst *usb; @@ -340,7 +340,7 @@ static void resubmit_transfer(struct libusb_transfer *transfer) } -SR_PRIV void mso_send_data_proc(struct sr_dev_inst *sdi, +static void mso_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, size_t length, size_t sample_width) { size_t i; @@ -392,7 +392,7 @@ SR_PRIV void mso_send_data_proc(struct sr_dev_inst *sdi, sr_session_send(sdi, &analog_packet); } -SR_PRIV void la_send_data_proc(struct sr_dev_inst *sdi, +static void la_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, size_t length, size_t sample_width) { const struct sr_datafeed_logic logic = { @@ -409,7 +409,7 @@ SR_PRIV void la_send_data_proc(struct sr_dev_inst *sdi, sr_session_send(sdi, &packet); } -SR_PRIV void LIBUSB_CALL fx2lafw_receive_transfer(struct libusb_transfer *transfer) +static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) { struct sr_dev_inst *sdi; struct dev_context *devc; @@ -504,12 +504,46 @@ SR_PRIV void LIBUSB_CALL fx2lafw_receive_transfer(struct libusb_transfer *transf resubmit_transfer(transfer); } +static int configure_channels(const struct sr_dev_inst *sdi) +{ + struct dev_context *devc; + 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; + + for (l = sdi->channels, p = 0; l; l = l->next, p++) { + ch = l->data; + 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. + */ + devc->sample_wide = channel_mask > 0xff || num_analog > 0; + + return SR_OK; +} + static unsigned int to_bytes_per_ms(unsigned int samplerate) { return samplerate / 1000; } -SR_PRIV size_t fx2lafw_get_buffer_size(struct dev_context *devc) +static size_t get_buffer_size(struct dev_context *devc) { size_t s; @@ -521,13 +555,13 @@ SR_PRIV size_t fx2lafw_get_buffer_size(struct dev_context *devc) return (s + 511) & ~511; } -SR_PRIV unsigned int fx2lafw_get_number_of_transfers(struct dev_context *devc) +static unsigned int get_number_of_transfers(struct dev_context *devc) { unsigned int n; /* Total buffer size should be able to hold about 500ms of data. */ n = (500 * to_bytes_per_ms(devc->cur_samplerate) / - fx2lafw_get_buffer_size(devc)); + get_buffer_size(devc)); if (n > NUM_SIMUL_TRANSFERS) return NUM_SIMUL_TRANSFERS; @@ -535,13 +569,153 @@ SR_PRIV unsigned int fx2lafw_get_number_of_transfers(struct dev_context *devc) return n; } -SR_PRIV unsigned int fx2lafw_get_timeout(struct dev_context *devc) +static unsigned int get_timeout(struct dev_context *devc) { size_t total_size; unsigned int timeout; - total_size = fx2lafw_get_buffer_size(devc) * - fx2lafw_get_number_of_transfers(devc); + total_size = get_buffer_size(devc) * + get_number_of_transfers(devc); timeout = total_size / to_bytes_per_ms(devc->cur_samplerate); return timeout + timeout / 4; /* Leave a headroom of 25% percent. */ } + +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; + + if (sdi->status != SR_ST_ACTIVE) + return SR_ERR_DEV_CLOSED; + + 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; +} diff --git a/src/hardware/fx2lafw/protocol.h b/src/hardware/fx2lafw/protocol.h index a18696c6..f5ef67c9 100644 --- a/src/hardware/fx2lafw/protocol.h +++ b/src/hardware/fx2lafw/protocol.h @@ -126,17 +126,9 @@ struct dev_context { float *analog_buffer; }; -SR_PRIV int fx2lafw_command_start_acquisition(const struct sr_dev_inst *sdi); SR_PRIV int fx2lafw_dev_open(struct sr_dev_inst *sdi, struct sr_dev_driver *di); SR_PRIV struct dev_context *fx2lafw_dev_new(void); +SR_PRIV int fx2lafw_start_acquisition(const struct sr_dev_inst *sdi); SR_PRIV void fx2lafw_abort_acquisition(struct dev_context *devc); -SR_PRIV void LIBUSB_CALL fx2lafw_receive_transfer(struct libusb_transfer *transfer); -SR_PRIV size_t fx2lafw_get_buffer_size(struct dev_context *devc); -SR_PRIV unsigned int fx2lafw_get_number_of_transfers(struct dev_context *devc); -SR_PRIV unsigned int fx2lafw_get_timeout(struct dev_context *devc); -SR_PRIV void la_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, - size_t length, size_t sample_width); -SR_PRIV void mso_send_data_proc(struct sr_dev_inst *sdi, uint8_t *data, - size_t length, size_t sample_width); #endif