Include PnP descriptor in size check
[libftdi] / src / ftdi.c
index 2b5003a..b613721 100644 (file)
@@ -2267,7 +2267,7 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer,
 
     \param ftdi pointer to ftdi_context
 
-    \retval >0: free eeprom size
+    \retval >=0: size of eeprom user area in bytes
     \retval -1: eeprom size (128 bytes) exceeded by custom strings
     \retval -2: Invalid eeprom pointer
     \retval -3: Invalid cbus function setting
@@ -2280,7 +2280,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 size_check;
+    int user_area_size;
     struct ftdi_eeprom *eeprom;
     unsigned char * output;
 
@@ -2307,31 +2307,28 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     if (eeprom->serial != NULL)
         serial_size = strlen(eeprom->serial);
 
-    size_check = 0x80;
-    switch(ftdi->type)
+    // eeprom size check
+    switch (ftdi->type)
     {
-    case TYPE_2232H:
-    case TYPE_4232H:
-        size_check -= 4;
-    case TYPE_R:
-        size_check -= 4;
-    case TYPE_2232C:
-        size_check -= 4;
-    case TYPE_AM:
-    case TYPE_BM:
-        size_check -= 0x14*2;
+        case TYPE_AM:
+        case TYPE_BM:
+            user_area_size = 96;    // base size for strings (total of 48 characters)
+            break;
+        case TYPE_2232C:
+           user_area_size = 90;     // two extra config bytes and 4 bytes PnP stuff
+           break;
+        case TYPE_R:
+           user_area_size = 88;     // four extra config bytes + 4 bytes PnP stuff
+           break;
+        case TYPE_2232H:            // six extra config bytes + 4 bytes PnP stuff
+        case TYPE_4232H:
+           user_area_size = 86;
+           break;
     }
+    user_area_size  -= (manufacturer_size + product_size + serial_size) * 2;
 
-    size_check -= manufacturer_size*2;
-    size_check -= product_size*2;
-    size_check -= serial_size*2;
-
-    /* Space for the string type and pointer bytes */
-    size_check -= -9;
-
-    // eeprom size exceeded?
-    if (size_check < 0)
-        return (-1);
+    if (user_area_size < 0)
+        ftdi_error_return(-1,"eeprom size exceeded");
 
     // empty eeprom
     memset (ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE);
@@ -2348,7 +2345,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
 
     // Addr 06: Device release number (0400h for BM features)
     output[0x06] = 0x00;
-    switch (ftdi->type) {
+    switch (ftdi->type)
+    {
         case TYPE_AM:
             output[0x07] = 0x02;
             break;
@@ -2461,24 +2459,27 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
         output[i & eeprom_size_mask] = eeprom->serial[j], i++;
         output[i & eeprom_size_mask] = 0x00, i++;
     }
-    output[i & eeprom_size_mask] = 0x02; /* as seen when written with FTD2XX */
-    i++;
-    output[i & eeprom_size_mask] = 0x03; /* as seen when written with FTD2XX */
-    i++;
-    output[i & eeprom_size_mask] = eeprom->is_not_pnp; /* as seen when written with FTD2XX */
-    i++;
+
+    // Legacy port name and PnP fields for FT2232 and newer chips
+    if (ftdi->type > TYPE_BM)
+    {
+        output[i & eeprom_size_mask] = 0x02; /* as seen when written with FTD2XX */
+        i++;
+        output[i & eeprom_size_mask] = 0x03; /* as seen when written with FTD2XX */
+        i++;
+        output[i & eeprom_size_mask] = eeprom->is_not_pnp; /* as seen when written with FTD2XX */
+        i++;
+    }
 
     output[0x13] = serial_size*2 + 2;
 
-    if(ftdi->type > TYPE_AM) /*use_serial not used in AM devices*/
+    if(ftdi->type > TYPE_AM) /* use_serial not used in AM devices */
     {
         if (eeprom->use_serial == USE_SERIAL_NUM )
             output[0x0A] |= USE_SERIAL_NUM;
         else
             output[0x0A] &= ~USE_SERIAL_NUM;
     }
-    /* Fixme: ftd2xx seems to append 0x02, 0x03 and 0x01 for PnP = 0 or 0x00 else */
-    // calculate checksum
 
     /* Bytes and Bits specific to (some) types
        Write linear, as this allows easier fixing*/
@@ -2489,7 +2490,6 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     case TYPE_BM:
         output[0x0C] = eeprom->usb_version & 0xff;
         output[0x0D] = (eeprom->usb_version>>8) & 0xff;
-        output[0x14] = eeprom->chip;
         break;
     case TYPE_2232C:
 
@@ -2649,7 +2649,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     output[eeprom->size-2] = checksum;
     output[eeprom->size-1] = checksum >> 8;
 
-    return size_check;
+    return user_area_size;
 }
 
 /**
@@ -2694,9 +2694,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
     // Bit 7: always 1
     // Bit 6: 1 if this device is self powered, 0 if bus powered
     // Bit 5: 1 if this device uses remote wakeup
-    // Bit 4: 1 if this device is battery powered
     eeprom->self_powered = buf[0x08] & 0x40;
-    eeprom->remote_wakeup = buf[0x08] & 0x20;;
+    eeprom->remote_wakeup = buf[0x08] & 0x20;
 
     // Addr 09: Max power consumption: max power = value * 2 mA
     eeprom->max_power = buf[0x09];