Hi!

I'm trying to include some data inside the EEPROM generated by ftdi_eeprom tool.
I modified the ftdi_eeprom tool and libftdi to:

1) Support a "--build-eeprom" command line option that just generates the EEPROM image (only flashed if --flash-eeprom is provided)
2) Support two configuration options:
- user_data_addr an integer indicating the offset where we want to put the user provided data. - user_data_file a string indicating the filename that contains the binary data to be added. 3) Extended libftdi API to store the above mentioned data inside the eeprom struct.
4) Extended ftdi_eeprom_build to include this data.

I'm attaching the output of "git diff".
Is this patch acceptable?

Regards, SET

PS: I fixed a couple of computations that assumed the EEPROM size is 128.

--
Ing. Salvador Eduardo Tropea          http://utic.inti.gob.ar/
INTI - Micro y Nanoelectrónica (CMNB) http://www.inti.gob.ar/
Unidad Técnica Sistemas Inteligentes  Av. General Paz 5445
Tel: (+54 11) 4724 6300 ext. 6919     San Martín - B1650KNA
FAX: (+54 11) 4754 5194               Buenos Aires * Argentina






--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [email protected]   
diff --git a/ftdi_eeprom/main.c b/ftdi_eeprom/main.c
index 455f156..9608c67 100644
--- a/ftdi_eeprom/main.c
+++ b/ftdi_eeprom/main.c
@@ -185,6 +185,7 @@ static void usage(const char *program)
     fprintf(stderr, "         i:<vendor>:<product>:<index>\n");
     fprintf(stderr, "         s:<vendor>:<product>:<serial>\n");
     fprintf(stderr, "--read-eeprom           Read eeprom and write to -filename- from config-file\n");
+    fprintf(stderr, "--build-eeprom          Build eeprom image\n");
     fprintf(stderr, "--erase-eeprom          Erase eeprom\n");
     fprintf(stderr, "--flash-eeprom          Flash eeprom\n");
 }
@@ -253,6 +254,8 @@ int main(int argc, char *argv[])
         CFG_BOOL("chc_rs485", cfg_false, 0),
         CFG_BOOL("chd_rs485", cfg_false, 0),
         CFG_FUNC("include", &cfg_include),
+        CFG_INT("user_data_addr", 0x18, 0),
+        CFG_STR("user_data_file", "", 0),
         CFG_END()
     };
     cfg_t *cfg;
@@ -263,10 +266,13 @@ int main(int argc, char *argv[])
     enum {
         COMMAND_READ = 1,
         COMMAND_ERASE,
-        COMMAND_FLASH
+        COMMAND_FLASH,
+        COMMAND_BUILD
     } command = 0;
     const char *cfg_filename = NULL;
     const char *device_description = NULL;
+    const char *user_data_file = NULL;
+    char *user_data_buffer = NULL;
 
     const int max_eeprom_size = 256;
     int my_eeprom_size = 0;
@@ -307,6 +313,10 @@ int main(int argc, char *argv[])
         {
             command = COMMAND_FLASH;
         }
+        else if (!strcmp(argv[i], "--build-eeprom"))
+        {
+            command = COMMAND_BUILD;
+        }
         else
         {
             usage(argv[0]);
@@ -511,6 +521,42 @@ int main(int argc, char *argv[])
     eeprom_set_value(ftdi, CHANNEL_C_RS485, cfg_getbool(cfg, "chc_rs485"));
     eeprom_set_value(ftdi, CHANNEL_D_RS485, cfg_getbool(cfg, "chd_rs485"));
 
+    /* Arbitrary user data */
+    eeprom_set_value(ftdi, USER_DATA_ADDR, cfg_getint(cfg, "user_data_addr"));
+    user_data_file = cfg_getstr(cfg, "user_data_file");
+    if (user_data_file  && strlen(user_data_file) > 0)
+    {
+        int data_size;
+
+        printf("User data file: %s\n", user_data_file);
+        /* Allocate a buffer for the user data */
+        user_data_buffer = (char *)malloc(max_eeprom_size);
+        if (user_data_buffer == NULL)
+        {
+            fprintf(stderr, "Malloc failed, aborting\n");
+            goto cleanup;
+        }
+
+        /* Read the user data file, no more than max_eeprom_size bytes */
+        FILE *fp = fopen(user_data_file, "rb");
+        if (fp == NULL)
+        {
+            printf ("Can't open user data file %s.\n", user_data_file);
+            exit (-1);
+        }
+        data_size = fread(user_data_buffer, 1, max_eeprom_size, fp);
+        fclose(fp);
+        if (data_size < 1)
+        {
+            printf ("Can't read user data file %s.\n", user_data_file);
+            exit (-1);
+        }
+        printf("User data size: %d\n", data_size);
+
+        ftdi_set_eeprom_user_buf(ftdi, user_data_buffer, data_size);
+    }
+
+
     if (command == COMMAND_ERASE)
     {
         printf("FTDI erase eeprom: %d\n", ftdi_erase_eeprom(ftdi));
@@ -521,7 +567,7 @@ int main(int argc, char *argv[])
 
     if (size_check == -1)
     {
-        printf ("Sorry, the eeprom can only contain 128 bytes.\n");
+        printf ("Sorry, the eeprom can only contain %d bytes.\n", my_eeprom_size);
         goto cleanup;
     }
     else if (size_check < 0)
@@ -558,6 +604,7 @@ int main(int argc, char *argv[])
                 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);
     }
@@ -585,6 +632,8 @@ int main(int argc, char *argv[])
 cleanup:
     if (eeprom_buf)
         free(eeprom_buf);
+    if (user_data_buffer)
+        free(user_data_buffer);
     if (command > 0)
     {
         printf("FTDI close: %d\n", ftdi_usb_close(ftdi));
diff --git a/src/ftdi.c b/src/ftdi.c
index 1b29468..fbb8b7d 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2563,7 +2563,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     unsigned char i, j, eeprom_size_mask;
     unsigned short checksum, value;
     unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
-    int user_area_size;
+    int user_area_size, free_start, free_end;
     struct ftdi_eeprom *eeprom;
     unsigned char * output;
 
@@ -2620,6 +2620,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
             user_area_size = 0;
             break;
     }
+    if (eeprom->size>128) user_area_size+=eeprom->size-128;
     user_area_size  -= (manufacturer_size + product_size + serial_size) * 2;
 
     if (user_area_size < 0)
@@ -2712,6 +2713,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     }
     /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */
     eeprom_size_mask = eeprom->size -1;
+    free_end = i & eeprom_size_mask;
 
     // Addr 0E: Offset of the manufacturer string + 0x80, calculated later
     // Addr 0F: Length of manufacturer string
@@ -2761,6 +2763,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     }
 
     output[0x13] = serial_size*2 + 2;
+    free_start = 0x14;
 
     if (ftdi->type > TYPE_AM) /* use_serial not used in AM devices */
     {
@@ -2829,6 +2832,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
             output[0x0C] = eeprom->usb_version & 0xff;
             output[0x0D] = (eeprom->usb_version>>8) & 0xff;
             output[0x14] = eeprom->chip;
+            free_start = 0x15;
             break;
         case TYPE_R:
             if (eeprom->high_current == HIGH_CURRENT_DRIVE_R)
@@ -2869,6 +2873,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
                 output[0x16] = CBUS_SLEEP;
             else
                 output[0x16] = eeprom->cbus_function[4];
+            free_start = 0x17;
             break;
         case TYPE_2232H:
             output[0x00] = type2bit(eeprom->channel_a_type, TYPE_2232H);
@@ -2929,7 +2934,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
                 output[0x0d] |= SLOW_SLEW<<4;
 
             output[0x18] = eeprom->chip;
-
+            free_start = 0x19;
             break;
         case TYPE_4232H:
             if (eeprom->channel_a_driver == DRIVER_VCP)
@@ -3008,7 +3013,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
                 output[0x0d] |= SLOW_SLEW<<4;
 
             output[0x18] = eeprom->chip;
-
+            free_start = 0x19;
             break;
         case TYPE_232H:
             output[0x00] = type2bit(eeprom->channel_a_type, TYPE_232H);
@@ -3059,6 +3064,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
             set_ft232h_cbus(eeprom, output);
 
             output[0x1e] = eeprom->chip;
+            free_start = 0x1F;
             fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n");
             break;
         case TYPE_230X:
@@ -3071,9 +3077,23 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
                 output[0x1a + j] = eeprom->cbus_function[j];
             }
             output[0x0b] = eeprom->invert;
+            free_start = 0x21;
             break;
     }
 
+    /* Arbitrary user data */
+    if (eeprom->user_data && (eeprom->user_data_size >= 0))
+    {
+        if (eeprom->user_data_addr < free_start)
+            fprintf(stderr,"Warning, user data starts inside the generated data!\n");
+        if (eeprom->user_data_addr + eeprom->user_data_size >= free_end)
+            fprintf(stderr,"Warning, user data overlaps the strings area!\n");
+        if (eeprom->user_data_addr + eeprom->user_data_size > eeprom->size)
+            ftdi_error_return(-1,"eeprom size exceeded");
+        memcpy(output + eeprom->user_data_addr, eeprom->user_data, eeprom->user_data_size);
+        user_area_size -= eeprom->user_data_size;
+    }
+
     // calculate checksum
     checksum = 0xAAAA;
 
@@ -3953,6 +3973,9 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu
         case EXTERNAL_OSCILLATOR:
             ftdi->eeprom->external_oscillator = value;
             break;
+        case USER_DATA_ADDR:
+            ftdi->eeprom->user_data_addr = value;
+            break;
 
         default :
             ftdi_error_return(-1, "Request to unknown EEPROM value");
@@ -3995,7 +4018,7 @@ int ftdi_get_eeprom_buf(struct ftdi_context *ftdi, unsigned char * buf, int size
     \param size Size of buffer
 
     \retval 0: All fine
-    \retval -1: struct ftdi_contxt or ftdi_eeprom of buf missing
+    \retval -1: struct ftdi_context or ftdi_eeprom or buf missing
 */
 int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, int size)
 {
@@ -4011,6 +4034,25 @@ int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, in
     return 0;
 }
 
+/** Set the EEPROM user data content from the user-supplied prefilled buffer
+
+    \param ftdi pointer to ftdi_context
+    \param buf buffer to read EEPROM user data content
+    \param size Size of buffer
+
+    \retval 0: All fine
+    \retval -1: struct ftdi_context or ftdi_eeprom or buf missing
+*/
+int ftdi_set_eeprom_user_buf(struct ftdi_context *ftdi, const char * buf, int size)
+{
+    if (!ftdi || !(ftdi->eeprom) || !buf)
+        ftdi_error_return(-1, "No appropriate structure");
+
+    ftdi->eeprom->user_data_size = size;
+    ftdi->eeprom->user_data = buf;
+    return 0;
+}
+
 /**
     Read eeprom location
 
diff --git a/src/ftdi.h b/src/ftdi.h
index 5aaeb6c..96cc7bb 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -333,6 +333,7 @@ enum ftdi_eeprom_value
     CHANNEL_D_RS485    = 54,
     RELEASE_NUMBER     = 55,
     EXTERNAL_OSCILLATOR= 56,
+    USER_DATA_ADDR     = 57,
 };
 
 /**
@@ -552,6 +553,8 @@ extern "C"
     int ftdi_get_eeprom_buf(struct ftdi_context *ftdi, unsigned char * buf, int size);
     int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, int size);
 
+    int ftdi_set_eeprom_user_buf(struct ftdi_context *ftdi, const char * buf, int size);
+
     int ftdi_read_eeprom(struct ftdi_context *ftdi);
     int ftdi_read_chipid(struct ftdi_context *ftdi, unsigned int *chipid);
     int ftdi_write_eeprom(struct ftdi_context *ftdi);
diff --git a/src/ftdi_i.h b/src/ftdi_i.h
index 060a877..cf2ac78 100644
--- a/src/ftdi_i.h
+++ b/src/ftdi_i.h
@@ -125,6 +125,11 @@ struct ftdi_eeprom
     int data_order;
     int flow_control;
 
+    /** user data **/
+    int user_data_addr;
+    int user_data_size;
+    const char *user_data;
+
     /** eeprom size in bytes. This doesn't get stored in the eeprom
         but is the only way to pass it to ftdi_eeprom_build. */
     int size;

Reply via email to