X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Ffx2lafw%2Ffx2lafw.c;h=a883406c94407b6216456c3d773101dce955736c;hb=aae2fed675fc63aae58569a03c71201dc449344b;hp=f37557755d8fcfe42ae5d75b7d9ff8c4832fb411;hpb=f302a082567d10f90cd20fca5a7abd68d7267d96;p=libsigrok.git diff --git a/hardware/fx2lafw/fx2lafw.c b/hardware/fx2lafw/fx2lafw.c index f3755775..a883406c 100644 --- a/hardware/fx2lafw/fx2lafw.c +++ b/hardware/fx2lafw/fx2lafw.c @@ -19,12 +19,76 @@ #include #include +#include +#include +#include #include "config.h" #include "sigrok.h" #include "sigrok-internal.h" #include "fx2lafw.h" +static struct fx2lafw_profile supported_fx2[] = { + /* USBee AX */ + { 0x08a9, 0x0014, "CWAV", "USBee AX", NULL, 8 }, + { 0, 0, 0, 0, 0, 0 } +}; + +static int fx2lafw_capabilities[] = { + SR_HWCAP_LOGIC_ANALYZER, + SR_HWCAP_SAMPLERATE, + + /* These are really implemented in the driver, not the hardware. */ + SR_HWCAP_LIMIT_SAMPLES, + SR_HWCAP_CONTINUOUS, + 0 +}; + +static const char *fx2lafw_probe_names[] = { + "D0", + "D1", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + NULL +}; + +static uint64_t fx2lafw_supported_samplerates[] = { + SR_MHZ(1), + SR_MHZ(2), + SR_MHZ(3), + SR_MHZ(4), + SR_MHZ(6), + SR_MHZ(8), + SR_MHZ(12), + SR_MHZ(16), + SR_MHZ(24) +}; + +static struct sr_samplerates fx2lafw_samplerates = { + SR_MHZ(1), + SR_MHZ(24), + SR_HZ(0), + fx2lafw_supported_samplerates +}; + +static GSList *device_instances = NULL; +static libusb_context *usb_context = NULL; + +static struct fx2lafw_device* fx2lafw_device_new(void) +{ + struct fx2lafw_device *fx2lafw; + + if (!(fx2lafw = g_try_malloc0(sizeof(struct fx2lafw_device)))) { + sr_err("fx2lafw: %s: fx2lafw_device malloc failed", __func__); + return NULL; + } + + return fx2lafw; +} /* * API callbacks @@ -32,8 +96,61 @@ static int hw_init(const char *deviceinfo) { + struct sr_dev_inst *sdi; + struct libusb_device_descriptor des; + struct fx2lafw_profile *fx2lafw_prof; + struct fx2lafw_device *fx2lafw_dev; + libusb_device **devlist; + int err; + int devcnt = 0; + int i, j; + + /* Avoid compiler warnings. */ (void)deviceinfo; - return 0; + + if (libusb_init(&usb_context) != 0) { + sr_warn("Failed to initialize USB."); + return 0; + } + + /* Find all fx2lafw compatible devices and upload firware to all of them. */ + libusb_get_device_list(usb_context, &devlist); + for (i = 0; devlist[i]; i++) { + + if ((err = libusb_get_device_descriptor( + devlist[i], &des)) != 0) { + sr_warn("failed to get device descriptor: %d", err); + continue; + } + + fx2lafw_prof = NULL; + for (j = 0; supported_fx2[j].vid; j++) { + if (des.idVendor == supported_fx2[j].vid && + des.idProduct == supported_fx2[j].pid) { + fx2lafw_prof = &supported_fx2[j]; + } + } + + /* Skip if the device was not found */ + if(!fx2lafw_prof) + continue; + + sdi = sr_dev_inst_new(devcnt, SR_ST_INITIALIZING, + fx2lafw_prof->vendor, fx2lafw_prof->model, + fx2lafw_prof->model_version); + if(!sdi) + return 0; + + fx2lafw_dev = fx2lafw_device_new(); + fx2lafw_dev->profile = fx2lafw_prof; + sdi->priv = fx2lafw_dev; + device_instances = g_slist_append(device_instances, sdi); + + devcnt++; + } + libusb_free_device_list(devlist, 1); + + return devcnt; } static int hw_dev_open(int device_index) @@ -50,25 +167,63 @@ static int hw_dev_close(int device_index) static int hw_cleanup(void) { + GSList *l; + struct sr_dev_inst *sdi; + + for(l = device_instances; l; l = l->next) { + sdi = l->data; + sr_dev_inst_free(sdi); + } + + g_slist_free(device_instances); + device_instances = NULL; + + if(usb_context) + libusb_exit(usb_context); + usb_context = NULL; + return SR_OK; } static void *hw_dev_info_get(int device_index, int device_info_id) { - (void)device_index; - (void)device_info_id; + struct sr_dev_inst *sdi; + struct fx2lafw_device *fx2lafw_dev; + + if (!(sdi = sr_dev_inst_get(device_instances, device_index))) + return NULL; + fx2lafw_dev = sdi->priv; + + switch (device_info_id) { + case SR_DI_INST: + return sdi; + case SR_DI_NUM_PROBES: + return GINT_TO_POINTER(fx2lafw_dev->profile->num_probes); + case SR_DI_PROBE_NAMES: + return fx2lafw_probe_names; + case SR_DI_SAMPLERATES: + return &fx2lafw_samplerates; + case SR_DI_TRIGGER_TYPES: + return TRIGGER_TYPES; + } + return NULL; } static int hw_dev_status_get(int device_index) { - (void)device_index; - return SR_ST_NOT_FOUND; + const struct sr_dev_inst *const sdi = + sr_dev_inst_get(device_instances, device_index); + + if (!sdi) + return SR_ST_NOT_FOUND; + + return sdi->status; } static int *hw_hwcap_get_all(void) { - return NULL; + return fx2lafw_capabilities; } static int hw_dev_config_set(int dev_index, int capability, void *value)