X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fsaleae-logic-pro%2Fapi.c;h=9c257d2c6060d28f7664a04ed66b1988768ce128;hb=e66d1892d0dd16ed166fc8f13493f95de0607362;hp=74bf7ccec57dc839fd09920b70d8a6f2e9d95088;hpb=b6189f7c8af7d8eed6bdcf75fa05c95d8120c9b8;p=libsigrok.git diff --git a/src/hardware/saleae-logic-pro/api.c b/src/hardware/saleae-logic-pro/api.c index 74bf7cce..9c257d2c 100644 --- a/src/hardware/saleae-logic-pro/api.c +++ b/src/hardware/saleae-logic-pro/api.c @@ -22,9 +22,9 @@ #include #include "protocol.h" -#define BUF_COUNT (8) -#define BUF_SIZE (16*1024) -#define BUF_TIMEOUT (1000*1000) +#define BUF_COUNT 512 +#define BUF_SIZE (16 * 1024) +#define BUF_TIMEOUT 1000 SR_PRIV struct sr_dev_driver saleae_logic_pro_driver_info; @@ -56,6 +56,78 @@ static const uint64_t samplerates[] = { SR_MHZ(50), }; +#define FW_HEADER_SIZE 7 +#define FW_MAX_PART_SIZE (4 * 1024) + +static int upload_firmware(struct sr_context *ctx, libusb_device *dev, const char *name) +{ + struct libusb_device_handle *hdl = NULL; + unsigned char *firmware = NULL; + int ret = SR_ERR; + size_t fw_size, fw_offset = 0; + uint32_t part_address = 0; + uint16_t part_size = 0; + uint8_t part_final = 0; + + firmware = sr_resource_load(ctx, SR_RESOURCE_FIRMWARE, + name, &fw_size, 256 * 1024); + if (!firmware) + goto out; + + sr_info("Uploading firmware '%s'.", name); + + if (libusb_open(dev, &hdl) != 0) + goto out; + + while ((fw_offset + FW_HEADER_SIZE) <= fw_size) { + part_size = GUINT16_FROM_LE(*(uint16_t*)(firmware + fw_offset)); + part_address = GUINT32_FROM_LE(*(uint32_t*)(firmware + fw_offset + 2)); + part_final = *(uint8_t*)(firmware + fw_offset + 6); + if (part_size > FW_MAX_PART_SIZE) { + sr_err("Part too large (%d).", part_size); + goto out; + } + fw_offset += FW_HEADER_SIZE; + if ((fw_offset + part_size) > fw_size) { + sr_err("Truncated firmware file."); + goto out; + } + ret = libusb_control_transfer(hdl, LIBUSB_REQUEST_TYPE_VENDOR | + LIBUSB_ENDPOINT_OUT, 0xa0, + part_address & 0xffff, part_address >> 16, + firmware + fw_offset, part_size, + 100); + if (ret < 0) { + sr_err("Unable to send firmware to device: %s.", + libusb_error_name(ret)); + ret = SR_ERR; + goto out; + } + if (part_size) + sr_spew("Uploaded %d bytes.", part_size); + else + sr_info("Started firmware at 0x%x.", part_address); + fw_offset += part_size; + } + + if ((!part_final) || (part_size != 0)) { + sr_err("Missing final part."); + goto out; + } + + ret = SR_OK; + + sr_info("Firmware upload done."); + + out: + if (hdl) + libusb_close(hdl); + + g_free(firmware); + + return ret; +} + static gboolean scan_firmware(libusb_device *dev) { struct libusb_device_descriptor des; @@ -102,8 +174,10 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) struct libusb_device_descriptor des; const char *conn; char connection_id[64]; + gboolean fw_loaded = FALSE; devices = NULL; + conn_devices = NULL; drvc = di->context; drvc->instances = NULL; @@ -118,14 +192,34 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) } } + libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); + for (unsigned int i = 0; devlist[i]; i++) { + libusb_get_device_descriptor(devlist[i], &des); + + if (des.idVendor != 0x21a9 || des.idProduct != 0x1006) + continue; + + if (!scan_firmware(devlist[i])) { + sr_info("Found a Logic Pro 16 device (no firmware loaded)."); + if (upload_firmware(drvc->sr_ctx, devlist[i], + "saleae-logicpro16-fx3.fw") != SR_OK) { + sr_err("Firmware upload failed."); + continue; + }; + fw_loaded = TRUE; + } + + } + if (fw_loaded) { + /* Give the device some time to come back and scan again */ + libusb_free_device_list(devlist, 1); + g_usleep(500 * 1000); + libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); + } if (conn) conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn); - else - conn_devices = NULL; - - libusb_get_device_list(drvc->sr_ctx->libusb_ctx, &devlist); for (unsigned int i = 0; devlist[i]; i++) { - if (conn) { + if (conn_devices) { struct sr_usb_dev_inst *usb = NULL; GSList *l; @@ -143,15 +237,10 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) libusb_get_device_descriptor(devlist[i], &des); - usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)); - if (des.idVendor != 0x21a9 || des.idProduct != 0x1006) continue; - if (!scan_firmware(devlist[i])) { - sr_err("Found a Logic Pro device, but firmware is not loaded (use Saleae application)."); - continue; - } + usb_get_port_path(devlist[i], connection_id, sizeof(connection_id)); sdi = g_malloc0(sizeof(struct sr_dev_inst)); sdi->status = SR_ST_INITIALIZING; @@ -174,17 +263,12 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) devices = g_slist_append(devices, sdi); } - libusb_free_device_list(devlist, 1); g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free); + libusb_free_device_list(devlist, 1); return std_scan_complete(di, devices); } -static int dev_clear(const struct sr_dev_driver *di) -{ - return std_dev_clear(di, NULL); -} - static int dev_open(struct sr_dev_inst *sdi) { struct sr_dev_driver *di = sdi->driver; @@ -201,22 +285,16 @@ static int dev_open(struct sr_dev_inst *sdi) return SR_ERR; } - /* configure default samplerate */ + /* Configure default samplerate. */ if (devc->dig_samplerate == 0) devc->dig_samplerate = samplerates[3]; - sdi->status = SR_ST_ACTIVE; - - return SR_OK; + return saleae_logic_pro_init(sdi); } static int dev_close(struct sr_dev_inst *sdi) { - struct sr_usb_dev_inst *usb = sdi->conn; - - sr_usb_close(usb); - - sdi->status = SR_ST_INACTIVE; + sr_usb_close(sdi->conn); return SR_OK; } @@ -226,11 +304,9 @@ static int config_get(uint32_t key, GVariant **data, { struct sr_usb_dev_inst *usb; struct dev_context *devc; - int ret; (void)cg; - ret = SR_OK; switch (key) { case SR_CONF_CONN: if (!sdi || !sdi->conn) @@ -248,31 +324,27 @@ static int config_get(uint32_t key, GVariant **data, return SR_ERR_NA; } - return ret; + return SR_OK; } static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; - int ret; (void)cg; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; devc = sdi->priv; - ret = SR_OK; switch (key) { case SR_CONF_SAMPLERATE: devc->dig_samplerate = g_variant_get_uint64(data); break; default: - ret = SR_ERR_NA; + return SR_ERR_NA; } - return ret; + return SR_OK; } static int config_list(uint32_t key, GVariant **data, @@ -280,32 +352,11 @@ static int config_list(uint32_t key, GVariant **data, { GVariant *gvar; GVariantBuilder gvb; - int ret; - - (void)sdi; - (void)cg; - ret = SR_OK; switch (key) { case SR_CONF_SCAN_OPTIONS: - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - scanopts, - ARRAY_SIZE(scanopts), - sizeof(uint32_t)); - break; case SR_CONF_DEVICE_OPTIONS: - if (!sdi) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - drvopts, - ARRAY_SIZE(drvopts), - sizeof(uint32_t)); - } else { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - devopts, - ARRAY_SIZE(devopts), - sizeof(uint32_t)); - } - break; + return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts); case SR_CONF_SAMPLERATE: g_variant_builder_init(&gvb, G_VARIANT_TYPE("a{sv}")); gvar = g_variant_new_fixed_array(G_VARIANT_TYPE("t"), @@ -317,7 +368,7 @@ static int config_list(uint32_t key, GVariant **data, return SR_ERR_NA; } - return ret; + return SR_OK; } static void dev_acquisition_abort(const struct sr_dev_inst *sdi) @@ -335,13 +386,16 @@ static int dev_acquisition_handle(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi = cb_data; struct drv_context *drvc = sdi->driver->context; - struct timeval tv = {}; + struct timeval tv = ALL_ZERO; (void)fd; - (void)revents; libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv); + /* Handle timeout */ + if (!revents) + sr_dev_acquisition_stop(sdi); + return TRUE; } @@ -354,13 +408,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) uint8_t *buf; unsigned int i, ret; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - - ret = saleae_logic_pro_init(sdi); - if (ret != SR_OK) - return ret; - ret = saleae_logic_pro_prepare(sdi); if (ret != SR_OK) return ret; @@ -375,8 +422,8 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) buf = g_malloc(BUF_SIZE); transfer = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(transfer, usb->devhdl, - 2 | LIBUSB_ENDPOINT_IN, buf, BUF_SIZE, - saleae_logic_pro_receive_data, (void *)sdi, BUF_TIMEOUT); + 2 | LIBUSB_ENDPOINT_IN, buf, BUF_SIZE, + saleae_logic_pro_receive_data, (void *)sdi, 0); if ((ret = libusb_submit_transfer(transfer)) != 0) { sr_err("Failed to submit transfer: %s.", libusb_error_name(ret)); @@ -405,9 +452,6 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi) struct dev_context *devc = sdi->priv; struct drv_context *drvc = sdi->driver->context; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - saleae_logic_pro_stop(sdi); std_session_send_df_end(sdi); @@ -427,7 +471,7 @@ SR_PRIV struct sr_dev_driver saleae_logic_pro_driver_info = { .cleanup = std_cleanup, .scan = scan, .dev_list = std_dev_list, - .dev_clear = dev_clear, + .dev_clear = std_dev_clear, .config_get = config_get, .config_set = config_set, .config_list = config_list,