Samples: fxload improvements and cleanup
authorFederico Manzan <f.manzan@gmail.com>
Sun, 10 Mar 2013 07:56:56 +0000 (07:56 +0000)
committerPete Batard <pete@akeo.ie>
Fri, 15 Mar 2013 00:46:24 +0000 (00:46 +0000)
* fix C++ compilation
* use stdint types
* allow to specify bus:address as a parameter
* allocate a buffer when transferring FX3 image and check for R/W errors

examples/ezusb.c
examples/ezusb.h
examples/fxload.c
libusb/version_nano.h

index 2ab7188..d80422f 100644 (file)
@@ -532,9 +532,9 @@ static int ram_poke(void *context, uint32_t addr, bool external,
  */
 int fx3_load_ram(libusb_device_handle *device, const char *path)
 {
-       unsigned int dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength;
-       unsigned short wSignature;
-       unsigned int dImageBuf[512 * 1024];
+       uint32_t dCheckSum, dExpectedCheckSum, dAddress, i, dLen, dLength;
+       uint16_t wSignature;
+       uint32_t* dImageBuf;
        unsigned char *bBuf, rBuf[4096];
        FILE *image;
 
@@ -545,22 +545,38 @@ int fx3_load_ram(libusb_device_handle *device, const char *path)
        } else if (verbose)
                logerror("open firmware image %s for RAM upload\n", path);
 
-       fread(&wSignature, 1, 2, image); // read signature bytes
-       if (wSignature != 0x5943) { // check CY signature byte
-               logerror("Invalid image");
+       if ((fread(&wSignature, sizeof(uint16_t), 1, image) != 1) ||
+               (wSignature != 0x5943)) { // check "CY" signature byte
+               logerror("invalid image (signature error)");
+               return -3;
+       }
+       if (fread(&i, 1, 2, image) != 2) { // skip 2 dummy bytes
+               logerror("could not read image");
                return -3;
        }
-       fread(&i, 2, 1, image); // skip 2 dummy bytes
 
        dCheckSum = 0;
        while (1) {
-               fread(&dLength, 4, 1, image); // read dLength
-               fread(&dAddress, 4, 1, image); // read dAddress
+               if ((fread(&dLength, sizeof(uint32_t), 1, image) != 1) ||  // read dLength
+                       (fread(&dAddress, sizeof(uint32_t), 1, image) != 1)) { // read dAddress
+                       logerror("could not read image");
+                       return -3;
+               }
                if (dLength == 0)
                        break; // done
 
+               dImageBuf = calloc(dLength, sizeof(uint32_t));
+               if (dImageBuf == NULL) {
+                       logerror("could not allocate buffer for image chunk\n");
+                       return -4;
+               }
+
                // read sections
-               fread(dImageBuf, 4, dLength, image);
+               if (fread(dImageBuf, sizeof(uint32_t), dLength, image) != dLength) {
+                       logerror("could not read image");
+                       free(dImageBuf);
+                       return -3;
+               }
                for (i = 0; i < dLength; i++)
                        dCheckSum += dImageBuf[i];
                dLength <<= 2; // convert to Byte length
@@ -570,13 +586,18 @@ int fx3_load_ram(libusb_device_handle *device, const char *path)
                        dLen = 4096; // 4K max
                        if (dLen > dLength)
                                dLen = dLength;
-                       ezusb_write(device, "Write firmware", RW_INTERNAL, dAddress, bBuf, dLen);
-                       ezusb_read(device, "Read firmware", RW_INTERNAL, dAddress, rBuf, dLen);
+                       if ((ezusb_write(device, "write firmware", RW_INTERNAL, dAddress, bBuf, dLen) < 0) ||
+                               (ezusb_read(device, "read firmware", RW_INTERNAL, dAddress, rBuf, dLen) < 0)) {
+                               logerror("R/W error\n");
+                               free(dImageBuf);
+                               return -5;
+                       }
                        // Verify data: rBuf with bBuf
                        for (i = 0; i < dLen; i++) {
                                if (rBuf[i] != bBuf[i]) {
-                                       logerror("Fail to verify image");
-                                       return -3;
+                                       logerror("verify error");
+                                       free(dImageBuf);
+                                       return -6;
                                }
                        }
 
@@ -584,19 +605,22 @@ int fx3_load_ram(libusb_device_handle *device, const char *path)
                        bBuf += dLen;
                        dAddress += dLen;
                }
+               free(dImageBuf);
        }
 
        // read pre-computed checksum data
-       fread(&dExpectedCheckSum, 4, 1, image);
-       if (dCheckSum != dExpectedCheckSum) {
-               logerror("Fail to boot due to checksum error\n");
-               return -4;
+       if ((fread(&dExpectedCheckSum, sizeof(uint32_t), 1, image) != 1) ||
+               (dCheckSum != dExpectedCheckSum)) {
+               logerror("checksum error\n");
+               return -7;
        }
 
        // transfer execution to Program Entry
-       ezusb_write(device, "Jump command", RW_INTERNAL, dAddress, NULL, 0);
+       if (ezusb_write(device, "Jump command", RW_INTERNAL, dAddress, NULL, 0) < 0) {
+               logerror("failed to send jump command\n");
+               return -6;
+       }
 
-       logerror("Done!\n");
        return 0;
 }
 
index 2bbe979..c5d9868 100644 (file)
 #define IMG_TYPE_MAX       4
 #define IMG_TYPE_NAMES     { "Intel HEX", "Cypress 8051 IIC", "Cypress 8051 BIX", "Cypress IMG format" }
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* 
  * Automatically identified devices (VID, PID, type, designation).
  * TODO: Could use some validation. Also where's the FX2?
@@ -108,4 +112,9 @@ extern int ezusb_load_eeprom(libusb_device_handle *device,
 
 /* boolean flag, says whether to write extra messages to stderr */
 extern int verbose;
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index 7086fe7..d69eea4 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright © 2001-2002 David Brownell (dbrownell@users.sourceforge.net)
  * Copyright © 2008 Roger Williams (rawqux@users.sourceforge.net)
  * Copyright © 2012 Pete Batard (pete@akeo.ie)
+ * Copyright © 2013 Federico Manzan (f.manzan@gmail.com)
  *
  *    This source code is free software; you can redistribute it
  *    and/or modify it in source code form under the terms of the GNU
  *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-/*
- * This program supports uploading firmware into a target USB device.
- *
- *     -I <path>       -- Upload this firmware
- *     -t <type>       -- uController type: an21, fx, fx2, fx2lp, fx3
- *
- *     -D <vid:pid>    -- Use this device, instead of $DEVICE
- *
- *     -V              -- Print version ID for program
- */
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -79,24 +70,39 @@ int main(int argc, char*argv[])
 {
        fx_known_device known_device[] = FX_KNOWN_DEVICES;
        const char *path[] = { NULL, NULL };
-       const char *device_id = getenv("DEVICE");
+       const char *device_id = NULL;
+       const char *device_path = getenv("DEVICE");
        const char *type = NULL;
        const char *fx_name[FX_TYPE_MAX] = FX_TYPE_NAMES;
        const char *ext, *img_name[] = IMG_TYPE_NAMES;
        int fx_type = FX_TYPE_UNDEFINED, img_type[ARRAYSIZE(path)];
        int i, j, opt, status;
        unsigned vid = 0, pid = 0;
+       unsigned busnum = 0, devaddr = 0;
        libusb_device *dev, **devs;
        libusb_device_handle *device = NULL;
        struct libusb_device_descriptor desc;
 
-       while ((opt = getopt(argc, argv, "vV?D:I:c:s:t:")) != EOF)
+       while ((opt = getopt(argc, argv, "vV?hd:a:i:I:t:")) != EOF)
                switch (opt) {
 
-               case 'D':
+               case 'd':
                        device_id = optarg;
+                       if (sscanf(device_id, "%x:%x" , &vid, &pid) != 2 ) {
+                               fputs ("please specify VID & PID as \"vid:pid\", in hexadecimal format\n", stderr);
+                               return -1;
+                       }
                        break;
 
+               case 'a':
+                       device_path = optarg;
+                       if (sscanf(device_path, "%u:%u", &busnum, &devaddr) != 2 ) {
+                               fputs ("please specify bus number & device address as \"bus:addr\", in decimal format\n", stderr);
+                               return -1;
+                       }
+                       break;
+
+               case 'i':
                case 'I':
                        path[FIRMWARE] = optarg;
                        break;
@@ -114,6 +120,7 @@ int main(int argc, char*argv[])
                        break;
 
                case '?':
+               case 'h':
                default:
                        goto usage;
 
@@ -122,13 +129,13 @@ int main(int argc, char*argv[])
        if (path[FIRMWARE] == NULL) {
                logerror("no firmware specified!\n");
 usage:
-               fprintf(stderr, "\nusage: %s [-vV] [-t type] [-D vid:pid] -I firmware\n", argv[0]);
-               fprintf(stderr, "      type: one of an21, fx, fx2, fx2lp, fx3\n");
-               return -1;
-       }
-
-       if ((device_id != NULL) && (sscanf(device_id, "%x:%x" , &vid, &pid) != 2 )) {
-               fputs ("please specify VID & PID as \"vid:pid\" in hexadecimal format\n", stderr);
+               fprintf(stderr, "\nUsage: fxload [-v] [-V] [-t type] [-d vid:pid] [-a bus:addr] -i firmware\n");
+               fprintf(stderr, "  -i <path>       -- Firmware to upload\n");
+               fprintf(stderr, "  -t <type>       -- Target type: an21, fx, fx2, fx2lp, fx3\n");
+               fprintf(stderr, "  -d <vid:pid>    -- Target device, as an USB VID:PID\n");
+               fprintf(stderr, "  -a <bus:addr>   -- Target device, as a libusbx bus and address\n");
+               fprintf(stderr, "  -v              -- Increase verbosity\n");
+               fprintf(stderr, "  -V              -- Print program version\n");
                return -1;
        }
 
@@ -155,12 +162,17 @@ usage:
        libusb_set_debug(NULL, verbose);
 
        /* try to pick up missing parameters from known devices */
-       if ((type == NULL) || (device_id == NULL)) {
+       if (device_path || (type == NULL) || (device_id == NULL)) {
                if (libusb_get_device_list(NULL, &devs) < 0) {
                        logerror("libusb_get_device_list() failed: %s\n", libusb_error_name(status));
                        goto err;
                }
                for (i=0; (dev=devs[i]) != NULL; i++) {
+                       if (device_path) {
+                               if ((libusb_get_bus_number(dev) == busnum) && (libusb_get_device_address(dev) == devaddr))
+                                       break;
+                               continue;
+                       }
                        status = libusb_get_device_descriptor(dev, &desc);
                        if (status >= 0) {
                                if (verbose >= 2)
@@ -195,7 +207,7 @@ usage:
                }
                if (dev == NULL) {
                        libusb_free_device_list(devs, 1);
-                       logerror("could not find a known device - please specify type and/or vid:pid\n");
+                       logerror("could not find a known device - please specify type and/or vid:pid or bus:addr\n");
                        goto usage;
                }
                status = libusb_open(dev, &device);
@@ -211,6 +223,7 @@ usage:
                        goto err;
                }
        }
+
        /* We need to claim the first interface */
        status = libusb_claim_interface(device, 0);
 #if defined(__linux__)
index bd8f428..e652d0e 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 10628
+#define LIBUSB_NANO 10629