X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=612376b2e15440e887c582c72210e733a3f35a2b;hp=9f892d39514cf3fabc18ae8fa970b18a03de99cb;hb=d4b5af27db53a281adb134aaa91b75335accb57d;hpb=bb104e5b1066701452e56fb0fbacd1851f2ab22a diff --git a/src/ftdi.c b/src/ftdi.c index 9f892d3..612376b 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -63,6 +63,8 @@ static void ftdi_usb_close_internal (struct ftdi_context *ftdi) { libusb_close (ftdi->usb_dev); ftdi->usb_dev = NULL; + if(ftdi->eeprom) + ftdi->eeprom->initialized_for_connected_device = 0; } } @@ -1089,6 +1091,16 @@ static int ftdi_convert_baudrate(int baudrate, struct ftdi_context *ftdi, } /** + * @brief Wrapper function to export ftdi_convert_baudrate() to the unit test + * Do not use, it's only for the unit test framework + **/ +int convert_baudrate_UT_export(int baudrate, struct ftdi_context *ftdi, + unsigned short *value, unsigned short *index) +{ + return ftdi_convert_baudrate(baudrate, ftdi, value, index); +} + +/** Sets the chip baud rate \param ftdi pointer to ftdi_context @@ -2177,7 +2189,7 @@ int ftdi_set_error_char(struct ftdi_context *ftdi, } /** - Init eeprom with default values. + Init eeprom with default values for the connected device \param ftdi pointer to ftdi_context \param manufacturer String to use as Manufacturer \param product String to use as Product description @@ -2186,6 +2198,7 @@ int ftdi_set_error_char(struct ftdi_context *ftdi, \retval 0: all fine \retval -1: No struct ftdi_context \retval -2: No struct ftdi_eeprom + \retval -3: No connected device or device not yet opened */ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, char * product, char * serial) @@ -2201,8 +2214,11 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, eeprom = ftdi->eeprom; memset(eeprom, 0, sizeof(struct ftdi_eeprom)); + if (ftdi->usb_dev == NULL) + ftdi_error_return(-3, "No connected device or device not yet opened"); + eeprom->vendor_id = 0x0403; - eeprom->use_serial = USE_SERIAL_NUM; + eeprom->use_serial = 1; if ((ftdi->type == TYPE_AM) || (ftdi->type == TYPE_BM) || (ftdi->type == TYPE_R)) eeprom->product_id = 0x6001; @@ -2269,6 +2285,7 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, } eeprom->size = -1; } + eeprom->initialized_for_connected_device = 1; return 0; } /*FTD2XX doesn't check for values not fitting in the ACBUS Signal oprtions*/ @@ -2290,6 +2307,42 @@ void set_ft232h_cbus(struct ftdi_eeprom *eeprom, unsigned char * output) output[0x18+i] = mode_high <<4 | mode_low; } } +/* Return the bits for the encoded EEPROM Structure of a requested Mode + * + */ +static unsigned char type2bit(unsigned char type, enum ftdi_chip_type chip) +{ + switch (chip) + { + case TYPE_2232H: + case TYPE_2232C: + { + switch (type) + { + case CHANNEL_IS_UART: return 0; + case CHANNEL_IS_FIFO: return 0x01; + case CHANNEL_IS_OPTO: return 0x02; + case CHANNEL_IS_CPU : return 0x04; + default: return 0; + } + } + case TYPE_232H: + { + switch (type) + { + case CHANNEL_IS_UART : return 0; + case CHANNEL_IS_FIFO : return 0x01; + case CHANNEL_IS_OPTO : return 0x02; + case CHANNEL_IS_CPU : return 0x04; + case CHANNEL_IS_FT1284 : return 0x08; + default: return 0; + } + } + default: return 0; + } + return 0; +} + /** Build binary buffer from ftdi_eeprom structure. Output is suitable for ftdi_write_eeprom(). @@ -2353,6 +2406,9 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_4232H: user_area_size = 86; break; + case TYPE_232H: + user_area_size = 80; + break; default: user_area_size = 0; break; @@ -2513,7 +2569,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) if (ftdi->type > TYPE_AM) /* use_serial not used in AM devices */ { - if (eeprom->use_serial == USE_SERIAL_NUM ) + if (eeprom->use_serial) output[0x0A] |= USE_SERIAL_NUM; else output[0x0A] &= ~USE_SERIAL_NUM; @@ -2536,7 +2592,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) break; case TYPE_2232C: - output[0x00] = (eeprom->channel_a_type)?((1<<(eeprom->channel_a_type)) & 0x7):0; + output[0x00] = type2bit(eeprom->channel_a_type, TYPE_2232C); if ( eeprom->channel_a_driver == DRIVER_VCP) output[0x00] |= DRIVER_VCP; else @@ -2547,7 +2603,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) else output[0x00] &= ~HIGH_CURRENT_DRIVE; - output[0x01] = (eeprom->channel_b_type)?((1<<(eeprom->channel_b_type)) & 0x7):0; + output[0x01] = type2bit(eeprom->channel_b_type, TYPE_2232C); if ( eeprom->channel_b_driver == DRIVER_VCP) output[0x01] |= DRIVER_VCP; else @@ -2618,13 +2674,13 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) output[0x16] = eeprom->cbus_function[4]; break; case TYPE_2232H: - output[0x00] = (eeprom->channel_a_type)?((1<<(eeprom->channel_a_type)) & 0x7):0; + output[0x00] = type2bit(eeprom->channel_a_type, TYPE_2232H); if ( eeprom->channel_a_driver == DRIVER_VCP) output[0x00] |= DRIVER_VCP; else output[0x00] &= ~DRIVER_VCP; - output[0x01] = (eeprom->channel_b_type)?((1<<(eeprom->channel_b_type)) & 0x7):0; + output[0x01] = type2bit(eeprom->channel_b_type, TYPE_2232H); if ( eeprom->channel_b_driver == DRIVER_VCP) output[0x01] |= DRIVER_VCP; else @@ -2683,7 +2739,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n"); break; case TYPE_232H: - output[0x00] = (eeprom->channel_a_type)?((1<<(eeprom->channel_a_type)) & 0xf):0; + output[0x00] = type2bit(eeprom->channel_a_type, TYPE_232H); if ( eeprom->channel_a_driver == DRIVER_VCP) output[0x00] |= DRIVER_VCPH; else @@ -2747,23 +2803,26 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) return user_area_size; } -/* FTD2XX doesn't allow to set multiple bits in the interface mode bitfield*/ -unsigned char bit2type(unsigned char bits) +/* Decode the encoded EEPROM field for the FTDI Mode into a value for the abstracted + * EEPROM structure + * + * FTD2XX doesn't allow to set multiple bits in the interface mode bitfield, and so do we + */ +static unsigned char bit2type(unsigned char bits) { switch (bits) { - case 0: return 0; - case 1: return 1; - case 2: return 2; - case 4: return 3; - case 8: return 4; + case 0: return CHANNEL_IS_UART; + case 1: return CHANNEL_IS_FIFO; + case 2: return CHANNEL_IS_OPTO; + case 4: return CHANNEL_IS_CPU; + case 8: return CHANNEL_IS_FT1284; default: fprintf(stderr," Unexpected value %d for Hardware Interface type\n", bits); } return 0; } - /** Decode binary EEPROM image into an ftdi_eeprom structure. @@ -2825,7 +2884,7 @@ 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; + eeprom->use_serial = (buf[0x0A] & USE_SERIAL_NUM)?1:0; eeprom->use_usb_version = buf[0x0A] & USE_USB_VERSION_BIT; // Addr 0C: USB version low byte when 0x0A @@ -2959,7 +3018,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) { eeprom->channel_a_type = bit2type(buf[0x00] & 0x7); eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP; - eeprom->channel_b_type = buf[0x01] & 0x7; + eeprom->channel_b_type = bit2type(buf[0x01] & 0x7); eeprom->channel_b_driver = buf[0x01] & DRIVER_VCP; if (ftdi->type == TYPE_2232H) @@ -3007,7 +3066,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) if (verbose) { - char *channel_mode[] = {"UART","245","CPU", "OPTO", "FT1284"}; + 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); @@ -3713,6 +3772,7 @@ int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr, \retval 0: all fine \retval -1: read failed \retval -2: USB device unavailable + \retval -3: EEPROM not initialized for the connected device; */ int ftdi_write_eeprom(struct ftdi_context *ftdi) { @@ -3722,6 +3782,10 @@ int ftdi_write_eeprom(struct ftdi_context *ftdi) if (ftdi == NULL || ftdi->usb_dev == NULL) ftdi_error_return(-2, "USB device unavailable"); + + if(ftdi->eeprom->initialized_for_connected_device == 0) + ftdi_error_return(-3, "EEPROM not initialized for the connected device"); + eeprom = ftdi->eeprom->buf; /* These commands were traced while running MProg */