/*************************************************************************** main.c - description ------------------- begin : Mon Apr 7 12:05:22 CEST 2003 copyright : (C) 2003 by Intra2net AG email : opensource@intra2net.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 * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* FH - dodelavane funkce: 1) v conf souboru je mozne specifikovat VID a PID pod kterym se bude k eeprom pristupovat (vendor_id a product_id je nyni jen pro novy obsah) 2) --write-eeprom (novy prikaz): zapise do eeprom obsah souboru filename a pripadne definice hodnot v conf souboru a do souboru filenameo (if je definovan) zapise puvodni obsah eeprom. 3) --update-eeprom (novy prikaz): v eeprom zmeni pouze hodnoty definovane v conf souboru, do souboru filenameo (if definovan) zapise puvodni obsah eeprom a do souboru filename (if definovan) zapise novy obsah eeprom. 4) --list-eeprom (novy prikaz): na stdout vypise obsah eeprom. 5) --flash-eeprom (update): do souboru filenameo (if definovan) zapise puvodni obsah eeprom 6) prehlednejsi chybova hlaseni */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include cfg_t *cfg; /* normal variables */ int _read = 0, _write = 0, _update = 0, _list = 0,_erase = 0, _flash = 0; int vendoro_id, producto_id, vendorid, productid; unsigned char eeprom_buf[128], vata[128]; unsigned char r_manufacturer[128], r_product[128],r_serial[128]; char *filename, *filenameo; FILE *fp; struct ftdi_context ftdi; struct ftdi_eeprom eeprom; int main(int argc, char *argv[]) { /* configuration options */ cfg_opt_t opts[] = { CFG_INT("vendor_id", 0, CFGF_NODEFAULT), CFG_INT("product_id", 0, CFGF_NODEFAULT), CFG_INT("vendoro_id", 0, 0), CFG_INT("producto_id", 0, 0), CFG_BOOL("self_powered", cfg_true, CFGF_NODEFAULT), CFG_BOOL("remote_wakeup", cfg_true, CFGF_NODEFAULT), CFG_BOOL("BM_type_chip", cfg_true, CFGF_NODEFAULT), CFG_BOOL("in_is_isochronous", cfg_false, CFGF_NODEFAULT), CFG_BOOL("out_is_isochronous", cfg_false, CFGF_NODEFAULT), CFG_BOOL("suspend_pull_downs", cfg_false, CFGF_NODEFAULT), CFG_BOOL("use_serial", cfg_false, CFGF_NODEFAULT), CFG_BOOL("change_usb_version", cfg_false, CFGF_NODEFAULT), CFG_INT("usb_version", 0, CFGF_NODEFAULT), CFG_INT("max_power", 0, CFGF_NODEFAULT), CFG_STR("manufacturer", "Acme Inc.", CFGF_NODEFAULT), CFG_STR("product", "USB Serial Converter", CFGF_NODEFAULT), CFG_STR("serial", "08-15", CFGF_NODEFAULT), CFG_STR("filename", "", CFGF_NODEFAULT), CFG_STR("filenameo", "", 0), CFG_END() }; int size_check; int i, j, argc_filename; /* write 128 bytes of eeprom binary image in eeprom_buf to file specified as parameter */ int wb2filename (char *ofilename){ int retval; retval = 0; if (ofilename != NULL && strlen(ofilename) > 0) { fp = fopen(ofilename, "wb"); if (fp == NULL) { printf ("Can't write eeprom data to file \"%s\".\n",ofilename); return (-1); } else { retval = fwrite(eeprom_buf, 128, 1, fp); printf ("Writing %i x 128 bytes to file \"%s\"\n",retval, ofilename); fclose(fp); } } return (retval); } /* fill values into ftdi_eeprom struct: - if parameter = 0, then only values from config file - otherwise fill first default program values and then those from conf file */ int opt2eeprom(int dftoo) { int jp; jp=0; if ( dftoo != 0 ) { eeprom.vendor_id=0x0403; // Vendor ID eeprom.product_id=0x6001; // Product ID eeprom.max_power=0; // Max. power consumption: value * 2 mA. Use 0 if self_powered = true. eeprom.manufacturer="ACME Inc"; // Manufacturer eeprom.product="USB Serial Converter"; // Product eeprom.serial="08-15"; // Serial eeprom.self_powered=1; // Turn this off for bus powered eeprom.remote_wakeup=0; // Turn this on for remote wakeup feature eeprom.use_serial=0; // Use the serial number string eeprom.BM_type_chip=1; // Newer chips are all BM type eeprom.in_is_isochronous=0; // In Endpoint is Isochronous eeprom.out_is_isochronous=0; // Out Endpoint is Isochronous eeprom.suspend_pull_downs=0; // Enable suspend pull downs for lower power eeprom.change_usb_version=0; // Change USB Version eeprom.usb_version=0x0200; // Only used when change_usb_version is enabled // jp=15; } if (cfg_size(cfg, "vendor_id") >0){ eeprom.vendor_id = cfg_getint(cfg, "vendor_id"); jp++; } if (cfg_size(cfg, "product_id") >0){ eeprom.product_id = cfg_getint(cfg, "product_id"); jp++; } if (cfg_size(cfg, "BM_type_chip") >0){ eeprom.BM_type_chip = cfg_getbool(cfg, "BM_type_chip"); jp++; } if (cfg_size(cfg, "self_powered") >0){ eeprom.self_powered = cfg_getbool(cfg, "self_powered"); jp++; } if (cfg_size(cfg, "remote_wakeup") >0){ eeprom.remote_wakeup = cfg_getbool(cfg, "remote_wakeup"); jp++; } if (cfg_size(cfg, "max_power") >0){ eeprom.max_power = cfg_getint(cfg, "max_power"); jp++; } if (cfg_size(cfg, "in_is_isochronous") >0){ eeprom.in_is_isochronous = cfg_getbool(cfg, "in_is_isochronous"); jp++; } if (cfg_size(cfg, "out_is_isochronous") >0){ eeprom.out_is_isochronous = cfg_getbool(cfg, "out_is_isochronous"); jp++; } if (cfg_size(cfg, "suspend_pull_downs") >0){ eeprom.suspend_pull_downs = cfg_getbool(cfg, "suspend_pull_downs"); jp++; } if (cfg_size(cfg, "use_serial") >0){ eeprom.use_serial = cfg_getbool(cfg, "use_serial"); jp++; } if (cfg_size(cfg, "change_usb_version") >0){ eeprom.change_usb_version = cfg_getbool(cfg, "change_usb_version"); jp++; } if (cfg_size(cfg, "usb_version") >0){ eeprom.usb_version = cfg_getint(cfg, "usb_version"); jp++; } if (cfg_size(cfg, "manufacturer") >0){ eeprom.manufacturer = cfg_getstr(cfg, "manufacturer"); jp++; } if (cfg_size(cfg, "product") >0){ eeprom.product = cfg_getstr(cfg, "product"); jp++; } if (cfg_size(cfg, "serial") >0){ eeprom.serial = cfg_getstr(cfg, "serial"); jp++; } return (jp); } //------------------------- main start -------------------------- printf("\nFTDI eeprom generator v%s\n", VERSION); printf ("(c) Intra2net AG \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("--write-eeprom write eeprom with contents of -filename- + config-values\n"); printf("--update-eeprom update only values in config file\n"); printf("--list-eeprom print eeprom data on stdout\n"); printf("--erase-eeprom Erase eeprom\n"); printf("--flash-eeprom Flash eeprom with program defaults + config-values\n"); exit (-1); } if (argc == 3) { if (strcmp(argv[1], "--write-eeprom") == 0) _write = 1; if (strcmp(argv[1], "--update-eeprom") == 0) _update = 1; if (strcmp(argv[1], "--list-eeprom") == 0) _list = 1; if (strcmp(argv[1], "--read-eeprom") == 0) _read = 1; if (strcmp(argv[1], "--erase-eeprom") == 0) _erase = 1; if (strcmp(argv[1], "--flash-eeprom") == 0) _flash = 1; argc_filename = 2; } else { argc_filename = 1; } if ((fp = fopen(argv[argc_filename], "r")) == NULL) { printf ("Can't open configuration file \"%s\"\n",argv[argc_filename]); exit (-1); } fclose (fp); cfg = cfg_init(opts, 0); cfg_parse(cfg, argv[argc_filename]); filename = cfg_getstr(cfg, "filename"); filenameo = cfg_getstr(cfg, "filenameo"); vendoro_id = cfg_getint(cfg, "vendoro_id"); producto_id = cfg_getint(cfg, "producto_id"); if (cfg_size(cfg, "self_powered") > 0){ if (cfg_getbool(cfg, "self_powered")){ if (cfg_size(cfg, "max_power") != 0){ printf("Hint: Self powered devices may not have specified max_power setting (assumed 0).\n"); } } else { if (cfg_size(cfg, "max_power") == 0){ printf("Hint: USB bus powered devices may have specified max_power setting.\n"); } else { if (cfg_getint(cfg, "max_power") == 0){ printf("Hint: USB bus powered devices should have a max_power setting > 0.\n"); } } } } else { if (cfg_size(cfg, "max_power") != 0){ if (cfg_getint(cfg, "max_power") == 0){ printf("Hint: Self powered devices should have specified parameter self_powered=1\n"); } } } ftdi_eeprom_initdefaults (&eeprom); if (_read > 0 || _write > 0 || _update > 0 || _list > 0 || _erase > 0 || _flash > 0) { printf("FTDI init: %d\n", ftdi_init(&ftdi)); if ((vendoro_id != 0) || (producto_id != 0)) { vendorid = vendoro_id; productid = producto_id; i = ftdi_usb_open(&ftdi, vendorid, productid); if (i != 0) { printf("Unable to find FTDI devices under given vendor/product id: 0x%X/0x%X (libftdi ftdi_usb_open err %d)\n", vendorid, productid, i); exit (-1); } else { printf("FTDI device opened at given vendor/product id (0x%X/0x%X)\n", vendorid, productid); } } else { if ((cfg_size(cfg, "vendor_id") != 0) && (cfg_size(cfg, "product_id") != 0)) { vendorid = cfg_getint(cfg, "vendor_id"); productid = cfg_getint(cfg, "product_id"); i = ftdi_usb_open(&ftdi, vendorid, productid); if (i == 0) { printf("FTDI device opened at given vendor/product id (0x%X/0x%X)\n", vendorid, productid); } else { printf("Unable to find FTDI devices under given vendor/product id: 0x%X/0x%X (libftdi ftdi_usb_open err %d)\n", vendorid, productid, i); } } if ( i != 0) { vendorid = 0x0403; productid = 0x6001; printf("Retrying with default FTDI id (0x%04X,0x%04X).\n",vendorid,productid); i = ftdi_usb_open(&ftdi, vendorid, productid); if (i != 0) { printf("Sorry, unable to find FTDI USB chip(libftdi ftdi_usb_open err %d)\n",i); exit (-1); } } } printf("FTDI read eeprom data: %d\n", ftdi_read_eeprom(&ftdi, (char *)&eeprom_buf)); } // eeprom data are in eeprom_buf -------------------------^ if (_read > 0) { i = wb2filename (filename); if (i == 0 ){ printf("FTDI read eeprom Warning: Not writing eeprom data to external file,\n you must supply a valid filename\n"); } goto cleanup; } if (_write > 0 ) { // write image + config file definitions to eeprom i = wb2filename (filenameo); // existing old eeprom image to backup file if (i == 0 ){ printf("Warning: filename for old contens wasn't specified, write without backup\n"); } if (filename != NULL && strlen(filename) > 0) { FILE *fp = fopen (filename, "rb"); size_check = fread (&eeprom_buf, 1, 130, fp); fclose (fp); if ( size_check != 128 ) { printf ("Sorry, the eeprom image must be 128 bytes long.\n"); printf ("File \"%s\" isn't valid eeprom image (%d bytes read)\n", filename, size_check); goto cleanup; } else { i = ftdi_eeprom_fill(&eeprom, eeprom_buf, r_manufacturer, r_product,r_serial); // fill and check ftdi_eeprom struct switch (i) { case -1: printf ("Incorrect eeprom image checksum !\n"); goto cleanup; case -2: printf ("Eeprom image has invalid total (manufacturer+product+serila) string length !\n"); goto cleanup; case -3: printf ("Incorrect eeprom image manufacturer string !\n"); goto cleanup; case -4: printf ("Incorrect eeprom image product string !\n"); goto cleanup; case -5: printf ("Incorrect eeprom image serial string !\n"); goto cleanup; case 0: printf ("eeprom image check: OK\n"); break; } opt2eeprom(0); // fill items from conf file to eeprom struct size_check = ftdi_eeprom_build(&eeprom, eeprom_buf); 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 { printf ("Used eeprom space: %d bytes, %d items changed from config file\n", 128-size_check,j); printf ("FTDI write eeprom: %d\n", ftdi_write_eeprom(&ftdi, (char *)&eeprom_buf)); } } } else { printf("Warning: Not writing eeprom, you must supply a valid filename\n"); } goto cleanup; } if (_update > 0 ) { // update eeprom with config file definitions i = wb2filename (filenameo); // existing old eeprom image to backup file if (i == 0 ){ printf("Warning: filename for old contens wasn't specified, write without backup\n"); } i = ftdi_eeprom_fill(&eeprom, eeprom_buf, r_manufacturer, r_product, r_serial); // fill and check ftdi_eeprom struct switch (i) { case -1: printf ("Incorrect eeprom image checksum !\n"); goto cleanup; case -2: printf ("Eeprom image has invalid total (manufacturer+product+serila) string length !\n"); goto cleanup; case -3: printf ("Incorrect eeprom image manufacturer string !\n"); goto cleanup; case -4: printf ("Incorrect eeprom image product string !\n"); goto cleanup; case -5: printf ("Incorrect eeprom image serial string !\n"); goto cleanup; case 0: printf ("eeprom image check: OK\n"); break; } opt2eeprom(0); // fill items from conf file to eeprom struct size_check = ftdi_eeprom_build(&eeprom, eeprom_buf); 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 { printf ("Used eeprom space: %d bytes, %d items changed from config file\n", 128-size_check,j); printf ("FTDI update eeprom: %d\n", ftdi_write_eeprom(&ftdi, (char *)&eeprom_buf)); wb2filename(filename); // write new eeprom image to file, if specified } goto cleanup; } if (_list > 0 ) { // list eeprom i = ftdi_eeprom_fill(&eeprom, eeprom_buf, r_manufacturer, r_product, r_serial); // fill and check ftdi_eeprom struct switch (i) { case -1: printf ("Incorrect eeprom image checksum !\n"); break; case -2: printf ("Eeprom image has invalid total (manufacturer+product+serila) string length !\n"); break; case -3: printf ("Incorrect eeprom image manufacturer string !\n"); break; case -4: printf ("Incorrect eeprom image product string !\n"); break; case -5: printf ("Incorrect eeprom image serial string !\n"); break; case 0: printf ("eeprom image check: OK\n"); break; } printf ("Vendor ID:\t0x%04x\n",eeprom.vendor_id); printf ("Product ID:\t0x%04x\n",eeprom.product_id); printf ("Manufacturer:\t%s\n",eeprom.manufacturer); printf ("Product:\t%s\n",eeprom.product); printf ("Serial:\t\t%s\n",eeprom.serial); printf ("Self_Powered:\t%d\n",eeprom.self_powered); printf ("Max_power:\t%d\n",eeprom.max_power); printf ("Remote_wakeup:\t%d\n",eeprom.remote_wakeup); printf ("BM_type_chip:\t%d\n",eeprom.BM_type_chip); printf ("In_is_isochronous:\t%d\n",eeprom.in_is_isochronous); printf ("Out_is_isochronous:\t%d\n",eeprom.out_is_isochronous); printf ("Suspend_pull_downs:\t%d\n",eeprom.suspend_pull_downs); printf ("Use_serial:\t\t%d\n",eeprom.use_serial); printf ("Change_usb_version:\t%d\n",eeprom.change_usb_version); printf ("Usb_version:\t\t0x%04x\n",eeprom.usb_version); goto cleanup; } if (_erase > 0) { printf("FTDI erase eeprom: %d\n", ftdi_erase_eeprom(&ftdi)); goto cleanup; } if (_flash > 0) { wb2filename(filenameo); // write existing eeprom image to file, if specified opt2eeprom(1); // fill default + items from conf file to eeprom struct size_check = ftdi_eeprom_build(&eeprom, eeprom_buf); 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 { printf ("Used eeprom space: %d bytes\n", 128-size_check); } printf ("FTDI flash eeprom: %d\n", ftdi_write_eeprom(&ftdi, (char *)&eeprom_buf)); wb2filename(filename); // write new eeprom image to file, if specified } cleanup: if (_read > 0 || _write > 0 || _update > 0 || _erase > 0 || _flash > 0) { printf("FTDI close: %d\n", ftdi_usb_close(&ftdi)); } ftdi_deinit (&ftdi); cfg_free(cfg); printf("\n"); return 0; }