From: Joel Holdsworth Date: Thu, 15 Jun 2017 17:34:52 +0000 (-0600) Subject: fx2lafw: Moved all protocol handling to protocol.c X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=b0acb693f94d920887684eb9fdae77e036965975 fx2lafw: Moved all protocol handling to protocol.c Previously the USB communication code was split between api.c and protocol.c, with protocol internals split between both. This patch puts all the protocol handling code into one source file reducing the number of internal interfaces and making the code more readable. --- 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