ftdi.c - description
-------------------
begin : Fri Apr 4 2003
- copyright : (C) 2003-2011 by Intra2net AG and the libftdi developers
+ copyright : (C) 2003-2013 by Intra2net AG and the libftdi developers
email : opensource@intra2net.com
***************************************************************************/
#include "ftdi_version_i.h"
#define ftdi_error_return(code, str) do { \
- ftdi->error_str = str; \
+ if ( ftdi ) \
+ ftdi->error_str = str; \
+ else \
+ fprintf(stderr, str); \
return code; \
} while(0);
\retval 0: all fine
\retval -1: unknown interface
\retval -2: USB device unavailable
+ \retval -3: Device already open, interface can't be set in that state
*/
int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface)
{
if (ftdi == NULL)
ftdi_error_return(-2, "USB device unavailable");
+ if (ftdi->usb_dev != NULL)
+ {
+ int check_interface = interface;
+ if (check_interface == INTERFACE_ANY)
+ check_interface = INTERFACE_A;
+
+ if (ftdi->index != check_interface)
+ ftdi_error_return(-3, "Interface can not be changed on an already open device");
+ }
+
switch (interface)
{
case INTERFACE_ANY:
strcpy(eeprom->serial, serial);
}
-
if (ftdi->type == TYPE_R)
{
eeprom->max_power = 90;
if (eeprom->cbus_function[2*i+1]> CBUSH_CLK7_5)
mode_high = CBUSH_TRISTATE;
else
- mode_high = eeprom->cbus_function[2*i];
+ mode_high = eeprom->cbus_function[2*i+1];
- output[0x18+i] = mode_high <<4 | mode_low;
+ output[0x18+i] = (mode_high <<4) | mode_low;
}
}
/* Return the bits for the encoded EEPROM Structure of a requested Mode
// Bit 5: 1 if this device uses remote wakeup
// Bit 4-0: reserved - 0
j = 0x80;
- if (eeprom->self_powered == 1)
+ if (eeprom->self_powered)
j |= 0x40;
- if (eeprom->remote_wakeup == 1)
+ if (eeprom->remote_wakeup)
j |= 0x20;
output[0x08] = j;
// Addr 09: Max power consumption: max power = value * 2 mA
- output[0x09] = eeprom->max_power>>1;
+ output[0x09] = eeprom->max_power / MAX_POWER_MILLIAMP_PER_UNIT;
if (ftdi->type != TYPE_AM)
{
// Bit 0: 1 - In EndPoint is Isochronous
//
j = 0;
- if (eeprom->in_is_isochronous == 1)
+ if (eeprom->in_is_isochronous)
j = j | 1;
- if (eeprom->out_is_isochronous == 1)
+ if (eeprom->out_is_isochronous)
j = j | 2;
output[0x0A] = j;
}
else
output[0x01] &= ~HIGH_CURRENT_DRIVE;
- if (eeprom->in_is_isochronous == 1)
+ if (eeprom->in_is_isochronous)
output[0x0A] |= 0x1;
else
output[0x0A] &= ~0x1;
- if (eeprom->out_is_isochronous == 1)
+ if (eeprom->out_is_isochronous)
output[0x0A] |= 0x2;
else
output[0x0A] &= ~0x2;
- if (eeprom->suspend_pull_downs == 1)
+ if (eeprom->suspend_pull_downs)
output[0x0A] |= 0x4;
else
output[0x0A] &= ~0x4;
output[0x00] |= HIGH_CURRENT_DRIVE_R;
output[0x01] = 0x40; /* Hard coded Endpoint Size*/
- if (eeprom->suspend_pull_downs == 1)
+ if (eeprom->suspend_pull_downs)
output[0x0A] |= 0x4;
else
output[0x0A] &= ~0x4;
else
output[0x01] &= ~SUSPEND_DBUS7_BIT;
- if (eeprom->suspend_pull_downs == 1)
+ if (eeprom->suspend_pull_downs)
output[0x0A] |= 0x4;
else
output[0x0A] &= ~0x4;
break;
case TYPE_4232H:
+ if (eeprom->channel_a_driver == DRIVER_VCP)
+ output[0x00] |= DRIVER_VCP;
+ else
+ output[0x00] &= ~DRIVER_VCP;
+ if (eeprom->channel_b_driver == DRIVER_VCP)
+ output[0x01] |= DRIVER_VCP;
+ else
+ output[0x01] &= ~DRIVER_VCP;
+ if (eeprom->channel_c_driver == DRIVER_VCP)
+ output[0x00] |= (DRIVER_VCP << 4);
+ else
+ output[0x00] &= ~(DRIVER_VCP << 4);
+ if (eeprom->channel_d_driver == DRIVER_VCP)
+ output[0x01] |= (DRIVER_VCP << 4);
+ else
+ output[0x01] &= ~(DRIVER_VCP << 4);
+
+ if (eeprom->suspend_pull_downs)
+ output[0x0a] |= 0x4;
+ else
+ output[0x0a] &= ~0x4;
+
+ if (eeprom->channel_a_rs485enable)
+ output[0x0b] |= CHANNEL_IS_RS485 << 0;
+ else
+ output[0x0b] &= ~(CHANNEL_IS_RS485 << 0);
+ if (eeprom->channel_b_rs485enable)
+ output[0x0b] |= CHANNEL_IS_RS485 << 1;
+ else
+ output[0x0b] &= ~(CHANNEL_IS_RS485 << 1);
+ if (eeprom->channel_c_rs485enable)
+ output[0x0b] |= CHANNEL_IS_RS485 << 2;
+ else
+ output[0x0b] &= ~(CHANNEL_IS_RS485 << 2);
+ if (eeprom->channel_d_rs485enable)
+ output[0x0b] |= CHANNEL_IS_RS485 << 3;
+ else
+ output[0x0b] &= ~(CHANNEL_IS_RS485 << 3);
+
+ 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[0x0c] |= DRIVE_16MA<<4;
+ else
+ output[0x0c] |= eeprom->group1_drive<<4;
+ if (eeprom->group1_schmitt == IS_SCHMITT)
+ output[0x0c] |= IS_SCHMITT<<4;
+ if (eeprom->group1_slew == SLOW_SLEW)
+ output[0x0c] |= SLOW_SLEW<<4;
+
+ if (eeprom->group2_drive > DRIVE_16MA)
+ output[0x0d] |= DRIVE_16MA;
+ else
+ output[0x0d] |= eeprom->group2_drive;
+ if (eeprom->group2_schmitt == IS_SCHMITT)
+ output[0x0d] |= IS_SCHMITT;
+ if (eeprom->group2_slew == SLOW_SLEW)
+ output[0x0d] |= SLOW_SLEW;
+
+ if (eeprom->group3_drive > DRIVE_16MA)
+ output[0x0d] |= DRIVE_16MA<<4;
+ else
+ output[0x0d] |= eeprom->group3_drive<<4;
+ if (eeprom->group3_schmitt == IS_SCHMITT)
+ output[0x0d] |= IS_SCHMITT<<4;
+ if (eeprom->group3_slew == SLOW_SLEW)
+ output[0x0d] |= SLOW_SLEW<<4;
+
output[0x18] = eeprom->chip;
- fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n");
+
break;
case TYPE_232H:
output[0x00] = type2bit(eeprom->channel_a_type, TYPE_232H);
eeprom->remote_wakeup = buf[0x08] & 0x20;
// Addr 09: Max power consumption: max power = value * 2 mA
- eeprom->max_power = buf[0x09];
+ eeprom->max_power = MAX_POWER_MILLIAMP_PER_UNIT * buf[0x09];
// Addr 0A: Chip configuration
// Bit 7: 0 - reserved
else if (ftdi->type == TYPE_R)
{
/* TYPE_R flags D2XX, not VCP as all others*/
- eeprom->channel_a_driver = (~buf[0x00]) & DRIVER_VCP;
+ eeprom->channel_a_driver = ~buf[0x00] & DRIVER_VCP;
eeprom->high_current = buf[0x00] & HIGH_CURRENT_DRIVE_R;
if ( (buf[0x01]&0x40) != 0x40)
fprintf(stderr,
eeprom->cbus_function[3] = (buf[0x15] >> 4) & 0x0f;
eeprom->cbus_function[4] = buf[0x16] & 0x0f;
}
- else if ((ftdi->type == TYPE_2232H) ||(ftdi->type == TYPE_4232H))
+ else if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H))
{
- eeprom->channel_a_type = bit2type(buf[0x00] & 0x7);
eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP;
- eeprom->channel_b_type = bit2type(buf[0x01] & 0x7);
eeprom->channel_b_driver = buf[0x01] & DRIVER_VCP;
if (ftdi->type == TYPE_2232H)
+ {
+ eeprom->channel_a_type = bit2type(buf[0x00] & 0x7);
+ eeprom->channel_b_type = bit2type(buf[0x01] & 0x7);
eeprom->suspend_dbus7 = buf[0x01] & SUSPEND_DBUS7_BIT;
+ }
+ else
+ {
+ eeprom->channel_c_driver = (buf[0x00] >> 4) & DRIVER_VCP;
+ eeprom->channel_d_driver = (buf[0x01] >> 4) & DRIVER_VCP;
+ eeprom->channel_a_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 0);
+ eeprom->channel_b_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 1);
+ eeprom->channel_c_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 2);
+ eeprom->channel_d_rs485enable = buf[0x0b] & (CHANNEL_IS_RS485 << 3);
+ }
eeprom->chip = buf[0x18];
eeprom->group0_drive = buf[0x0c] & DRIVE_16MA;
if (eeprom->self_powered)
fprintf(stdout, "Self-Powered%s", (eeprom->remote_wakeup)?", USB Remote Wake Up\n":"\n");
else
- fprintf(stdout, "Bus Powered: %3d mA%s", eeprom->max_power * 2,
+ fprintf(stdout, "Bus Powered: %3d mA%s", eeprom->max_power,
(eeprom->remote_wakeup)?" USB Remote Wake Up\n":"\n");
if (eeprom->manufacturer)
fprintf(stdout, "Manufacturer: %s\n",eeprom->manufacturer);
fprintf(stdout,"C%d Function: %s\n", i,
cbush_mux[eeprom->cbus_function[i]]);
}
-
}
if (ftdi->type == TYPE_R)
case CHANNEL_B_DRIVER:
*value = ftdi->eeprom->channel_b_driver;
break;
+ case CHANNEL_C_DRIVER:
+ *value = ftdi->eeprom->channel_c_driver;
+ break;
+ case CHANNEL_D_DRIVER:
+ *value = ftdi->eeprom->channel_d_driver;
+ break;
+ case CHANNEL_A_RS485:
+ *value = ftdi->eeprom->channel_a_rs485enable;
+ break;
+ case CHANNEL_B_RS485:
+ *value = ftdi->eeprom->channel_b_rs485enable;
+ break;
+ case CHANNEL_C_RS485:
+ *value = ftdi->eeprom->channel_c_rs485enable;
+ break;
+ case CHANNEL_D_RS485:
+ *value = ftdi->eeprom->channel_d_rs485enable;
+ break;
case CBUS_FUNCTION_0:
*value = ftdi->eeprom->cbus_function[0];
break;
case CHANNEL_B_DRIVER:
ftdi->eeprom->channel_b_driver = value;
break;
+ case CHANNEL_C_DRIVER:
+ ftdi->eeprom->channel_c_driver = value;
+ break;
+ case CHANNEL_D_DRIVER:
+ ftdi->eeprom->channel_d_driver = value;
+ break;
+ case CHANNEL_A_RS485:
+ ftdi->eeprom->channel_a_rs485enable = value;
+ break;
+ case CHANNEL_B_RS485:
+ ftdi->eeprom->channel_b_rs485enable = value;
+ break;
+ case CHANNEL_C_RS485:
+ ftdi->eeprom->channel_c_rs485enable = value;
+ break;
+ case CHANNEL_D_RS485:
+ ftdi->eeprom->channel_d_rs485enable = value;
+ break;
case CBUS_FUNCTION_0:
ftdi->eeprom->cbus_function[0] = value;
break;