X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=6d0163f20968c7ffa4f1091454ebb56f266b018f;hp=af813f33ae9fa0d631494664d43a2744cecbeab0;hb=efc843050e8d0eaef34cef36db7c4acfec7830ff;hpb=90ef163e06dc90aebca58b8e4c99946392e37152 diff --git a/src/ftdi.c b/src/ftdi.c index af813f3..6d0163f 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -101,7 +101,7 @@ int ftdi_init(struct ftdi_context *ftdi) ftdi->error_str = NULL; - ftdi->eeprom_size = FTDI_DEFAULT_EEPROM_SIZE; + ftdi->eeprom = NULL; /* All fine. Now allocate the readbuffer */ return ftdi_read_data_set_chunksize(ftdi, 4096); @@ -1523,12 +1523,13 @@ int ftdi_transfer_data_done(struct ftdi_transfer_control *tc) ret = tc->offset; /** * tc->transfer could be NULL if "(size <= ftdi->readbuffer_remaining)" - * at ftdi_read_data_submit(). Therefore, has to check it here. + * at ftdi_read_data_submit(). Therefore, we need to check it here. **/ - if (tc->transfer) { - if (tc->transfer->status != LIBUSB_TRANSFER_COMPLETED) - ret = -1; - libusb_free_transfer(tc->transfer); + if (tc->transfer) + { + if (tc->transfer->status != LIBUSB_TRANSFER_COMPLETED) + ret = -1; + libusb_free_transfer(tc->transfer); } free(tc); return ret; @@ -2164,8 +2165,8 @@ void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom *eeprom, if (ftdi == NULL) return; - ftdi->eeprom_size=size; - eeprom->size=size; + ftdi->eeprom = eeprom; + ftdi->eeprom->size=size; } /** @@ -2173,17 +2174,25 @@ void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom *eeprom, \param eeprom Pointer to ftdi_eeprom */ -void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) +void ftdi_eeprom_initdefaults(struct ftdi_context *ftdi) { - if (eeprom == NULL) + int i; + struct ftdi_eeprom *eeprom; + + if (ftdi == NULL) return; + if (ftdi->eeprom == NULL) + return; + + eeprom = ftdi->eeprom; + eeprom->vendor_id = 0x0403; eeprom->product_id = 0x6001; eeprom->self_powered = 1; eeprom->remote_wakeup = 1; - eeprom->BM_type_chip = 1; + eeprom->chip_type = TYPE_BM; eeprom->in_is_isochronous = 0; eeprom->out_is_isochronous = 0; @@ -2197,8 +2206,14 @@ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) eeprom->manufacturer = NULL; eeprom->product = NULL; eeprom->serial = NULL; + for (i=0; i < 5; i++) + { + eeprom->cbus_function[i] = 0; + } + eeprom->high_current = 0; + eeprom->invert = 0; - eeprom->size = FTDI_DEFAULT_EEPROM_SIZE; + eeprom->size = FTDI_MAX_EEPROM_SIZE; } /** @@ -2206,19 +2221,26 @@ void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom) \param eeprom Pointer to ftdi_eeprom */ -void ftdi_eeprom_free(struct ftdi_eeprom *eeprom) +void ftdi_eeprom_free(struct ftdi_context *ftdi) { - 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; + 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; + } } } @@ -2226,22 +2248,32 @@ void ftdi_eeprom_free(struct ftdi_eeprom *eeprom) Build binary output 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 - \retval >0: used eeprom size + \retval >0: free eeprom size \retval -1: eeprom size (128 bytes) exceeded by custom strings \retval -2: Invalid eeprom pointer + \retval -3: Invalid cbus function setting + \retval -4: Chip doesn't support invert + \retval -5: Chip doesn't support high current drive */ -int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) +int ftdi_eeprom_build(struct ftdi_context *ftdi, unsigned char *output) { unsigned char i, j; unsigned short checksum, value; unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; int size_check; + const int cbus_max[5] = {13, 13, 13, 13, 9}; + struct ftdi_eeprom *eeprom; - if (eeprom == NULL) - return -2; + if (ftdi == NULL) + ftdi_error_return(-2,"No context"); + if (ftdi->eeprom == NULL) + ftdi_error_return(-2,"No eeprom structure"); + + eeprom= ftdi->eeprom; if (eeprom->manufacturer != NULL) manufacturer_size = strlen(eeprom->manufacturer); @@ -2250,6 +2282,18 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) if (eeprom->serial != NULL) serial_size = strlen(eeprom->serial); + // highest allowed cbus value + for (i = 0; i < 5; i++) + { + if ((eeprom->cbus_function[i] > cbus_max[i]) || + (eeprom->cbus_function[i] && eeprom->chip_type != TYPE_R)) return -3; + } + if (eeprom->chip_type != TYPE_R) + { + if (eeprom->invert) return -4; + if (eeprom->high_current) return -5; + } + size_check = eeprom->size; size_check -= 28; // 28 are always in use (fixed) @@ -2257,7 +2301,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // it seems that the FTDI chip will not read these strings from the lower half // Each string starts with two bytes; offset and type (0x03 for string) // the checksum needs two bytes, so without the string data that 8 bytes from the top half - if (eeprom->size>=256)size_check = 120; + if (eeprom->size>=256) size_check = 120; size_check -= manufacturer_size*2; size_check -= product_size*2; size_check -= serial_size*2; @@ -2269,7 +2313,12 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // empty eeprom memset (output, 0, eeprom->size); - // Addr 00: Stay 00 00 + // Addr 00: High current IO + output[0x00] = eeprom->high_current ? HIGH_CURRENT_DRIVE : 0; + // Addr 01: IN endpoint size (for R type devices, different for FT2232) + if (eeprom->chip_type == TYPE_R) { + output[0x01] = 0x40; + } // Addr 02: Vendor ID output[0x02] = eeprom->vendor_id; output[0x03] = eeprom->vendor_id >> 8; @@ -2280,11 +2329,22 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // Addr 06: Device release number (0400h for BM features) output[0x06] = 0x00; - - if (eeprom->BM_type_chip == 1) - output[0x07] = 0x04; - else - output[0x07] = 0x02; + switch (eeprom->chip_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; + default: + output[0x07] = 0x00; + } // Addr 08: Config descriptor // Bit 7: always 1 @@ -2324,8 +2384,8 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) j = j | 16; output[0x0A] = j; - // Addr 0B: reserved - output[0x0B] = 0x00; + // Addr 0B: Invert data lines + output[0x0B] = eeprom->invert & 0xff; // Addr 0C: USB version low byte when 0x0A bit 4 is set // Addr 0D: USB version high byte when 0x0A bit 4 is set @@ -2348,9 +2408,23 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) // Addr 13: Length of serial string output[0x13] = serial_size*2 + 2; + // Addr 14: CBUS function: CBUS0, CBUS1 + // Addr 15: CBUS function: CBUS2, CBUS3 + // Addr 16: CBUS function: CBUS5 + output[0x14] = eeprom->cbus_function[0] | (eeprom->cbus_function[1] << 4); + output[0x15] = eeprom->cbus_function[2] | (eeprom->cbus_function[3] << 4); + output[0x16] = eeprom->cbus_function[4]; + // Addr 17: Unknown + // Dynamic content - i=0x14; - if (eeprom->size>=256) i = 0x80; + // In images produced by FTDI's FT_Prog for FT232R strings start at 0x18 + // Space till 0x18 should be considered as reserved. + if (eeprom->chip_type >= TYPE_R) { + i = 0x18; + } else { + i = 0x14; + } + if (eeprom->size >= 256) i = 0x80; // Output manufacturer @@ -2414,37 +2488,23 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output) 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_eeprom *eeprom, unsigned char *buf, int size) +int ftdi_eeprom_decode(struct ftdi_context *ftdi, unsigned char *buf, int size) { unsigned char i, j; unsigned short checksum, eeprom_checksum, value; unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; - int eeprom_size = 128; + int eeprom_size; + struct ftdi_eeprom *eeprom; - if (eeprom == NULL) - return -1; -#if 0 - size_check = eeprom->size; - size_check -= 28; // 28 are always in use (fixed) - - // Top half of a 256byte eeprom is used just for strings and checksum - // it seems that the FTDI chip will not read these strings from the lower half - // Each string starts with two bytes; offset and type (0x03 for string) - // the checksum needs two bytes, so without the string data that 8 bytes from the top half - if (eeprom->size>=256)size_check = 120; - size_check -= manufacturer_size*2; - size_check -= product_size*2; - size_check -= serial_size*2; - - // eeprom size exceeded? - if (size_check < 0) - return (-1); -#endif - - // empty eeprom struct - memset(eeprom, 0, sizeof(struct ftdi_eeprom)); - - // Addr 00: Stay 00 00 + if (ftdi == NULL) + ftdi_error_return(-1,"No context"); + if (ftdi->eeprom == NULL) + ftdi_error_return(-1,"No eeprom"); + + eeprom_size = ftdi->eeprom->size; + if(ftdi->type == TYPE_R) + eeprom_size = 0x80; + eeprom = ftdi->eeprom; // Addr 02: Vendor ID eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8); @@ -2455,14 +2515,17 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) value = buf[0x06] + (buf[0x07]<<8); switch (value) { + case 0x0600: + eeprom->chip_type = TYPE_R; + break; case 0x0400: - eeprom->BM_type_chip = 1; + eeprom->chip_type = TYPE_BM; break; case 0x0200: - eeprom->BM_type_chip = 0; + eeprom->chip_type = TYPE_AM; break; default: // Unknown device - eeprom->BM_type_chip = 0; + eeprom->chip_type = 0; break; } @@ -2495,7 +2558,8 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) if (j&0x08) eeprom->use_serial = 1; if (j&0x10) eeprom->change_usb_version = 1; - // Addr 0B: reserved + // Addr 0B: Invert data lines + eeprom->invert = buf[0x0B]; // Addr 0C: USB version low byte when 0x0A bit 4 is set // Addr 0D: USB version high byte when 0x0A bit 4 is set @@ -2507,44 +2571,72 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) // Addr 0E: Offset of the manufacturer string + 0x80, calculated later // Addr 0F: Length of manufacturer string manufacturer_size = buf[0x0F]/2; - if (manufacturer_size > 0) eeprom->manufacturer = malloc(manufacturer_size); + if (manufacturer_size > 0) + { + eeprom->manufacturer = malloc(manufacturer_size); + if (eeprom->manufacturer) + { + // Decode manufacturer + i = buf[0x0E]; // offset + for (j=0;jmanufacturer[j] = buf[2*j+i+2]; + } + eeprom->manufacturer[j] = '\0'; + } + } else eeprom->manufacturer = NULL; // Addr 10: Offset of the product string + 0x80, calculated later // Addr 11: Length of product string product_size = buf[0x11]/2; - if (product_size > 0) eeprom->product = malloc(product_size); + if (product_size > 0) + { + eeprom->product = malloc(product_size); + if(eeprom->product) + { + // Decode product name + i = buf[0x10]; // offset + for (j=0;jproduct[j] = buf[2*j+i+2]; + } + eeprom->product[j] = '\0'; + } + } else eeprom->product = NULL; // Addr 12: Offset of the serial string + 0x80, calculated later // Addr 13: Length of serial string serial_size = buf[0x13]/2; - if (serial_size > 0) eeprom->serial = malloc(serial_size); - else eeprom->serial = NULL; - - // Decode manufacturer - i = buf[0x0E] & 0x7f; // offset - for (j=0;jmanufacturer[j] = buf[2*j+i+2]; - } - eeprom->manufacturer[j] = '\0'; - - // Decode product name - i = buf[0x10] & 0x7f; // offset - for (j=0;j 0) { - eeprom->product[j] = buf[2*j+i+2]; + eeprom->serial = malloc(serial_size); + if(eeprom->serial) + { + // Decode serial + i = buf[0x12]; // offset + for (j=0;jserial[j] = buf[2*j+i+2]; + } + eeprom->serial[j] = '\0'; + } } - eeprom->product[j] = '\0'; + else eeprom->serial = NULL; - // Decode serial - i = buf[0x12] & 0x7f; // offset - for (j=0;jserial[j] = buf[2*j+i+2]; + // Addr 14: CBUS function: CBUS0, CBUS1 + // Addr 15: CBUS function: CBUS2, CBUS3 + // Addr 16: CBUS function: CBUS5 + if (eeprom->chip_type == TYPE_R) { + eeprom->cbus_function[0] = buf[0x14] & 0x0f; + eeprom->cbus_function[1] = (buf[0x14] >> 4) & 0x0f; + eeprom->cbus_function[2] = buf[0x15] & 0x0f; + eeprom->cbus_function[3] = (buf[0x15] >> 4) & 0x0f; + eeprom->cbus_function[4] = buf[0x16] & 0x0f; + } else { + for (j=0; j<5; j++) eeprom->cbus_function[j] = 0; } - eeprom->serial[j] = '\0'; // verify checksum checksum = 0xAAAA; @@ -2563,7 +2655,7 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *buf, int size) if (eeprom_checksum != checksum) { fprintf(stderr, "Checksum Error: %04x %04x\n", checksum, eeprom_checksum); - return -1; + ftdi_error_return(-1,"EEPROM checksum error"); } return 0; @@ -2585,7 +2677,7 @@ int ftdi_read_eeprom_location (struct ftdi_context *ftdi, int eeprom_addr, unsig if (ftdi == NULL || ftdi->usb_dev == NULL) ftdi_error_return(-2, "USB device unavailable"); - if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, eeprom_addr, (char *)eeprom_val, 2, ftdi->usb_read_timeout) != 2) + if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_IN_REQTYPE, SIO_READ_EEPROM_REQUEST, 0, eeprom_addr, (unsigned char *)eeprom_val, 2, ftdi->usb_read_timeout) != 2) ftdi_error_return(-1, "reading eeprom failed"); return 0; @@ -2608,12 +2700,24 @@ int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) if (ftdi == NULL || ftdi->usb_dev == NULL) ftdi_error_return(-2, "USB device unavailable"); - for (i = 0; i < ftdi->eeprom_size/2; i++) + 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) ftdi_error_return(-1, "reading eeprom failed"); } + if (ftdi->type == TYPE_R) + ftdi->eeprom->size = 0xa0; + /* 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)) + ftdi->eeprom->size = -1; + else if(memcmp(eeprom,&eeprom[0x80],0x80) == 0) + ftdi->eeprom->size = 0x80; + else if(memcmp(eeprom,&eeprom[0x40],0x40) == 0) + ftdi->eeprom->size = 0x40; + else + ftdi->eeprom->size = 0x100; return 0; } @@ -2669,43 +2773,6 @@ int ftdi_read_chipid(struct ftdi_context *ftdi, unsigned int *chipid) } /** - Guesses size of eeprom by reading eeprom and comparing halves - will not work with blank eeprom - Call this function then do a write then call again to see if size changes, if so write again. - - \param ftdi pointer to ftdi_context - \param eeprom Pointer to store eeprom into - \param maxsize the size of the buffer to read into - - \retval -1: eeprom read failed - \retval -2: USB device unavailable - \retval >=0: size of eeprom -*/ -int ftdi_read_eeprom_getsize(struct ftdi_context *ftdi, unsigned char *eeprom, int maxsize) -{ - int i=0,j,minsize=32; - int size=minsize; - - if (ftdi == NULL || ftdi->usb_dev == NULL) - ftdi_error_return(-2, "USB device unavailable"); - - do - { - for (j = 0; i < maxsize/2 && jusb_dev, FTDI_DEVICE_IN_REQTYPE, - SIO_READ_EEPROM_REQUEST, 0, i, - eeprom+(i*2), 2, ftdi->usb_read_timeout) != 2) - ftdi_error_return(-1, "eeprom read failed"); - i++; - } - size*=2; - } - while (size<=maxsize && memcmp(eeprom,&eeprom[size/2],size/2)!=0); - - return size/2; -} - -/** Write eeprom location \param ftdi pointer to ftdi_context @@ -2755,7 +2822,7 @@ int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom) if ((ret = ftdi_set_latency_timer(ftdi, 0x77)) != 0) return ret; - for (i = 0; i < ftdi->eeprom_size/2; i++) + for (i = 0; i < ftdi->eeprom->size/2; i++) { usb_val = eeprom[i*2]; usb_val += eeprom[(i*2)+1] << 8;