Пример #1
0
int Eeprom::read(unsigned char *eeprom)
{
    return ftdi_read_eeprom(d->context, eeprom);
}
Пример #2
0
int main(int argc, char *argv[])
{
    /*
    configuration options
    */
    cfg_opt_t opts[] =
    {
        CFG_INT("vendor_id", 0, 0),
        CFG_INT("product_id", 0, 0),
        CFG_BOOL("self_powered", cfg_true, 0),
        CFG_BOOL("remote_wakeup", cfg_true, 0),
        CFG_BOOL("in_is_isochronous", cfg_false, 0),
        CFG_BOOL("out_is_isochronous", cfg_false, 0),
        CFG_BOOL("suspend_pull_downs", cfg_false, 0),
        CFG_BOOL("use_serial", cfg_false, 0),
        CFG_BOOL("change_usb_version", cfg_false, 0),
        CFG_INT("usb_version", 0, 0),
        CFG_INT("default_pid", 0x6001, 0),
        CFG_INT("max_power", 0, 0),
        CFG_STR("manufacturer", "Acme Inc.", 0),
        CFG_STR("product", "USB Serial Converter", 0),
        CFG_STR("serial", "08-15", 0),
        CFG_INT("eeprom_type", 0x00, 0),
        CFG_STR("filename", "", 0),
        CFG_BOOL("flash_raw", cfg_false, 0),
        CFG_BOOL("high_current", cfg_false, 0),
        CFG_STR_LIST("cbus0", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
        CFG_STR_LIST("cbus1", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
        CFG_STR_LIST("cbus2", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
        CFG_STR_LIST("cbus3", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
        CFG_STR_LIST("cbus4", "{TXDEN,PWRON,RXLED,TXLED,TX_RX_LED,SLEEP,CLK48,CLK24,CLK12,CLK6}", 0),
        CFG_BOOL("invert_txd", cfg_false, 0),
        CFG_BOOL("invert_rxd", cfg_false, 0),
        CFG_BOOL("invert_rts", cfg_false, 0),
        CFG_BOOL("invert_cts", cfg_false, 0),
        CFG_BOOL("invert_dtr", cfg_false, 0),
        CFG_BOOL("invert_dsr", cfg_false, 0),
        CFG_BOOL("invert_dcd", cfg_false, 0),
        CFG_BOOL("invert_ri", cfg_false, 0),
        CFG_END()
    };
    cfg_t *cfg;

    /*
    normal variables
    */
    int _read = 0, _erase = 0, _flash = 0;

    const int max_eeprom_size = 256;
    int my_eeprom_size = 0;
    unsigned char *eeprom_buf = NULL;
    char *filename;
    int size_check;
    int i, argc_filename;
    FILE *fp;

    struct ftdi_context *ftdi = NULL;

    printf("\nFTDI eeprom generator v%s\n", EEPROM_VERSION_STRING);
    printf ("(c) Intra2net AG and the libftdi developers <*****@*****.**>\n");

    if (argc != 2 && argc != 3)
    {
        printf("Syntax: %s [commands] config-file\n", argv[0]);
        printf("Valid commands:\n");
        printf("--read-eeprom  Read eeprom and write to -filename- from config-file\n");
        printf("--erase-eeprom  Erase eeprom\n");
        printf("--flash-eeprom  Flash eeprom\n");
        exit (-1);
    }

    if (argc == 3)
    {
        if (strcmp(argv[1], "--read-eeprom") == 0)
            _read = 1;
        else if (strcmp(argv[1], "--erase-eeprom") == 0)
            _erase = 1;
        else if (strcmp(argv[1], "--flash-eeprom") == 0)
            _flash = 1;
        else
        {
            printf ("Can't open configuration file\n");
            exit (-1);
        }
        argc_filename = 2;
    }
    else
    {
        argc_filename = 1;
    }

    if ((fp = fopen(argv[argc_filename], "r")) == NULL)
    {
        printf ("Can't open configuration file\n");
        exit (-1);
    }
    fclose (fp);

    cfg = cfg_init(opts, 0);
    cfg_parse(cfg, argv[argc_filename]);
    filename = cfg_getstr(cfg, "filename");

    if (cfg_getbool(cfg, "self_powered") && cfg_getint(cfg, "max_power") > 0)
        printf("Hint: Self powered devices should have a max_power setting of 0.\n");

    if ((ftdi = ftdi_new()) == 0)
    {
        fprintf(stderr, "Failed to allocate ftdi structure :%s \n",
                ftdi_get_error_string(ftdi));
        return EXIT_FAILURE;
    }

    if (_read > 0 || _erase > 0 || _flash > 0)
    {
        int vendor_id = cfg_getint(cfg, "vendor_id");
        int product_id = cfg_getint(cfg, "product_id");

        i = ftdi_usb_open(ftdi, vendor_id, product_id);

        if (i != 0)
        {
            int default_pid = cfg_getint(cfg, "default_pid");
            printf("Unable to find FTDI devices under given vendor/product id: 0x%X/0x%X\n", vendor_id, product_id);
            printf("Error code: %d (%s)\n", i, ftdi_get_error_string(ftdi));
            printf("Retrying with default FTDI pid=%#04x.\n", default_pid);

            i = ftdi_usb_open(ftdi, 0x0403, default_pid);
            if (i != 0)
            {
                printf("Error: %s\n", ftdi->error_str);
                exit (-1);
            }
        }
    }
    ftdi_eeprom_initdefaults (ftdi, cfg_getstr(cfg, "manufacturer"), 
                              cfg_getstr(cfg, "product"), 
                              cfg_getstr(cfg, "serial"));

    printf("FTDI read eeprom: %d\n", ftdi_read_eeprom(ftdi));
    eeprom_get_value(ftdi, CHIP_SIZE, &my_eeprom_size);
    printf("EEPROM size: %d\n", my_eeprom_size);

    if (_read > 0)
    {
        ftdi_eeprom_decode(ftdi, 1);

        eeprom_buf = malloc(my_eeprom_size);
        ftdi_get_eeprom_buf(ftdi, eeprom_buf, my_eeprom_size);

        if (eeprom_buf == NULL)
        {
            fprintf(stderr, "Malloc failed, aborting\n");
            goto cleanup;
        }
        if (filename != NULL && strlen(filename) > 0)
        {

            FILE *fp = fopen (filename, "wb");
            fwrite (eeprom_buf, 1, my_eeprom_size, fp);
            fclose (fp);
        }
        else
        {
            printf("Warning: Not writing eeprom, you must supply a valid filename\n");
        }

        goto cleanup;
    }

    eeprom_set_value(ftdi, VENDOR_ID, cfg_getint(cfg, "vendor_id"));
    eeprom_set_value(ftdi, PRODUCT_ID, cfg_getint(cfg, "product_id"));

    eeprom_set_value(ftdi, SELF_POWERED, cfg_getbool(cfg, "self_powered"));
    eeprom_set_value(ftdi, REMOTE_WAKEUP, cfg_getbool(cfg, "remote_wakeup"));
    eeprom_set_value(ftdi, MAX_POWER, cfg_getint(cfg, "max_power"));

    eeprom_set_value(ftdi, IN_IS_ISOCHRONOUS, cfg_getbool(cfg, "in_is_isochronous"));
    eeprom_set_value(ftdi, OUT_IS_ISOCHRONOUS, cfg_getbool(cfg, "out_is_isochronous"));
    eeprom_set_value(ftdi, SUSPEND_PULL_DOWNS, cfg_getbool(cfg, "suspend_pull_downs"));

    eeprom_set_value(ftdi, USE_SERIAL, cfg_getbool(cfg, "use_serial"));
    eeprom_set_value(ftdi, USE_USB_VERSION, cfg_getbool(cfg, "change_usb_version"));
    eeprom_set_value(ftdi, USB_VERSION, cfg_getint(cfg, "usb_version"));
    eeprom_set_value(ftdi, CHIP_TYPE, cfg_getint(cfg, "eeprom_type"));

    eeprom_set_value(ftdi, HIGH_CURRENT, cfg_getbool(cfg, "high_current"));
    eeprom_set_value(ftdi, CBUS_FUNCTION_0, str_to_cbus(cfg_getstr(cfg, "cbus0"), 13));
    eeprom_set_value(ftdi, CBUS_FUNCTION_1, str_to_cbus(cfg_getstr(cfg, "cbus1"), 13));
    eeprom_set_value(ftdi, CBUS_FUNCTION_2, str_to_cbus(cfg_getstr(cfg, "cbus2"), 13));
    eeprom_set_value(ftdi, CBUS_FUNCTION_3, str_to_cbus(cfg_getstr(cfg, "cbus3"), 13));
    eeprom_set_value(ftdi, CBUS_FUNCTION_4, str_to_cbus(cfg_getstr(cfg, "cbus4"), 9));
    int invert = 0;
    if (cfg_getbool(cfg, "invert_rxd")) invert |= INVERT_RXD;
    if (cfg_getbool(cfg, "invert_txd")) invert |= INVERT_TXD;
    if (cfg_getbool(cfg, "invert_rts")) invert |= INVERT_RTS;
    if (cfg_getbool(cfg, "invert_cts")) invert |= INVERT_CTS;
    if (cfg_getbool(cfg, "invert_dtr")) invert |= INVERT_DTR;
    if (cfg_getbool(cfg, "invert_dsr")) invert |= INVERT_DSR;
    if (cfg_getbool(cfg, "invert_dcd")) invert |= INVERT_DCD;
    if (cfg_getbool(cfg, "invert_ri")) invert |= INVERT_RI;
    eeprom_set_value(ftdi, INVERT, invert);

    eeprom_set_value(ftdi, CHANNEL_A_DRIVER, DRIVER_VCP);
    eeprom_set_value(ftdi, CHANNEL_B_DRIVER, DRIVER_VCP);
    eeprom_set_value(ftdi, CHANNEL_C_DRIVER, DRIVER_VCP);
    eeprom_set_value(ftdi, CHANNEL_D_DRIVER, DRIVER_VCP);
    eeprom_set_value(ftdi, CHANNEL_A_RS485, 0);
    eeprom_set_value(ftdi, CHANNEL_B_RS485, 0);
    eeprom_set_value(ftdi, CHANNEL_C_RS485, 0);
    eeprom_set_value(ftdi, CHANNEL_D_RS485, 0);

    if (_erase > 0)
    {
        printf("FTDI erase eeprom: %d\n", ftdi_erase_eeprom(ftdi));
    }

    size_check = ftdi_eeprom_build(ftdi);
    eeprom_get_value(ftdi, CHIP_SIZE, &my_eeprom_size);

    if (size_check == -1)
    {
        printf ("Sorry, the eeprom can only contain 128 bytes (100 bytes for your strings).\n");
        printf ("You need to short your string by: %d bytes\n", size_check);
        goto cleanup;
    } else if (size_check < 0) {
        printf ("ftdi_eeprom_build(): error: %d\n", size_check);
    }
    else
    {
        printf ("Used eeprom space: %d bytes\n", my_eeprom_size-size_check);
    }

    if (_flash > 0)
    {
        if (cfg_getbool(cfg, "flash_raw"))
        {
            if (filename != NULL && strlen(filename) > 0)
            {
                eeprom_buf = malloc(max_eeprom_size);
                FILE *fp = fopen(filename, "rb");
                if (fp == NULL)
                {
                    printf ("Can't open eeprom file %s.\n", filename);
                    exit (-1);
                }
                my_eeprom_size = fread(eeprom_buf, 1, max_eeprom_size, fp);
                fclose(fp);
                if (my_eeprom_size < 128)
                {
                    printf ("Can't read eeprom file %s.\n", filename);
                    exit (-1);
                }

                ftdi_set_eeprom_buf(ftdi, eeprom_buf, my_eeprom_size);
            }
        }
        printf ("FTDI write eeprom: %d\n", ftdi_write_eeprom(ftdi));
        libusb_reset_device(ftdi->usb_dev);
    }

    // Write to file?
    if (filename != NULL && strlen(filename) > 0 && !cfg_getbool(cfg, "flash_raw"))
    {
        fp = fopen(filename, "w");
        if (fp == NULL)
        {
            printf ("Can't write eeprom file.\n");
            exit (-1);
        }
        else
            printf ("Writing to file: %s\n", filename);

        if (eeprom_buf == NULL)
            eeprom_buf = malloc(my_eeprom_size);
        ftdi_get_eeprom_buf(ftdi, eeprom_buf, my_eeprom_size);

        fwrite(eeprom_buf, my_eeprom_size, 1, fp);
        fclose(fp);
    }

cleanup:
    if (eeprom_buf)
        free(eeprom_buf);
    if (_read > 0 || _erase > 0 || _flash > 0)
    {
        printf("FTDI close: %d\n", ftdi_usb_close(ftdi));
    }

    ftdi_deinit (ftdi);
    ftdi_free (ftdi);

    cfg_free(cfg);

    printf("\n");
    return 0;
}
int main(int argc, char *argv[])
{
    int ret, i;
    struct ftdi_device_list *devlist, *curdev;
    struct ftdi_context ftdic;
    struct ftdi_eeprom  eeprom;

    for (i = 0; i < CBUS_NUM; i++)
    {
        apcCBUS[i] = NULL;
    }

    {
        static struct option long_options[] =
        {

            {"help",                    no_argument,        NULL, 'h'},
            {"verbosity",               required_argument,  NULL, 'V'},

            {"vid",                     required_argument,  NULL, 'v'},
            {"pid",                     required_argument,  NULL, 'p'},

            {"manufacturer",            required_argument,  NULL, 'm'},
            {"description",             required_argument,  NULL, 'd'},

            {"serial",                  required_argument,  NULL, 's'},
            {"autoserial",              required_argument,  NULL, 'a'},

            {"C0",                      required_argument,  NULL, '0'},
            {"C1",                      required_argument,  NULL, '1'},
            {"C2",                      required_argument,  NULL, '2'},
            {"C3",                      required_argument,  NULL, '3'},
            {"C4",                      required_argument,  NULL, '4'},

            { NULL, 0, NULL, 0}
        };
        signed char opt;
        int option_index;

        while ((opt = getopt_long(argc, argv, "hV:v:p:m:d:s:a:0:1:2:3:4:", long_options, &option_index)) != -1)
        {
            switch (opt)
            {
            case 'h':
                print_usage_exit(argv);
                break;

            case 'V':
                if (iMyStrtoul(&u32Verbosity, optarg, "verbosity", 2))
                {
                    return EXIT_FAILURE;
                }
                break;

            case 'v':
                if (iMyStrtoul(&u32VID, optarg, "vendor id", 0xFFFF))
                {
                    return EXIT_FAILURE;
                }
                break;

            case 'p':
                if (iMyStrtoul(&u32PID, optarg, "product id", 0xFFFF))
                {
                    return EXIT_FAILURE;
                }
                break;

            case 'm':
                pcManufacturer = optarg;
                break;

            case 'd':
                pcDescription = optarg;
                break;

            case 's':
                pcSerial = optarg;
                break;

            case 'a':
                pcAutoSerial = optarg;
                break;

            case '0':
                apcCBUS[0] = optarg;
                break;

            case '1':
                apcCBUS[1] = optarg;
                break;

            case '2':
                apcCBUS[2] = optarg;
                break;

            case '3':
                apcCBUS[3] = optarg;
                break;

            case '4':
                apcCBUS[4] = optarg;
                break;

            default: /* '?' */
                print_usage_exit(argv);
            }
        }
    }

    printf("FTProg FTDI Programmer version %s\n\r", Version);

    /* Handle serial numbers */
    if (pcSerial && pcAutoSerial)
    {
        fprintf(stderr, "Please specify only one of serial number and autoserial\n\r");
        return EXIT_FAILURE;
    }

    if (pcSerial)
    {
        if (strlen(pcSerial) != 8)
        {
            fprintf(stderr, "Serial number must be 8 character string\n\r");
            return EXIT_FAILURE;
        }
    }

    if (pcAutoSerial)
    {
        int fd;
        if (strlen(pcAutoSerial) != 2)
        {
            fprintf(stderr, "Serial number prefix must be 2 character string\n\r");
            return EXIT_FAILURE;
        }

        pcSerial = malloc(sizeof(char) * 9);
        if (!pcSerial)
        {
            fprintf(stderr, "Memory error\n");
            return EXIT_FAILURE;
        }
        pcSerial[0] = pcAutoSerial[0];
        pcSerial[1] = pcAutoSerial[1];

        if ((fd = open("/dev/urandom", O_RDONLY)) < 0)
        {
            fprintf(stderr, "Could not open /dev/urandom (%s)\n\r", strerror(errno));
            return EXIT_FAILURE;
        }
        for (i = 2; i < 8; i++)
        {
            uint32_t j;
            read(fd, &j, 1);
            pcSerial[i] = "0123456789ABCDEF"[j % 16];
        }
        close(fd);

        pcSerial[8] = '\0';
        if (u32Verbosity > 0)
        {
            printf("Autogenerated serial number: '%s'\n", pcSerial);
        }
    }


    for (i = 0; i < CBUS_NUM; i++)
    {
        if (apcCBUS[i])
        {
            int j, iFound = 0;
            for (j = 0; j < (sizeof(asCBUSModeLookup)/sizeof(tsCBUSModeLookup)); j++)
            {
                if (strcmp(apcCBUS[i], asCBUSModeLookup[j].pcDescription) == 0)
                {
                    iFound = 1;
                    apsCBUS_Function[i] = &asCBUSModeLookup[j];
                }
            }
            if (!iFound)
            {
                fprintf(stderr, "Invalid C%d '%s'\n\r", i, apcCBUS[i]);
                return EXIT_FAILURE;
            }
        }
    }

    if (ftdi_init(&ftdic) < 0)
    {
        fprintf(stderr, "ftdi_init failed\n");
        return EXIT_FAILURE;
    }

    if ((ret = ftdi_usb_find_all(&ftdic, &devlist, u32VID, u32PID)) < 0)
    {
        fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
        return EXIT_FAILURE;
    }

    printf("Number of FTDI devices found: %d\n", ret);

    for (i=0, curdev = devlist; curdev != NULL; i++, curdev = curdev->next)
    {
        printf(" Updating device: %d\n\r", i);

        if ((ret = ftdi_usb_open_dev(&ftdic, curdev->dev)) < 0)
        {
            fprintf(stderr, "ftdi_usb_open_dev failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
            return EXIT_FAILURE;
        }

        // Read out FTDIChip-ID of R type chips
        if (ftdic.type == TYPE_R)
        {
            unsigned char *pcEepromBuffer = NULL;
            unsigned int chipid;

            if ((ret = ftdi_read_chipid(&ftdic, &chipid)) < 0)
            {
                fprintf(stderr, "ftdi_read_chipid failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
                return EXIT_FAILURE;
            }

            printf("  FTDI chipid: %X\n", chipid);

            /* EEPROM is 160 bytes */
            ftdi_eeprom_setsize(&ftdic, &eeprom, 160);

            printf("  EEPROM size: %d bytes\n", ftdic.eeprom_size);
            pcEepromBuffer = malloc(ftdic.eeprom_size);
            if (!pcEepromBuffer)
            {
                fprintf(stderr, "Memory error!");
                return EXIT_FAILURE;
            }
            else
            {

                int i;
                if ((ret = ftdi_read_eeprom(&ftdic, pcEepromBuffer)) < 0)
                {
                    fprintf(stderr, "ftdi_read_eeprom failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
                    return EXIT_FAILURE;
                }
                if ((ret = ftdi_eeprom_decode(&eeprom, pcEepromBuffer, ftdic.eeprom_size)) < 0)
                {
                    if (ret != -1)
                    {
                        /* Avoid errors due to hard coded size causing checksum to fail. */
                        fprintf(stderr, "Error decoding eeprom buffer: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
                        return EXIT_FAILURE;
                    }
                }

                if (u32Verbosity > 0)
                {
                    printf("    Current Vendor: %d, %s\n", eeprom.vendor_id, eeprom.manufacturer);
                    printf("    Current Product: %d, %s\n", eeprom.product_id, eeprom.product);
                    printf("    Current Serial: %s\n", eeprom.serial);

                    if (u32Verbosity >= 2)
                    {
                        printf("      Current EEPROM Contents\n\r");
                        for (i = 0; i < ftdic.eeprom_size; i+=2)
                        {
                            if ((i % 16) == 0)
                            {
                                printf("        %04x:", i/2);
                            }
                            printf(" 0x%02x%02x", pcEepromBuffer[i],pcEepromBuffer[i+1]);
                            if ((i % 16) == 14)
                            {
                                printf("\n\r");
                            }
                        }
                    }
                }

                if (pcManufacturer)
                {
                    printf("  Setting manufacturer: '%s'\n\r", pcManufacturer);
                    free(eeprom.manufacturer);
                    eeprom.manufacturer     = pcManufacturer;
                }

                if (pcDescription)
                {
                    printf("  Setting description: '%s'\n\r", pcDescription);
                    free(eeprom.product);
                    eeprom.product          = pcDescription;
                }

                if (pcSerial)
                {
                    printf("  Setting serial number: '%s'\n\r", pcSerial);
                    free(eeprom.serial);
                    eeprom.serial           = pcSerial;
                }

                for (i = 0; i < CBUS_NUM; i++)
                {
                    if (apcCBUS[i])
                    {
                        /* Argument given */
                        printf("  Setting C%d: '%s' (%d)\n\r", i,
                               apsCBUS_Function[i]->pcDescription,
                               apsCBUS_Function[i]->iCBUSMode);

                        eeprom.cbus_function[i] = apsCBUS_Function[i]->iCBUSMode;
                    }
                }

                /* EEPROM is 160 bytes */
                ftdi_eeprom_setsize(&ftdic, &eeprom, 160);

                if ((ret = ftdi_eeprom_build(&eeprom, pcEepromBuffer)) < 0)
                {
                    fprintf(stderr, "ftdi_eeprom_build failed: %d (%s)\n\r", ret, ftdi_get_error_string(&ftdic));
                    return -1;
                }

                if ((ret = ftdi_write_eeprom(&ftdic, pcEepromBuffer)) < 0)
                {
                    fprintf(stderr, "ftdi_write_eeprom failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic));
                    return -1;
                }
                printf("  Wrote new EEPROM data successfully\n\r");
            }
        }

        if ((ret = ftdi_usb_close(&ftdic)) < 0)
        {
            fprintf(stderr, "ftdi_usb_close failed: %d (%s)\n\r", ret, ftdi_get_error_string(&ftdic));
            return EXIT_FAILURE;
        }
    }

    ftdi_list_free(&devlist);
    ftdi_deinit(&ftdic);
    return EXIT_SUCCESS;
}