X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=aa4b4ecf160fe7280d71fab7c37c6fa7a5a84dc2;hp=68489ea096be6f1e4dd4224104d9210fa9a88d69;hb=6e962b9a0991bf28571c7a143a532d83237c05af;hpb=1162549f619aad91ba30008b64827b3716d15b76 diff --git a/src/ftdi.c b/src/ftdi.c index 68489ea..aa4b4ec 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -2563,7 +2563,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) unsigned char i, j, eeprom_size_mask; unsigned short checksum, value; unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0; - int user_area_size; + int user_area_size, free_start, free_end; struct ftdi_eeprom *eeprom; unsigned char * output; @@ -2598,14 +2598,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) { case TYPE_AM: case TYPE_BM: + case TYPE_R: user_area_size = 96; // base size for strings (total of 48 characters) break; case TYPE_2232C: user_area_size = 90; // two extra config bytes and 4 bytes PnP stuff break; - case TYPE_R: - user_area_size = 96; - break; case TYPE_230X: user_area_size = 88; // four extra config bytes + 4 bytes PnP stuff break; @@ -2712,6 +2710,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) } /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */ eeprom_size_mask = eeprom->size -1; + free_end = i & eeprom_size_mask; // Addr 0E: Offset of the manufacturer string + 0x80, calculated later // Addr 0F: Length of manufacturer string @@ -2779,7 +2778,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_BM: output[0x0C] = eeprom->usb_version & 0xff; output[0x0D] = (eeprom->usb_version>>8) & 0xff; - if (eeprom->use_usb_version == USE_USB_VERSION_BIT) + if (eeprom->use_usb_version) output[0x0A] |= USE_USB_VERSION_BIT; else output[0x0A] &= ~USE_USB_VERSION_BIT; @@ -2821,7 +2820,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x0A] |= 0x4; else output[0x0A] &= ~0x4; - if (eeprom->use_usb_version == USE_USB_VERSION_BIT) + if (eeprom->use_usb_version) output[0x0A] |= USE_USB_VERSION_BIT; else output[0x0A] &= ~USE_USB_VERSION_BIT; @@ -2833,6 +2832,8 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_R: if (eeprom->high_current == HIGH_CURRENT_DRIVE_R) output[0x00] |= HIGH_CURRENT_DRIVE_R; + if (eeprom->external_oscillator) + output[0x00] |= 0x02; output[0x01] = 0x40; /* Hard coded Endpoint Size*/ if (eeprom->suspend_pull_downs) @@ -3072,6 +3073,38 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) break; } + /* First address without use */ + free_start = 0; + switch (ftdi->type) + { + case TYPE_230X: + free_start += 2; + case TYPE_232H: + free_start += 6; + case TYPE_2232H: + case TYPE_4232H: + free_start += 2; + case TYPE_R: + free_start += 2; + case TYPE_2232C: + free_start++; + case TYPE_AM: + case TYPE_BM: + free_start += 0x14; + } + + /* Arbitrary user data */ + if (eeprom->user_data && eeprom->user_data_size >= 0) + { + if (eeprom->user_data_addr < free_start) + fprintf(stderr,"Warning, user data starts inside the generated data!\n"); + if (eeprom->user_data_addr + eeprom->user_data_size >= free_end) + fprintf(stderr,"Warning, user data overlaps the strings area!\n"); + if (eeprom->user_data_addr + eeprom->user_data_size > eeprom->size) + ftdi_error_return(-1,"eeprom size exceeded"); + memcpy(output + eeprom->user_data_addr, eeprom->user_data, eeprom->user_data_size); + } + // calculate checksum checksum = 0xAAAA; @@ -3203,8 +3236,8 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->in_is_isochronous = buf[0x0A]&0x01; eeprom->out_is_isochronous = buf[0x0A]&0x02; eeprom->suspend_pull_downs = buf[0x0A]&0x04; - eeprom->use_serial = (buf[0x0A] & USE_SERIAL_NUM)?1:0; - eeprom->use_usb_version = buf[0x0A] & USE_USB_VERSION_BIT; + eeprom->use_serial = !!(buf[0x0A] & USE_SERIAL_NUM); + eeprom->use_usb_version = !!(buf[0x0A] & USE_USB_VERSION_BIT); // Addr 0C: USB version low byte when 0x0A // Addr 0D: USB version high byte when 0x0A @@ -3318,6 +3351,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) /* TYPE_R flags D2XX, not VCP as all others*/ eeprom->channel_a_driver = ~buf[0x00] & DRIVER_VCP; eeprom->high_current = buf[0x00] & HIGH_CURRENT_DRIVE_R; + eeprom->external_oscillator = buf[0x00] & 0x02; if ( (buf[0x01]&0x40) != 0x40) fprintf(stderr, "TYPE_R EEPROM byte[0x01] Bit 6 unexpected Endpoint size." @@ -3431,8 +3465,10 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) if (eeprom->serial) fprintf(stdout, "Serial: %s\n",eeprom->serial); fprintf(stdout, "Checksum : %04x\n", checksum); - if (ftdi->type == TYPE_R) + if (ftdi->type == TYPE_R) { fprintf(stdout, "Internal EEPROM\n"); + fprintf(stdout,"Oscillator: %s\n", eeprom->external_oscillator?"External":"Internal"); + } else if (eeprom->chip >= 0x46) fprintf(stdout, "Attached EEPROM: 93x%02x\n", eeprom->chip); if (eeprom->suspend_dbus7) @@ -3465,7 +3501,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) (eeprom->channel_b_driver)?" VCP":"", (eeprom->high_current_b)?" High Current IO":""); if (((ftdi->type == TYPE_BM) || (ftdi->type == TYPE_2232C)) && - eeprom->use_usb_version == USE_USB_VERSION_BIT) + eeprom->use_usb_version) fprintf(stdout,"Use explicit USB Version %04x\n",eeprom->usb_version); if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H)) @@ -3752,6 +3788,9 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CHIP_SIZE: *value = ftdi->eeprom->size; break; + case EXTERNAL_OSCILLATOR: + *value = ftdi->eeprom->external_oscillator; + break; default: ftdi_error_return(-1, "Request for unknown EEPROM value"); } @@ -3942,6 +3981,12 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CHIP_SIZE: ftdi_error_return(-2, "EEPROM Value can't be changed"); break; + case EXTERNAL_OSCILLATOR: + ftdi->eeprom->external_oscillator = value; + break; + case USER_DATA_ADDR: + ftdi->eeprom->user_data_addr = value; + break; default : ftdi_error_return(-1, "Request to unknown EEPROM value"); @@ -3984,7 +4029,7 @@ int ftdi_get_eeprom_buf(struct ftdi_context *ftdi, unsigned char * buf, int size \param size Size of buffer \retval 0: All fine - \retval -1: struct ftdi_contxt or ftdi_eeprom of buf missing + \retval -1: struct ftdi_context or ftdi_eeprom or buf missing */ int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, int size) { @@ -4000,6 +4045,25 @@ int ftdi_set_eeprom_buf(struct ftdi_context *ftdi, const unsigned char * buf, in return 0; } +/** Set the EEPROM user data content from the user-supplied prefilled buffer + + \param ftdi pointer to ftdi_context + \param buf buffer to read EEPROM user data content + \param size Size of buffer + + \retval 0: All fine + \retval -1: struct ftdi_context or ftdi_eeprom or buf missing +*/ +int ftdi_set_eeprom_user_data(struct ftdi_context *ftdi, const char * buf, int size) +{ + if (!ftdi || !(ftdi->eeprom) || !buf) + ftdi_error_return(-1, "No appropriate structure"); + + ftdi->eeprom->user_data_size = size; + ftdi->eeprom->user_data = buf; + return 0; +} + /** Read eeprom location