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; }
int Eeprom::write(unsigned char *eeprom) { return ftdi_write_eeprom(d->context, eeprom); }
int main(int argc, char *argv[]) { int c; static struct option long_options[] = { {"manufacturer", 1, 0, 'm'}, {"product", 1, 0, 'p'}, {"serial", 1, 0, 's'}, {"verbose", 0, 0, 'v'}, {"help", 0, 0, 'h'}, {NULL, 0, NULL, 0} }; char orig_manufacturer[128]; char* manufacturer = NULL; char orig_product[128]; char* product = NULL; char orig_serial[128]; char* serial = NULL; int bus = -1; int device = -1; struct ftdi_context ftdi; int ires = 0; while ((c = getopt_long(argc, argv, "m:p:s:vh", long_options, &optind)) != -1) { switch (c) { case 'm': manufacturer = optarg; break; case 'p': product = optarg; break; case 's': serial = optarg; break; case 'v': verbose_mode = true; break; case 'h': print_help(argc, argv); return EXIT_SUCCESS; break; } } if (optind + 1 != argc) { print_help(argc, argv); return EXIT_FAILURE; } else { if (!parse_device_identifier(&bus, &device, argv[optind])) { fprintf(stderr, "Unable to parse `%s'\n", argv[optind]); return EXIT_FAILURE; } print_verbose("Using device %03d:%03d\n", bus, device); } libusb_init(NULL); libusb_device** usb_devices; ssize_t n_devices = libusb_get_device_list(NULL, &usb_devices); if (n_devices < 0) { fprintf(stderr, "ERROR: Unable to list USB devices [%zd]: %s\n", n_devices, libusb_strerror((enum libusb_error) n_devices)); return EXIT_FAILURE; } libusb_device* usb_device = NULL; for (int i = 0 ; i < n_devices ; i++) { if (libusb_get_bus_number(usb_devices[i]) == bus && libusb_get_device_address(usb_devices[i]) == device) { usb_device = usb_devices[i]; break; } } if (usb_device == NULL) { fprintf(stderr, "ERROR: Unable to find USB device at %03d:%03d\n", bus, device); return EXIT_FAILURE; } if ((ires = ftdi_init(&ftdi)) != 0) { fprintf(stderr, "ERROR: Unable to initialize libftdi (%d)\n", ires); return EXIT_FAILURE; } if ((ires = ftdi_usb_open_dev(&ftdi, usb_device)) != 0) { fprintf(stderr, "ERROR: Unable to open device (%d)\n", ires); fprintf(stderr, " Perhaps you don't have sufficient permissions (i.e., you aren't root)?\n"); return EXIT_FAILURE; } { struct libusb_device_descriptor desc; if ((ires = libusb_get_device_descriptor(libusb_get_device (ftdi.usb_dev), &desc)) < 0) { fprintf(stderr, "ERROR: Unable to retrieve device descriptor (%d): %s\n", ires, libusb_strerror((enum libusb_error) ires)); return EXIT_FAILURE; } if ((ires = libusb_get_string_descriptor_ascii(ftdi.usb_dev, desc.iManufacturer, (unsigned char*) orig_manufacturer, sizeof(orig_manufacturer))) < 0) { fprintf(stderr, "ERROR: Unable to retrieve manufacturer (%d): %s\n", ires, libusb_strerror((enum libusb_error) ires)); return EXIT_FAILURE; } print_verbose("Old manufacturer: %s\n", orig_manufacturer); if (manufacturer == NULL) manufacturer = orig_manufacturer; if ((ires = libusb_get_string_descriptor_ascii(ftdi.usb_dev, desc.iProduct, (unsigned char*) orig_product, sizeof(orig_product))) < 0) { fprintf(stderr, "ERROR: Unable to retrieve product (%d): %s\n", ires, libusb_strerror((enum libusb_error) ires)); return EXIT_FAILURE; } print_verbose("Old product: %s\n", orig_product); if (product == NULL) product = orig_product; if ((ires = libusb_get_string_descriptor_ascii(ftdi.usb_dev, desc.iSerialNumber, (unsigned char*) orig_serial, sizeof(orig_serial))) < 0) { fprintf(stderr, "ERROR: Unable to retrieve serial (%d): %s\n", ires, libusb_strerror((enum libusb_error) ires)); return EXIT_FAILURE; } print_verbose("Old serial: %s\n", orig_serial); if (serial == NULL) serial = orig_serial; } print_verbose("New manufacturer: %s\n", manufacturer); print_verbose("New product: %s\n", product); print_verbose("New serial: %s\n", serial); if ((ires = ftdi_eeprom_initdefaults (&ftdi, manufacturer, product, serial)) < 0) { fprintf(stderr, "Unable to set EEPROM defaults: %d\n", ires); return EXIT_FAILURE; } if ((ires = ftdi_eeprom_build (&ftdi)) < 0) { fprintf(stderr, "Unable to build EEPROM: %d\n", ires); return EXIT_FAILURE; } if ((ires = ftdi_write_eeprom (&ftdi)) < 0) { fprintf(stderr, "Unable to write EEPROM: %d\n", ires); return EXIT_FAILURE; } ftdi_deinit(&ftdi); return EXIT_SUCCESS; }