FT232H: Handle the EEPROM Bit for Enter Powerdsave on ACBUS7
[libftdi] / src / ftdi.c
index 0893421..ed2bbe0 100644 (file)
@@ -289,13 +289,13 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli
         struct libusb_device_descriptor desc;
 
         if (libusb_get_device_descriptor(dev, &desc) < 0)
-            ftdi_error_return(-6, "libusb_get_device_descriptor() failed");
+            ftdi_error_return_free_device_list(-6, "libusb_get_device_descriptor() failed", devs);
 
         if (desc.idVendor == vendor && desc.idProduct == product)
         {
             *curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list));
             if (!*curdev)
-                ftdi_error_return(-3, "out of memory");
+                ftdi_error_return_free_device_list(-3, "out of memory", devs);
 
             (*curdev)->next = NULL;
             (*curdev)->dev = dev;
@@ -304,7 +304,7 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli
             count++;
         }
     }
-
+    libusb_free_device_list(devs,1);
     return count;
 }
 
@@ -428,7 +428,7 @@ static unsigned int _ftdi_determine_max_packet_size(struct ftdi_context *ftdi, l
     // Determine maximum packet size. Init with default value.
     // New hi-speed devices from FTDI use a packet size of 512 bytes
     // but could be connected to a normal speed USB hub -> 64 bytes packet size.
-    if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H)
+    if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H )
         packet_size = 512;
     else
         packet_size = 64;
@@ -564,6 +564,8 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, libusb_device *dev)
         ftdi->type = TYPE_2232H;
     else if (desc.bcdDevice == 0x800)
         ftdi->type = TYPE_4232H;
+    else if (desc.bcdDevice == 0x900)
+        ftdi->type = TYPE_232H;
 
     // Determine maximum packet size
     ftdi->max_packet_size = _ftdi_determine_max_packet_size(ftdi, dev);
@@ -2205,6 +2207,10 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer,
     if ((ftdi->type == TYPE_AM) || (ftdi->type == TYPE_BM) ||
             (ftdi->type == TYPE_R))
         eeprom->product_id = 0x6001;
+    else if (ftdi->type == TYPE_4232H)
+        eeprom->product_id = 0x6011;
+    else if (ftdi->type == TYPE_232H)
+        eeprom->product_id = 0x6014;
     else
         eeprom->product_id = 0x6010;
     if (ftdi->type == TYPE_AM)
@@ -2366,6 +2372,9 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
         case TYPE_4232H:
             output[0x07] = 0x08;
             break;
+        case TYPE_232H:
+            output[0x07] = 0x09;
+            break;
         default:
             output[0x07] = 0x00;
     }
@@ -2408,9 +2417,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
     // Dynamic content
     // Strings start at 0x94 (TYPE_AM, TYPE_BM)
     // 0x96 (TYPE_2232C), 0x98 (TYPE_R) and 0x9a (TYPE_x232H)
+    // 0xa0 (TYPE_232H)
     i = 0;
     switch (ftdi->type)
     {
+        case TYPE_232H:
+            i += 2;
         case TYPE_2232H:
         case TYPE_4232H:
             i += 2;
@@ -2642,7 +2654,42 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi)
 
             break;
         case TYPE_4232H:
+            output[0x18] = eeprom->chip;
             fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n");
+            break;
+        case TYPE_232H:
+            output[0x00] = (eeprom->channel_a_type);
+            if ( eeprom->channel_a_driver == DRIVER_VCP)
+                output[0x00] |= DRIVER_VCPH;
+            else
+                output[0x00] &= ~DRIVER_VCPH;
+            if (eeprom->powersave)
+                output[0x01] |= POWER_SAVE_DISABLE_H;
+            else
+                output[0x01] &= ~POWER_SAVE_DISABLE_H;
+
+            if (eeprom->group0_drive > DRIVE_16MA)
+                output[0x0c] |= DRIVE_16MA;
+            else
+                output[0x0c] |= eeprom->group0_drive;
+            if (eeprom->group0_schmitt == IS_SCHMITT)
+                output[0x0c] |= IS_SCHMITT;
+            if (eeprom->group0_slew == SLOW_SLEW)
+                output[0x0c] |= SLOW_SLEW;
+
+            if (eeprom->group1_drive > DRIVE_16MA)
+                output[0x0d] |= DRIVE_16MA;
+            else
+                output[0x0d] |= eeprom->group1_drive;
+            if (eeprom->group1_schmitt == IS_SCHMITT)
+                output[0x0d] |= IS_SCHMITT;
+            if (eeprom->group1_slew == SLOW_SLEW)
+                output[0x0d] |= SLOW_SLEW;
+
+            output[0x1e] = eeprom->chip;
+            fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n");
+            break;
+              
     }
 
     // calculate checksum
@@ -2878,10 +2925,25 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
         eeprom->group3_schmitt = (buf[0x0d] >> 4) & IS_SCHMITT;
         eeprom->group3_slew    = (buf[0x0d] >> 4) & SLOW_SLEW;
     }
+    else if (ftdi->type == TYPE_232H)
+    {
+        eeprom->channel_a_type   = buf[0x00] & 0xf;
+        eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0;
+        eeprom->powersave      =  buf[0x01]       & POWER_SAVE_DISABLE_H;
+        eeprom->group0_drive   =  buf[0x0c]       & DRIVE_16MA;
+        eeprom->group0_schmitt =  buf[0x0c]       & IS_SCHMITT;
+        eeprom->group0_slew    =  buf[0x0c]       & SLOW_SLEW;
+        eeprom->group1_drive   =  buf[0x0d]       & DRIVE_16MA;
+        eeprom->group1_schmitt =  buf[0x0d]       & IS_SCHMITT;
+        eeprom->group1_slew    =  buf[0x0d]       & SLOW_SLEW;
+
+        eeprom->chip = buf[0x1e];
+        /*FIXME: Decipher more values*/
+    }
 
     if (verbose)
     {
-        char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO"};
+        char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO", "unknown1","unknown2","unknown3","FT1284"};
         fprintf(stdout, "VID:     0x%04x\n",eeprom->vendor_id);
         fprintf(stdout, "PID:     0x%04x\n",eeprom->product_id);
         fprintf(stdout, "Release: 0x%04x\n",release);
@@ -2906,6 +2968,11 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
             fprintf(stdout, "Suspend on DBUS7\n");
         if (eeprom->suspend_pull_downs)
             fprintf(stdout, "Pull IO pins low during suspend\n");
+        if(eeprom->powersave)
+        {
+            if(ftdi->type >= TYPE_232H)
+                fprintf(stdout,"Enter low power state on ACBUS7\n");
+        } 
         if (eeprom->remote_wakeup)
             fprintf(stdout, "Enable Remote Wake Up\n");
         fprintf(stdout, "PNP: %d\n",(eeprom->is_not_pnp)?0:1);
@@ -2914,7 +2981,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
                     channel_mode[eeprom->channel_a_type],
                     (eeprom->channel_a_driver)?" VCP":"",
                     (eeprom->high_current_a)?" High Current IO":"");
-        if ((ftdi->type >= TYPE_2232C) && (ftdi->type != TYPE_R))
+        if ((ftdi->type >= TYPE_2232C) && (ftdi->type != TYPE_R) && (ftdi->type != TYPE_232H))
             fprintf(stdout,"Channel B has Mode %s%s%s\n",
                     channel_mode[eeprom->channel_b_type],
                     (eeprom->channel_b_driver)?" VCP":"",
@@ -2946,6 +3013,18 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
                     (eeprom->group3_schmitt)?" Schmitt Input":"",
                     (eeprom->group3_slew)?" Slow Slew":"");
         }
+        else if (ftdi->type == TYPE_232H)
+        {
+            fprintf(stdout,"ACBUS has %d mA drive%s%s\n",
+                    (eeprom->group0_drive+1) *4,
+                    (eeprom->group0_schmitt)?" Schmitt Input":"",
+                    (eeprom->group0_slew)?" Slow Slew":"");
+            fprintf(stdout,"ADBUS has %d mA drive%s%s\n",
+                    (eeprom->group1_drive+1) *4,
+                    (eeprom->group1_schmitt)?" Schmitt Input":"",
+                    (eeprom->group1_slew)?" Slow Slew":"");
+        }
+
         if (ftdi->type == TYPE_R)
         {
             char *cbus_mux[] = {"TXDEN","PWREN","RXLED", "TXLED","TX+RXLED",
@@ -3106,6 +3185,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu
         case GROUP3_SLEW:
             *value = ftdi->eeprom->group3_slew;
             break;
+         case POWER_SAVE:
+            *value = ftdi->eeprom->powersave;
+            break;
         case CHIP_TYPE:
             *value = ftdi->eeprom->chip;
             break;
@@ -3245,6 +3327,9 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu
         case CHIP_TYPE:
             ftdi->eeprom->chip = value;
             break;
+         case POWER_SAVE:
+            ftdi->eeprom->powersave = value;
+            break;
         case CHIP_SIZE:
             ftdi_error_return(-2, "EEPROM Value can't be changed");
         default :
@@ -3431,6 +3516,9 @@ int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr,
         case TYPE_4232H:
             chip_type_location = 0x18;
             break;
+        case TYPE_232H:
+            chip_type_location = 0x1e;
+            break;
         default:
             ftdi_error_return(-4, "Device can't access unprotected area");
     }