X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=e2c4009c83f71b4932167a9d314cbe0df0146974;hp=95028e52e64e0de7318a367638521ca990a45677;hb=2f80efc24176c903d82cea1f084453fd3df9b992;hpb=f37a15246fb738210ecc188d168039037adc50bf diff --git a/src/ftdi.c b/src/ftdi.c index 95028e5..e2c4009 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -2,7 +2,7 @@ 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 ***************************************************************************/ @@ -470,7 +470,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 || ftdi->type == TYPE_232H ) + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H || ftdi->type == TYPE_230X) packet_size = 512; else packet_size = 64; @@ -608,6 +608,8 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, libusb_device *dev) ftdi->type = TYPE_4232H; else if (desc.bcdDevice == 0x900) ftdi->type = TYPE_232H; + else if (desc.bcdDevice == 0x1000) + ftdi->type = TYPE_230X; // Determine maximum packet size ftdi->max_packet_size = _ftdi_determine_max_packet_size(ftdi, dev); @@ -1173,7 +1175,7 @@ static int ftdi_convert_baudrate(int baudrate, struct ftdi_context *ftdi, #define H_CLK 120000000 #define C_CLK 48000000 - if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H) || (ftdi->type == TYPE_232H )) + if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H) || (ftdi->type == TYPE_232H) || (ftdi->type == TYPE_230X)) { if(baudrate*10 > H_CLK /0x3fff) { @@ -1198,8 +1200,7 @@ static int ftdi_convert_baudrate(int baudrate, struct ftdi_context *ftdi, } // Split into "value" and "index" values *value = (unsigned short)(encoded_divisor & 0xFFFF); - if (ftdi->type == TYPE_2232H || - ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H ) + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H || ftdi->type == TYPE_230X) { *index = (unsigned short)(encoded_divisor >> 8); *index &= 0xFF00; @@ -1542,7 +1543,7 @@ struct ftdi_transfer_control *ftdi_write_data_submit(struct ftdi_context *ftdi, tc->size = size; tc->offset = 0; - if (size < ftdi->writebuffer_chunksize) + if (size < (int)ftdi->writebuffer_chunksize) write_size = size; else write_size = ftdi->writebuffer_chunksize; @@ -1595,7 +1596,7 @@ struct ftdi_transfer_control *ftdi_read_data_submit(struct ftdi_context *ftdi, u tc->buf = buf; tc->size = size; - if (size <= ftdi->readbuffer_remaining) + if (size <= (int)ftdi->readbuffer_remaining) { memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset, size); @@ -1759,7 +1760,7 @@ int ftdi_read_data(struct ftdi_context *ftdi, unsigned char *buf, int size) ftdi_error_return(-1, "max_packet_size is bogus (zero)"); // everything we want is still in the readbuffer? - if (size <= ftdi->readbuffer_remaining) + if (size <= (int)ftdi->readbuffer_remaining) { memcpy (buf, ftdi->readbuffer+ftdi->readbuffer_offset, size); @@ -2315,8 +2316,11 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, eeprom->product_id = 0x6011; else if (ftdi->type == TYPE_232H) eeprom->product_id = 0x6014; + else if (ftdi->type == TYPE_230X) + eeprom->product_id = 0x6015; else eeprom->product_id = 0x6010; + if (ftdi->type == TYPE_AM) eeprom->usb_version = 0x0101; else @@ -2354,6 +2358,7 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, case TYPE_2232H: default_product = "Dual RS232-HS"; break; case TYPE_4232H: default_product = "FT4232H"; break; case TYPE_232H: default_product = "Single-RS232-HS"; break; + case TYPE_230X: default_product = "FT230X Basic UART"; break; default: ftdi_error_return(-3, "Unknown chip type"); } @@ -2382,6 +2387,15 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, eeprom->cbus_function[3] = CBUS_PWREN; eeprom->cbus_function[4] = CBUS_SLEEP; } + else if (ftdi->type == TYPE_230X) + { + eeprom->max_power = 90; + eeprom->size = 0x100; + eeprom->cbus_function[0] = CBUSH_TXDEN; + eeprom->cbus_function[1] = CBUSH_RXLED; + eeprom->cbus_function[2] = CBUSH_TXLED; + eeprom->cbus_function[3] = CBUSH_SLEEP; + } else { if(ftdi->type == TYPE_232H) @@ -2392,9 +2406,83 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, } eeprom->size = -1; } - eeprom->initialized_for_connected_device = 1; + switch (ftdi->type) + { + case TYPE_AM: + eeprom->release_number = 0x0200; + break; + case TYPE_BM: + eeprom->release_number = 0x0400; + break; + case TYPE_2232C: + eeprom->release_number = 0x0500; + break; + case TYPE_R: + eeprom->release_number = 0x0600; + break; + case TYPE_2232H: + eeprom->release_number = 0x0700; + break; + case TYPE_4232H: + eeprom->release_number = 0x0800; + break; + case TYPE_232H: + eeprom->release_number = 0x0900; + break; + case TYPE_230X: + eeprom->release_number = 0x1000; + break; + default: + eeprom->release_number = 0x00; + } + return 0; +} + +int ftdi_eeprom_set_strings(struct ftdi_context *ftdi, char * manufacturer, + char * product, char * serial) +{ + struct ftdi_eeprom *eeprom; + + if (ftdi == NULL) + ftdi_error_return(-1, "No struct ftdi_context"); + + if (ftdi->eeprom == NULL) + ftdi_error_return(-2,"No struct ftdi_eeprom"); + + eeprom = ftdi->eeprom; + + if (ftdi->usb_dev == NULL) + ftdi_error_return(-3, "No connected device or device not yet opened"); + + if (manufacturer) { + if (eeprom->manufacturer) + free (eeprom->manufacturer); + eeprom->manufacturer = malloc(strlen(manufacturer)+1); + if (eeprom->manufacturer) + strcpy(eeprom->manufacturer, manufacturer); + } + + if(product) { + if (eeprom->product) + free (eeprom->product); + eeprom->product = malloc(strlen(product)+1); + if (eeprom->product) + strcpy(eeprom->product, product); + } + + if (serial) { + if (eeprom->serial) + free (eeprom->serial); + eeprom->serial = malloc(strlen(serial)+1); + if (eeprom->serial) { + strcpy(eeprom->serial, serial); + eeprom->use_serial = 1; + } + } return 0; } + + /*FTD2XX doesn't check for values not fitting in the ACBUS Signal oprtions*/ void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output) { @@ -2445,6 +2533,7 @@ static unsigned char type2bit(unsigned char type, enum ftdi_chip_type chip) default: return 0; } } + case TYPE_230X: /* FT230X is only UART */ default: return 0; } return 0; @@ -2484,10 +2573,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) if (eeprom->chip == -1) ftdi_error_return(-6,"No connected EEPROM or EEPROM type unknown"); - if ((eeprom->chip == 0x56) || (eeprom->chip == 0x66)) - eeprom->size = 0x100; - else - eeprom->size = 0x80; + if (eeprom->size == -1) { + if ((eeprom->chip == 0x56) || (eeprom->chip == 0x66)) + eeprom->size = 0x100; + else + eeprom->size = 0x80; + } if (eeprom->manufacturer != NULL) manufacturer_size = strlen(eeprom->manufacturer); @@ -2507,6 +2598,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) user_area_size = 90; // two extra config bytes and 4 bytes PnP stuff break; case TYPE_R: + case TYPE_230X: user_area_size = 88; // four extra config bytes + 4 bytes PnP stuff break; case TYPE_2232H: // six extra config bytes + 4 bytes PnP stuff @@ -2526,7 +2618,14 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) ftdi_error_return(-1,"eeprom size exceeded"); // empty eeprom - memset (ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE); + if (ftdi->type == TYPE_230X) { + /* FT230X have a reserved section in the middle of the MTP, + which cannot be written to, but must be included in the checksum */ + memset(ftdi->eeprom->buf, 0, 0x80); + memset((ftdi->eeprom->buf + 0xa0), 0, (FTDI_MAX_EEPROM_SIZE - 0xa0)); + } else { + memset(ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE); + } // Bytes and Bits set for all Types @@ -2539,33 +2638,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x05] = eeprom->product_id >> 8; // Addr 06: Device release number (0400h for BM features) - output[0x06] = 0x00; - switch (ftdi->type) - { - case TYPE_AM: - output[0x07] = 0x02; - break; - case TYPE_BM: - output[0x07] = 0x04; - break; - case TYPE_2232C: - output[0x07] = 0x05; - break; - case TYPE_R: - output[0x07] = 0x06; - break; - case TYPE_2232H: - output[0x07] = 0x07; - break; - case TYPE_4232H: - output[0x07] = 0x08; - break; - case TYPE_232H: - output[0x07] = 0x09; - break; - default: - output[0x07] = 0x00; - } + output[0x06] = eeprom->release_number; + output[0x07] = eeprom->release_number >> 8; // Addr 08: Config descriptor // Bit 7: always 1 @@ -2573,16 +2647,16 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) // 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 / MAX_POWER_MILLIAMP_PER_UNIT; - if (ftdi->type != TYPE_AM) + if ((ftdi->type != TYPE_AM) && (ftdi->type != TYPE_230X)) { // Addr 0A: Chip configuration // Bit 7: 0 - reserved @@ -2595,9 +2669,9 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) // 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; } @@ -2621,6 +2695,10 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_AM: case TYPE_BM: i += 0x94; + break; + case TYPE_230X: + i = 0xa0; + break; } /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */ eeprom_size_mask = eeprom->size -1; @@ -2721,15 +2799,15 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) 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; @@ -2747,7 +2825,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) 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; @@ -2797,7 +2875,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) else output[0x01] &= ~SUSPEND_DBUS7_BIT; - if (eeprom->suspend_pull_downs == 1) + if (eeprom->suspend_pull_downs) output[0x0A] |= 0x4; else output[0x0A] &= ~0x4; @@ -2859,7 +2937,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) else output[0x01] &= ~(DRIVER_VCP << 4); - if (eeprom->suspend_pull_downs == 1) + if (eeprom->suspend_pull_downs) output[0x0a] |= 0x4; else output[0x0a] &= ~0x4; @@ -2965,7 +3043,14 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x1e] = eeprom->chip; fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n"); break; - + case TYPE_230X: + output[0x00] = 0x80; /* Actually, leave the default value */ + output[0x0a] = 0x08; /* Enable USB Serial Number */ + output[0x0c] = (0x01) | (0x3 << 4); /* DBUS drive 4mA, CBUS drive 16mA */ + for (j = 0; j <= 6; j++) { + output[0x1a + j] = eeprom->cbus_function[j]; + } + break; } // calculate checksum @@ -2973,6 +3058,10 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) for (i = 0; i < eeprom->size/2-1; i++) { + if ((ftdi->type == TYPE_230X) && (i == 0x12)) { + /* FT230X has a user section in the MTP which is not part of the checksum */ + i = 0x40; + } value = output[i*2]; value += output[(i*2)+1] << 8; @@ -2983,6 +3072,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[eeprom->size-2] = checksum; output[eeprom->size-1] = checksum >> 8; + eeprom->initialized_for_connected_device = 1; return user_area_size; } /* Decode the encoded EEPROM field for the FTDI Mode into a value for the abstracted @@ -3024,8 +3114,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) 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; + unsigned char *buf = NULL; if (ftdi == NULL) ftdi_error_return(-1,"No context"); @@ -3034,6 +3123,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom = ftdi->eeprom; eeprom_size = eeprom->size; + buf = ftdi->eeprom->buf; // Addr 02: Vendor ID eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8); @@ -3041,7 +3131,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) // Addr 04: Product ID eeprom->product_id = buf[0x04] + (buf[0x05] << 8); - release = buf[0x06] + (buf[0x07]<<8); + // Addr 06: Device release number + eeprom->release_number = buf[0x06] + (buf[0x07]<<8); // Addr 08: Config descriptor // Bit 7: always 1 @@ -3141,6 +3232,10 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) for (i = 0; i < eeprom_size/2-1; i++) { + if ((ftdi->type == TYPE_230X) && (i == 0x12)) { + /* FT230X has a user section in the MTP which is not part of the checksum */ + i = 0x40; + } value = buf[i*2]; value += buf[(i*2)+1] << 8; @@ -3256,13 +3351,25 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->chip = buf[0x1e]; /*FIXME: Decipher more values*/ } + else if (ftdi->type == TYPE_230X) + { + for(i=0; i<4; i++) { + eeprom->cbus_function[i] = buf[0x1a + i] & 0xFF; + } + eeprom->group0_drive = buf[0x0c] & 0x03; + eeprom->group0_schmitt = buf[0x0c] & IS_SCHMITT; + eeprom->group0_slew = buf[0x0c] & SLOW_SLEW; + eeprom->group1_drive = (buf[0x0c] >> 4) & 0x03; + eeprom->group1_schmitt = (buf[0x0c] >> 4) & IS_SCHMITT; + eeprom->group1_slew = (buf[0x0c] >> 4) & SLOW_SLEW; + } if (verbose) { char *channel_mode[] = {"UART", "FIFO", "CPU", "OPTO", "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); + fprintf(stdout, "Release: 0x%04x\n",eeprom->release_number); if (eeprom->self_powered) fprintf(stdout, "Self-Powered%s", (eeprom->remote_wakeup)?", USB Remote Wake Up\n":"\n"); @@ -3358,6 +3465,29 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) cbush_mux[eeprom->cbus_function[i]]); } } + else if (ftdi->type == TYPE_230X) + { + int i; + char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN", + "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN", + "CLK24","CLK12","CLK6","BAT_DETECT","BAT_DETECT#", + "I2C_TXE#", "I2C_RXF#", "VBUS_SENSE", "BB_WR#", + "BBRD#", "TIME_STAMP", "AWAKE#", + }; + fprintf(stdout,"IOBUS has %d mA drive%s%s\n", + (eeprom->group0_drive+1) *4, + (eeprom->group0_schmitt)?" Schmitt Input":"", + (eeprom->group0_slew)?" Slow Slew":""); + fprintf(stdout,"CBUS has %d mA drive%s%s\n", + (eeprom->group1_drive+1) *4, + (eeprom->group1_schmitt)?" Schmitt Input":"", + (eeprom->group1_slew)?" Slow Slew":""); + for (i=0; i<4; i++) + { + if (eeprom->cbus_function[i]<= CBUSH_AWAKE) + fprintf(stdout,"CBUS%d Function: %s\n", i, cbush_mux[eeprom->cbus_function[i]]); + } + } if (ftdi->type == TYPE_R) { @@ -3417,6 +3547,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case PRODUCT_ID: *value = ftdi->eeprom->product_id; break; + case RELEASE_NUMBER: + *value = ftdi->eeprom->release_number; + break; case SELF_POWERED: *value = ftdi->eeprom->self_powered; break; @@ -3604,6 +3737,9 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case PRODUCT_ID: ftdi->eeprom->product_id = value; break; + case RELEASE_NUMBER: + ftdi->eeprom->release_number = value; + break; case SELF_POWERED: ftdi->eeprom->self_powered = value; break; @@ -3765,6 +3901,7 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu default : ftdi_error_return(-1, "Request to unknown EEPROM value"); } + ftdi->eeprom->initialized_for_connected_device = 0; return 0; } @@ -4026,6 +4163,10 @@ int ftdi_write_eeprom(struct ftdi_context *ftdi) for (i = 0; i < ftdi->eeprom->size/2; i++) { + /* Do not try to write to reserved area */ + if ((ftdi->type == TYPE_230X) && (i == 0x40)) { + i = 0x50; + } usb_val = eeprom[i*2]; usb_val += eeprom[(i*2)+1] << 8; if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,