\retval 0: all fine
\retval -1: couldn't allocate read buffer
+ \retval -2: couldn't allocate struct buffer
\remark This should be called before all functions
*/
int ftdi_init(struct ftdi_context *ftdi)
{
+ struct ftdi_eeprom* eeprom = (struct ftdi_eeprom *)malloc(sizeof(struct ftdi_eeprom));
ftdi->usb_ctx = NULL;
ftdi->usb_dev = NULL;
ftdi->usb_read_timeout = 5000;
ftdi->error_str = NULL;
- ftdi->eeprom = NULL;
+ if (eeprom == 0)
+ ftdi_error_return(-2, "Can't malloc struct ftdi_eeprom");
+ memset(eeprom, 0, sizeof(struct ftdi_eeprom));
+ ftdi->eeprom = eeprom;
/* All fine. Now allocate the readbuffer */
return ftdi_read_data_set_chunksize(ftdi, 4096);
free(ftdi->readbuffer);
ftdi->readbuffer = NULL;
}
+
+ if (ftdi->eeprom != NULL)
+ {
+ if (ftdi->eeprom->manufacturer != 0)
+ {
+ free(ftdi->eeprom->manufacturer);
+ ftdi->eeprom->manufacturer = 0;
+ }
+ if (ftdi->eeprom->product != 0)
+ {
+ free(ftdi->eeprom->product);
+ ftdi->eeprom->product = 0;
+ }
+ if (ftdi->eeprom->serial != 0)
+ {
+ free(ftdi->eeprom->serial);
+ ftdi->eeprom->serial = 0;
+ }
+ free(ftdi->eeprom);
+ ftdi->eeprom = NULL;
+ }
libusb_exit(ftdi->usb_ctx);
}
}
/**
- Set the eeprom size
-
- \param ftdi pointer to ftdi_context
- \param eeprom Pointer to ftdi_eeprom
- \param size
-
-*/
-void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom *eeprom, int size)
-{
- if (ftdi == NULL)
- return;
-
- ftdi->eeprom = eeprom;
- ftdi->eeprom->size=size;
-}
-
-/**
Init eeprom with default values.
+ \param ftdi pointer to ftdi_context
+ \param manufacturer String to use as Manufacturer
+ \param product String to use as Product description
+ \param serial String to use as Serial number description
- \param eeprom Pointer to ftdi_eeprom
+ \retval 0: all fine
+ \retval -1: No struct ftdi_context
+ \retval -2: No struct ftdi_eeprom
*/
-void ftdi_eeprom_initdefaults(struct ftdi_context *ftdi)
+int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer,
+ char * product, char * serial)
{
- int i;
struct ftdi_eeprom *eeprom;
if (ftdi == NULL)
- return;
+ ftdi_error_return(-1, "No struct ftdi_context");
if (ftdi->eeprom == NULL)
- return;
+ ftdi_error_return(-2,"No struct ftdi_eeprom");
eeprom = ftdi->eeprom;
memset(eeprom, 0, sizeof(struct ftdi_eeprom));
eeprom->usb_version = 0x0101;
else
eeprom->usb_version = 0x0200;
- eeprom->max_power = 50;
+ eeprom->max_power = 100;
+ if (eeprom->manufacturer)
+ free (eeprom->manufacturer);
eeprom->manufacturer = NULL;
+ if (manufacturer)
+ {
+ eeprom->manufacturer = malloc(strlen(manufacturer)+1);
+ if (eeprom->manufacturer)
+ strcpy(eeprom->manufacturer, manufacturer);
+ }
+
+ if (eeprom->product)
+ free (eeprom->product);
eeprom->product = NULL;
+ {
+ eeprom->product = malloc(strlen(product)+1);
+ if (eeprom->product)
+ strcpy(eeprom->product, product);
+ }
+
+ if (eeprom->serial)
+ free (eeprom->serial);
eeprom->serial = NULL;
+ if (serial)
+ {
+ eeprom->serial = malloc(strlen(serial)+1);
+ if (eeprom->serial)
+ strcpy(eeprom->serial, serial);
+ }
+
if(ftdi->type == TYPE_R)
{
- eeprom->max_power = 45;
+ eeprom->max_power = 90;
eeprom->size = 0x80;
eeprom->cbus_function[0] = CBUS_TXLED;
eeprom->cbus_function[1] = CBUS_RXLED;
}
else
eeprom->size = -1;
+ return 0;
}
/**
- Frees allocated memory in eeprom.
-
- \param eeprom Pointer to ftdi_eeprom
-*/
-void ftdi_eeprom_free(struct ftdi_context *ftdi)
-{
- if (!ftdi)
- return;
- if (ftdi->eeprom)
- {
- struct ftdi_eeprom *eeprom = ftdi->eeprom;
-
- if (eeprom->manufacturer != 0) {
- free(eeprom->manufacturer);
- eeprom->manufacturer = 0;
- }
- if (eeprom->product != 0) {
- free(eeprom->product);
- eeprom->product = 0;
- }
- if (eeprom->serial != 0) {
- free(eeprom->serial);
- eeprom->serial = 0;
- }
- }
-}
-
-/**
- Build binary output from ftdi_eeprom structure.
+ Build binary buffer from ftdi_eeprom structure.
Output is suitable for ftdi_write_eeprom().
- \note This function doesn't handle FT2232x devices. Only FT232x.
- \param eeprom Pointer to ftdi_eeprom
- \param output Buffer of 128 bytes to store eeprom image to
+ \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
\retval -5: Chip doesn't support high current drive
\retval -6: No connected EEPROM or EEPROM Type unknown
*/
-int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output)
+int ftdi_eeprom_build(struct ftdi_context *ftdi)
{
- unsigned char i, j, k;
+ 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;
if (ftdi == NULL)
ftdi_error_return(-2,"No context");
ftdi_error_return(-2,"No eeprom structure");
eeprom= ftdi->eeprom;
+ output = eeprom->buf;
if(eeprom->chip == -1)
- ftdi_error_return(-5,"No connected EEPROM or EEPROM Type unknown");
+ ftdi_error_return(-5,"No connected EEPROM or EEPROM type unknown");
if ((eeprom->chip == 0x56) || (eeprom->chip == 0x66))
eeprom->size = 0x100;
if (eeprom->serial != NULL)
serial_size = strlen(eeprom->serial);
- size_check = 0x80;
- switch(ftdi->type)
- {
- case TYPE_2232H:
- case TYPE_4232H:
- size_check -= 4;
- case TYPE_R:
- size_check -= 4;
- case TYPE_2232C:
- size_check -= 4;
+ // eeprom size exceeded?
+
+ switch (ftdi->type) {
case TYPE_AM:
case TYPE_BM:
- size_check -= 0x14*2;
+ user_area_size = 96;
+ break;
+ case TYPE_2232C:
+ user_area_size = 94;
+ break;
+ case TYPE_R:
+ user_area_size = 92;
+ break;
+ case TYPE_2232H:
+ case TYPE_4232H:
+ user_area_size = 90;
+ break;
}
-
- 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 -= -6;
-
- // eeprom size exceeded?
- if (size_check < 0)
- return (-1);
+ user_area_size -= (manufacturer_size + product_size + serial_size) * 2;
+ if (user_area_size < 0)
+ ftdi_error_return(-1,"eeprom size exceeded");
// empty eeprom
- memset (output, 0, eeprom->size);
+ memset (ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE);
// Bytes and Bits set for all Types
// 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
+ // Bit 4-0: reserved - 0
j = 0x80;
if (eeprom->self_powered == 1)
j |= 0x40;
output[0x08] = j;
// Addr 09: Max power consumption: max power = value * 2 mA
- output[0x09] = eeprom->max_power;
+ output[0x09] = eeprom->max_power>>1;
if(ftdi->type != TYPE_AM)
{
i += 0x94;
}
/* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */
- k = eeprom->size -1;
+ eeprom_size_mask = eeprom->size -1;
// Addr 0E: Offset of the manufacturer string + 0x80, calculated later
// Addr 0F: Length of manufacturer string
// Output manufacturer
output[0x0E] = i; // calculate offset
- output[i++ & k] = manufacturer_size*2 + 2;
- output[i++ & k] = 0x03; // type: string
+ output[i & eeprom_size_mask] = manufacturer_size*2 + 2, i++;
+ output[i & eeprom_size_mask] = 0x03, i++; // type: string
for (j = 0; j < manufacturer_size; j++)
{
- output[i & k] = eeprom->manufacturer[j], i++;
- output[i & k] = 0x00, i++;
+ output[i & eeprom_size_mask] = eeprom->manufacturer[j], i++;
+ output[i & eeprom_size_mask] = 0x00, i++;
}
output[0x0F] = manufacturer_size*2 + 2;
// Addr 10: Offset of the product string + 0x80, calculated later
// Addr 11: Length of product string
output[0x10] = i | 0x80; // calculate offset
- output[i & k] = product_size*2 + 2, i++;
- output[i & k] = 0x03, i++;
+ output[i & eeprom_size_mask] = product_size*2 + 2, i++;
+ output[i & eeprom_size_mask] = 0x03, i++;
for (j = 0; j < product_size; j++)
{
- output[i & k] = eeprom->product[j], i++;
- output[i & k] = 0x00, i++;
+ output[i & eeprom_size_mask] = eeprom->product[j], i++;
+ output[i & eeprom_size_mask] = 0x00, i++;
}
output[0x11] = product_size*2 + 2;
-
+
// Addr 12: Offset of the serial string + 0x80, calculated later
// Addr 13: Length of serial string
output[0x12] = i | 0x80; // calculate offset
- output[i & k] = serial_size*2 + 2, i++;
- output[i & k] = 0x03, i++;
+ output[i & eeprom_size_mask] = serial_size*2 + 2, i++;
+ output[i & eeprom_size_mask] = 0x03, i++;
for (j = 0; j < serial_size; j++)
{
- output[i & k] = eeprom->serial[j], i++;
- output[i & k] = 0x00, i++;
+ output[i & eeprom_size_mask] = eeprom->serial[j], i++;
+ output[i & eeprom_size_mask] = 0x00, 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;
- /* Fixme: ftd2xx seems to append 0x02, 0x03 and 0x01 for PnP = 0 or 0x00 else */
- // calculate checksum
+ 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;
+ }
/* Bytes and Bits specific to (some) types
Write linear, as this allows easier fixing*/
case TYPE_BM:
output[0x0C] = eeprom->usb_version & 0xff;
output[0x0D] = (eeprom->usb_version>>8) & 0xff;
- if (eeprom->use_serial == 1)
- output[0x0A] |= 0x8;
- else
- output[0x0A] &= ~0x8;
- output[0x14] = eeprom->chip;
break;
case TYPE_2232C:
output[0x00] |= DRIVER_VCP;
else
output[0x00] &= ~DRIVER_VCP;
-
+
if ( eeprom->high_current_a == HIGH_CURRENT_DRIVE)
output[0x00] |= HIGH_CURRENT_DRIVE;
else
output[0x01] |= DRIVER_VCP;
else
output[0x01] &= ~DRIVER_VCP;
-
+
if ( eeprom->high_current_b == HIGH_CURRENT_DRIVE)
output[0x01] |= HIGH_CURRENT_DRIVE;
else
output[0x0A] |= 0x4;
else
output[0x0A] &= ~0x4;
- if (eeprom->use_serial == USE_SERIAL_NUM )
- output[0x0A] |= USE_SERIAL_NUM;
- else
- output[0x0A] &= ~0x8;
output[0x0C] = eeprom->usb_version & 0xff;
output[0x0D] = (eeprom->usb_version>>8) & 0xff;
output[0x14] = eeprom->chip;
if(eeprom->high_current == HIGH_CURRENT_DRIVE_R)
output[0x00] |= HIGH_CURRENT_DRIVE_R;
output[0x01] = 0x40; /* Hard coded Endpoint Size*/
-
+
if (eeprom->suspend_pull_downs == 1)
output[0x0A] |= 0x4;
else
output[0x0A] &= ~0x4;
- if (eeprom->use_serial == USE_SERIAL_NUM)
- output[0x0A] |= USE_SERIAL_NUM;
- else
- output[0x0A] &= ~0x8;
output[0x0B] = eeprom->invert;
output[0x0C] = eeprom->usb_version & 0xff;
output[0x0D] = (eeprom->usb_version>>8) & 0xff;
-
+
if(eeprom->cbus_function[0] > CBUS_BB)
output[0x14] = CBUS_TXLED;
else
output[0x14] = eeprom->cbus_function[0];
-
+
if(eeprom->cbus_function[1] > CBUS_BB)
output[0x14] |= CBUS_RXLED<<4;
else
output[0x14] |= eeprom->cbus_function[1]<<4;
-
+
if(eeprom->cbus_function[2] > CBUS_BB)
output[0x15] = CBUS_TXDEN;
else
output[0x15] = eeprom->cbus_function[2];
-
+
if(eeprom->cbus_function[3] > CBUS_BB)
output[0x15] |= CBUS_PWREN<<4;
else
output[0x15] |= eeprom->cbus_function[3]<<4;
-
+
if(eeprom->cbus_function[4] > CBUS_CLK6)
output[0x16] = CBUS_SLEEP;
else
output[0x00] |= DRIVER_VCP;
else
output[0x00] &= ~DRIVER_VCP;
-
+
output[0x01] = (eeprom->channel_b_type);
if ( eeprom->channel_b_driver == DRIVER_VCP)
output[0x01] |= DRIVER_VCP;
output[0x01] |= SUSPEND_DBUS7;
else
output[0x01] &= ~SUSPEND_DBUS7;
-
+
+ if (eeprom->suspend_pull_downs == 1)
+ output[0x0A] |= 0x4;
+ else
+ output[0x0A] &= ~0x4;
+
if(eeprom->group0_drive > DRIVE_16MA)
output[0x0c] |= DRIVE_16MA;
else
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[0x18] = eeprom->chip;
break;
+ case TYPE_4232H:
+ fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n");
}
// calculate checksum
output[eeprom->size-2] = checksum;
output[eeprom->size-1] = checksum >> 8;
- return size_check;
+ return user_area_size;
}
/**
Decode binary EEPROM image into an ftdi_eeprom structure.
- \param eeprom Pointer to ftdi_eeprom which will be filled in.
- \param buf Buffer of \a size bytes of raw eeprom data
- \param size size size of eeprom data in bytes
-
+ \param ftdi pointer to ftdi_context
+ \param verbose Decode EEPROM on stdout
+
\retval 0: all fine
\retval -1: something went wrong
FIXME: How to pass size? How to handle size field in ftdi_eeprom?
FIXME: Strings are malloc'ed here and should be freed somewhere
*/
-int ftdi_eeprom_decode(struct ftdi_context *ftdi, unsigned char *buf, int size, int verbose)
+int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose)
{
unsigned char i, j;
unsigned short checksum, eeprom_checksum, value;
unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
int eeprom_size;
struct ftdi_eeprom *eeprom;
+ unsigned char *buf = ftdi->eeprom->buf;
int release;
if (ftdi == NULL)
if (ftdi->eeprom == NULL)
ftdi_error_return(-1,"No eeprom structure");
- eeprom_size = ftdi->eeprom->size;
- if(ftdi->type == TYPE_R)
- eeprom_size = 0x80;
eeprom = ftdi->eeprom;
+ eeprom_size = eeprom->size;
// Addr 02: Vendor ID
eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8);
// 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;;
// Addr 0E: Offset of the manufacturer string + 0x80, calculated later
// Addr 0F: Length of manufacturer string
manufacturer_size = buf[0x0F]/2;
+ if(eeprom->manufacturer)
+ free(eeprom->manufacturer);
if (manufacturer_size > 0)
{
eeprom->manufacturer = malloc(manufacturer_size);
// Addr 10: Offset of the product string + 0x80, calculated later
// Addr 11: Length of product string
+ if(eeprom->product)
+ free(eeprom->product);
product_size = buf[0x11]/2;
if (product_size > 0)
{
// Addr 12: Offset of the serial string + 0x80, calculated later
// Addr 13: Length of serial string
+ if(eeprom->serial)
+ free(eeprom->serial);
serial_size = buf[0x13]/2;
if (serial_size > 0)
{
}
else if ((ftdi->type == TYPE_2232H) ||(ftdi->type == TYPE_4232H))
{
- eeprom->high_current = buf[0x00] & HIGH_CURRENT_DRIVE_R;
+ eeprom->channel_a_type = buf[0x00] & 0x7;
eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP;
eeprom->channel_b_type = buf[0x01] & 0x7;
eeprom->channel_b_driver = buf[0x01] & DRIVER_VCP;
fprintf(stdout, "Pull IO pins low during suspend\n");
if(eeprom->remote_wakeup)
fprintf(stdout, "Enable Remote Wake Up\n");
+ fprintf(stdout, "PNP: %d\n",(eeprom->is_not_pnp)?0:1);
if (ftdi->type >= TYPE_2232C)
fprintf(stdout,"Channel A has Mode %s%s%s\n",
channel_mode[eeprom->channel_a_type],
Read eeprom
\param ftdi pointer to ftdi_context
- \param eeprom Pointer to store eeprom into
\retval 0: all fine
\retval -1: read failed
\retval -2: USB device unavailable
*/
-int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom)
+int ftdi_read_eeprom(struct ftdi_context *ftdi)
{
int i;
+ unsigned char *buf;
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
+ buf = ftdi->eeprom->buf;
for (i = 0; i < FTDI_MAX_EEPROM_SIZE/2; i++)
{
- if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, i, eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2)
+ if (libusb_control_transfer(
+ ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE,SIO_READ_EEPROM_REQUEST, 0, i,
+ buf+(i*2), 2, ftdi->usb_read_timeout) != 2)
ftdi_error_return(-1, "reading eeprom failed");
}
if (ftdi->type == TYPE_R)
- ftdi->eeprom->size = 0xa0;
+ ftdi->eeprom->size = 0x80;
/* Guesses size of eeprom by comparing halves
- will not work with blank eeprom */
- else if (strrchr((const char *)eeprom, 0xff) == ((const char *)eeprom +FTDI_MAX_EEPROM_SIZE -1))
+ else if (strrchr((const char *)buf, 0xff) == ((const char *)buf +FTDI_MAX_EEPROM_SIZE -1))
ftdi->eeprom->size = -1;
- else if(memcmp(eeprom,&eeprom[0x80],0x80) == 0)
+ else if(memcmp(buf,&buf[0x80],0x80) == 0)
ftdi->eeprom->size = 0x80;
- else if(memcmp(eeprom,&eeprom[0x40],0x40) == 0)
+ else if(memcmp(buf,&buf[0x40],0x40) == 0)
ftdi->eeprom->size = 0x40;
else
ftdi->eeprom->size = 0x100;
\param eeprom_val Value to be written
\retval 0: all fine
- \retval -1: read failed
+ \retval -1: write failed
\retval -2: USB device unavailable
+ \retval -3: Invalid access to checksum protected area below 0x80
+ \retval -4: Device can't access unprotected area
+ \retval -5: Reading chip type failed
*/
-int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr, unsigned short eeprom_val)
+int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr,
+ unsigned short eeprom_val)
{
+ int chip_type_location;
+ unsigned short chip_type;
+
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
+ if(eeprom_addr <0x80)
+ ftdi_error_return(-2, "Invalid access to checksum protected area below 0x80");
+
+
+ switch (ftdi->type)
+ {
+ case TYPE_BM:
+ case TYPE_2232C:
+ chip_type_location = 0x14;
+ break;
+ case TYPE_2232H:
+ case TYPE_4232H:
+ chip_type_location = 0x18;
+ break;
+ default:
+ ftdi_error_return(-4, "Device can't access unprotected area");
+ }
+
+ if (ftdi_read_eeprom_location( ftdi, chip_type_location>>1, &chip_type))
+ ftdi_error_return(-5, "Reading failed failed");
+ fprintf(stderr," loc 0x%04x val 0x%04x\n", chip_type_location,chip_type);
+ if((chip_type & 0xff) != 0x66)
+ {
+ ftdi_error_return(-6, "EEPROM is not of 93x66");
+ }
+
if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
SIO_WRITE_EEPROM_REQUEST, eeprom_val, eeprom_addr,
NULL, 0, ftdi->usb_write_timeout) != 0)
Write eeprom
\param ftdi pointer to ftdi_context
- \param eeprom Pointer to read eeprom from
-
+
\retval 0: all fine
\retval -1: read failed
\retval -2: USB device unavailable
*/
-int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom)
+int ftdi_write_eeprom(struct ftdi_context *ftdi)
{
unsigned short usb_val, status;
int i, ret;
+ unsigned char *eeprom;
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
+ eeprom = ftdi->eeprom->buf;
/* These commands were traced while running MProg */
if ((ret = ftdi_usb_reset(ftdi)) != 0)
Chip is 93x46 if magic is read at word position 0x00, as wraparound happens around 0x40
Chip is 93x56 if magic is read at word position 0x40, as wraparound happens around 0x80
Chip is 93x66 if magic is only read at word position 0xc0*/
- if( ftdi_write_eeprom_location(ftdi, 0xc0, MAGIC))
+ if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+ SIO_WRITE_EEPROM_REQUEST, MAGIC, 0xc0,
+ NULL, 0, ftdi->usb_write_timeout) != 0)
ftdi_error_return(-3, "Writing magic failed");
if (ftdi_read_eeprom_location( ftdi, 0x00, &eeprom_value))
ftdi_error_return(-4, "Reading failed failed");