X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fsaleae-logic%2Fsaleae-logic.c;h=a499191e598d5f7ff880a714ab7d7f34896ee6f1;hb=d68e2d1a21ac5c3f24d88b7689f98764e4d57c30;hp=09a37cb29caa63dae0e0a98ae850c17c920f60ae;hpb=5c64390e5ac8a0052d8b7eeb49c781d86027c814;p=libsigrok.git diff --git a/hardware/saleae-logic/saleae-logic.c b/hardware/saleae-logic/saleae-logic.c index 09a37cb2..a499191e 100644 --- a/hardware/saleae-logic/saleae-logic.c +++ b/hardware/saleae-logic/saleae-logic.c @@ -1,7 +1,7 @@ /* * This file is part of the sigrok project. * - * Copyright (C) 2012 Bert Vermeulen + * Copyright (C) 2010-2012 Bert Vermeulen * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -87,12 +87,14 @@ static struct sr_samplerates samplerates = { supported_samplerates, }; -/* List of struct sr_device_instance, maintained by opendev()/closedev(). */ -static GSList *device_instances = NULL; +/* List of struct sr_dev_inst, maintained by opendev()/closedev(). */ +static GSList *dev_insts = NULL; static libusb_context *usb_context = NULL; +static int new_saleae_logic_firmware = 0; + static int hw_set_configuration(int device_index, int capability, void *value); -static void hw_stop_acquisition(int device_index, gpointer session_device_id); +static int hw_stop_acquisition(int device_index, gpointer session_device_id); /** * Check the USB configuration to determine if this is a Saleae Logic. @@ -130,20 +132,29 @@ static int check_conf_profile(libusb_device *dev) break; intf_dsc = &(conf_dsc->interface[0].altsetting[0]); - if (intf_dsc->bNumEndpoints != 2) - /* Need 2 endpoints. */ + if (intf_dsc->bNumEndpoints == 4) { + /* The new Saleae Logic firmware has 4 endpoints. */ + new_saleae_logic_firmware = 1; + } else if (intf_dsc->bNumEndpoints == 2) { + /* The old Saleae Logic firmware has 2 endpoints. */ + new_saleae_logic_firmware = 0; + } else { + /* Other number of endpoints -> not a Saleae Logic. */ break; + } if ((intf_dsc->endpoint[0].bEndpointAddress & 0x8f) != (1 | LIBUSB_ENDPOINT_OUT)) - /* First endpoint should be 1 (outbound). */ + /* The first endpoint should be 1 (outbound). */ break; if ((intf_dsc->endpoint[1].bEndpointAddress & 0x8f) != (2 | LIBUSB_ENDPOINT_IN)) - /* First endpoint should be 2 (inbound). */ + /* The second endpoint should be 2 (inbound). */ break; + /* TODO: The new firmware has 4 endpoints... */ + /* If we made it here, it must be a Saleae Logic. */ ret = 1; } @@ -158,11 +169,11 @@ static int sl_open_device(int device_index) { libusb_device **devlist; struct libusb_device_descriptor des; - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; struct fx2_device *fx2; int err, skip, i; - if (!(sdi = sr_get_device_instance(device_instances, device_index))) + if (!(sdi = sr_dev_inst_get(dev_insts, device_index))) return SR_ERR; fx2 = sdi->priv; @@ -174,11 +185,12 @@ static int sl_open_device(int device_index) libusb_get_device_list(usb_context, &devlist); for (i = 0; devlist[i]; i++) { if ((err = libusb_get_device_descriptor(devlist[i], &des))) { - sr_warn("failed to get device descriptor: %d", err); + sr_err("logic: failed to get device descriptor: %d", err); continue; } - if (des.idVendor != fx2->profile->fw_vid || des.idProduct != fx2->profile->fw_pid) + if (des.idVendor != fx2->profile->fw_vid + || des.idProduct != fx2->profile->fw_pid) continue; if (sdi->status == SR_ST_INITIALIZING) { @@ -189,8 +201,8 @@ static int sl_open_device(int device_index) } } else if (sdi->status == SR_ST_INACTIVE) { /* - * This device is fully enumerated, so we need to find this - * device by vendor, product, bus and address. + * This device is fully enumerated, so we need to find + * this device by vendor, product, bus and address. */ if (libusb_get_bus_number(devlist[i]) != fx2->usb->bus || libusb_get_device_address(devlist[i]) != fx2->usb->address) @@ -207,11 +219,11 @@ static int sl_open_device(int device_index) fx2->usb->address = libusb_get_device_address(devlist[i]); sdi->status = SR_ST_ACTIVE; - sr_info("saleae: opened device %d on %d.%d interface %d", - sdi->index, fx2->usb->bus, - fx2->usb->address, USB_INTERFACE); + sr_info("logic: opened device %d on %d.%d interface %d", + sdi->index, fx2->usb->bus, + fx2->usb->address, USB_INTERFACE); } else { - sr_warn("failed to open device: %d", err); + sr_err("logic: failed to open device: %d", err); } /* if we made it here, we handled the device one way or another */ @@ -225,7 +237,7 @@ static int sl_open_device(int device_index) return SR_OK; } -static void close_device(struct sr_device_instance *sdi) +static void close_device(struct sr_dev_inst *sdi) { struct fx2_device *fx2; @@ -234,7 +246,7 @@ static void close_device(struct sr_device_instance *sdi) if (fx2->usb->devhdl == NULL) return; - sr_info("saleae: closing device %d on %d.%d interface %d", sdi->index, + sr_info("logic: closing device %d on %d.%d interface %d", sdi->index, fx2->usb->bus, fx2->usb->address, USB_INTERFACE); libusb_release_interface(fx2->usb->devhdl, USB_INTERFACE); libusb_close(fx2->usb->devhdl); @@ -293,7 +305,7 @@ static struct fx2_device *fx2_device_new(void) struct fx2_device *fx2; if (!(fx2 = g_try_malloc0(sizeof(struct fx2_device)))) { - sr_err("saleae: %s: fx2 malloc failed", __func__); + sr_err("logic: %s: fx2 malloc failed", __func__); return NULL; } fx2->trigger_stage = TRIGGER_FIRED; @@ -309,7 +321,7 @@ static struct fx2_device *fx2_device_new(void) static int hw_init(const char *deviceinfo) { - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; struct libusb_device_descriptor des; struct fx2_profile *fx2_prof; struct fx2_device *fx2; @@ -320,7 +332,7 @@ static int hw_init(const char *deviceinfo) (void)deviceinfo; if (libusb_init(&usb_context) != 0) { - sr_warn("Failed to initialize USB."); + sr_err("logic: Failed to initialize USB."); return 0; } @@ -331,7 +343,8 @@ static int hw_init(const char *deviceinfo) fx2_prof = NULL; err = libusb_get_device_descriptor(devlist[i], &des); if (err != 0) { - sr_warn("failed to get device descriptor: %d", err); + sr_err("logic: failed to get device descriptor: %d", + err); continue; } @@ -346,19 +359,21 @@ static int hw_init(const char *deviceinfo) /* not a supported VID/PID */ continue; - sdi = sr_device_instance_new(devcnt, SR_ST_INITIALIZING, + sdi = sr_dev_inst_new(devcnt, SR_ST_INITIALIZING, fx2_prof->vendor, fx2_prof->model, fx2_prof->model_version); if (!sdi) return 0; fx2 = fx2_device_new(); fx2->profile = fx2_prof; sdi->priv = fx2; - device_instances = g_slist_append(device_instances, sdi); + dev_insts = g_slist_append(dev_insts, sdi); if (check_conf_profile(devlist[i])) { /* Already has the firmware, so fix the new address. */ + sr_dbg("logic: Found a Saleae Logic with %s firmware.", + new_saleae_logic_firmware ? "new" : "old"); sdi->status = SR_ST_INACTIVE; - fx2->usb = sr_usb_device_instance_new + fx2->usb = sr_usb_dev_inst_new (libusb_get_bus_number(devlist[i]), libusb_get_device_address(devlist[i]), NULL); } else { @@ -366,8 +381,9 @@ static int hw_init(const char *deviceinfo) /* Remember when the firmware on this device was updated */ g_get_current_time(&fx2->fw_updated); else - sr_warn("firmware upload failed for device %d", devcnt); - fx2->usb = sr_usb_device_instance_new + sr_err("logic: firmware upload failed for " + "device %d", devcnt); + fx2->usb = sr_usb_dev_inst_new (libusb_get_bus_number(devlist[i]), 0xff, NULL); } devcnt++; @@ -380,11 +396,11 @@ static int hw_init(const char *deviceinfo) static int hw_opendev(int device_index) { GTimeVal cur_time; - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; struct fx2_device *fx2; int timediff, err; - if (!(sdi = sr_get_device_instance(device_instances, device_index))) + if (!(sdi = sr_dev_inst_get(dev_insts, device_index))) return SR_ERR; fx2 = sdi->priv; @@ -394,31 +410,31 @@ static int hw_opendev(int device_index) */ err = 0; if (GTV_TO_MSEC(fx2->fw_updated) > 0) { - sr_info("saleae: waiting for device to reset"); + sr_info("logic: waiting for device to reset"); /* takes at least 300ms for the FX2 to be gone from the USB bus */ - g_usleep(300*1000); + g_usleep(300 * 1000); timediff = 0; while (timediff < MAX_RENUM_DELAY) { if ((err = sl_open_device(device_index)) == SR_OK) break; - g_usleep(100*1000); + g_usleep(100 * 1000); g_get_current_time(&cur_time); timediff = GTV_TO_MSEC(cur_time) - GTV_TO_MSEC(fx2->fw_updated); } - sr_info("saleae: device came back after %d ms", timediff); + sr_info("logic: device came back after %d ms", timediff); } else { err = sl_open_device(device_index); } if (err != SR_OK) { - sr_warn("unable to open device"); + sr_err("logic: unable to open device"); return SR_ERR; } fx2 = sdi->priv; err = libusb_claim_interface(fx2->usb->devhdl, USB_INTERFACE); if (err != 0) { - sr_warn("Unable to claim interface: %d", err); + sr_err("logic: Unable to claim interface: %d", err); return SR_ERR; } @@ -434,9 +450,9 @@ static int hw_opendev(int device_index) static int hw_closedev(int device_index) { - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; - if (!(sdi = sr_get_device_instance(device_instances, device_index))) { + if (!(sdi = sr_dev_inst_get(dev_insts, device_index))) { sr_err("logic: %s: sdi was NULL", __func__); return SR_ERR; /* TODO: SR_ERR_ARG? */ } @@ -447,36 +463,50 @@ static int hw_closedev(int device_index) return SR_OK; } -static void hw_cleanup(void) +static int hw_cleanup(void) { GSList *l; - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; struct fx2_device *fx2; + int ret = SR_OK; /* Properly close and free all devices. */ - for (l = device_instances; l; l = l->next) { - sdi = l->data; - fx2 = sdi->priv; + for (l = dev_insts; l; l = l->next) { + if (!(sdi = l->data)) { + /* Log error, but continue cleaning up the rest. */ + sr_err("logic: %s: sdi was NULL, continuing", __func__); + ret = SR_ERR_BUG; + continue; + } + if (!(fx2 = sdi->priv)) { + /* Log error, but continue cleaning up the rest. */ + sr_err("logic: %s: sdi->priv was NULL, continuing", + __func__); + ret = SR_ERR_BUG; + continue; + } close_device(sdi); - sr_usb_device_instance_free(fx2->usb); - sr_device_instance_free(sdi); + sr_usb_dev_inst_free(fx2->usb); + sr_dev_inst_free(sdi); } - g_slist_free(device_instances); - device_instances = NULL; + g_slist_free(dev_insts); + dev_insts = NULL; if (usb_context) libusb_exit(usb_context); usb_context = NULL; + + return ret; } static void *hw_get_device_info(int device_index, int device_info_id) { - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; struct fx2_device *fx2; void *info = NULL; - if (!(sdi = sr_get_device_instance(device_instances, device_index))) + if (!(sdi = sr_dev_inst_get(dev_insts, device_index))) return NULL; fx2 = sdi->priv; @@ -506,9 +536,9 @@ static void *hw_get_device_info(int device_index, int device_info_id) static int hw_get_status(int device_index) { - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; - sdi = sr_get_device_instance(device_instances, device_index); + sdi = sr_dev_inst_get(dev_insts, device_index); if (sdi) return sdi->status; else @@ -520,7 +550,48 @@ static int *hw_get_capabilities(void) return capabilities; } -static int set_configuration_samplerate(struct sr_device_instance *sdi, +static uint8_t new_firmware_divider_value(uint64_t samplerate) +{ + switch (samplerate) { + case SR_MHZ(24): + return 0xe0; + break; + case SR_MHZ(16): + return 0xd5; + break; + case SR_MHZ(12): + return 0xe2; + break; + case SR_MHZ(8): + return 0xd4; + break; + case SR_MHZ(4): + return 0xda; + break; + case SR_MHZ(2): + return 0xe6; + break; + case SR_MHZ(1): + return 0x8e; + break; + case SR_KHZ(500): + return 0xfe; + break; + case SR_KHZ(250): + return 0x9e; + break; + case SR_KHZ(200): + return 0x4e; + break; + } + + /* Shouldn't happen. */ + sr_err("logic: %s: Invalid samplerate %" PRIu64 "", + __func__, samplerate); + return 0; +} + +static int set_configuration_samplerate(struct sr_dev_inst *sdi, uint64_t samplerate) { struct fx2_device *fx2; @@ -536,16 +607,20 @@ static int set_configuration_samplerate(struct sr_device_instance *sdi, if (supported_samplerates[i] == 0) return SR_ERR_SAMPLERATE; - divider = (uint8_t) (48 / (samplerate / 1000000.0)) - 1; + if (new_saleae_logic_firmware) + divider = new_firmware_divider_value(samplerate); + else + divider = (uint8_t) (48 / (samplerate / 1000000.0)) - 1; - sr_info("saleae: setting samplerate to %" PRIu64 " Hz (divider %d)", + sr_info("logic: setting samplerate to %" PRIu64 " Hz (divider %d)", samplerate, divider); - buf[0] = 0x01; + + buf[0] = (new_saleae_logic_firmware) ? 0xd5 : 0x01; buf[1] = divider; ret = libusb_bulk_transfer(fx2->usb->devhdl, 1 | LIBUSB_ENDPOINT_OUT, buf, 2, &result, 500); if (ret != 0) { - sr_warn("failed to set samplerate: %d", ret); + sr_err("logic: failed to set samplerate: %d", ret); return SR_ERR; } fx2->cur_samplerate = samplerate; @@ -555,12 +630,12 @@ static int set_configuration_samplerate(struct sr_device_instance *sdi, static int hw_set_configuration(int device_index, int capability, void *value) { - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; struct fx2_device *fx2; int ret; uint64_t *tmp_u64; - if (!(sdi = sr_get_device_instance(device_instances, device_index))) + if (!(sdi = sr_dev_inst_get(dev_insts, device_index))) return SR_ERR; fx2 = sdi->priv; @@ -620,7 +695,7 @@ static void receive_transfer(struct libusb_transfer *transfer) return; } - sr_info("saleae: receive_transfer(): status %d received %d bytes", + sr_info("logic: receive_transfer(): status %d received %d bytes", transfer->status, transfer->actual_length); /* Save incoming transfer before reusing the transfer struct. */ @@ -630,16 +705,16 @@ static void receive_transfer(struct libusb_transfer *transfer) /* Fire off a new request. */ if (!(new_buf = g_try_malloc(4096))) { - sr_err("saleae: %s: new_buf malloc failed", __func__); - // return SR_ERR_MALLOC; - return; /* FIXME */ + sr_err("logic: %s: new_buf malloc failed", __func__); + return; /* TODO: SR_ERR_MALLOC */ } transfer->buffer = new_buf; transfer->length = 4096; if (libusb_submit_transfer(transfer) != 0) { /* TODO: Stop session? */ - sr_warn("eek"); + /* TODO: Better error message. */ + sr_err("logic: %s: libusb_submit_transfer error", __func__); } if (cur_buflen == 0) { @@ -735,7 +810,7 @@ static void receive_transfer(struct libusb_transfer *transfer) static int hw_start_acquisition(int device_index, gpointer session_data) { - struct sr_device_instance *sdi; + struct sr_dev_inst *sdi; struct sr_datafeed_packet *packet; struct sr_datafeed_header *header; struct fx2_device *fx2; @@ -744,18 +819,18 @@ static int hw_start_acquisition(int device_index, gpointer session_data) int size, i; unsigned char *buf; - if (!(sdi = sr_get_device_instance(device_instances, device_index))) + if (!(sdi = sr_dev_inst_get(dev_insts, device_index))) return SR_ERR; fx2 = sdi->priv; fx2->session_data = session_data; if (!(packet = g_try_malloc(sizeof(struct sr_datafeed_packet)))) { - sr_err("saleae: %s: packet malloc failed", __func__); + sr_err("logic: %s: packet malloc failed", __func__); return SR_ERR_MALLOC; } if (!(header = g_try_malloc(sizeof(struct sr_datafeed_header)))) { - sr_err("saleae: %s: header malloc failed", __func__); + sr_err("logic: %s: header malloc failed", __func__); return SR_ERR_MALLOC; } @@ -763,7 +838,7 @@ static int hw_start_acquisition(int device_index, gpointer session_data) size = 2048; for (i = 0; i < NUM_SIMUL_TRANSFERS; i++) { if (!(buf = g_try_malloc(size))) { - sr_err("saleae: %s: buf malloc failed", __func__); + sr_err("logic: %s: buf malloc failed", __func__); return SR_ERR_MALLOC; } transfer = libusb_alloc_transfer(0); @@ -783,7 +858,7 @@ static int hw_start_acquisition(int device_index, gpointer session_data) for (i = 0; lupfd[i]; i++) sr_source_add(lupfd[i]->fd, lupfd[i]->events, 40, receive_data, NULL); - free(lupfd); + free(lupfd); /* NOT g_free()! */ packet->type = SR_DF_HEADER; packet->payload = header; @@ -799,7 +874,7 @@ static int hw_start_acquisition(int device_index, gpointer session_data) } /* This stops acquisition on ALL devices, ignoring device_index. */ -static void hw_stop_acquisition(int device_index, gpointer session_data) +static int hw_stop_acquisition(int device_index, gpointer session_data) { struct sr_datafeed_packet packet; @@ -812,6 +887,8 @@ static void hw_stop_acquisition(int device_index, gpointer session_data) receive_transfer(NULL); /* TODO: Need to cancel and free any queued up transfers. */ + + return SR_OK; } SR_PRIV struct sr_device_plugin saleae_logic_plugin_info = {