]> sigrok.org Git - libsigrok.git/blobdiff - hardware/saleae-logic/saleae-logic.c
sr: adjust copyright year
[libsigrok.git] / hardware / saleae-logic / saleae-logic.c
index 49174097af0052c8805b328c98aa48660fe399d6..bde17d75201c2a281cd2c9361eaac6b7f8d6969d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the sigrok project.
  *
- * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
+ * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
  *
  * 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
@@ -91,6 +91,8 @@ static struct sr_samplerates samplerates = {
 static GSList *device_instances = 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);
 
@@ -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;
        }
@@ -174,7 +185,7 @@ 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("failed to get device descriptor: %d", err);
                        continue;
                }
 
@@ -211,7 +222,7 @@ static int sl_open_device(int device_index)
                                  sdi->index, fx2->usb->bus,
                                  fx2->usb->address, USB_INTERFACE);
                } else {
-                       sr_warn("failed to open device: %d", err);
+                       sr_err("failed to open device: %d", err);
                }
 
                /* if we made it here, we handled the device one way or another */
@@ -320,7 +331,7 @@ static int hw_init(const char *deviceinfo)
        (void)deviceinfo;
 
        if (libusb_init(&usb_context) != 0) {
-               sr_warn("Failed to initialize USB.");
+               sr_err("Failed to initialize USB.");
                return 0;
        }
 
@@ -331,7 +342,7 @@ 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("failed to get device descriptor: %d", err);
                        continue;
                }
 
@@ -357,6 +368,8 @@ static int hw_init(const char *deviceinfo)
 
                if (check_conf_profile(devlist[i])) {
                        /* Already has the firmware, so fix the new address. */
+                       sr_dbg("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
                            (libusb_get_bus_number(devlist[i]),
@@ -366,7 +379,7 @@ 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);
+                               sr_err("firmware upload failed for device %d", devcnt);
                        fx2->usb = sr_usb_device_instance_new
                                (libusb_get_bus_number(devlist[i]), 0xff, NULL);
                }
@@ -411,14 +424,14 @@ static int hw_opendev(int device_index)
        }
 
        if (err != SR_OK) {
-               sr_warn("unable to open device");
+               sr_err("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("Unable to claim interface: %d", err);
                return SR_ERR;
        }
 
@@ -520,6 +533,47 @@ static int *hw_get_capabilities(void)
        return capabilities;
 }
 
+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("saleae: %s: Invalid samplerate %" PRIu64 "",
+              __func__, samplerate);
+       return 0;
+}
+
 static int set_configuration_samplerate(struct sr_device_instance *sdi,
                                        uint64_t samplerate)
 {
@@ -536,16 +590,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)",
                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("failed to set samplerate: %d", ret);
                return SR_ERR;
        }
        fx2->cur_samplerate = samplerate;
@@ -631,15 +689,14 @@ 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 */
+               return; /* TODO: SR_ERR_MALLOC */
        }
 
        transfer->buffer = new_buf;
        transfer->length = 4096;
        if (libusb_submit_transfer(transfer) != 0) {
                /* TODO: Stop session? */
-               sr_warn("eek");
+               sr_err("eek");
        }
 
        if (cur_buflen == 0) {
@@ -783,7 +840,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;
@@ -791,7 +848,6 @@ static int hw_start_acquisition(int device_index, gpointer session_data)
        gettimeofday(&header->starttime, NULL);
        header->samplerate = fx2->cur_samplerate;
        header->num_logic_probes = fx2->profile->num_probes;
-       header->num_analog_probes = 0;
        sr_session_bus(session_data, packet);
        g_free(header);
        g_free(packet);