X-Git-Url: http://developer.intra2net.com/git/?p=libftdi;a=blobdiff_plain;f=src%2Fftdi.c;h=852b3ff0b3166de141c9c99cb866897a727131b9;hp=33b6a50f655da7fdc81475eff7792a5b8bca7737;hb=56631bed49236cc5f3c2b66da38eca5567867310;hpb=77377af7cb038876829f2421dba5977718ca154f diff --git a/src/ftdi.c b/src/ftdi.c index 33b6a50..852b3ff 100644 --- a/src/ftdi.c +++ b/src/ftdi.c @@ -257,8 +257,10 @@ void ftdi_set_usbdev (struct ftdi_context *ftdi, libusb_device_handle *usb) /** - Finds all ftdi devices on the usb bus. Creates a new ftdi_device_list which - needs to be deallocated by ftdi_list_free() after use. + Finds all ftdi devices with given VID:PID on the usb bus. Creates a new + ftdi_device_list which needs to be deallocated by ftdi_list_free() after + use. With VID:PID 0:0, search for the default devices + (0x403:0x6001, 0x403:0x6010, 0x403:0x6011, 0x403:0x6014) \param ftdi pointer to ftdi_context \param devlist Pointer where to store list of found devices @@ -291,7 +293,11 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli if (libusb_get_device_descriptor(dev, &desc) < 0) ftdi_error_return_free_device_list(-6, "libusb_get_device_descriptor() failed", devs); - if (desc.idVendor == vendor && desc.idProduct == product) + if (((vendor != 0 && product != 0) && + desc.idVendor == vendor && desc.idProduct == product) || + ((vendor == 0 && product == 0) && + (desc.idVendor == 0x403) && (desc.idProduct == 0x6001 || desc.idProduct == 0x6010 + || desc.idProduct == 0x6011 || desc.idProduct == 0x6014))) { *curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list)); if (!*curdev) @@ -299,7 +305,7 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli (*curdev)->next = NULL; (*curdev)->dev = dev; - + libusb_ref_device(dev); curdev = &(*curdev)->next; count++; } @@ -320,6 +326,7 @@ void ftdi_list_free(struct ftdi_device_list **devlist) for (curdev = *devlist; curdev != NULL;) { next = curdev->next; + libusb_unref_device(curdev->dev); free(curdev); curdev = next; } @@ -428,7 +435,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) + if (ftdi->type == TYPE_2232H || ftdi->type == TYPE_4232H || ftdi->type == TYPE_232H ) packet_size = 512; else packet_size = 64; @@ -564,6 +571,8 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi, libusb_device *dev) ftdi->type = TYPE_2232H; else if (desc.bcdDevice == 0x800) ftdi->type = TYPE_4232H; + else if (desc.bcdDevice == 0x900) + ftdi->type = TYPE_232H; // Determine maximum packet size ftdi->max_packet_size = _ftdi_determine_max_packet_size(ftdi, dev); @@ -609,7 +618,6 @@ int ftdi_usb_open(struct ftdi_context *ftdi, int vendor, int product) \retval -7: set baudrate failed \retval -8: get product description failed \retval -9: get serial number failed - \retval -11: libusb_init() failed \retval -12: libusb_get_device_list() failed \retval -13: libusb_get_device_descriptor() failed */ @@ -654,9 +662,6 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, if (ftdi == NULL) ftdi_error_return(-11, "ftdi context invalid"); - if (libusb_init(&ftdi->usb_ctx) < 0) - ftdi_error_return(-11, "libusb_init() failed"); - if (libusb_get_device_list(ftdi->usb_ctx, &devs) < 0) ftdi_error_return(-12, "libusb_get_device_list() failed"); @@ -732,7 +737,6 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product, \note The description format may be extended in later versions. \retval 0: all fine - \retval -1: libusb_init() failed \retval -2: libusb_get_device_list() failed \retval -3: usb device not found \retval -4: unable to open device @@ -760,9 +764,6 @@ int ftdi_usb_open_string(struct ftdi_context *ftdi, const char* description) unsigned int bus_number, device_address; int i = 0; - if (libusb_init (&ftdi->usb_ctx) < 0) - ftdi_error_return(-1, "libusb_init() failed"); - if (libusb_get_device_list(ftdi->usb_ctx, &devs) < 0) ftdi_error_return(-2, "libusb_get_device_list() failed"); @@ -2205,6 +2206,10 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, if ((ftdi->type == TYPE_AM) || (ftdi->type == TYPE_BM) || (ftdi->type == TYPE_R)) eeprom->product_id = 0x6001; + else if (ftdi->type == TYPE_4232H) + eeprom->product_id = 0x6011; + else if (ftdi->type == TYPE_232H) + eeprom->product_id = 0x6014; else eeprom->product_id = 0x6010; if (ftdi->type == TYPE_AM) @@ -2255,10 +2260,36 @@ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer, eeprom->cbus_function[4] = CBUS_SLEEP; } else + { + if(ftdi->type == TYPE_232H) + { + int i; + for (i=0; i<10; i++) + eeprom->cbus_function[i] = CBUSH_TRISTATE; + } eeprom->size = -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) +{ + int i; + for(i=0; i<5;i++) + { + int mode_low, mode_high; + if (eeprom->cbus_function[2*i]> CBUSH_CLK7_5) + mode_low = CBUSH_TRISTATE; + else + mode_low = eeprom->cbus_function[2*i]; + if (eeprom->cbus_function[2*i+1]> CBUSH_CLK7_5) + mode_high = CBUSH_TRISTATE; + else + mode_high = eeprom->cbus_function[2*i]; + output[0x18+i] = mode_high <<4 | mode_low; + } +} /** Build binary buffer from ftdi_eeprom structure. Output is suitable for ftdi_write_eeprom(). @@ -2366,6 +2397,9 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) case TYPE_4232H: output[0x07] = 0x08; break; + case TYPE_232H: + output[0x07] = 0x09; + break; default: output[0x07] = 0x00; } @@ -2408,9 +2442,12 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) // Dynamic content // Strings start at 0x94 (TYPE_AM, TYPE_BM) // 0x96 (TYPE_2232C), 0x98 (TYPE_R) and 0x9a (TYPE_x232H) + // 0xa0 (TYPE_232H) i = 0; switch (ftdi->type) { + case TYPE_232H: + i += 2; case TYPE_2232H: case TYPE_4232H: i += 2; @@ -2499,7 +2536,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) break; case TYPE_2232C: - output[0x00] = (eeprom->channel_a_type); + output[0x00] = (eeprom->channel_a_type)?((1<<(eeprom->channel_a_type)) & 0x7):0; if ( eeprom->channel_a_driver == DRIVER_VCP) output[0x00] |= DRIVER_VCP; else @@ -2510,7 +2547,7 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) else output[0x00] &= ~HIGH_CURRENT_DRIVE; - output[0x01] = (eeprom->channel_b_type); + output[0x01] = (eeprom->channel_b_type)?((1<<(eeprom->channel_b_type)) & 0x7):0; if ( eeprom->channel_b_driver == DRIVER_VCP) output[0x01] |= DRIVER_VCP; else @@ -2581,13 +2618,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); + output[0x00] = (eeprom->channel_a_type)?((1<<(eeprom->channel_a_type)) & 0x7):0; if ( eeprom->channel_a_driver == DRIVER_VCP) output[0x00] |= DRIVER_VCP; else output[0x00] &= ~DRIVER_VCP; - output[0x01] = (eeprom->channel_b_type); + output[0x01] = (eeprom->channel_b_type)?((1<<(eeprom->channel_b_type)) & 0x7):0; if ( eeprom->channel_b_driver == DRIVER_VCP) output[0x01] |= DRIVER_VCP; else @@ -2642,7 +2679,55 @@ int ftdi_eeprom_build(struct ftdi_context *ftdi) break; case TYPE_4232H: + output[0x18] = eeprom->chip; 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; + if ( eeprom->channel_a_driver == DRIVER_VCP) + output[0x00] |= DRIVER_VCPH; + else + output[0x00] &= ~DRIVER_VCPH; + if (eeprom->powersave) + output[0x01] |= POWER_SAVE_DISABLE_H; + else + output[0x01] &= ~POWER_SAVE_DISABLE_H; + if (eeprom->clock_polarity) + output[0x01] |= FT1284_CLK_IDLE_STATE; + else + output[0x01] &= ~FT1284_CLK_IDLE_STATE; + if (eeprom->data_order) + output[0x01] |= FT1284_DATA_LSB; + else + output[0x01] &= ~FT1284_DATA_LSB; + if (eeprom->flow_control) + output[0x01] |= FT1284_FLOW_CONTROL; + else + output[0x01] &= ~FT1284_FLOW_CONTROL; + if (eeprom->group0_drive > DRIVE_16MA) + output[0x0c] |= DRIVE_16MA; + else + output[0x0c] |= eeprom->group0_drive; + if (eeprom->group0_schmitt == IS_SCHMITT) + output[0x0c] |= IS_SCHMITT; + if (eeprom->group0_slew == SLOW_SLEW) + output[0x0c] |= SLOW_SLEW; + + if (eeprom->group1_drive > DRIVE_16MA) + output[0x0d] |= DRIVE_16MA; + else + output[0x0d] |= eeprom->group1_drive; + if (eeprom->group1_schmitt == IS_SCHMITT) + output[0x0d] |= IS_SCHMITT; + if (eeprom->group1_slew == SLOW_SLEW) + output[0x0d] |= SLOW_SLEW; + + set_ft232h_cbus(eeprom, output); + + output[0x1e] = eeprom->chip; + fprintf(stderr,"FIXME: Build FT232H specific EEPROM settings\n"); + break; + } // calculate checksum @@ -2662,6 +2747,22 @@ 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) +{ + switch (bits) + { + case 0: return 0; + case 1: return 1; + case 2: return 2; + case 4: return 3; + case 8: return 4; + default: + fprintf(stderr," Unexpected value %d for Hardware Interface type\n", + bits); + } + return 0; +} /** Decode binary EEPROM image into an ftdi_eeprom structure. @@ -2821,7 +2922,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) } else if (ftdi->type == TYPE_2232C) { - eeprom->channel_a_type = buf[0x00] & 0x7; + eeprom->channel_a_type = bit2type(buf[0x00] & 0x7); eeprom->channel_a_driver = buf[0x00] & DRIVER_VCP; eeprom->high_current_a = buf[0x00] & HIGH_CURRENT_DRIVE; eeprom->channel_b_type = buf[0x01] & 0x7; @@ -2856,7 +2957,7 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) } else if ((ftdi->type == TYPE_2232H) ||(ftdi->type == TYPE_4232H)) { - eeprom->channel_a_type = buf[0x00] & 0x7; + 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_driver = buf[0x01] & DRIVER_VCP; @@ -2878,10 +2979,35 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) eeprom->group3_schmitt = (buf[0x0d] >> 4) & IS_SCHMITT; eeprom->group3_slew = (buf[0x0d] >> 4) & SLOW_SLEW; } + else if (ftdi->type == TYPE_232H) + { + int i; + + eeprom->channel_a_type = buf[0x00] & 0xf; + eeprom->channel_a_driver = (buf[0x00] & DRIVER_VCPH)?DRIVER_VCP:0; + eeprom->clock_polarity = buf[0x01] & FT1284_CLK_IDLE_STATE; + eeprom->data_order = buf[0x01] & FT1284_DATA_LSB; + eeprom->flow_control = buf[0x01] & FT1284_FLOW_CONTROL; + eeprom->powersave = buf[0x01] & POWER_SAVE_DISABLE_H; + eeprom->group0_drive = buf[0x0c] & DRIVE_16MA; + eeprom->group0_schmitt = buf[0x0c] & IS_SCHMITT; + eeprom->group0_slew = buf[0x0c] & SLOW_SLEW; + eeprom->group1_drive = buf[0x0d] & DRIVE_16MA; + eeprom->group1_schmitt = buf[0x0d] & IS_SCHMITT; + eeprom->group1_slew = buf[0x0d] & SLOW_SLEW; + + for(i=0; i<5; i++) + { + eeprom->cbus_function[2*i ] = buf[0x18+i] & 0x0f; + eeprom->cbus_function[2*i+1] = (buf[0x18+i] >> 4) & 0x0f; + } + eeprom->chip = buf[0x1e]; + /*FIXME: Decipher more values*/ + } if (verbose) { - char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO"}; + char *channel_mode[] = {"UART","245","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); @@ -2906,6 +3032,11 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) fprintf(stdout, "Suspend on DBUS7\n"); if (eeprom->suspend_pull_downs) fprintf(stdout, "Pull IO pins low during suspend\n"); + if(eeprom->powersave) + { + if(ftdi->type >= TYPE_232H) + fprintf(stdout,"Enter low power state on ACBUS7\n"); + } if (eeprom->remote_wakeup) fprintf(stdout, "Enable Remote Wake Up\n"); fprintf(stdout, "PNP: %d\n",(eeprom->is_not_pnp)?0:1); @@ -2914,7 +3045,14 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) channel_mode[eeprom->channel_a_type], (eeprom->channel_a_driver)?" VCP":"", (eeprom->high_current_a)?" High Current IO":""); - if ((ftdi->type >= TYPE_2232C) && (ftdi->type != TYPE_R)) + if (ftdi->type >= TYPE_232H) + { + fprintf(stdout,"FT1284 Mode Clock is idle %s, %s first, %sFlow Control\n", + (eeprom->clock_polarity)?"HIGH":"LOW", + (eeprom->data_order)?"LSB":"MSB", + (eeprom->flow_control)?"":"No "); + } + if ((ftdi->type >= TYPE_2232C) && (ftdi->type != TYPE_R) && (ftdi->type != TYPE_232H)) fprintf(stdout,"Channel B has Mode %s%s%s\n", channel_mode[eeprom->channel_b_type], (eeprom->channel_b_driver)?" VCP":"", @@ -2946,6 +3084,30 @@ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose) (eeprom->group3_schmitt)?" Schmitt Input":"", (eeprom->group3_slew)?" Slow Slew":""); } + else if (ftdi->type == TYPE_232H) + { + int i; + char *cbush_mux[] = {"TRISTATE","RXLED","TXLED", "TXRXLED","PWREN", + "SLEEP","DRIVE_0","DRIVE_1","IOMODE","TXDEN", + "CLK30","CLK15","CLK7_5" + }; + fprintf(stdout,"ACBUS has %d mA drive%s%s\n", + (eeprom->group0_drive+1) *4, + (eeprom->group0_schmitt)?" Schmitt Input":"", + (eeprom->group0_slew)?" Slow Slew":""); + fprintf(stdout,"ADBUS 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<10; i++) + { + if (eeprom->cbus_function[i]<= CBUSH_CLK7_5 ) + fprintf(stdout,"C%d Function: %s\n", i, + cbush_mux[eeprom->cbus_function[i]]); + } + + } + if (ftdi->type == TYPE_R) { char *cbus_mux[] = {"TXDEN","PWREN","RXLED", "TXLED","TX+RXLED", @@ -3058,6 +3220,21 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CBUS_FUNCTION_4: *value = ftdi->eeprom->cbus_function[4]; break; + case CBUS_FUNCTION_5: + *value = ftdi->eeprom->cbus_function[5]; + break; + case CBUS_FUNCTION_6: + *value = ftdi->eeprom->cbus_function[6]; + break; + case CBUS_FUNCTION_7: + *value = ftdi->eeprom->cbus_function[7]; + break; + case CBUS_FUNCTION_8: + *value = ftdi->eeprom->cbus_function[8]; + break; + case CBUS_FUNCTION_9: + *value = ftdi->eeprom->cbus_function[8]; + break; case HIGH_CURRENT: *value = ftdi->eeprom->high_current; break; @@ -3106,7 +3283,19 @@ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case GROUP3_SLEW: *value = ftdi->eeprom->group3_slew; break; - case CHIP_TYPE: + case POWER_SAVE: + *value = ftdi->eeprom->powersave; + break; + case CLOCK_POLARITY: + *value = ftdi->eeprom->clock_polarity; + break; + case DATA_ORDER: + *value = ftdi->eeprom->data_order; + break; + case FLOW_CONTROL: + *value = ftdi->eeprom->flow_control; + break; + case CHIP_TYPE: *value = ftdi->eeprom->chip; break; case CHIP_SIZE: @@ -3194,6 +3383,21 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CBUS_FUNCTION_4: ftdi->eeprom->cbus_function[4] = value; break; + case CBUS_FUNCTION_5: + ftdi->eeprom->cbus_function[5] = value; + break; + case CBUS_FUNCTION_6: + ftdi->eeprom->cbus_function[6] = value; + break; + case CBUS_FUNCTION_7: + ftdi->eeprom->cbus_function[7] = value; + break; + case CBUS_FUNCTION_8: + ftdi->eeprom->cbus_function[8] = value; + break; + case CBUS_FUNCTION_9: + ftdi->eeprom->cbus_function[9] = value; + break; case HIGH_CURRENT: ftdi->eeprom->high_current = value; break; @@ -3245,6 +3449,18 @@ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value valu case CHIP_TYPE: ftdi->eeprom->chip = value; break; + case POWER_SAVE: + ftdi->eeprom->powersave = value; + break; + case CLOCK_POLARITY: + ftdi->eeprom->clock_polarity = value; + break; + case DATA_ORDER: + ftdi->eeprom->data_order = value; + break; + case FLOW_CONTROL: + ftdi->eeprom->flow_control = value; + break; case CHIP_SIZE: ftdi_error_return(-2, "EEPROM Value can't be changed"); default : @@ -3431,6 +3647,9 @@ int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr, case TYPE_4232H: chip_type_location = 0x18; break; + case TYPE_232H: + chip_type_location = 0x1e; + break; default: ftdi_error_return(-4, "Device can't access unprotected area"); }