Exemple #1
0
static int perform_recovery(struct cli_state *state,
                            uint8_t bus, uint8_t addr,
                            const char *firmware_file)
{
    int status;
    libusb_context *ctx;
    libusb_device_handle *handle = NULL;

    status = libusb_init(&ctx);
    if (status != 0) {
        return CMD_RET_UNKNOWN;
    }

    status = find_device(state, ctx, bus, addr, &handle, false);
    if (status == 0) {
        status = ezusb_load_ram(handle, firmware_file,
                                FX_TYPE_FX3, IMG_TYPE_IMG, 0);
    }

    libusb_close(handle);
    libusb_exit(ctx);
    return status;
}
Exemple #2
0
int main(int argc, char*argv[])
{
      const char	*link_path = 0;
      const char	*ihex_path = 0;
      const char	*device_path = getenv("DEVICE");
      const char	*type = 0;
      const char	*stage1 = 0;
      mode_t		mode = 0;
      int		opt;
      int		config = -1;

      while ((opt = getopt (argc, argv, "2vV?D:I:L:c:lm:s:t:")) != EOF)
      switch (opt) {

	  case '2':		// original version of "-t fx2"
	    type = "fx2";
	    break;

	  case 'D':
	    device_path = optarg;
	    break;

	  case 'I':
	    ihex_path = optarg;
	    break;

	  case 'L':
	    link_path = optarg;
	    break;

	  case 'V':
	    puts (FXLOAD_VERSION);
	    return 0;

	  case 'c':
	    config = strtoul (optarg, 0, 0);
	    if (config < 0 || config > 255) {
		logerror("illegal config byte: %s\n", optarg);
		goto usage;
	    }
	    break;

	  case 'l':
	    openlog(argv[0], LOG_CONS|LOG_NOWAIT|LOG_PERROR, LOG_USER);
	    dosyslog=1;
	    break;

	  case 'm':
	    mode = strtoul(optarg,0,0);
	    mode &= 0777;
	    break;

	  case 's':
	    stage1 = optarg;
	    break;

	  case 't':
	    if (strcmp (optarg, "an21")		// original AnchorChips parts
		    && strcmp (optarg, "fx")	// updated Cypress versions
		    && strcmp (optarg, "fx2")	// Cypress USB 2.0 versions
		    && strcmp (optarg, "fx2lp")	// updated FX2
		    ) {
		logerror("illegal microcontroller type: %s\n", optarg);
		goto usage;
	    }
	    type = optarg;
	    break;

	  case 'v':
	    verbose++;
	    break;

	  case '?':
	  default:
	    goto usage;

      }

      if (config >= 0) {
	    if (type == 0) {
		logerror("must specify microcontroller type %s",
				"to write EEPROM!\n");
		goto usage;
	    }
	    if (!stage1 || !ihex_path) {
		logerror("need 2nd stage loader and firmware %s",
				"to write EEPROM!\n");
		goto usage;
	    }
	    if (link_path || mode) {
		logerror("links and modes not set up when writing EEPROM\n");
		goto usage;
	    }
      }

      if (!device_path) {
	    logerror("no device specified!\n");
usage:
	    fputs ("usage: ", stderr);
	    fputs (argv [0], stderr);
	    fputs (" [-vV] [-l] [-t type] [-D devpath]\n", stderr);
	    fputs ("\t\t[-I firmware_hexfile] ", stderr);
	    fputs ("[-s loader] [-c config_byte]\n", stderr);
	    fputs ("\t\t[-L link] [-m mode]\n", stderr);
	    fputs ("... [-D devpath] overrides DEVICE= in env\n", stderr);
	    fputs ("... device types:  one of an21, fx, fx2, fx2lp\n", stderr);
	    fputs ("... at least one of -I, -L, -m is required\n", stderr);
	    return -1;
      }

      if (ihex_path) {
	    int fd = open(device_path, O_RDWR);
	    int status;
	    int	fx2;

	    if (fd == -1) {
		logerror("%s : %s\n", strerror(errno), device_path);
		return -1;
	    }

	    if (type == 0) {
		type = "fx";	/* an21-compatible for most purposes */
		fx2 = 0;
	    } else if (strcmp (type, "fx2lp") == 0)
                fx2 = 2;
            else
                fx2 = (strcmp (type, "fx2") == 0);

	    if (verbose)
		logerror("microcontroller type: %s\n", type);

	    if (stage1) {
		/* first stage:  put loader into internal memory */
		if (verbose)
		    logerror("1st stage:  load 2nd stage loader\n");
		status = ezusb_load_ram (fd, stage1, fx2, 0);
		if (status != 0)
		    return status;

		/* second stage ... write either EEPROM, or RAM.  */
		if (config >= 0)
		    status = ezusb_load_eeprom (fd, ihex_path, type, config);
		else
		    status = ezusb_load_ram (fd, ihex_path, fx2, 1);
		if (status != 0)
		    return status;
	    } else {
		/* single stage, put into internal memory */
		if (verbose)
		    logerror("single stage:  load on-chip memory\n");
		status = ezusb_load_ram (fd, ihex_path, fx2, 0);
		if (status != 0)
		    return status;
	    }

	    /* some firmware won't renumerate, but typically it will.
	     * link and chmod only make sense without renumeration...
	     */
      }

      if (link_path) {
	    int rc = unlink(link_path);
	    rc = symlink(device_path, link_path);
	    if (rc == -1) {
		  logerror("%s : %s\n", strerror(errno), link_path);
		  return -1;
	    }
      }

      if (mode != 0) {
	    int rc = chmod(device_path, mode);
	    if (rc == -1) {
		  logerror("%s : %s\n", strerror(errno), link_path);
		  return -1;
	    }
      }

      if (!ihex_path && !link_path && !mode) {
	    logerror("missing request! (firmware, link, or mode)\n");
	    return -1;
      }

      return 0;
}
Exemple #3
0
int main(int argc, char*argv[])
{
    fx_known_device known_device[] = FX_KNOWN_DEVICES;
    const char *path[] = { NULL, NULL };
    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, _busnum, _devaddr;
    libusb_device *dev, **devs;
    libusb_device_handle *device = NULL;
    struct libusb_device_descriptor desc;

    while ((opt = getopt(argc, argv, "qvV?hd:p:i:I:t:")) != EOF)
        switch (opt) {

        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 'p':
            device_path = optarg;
            if (sscanf(device_path, "%u,%u", &busnum, &devaddr) != 2 ) {
                fputs ("please specify bus number & device number as \"bus,dev\" in decimal format\n", stderr);
                return -1;
            }
            break;

        case 'i':
        case 'I':
            path[FIRMWARE] = optarg;
            break;

        case 'V':
            puts(FXLOAD_VERSION);
            return 0;

        case 't':
            type = optarg;
            break;

        case 'v':
            verbose++;
            break;

        case 'q':
            verbose--;
            break;

        case '?':
        case 'h':
        default:
            return print_usage(-1);

    }

    if (path[FIRMWARE] == NULL) {
        logerror("no firmware specified!\n");
        return print_usage(-1);
    }
    if ((device_id != NULL) && (device_path != NULL)) {
        logerror("only one of -d or -p can be specified\n");
        return print_usage(-1);
    }

    /* determine the target type */
    if (type != NULL) {
        for (i=0; i<FX_TYPE_MAX; i++) {
            if (strcmp(type, fx_name[i]) == 0) {
                fx_type = i;
                break;
            }
        }
        if (i >= FX_TYPE_MAX) {
            logerror("illegal microcontroller type: %s\n", type);
            return print_usage(-1);
        }
    }

    /* open the device using libusb */
    status = libusb_init(NULL);
    if (status < 0) {
        logerror("libusb_init() failed: %s\n", libusb_error_name(status));
        return -1;
    }
    libusb_set_debug(NULL, verbose);

    /* try to pick up missing parameters from known devices */
    if ((type == NULL) || (device_id == NULL) || (device_path != 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++)
        {
            _busnum = libusb_get_bus_number(dev);
            _devaddr = libusb_get_device_address(dev);
            if ((type != NULL) && (device_path != NULL))
            {
                printf("Check Point 1\n");
                // if both a type and bus,addr were specified, we just need to find our match
                if ((libusb_get_bus_number(dev) == busnum) && (libusb_get_device_address(dev) == devaddr))
                {
                  printf("Check Point 2\n");
                    break;
                }
            }
            else
            {
                status = libusb_get_device_descriptor(dev, &desc);
                if (status >= 0)
                {
                    if (verbose >= 3)
                    {
                        logerror("examining %04x:%04x (%d,%d)\n",
                            desc.idVendor, desc.idProduct, _busnum, _devaddr);
                    }
                    for (j=0; j<ARRAYSIZE(known_device); j++)
                    {
                        if ((desc.idVendor == known_device[j].vid)
                            && (desc.idProduct == known_device[j].pid))
                            {
                            printf("Check Point 3\n");
                            if (// nothing was specified
                                ((type == NULL) && (device_id == NULL) && (device_path == NULL)) ||
                                // vid:pid was specified and we have a match
                                ((type == NULL) && (device_id != NULL) && (vid == desc.idVendor) && (pid == desc.idProduct)) ||
                                // bus,addr was specified and we have a match
                                ((type == NULL) && (device_path != NULL) && (busnum == _busnum) && (devaddr == _devaddr)) ||
                                // type was specified and we have a match
                                ((type != NULL) && (device_id == NULL) && (device_path == NULL) && (fx_type == known_device[j].type)) )
                              {
                                printf("Check Point 4\n");
                                fx_type = known_device[j].type;
                                vid = desc.idVendor;
                                pid = desc.idProduct;
                                busnum = _busnum;
                                devaddr = _devaddr;
                                break;
                              }
                            }
                            printf("Check Point 5\n");
                    }

                    if (j < ARRAYSIZE(known_device))
                    {
                      printf("Check Point 6\n");
                        if (verbose)
                            logerror("found device '%s' [%04x:%04x] (%d,%d)\n",
                                known_device[j].designation, vid, pid, busnum, devaddr);
                        break;
                    }
                }
            }
        }
        if (dev == NULL) {
            printf("Check Point 7\n");
            libusb_free_device_list(devs, 1);
            logerror("could not find a known device - please specify type and/or vid:pid and/or bus,dev\n");
            return print_usage(-1);
        }
        status = libusb_open(dev, &device);
        if (status < 0) {
            logerror("libusb_open() failed: %s\n", libusb_error_name(status));
            goto err;
        }
        libusb_free_device_list(devs, 1);
    } else if (device_id != NULL) {
        printf("Check Point 9\n");
        printf("Check Point 9  vid %d\n", pid);
        printf("Check Point 9  pid %d\n", vid);
        device = libusb_open_device_with_vid_pid(NULL, (uint16_t)vid, (uint16_t)pid);
        if (device == NULL) {
            logerror("libusb_open() failed\n");
            goto err;
        }
    }

    /* We need to claim the first interface */
    printf("Check Point 10\n");
    libusb_set_auto_detach_kernel_driver(device, 1);
    status = libusb_claim_interface(device, 0);
    if (status != LIBUSB_SUCCESS) {
        logerror("libusb_claim_interface failed: %s\n", libusb_error_name(status));
        goto err;
    }

    if (verbose)
        logerror("microcontroller type: %s\n", fx_name[fx_type]);

    for (i=0; i<ARRAYSIZE(path); i++) {
        if (path[i] != NULL) {
            ext = path[i] + strlen(path[i]) - 4;
            if ((_stricmp(ext, ".hex") == 0) || (strcmp(ext, ".ihx") == 0))
                img_type[i] = IMG_TYPE_HEX;
            else if (_stricmp(ext, ".iic") == 0)
                img_type[i] = IMG_TYPE_IIC;
            else if (_stricmp(ext, ".bix") == 0)
                img_type[i] = IMG_TYPE_BIX;
            else if (_stricmp(ext, ".img") == 0)
                img_type[i] = IMG_TYPE_IMG;
            else {
                logerror("%s is not a recognized image type\n", path[i]);
                goto err;
            }
        }
        if (verbose && path[i] != NULL)
            logerror("%s: type %s\n", path[i], img_name[img_type[i]]);
    }

    printf("Check Point 11\n");
    printf("Check Point 11  img_type[FIRMWARE]  %d\n", img_type[FIRMWARE]);
    printf("Check Point 11  fx_type  %d\n", fx_type);

    /* single stage, put into internal memory */
    if (verbose > 1)
        logerror("single stage: load on-chip memory\n");
    status = ezusb_load_ram(device, path[FIRMWARE], fx_type, img_type[FIRMWARE], 0);

    libusb_release_interface(device, 0);
    libusb_close(device);
    libusb_exit(NULL);
    return status;
err:
    libusb_exit(NULL);
    return -1;
}
Exemple #4
0
// Open connection to a Tacx Fortius
//
// The Fortius handlebar controller is an EZ-USB device. This is an
// embedded system using an 8051 microcontroller. Firmware must be
// downloaded to it once it is connected. This firmware is obviously
// copyrighted by Tacx and is not distributed with Golden Cheetah.
// Instead we ask the user to tell us where it can be found when they
// configure the device. (On Windows platforms the firmware is installed
// by the standard Tacx software as c:\windows\system32\FortiusSWPID1942Renum.hex).
//
// So when we open a Fortius device we need to search for an unitialised
// handlebar controller 3651:e6be and upload the firmware using the EzUsb
// functions. Once that has completed the controller will represent itself
// as 3651:1942.
// 
// Firmware will need to be reloaded if the device is disconnected or the
// USB controller is reset after sleep/resume.
//
// The EZUSB code is found in EzUsb.c, which is essentially the code used
// in the 'fxload' command on Linux, some minor changes have been made to the
// standard code wrt to logging errors.
//
// The only function we use is:
// int ezusb_load_ram (usb_dev_handle *device, const char *path, int fx2, int stage)
//      device is a usb device handle
//      path is the filename of the firmware file
//      fx2 is non-zero to indicate an fx2 device (we pass 0, since the Fortius is fx)
//      stage is to control two stage loading, we load in a single stage
struct usb_dev_handle* LibUsb::OpenFortius()
{
    struct usb_bus* bus;
    struct usb_device* dev;
    struct usb_dev_handle* udev;

    bool programmed = false;

    //
    // Search for an UN-INITIALISED Fortius device
    //
    for (bus = usb_get_busses(); bus; bus = bus->next) {


        for (dev = bus->devices; dev; dev = dev->next) {


            if (dev->descriptor.idVendor == FORTIUS_VID && dev->descriptor.idProduct == FORTIUS_INIT_PID) {

                if ((udev = usb_open(dev))) {

                    // LOAD THE FIRMWARE
                    ezusb_load_ram (udev, appsettings->value(NULL, FORTIUS_FIRMWARE, "").toString().toLatin1(), 0, 0);
                }

                // Now close the connection, our work here is done
                usb_close(udev);
                programmed = true;

            }
        }
    }

    // We need to rescan devices, since once the Fortius has
    // been programmed it will present itself again with a
    // different PID. But it takes its time, so we sleep for
    // 3 seconds. This may be too short on some operating
    // systems. We can fix if issues are reported.  On my Linux
    // host running a v3 kernel on an AthlonXP 2 seconds is not
    // long enough.
    // 
    // Given this is only required /the first time/ the Fortius
    // is connected, it can't be that bad?
    if (programmed == true) {
#ifdef WIN32
        Sleep(3000); // windows sleep is in milliseconds
#else
        sleep(3);  // do not be tempted to reduce this, it really does take that long!
#endif
        usb_find_busses();
        usb_find_devices();
    }

    //
    // Now search for an INITIALISED Fortius device
    //
    for (bus = usb_get_busses(); bus; bus = bus->next) {

        for (dev = bus->devices; dev; dev = dev->next) {

            if (dev->descriptor.idVendor == FORTIUS_VID && 
                (dev->descriptor.idProduct == FORTIUS_PID || dev->descriptor.idProduct == FORTIUSVR_PID)) {

                //Avoid noisy output
                //qDebug() << "Found a Garmin USB2 ANT+ stick";

                if ((udev = usb_open(dev))) {

                    if (dev->descriptor.bNumConfigurations) {

                        if ((intf = usb_find_interface(&dev->config[0])) != NULL) {

                            int rc = usb_set_configuration(udev, 1);
                            if (rc < 0) {
                                qDebug()<<"usb_set_configuration Error: "<< usb_strerror();

                                if (OperatingSystem == LINUX) {
                                    // looks like the udev rule has not been implemented
                                    qDebug()<<"check permissions on:"<<QString("/dev/bus/usb/%1/%2").arg(bus->dirname).arg(dev->filename);
                                    qDebug()<<"did you remember to setup a udev rule for this device?";
                                }
                            }

                            rc = usb_claim_interface(udev, interface);
                            if (rc < 0) qDebug()<<"usb_claim_interface Error: "<< usb_strerror();

                            if (OperatingSystem != OSX) {
                                // fails on Mac OS X, we don't actually need it anyway
                                rc = usb_set_altinterface(udev, alternate);
                                if (rc < 0) qDebug()<<"usb_set_altinterface Error: "<< usb_strerror();
                            }

                            return udev;
                        }
                    }

                    usb_close(udev);
                }
            }
        }
    }
    return NULL;
}