From: Joel Holdsworth Date: Sat, 25 Feb 2012 11:58:55 +0000 (+0000) Subject: fx2lafw: Implemented firmware upload X-Git-Tag: libsigrok-0.1.0~92 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=b1eeb67e926ddaddc11e8a509692fdcaf3e2226e;p=libsigrok.git fx2lafw: Implemented firmware upload --- diff --git a/hardware/fx2lafw/fx2lafw.c b/hardware/fx2lafw/fx2lafw.c index 36362f8d..5522a420 100644 --- a/hardware/fx2lafw/fx2lafw.c +++ b/hardware/fx2lafw/fx2lafw.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -78,6 +79,68 @@ static struct sr_samplerates fx2lafw_samplerates = { static GSList *dev_insts = NULL; static libusb_context *usb_context = NULL; +/** + * Check the USB configuration to determine if this is an fx2lafw device. + * + * @return true if the device's configuration profile match fx2lafw + * configuration, flase otherwise. + */ +static bool check_conf_profile(libusb_device *dev) +{ + struct libusb_device_descriptor des; + struct libusb_config_descriptor *conf_dsc = NULL; + const struct libusb_interface_descriptor *intf_dsc; + bool ret = false; + + while (!ret) { + /* Assume it's not a Saleae Logic unless proven wrong. */ + ret = 0; + + if (libusb_get_device_descriptor(dev, &des) != 0) + break; + + if (des.bNumConfigurations != 1) + /* Need exactly 1 configuration. */ + break; + + if (libusb_get_config_descriptor(dev, 0, &conf_dsc) != 0) + break; + + if (conf_dsc->bNumInterfaces != 1) + /* Need exactly 1 interface. */ + break; + + if (conf_dsc->interface[0].num_altsetting != 1) + /* Need just one alternate setting. */ + break; + + intf_dsc = &(conf_dsc->interface[0].altsetting[0]); + if (intf_dsc->bNumEndpoints != 3) + /* Need exactly 3 end points. */ + break; + + if ((intf_dsc->endpoint[0].bEndpointAddress & 0x8f) != + (1 | LIBUSB_ENDPOINT_OUT)) + /* The first endpoint should be 1 (outbound). */ + break; + + if ((intf_dsc->endpoint[1].bEndpointAddress & 0x8f) != + (2 | LIBUSB_ENDPOINT_IN)) + /* The second endpoint should be 2 (inbound). */ + break; + + /* TODO: Check the debug channel... */ + + /* If we made it here, it must be an fx2lafw. */ + ret = true; + } + + if (conf_dsc) + libusb_free_config_descriptor(conf_dsc); + + return ret; +} + static struct fx2lafw_device* fx2lafw_device_new(void) { struct fx2lafw_device *fx2lafw; @@ -146,6 +209,24 @@ static int hw_init(const char *deviceinfo) sdi->priv = ctx; device_instances = g_slist_append(dev_insts, sdi); + if (check_conf_profile(devlist[i])) { + /* Already has the firmware, so fix the new address. */ + sr_dbg("fx2lafw: Found a fx2lafw device."); + sdi->status = SR_ST_INACTIVE; + ctx->usb = sr_usb_dev_inst_new + (libusb_get_bus_number(devlist[i]), + libusb_get_device_address(devlist[i]), NULL); + } else { + if (ezusb_upload_firmware(devlist[i], USB_CONFIGURATION, FIRMWARE) == SR_OK) + /* Remember when the firmware on this device was updated */ + g_get_current_time(&ctx->fw_updated); + else + sr_err("fx2lafw: firmware upload failed for " + "device %d", devcnt); + ctx->usb = sr_usb_dev_inst_new + (libusb_get_bus_number(devlist[i]), 0xff, NULL); + } + devcnt++; } libusb_free_device_list(devlist, 1); diff --git a/hardware/fx2lafw/fx2lafw.h b/hardware/fx2lafw/fx2lafw.h index 49d93115..88536a83 100644 --- a/hardware/fx2lafw/fx2lafw.h +++ b/hardware/fx2lafw/fx2lafw.h @@ -20,7 +20,10 @@ #ifndef LIBSIGROK_HARDWARE_FX2LAFW #define LIBSIGROK_HARDWARE_FX2LAFW -#define TRIGGER_TYPES "01rf" +#define USB_INTERFACE 0 +#define USB_CONFIGURATION 1 +#define TRIGGER_TYPES "01rf" +#define FIRMWARE FIRMWARE_DIR "/fx2lafw-cwav-usbeeax.fw" struct fx2lafw_profile { uint16_t vid; @@ -36,9 +39,17 @@ struct fx2lafw_profile { struct fx2lafw_device { struct fx2lafw_profile *profile; + /* + * Since we can't keep track of an fx2lafw device after upgrading + * the firmware (it re-enumerates into a different device address + * after the upgrade) this is like a global lock. No device will open + * until a proper delay after the last device was upgraded. + */ + GTimeVal fw_updated; + void *session_data; - struct sr_usb_device_instance *usb; + struct sr_usb_dev_inst *usb; }; #endif