The branch, master has been updated
via f276fe667f966ba9e39ec67c64443e91aec479f0 (commit)
via dc09eaa8d384f8c31fe3015d104e5b3bdd8db009 (commit)
via d4afae5f9625fa08d801715b0a21faaa52ecf83c (commit)
via 6ab07768470d23ded51bbfd6e5e181b11cd70cd3 (commit)
via 3a55cda4af2de515d7c83738a12ffc95f8865091 (commit)
via e6ac34c8096624d5b982a30c40eb626fbe12429d (commit)
via 643a89ea185ffd80d07f39be887598c2a64e58a5 (commit)
via 89e7cfb530ba14c6a1353b217f6ae0569b81959c (commit)
via 673ca43324bff1ec3b23e071e1977379dc0b5d7e (commit)
via 200bd3ed2e1d2389217be44c0adc728909a2a100 (commit)
via b95e46548cdf96ef21b3de2a1b3d55ceeca12075 (commit)
via d327f924c20f61561facfd9537fc495beb3fc315 (commit)
via 545f9df90958b8cedd9945ddc267ef54a735532d (commit)
via de4871c4b481faf22acdb227cdd384aebe05d421 (commit)
via 8a987aa2e1335d9ef3ebbdf496a7b071317b40a3 (commit)
via c53a7cd0a31c56cc2fab5fb5551358f68dc4c237 (commit)
via 213fb57e9e2ce7e047d753bea68369d524760c0c (commit)
via 5e77e87002972d3e5794a4b375cd78a5ae6dde01 (commit)
via 118c45611363a6148dfcf09882fb6136dafda5d8 (commit)
via 735e81ea04451df5b8aa4a18ec4620d8e1c61fb7 (commit)
via 17431287ffa37d2085dbe7cb30afa17487e456a2 (commit)
via 2c1e2bde004c2dc28770343f0bbe999dd60ac697 (commit)
via d10d3929a1acbfc8e049961a94363c6ec3c9f257 (commit)
via 85e6c679c6f23cfd78b9fe912b11752cf499c5ff (commit)
via ac0af8ec4e70b4c4137f34df8efb61546794720d (commit)
via fa1def99efffbb03b8ab0b1d43a122348a118670 (commit)
via ade814a59b4660c5af865dd86cdd48cfa55e1ae5 (commit)
via e47d7975a1c8648e3a86f980eb01eaf96c86a023 (commit)
via 05c2e40a3c720c63a75d36a33d0d5de0677f8f57 (commit)
via 56ac0383edadfa388c3af9df52f3b4c140560527 (commit)
via 82e0fc5a711fb49896428322d58a5c4c7000ff6b (commit)
via 44ef02bd31e3546576efaf5ed7db4893babe42f8 (commit)
via caec12943241837aa054c691f49c548bc2e87145 (commit)
via ec0dcd3fab853d056067830b261f46494eed96b8 (commit)
via a9dddb4dd1f45377a7d978adfd6b2b7ec25779c6 (commit)
via ededbc1c93768073f8073bed759327590503c06d (commit)
via 4e7fa44d1b80eabc277f04b6739eff9228243623 (commit)
via 814710babd85edb7560418feb87b5ed003d437b2 (commit)
via f24a830c2b6e4a9c00a2779b33f7b468b541b650 (commit)
via 665cda0403fc795be8785c9545f357d039dda62d (commit)
via c2700d6da86375b156e16cafb52085fbf5594136 (commit)
via a45ea32b4ffd3f5aa04aabaac810e89a35916a3f (commit)
via 043eafc0ecaaea0192ca2721652598bcbe1ae9a6 (commit)
via 8bc605f3743d3dd30e2cd45e2cced1c4a730166c (commit)
via 516ebfb1a0b4a53d358d2cbb09f0b4a6ae46a34e (commit)
via fccd6562b4de965f7032f5e55a5668f4629ab313 (commit)
via 6fba850777b3bc923c5de6e44a6303d7ebc0a85e (commit)
via e2bbd9affaabb71470c0fe4f6d1a6c5a72c88609 (commit)
via 37186e3415303371bbdd4f8aaa29dea8c889fedb (commit)
via 4e74064bcb5b67b3b51c077adae689be43df0cec (commit)
via 3c75ad2a59c0ff5b1def6a0b48d8c6276e07b95f (commit)
via 33887896c977b344205a74da6f91a93c0d5e9076 (commit)
via 10186c1fa4b660a1fed39b66f1fa2ad9cfe29b19 (commit)
via e27531f4c4b739744c48872eb5f940883d207ab6 (commit)
via 398d7b972ecf5c933d3487da4bac543ba2859fe9 (commit)
via b4d19dead949a262c14af0a4515e7fbceac69373 (commit)
via d45d6648ad017652e18aefc65c1300c5392b2f8e (commit)
via 6e6a1c3fab17eceb680cae1b01d027030ed1e728 (commit)
via a886436ae0a98e39376383b176f05382009290e7 (commit)
via c6b94478680a22e4659431773f67e361fb6c527c (commit)
via 0091182efcba6f7369b678e429ac936296997aa2 (commit)
via a661e3e44b5df0dd84ddd1a5396a880a0063fe67 (commit)
via bf2f6ef7f73ba0a1bf3f04db4435ce2014231ba3 (commit)
via bb5ec68a9a7e2218b0e5852d62e878201dd4d653 (commit)
via 802a949e535f479b694ee04d49c071900314ce91 (commit)
via f14f84d3ab33c785903e5b4fb615076f9cbcefad (commit)
via 74e8e79d4e311001d0f890cdf0219d84b58bb70a (commit)
via a35aa9bdfbb149efe72c32727a0ebfe3585465f8 (commit)
via f38b0866c6725ff41e23dcef0d0da7ea0ece2031 (commit)
via 4fb2ebbb87a4bdb1ca3e2d7768c87f7a228fe784 (commit)
via 13f00d3cd7a7cef13df7b1ecc0b0f0c678456cca (commit)
via 2db3a766fd94a852d95f46efadf3a0dacccd29f5 (commit)
via 7345e9551c75957b19de981846bc975c487dee09 (commit)
via a49800437bffd7b155971f0a51316644deee8ba5 (commit)
via 38801bf8af278a43149862ab7a07128f8c4d5aab (commit)
via 2c2953e66c7167e76fe64633435a5b232a8efc40 (commit)
via cbf65673d6b8d20707b029eaac1e44b28f667c3d (commit)
via 3802140cfb91928c3a168ea42d62c61d1c69cb32 (commit)
via 93738c7952c0ed4b83a459ae2ab9054dc2f7bfad (commit)
via f75bf1391d34f5dfd8b277030f314758cacf4ed7 (commit)
via 6123f7abcc98374ffcfa00bf5eb3bfe9062ada50 (commit)
via eb498cffdb0283ab81756a99ff31fb92690c2c4c (commit)
via aa099f46f01d68f020796b4e5806b3bde7d6e03f (commit)
via 2cde7c524141286c424de68e46710f9e3dbf838d (commit)
via ca41c8ee8dcc93a431fbc0b6746b5ea246d511f9 (commit)
via 71ba2c2cc274bbe898f4a00b0cd175439ea6609f (commit)
via 87f66e30002a1d48b7f1b835944c0dc4342ff077 (commit)
via 75388926b7825ede2b111e86ab8d003b95d8d554 (commit)
via b1859923f302ce55de34bbd74538c72b5aef47f5 (commit)
via 53c7c901d93038e5357caf52d460a65b3148e4bf (commit)
via b641e5ee64bf900594fede686f34f66c76802760 (commit)
via 2b9a3c8226573d507149b8ca6e5a925229dd691d (commit)
via 99404ad5ac076785991e179d3ce9332857a0ca7f (commit)
via 6cd4f92217aa33f3b8c6c304ceeb893ec913c71c (commit)
via 1cd815ad0747825fc41829d4a668a235a715bafa (commit)
via 7e76a5ef2b1022adab883bf1202c34d3f6b4b2c2 (commit)
via 6855afda867f75e0265d815c411a180a0abc139b (commit)
via e5d95e9cf85c2b19b30c224cfe6c65d29b041e82 (commit)
via f456288064f8a671c6a2125f3fabb6c1ae5cf250 (commit)
via 45619eaa83e12b54afa2b4b4cd67b8293778dcb9 (commit)
via a02587d5f941d4e7fe8397e3615325251162dedd (commit)
via fb9bfdd1a9d3256cf8e729b5f8827d23a5a6b9b5 (commit)
via 02e4a740e847307c069bf0f58b24c72d6f239183 (commit)
via db099ec562c4e0199c6ec2c71020612e3623f036 (commit)
via e107f5092fa731fad1aa900b5c736fcb97c76d47 (commit)
via 2938669c3789b6587f6db2fa2192706d6d830580 (commit)
via 308f1fa790ebee51f6a4d2f5dd4ed3611745489b (commit)
via 3d7ba8719da16c784a3c6e13c5976810073ff8bb (commit)
via 85394e6249329e13fd8530a5aeb72355c5340d62 (commit)
via 49a6bc10a1c75b1595572e67910c53e09752a6f2 (commit)
via 07851949856f2d82e71ce5be0c62f8f51d5cd506 (commit)
via cecb9cb2c8bb9d7c71ae4a5c21c45203148afe0e (commit)
via d60d79c508f57f711a2375b1c154023d58581563 (commit)
via 947d9552b56eb04ad630e88a4c99a3668e8f4873 (commit)
via 42ae7c628196dcda467ece62d2f4e04bc77bc8c4 (commit)
via 8d3fe5c92a771cb501084d17c6ff49904d5c43d9 (commit)
via 84ec032f8e8d467b87419a32435c120276d9a1ca (commit)
via 065edc587bed136ef4a1cca5980f116c69e9ae00 (commit)
via f6ef2983ec626387a30502e0369ef4d79cb1bdce (commit)
via 564b271685e24105db5c69a10bbc682efd90e919 (commit)
via 642f94997c2614312fb371c6a3712b4c6bc5d0c0 (commit)
via efc843050e8d0eaef34cef36db7c4acfec7830ff (commit)
via acc1fa05ce669aa2c5f35b51053d9ca59ffd392b (commit)
via 8080d2ceab3809d25d5bc6799dce499e068308d8 (commit)
via f5b8b5b3b28340d1ae710a8d2af0192ab1d28a02 (commit)
via f2cd9fd5d8cac4ca8c94e4f5e6560b4967c87be5 (commit)
via 1bc78a0512f5909dcbe974a901f6ccd94c2a974b (commit)
via 2d543486ed96287e3d0f8f33d82321dfc2f835d0 (commit)
via 3d6d20c0add502b5c93c1bda8331711262791440 (commit)
via 6e73861dd69c21fd9eb56095f09ff2baaca8694c (commit)
via cc9c9d58811e9efb38d274b5ce3baacfedd0b5d6 (commit)
via c0a96aed965e1010f131aaac4d7025ebf00c35dd (commit)
from ce3940810901906eb00d67fe259d5540a9008630 (commit)
- Log -----------------------------------------------------------------
commit f276fe667f966ba9e39ec67c64443e91aec479f0
Merge: ce3940810901906eb00d67fe259d5540a9008630
dc09eaa8d384f8c31fe3015d104e5b3bdd8db009
Author: Thomas Jarosch <thomas.jarosch@xxxxxxxxxxxxx>
Date: Fri May 20 16:10:11 2011 +0200
Merge branch 'eeprom-new'
Conflicts:
examples/stream_test.c
-----------------------------------------------------------------------
Summary of changes:
.gitignore | 1 +
CMakeLists.txt | 1 +
bindings/ftdi.i | 6 +-
doc/EEPROM-structure | 105 +++
examples/CMakeLists.txt | 2 +
examples/baud_test.c | 18 +-
examples/eeprom.c | 236 ++++++
examples/serial_read.c | 41 +-
ftdi_eeprom/CMakeLists.txt | 41 +
ftdi_eeprom/example.conf | 32 +
ftdi_eeprom/ftdi_eeprom_version.h.in | 8 +
ftdi_eeprom/main.c | 394 +++++++++
ftdipp/ftdi.cpp | 20 +-
ftdipp/ftdi.hpp | 4 +-
libftdi-1.0.kdev4 | 3 +
libftdi.kdevelop | 212 -----
libftdi.lnt | 1 +
src/ftdi.c | 1443 +++++++++++++++++++++++++---------
src/ftdi.h | 270 +++++---
19 files changed, 2112 insertions(+), 726 deletions(-)
create mode 100644 doc/EEPROM-structure
create mode 100644 examples/eeprom.c
create mode 100644 ftdi_eeprom/CMakeLists.txt
create mode 100644 ftdi_eeprom/example.conf
create mode 100644 ftdi_eeprom/ftdi_eeprom_version.h.in
create mode 100644 ftdi_eeprom/main.c
create mode 100644 libftdi-1.0.kdev4
delete mode 100644 libftdi.kdevelop
diff --git a/.gitignore b/.gitignore
index 4bacdb7..5a47eba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
*.pc
.deps/
.libs/
+.kdev4/
build/
# Automake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a661d0f..73517cf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -96,6 +96,7 @@ endif(${UNIX})
add_subdirectory(src)
add_subdirectory(ftdipp)
add_subdirectory(bindings)
+add_subdirectory(ftdi_eeprom)
add_subdirectory(examples)
add_subdirectory(packages)
diff --git a/bindings/ftdi.i b/bindings/ftdi.i
index ce1149c..b1d550a 100644
--- a/bindings/ftdi.i
+++ b/bindings/ftdi.i
@@ -41,12 +41,12 @@ extern "C" {
%clear unsigned short *status;
%apply char *OUTPUT { unsigned char *output };
- int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output);
+ int ftdi_eeprom_build(struct ftdi_context *ftdi);
%clear unsigned char *output;
%apply char *OUTPUT { unsigned char *eeprom };
- int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom);
- int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom);
+ int ftdi_read_eeprom(struct ftdi_context *ftdi);
+ int ftdi_write_eeprom(struct ftdi_context *ftdi);
%clear unsigned char *eeprom;
%apply int *OUTPUT { unsigned int *chipid };
diff --git a/doc/EEPROM-structure b/doc/EEPROM-structure
new file mode 100644
index 0000000..c83337e
--- /dev/null
+++ b/doc/EEPROM-structure
@@ -0,0 +1,105 @@
+Here we try to document what we know about the EEPROM Structure.
+
+Even with a 93xx66 EEPROM, at maximum 256 Bytes are used
+
+All important things happen in the first
+0x14(FT232/245), 0x16(FT2232CD), 0x18(FT232/245R) or 0x1a (FT2232H/4432H) bytes
+
+Type | Use extra EEPROM space
+FT2XXB | No
+
+Byte.BIT| TYPE_AM TYPE_BM TYPE_2232C TYPE_R TYPE_2232H
TYPE_4232H
+00.0 | 0 0 channel_a_type channel_a_type
channel_a_type
+00.1 | 0 0 channel_a_type channel_a_type
channel_a_type
+00.2 | 0 0 channel_a_type high_current channel_a_type
channel_a_type
+00.3 | 0 0 channel_a_driver channel_a_driver channel_a_driver
channel_a_driver
+00.4 | 0 0 high_current_a 0 0 0
+00.5 | 0 0 0 0 0 0
+00.6 | 0 0 0 0 0 0
+00.7 | 0 0 0 0 SUSPEND_DBUS7 0
+
+On TYPE_R 00.3 set mean D2XX, on other devices VCP
+
+01.0 | 0 0 channel_b_type channel_b_type
channel_b_type
+01.1 | 0 0 channel_b_type channel_b_type
channel_b_type
+01.2 | 0 0 channel_b_type 0 channel_b_type
channel_b_type
+01.3 | 0 0 channel_b_driver 0 channel_b_driver
channel_b_driver
+01.4 | 0 0 high_current_b 0 0 0
+01.5 | 0 0 0 0 0 0
+01.6 | 0 0 0 0 0
+01.7 | 0 0 0 0 0 0
+
+Fixme: Missing 4232H validation and channel_c_driver, channel_d_driver,
channel_a|b|c|d_rs484enable
+
+02 | Vendor ID (VID) LSB (all)
+03 | Vendor ID (VID) MSB (all)
+04 | Product ID (PID) LSB (all)
+05 | Product ID (PID) MSB (all)
+06 | Device release number LSB (not tested on TYPE_4232H)
+07 | Device release number MSB (not tested on TYPE_4232H)
+ |
+08.4 | Battery powered
+08.5 | Remote wakeup
+08.6 | Self powered: 1, bus powered: 0
+08.7 | Always 1
+ |
+09 | Max power (mA/2)
+ |
+Byte.BIT| TYPE_AM TYPE_BM TYPE_2232C TYPE_R TYPE_2232H
TYPE_4232H
+0a.0 | 0 IsoIn IsoIn part A 0 0
0
+0a.1 | 0 IsoOut IsoOut part A 0 0
0
+0a.2 | 0 suspend_pull_down suspend_pull_down
suspend_pull_down
+0a.3 | 0 use_serial use_serial
+0a.4 | 0 change_usb_version change_usb_version
+0a.5 | 0 0 IsoIn part B 0 0
0
+0a.6 | 0 0 IsoOut part B 0 0
0
+0a.7 | 0 - reserved
+
+ |
+0b | TYPE_R Bitmask Invert, 0 else
+
+Byte | TYPE_AM TYPE_BM TYPE_2232C TYPE_R TYPE_2232H
TYPE_4232H
+0c | 0 USB-VER-LSB USB-VER-LSB 0 ? ?
+0d | 0 USB-VER-MSB USB-VER-MSB 0 ? ?
+(On several FT2232H different values were observed -> The value is unused
+ if change USB version is not set, so it might contain garbage)
+
+0e | OFFSET Vendor
+0f | Len VENDOR
+
+10 | Offset Product
+11 | Length Product
+
+12 | Offset Serial
+13 | Length Serial
+
+Byte.BIT| TYPE_AM TYPE_BM TYPE_2232C TYPE_R TYPE_2232H
TYPE_4232H
+14.3:0 | UA UA CHIP CBUS[0] AL A
+14.7:0 | UA UA CHIP CBUS[1] AH B
+15.3:0 | UA UA 0 CBUS[2] BL C
+15.7:0 | UA UA 0 CBUS[3] BH D
+16.3:0 | UA UA UA CBUS[4] 0 0
+16.7:0 | UA UA UA 0 0 0
+
+CHIP values:
+0x46: EEPROM is a 93xx46
+0x56: EEPROM is a 93xx56
+0x66: EEPROM is a 93xx66
+
+17 UA UA UA 0 0 0
+18 UA UA UA VENDOR CHIP CHIP
+19 UA UA UA VENDOR 0 0
+
+1a UA (all)
+
+
+Additional fields after the serial string:
+0x00, 0x00 - reserved for "legacy port name prefix"
+0x00, 0x00 - reserved for plug and play options
+(Observed values with PnP == 0:
+0x02 0x03 0x01 0x00)
+
+Note: The additional fields after the serial number string
+collide with the official FTDI formula from AN_121 regarding
+the start of the user area:
+"Start Address = the address following the last byte of SerialNumber string."
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index af7f57a..d8be6f5 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -21,6 +21,7 @@ if (EXAMPLES)
add_executable(serial_read serial_read.c)
add_executable(baud_test baud_test.c)
add_executable(stream_test stream_test.c)
+ add_executable(eeprom eeprom.c)
# Linkage
target_link_libraries(simple ftdi)
@@ -32,6 +33,7 @@ if (EXAMPLES)
target_link_libraries(serial_read ftdi)
target_link_libraries(baud_test ftdi)
target_link_libraries(stream_test ftdi)
+ target_link_libraries(eeprom ftdi)
# libftdi++ examples
if(FTDI_BUILD_CPP)
diff --git a/examples/baud_test.c b/examples/baud_test.c
index b53031b..d8d4886 100644
--- a/examples/baud_test.c
+++ b/examples/baud_test.c
@@ -12,7 +12,7 @@
* s:<vendor>:<product>:<serial> first device with given vendor id,
product id and serial string
* -d <datasize to send in bytes>
* -b <baudrate> (divides by 16 if bitbang as taken from the ftdi datasheets)
- * -m <mode to use> r: serial a: async bitbang s:sync bitbang
+ * -m <mode to use> r: serial a: async bitbang s:sync bitbang
* -c <chunksize>
*
* (C) 2009 by Gerd v. Egidy <gerd.von.egidy@xxxxxxxxxxxxx>
@@ -39,7 +39,7 @@ double get_prec_time()
{
struct timeval tv;
double res;
-
+
gettimeofday(&tv,NULL);
res=tv.tv_sec;
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
char *devicedesc=default_devicedesc;
int txchunksize=256;
enum ftdi_mpsse_mode test_mode=BITMODE_BITBANG;
-
+
while ((t = getopt (argc, argv, "b:d:p:m:c:")) != -1)
{
switch (t)
@@ -74,7 +74,7 @@ int main(int argc, char **argv)
datasize = atoi (optarg);
break;
case 'm':
- switch(*optarg)
+ switch (*optarg)
{
case 'r':
// serial
@@ -162,16 +162,16 @@ int main(int argc, char **argv)
}
if (ftdi_write_data_set_chunksize(&ftdic, txchunksize) < 0 ||
- ftdi_read_data_set_chunksize(&ftdic, txchunksize) < 0)
+ ftdi_read_data_set_chunksize(&ftdic, txchunksize) < 0)
{
fprintf(stderr,"Can't set chunksize:
%s\n",ftdi_get_error_string(&ftdic));
return EXIT_FAILURE;
}
- if(test_mode==BITMODE_SYNCBB)
+ if (test_mode==BITMODE_SYNCBB)
{
// completely clear the receive buffer before beginning
- while(ftdi_read_data(&ftdic, rxbuf, txchunksize)>0);
+ while (ftdi_read_data(&ftdic, rxbuf, txchunksize)>0);
}
start=get_prec_time();
@@ -181,7 +181,7 @@ int main(int argc, char **argv)
ftdic.usb_read_timeout=1;
i=0;
- while(i < datasize)
+ while (i < datasize)
{
int sendsize=txchunksize;
if (i+sendsize > datasize)
@@ -196,7 +196,7 @@ int main(int argc, char **argv)
i+=sendsize;
- if(test_mode==BITMODE_SYNCBB)
+ if (test_mode==BITMODE_SYNCBB)
{
// read the same amount of data as sent
ftdi_read_data(&ftdic, rxbuf, sendsize);
diff --git a/examples/eeprom.c b/examples/eeprom.c
new file mode 100644
index 0000000..e2c8052
--- /dev/null
+++ b/examples/eeprom.c
@@ -0,0 +1,236 @@
+/* LIBFTDI EEPROM access example
+
+ This program is distributed under the GPL, version 2
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <ftdi.h>
+
+int main(int argc, char **argv)
+{
+ struct ftdi_context *ftdi;
+ unsigned char buf[256];
+ int f, i, j;
+ int vid = 0x0403;
+ int pid = 0x6010;
+ char const *desc = 0;
+ char const *serial = 0;
+ int erase = 0;
+ int use_defaults = 0;
+ int large_chip = 0;
+ int do_write = 0;
+ int size;
+ int value;
+
+ if ((ftdi = ftdi_new()) == 0)
+ {
+ fprintf(stderr, "Failed to allocate ftdi structure :%s \n",
+ ftdi_get_error_string(ftdi));
+ return EXIT_FAILURE;
+ }
+
+ while ((i = getopt(argc, argv, "d::ev:p:l:P:S:w")) != -1)
+ {
+ switch (i)
+ {
+ case 'd':
+ use_defaults = 1;
+ if (optarg)
+ large_chip = 0x66;
+ break;
+ case 'e':
+ erase = 1;
+ break;
+ case 'v':
+ vid = strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ pid = strtoul(optarg, NULL, 0);
+ break;
+ case 'P':
+ desc = optarg;
+ break;
+ case 'S':
+ serial = optarg;
+ break;
+ case 'w':
+ do_write = 1;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [options]\n", *argv);
+ fprintf(stderr, "\t-d[num] Work with default valuesfor 128
Byte "
+ "EEPROM or for 256 Byte EEPROM if some [num] is
given\n");
+ fprintf(stderr, "\t-w write\n");
+ fprintf(stderr, "\t-e erase\n");
+ fprintf(stderr, "\t-v verbose decoding\n");
+ fprintf(stderr, "\t-p <number> Search for device with PID ==
number\n");
+ fprintf(stderr, "\t-v <number> Search for device with VID ==
number\n");
+ fprintf(stderr, "\t-P <string? Search for device with given "
+ "product description\n");
+ fprintf(stderr, "\t-S <string? Search for device with given "
+ "serial number\n");
+ exit(-1);
+ }
+ }
+
+ // Select first interface
+ ftdi_set_interface(ftdi, INTERFACE_ANY);
+
+ // Open device
+ f = ftdi_usb_open_desc(ftdi, vid, pid, desc, serial);
+ if (f < 0)
+ {
+ fprintf(stderr, "Device VID 0x%04x PID 0x%04x", vid, pid);
+ if (desc)
+ fprintf(stderr, " Desc %s", desc);
+ if (serial)
+ fprintf(stderr, " Serial %s", serial);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+
+ exit(-1);
+ }
+
+ if (erase)
+ {
+ f = ftdi_erase_eeprom(ftdi); /* needed to determine EEPROM chip type */
+ if (f < 0)
+ {
+ fprintf(stderr, "Erase failed: %s",
+ ftdi_get_error_string(ftdi));
+ return -2;
+ }
+ if (ftdi_get_eeprom_value(ftdi, CHIP_TYPE, & value) <0)
+ {
+ fprintf(stderr, "ftdi_get_eeprom_value: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ }
+ if (value == -1)
+ fprintf(stderr, "No EEPROM\n");
+ else if (value == 0)
+ fprintf(stderr, "Internal EEPROM\n");
+ else
+ fprintf(stderr, "Found 93x%02x\n", value);
+ return 0;
+ }
+
+ if (use_defaults)
+ {
+ ftdi_eeprom_initdefaults(ftdi, "IKDA", "FTDIJTAG", "0001");
+ ftdi_eeprom_initdefaults(ftdi, "IKDA", "FTDIJTAG", "0001");
+ if (ftdi_set_eeprom_value(ftdi, MAX_POWER, 500) <0)
+ {
+ fprintf(stderr, "ftdi_set_eeprom_value: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ }
+ if (large_chip)
+ if (ftdi_set_eeprom_value(ftdi, CHIP_TYPE, 0x66) <0)
+ {
+ fprintf(stderr, "ftdi_set_eeprom_value: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ }
+ f=(ftdi_eeprom_build(ftdi));
+ if (f < 0)
+ {
+ fprintf(stderr, "ftdi_eeprom_build: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ exit(-1);
+ }
+ }
+ else if (do_write)
+ {
+ ftdi_eeprom_initdefaults(ftdi, "IKDA", "FTDIJTAG", "0001");
+ f = ftdi_erase_eeprom(ftdi);
+ if (ftdi_set_eeprom_value(ftdi, MAX_POWER, 500) <0)
+ {
+ fprintf(stderr, "ftdi_set_eeprom_value: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ }
+ f = ftdi_erase_eeprom(ftdi);/* needed to determine EEPROM chip type */
+ if (ftdi_get_eeprom_value(ftdi, CHIP_TYPE, & value) <0)
+ {
+ fprintf(stderr, "ftdi_get_eeprom_value: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ }
+ if (value == -1)
+ fprintf(stderr, "No EEPROM\n");
+ else if (value == 0)
+ fprintf(stderr, "Internal EEPROM\n");
+ else
+ fprintf(stderr, "Found 93x%02x\n", value);
+ f=(ftdi_eeprom_build(ftdi));
+ if (f < 0)
+ {
+ fprintf(stderr, "Erase failed: %s",
+ ftdi_get_error_string(ftdi));
+ return -2;
+ }
+ f = ftdi_write_eeprom(ftdi);
+ {
+ fprintf(stderr, "ftdi_eeprom_decode: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ exit(-1);
+ }
+ f = ftdi_read_eeprom(ftdi);
+ if (f < 0)
+ {
+ fprintf(stderr, "ftdi_read_eeprom: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ exit(-1);
+ }
+ }
+ else
+ {
+ f = ftdi_read_eeprom(ftdi);
+ if (f < 0)
+ {
+ fprintf(stderr, "ftdi_read_eeprom: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ exit(-1);
+ }
+ }
+
+
+ ftdi_get_eeprom_value(ftdi, CHIP_SIZE, & value);
+ fprintf(stderr, "Chip type %d ftdi_eeprom_size: %d\n", ftdi->type, value);
+ if (ftdi->type == TYPE_R)
+ size = 0xa0;
+ else
+ size = value;
+ ftdi_get_eeprom_buf(ftdi, buf, size);
+ for (i=0; i < size; i += 16)
+ {
+ fprintf(stdout,"0x%03x:", i);
+
+ for (j = 0; j< 8; j++)
+ fprintf(stdout," %02x", buf[i+j]);
+ fprintf(stdout," ");
+ for (; j< 16; j++)
+ fprintf(stdout," %02x", buf[i+j]);
+ fprintf(stdout," ");
+ for (j = 0; j< 8; j++)
+ fprintf(stdout,"%c", isprint(buf[i+j])?buf[i+j]:'.');
+ fprintf(stdout," ");
+ for (; j< 16; j++)
+ fprintf(stdout,"%c", isprint(buf[i+j])?buf[i+j]:'.');
+ fprintf(stdout,"\n");
+ }
+
+ f = ftdi_eeprom_decode(ftdi, 1);
+ if (f < 0)
+ {
+ fprintf(stderr, "ftdi_eeprom_decode: %d (%s)\n",
+ f, ftdi_get_error_string(ftdi));
+ exit(-1);
+ }
+
+ ftdi_usb_close(ftdi);
+ ftdi_free(ftdi);
+ return 0;
+}
diff --git a/examples/serial_read.c b/examples/serial_read.c
index 5d05d66..aec18d0 100644
--- a/examples/serial_read.c
+++ b/examples/serial_read.c
@@ -25,21 +25,21 @@ int main(int argc, char **argv)
{
switch (i)
{
- case 'i': // 0=ANY, 1=A, 2=B, 3=C, 4=D
- interface = strtoul(optarg, NULL, 0);
- break;
- case 'v':
- vid = strtoul(optarg, NULL, 0);
- break;
- case 'p':
- pid = strtoul(optarg, NULL, 0);
- break;
- case 'b':
- baudrate = strtoul(optarg, NULL, 0);
- break;
- default:
- fprintf(stderr, "usage: %s [-i interface] [-v vid] [-p pid] [-b
baudrate]\n", *argv);
- exit(-1);
+ case 'i': // 0=ANY, 1=A, 2=B, 3=C, 4=D
+ interface = strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ vid = strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ pid = strtoul(optarg, NULL, 0);
+ break;
+ case 'b':
+ baudrate = strtoul(optarg, NULL, 0);
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-i interface] [-v vid] [-p pid]
[-b baudrate]\n", *argv);
+ exit(-1);
}
}
@@ -70,11 +70,12 @@ int main(int argc, char **argv)
}
// Read data forever
- while ((f = ftdi_read_data(&ftdic, buf, sizeof(buf))) >= 0) {
- fprintf(stderr, "read %d bytes\n", f);
- fwrite(buf, f, 1, stdout);
- fflush(stderr);
- fflush(stdout);
+ while ((f = ftdi_read_data(&ftdic, buf, sizeof(buf))) >= 0)
+ {
+ fprintf(stderr, "read %d bytes\n", f);
+ fwrite(buf, f, 1, stdout);
+ fflush(stderr);
+ fflush(stdout);
}
ftdi_usb_close(&ftdic);
diff --git a/ftdi_eeprom/CMakeLists.txt b/ftdi_eeprom/CMakeLists.txt
new file mode 100644
index 0000000..3f1d7dc
--- /dev/null
+++ b/ftdi_eeprom/CMakeLists.txt
@@ -0,0 +1,41 @@
+set(FTDI_BUILD_EEPROM False PARENT_SCOPE)
+
+option(FTDI_EEPROM "Build ftdi_eeprom" ON)
+
+if (FTDI_EEPROM)
+ include(FindPkgConfig)
+ pkg_check_modules(Confuse libconfuse)
+ INCLUDE_DIRECTORIES(${Confuse_INCLUDE_DIRS})
+ LINK_DIRECTORIES(${Confuse_LIBRARY_DIRS})
+ SET(libs ${libs} ${Confuse_LIBRARIES})
+
+ if(Confuse_FOUND)
+ set(FTDI_BUILD_EEPROM True PARENT_SCOPE)
+ message(STATUS "Building ftdi_eeprom")
+
+ # Version defines
+ set(EEPROM_MAJOR_VERSION 0)
+ set(EEPROM_MINOR_VERSION 17)
+ set(EEPROM_VERSION_STRING
${EEPROM_MAJOR_VERSION}.${EEPROM_MINOR_VERSION})
+
+ include_directories(${CMAKE_SOURCE_DIR}/src)
+ include_directories(${CMAKE_BINARY_DIR}/ftdi_eeprom)
+
+ configure_file(
+ "ftdi_eeprom_version.h.in"
+ "${CMAKE_BINARY_DIR}/ftdi_eeprom/ftdi_eeprom_version.h"
+ )
+
+ add_executable(ftdi_eeprom main.c)
+ target_link_libraries(ftdi_eeprom ftdi)
+ target_link_libraries(ftdi_eeprom ${Confuse_LIBRARIES})
+
+ else(Confuse_FOUND)
+ message(STATUS "libConfuse not found, won't build ftdi_eeprom")
+ endif(Confuse_FOUND)
+
+else(FTDI_EEPROM)
+
+ message(STATUS "ftdi_eeprom build is disabled")
+
+endif(FTDI_EEPROM)
diff --git a/ftdi_eeprom/example.conf b/ftdi_eeprom/example.conf
new file mode 100644
index 0000000..cfc9fc3
--- /dev/null
+++ b/ftdi_eeprom/example.conf
@@ -0,0 +1,32 @@
+vendor_id=0x0403 # Vendor ID
+product_id=0x6001 # Product ID
+
+max_power=0 # Max. power consumption: value * 2 mA. Use 0 if
self_powered = true.
+
+###########
+# Strings #
+###########
+manufacturer="ACME Inc" # Manufacturer
+product="USB Serial Converter" # Product
+serial="08-15" # Serial
+
+###########
+# Options #
+###########
+self_powered=true # Turn this off for bus powered
+remote_wakeup=false # Turn this on for remote wakeup feature
+use_serial=true # Use the serial number string
+
+# Normally out don't have to change one of these flags
+BM_type_chip=true # Newer chips are all BM type
+in_is_isochronous=false # In Endpoint is Isochronous
+out_is_isochronous=false # Out Endpoint is Isochronous
+suspend_pull_downs=false # Enable suspend pull downs for lower power
+change_usb_version=false # Change USB Version
+usb_version=0x0200 # Only used when change_usb_version is enabled
+
+########
+# Misc #
+########
+
+filename="eeprom.new" # Filename, leave empty to skip file writing
diff --git a/ftdi_eeprom/ftdi_eeprom_version.h.in
b/ftdi_eeprom/ftdi_eeprom_version.h.in
new file mode 100644
index 0000000..db7717d
--- /dev/null
+++ b/ftdi_eeprom/ftdi_eeprom_version.h.in
@@ -0,0 +1,8 @@
+#ifndef _FTDI_EEPROM_VERSION_H
+#define _FTDI_EEPROM_VERSION_H
+
+#define EEPROM_MAJOR_VERSION @EEPROM_MAJOR_VERSION@
+#define EEPROM_MINOR_VERSION @EEPROM_MINOR_VERSION@
+#define EEPROM_VERSION_STRING "@EEPROM_VERSION_STRING@"
+
+#endif
diff --git a/ftdi_eeprom/main.c b/ftdi_eeprom/main.c
new file mode 100644
index 0000000..3977f86
--- /dev/null
+++ b/ftdi_eeprom/main.c
@@ -0,0 +1,394 @@
+/***************************************************************************
+ main.c - description
+ -------------------
+ begin : Mon Apr 7 12:05:22 CEST 2003
+ copyright : (C) 2003-2011 by Intra2net AG and the libftdi
developers
+ email : opensource@xxxxxxxxxxxxx
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License version 2 as *
+ * published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+/*
+ TODO:
+ - Remove 128 bytes limit
+ - Merge Uwe's eeprom tool. Current features:
+ - Init eeprom defaults based upon eeprom type
+ - Read -> Already there
+ - Write -> Already there
+ - Erase -> Already there
+ - Decode on stdout
+ - Ability to find device by PID/VID, product name or serial
+
+ TODO nice-to-have:
+ - Out-of-the-box compatibility with FTDI's eeprom tool configuration files
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <confuse.h>
+#include <ftdi.h>
+#include <ftdi_eeprom_version.h>
+
+static int str_to_cbus(char *str, int max_allowed)
+{
+ #define MAX_OPTION 14
+ const char* options[MAX_OPTION] = {
+ "TXDEN", "PWREN", "RXLED", "TXLED", "TXRXLED", "SLEEP",
+ "CLK48", "CLK24", "CLK12", "CLK6",
+ "IO_MODE", "BITBANG_WR", "BITBANG_RD", "SPECIAL"};
+ int i;
+ max_allowed += 1;
+ if (max_allowed > MAX_OPTION) max_allowed = MAX_OPTION;
+ for (i=0; i<max_allowed; i++) {
+ if (!(strcmp(options[i], str))) {
+ return i;
+ }
+ }
+ printf("WARNING: Invalid cbus option '%s'\n", str);
+ return 0;
+}
+
+/**
+ * @brief Set eeprom value
+ *
+ * \param ftdi pointer to ftdi_context
+ * \param value_name Enum of the value to set
+ * \param value Value to set
+ *
+ * Function will abort the program on error
+ **/
+static void eeprom_set_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value
value_name, int value)
+{
+ if (ftdi_set_eeprom_value(ftdi, value_name, value) < 0)
+ {
+ printf("Unable to set eeprom value %d: %s. Aborting\n", value_name,
ftdi_get_error_string(ftdi));
+ exit (-1);
+ }
+}
+
+/**
+ * @brief Get eeprom value
+ *
+ * \param ftdi pointer to ftdi_context
+ * \param value_name Enum of the value to get
+ * \param value Value to get
+ *
+ * Function will abort the program on error
+ **/
+static void eeprom_get_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value
value_name, int *value)
+{
+ if (ftdi_get_eeprom_value(ftdi, value_name, value) < 0)
+ {
+ printf("Unable to get eeprom value %d: %s. Aborting\n", value_name,
ftdi_get_error_string(ftdi));
+ exit (-1);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ /*
+ configuration options
+ */
+ cfg_opt_t opts[] =
+ {
+ CFG_INT("vendor_id", 0, 0),
+ CFG_INT("product_id", 0, 0),
+ CFG_BOOL("self_powered", cfg_true, 0),
+ CFG_BOOL("remote_wakeup", cfg_true, 0),
+ CFG_STR_LIST("chip_type", "{BM,R,other}", 0),
+ CFG_BOOL("in_is_isochronous", cfg_false, 0),
+ CFG_BOOL("out_is_isochronous", cfg_false, 0),
+ CFG_BOOL("suspend_pull_downs", cfg_false, 0),
+ CFG_BOOL("use_serial", cfg_false, 0),
+ CFG_BOOL("change_usb_version", cfg_false, 0),
+ CFG_INT("usb_version", 0, 0),
+ CFG_INT("default_pid", 0x6001, 0),
+ CFG_INT("max_power", 0, 0),
+ CFG_STR("manufacturer", "Acme Inc.", 0),
+ CFG_STR("product", "USB Serial Converter", 0),
+ CFG_STR("serial", "08-15", 0),
+ CFG_STR("filename", "", 0),
+ CFG_BOOL("flash_raw", cfg_false, 0),
+ CFG_BOOL("high_current", cfg_false, 0),
+ CFG_STR_LIST("cbus0",
"{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}",
0),
+ CFG_STR_LIST("cbus1",
"{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}",
0),
+ CFG_STR_LIST("cbus2",
"{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}",
0),
+ CFG_STR_LIST("cbus3",
"{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}",
0),
+ CFG_STR_LIST("cbus4",
"{TXDEN,PWRON,RXLED,TXLED,TX_RX_LED,SLEEP,CLK48,CLK24,CLK12,CLK6}", 0),
+ CFG_BOOL("invert_txd", cfg_false, 0),
+ CFG_BOOL("invert_rxd", cfg_false, 0),
+ CFG_BOOL("invert_rts", cfg_false, 0),
+ CFG_BOOL("invert_cts", cfg_false, 0),
+ CFG_BOOL("invert_dtr", cfg_false, 0),
+ CFG_BOOL("invert_dsr", cfg_false, 0),
+ CFG_BOOL("invert_dcd", cfg_false, 0),
+ CFG_BOOL("invert_ri", cfg_false, 0),
+ CFG_END()
+ };
+ cfg_t *cfg;
+
+ /*
+ normal variables
+ */
+ int _read = 0, _erase = 0, _flash = 0;
+
+ const int my_eeprom_size = 128; /* TODO: Kill this. Check
with Uwe how we can determine the eeprom size properly
+ because it's
initialized with -1. Maybe assume 128 bytes per default? */
+ unsigned char eeprom_buf[my_eeprom_size];
+ char *filename;
+ int size_check;
+ int i, argc_filename;
+ FILE *fp;
+
+ struct ftdi_context *ftdi = NULL;
+
+ printf("\nFTDI eeprom generator v%s\n", EEPROM_VERSION_STRING);
+ printf ("(c) Intra2net AG and the libftdi developers
<opensource@xxxxxxxxxxxxx>\n");
+
+ if (argc != 2 && argc != 3)
+ {
+ printf("Syntax: %s [commands] config-file\n", argv[0]);
+ printf("Valid commands:\n");
+ printf("--read-eeprom Read eeprom and write to -filename- from
config-file\n");
+ printf("--erase-eeprom Erase eeprom\n");
+ printf("--flash-eeprom Flash eeprom\n");
+ exit (-1);
+ }
+
+ if (argc == 3)
+ {
+ if (strcmp(argv[1], "--read-eeprom") == 0)
+ _read = 1;
+ if (strcmp(argv[1], "--erase-eeprom") == 0)
+ _erase = 1;
+ if (strcmp(argv[1], "--flash-eeprom") == 0)
+ _flash = 1;
+
+ argc_filename = 2;
+ }
+ else
+ {
+ argc_filename = 1;
+ }
+
+ if ((fp = fopen(argv[argc_filename], "r")) == NULL)
+ {
+ printf ("Can't open configuration file\n");
+ exit (-1);
+ }
+ fclose (fp);
+
+ cfg = cfg_init(opts, 0);
+ cfg_parse(cfg, argv[argc_filename]);
+ filename = cfg_getstr(cfg, "filename");
+
+ if (cfg_getbool(cfg, "self_powered") && cfg_getint(cfg, "max_power") > 0)
+ printf("Hint: Self powered devices should have a max_power setting of
0.\n");
+
+ if ((ftdi = ftdi_new()) == 0)
+ {
+ fprintf(stderr, "Failed to allocate ftdi structure :%s \n",
+ ftdi_get_error_string(ftdi));
+ return EXIT_FAILURE;
+ }
+
+ ftdi_eeprom_initdefaults (ftdi, "Acme Inc.", "FTDI Chip", NULL);
+
+ eeprom_set_value(ftdi, VENDOR_ID, cfg_getint(cfg, "vendor_id"));
+ eeprom_set_value(ftdi, PRODUCT_ID, cfg_getint(cfg, "product_id"));
+
+ // TODO: Support all chip types
+ char *type = cfg_getstr(cfg, "chip_type");
+ if (!strcmp(type, "BM")) {
+ ftdi->type = TYPE_BM;
+ } else if (!strcmp(type, "R")) {
+ ftdi->type = TYPE_R;
+ } else {
+ ftdi->type = TYPE_AM;
+ }
+
+ eeprom_set_value(ftdi, SELF_POWERED, cfg_getbool(cfg, "self_powered"));
+ eeprom_set_value(ftdi, REMOTE_WAKEUP, cfg_getbool(cfg, "remote_wakeup"));
+ eeprom_set_value(ftdi, MAX_POWER, cfg_getint(cfg, "max_power"));
+
+ eeprom_set_value(ftdi, IN_IS_ISOCHRONOUS, cfg_getbool(cfg,
"in_is_isochronous"));
+ eeprom_set_value(ftdi, OUT_IS_ISOCHRONOUS, cfg_getbool(cfg,
"out_is_isochronous"));
+ eeprom_set_value(ftdi, SUSPEND_PULL_DOWNS, cfg_getbool(cfg,
"suspend_pull_downs"));
+
+ eeprom_set_value(ftdi, USE_SERIAL, cfg_getbool(cfg, "use_serial"));
+ eeprom_set_value(ftdi, USE_USB_VERSION, cfg_getbool(cfg,
"change_usb_version"));
+ eeprom_set_value(ftdi, USB_VERSION, cfg_getint(cfg, "usb_version"));
+
+
+ ftdi->eeprom->manufacturer = cfg_getstr(cfg, "manufacturer");
+ ftdi->eeprom->product = cfg_getstr(cfg, "product");
+ ftdi->eeprom->serial = cfg_getstr(cfg, "serial");
+ eeprom_set_value(ftdi, HIGH_CURRENT, cfg_getbool(cfg, "high_current"));
+ eeprom_set_value(ftdi, CBUS_FUNCTION_0, str_to_cbus(cfg_getstr(cfg,
"cbus0"), 13));
+ eeprom_set_value(ftdi, CBUS_FUNCTION_1, str_to_cbus(cfg_getstr(cfg,
"cbus1"), 13));
+ eeprom_set_value(ftdi, CBUS_FUNCTION_2, str_to_cbus(cfg_getstr(cfg,
"cbus2"), 13));
+ eeprom_set_value(ftdi, CBUS_FUNCTION_3, str_to_cbus(cfg_getstr(cfg,
"cbus3"), 13));
+ eeprom_set_value(ftdi, CBUS_FUNCTION_4, str_to_cbus(cfg_getstr(cfg,
"cbus4"), 9));
+ int invert = 0;
+ if (cfg_getbool(cfg, "invert_rxd")) invert |= INVERT_RXD;
+ if (cfg_getbool(cfg, "invert_txd")) invert |= INVERT_TXD;
+ if (cfg_getbool(cfg, "invert_rts")) invert |= INVERT_RTS;
+ if (cfg_getbool(cfg, "invert_cts")) invert |= INVERT_CTS;
+ if (cfg_getbool(cfg, "invert_dtr")) invert |= INVERT_DTR;
+ if (cfg_getbool(cfg, "invert_dsr")) invert |= INVERT_DSR;
+ if (cfg_getbool(cfg, "invert_dcd")) invert |= INVERT_DCD;
+ if (cfg_getbool(cfg, "invert_ri")) invert |= INVERT_RI;
+ eeprom_set_value(ftdi, INVERT, invert);
+
+ if (_read > 0 || _erase > 0 || _flash > 0)
+ {
+ int vendor_id = 0, product_id = 0;
+ eeprom_get_value(ftdi, VENDOR_ID, &vendor_id);
+ eeprom_get_value(ftdi, PRODUCT_ID, &product_id);
+
+ i = ftdi_usb_open(ftdi, vendor_id, product_id);
+
+ if (i == 0)
+ {
+ // TODO: Do we know the eeprom size already?
+ printf("EEPROM size: %d\n", ftdi->eeprom->size);
+ }
+ else
+ {
+ int default_pid = cfg_getint(cfg, "default_pid");
+ printf("Unable to find FTDI devices under given vendor/product id:
0x%X/0x%X\n", vendor_id, product_id);
+ printf("Error code: %d (%s)\n", i, ftdi_get_error_string(ftdi));
+ printf("Retrying with default FTDI pid=%#04x.\n", default_pid);
+
+ i = ftdi_usb_open(ftdi, 0x0403, default_pid);
+ if (i != 0)
+ {
+ printf("Error: %s\n", ftdi->error_str);
+ exit (-1);
+ }
+ }
+ }
+
+ if (_read > 0)
+ {
+ printf("FTDI read eeprom: %d\n", ftdi_read_eeprom(ftdi));
+
+ ftdi_eeprom_decode(ftdi, 0);
+ /* Debug output */
+ /*
+ const char* chip_types[] = {"other", "BM", "R"};
+ printf("vendor_id = \"%04x\"\n", eeprom->vendor_id);
+ printf("product_id = \"%04x\"\n", eeprom->product_id);
+ printf("chip_type = \"%s\"\n",
+ (eeprom->chip_type > 0x06) || (eeprom->chip_type & 0x01) ? "unknown":
+ chip_types[eeprom->chip_type>>1]);
+ printf("self_powered = \"%s\"\n", eeprom->self_powered?"true":"false");
+ printf("remote_wakeup = \"%s\"\n",
eeprom->remote_wakeup?"true":"false");
+ printf("max_power = \"%d\"\n", eeprom->max_power);
+ printf("in_is_isochronous = \"%s\"\n",
eeprom->in_is_isochronous?"true":"false");
+ printf("out_is_isochronous = \"%s\"\n",
eeprom->out_is_isochronous?"true":"false");
+ printf("suspend_pull_downs = \"%s\"\n",
eeprom->suspend_pull_downs?"true":"false");
+ printf("use_serial = \"%s\"\n", eeprom->use_serial?"true":"false");
+ printf("change_usb_version = \"%s\"\n",
eeprom->change_usb_version?"true":"false");
+ printf("usb_version = \"%d\"\n", eeprom->usb_version);
+ printf("manufacturer = \"%s\"\n", eeprom->manufacturer);
+ printf("product = \"%s\"\n", eeprom->product);
+ printf("serial = \"%s\"\n", eeprom->serial);
+ */
+
+ if (filename != NULL && strlen(filename) > 0)
+ {
+ ftdi_get_eeprom_buf(ftdi, eeprom_buf, my_eeprom_size);
+
+ FILE *fp = fopen (filename, "wb");
+ fwrite (eeprom_buf, 1, my_eeprom_size, fp);
+ fclose (fp);
+ }
+ else
+ {
+ printf("Warning: Not writing eeprom, you must supply a valid
filename\n");
+ }
+
+ goto cleanup;
+ }
+
+ if (_erase > 0)
+ {
+ printf("FTDI erase eeprom: %d\n", ftdi_erase_eeprom(ftdi));
+ }
+
+ size_check = ftdi_eeprom_build(ftdi);
+
+ if (size_check == -1)
+ {
+ printf ("Sorry, the eeprom can only contain 128 bytes (100 bytes for
your strings).\n");
+ printf ("You need to short your string by: %d bytes\n", size_check);
+ goto cleanup;
+ } else if (size_check < 0) {
+ printf ("ftdi_eeprom_build(): error: %d\n", size_check);
+ }
+ else
+ {
+ printf ("Used eeprom space: %d bytes\n", my_eeprom_size-size_check);
+ }
+
+ if (_flash > 0)
+ {
+ if (cfg_getbool(cfg, "flash_raw"))
+ {
+ if (filename != NULL && strlen(filename) > 0)
+ {
+ FILE *fp = fopen(filename, "rb");
+ fread(eeprom_buf, 1, my_eeprom_size, fp);
+ fclose(fp);
+
+ /* TODO: Dirty hack. Create an API for this. How about
ftdi_set_eeprom_buf()? */
+ memcpy(ftdi->eeprom->buf, eeprom_buf, my_eeprom_size);
+ }
+ }
+ printf ("FTDI write eeprom: %d\n", ftdi_write_eeprom(ftdi));
+ }
+
+ // Write to file?
+ if (filename != NULL && strlen(filename) > 0 && !cfg_getbool(cfg,
"flash_raw"))
+ {
+ fp = fopen(filename, "w");
+ if (fp == NULL)
+ {
+ printf ("Can't write eeprom file.\n");
+ exit (-1);
+ }
+ else
+ printf ("Writing to file: %s\n", filename);
+
+ ftdi_get_eeprom_buf(ftdi, eeprom_buf, my_eeprom_size);
+
+ fwrite(eeprom_buf, my_eeprom_size, 1, fp);
+ fclose(fp);
+ }
+
+cleanup:
+ if (_read > 0 || _erase > 0 || _flash > 0)
+ {
+ printf("FTDI close: %d\n", ftdi_usb_close(ftdi));
+ }
+
+ ftdi_deinit (ftdi);
+
+ cfg_free(cfg);
+
+ printf("\n");
+ return 0;
+}
diff --git a/ftdipp/ftdi.cpp b/ftdipp/ftdi.cpp
index c81eb5f..2754033 100644
--- a/ftdipp/ftdi.cpp
+++ b/ftdipp/ftdi.cpp
@@ -393,19 +393,9 @@ Eeprom::~Eeprom()
{
}
-void Eeprom::init_defaults()
+int Eeprom::init_defaults(char* manufacturer, char *product, char * serial)
{
- return ftdi_eeprom_initdefaults(&d->eeprom);
-}
-
-void Eeprom::set_size(int size)
-{
- return ftdi_eeprom_setsize(d->context, &d->eeprom, size);
-}
-
-int Eeprom::size(unsigned char *eeprom, int maxsize)
-{
- return ftdi_read_eeprom_getsize(d->context, eeprom, maxsize);
+ return ftdi_eeprom_initdefaults(d->context, manufacturer, product, serial);
}
int Eeprom::chip_id(unsigned int *chipid)
@@ -415,17 +405,17 @@ int Eeprom::chip_id(unsigned int *chipid)
int Eeprom::build(unsigned char *output)
{
- return ftdi_eeprom_build(&d->eeprom, output);
+ return ftdi_eeprom_build(d->context);
}
int Eeprom::read(unsigned char *eeprom)
{
- return ftdi_read_eeprom(d->context, eeprom);
+ return ftdi_read_eeprom(d->context);
}
int Eeprom::write(unsigned char *eeprom)
{
- return ftdi_write_eeprom(d->context, eeprom);
+ return ftdi_write_eeprom(d->context);
}
int Eeprom::read_location(int eeprom_addr, unsigned short *eeprom_val)
diff --git a/ftdipp/ftdi.hpp b/ftdipp/ftdi.hpp
index ba20346..3a5d993 100644
--- a/ftdipp/ftdi.hpp
+++ b/ftdipp/ftdi.hpp
@@ -152,9 +152,7 @@ public:
Eeprom(Context* parent);
~Eeprom();
- void init_defaults();
- void set_size(int size);
- int size(unsigned char *eeprom, int maxsize);
+ int init_defaults(char *manufacturer, char* product, char * serial);
int chip_id(unsigned int *chipid);
int build(unsigned char *output);
diff --git a/libftdi-1.0.kdev4 b/libftdi-1.0.kdev4
new file mode 100644
index 0000000..6da24c2
--- /dev/null
+++ b/libftdi-1.0.kdev4
@@ -0,0 +1,3 @@
+[Project]
+Manager=KDevCMakeManager
+Name=libftdi-1.0
diff --git a/libftdi.kdevelop b/libftdi.kdevelop
deleted file mode 100644
index 421d88d..0000000
--- a/libftdi.kdevelop
+++ /dev/null
@@ -1,212 +0,0 @@
-<?xml version = '1.0'?>
-<kdevelop>
- <general>
- <author>Thomas Jarosch</author>
- <email>opensource@xxxxxxxxxxxxx</email>
- <version>0.6</version>
- <projectmanagement>KDevAutoProject</projectmanagement>
- <primarylanguage>C</primarylanguage>
- <keywords>
- <keyword>C</keyword>
- <keyword>Code</keyword>
- </keywords>
- <projectdirectory>.</projectdirectory>
- <absoluteprojectpath>false</absoluteprojectpath>
- <description/>
- <ignoreparts/>
- <secondaryLanguages/>
- <projectname>libftdi</projectname>
- </general>
- <kdevautoproject>
- <general>
- <activetarget>src/libftdi</activetarget>
- <useconfiguration>default</useconfiguration>
- </general>
- <run>
- <mainprogram>src/libftdi</mainprogram>
- <terminal>true</terminal>
- <directoryradio>executable</directoryradio>
- <customdirectory>/</customdirectory>
- <programargs/>
- <autocompile>true</autocompile>
- <envvars/>
- </run>
- <configurations>
- <optimized>
- <builddir>optimized</builddir>
- <ccompiler>kdevgccoptions</ccompiler>
- <cxxcompiler>kdevgppoptions</cxxcompiler>
- <f77compiler>kdevg77options</f77compiler>
- <cflags>-O2 -g0</cflags>
- </optimized>
- <debug>
- <configargs>--enable-debug=full</configargs>
- <builddir>debug</builddir>
- <ccompiler>kdevgccoptions</ccompiler>
- <cxxcompiler>kdevgppoptions</cxxcompiler>
- <f77compiler>kdevg77options</f77compiler>
- <cflags>-O0 -g3</cflags>
- </debug>
- <default>
- <envvars/>
- </default>
- </configurations>
- <make>
- <envvars>
- <envvar value="1" name="WANT_AUTOCONF_2_5" />
- <envvar value="1" name="WANT_AUTOMAKE_1_6" />
- </envvars>
- <abortonerror>false</abortonerror>
- <numberofjobs>1</numberofjobs>
- <dontact>false</dontact>
- <makebin/>
- <prio>0</prio>
- </make>
- </kdevautoproject>
- <kdevdoctreeview>
- <ignoretocs>
- <toc>ada</toc>
- <toc>ada_bugs_gcc</toc>
- <toc>bash</toc>
- <toc>bash_bugs</toc>
- <toc>clanlib</toc>
- <toc>w3c-dom-level2-html</toc>
- <toc>fortran_bugs_gcc</toc>
- <toc>gnome1</toc>
- <toc>gnustep</toc>
- <toc>gtk</toc>
- <toc>gtk_bugs</toc>
- <toc>haskell</toc>
- <toc>haskell_bugs_ghc</toc>
- <toc>java_bugs_gcc</toc>
- <toc>java_bugs_sun</toc>
- <toc>kde2book</toc>
- <toc>libstdc++</toc>
- <toc>opengl</toc>
- <toc>pascal_bugs_fp</toc>
- <toc>php</toc>
- <toc>php_bugs</toc>
- <toc>perl</toc>
- <toc>perl_bugs</toc>
- <toc>python</toc>
- <toc>python_bugs</toc>
- <toc>qt-kdev3</toc>
- <toc>ruby</toc>
- <toc>ruby_bugs</toc>
- <toc>sdl</toc>
- <toc>stl</toc>
- <toc>w3c-svg</toc>
- <toc>sw</toc>
- <toc>w3c-uaag10</toc>
- <toc>wxwindows_bugs</toc>
- </ignoretocs>
- <ignoreqt_xml>
- <toc>Guide to the Qt Translation Tools</toc>
- <toc>Qt Assistant Manual</toc>
- <toc>Qt Designer Manual</toc>
- <toc>Qt Reference Documentation</toc>
- <toc>qmake User Guide</toc>
- </ignoreqt_xml>
- <ignoredoxygen>
- <toc>KDE Libraries (Doxygen)</toc>
- </ignoredoxygen>
- </kdevdoctreeview>
- <kdevfilecreate>
- <filetypes/>
- <useglobaltypes>
- <type ext="c" />
- <type ext="h" />
- </useglobaltypes>
- </kdevfilecreate>
- <kdevfileview>
- <groups>
- <group pattern="*.h" name="Header files" />
- <group pattern="*.c" name="Source files" />
- <hidenonprojectfiles>false</hidenonprojectfiles>
- <hidenonlocation>false</hidenonlocation>
- </groups>
- <tree>
- <hidepatterns>*.o,*.lo,CVS</hidepatterns>
- <hidenonprojectfiles>false</hidenonprojectfiles>
- <showvcsfields>false</showvcsfields>
- </tree>
- </kdevfileview>
- <kdevcppsupport>
- <references/>
- <codecompletion>
- <includeGlobalFunctions>true</includeGlobalFunctions>
- <includeTypes>true</includeTypes>
- <includeEnums>true</includeEnums>
- <includeTypedefs>false</includeTypedefs>
- <automaticCodeCompletion>true</automaticCodeCompletion>
- <automaticArgumentsHint>true</automaticArgumentsHint>
- <automaticHeaderCompletion>true</automaticHeaderCompletion>
- <codeCompletionDelay>250</codeCompletionDelay>
- <argumentsHintDelay>400</argumentsHintDelay>
- <headerCompletionDelay>250</headerCompletionDelay>
- <showOnlyAccessibleItems>false</showOnlyAccessibleItems>
- <completionBoxItemOrder>0</completionBoxItemOrder>
- <howEvaluationContextMenu>true</howEvaluationContextMenu>
- <showCommentWithArgumentHint>true</showCommentWithArgumentHint>
- <statusBarTypeEvaluation>false</statusBarTypeEvaluation>
- <namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
- <processPrimaryTypes>true</processPrimaryTypes>
- <processFunctionArguments>false</processFunctionArguments>
- <preProcessAllHeaders>false</preProcessAllHeaders>
- <parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
-
<resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
- <alwaysParseInBackground>true</alwaysParseInBackground>
- <usePermanentCaching>true</usePermanentCaching>
- <alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
- <includePaths>.;</includePaths>
- </codecompletion>
- <qt>
- <used>false</used>
- <version>3</version>
- <includestyle>3</includestyle>
- <root>/usr/lib/qt-3.3</root>
- <designerintegration>EmbeddedKDevDesigner</designerintegration>
- <qmake>/usr/lib/qt-3.3/bin/qmake</qmake>
- <designer>/usr/lib/qt-3.3/bin/designer</designer>
- <designerpluginpaths/>
- </qt>
- </kdevcppsupport>
- <cppsupportpart>
- <filetemplates>
- <interfacesuffix>.h</interfacesuffix>
- <implementationsuffix>.cpp</implementationsuffix>
- </filetemplates>
- </cppsupportpart>
- <kdevdebugger>
- <general>
- <programargs/>
- <gdbpath/>
- <dbgshell/>
- <configGdbScript/>
- <runShellScript/>
- <runGdbScript/>
- <breakonloadinglibs>true</breakonloadinglibs>
- <separatetty>false</separatetty>
- <floatingtoolbar>false</floatingtoolbar>
- </general>
- <display>
- <staticmembers>false</staticmembers>
- <demanglenames>true</demanglenames>
- <outputradix>10</outputradix>
- </display>
- </kdevdebugger>
- <kdevdocumentation>
- <projectdoc>
- <docsystem/>
- <docurl/>
- <usermanualurl/>
- </projectdoc>
- </kdevdocumentation>
- <kdevcvsservice>
- <recursivewhenupdate>true</recursivewhenupdate>
- <prunedirswhenupdate>true</prunedirswhenupdate>
- <createdirswhenupdate>true</createdirswhenupdate>
- <recursivewhencommitremove>true</recursivewhencommitremove>
- <revertoptions>-C</revertoptions>
- </kdevcvsservice>
-</kdevelop>
diff --git a/libftdi.lnt b/libftdi.lnt
index 89ad21d..2682b95 100644
--- a/libftdi.lnt
+++ b/libftdi.lnt
@@ -1,4 +1,5 @@
// PC-Lint 9.00 settings
+--iz:\usr\include\libusb-1.0
-emacro(527, ftdi_error_return) // ignore "unreachable code"
-emacro(717, ftdi_error_return)
diff --git a/src/ftdi.c b/src/ftdi.c
index 41496ee..c53d7aa 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -2,7 +2,7 @@
ftdi.c - description
-------------------
begin : Fri Apr 4 2003
- copyright : (C) 2003-2010 by Intra2net AG
+ copyright : (C) 2003-2011 by Intra2net AG and the libftdi
developers
email : opensource@xxxxxxxxxxxxx
***************************************************************************/
@@ -61,8 +61,8 @@ static void ftdi_usb_close_internal (struct ftdi_context
*ftdi)
{
if (ftdi && ftdi->usb_dev)
{
- libusb_close (ftdi->usb_dev);
- ftdi->usb_dev = NULL;
+ libusb_close (ftdi->usb_dev);
+ ftdi->usb_dev = NULL;
}
}
@@ -73,11 +73,13 @@ static void ftdi_usb_close_internal (struct ftdi_context
*ftdi)
\retval 0: all fine
\retval -1: couldn't allocate read buffer
+ \retval -2: couldn't allocate struct buffer
\remark This should be called before all functions
*/
int ftdi_init(struct ftdi_context *ftdi)
{
+ struct ftdi_eeprom* eeprom = (struct ftdi_eeprom *)malloc(sizeof(struct
ftdi_eeprom));
ftdi->usb_ctx = NULL;
ftdi->usb_dev = NULL;
ftdi->usb_read_timeout = 5000;
@@ -98,7 +100,10 @@ int ftdi_init(struct ftdi_context *ftdi)
ftdi->error_str = NULL;
- ftdi->eeprom_size = FTDI_DEFAULT_EEPROM_SIZE;
+ if (eeprom == 0)
+ ftdi_error_return(-2, "Can't malloc struct ftdi_eeprom");
+ memset(eeprom, 0, sizeof(struct ftdi_eeprom));
+ ftdi->eeprom = eeprom;
/* All fine. Now allocate the readbuffer */
return ftdi_read_data_set_chunksize(ftdi, 4096);
@@ -192,6 +197,27 @@ void ftdi_deinit(struct ftdi_context *ftdi)
free(ftdi->readbuffer);
ftdi->readbuffer = NULL;
}
+
+ if (ftdi->eeprom != NULL)
+ {
+ if (ftdi->eeprom->manufacturer != 0)
+ {
+ free(ftdi->eeprom->manufacturer);
+ ftdi->eeprom->manufacturer = 0;
+ }
+ if (ftdi->eeprom->product != 0)
+ {
+ free(ftdi->eeprom->product);
+ ftdi->eeprom->product = 0;
+ }
+ if (ftdi->eeprom->serial != 0)
+ {
+ free(ftdi->eeprom->serial);
+ ftdi->eeprom->serial = 0;
+ }
+ free(ftdi->eeprom);
+ ftdi->eeprom = NULL;
+ }
libusb_exit(ftdi->usb_ctx);
}
@@ -265,7 +291,7 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct
ftdi_device_list **devli
*curdev = (struct ftdi_device_list*)malloc(sizeof(struct
ftdi_device_list));
if (!*curdev)
ftdi_error_return(-3, "out of memory");
-
+
(*curdev)->next = NULL;
(*curdev)->dev = dev;
@@ -485,7 +511,7 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi,
libusb_device *dev)
if (libusb_set_configuration(ftdi->usb_dev, cfg0) < 0)
{
ftdi_usb_close_internal (ftdi);
- if(detach_errno == EPERM)
+ if (detach_errno == EPERM)
{
ftdi_error_return(-8, "inappropriate permissions on device!");
}
@@ -499,7 +525,7 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi,
libusb_device *dev)
if (libusb_claim_interface(ftdi->usb_dev, ftdi->interface) < 0)
{
ftdi_usb_close_internal (ftdi);
- if(detach_errno == EPERM)
+ if (detach_errno == EPERM)
{
ftdi_error_return(-8, "inappropriate permissions on device!");
}
@@ -518,7 +544,7 @@ int ftdi_usb_open_dev(struct ftdi_context *ftdi,
libusb_device *dev)
// Try to guess chip type
// Bug in the BM type chips: bcdDevice is 0x200 for serial == 0
if (desc.bcdDevice == 0x400 || (desc.bcdDevice == 0x200
- && desc.iSerialNumber == 0))
+ && desc.iSerialNumber == 0))
ftdi->type = TYPE_BM;
else if (desc.bcdDevice == 0x200)
ftdi->type = TYPE_AM;
@@ -610,7 +636,7 @@ int ftdi_usb_open_desc(struct ftdi_context *ftdi, int
vendor, int product,
\retval -11: ftdi context invalid
*/
int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int
product,
- const char* description, const char* serial, unsigned
int index)
+ const char* description, const char* serial,
unsigned int index)
{
libusb_device *dev;
libusb_device **devs;
@@ -668,11 +694,11 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi,
int vendor, int product,
ftdi_usb_close_internal (ftdi);
- if (index > 0)
- {
- index--;
- continue;
- }
+ if (index > 0)
+ {
+ index--;
+ continue;
+ }
res = ftdi_usb_open_dev(ftdi, dev);
libusb_free_device_list(devs,1);
@@ -723,24 +749,24 @@ int ftdi_usb_open_string(struct ftdi_context *ftdi, const
char* description)
{
libusb_device *dev;
libusb_device **devs;
- unsigned int bus_number, device_address;
- int i = 0;
+ unsigned int bus_number, device_address;
+ int i = 0;
if (libusb_init (&ftdi->usb_ctx) < 0)
- ftdi_error_return(-1, "libusb_init() failed");
+ 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");
+ if (libusb_get_device_list(ftdi->usb_ctx, &devs) < 0)
+ ftdi_error_return(-2, "libusb_get_device_list() failed");
/* XXX: This doesn't handle symlinks/odd paths/etc... */
if (sscanf (description + 2, "%u/%u", &bus_number, &device_address) !=
2)
- ftdi_error_return_free_device_list(-11, "illegal description
format", devs);
+ ftdi_error_return_free_device_list(-11, "illegal description
format", devs);
- while ((dev = devs[i++]) != NULL)
+ while ((dev = devs[i++]) != NULL)
{
int ret;
- if (bus_number == libusb_get_bus_number (dev)
- && device_address == libusb_get_device_address (dev))
+ if (bus_number == libusb_get_bus_number (dev)
+ && device_address == libusb_get_device_address (dev))
{
ret = ftdi_usb_open_dev(ftdi, dev);
libusb_free_device_list(devs,1);
@@ -1247,9 +1273,9 @@ static void ftdi_read_data_cb(struct libusb_transfer
*transfer)
if (actual_length > packet_size - 2)
{
for (i = 1; i < num_of_chunks; i++)
- memmove (ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size -
2)*i,
- ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i,
- packet_size - 2);
+ memmove (ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size
- 2)*i,
+
ftdi->readbuffer+ftdi->readbuffer_offset+packet_size*i,
+ packet_size - 2);
if (chunk_remains > 2)
{
memmove (ftdi->readbuffer+ftdi->readbuffer_offset+(packet_size
- 2)*i,
@@ -1258,7 +1284,7 @@ static void ftdi_read_data_cb(struct libusb_transfer
*transfer)
actual_length -= 2*num_of_chunks;
}
else
- actual_length -= 2*(num_of_chunks-1)+chunk_remains;
+ actual_length -= 2*(num_of_chunks-1)+chunk_remains;
}
if (actual_length > 0)
@@ -1309,9 +1335,9 @@ static void ftdi_write_data_cb(struct libusb_transfer
*transfer)
{
struct ftdi_transfer_control *tc = (struct ftdi_transfer_control *)
transfer->user_data;
struct ftdi_context *ftdi = tc->ftdi;
-
+
tc->offset += transfer->actual_length;
-
+
if (tc->offset == tc->size)
{
tc->completed = 1;
@@ -1350,19 +1376,22 @@ static void ftdi_write_data_cb(struct libusb_transfer
*transfer)
struct ftdi_transfer_control *ftdi_write_data_submit(struct ftdi_context
*ftdi, unsigned char *buf, int size)
{
struct ftdi_transfer_control *tc;
- struct libusb_transfer *transfer = libusb_alloc_transfer(0);
+ struct libusb_transfer *transfer;
int write_size, ret;
if (ftdi == NULL || ftdi->usb_dev == NULL)
- {
- libusb_free_transfer(transfer);
return NULL;
- }
tc = (struct ftdi_transfer_control *) malloc (sizeof (*tc));
+ if (!tc)
+ return NULL;
- if (!tc || !transfer)
+ transfer = libusb_alloc_transfer(0);
+ if (!transfer)
+ {
+ free(tc);
return NULL;
+ }
tc->ftdi = ftdi;
tc->completed = 0;
@@ -1371,9 +1400,9 @@ struct ftdi_transfer_control
*ftdi_write_data_submit(struct ftdi_context *ftdi,
tc->offset = 0;
if (size < ftdi->writebuffer_chunksize)
- write_size = size;
+ write_size = size;
else
- write_size = ftdi->writebuffer_chunksize;
+ write_size = ftdi->writebuffer_chunksize;
libusb_fill_bulk_transfer(transfer, ftdi->usb_dev, ftdi->in_ep, buf,
write_size, ftdi_write_data_cb, tc,
@@ -1384,8 +1413,7 @@ struct ftdi_transfer_control
*ftdi_write_data_submit(struct ftdi_context *ftdi,
if (ret < 0)
{
libusb_free_transfer(transfer);
- tc->completed = 1;
- tc->transfer = NULL;
+ free(tc);
return NULL;
}
tc->transfer = transfer;
@@ -2140,109 +2168,126 @@ int ftdi_set_error_char(struct ftdi_context *ftdi,
}
/**
- Set the eeprom size
-
- \param ftdi pointer to ftdi_context
- \param eeprom Pointer to ftdi_eeprom
- \param size
-
-*/
-void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom
*eeprom, int size)
-{
- if (ftdi == NULL)
- return;
-
- ftdi->eeprom_size=size;
- eeprom->size=size;
-}
-
-/**
Init eeprom with default values.
+ \param ftdi pointer to ftdi_context
+ \param manufacturer String to use as Manufacturer
+ \param product String to use as Product description
+ \param serial String to use as Serial number description
- \param eeprom Pointer to ftdi_eeprom
+ \retval 0: all fine
+ \retval -1: No struct ftdi_context
+ \retval -2: No struct ftdi_eeprom
*/
-void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom)
+int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi, char * manufacturer,
+ char * product, char * serial)
{
- int i;
-
- if (eeprom == NULL)
- return;
+ struct ftdi_eeprom *eeprom;
- eeprom->vendor_id = 0x0403;
- eeprom->product_id = 0x6001;
+ if (ftdi == NULL)
+ ftdi_error_return(-1, "No struct ftdi_context");
- eeprom->self_powered = 1;
- eeprom->remote_wakeup = 1;
- eeprom->chip_type = TYPE_BM;
+ if (ftdi->eeprom == NULL)
+ ftdi_error_return(-2,"No struct ftdi_eeprom");
- eeprom->in_is_isochronous = 0;
- eeprom->out_is_isochronous = 0;
- eeprom->suspend_pull_downs = 0;
+ eeprom = ftdi->eeprom;
+ memset(eeprom, 0, sizeof(struct ftdi_eeprom));
- eeprom->use_serial = 0;
- eeprom->change_usb_version = 0;
- eeprom->usb_version = 0x0200;
- eeprom->max_power = 0;
+ eeprom->vendor_id = 0x0403;
+ eeprom->use_serial = USE_SERIAL_NUM;
+ if ((ftdi->type == TYPE_AM) || (ftdi->type == TYPE_BM) ||
+ (ftdi->type == TYPE_R))
+ eeprom->product_id = 0x6001;
+ else
+ eeprom->product_id = 0x6010;
+ if (ftdi->type == TYPE_AM)
+ eeprom->usb_version = 0x0101;
+ else
+ eeprom->usb_version = 0x0200;
+ eeprom->max_power = 100;
+ if (eeprom->manufacturer)
+ free (eeprom->manufacturer);
eeprom->manufacturer = NULL;
+ if (manufacturer)
+ {
+ eeprom->manufacturer = malloc(strlen(manufacturer)+1);
+ if (eeprom->manufacturer)
+ strcpy(eeprom->manufacturer, manufacturer);
+ }
+
+ if (eeprom->product)
+ free (eeprom->product);
eeprom->product = NULL;
- eeprom->serial = NULL;
- for (i=0; i < 5; i++)
{
- eeprom->cbus_function[i] = 0;
+ eeprom->product = malloc(strlen(product)+1);
+ if (eeprom->product)
+ strcpy(eeprom->product, product);
}
- eeprom->high_current = 0;
- eeprom->invert = 0;
- eeprom->size = FTDI_DEFAULT_EEPROM_SIZE;
-}
+ if (eeprom->serial)
+ free (eeprom->serial);
+ eeprom->serial = NULL;
+ if (serial)
+ {
+ eeprom->serial = malloc(strlen(serial)+1);
+ if (eeprom->serial)
+ strcpy(eeprom->serial, serial);
+ }
-/**
- Frees allocated memory in eeprom.
- \param eeprom Pointer to ftdi_eeprom
-*/
-void ftdi_eeprom_free(struct ftdi_eeprom *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;
+ if (ftdi->type == TYPE_R)
+ {
+ eeprom->max_power = 90;
+ eeprom->size = 0x80;
+ eeprom->cbus_function[0] = CBUS_TXLED;
+ eeprom->cbus_function[1] = CBUS_RXLED;
+ eeprom->cbus_function[2] = CBUS_TXDEN;
+ eeprom->cbus_function[3] = CBUS_PWREN;
+ eeprom->cbus_function[4] = CBUS_SLEEP;
}
+ else
+ eeprom->size = -1;
+ return 0;
}
/**
- Build binary output from ftdi_eeprom structure.
+ Build binary buffer 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
+ \param ftdi pointer to ftdi_context
- \retval >0: free eeprom size
+ \retval >=0: size of eeprom user area in bytes
\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
+ \retval -2: Invalid eeprom or ftdi pointer
+ \retval -3: Invalid cbus function setting (FIXME: Not in the code?)
+ \retval -4: Chip doesn't support invert (FIXME: Not in the code?)
+ \retval -5: Chip doesn't support high current drive (FIXME: Not in
the code?)
+ \retval -6: No connected EEPROM or EEPROM Type unknown
*/
-int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output)
+int ftdi_eeprom_build(struct ftdi_context *ftdi)
{
- unsigned char i, j;
+ unsigned char i, j, eeprom_size_mask;
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};
+ int user_area_size;
+ struct ftdi_eeprom *eeprom;
+ unsigned char * output;
- 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;
+ output = eeprom->buf;
+
+ 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->manufacturer != NULL)
manufacturer_size = strlen(eeprom->manufacturer);
@@ -2251,43 +2296,37 @@ 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)
+ // eeprom size check
+ switch (ftdi->type)
{
- if (eeprom->invert) return -4;
- if (eeprom->high_current) return -5;
+ case TYPE_AM:
+ case TYPE_BM:
+ 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 = 88; // four extra config bytes + 4 bytes PnP
stuff
+ break;
+ case TYPE_2232H: // six extra config bytes + 4 bytes PnP
stuff
+ case TYPE_4232H:
+ user_area_size = 86;
+ break;
+ default:
+ user_area_size = 0;
+ break;
}
+ user_area_size -= (manufacturer_size + product_size + serial_size) * 2;
- 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);
+ if (user_area_size < 0)
+ ftdi_error_return(-1,"eeprom size exceeded");
// empty eeprom
- memset (output, 0, eeprom->size);
+ memset (ftdi->eeprom->buf, 0, FTDI_MAX_EEPROM_SIZE);
+
+ // Bytes and Bits set for all Types
- // 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;
@@ -2298,7 +2337,8 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
// Addr 06: Device release number (0400h for BM features)
output[0x06] = 0x00;
- switch (eeprom->chip_type) {
+ switch (ftdi->type)
+ {
case TYPE_AM:
output[0x07] = 0x02;
break;
@@ -2311,6 +2351,12 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
case TYPE_R:
output[0x07] = 0x06;
break;
+ case TYPE_2232H:
+ output[0x07] = 0x07;
+ break;
+ case TYPE_4232H:
+ output[0x07] = 0x08;
+ break;
default:
output[0x07] = 0x00;
}
@@ -2319,7 +2365,7 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
// Bit 7: always 1
// Bit 6: 1 if this device is self powered, 0 if bus powered
// Bit 5: 1 if this device uses remote wakeup
- // Bit 4: 1 if this device is battery powered
+ // Bit 4-0: reserved - 0
j = 0x80;
if (eeprom->self_powered == 1)
j |= 0x40;
@@ -2328,102 +2374,266 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
output[0x08] = j;
// Addr 09: Max power consumption: max power = value * 2 mA
- output[0x09] = eeprom->max_power;
+ output[0x09] = eeprom->max_power>>1;
- // Addr 0A: Chip configuration
- // Bit 7: 0 - reserved
- // Bit 6: 0 - reserved
- // Bit 5: 0 - reserved
- // Bit 4: 1 - Change USB version
- // Bit 3: 1 - Use the serial number string
- // Bit 2: 1 - Enable suspend pull downs for lower power
- // Bit 1: 1 - Out EndPoint is Isochronous
- // Bit 0: 1 - In EndPoint is Isochronous
- //
- j = 0;
- if (eeprom->in_is_isochronous == 1)
- j = j | 1;
- if (eeprom->out_is_isochronous == 1)
- j = j | 2;
- if (eeprom->suspend_pull_downs == 1)
- j = j | 4;
- if (eeprom->use_serial == 1)
- j = j | 8;
- if (eeprom->change_usb_version == 1)
- j = j | 16;
- output[0x0A] = j;
-
- // 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
- if (eeprom->change_usb_version == 1)
+ if (ftdi->type != TYPE_AM)
{
- output[0x0C] = eeprom->usb_version;
- output[0x0D] = eeprom->usb_version >> 8;
+ // Addr 0A: Chip configuration
+ // Bit 7: 0 - reserved
+ // Bit 6: 0 - reserved
+ // Bit 5: 0 - reserved
+ // Bit 4: 1 - Change USB version
+ // Bit 3: 1 - Use the serial number string
+ // Bit 2: 1 - Enable suspend pull downs for lower power
+ // Bit 1: 1 - Out EndPoint is Isochronous
+ // Bit 0: 1 - In EndPoint is Isochronous
+ //
+ j = 0;
+ if (eeprom->in_is_isochronous == 1)
+ j = j | 1;
+ if (eeprom->out_is_isochronous == 1)
+ j = j | 2;
+ output[0x0A] = j;
}
+ // Dynamic content
+ // Strings start at 0x94 (TYPE_AM, TYPE_BM)
+ // 0x96 (TYPE_2232C), 0x98 (TYPE_R) and 0x9a (TYPE_x232H)
+ i = 0;
+ switch (ftdi->type)
+ {
+ case TYPE_2232H:
+ case TYPE_4232H:
+ i += 2;
+ case TYPE_R:
+ i += 2;
+ case TYPE_2232C:
+ i += 2;
+ case TYPE_AM:
+ case TYPE_BM:
+ i += 0x94;
+ }
+ /* Wrap around 0x80 for 128 byte EEPROMS (Internale and 93x46) */
+ eeprom_size_mask = eeprom->size -1;
// Addr 0E: Offset of the manufacturer string + 0x80, calculated later
// Addr 0F: Length of manufacturer string
+ // Output manufacturer
+ output[0x0E] = i; // calculate offset
+ output[i & eeprom_size_mask] = manufacturer_size*2 + 2, i++;
+ output[i & eeprom_size_mask] = 0x03, i++; // type: string
+ for (j = 0; j < manufacturer_size; j++)
+ {
+ output[i & eeprom_size_mask] = eeprom->manufacturer[j], i++;
+ output[i & eeprom_size_mask] = 0x00, i++;
+ }
output[0x0F] = manufacturer_size*2 + 2;
// Addr 10: Offset of the product string + 0x80, calculated later
// Addr 11: Length of product string
+ output[0x10] = i | 0x80; // calculate offset
+ output[i & eeprom_size_mask] = product_size*2 + 2, i++;
+ output[i & eeprom_size_mask] = 0x03, i++;
+ for (j = 0; j < product_size; j++)
+ {
+ output[i & eeprom_size_mask] = eeprom->product[j], i++;
+ output[i & eeprom_size_mask] = 0x00, i++;
+ }
output[0x11] = product_size*2 + 2;
// Addr 12: Offset of the serial string + 0x80, calculated later
// 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
- // 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;
+ output[0x12] = i | 0x80; // calculate offset
+ output[i & eeprom_size_mask] = serial_size*2 + 2, i++;
+ output[i & eeprom_size_mask] = 0x03, i++;
+ for (j = 0; j < serial_size; j++)
+ {
+ output[i & eeprom_size_mask] = eeprom->serial[j], i++;
+ output[i & eeprom_size_mask] = 0x00, i++;
}
- if (eeprom->size >= 256) i = 0x80;
-
- // Output manufacturer
- output[0x0E] = i | 0x80; // calculate offset
- output[i++] = manufacturer_size*2 + 2;
- output[i++] = 0x03; // type: string
- for (j = 0; j < manufacturer_size; j++)
+ // Legacy port name and PnP fields for FT2232 and newer chips
+ if (ftdi->type > TYPE_BM)
{
- output[i] = eeprom->manufacturer[j], i++;
- output[i] = 0x00, i++;
+ output[i & eeprom_size_mask] = 0x02; /* as seen when written with
FTD2XX */
+ i++;
+ output[i & eeprom_size_mask] = 0x03; /* as seen when written with
FTD2XX */
+ i++;
+ output[i & eeprom_size_mask] = eeprom->is_not_pnp; /* as seen when
written with FTD2XX */
+ i++;
}
- // Output product name
- output[0x10] = i | 0x80; // calculate offset
- output[i] = product_size*2 + 2, i++;
- output[i] = 0x03, i++;
- for (j = 0; j < product_size; j++)
+ output[0x13] = serial_size*2 + 2;
+
+ if (ftdi->type > TYPE_AM) /* use_serial not used in AM devices */
{
- output[i] = eeprom->product[j], i++;
- output[i] = 0x00, i++;
+ if (eeprom->use_serial == USE_SERIAL_NUM )
+ output[0x0A] |= USE_SERIAL_NUM;
+ else
+ output[0x0A] &= ~USE_SERIAL_NUM;
}
- // Output serial
- output[0x12] = i | 0x80; // calculate offset
- output[i] = serial_size*2 + 2, i++;
- output[i] = 0x03, i++;
- for (j = 0; j < serial_size; j++)
+ /* Bytes and Bits specific to (some) types
+ Write linear, as this allows easier fixing*/
+ switch (ftdi->type)
{
- output[i] = eeprom->serial[j], i++;
- output[i] = 0x00, i++;
+ case TYPE_AM:
+ break;
+ 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)
+ output[0x0A] |= USE_USB_VERSION_BIT;
+ else
+ output[0x0A] &= ~USE_USB_VERSION_BIT;
+
+ break;
+ case TYPE_2232C:
+
+ output[0x00] = (eeprom->channel_a_type);
+ if ( eeprom->channel_a_driver == DRIVER_VCP)
+ output[0x00] |= DRIVER_VCP;
+ else
+ output[0x00] &= ~DRIVER_VCP;
+
+ if ( eeprom->high_current_a == HIGH_CURRENT_DRIVE)
+ output[0x00] |= HIGH_CURRENT_DRIVE;
+ else
+ output[0x00] &= ~HIGH_CURRENT_DRIVE;
+
+ output[0x01] = (eeprom->channel_b_type);
+ if ( eeprom->channel_b_driver == DRIVER_VCP)
+ output[0x01] |= DRIVER_VCP;
+ else
+ output[0x01] &= ~DRIVER_VCP;
+
+ if ( eeprom->high_current_b == HIGH_CURRENT_DRIVE)
+ output[0x01] |= HIGH_CURRENT_DRIVE;
+ else
+ output[0x01] &= ~HIGH_CURRENT_DRIVE;
+
+ if (eeprom->in_is_isochronous == 1)
+ output[0x0A] |= 0x1;
+ else
+ output[0x0A] &= ~0x1;
+ if (eeprom->out_is_isochronous == 1)
+ output[0x0A] |= 0x2;
+ else
+ output[0x0A] &= ~0x2;
+ if (eeprom->suspend_pull_downs == 1)
+ output[0x0A] |= 0x4;
+ else
+ output[0x0A] &= ~0x4;
+ if (eeprom->use_usb_version == USE_USB_VERSION_BIT)
+ output[0x0A] |= USE_USB_VERSION_BIT;
+ else
+ output[0x0A] &= ~USE_USB_VERSION_BIT;
+
+ output[0x0C] = eeprom->usb_version & 0xff;
+ output[0x0D] = (eeprom->usb_version>>8) & 0xff;
+ output[0x14] = eeprom->chip;
+ break;
+ case TYPE_R:
+ if (eeprom->high_current == HIGH_CURRENT_DRIVE_R)
+ output[0x00] |= HIGH_CURRENT_DRIVE_R;
+ output[0x01] = 0x40; /* Hard coded Endpoint Size*/
+
+ if (eeprom->suspend_pull_downs == 1)
+ output[0x0A] |= 0x4;
+ else
+ output[0x0A] &= ~0x4;
+ output[0x0B] = eeprom->invert;
+ output[0x0C] = eeprom->usb_version & 0xff;
+ output[0x0D] = (eeprom->usb_version>>8) & 0xff;
+
+ if (eeprom->cbus_function[0] > CBUS_BB)
+ output[0x14] = CBUS_TXLED;
+ else
+ output[0x14] = eeprom->cbus_function[0];
+
+ if (eeprom->cbus_function[1] > CBUS_BB)
+ output[0x14] |= CBUS_RXLED<<4;
+ else
+ output[0x14] |= eeprom->cbus_function[1]<<4;
+
+ if (eeprom->cbus_function[2] > CBUS_BB)
+ output[0x15] = CBUS_TXDEN;
+ else
+ output[0x15] = eeprom->cbus_function[2];
+
+ if (eeprom->cbus_function[3] > CBUS_BB)
+ output[0x15] |= CBUS_PWREN<<4;
+ else
+ output[0x15] |= eeprom->cbus_function[3]<<4;
+
+ if (eeprom->cbus_function[4] > CBUS_CLK6)
+ output[0x16] = CBUS_SLEEP;
+ else
+ output[0x16] = eeprom->cbus_function[4];
+ break;
+ case TYPE_2232H:
+ output[0x00] = (eeprom->channel_a_type);
+ if ( eeprom->channel_a_driver == DRIVER_VCP)
+ output[0x00] |= DRIVER_VCP;
+ else
+ output[0x00] &= ~DRIVER_VCP;
+
+ output[0x01] = (eeprom->channel_b_type);
+ if ( eeprom->channel_b_driver == DRIVER_VCP)
+ output[0x01] |= DRIVER_VCP;
+ else
+ output[0x01] &= ~DRIVER_VCP;
+ if (eeprom->suspend_dbus7 == SUSPEND_DBUS7_BIT)
+ output[0x01] |= SUSPEND_DBUS7_BIT;
+ else
+ output[0x01] &= ~SUSPEND_DBUS7_BIT;
+
+ if (eeprom->suspend_pull_downs == 1)
+ output[0x0A] |= 0x4;
+ else
+ output[0x0A] &= ~0x4;
+
+ 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[0x0c] |= DRIVE_16MA<<4;
+ else
+ output[0x0c] |= eeprom->group1_drive<<4;
+ if (eeprom->group1_schmitt == IS_SCHMITT)
+ output[0x0c] |= IS_SCHMITT<<4;
+ if (eeprom->group1_slew == SLOW_SLEW)
+ output[0x0c] |= SLOW_SLEW<<4;
+
+ if (eeprom->group2_drive > DRIVE_16MA)
+ output[0x0d] |= DRIVE_16MA;
+ else
+ output[0x0d] |= eeprom->group2_drive;
+ if (eeprom->group2_schmitt == IS_SCHMITT)
+ output[0x0d] |= IS_SCHMITT;
+ if (eeprom->group2_slew == SLOW_SLEW)
+ output[0x0d] |= SLOW_SLEW;
+
+ if (eeprom->group3_drive > DRIVE_16MA)
+ output[0x0d] |= DRIVE_16MA<<4;
+ else
+ output[0x0d] |= eeprom->group3_drive<<4;
+ if (eeprom->group3_schmitt == IS_SCHMITT)
+ output[0x0d] |= IS_SCHMITT<<4;
+ if (eeprom->group3_slew == SLOW_SLEW)
+ output[0x0d] |= SLOW_SLEW<<4;
+
+ output[0x18] = eeprom->chip;
+
+ break;
+ case TYPE_4232H:
+ fprintf(stderr,"FIXME: Build FT4232H specific EEPROM settings\n");
}
// calculate checksum
@@ -2441,15 +2651,14 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
output[eeprom->size-2] = checksum;
output[eeprom->size-1] = checksum >> 8;
- return size_check;
+ return user_area_size;
}
/**
Decode binary EEPROM image into an ftdi_eeprom structure.
- \param eeprom Pointer to ftdi_eeprom which will be filled in.
- \param buf Buffer of \a size bytes of raw eeprom data
- \param size size size of eeprom data in bytes
+ \param ftdi pointer to ftdi_context
+ \param verbose Decode EEPROM on stdout
\retval 0: all fine
\retval -1: something went wrong
@@ -2457,38 +2666,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, int verbose)
{
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;
-
- 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
+ int eeprom_size;
+ struct ftdi_eeprom *eeprom;
+ unsigned char *buf = ftdi->eeprom->buf;
+ int release;
- // empty eeprom struct
- memset(eeprom, 0, sizeof(struct ftdi_eeprom));
+ if (ftdi == NULL)
+ ftdi_error_return(-1,"No context");
+ if (ftdi->eeprom == NULL)
+ ftdi_error_return(-1,"No eeprom structure");
- // Addr 00: High current IO
- eeprom->high_current = (buf[0x02] & HIGH_CURRENT_DRIVE);
+ eeprom = ftdi->eeprom;
+ eeprom_size = eeprom->size;
// Addr 02: Vendor ID
eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8);
@@ -2496,31 +2690,14 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom,
unsigned char *buf, int size)
// Addr 04: Product ID
eeprom->product_id = buf[0x04] + (buf[0x05] << 8);
- value = buf[0x06] + (buf[0x07]<<8);
- switch (value)
- {
- case 0x0600:
- eeprom->chip_type = TYPE_R;
- break;
- case 0x0400:
- eeprom->chip_type = TYPE_BM;
- break;
- case 0x0200:
- eeprom->chip_type = TYPE_AM;
- break;
- default: // Unknown device
- eeprom->chip_type = 0;
- break;
- }
+ release = buf[0x06] + (buf[0x07]<<8);
// Addr 08: Config descriptor
// Bit 7: always 1
// Bit 6: 1 if this device is self powered, 0 if bus powered
// Bit 5: 1 if this device uses remote wakeup
- // Bit 4: 1 if this device is battery powered
- j = buf[0x08];
- if (j&0x40) eeprom->self_powered = 1;
- if (j&0x20) eeprom->remote_wakeup = 1;
+ eeprom->self_powered = buf[0x08] & 0x40;
+ eeprom->remote_wakeup = buf[0x08] & 0x20;
// Addr 09: Max power consumption: max power = value * 2 mA
eeprom->max_power = buf[0x09];
@@ -2529,83 +2706,84 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom,
unsigned char *buf, int size)
// Bit 7: 0 - reserved
// Bit 6: 0 - reserved
// Bit 5: 0 - reserved
- // Bit 4: 1 - Change USB version
+ // Bit 4: 1 - Change USB version on BM and 2232C
// Bit 3: 1 - Use the serial number string
// Bit 2: 1 - Enable suspend pull downs for lower power
// Bit 1: 1 - Out EndPoint is Isochronous
// Bit 0: 1 - In EndPoint is Isochronous
//
- j = buf[0x0A];
- if (j&0x01) eeprom->in_is_isochronous = 1;
- if (j&0x02) eeprom->out_is_isochronous = 1;
- if (j&0x04) eeprom->suspend_pull_downs = 1;
- if (j&0x08) eeprom->use_serial = 1;
- if (j&0x10) eeprom->change_usb_version = 1;
+ 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_usb_version = buf[0x0A] & USE_USB_VERSION_BIT;
- // 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
- if (eeprom->change_usb_version == 1)
- {
- eeprom->usb_version = buf[0x0C] + (buf[0x0D] << 8);
- }
+ // Addr 0C: USB version low byte when 0x0A
+ // Addr 0D: USB version high byte when 0x0A
+ eeprom->usb_version = buf[0x0C] + (buf[0x0D] << 8);
// 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 (eeprom->manufacturer)
+ free(eeprom->manufacturer);
+ if (manufacturer_size > 0)
+ {
+ eeprom->manufacturer = malloc(manufacturer_size);
+ if (eeprom->manufacturer)
+ {
+ // Decode manufacturer
+ i = buf[0x0E] & (eeprom_size -1); // offset
+ for (j=0;j<manufacturer_size-1;j++)
+ {
+ eeprom->manufacturer[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
+ if (eeprom->product)
+ free(eeprom->product);
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] & (eeprom_size -1); // offset
+ for (j=0;j<product_size-1;j++)
+ {
+ eeprom->product[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
+ if (eeprom->serial)
+ free(eeprom->serial);
serial_size = buf[0x13]/2;
- if (serial_size > 0) eeprom->serial = malloc(serial_size);
- else eeprom->serial = NULL;
-
- // 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;
- }
-
- // Decode manufacturer
- i = buf[0x0E] & 0x7f; // offset
- for (j=0;j<manufacturer_size-1;j++)
+ if (serial_size > 0)
{
- eeprom->manufacturer[j] = buf[2*j+i+2];
- }
- eeprom->manufacturer[j] = '\0';
-
- // Decode product name
- i = buf[0x10] & 0x7f; // offset
- for (j=0;j<product_size-1;j++)
- {
- eeprom->product[j] = buf[2*j+i+2];
- }
- eeprom->product[j] = '\0';
-
- // Decode serial
- i = buf[0x12] & 0x7f; // offset
- for (j=0;j<serial_size-1;j++)
- {
- eeprom->serial[j] = buf[2*j+i+2];
+ eeprom->serial = malloc(serial_size);
+ if (eeprom->serial)
+ {
+ // Decode serial
+ i = buf[0x12] & (eeprom_size -1); // offset
+ for (j=0;j<serial_size-1;j++)
+ {
+ eeprom->serial[j] = buf[2*j+i+2];
+ }
+ eeprom->serial[j] = '\0';
+ }
}
- eeprom->serial[j] = '\0';
+ else eeprom->serial = NULL;
// verify checksum
checksum = 0xAAAA;
@@ -2624,8 +2802,471 @@ 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");
+ }
+
+ eeprom->channel_a_type = 0;
+ if ((ftdi->type == TYPE_AM) || (ftdi->type == TYPE_BM))
+ {
+ eeprom->chip = -1;
+ }
+ else if (ftdi->type == TYPE_2232C)
+ {
+ eeprom->channel_a_type = 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;
+ eeprom->channel_b_driver = buf[0x01] & DRIVER_VCP;
+ eeprom->high_current_b = buf[0x01] & HIGH_CURRENT_DRIVE;
+ eeprom->chip = buf[0x14];
+ }
+ else if (ftdi->type == TYPE_R)
+ {
+ /* 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;
+ if ( (buf[0x01]&0x40) != 0x40)
+ fprintf(stderr,
+ "TYPE_R EEPROM byte[0x01] Bit 6 unexpected Endpoint size."
+ " If this happened with the\n"
+ " EEPROM programmed by FTDI tools, please report "
+ "to libftdi@xxxxxxxxxxxxxxxxxxxxxxx\n");
+
+ eeprom->chip = buf[0x16];
+ // Addr 0B: Invert data lines
+ // Works only on FT232R, not FT245R, but no way to distinguish
+ eeprom->invert = buf[0x0B];
+ // Addr 14: CBUS function: CBUS0, CBUS1
+ // Addr 15: CBUS function: CBUS2, CBUS3
+ // Addr 16: CBUS function: CBUS5
+ 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 if ((ftdi->type == TYPE_2232H) ||(ftdi->type == TYPE_4232H))
+ {
+ eeprom->channel_a_type = 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;
+
+ if (ftdi->type == TYPE_2232H)
+ eeprom->suspend_dbus7 = buf[0x01] & SUSPEND_DBUS7_BIT;
+
+ eeprom->chip = buf[0x18];
+ 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[0x0c] >> 4) & 0x3;
+ eeprom->group1_schmitt = (buf[0x0c] >> 4) & IS_SCHMITT;
+ eeprom->group1_slew = (buf[0x0c] >> 4) & SLOW_SLEW;
+ eeprom->group2_drive = buf[0x0d] & DRIVE_16MA;
+ eeprom->group2_schmitt = buf[0x0d] & IS_SCHMITT;
+ eeprom->group2_slew = buf[0x0d] & SLOW_SLEW;
+ eeprom->group3_drive = (buf[0x0d] >> 4) & DRIVE_16MA;
+ eeprom->group3_schmitt = (buf[0x0d] >> 4) & IS_SCHMITT;
+ eeprom->group3_slew = (buf[0x0d] >> 4) & SLOW_SLEW;
+ }
+
+ if (verbose)
+ {
+ char *channel_mode[] = {"UART","245","CPU", "unknown", "OPTO"};
+ 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);
+
+ if (eeprom->self_powered)
+ fprintf(stdout, "Self-Powered%s", (eeprom->remote_wakeup)?", USB
Remote Wake Up\n":"\n");
+ else
+ fprintf(stdout, "Bus Powered: %3d mA%s", eeprom->max_power * 2,
+ (eeprom->remote_wakeup)?" USB Remote Wake Up\n":"\n");
+ if (eeprom->manufacturer)
+ fprintf(stdout, "Manufacturer: %s\n",eeprom->manufacturer);
+ if (eeprom->product)
+ fprintf(stdout, "Product: %s\n",eeprom->product);
+ if (eeprom->serial)
+ fprintf(stdout, "Serial: %s\n",eeprom->serial);
+ fprintf(stdout, "Checksum : %04x\n", checksum);
+ if (ftdi->type == TYPE_R)
+ fprintf(stdout, "Internal EEPROM\n");
+ else if (eeprom->chip >= 0x46)
+ fprintf(stdout, "Attached EEPROM: 93x%02x\n", eeprom->chip);
+ if (eeprom->suspend_dbus7)
+ fprintf(stdout, "Suspend on DBUS7\n");
+ if (eeprom->suspend_pull_downs)
+ fprintf(stdout, "Pull IO pins low during suspend\n");
+ if (eeprom->remote_wakeup)
+ fprintf(stdout, "Enable Remote Wake Up\n");
+ fprintf(stdout, "PNP: %d\n",(eeprom->is_not_pnp)?0:1);
+ if (ftdi->type >= TYPE_2232C)
+ fprintf(stdout,"Channel A has Mode %s%s%s\n",
+ 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))
+ fprintf(stdout,"Channel B has Mode %s%s%s\n",
+ channel_mode[eeprom->channel_b_type],
+ (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)
+ fprintf(stdout,"Use explicit USB Version
%04x\n",eeprom->usb_version);
+
+ if ((ftdi->type == TYPE_2232H) || (ftdi->type == TYPE_4232H))
+ {
+ fprintf(stdout,"%s has %d mA drive%s%s\n",
+ (ftdi->type == TYPE_2232H)?"AL":"A",
+ (eeprom->group0_drive+1) *4,
+ (eeprom->group0_schmitt)?" Schmitt Input":"",
+ (eeprom->group0_slew)?" Slow Slew":"");
+ fprintf(stdout,"%s has %d mA drive%s%s\n",
+ (ftdi->type == TYPE_2232H)?"AH":"B",
+ (eeprom->group1_drive+1) *4,
+ (eeprom->group1_schmitt)?" Schmitt Input":"",
+ (eeprom->group1_slew)?" Slow Slew":"");
+ fprintf(stdout,"%s has %d mA drive%s%s\n",
+ (ftdi->type == TYPE_2232H)?"BL":"C",
+ (eeprom->group2_drive+1) *4,
+ (eeprom->group2_schmitt)?" Schmitt Input":"",
+ (eeprom->group2_slew)?" Slow Slew":"");
+ fprintf(stdout,"%s has %d mA drive%s%s\n",
+ (ftdi->type == TYPE_2232H)?"BH":"D",
+ (eeprom->group3_drive+1) *4,
+ (eeprom->group3_schmitt)?" Schmitt Input":"",
+ (eeprom->group3_slew)?" Slow Slew":"");
+ }
+ if (ftdi->type == TYPE_R)
+ {
+ char *cbus_mux[] = {"TXDEN","PWREN","RXLED", "TXLED","TX+RXLED",
+ "SLEEP","CLK48","CLK24","CLK12","CLK6",
+ "IOMODE","BB_WR","BB_RD"
+ };
+ char *cbus_BB[] = {"RXF","TXE","RD", "WR"};
+
+ if (eeprom->invert)
+ {
+ char *r_bits[] = {"TXD","RXD","RTS",
"CTS","DTR","DSR","DCD","RI"};
+ fprintf(stdout,"Inverted bits:");
+ for (i=0; i<8; i++)
+ if ((eeprom->invert & (1<<i)) == (1<<i))
+ fprintf(stdout," %s",r_bits[i]);
+ fprintf(stdout,"\n");
+ }
+ for (i=0; i<5; i++)
+ {
+ if (eeprom->cbus_function[i]<CBUS_BB)
+ fprintf(stdout,"C%d Function: %s\n", i,
+ cbus_mux[eeprom->cbus_function[i]]);
+ else
+ {
+ /* FIXME for Uwe: This results in an access above array
bounds.
+ Also I couldn't find documentation about this mode.
+ fprintf(stdout,"C%d BB Function: %s\n", i,
+ cbus_BB[i]);
+ */
+ fprintf(stdout, "Unknown CBUS mode. Might be special
mode?\n");
+ (void)cbus_BB;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ Get a value from the decoded EEPROM structure
+
+ \param ftdi pointer to ftdi_context
+ \param value_name Enum of the value to query
+ \param value Pointer to store read value
+
+ \retval 0: all fine
+ \retval -1: Value doesn't exist
+*/
+int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value
value_name, int* value)
+{
+ switch (value_name)
+ {
+ case VENDOR_ID:
+ *value = ftdi->eeprom->vendor_id;
+ break;
+ case PRODUCT_ID:
+ *value = ftdi->eeprom->product_id;
+ break;
+ case SELF_POWERED:
+ *value = ftdi->eeprom->self_powered;
+ break;
+ case REMOTE_WAKEUP:
+ *value = ftdi->eeprom->remote_wakeup;
+ break;
+ case IS_NOT_PNP:
+ *value = ftdi->eeprom->is_not_pnp;
+ break;
+ case SUSPEND_DBUS7:
+ *value = ftdi->eeprom->suspend_dbus7;
+ break;
+ case IN_IS_ISOCHRONOUS:
+ *value = ftdi->eeprom->in_is_isochronous;
+ break;
+ case SUSPEND_PULL_DOWNS:
+ *value = ftdi->eeprom->suspend_pull_downs;
+ break;
+ case USE_SERIAL:
+ *value = ftdi->eeprom->use_serial;
+ break;
+ case USB_VERSION:
+ *value = ftdi->eeprom->usb_version;
+ break;
+ case MAX_POWER:
+ *value = ftdi->eeprom->max_power;
+ break;
+ case CHANNEL_A_TYPE:
+ *value = ftdi->eeprom->channel_a_type;
+ break;
+ case CHANNEL_B_TYPE:
+ *value = ftdi->eeprom->channel_b_type;
+ break;
+ case CHANNEL_A_DRIVER:
+ *value = ftdi->eeprom->channel_a_driver;
+ break;
+ case CHANNEL_B_DRIVER:
+ *value = ftdi->eeprom->channel_b_driver;
+ break;
+ case CBUS_FUNCTION_0:
+ *value = ftdi->eeprom->cbus_function[0];
+ break;
+ case CBUS_FUNCTION_1:
+ *value = ftdi->eeprom->cbus_function[1];
+ break;
+ case CBUS_FUNCTION_2:
+ *value = ftdi->eeprom->cbus_function[2];
+ break;
+ case CBUS_FUNCTION_3:
+ *value = ftdi->eeprom->cbus_function[3];
+ break;
+ case CBUS_FUNCTION_4:
+ *value = ftdi->eeprom->cbus_function[4];
+ break;
+ case HIGH_CURRENT:
+ *value = ftdi->eeprom->high_current;
+ break;
+ case HIGH_CURRENT_A:
+ *value = ftdi->eeprom->high_current_a;
+ break;
+ case HIGH_CURRENT_B:
+ *value = ftdi->eeprom->high_current_b;
+ break;
+ case INVERT:
+ *value = ftdi->eeprom->invert;
+ break;
+ case GROUP0_DRIVE:
+ *value = ftdi->eeprom->group0_drive;
+ break;
+ case GROUP0_SCHMITT:
+ *value = ftdi->eeprom->group0_schmitt;
+ break;
+ case GROUP0_SLEW:
+ *value = ftdi->eeprom->group0_slew;
+ break;
+ case GROUP1_DRIVE:
+ *value = ftdi->eeprom->group1_drive;
+ break;
+ case GROUP1_SCHMITT:
+ *value = ftdi->eeprom->group1_schmitt;
+ break;
+ case GROUP1_SLEW:
+ *value = ftdi->eeprom->group1_slew;
+ break;
+ case GROUP2_DRIVE:
+ *value = ftdi->eeprom->group2_drive;
+ break;
+ case GROUP2_SCHMITT:
+ *value = ftdi->eeprom->group2_schmitt;
+ break;
+ case GROUP2_SLEW:
+ *value = ftdi->eeprom->group2_slew;
+ break;
+ case GROUP3_DRIVE:
+ *value = ftdi->eeprom->group3_drive;
+ break;
+ case GROUP3_SCHMITT:
+ *value = ftdi->eeprom->group3_schmitt;
+ break;
+ case GROUP3_SLEW:
+ *value = ftdi->eeprom->group3_slew;
+ break;
+ case CHIP_TYPE:
+ *value = ftdi->eeprom->chip;
+ break;
+ case CHIP_SIZE:
+ *value = ftdi->eeprom->size;
+ break;
+ default:
+ ftdi_error_return(-1, "Request for unknown EEPROM value");
}
+ return 0;
+}
+
+/**
+ Set a value in the decoded EEPROM Structure
+ No parameter checking is performed
+
+ \param ftdi pointer to ftdi_context
+ \param value_name Enum of the value to set
+ \param value to set
+
+ \retval 0: all fine
+ \retval -1: Value doesn't exist
+ \retval -2: Value not user settable
+*/
+int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum ftdi_eeprom_value
value_name, int value)
+{
+ switch (value_name)
+ {
+ case VENDOR_ID:
+ ftdi->eeprom->vendor_id = value;
+ break;
+ case PRODUCT_ID:
+ ftdi->eeprom->product_id = value;
+ break;
+ case SELF_POWERED:
+ ftdi->eeprom->self_powered = value;
+ break;
+ case REMOTE_WAKEUP:
+ ftdi->eeprom->remote_wakeup = value;
+ break;
+ case IS_NOT_PNP:
+ ftdi->eeprom->is_not_pnp = value;
+ break;
+ case SUSPEND_DBUS7:
+ ftdi->eeprom->suspend_dbus7 = value;
+ break;
+ case IN_IS_ISOCHRONOUS:
+ ftdi->eeprom->in_is_isochronous = value;
+ break;
+ case SUSPEND_PULL_DOWNS:
+ ftdi->eeprom->suspend_pull_downs = value;
+ break;
+ case USE_SERIAL:
+ ftdi->eeprom->use_serial = value;
+ break;
+ case USB_VERSION:
+ ftdi->eeprom->usb_version = value;
+ break;
+ case MAX_POWER:
+ ftdi->eeprom->max_power = value;
+ break;
+ case CHANNEL_A_TYPE:
+ ftdi->eeprom->channel_a_type = value;
+ break;
+ case CHANNEL_B_TYPE:
+ ftdi->eeprom->channel_b_type = value;
+ break;
+ case CHANNEL_A_DRIVER:
+ ftdi->eeprom->channel_a_driver = value;
+ break;
+ case CHANNEL_B_DRIVER:
+ ftdi->eeprom->channel_b_driver = value;
+ break;
+ case CBUS_FUNCTION_0:
+ ftdi->eeprom->cbus_function[0] = value;
+ break;
+ case CBUS_FUNCTION_1:
+ ftdi->eeprom->cbus_function[1] = value;
+ break;
+ case CBUS_FUNCTION_2:
+ ftdi->eeprom->cbus_function[2] = value;
+ break;
+ case CBUS_FUNCTION_3:
+ ftdi->eeprom->cbus_function[3] = value;
+ break;
+ case CBUS_FUNCTION_4:
+ ftdi->eeprom->cbus_function[4] = value;
+ break;
+ case HIGH_CURRENT:
+ ftdi->eeprom->high_current = value;
+ break;
+ case HIGH_CURRENT_A:
+ ftdi->eeprom->high_current_a = value;
+ break;
+ case HIGH_CURRENT_B:
+ ftdi->eeprom->high_current_b = value;
+ break;
+ case INVERT:
+ ftdi->eeprom->invert = value;
+ break;
+ case GROUP0_DRIVE:
+ ftdi->eeprom->group0_drive = value;
+ break;
+ case GROUP0_SCHMITT:
+ ftdi->eeprom->group0_schmitt = value;
+ break;
+ case GROUP0_SLEW:
+ ftdi->eeprom->group0_slew = value;
+ break;
+ case GROUP1_DRIVE:
+ ftdi->eeprom->group1_drive = value;
+ break;
+ case GROUP1_SCHMITT:
+ ftdi->eeprom->group1_schmitt = value;
+ break;
+ case GROUP1_SLEW:
+ ftdi->eeprom->group1_slew = value;
+ break;
+ case GROUP2_DRIVE:
+ ftdi->eeprom->group2_drive = value;
+ break;
+ case GROUP2_SCHMITT:
+ ftdi->eeprom->group2_schmitt = value;
+ break;
+ case GROUP2_SLEW:
+ ftdi->eeprom->group2_slew = value;
+ break;
+ case GROUP3_DRIVE:
+ ftdi->eeprom->group3_drive = value;
+ break;
+ case GROUP3_SCHMITT:
+ ftdi->eeprom->group3_schmitt = value;
+ break;
+ case GROUP3_SLEW:
+ ftdi->eeprom->group3_slew = value;
+ break;
+ case CHIP_TYPE:
+ ftdi->eeprom->chip = value;
+ break;
+ case CHIP_SIZE:
+ ftdi_error_return(-2, "EEPROM Value can't be changed");
+ default :
+ ftdi_error_return(-1, "Request to unknown EEPROM value");
+ }
+ return 0;
+}
+
+/** Get the read-only buffer to the binary EEPROM content
+
+ \param ftdi pointer to ftdi_context
+ \param buf buffer to receive EEPROM content
+ \param size Size of receiving buffer
+
+ \retval 0: All fine
+ \retval -1: struct ftdi_contxt or ftdi_eeprom missing
+ \retval -2: Not enough room to store eeprom
+*/
+int ftdi_get_eeprom_buf(struct ftdi_context *ftdi, unsigned char * buf, int
size)
+{
+ if (!ftdi || !(ftdi->eeprom))
+ ftdi_error_return(-1, "No appropriate structure");
+
+ if (!buf || size < ftdi->eeprom->size)
+ ftdi_error_return(-1, "Not enough room to store eeprom");
+
+ // Only copy up to FTDI_MAX_EEPROM_SIZE bytes
+ if (size > FTDI_MAX_EEPROM_SIZE)
+ size = FTDI_MAX_EEPROM_SIZE;
+
+ memcpy(buf, ftdi->eeprom->buf, size);
return 0;
}
@@ -2656,25 +3297,40 @@ int ftdi_read_eeprom_location (struct ftdi_context
*ftdi, int eeprom_addr, unsig
Read eeprom
\param ftdi pointer to ftdi_context
- \param eeprom Pointer to store eeprom into
\retval 0: all fine
\retval -1: read failed
\retval -2: USB device unavailable
*/
-int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom)
+int ftdi_read_eeprom(struct ftdi_context *ftdi)
{
int i;
+ unsigned char *buf;
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
+ buf = ftdi->eeprom->buf;
- 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)
+ if (libusb_control_transfer(
+ ftdi->usb_dev,
FTDI_DEVICE_IN_REQTYPE,SIO_READ_EEPROM_REQUEST, 0, i,
+ buf+(i*2), 2, ftdi->usb_read_timeout) != 2)
ftdi_error_return(-1, "reading eeprom failed");
}
+ if (ftdi->type == TYPE_R)
+ ftdi->eeprom->size = 0x80;
+ /* Guesses size of eeprom by comparing halves
+ - will not work with blank eeprom */
+ else if (strrchr((const char *)buf, 0xff) == ((const char *)buf
+FTDI_MAX_EEPROM_SIZE -1))
+ ftdi->eeprom->size = -1;
+ else if (memcmp(buf,&buf[0x80],0x80) == 0)
+ ftdi->eeprom->size = 0x80;
+ else if (memcmp(buf,&buf[0x40],0x40) == 0)
+ ftdi->eeprom->size = 0x40;
+ else
+ ftdi->eeprom->size = 0x100;
return 0;
}
@@ -2730,61 +3386,57 @@ 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.
+ Write eeprom location
\param ftdi pointer to ftdi_context
- \param eeprom Pointer to store eeprom into
- \param maxsize the size of the buffer to read into
+ \param eeprom_addr Address of eeprom location to be written
+ \param eeprom_val Value to be written
- \retval -1: eeprom read failed
+ \retval 0: all fine
+ \retval -1: write failed
\retval -2: USB device unavailable
- \retval >=0: size of eeprom
+ \retval -3: Invalid access to checksum protected area below 0x80
+ \retval -4: Device can't access unprotected area
+ \retval -5: Reading chip type failed
*/
-int ftdi_read_eeprom_getsize(struct ftdi_context *ftdi, unsigned char *eeprom,
int maxsize)
+int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr,
+ unsigned short eeprom_val)
{
- int i=0,j,minsize=32;
- int size=minsize;
+ int chip_type_location;
+ unsigned short chip_type;
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
- do
- {
- for (j = 0; i < maxsize/2 && j<size; j++)
- {
- 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, "eeprom read failed");
- i++;
- }
- size*=2;
- }
- while (size<=maxsize && memcmp(eeprom,&eeprom[size/2],size/2)!=0);
+ if (eeprom_addr <0x80)
+ ftdi_error_return(-2, "Invalid access to checksum protected area
below 0x80");
- return size/2;
-}
-/**
- Write eeprom location
-
- \param ftdi pointer to ftdi_context
- \param eeprom_addr Address of eeprom location to be written
- \param eeprom_val Value to be written
+ switch (ftdi->type)
+ {
+ case TYPE_BM:
+ case TYPE_2232C:
+ chip_type_location = 0x14;
+ break;
+ case TYPE_2232H:
+ case TYPE_4232H:
+ chip_type_location = 0x18;
+ break;
+ default:
+ ftdi_error_return(-4, "Device can't access unprotected area");
+ }
- \retval 0: all fine
- \retval -1: read failed
- \retval -2: USB device unavailable
-*/
-int ftdi_write_eeprom_location(struct ftdi_context *ftdi, int eeprom_addr,
unsigned short eeprom_val)
-{
- if (ftdi == NULL || ftdi->usb_dev == NULL)
- ftdi_error_return(-2, "USB device unavailable");
+ if (ftdi_read_eeprom_location( ftdi, chip_type_location>>1, &chip_type))
+ ftdi_error_return(-5, "Reading failed failed");
+ fprintf(stderr," loc 0x%04x val 0x%04x\n", chip_type_location,chip_type);
+ if ((chip_type & 0xff) != 0x66)
+ {
+ ftdi_error_return(-6, "EEPROM is not of 93x66");
+ }
if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
- SIO_WRITE_EEPROM_REQUEST, eeprom_val,
eeprom_addr,
- NULL, 0, ftdi->usb_write_timeout) != 0)
+ SIO_WRITE_EEPROM_REQUEST, eeprom_val,
eeprom_addr,
+ NULL, 0, ftdi->usb_write_timeout) != 0)
ftdi_error_return(-1, "unable to write eeprom");
return 0;
@@ -2794,19 +3446,20 @@ int ftdi_write_eeprom_location(struct ftdi_context
*ftdi, int eeprom_addr, unsig
Write eeprom
\param ftdi pointer to ftdi_context
- \param eeprom Pointer to read eeprom from
\retval 0: all fine
\retval -1: read failed
\retval -2: USB device unavailable
*/
-int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom)
+int ftdi_write_eeprom(struct ftdi_context *ftdi)
{
unsigned short usb_val, status;
int i, ret;
+ unsigned char *eeprom;
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
+ eeprom = ftdi->eeprom->buf;
/* These commands were traced while running MProg */
if ((ret = ftdi_usb_reset(ftdi)) != 0)
@@ -2816,7 +3469,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;
@@ -2839,15 +3492,63 @@ int ftdi_write_eeprom(struct ftdi_context *ftdi,
unsigned char *eeprom)
\retval 0: all fine
\retval -1: erase failed
\retval -2: USB device unavailable
+ \retval -3: Writing magic failed
+ \retval -4: Read EEPROM failed
+ \retval -5: Unexpected EEPROM value
*/
+#define MAGIC 0x55aa
int ftdi_erase_eeprom(struct ftdi_context *ftdi)
{
+ unsigned short eeprom_value;
if (ftdi == NULL || ftdi->usb_dev == NULL)
ftdi_error_return(-2, "USB device unavailable");
- if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
SIO_ERASE_EEPROM_REQUEST, 0, 0, NULL, 0, ftdi->usb_write_timeout) < 0)
+ if (ftdi->type == TYPE_R)
+ {
+ ftdi->eeprom->chip = 0;
+ return 0;
+ }
+
+ if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
SIO_ERASE_EEPROM_REQUEST,
+ 0, 0, NULL, 0, ftdi->usb_write_timeout) < 0)
ftdi_error_return(-1, "unable to erase eeprom");
+
+ /* detect chip type by writing 0x55AA as magic at word position 0xc0
+ Chip is 93x46 if magic is read at word position 0x00, as wraparound
happens around 0x40
+ Chip is 93x56 if magic is read at word position 0x40, as wraparound
happens around 0x80
+ Chip is 93x66 if magic is only read at word position 0xc0*/
+ if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
+ SIO_WRITE_EEPROM_REQUEST, MAGIC, 0xc0,
+ NULL, 0, ftdi->usb_write_timeout) != 0)
+ ftdi_error_return(-3, "Writing magic failed");
+ if (ftdi_read_eeprom_location( ftdi, 0x00, &eeprom_value))
+ ftdi_error_return(-4, "Reading failed failed");
+ if (eeprom_value == MAGIC)
+ {
+ ftdi->eeprom->chip = 0x46;
+ }
+ else
+ {
+ if (ftdi_read_eeprom_location( ftdi, 0x40, &eeprom_value))
+ ftdi_error_return(-4, "Reading failed failed");
+ if (eeprom_value == MAGIC)
+ ftdi->eeprom->chip = 0x56;
+ else
+ {
+ if (ftdi_read_eeprom_location( ftdi, 0xc0, &eeprom_value))
+ ftdi_error_return(-4, "Reading failed failed");
+ if (eeprom_value == MAGIC)
+ ftdi->eeprom->chip = 0x66;
+ else
+ {
+ ftdi->eeprom->chip = -1;
+ }
+ }
+ }
+ if (libusb_control_transfer(ftdi->usb_dev, FTDI_DEVICE_OUT_REQTYPE,
SIO_ERASE_EEPROM_REQUEST,
+ 0, 0, NULL, 0, ftdi->usb_write_timeout) < 0)
+ ftdi_error_return(-1, "unable to erase eeprom");
return 0;
}
diff --git a/src/ftdi.h b/src/ftdi.h
index 86e4c62..b7c0113 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -2,7 +2,7 @@
ftdi.h - description
-------------------
begin : Fri Apr 4 2003
- copyright : (C) 2003 by Intra2net AG
+ copyright : (C) 2003-2011 by Intra2net AG and the libftdi
developers
email : opensource@xxxxxxxxxxxxx
***************************************************************************/
@@ -19,7 +19,8 @@
#include <libusb.h>
-#define FTDI_DEFAULT_EEPROM_SIZE 128
+/* Even on 93xx66 at max 256 bytes are used (AN_121)*/
+#define FTDI_MAX_EEPROM_SIZE 256
/** FTDI chip type */
enum ftdi_chip_type { TYPE_AM=0, TYPE_BM=1, TYPE_2232C=2, TYPE_R=3,
TYPE_2232H=4, TYPE_4232H=5 };
@@ -168,6 +169,96 @@ struct ftdi_transfer_control
};
/**
+ \brief FTDI eeprom structure
+*/
+struct ftdi_eeprom
+{
+ /** vendor id */
+ int vendor_id;
+ /** product id */
+ int product_id;
+
+ /** self powered */
+ int self_powered;
+ /** remote wakeup */
+ int remote_wakeup;
+
+ int is_not_pnp;
+
+ /* Suspend on DBUS7 Low */
+ int suspend_dbus7;
+
+ /** input in isochronous transfer mode */
+ int in_is_isochronous;
+ /** output in isochronous transfer mode */
+ int out_is_isochronous;
+ /** suspend pull downs */
+ int suspend_pull_downs;
+
+ /** use serial */
+ int use_serial;
+ /** usb version */
+ int usb_version;
+ /** Use usb version on FT2232 devices*/
+ int use_usb_version;
+ /** maximum power */
+ int max_power;
+
+ /** manufacturer name */
+ char *manufacturer;
+ /** product name */
+ char *product;
+ /** serial number */
+ char *serial;
+
+ /* 2232D/H(/FT4432H?) specific */
+ /* Hardware type, 0 = RS232 Uart, 1 = 245 FIFO, 2 = CPU FIFO,
+ 4 = OPTO Isolate */
+ int channel_a_type;
+ int channel_b_type;
+ /* Driver Type, 1 = VCP */
+ int channel_a_driver;
+ int channel_b_driver;
+
+ /* Special function of FT232R devices (and possibly others as well) */
+ /** CBUS pin function. See CBUS_xxx defines. */
+ int cbus_function[5];
+ /** Select hight current drive on R devices. */
+ int high_current;
+ /** Select hight current drive on A channel (2232C */
+ int high_current_a;
+ /** Select hight current drive on B channel (2232C). */
+ int high_current_b;
+ /** Select inversion of data lines (bitmask). */
+ int invert;
+
+ /*2232H/4432H Group specific values */
+ /* Group0 is AL on 2322H and A on 4232H
+ Group1 is AH on 2232H and B on 4232H
+ Group2 is BL on 2322H and C on 4232H
+ Group3 is BH on 2232H and C on 4232H*/
+ int group0_drive;
+ int group0_schmitt;
+ int group0_slew;
+ int group1_drive;
+ int group1_schmitt;
+ int group1_slew;
+ int group2_drive;
+ int group2_schmitt;
+ int group2_slew;
+ int group3_drive;
+ int group3_schmitt;
+ int group3_slew;
+
+ /** eeprom size in bytes. This doesn't get stored in the eeprom
+ but is the only way to pass it to ftdi_eeprom_build. */
+ int size;
+ /* EEPROM Type 0x46 for 93xx46, 0x56 for 93xx56 and 0x66 for 93xx66*/
+ int chip;
+ unsigned char buf[FTDI_MAX_EEPROM_SIZE];
+};
+
+/**
\brief Main context structure for all libftdi functions.
Do not access directly if possible.
@@ -217,14 +308,61 @@ struct ftdi_context
/** Bitbang mode. 1: (default) Normal bitbang mode, 2: FT2232C SPI bitbang
mode */
unsigned char bitbang_mode;
- /** EEPROM size. Default is 128 bytes for 232BM and 245BM chips */
- int eeprom_size;
+ /** Decoded eeprom structure */
+ struct ftdi_eeprom *eeprom;
/** String representation of last error */
char *error_str;
};
/**
+ List all handled EEPROM values.
+ Append future new values only at the end to provide API/ABI stability*/
+enum ftdi_eeprom_value
+{
+ VENDOR_ID = 0,
+ PRODUCT_ID = 1,
+ SELF_POWERED = 2,
+ REMOTE_WAKEUP = 3,
+ IS_NOT_PNP = 4,
+ SUSPEND_DBUS7 = 5,
+ IN_IS_ISOCHRONOUS = 6,
+ OUT_IS_ISOCHRONOUS = 7,
+ SUSPEND_PULL_DOWNS = 8,
+ USE_SERIAL = 9,
+ USB_VERSION = 10,
+ USE_USB_VERSION = 11,
+ MAX_POWER = 12,
+ CHANNEL_A_TYPE = 13,
+ CHANNEL_B_TYPE = 14,
+ CHANNEL_A_DRIVER = 15,
+ CHANNEL_B_DRIVER = 16,
+ CBUS_FUNCTION_0 = 17,
+ CBUS_FUNCTION_1 = 18,
+ CBUS_FUNCTION_2 = 19,
+ CBUS_FUNCTION_3 = 20,
+ CBUS_FUNCTION_4 = 21,
+ HIGH_CURRENT = 22,
+ HIGH_CURRENT_A = 23,
+ HIGH_CURRENT_B = 24,
+ INVERT = 25,
+ GROUP0_DRIVE = 26,
+ GROUP0_SCHMITT = 27,
+ GROUP0_SLEW = 28,
+ GROUP1_DRIVE = 29,
+ GROUP1_SCHMITT = 30,
+ GROUP1_SLEW = 31,
+ GROUP2_DRIVE = 32,
+ GROUP2_SCHMITT = 33,
+ GROUP2_SLEW = 34,
+ GROUP3_DRIVE = 35,
+ GROUP3_SCHMITT = 36,
+ GROUP3_SLEW = 37,
+ CHIP_SIZE = 38,
+ CHIP_TYPE = 39
+};
+
+/**
\brief list of usb devices created by ftdi_usb_find_all()
*/
struct ftdi_device_list
@@ -235,33 +373,11 @@ struct ftdi_device_list
struct libusb_device *dev;
};
-/** TXDEN */
-#define CBUS_TXDEN 0
-/** PWREN# */
-#define CBUS_PWREN 1
-/** RXLED# */
-#define CBUS_RXLED 2
-/** TXLED#*/
-#define CBUS_TXLED 3
-/** RXLED# & TXLED# */
-#define CBUS_TXRXLED 4
-/** SLEEP# */
-#define CBUS_SLEEP 5
-/** 48 MHz clock */
-#define CBUS_CLK48 6
-/** 24 MHz clock */
-#define CBUS_CLK24 7
-/** 12 MHz clock */
-#define CBUS_CLK12 8
-/** 6 MHz clock */
-#define CBUS_CLK6 9
-/** Bitbang IO Mode*/
-#define CBUS_IOMODE 10
-/** Bitbang IO WR#*/
-#define CBUS_BB_WR 11
-/** Bitbang IO RD#*/
-#define CBUS_BB_RD 12
-
+#define USE_SERIAL_NUM 0x08
+enum ftdi_cbus_func {/* FIXME: Recheck value, especially the last */
+ CBUS_TXDEN = 0, CBUS_PWREN = 1, CBUS_RXLED = 2, CBUS_TXLED = 3,
CBUS_TXRXLED = 4,
+ CBUS_SLEEP = 5, CBUS_CLK48 = 6, CBUS_CLK24 = 7, CBUS_CLK12 = 8, CBUS_CLK6
= 9,
+ CBUS_IOMODE = 0xa, CBUS_BB_WR = 0xb, CBUS_BB_RD = 0xc, CBUS_BB = 0xd};
/** Invert TXD# */
#define INVERT_TXD 0x01
@@ -280,61 +396,29 @@ struct ftdi_device_list
/** Invert RI# */
#define INVERT_RI 0x80
-/** High current drive. */
-#define HIGH_CURRENT_DRIVE 0x04
+/** Interface Mode. */
+#define CHANNEL_IS_UART 0x0
+#define CHANNEL_IS_245 0x1
+#define CHANNEL_IS_CPU 0x2
+#define CHANNEL_IS_OPTO 0x4
-/**
- \brief FTDI eeprom structure
-*/
-struct ftdi_eeprom
-{
- /** vendor id */
- int vendor_id;
- /** product id */
- int product_id;
-
- /** self powered */
- int self_powered;
- /** remote wakeup */
- int remote_wakeup;
- /** chip type */
- int chip_type;
-
- /** input in isochronous transfer mode */
- int in_is_isochronous;
- /** output in isochronous transfer mode */
- int out_is_isochronous;
- /** suspend pull downs */
- int suspend_pull_downs;
+#define DRIVE_4MA 0
+#define DRIVE_8MA 1
+#define DRIVE_12MA 2
+#define DRIVE_16MA 3
+#define SLOW_SLEW 4
+#define IS_SCHMITT 8
- /** use serial */
- int use_serial;
- /** fake usb version */
- int change_usb_version;
- /** usb version */
- int usb_version;
- /** maximum power */
- int max_power;
+/** Driver Type. */
+#define DRIVER_VCP 0x08
- /** manufacturer name */
- char *manufacturer;
- /** product name */
- char *product;
- /** serial number */
- char *serial;
+#define USE_USB_VERSION_BIT 0x10
- /* Special function of FT232R devices (and possibly others as well) */
- /** CBUS pin function. See CBUS_xxx defines. */
- int cbus_function[5];
- /** Select hight current drive. */
- int high_current;
- /** Select inversion of data lines (bitmask). */
- int invert;
+#define SUSPEND_DBUS7_BIT 0x80
- /** eeprom size in bytes. This doesn't get stored in the eeprom
- but is the only way to pass it to ftdi_eeprom_build. */
- int size;
-};
+/** High current drive. */
+#define HIGH_CURRENT_DRIVE 0x10
+#define HIGH_CURRENT_DRIVE_R 0x04
/**
\brief Progress Info for streaming read
@@ -437,21 +521,21 @@ extern "C"
int ftdi_set_event_char(struct ftdi_context *ftdi, unsigned char eventch,
unsigned char enable);
int ftdi_set_error_char(struct ftdi_context *ftdi, unsigned char errorch,
unsigned char enable);
- /* set eeprom size */
- void ftdi_eeprom_setsize(struct ftdi_context *ftdi, struct ftdi_eeprom
*eeprom, int size);
+ /* init eeprom for the given FTDI type */
+ int ftdi_eeprom_initdefaults(struct ftdi_context *ftdi,
+ char * manufacturer, char *product,
+ char * serial);
+ int ftdi_eeprom_build(struct ftdi_context *ftdi);
+ int ftdi_eeprom_decode(struct ftdi_context *ftdi, int verbose);
+
+ int ftdi_get_eeprom_value(struct ftdi_context *ftdi, enum
ftdi_eeprom_value value_name, int* value);
+ int ftdi_set_eeprom_value(struct ftdi_context *ftdi, enum
ftdi_eeprom_value value_name, int value);
- /* init and build eeprom from ftdi_eeprom structure */
- void ftdi_eeprom_initdefaults(struct ftdi_eeprom *eeprom);
- void ftdi_eeprom_free(struct ftdi_eeprom *eeprom);
- int ftdi_eeprom_build(struct ftdi_eeprom *eeprom, unsigned char *output);
- int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom, unsigned char *output,
int size);
+ int ftdi_get_eeprom_buf(struct ftdi_context *ftdi, unsigned char * buf,
int size);
- /* "eeprom" needs to be valid 128 byte eeprom (generated by the eeprom
generator)
- the checksum of the eeprom is valided */
- int ftdi_read_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom);
+ int ftdi_read_eeprom(struct ftdi_context *ftdi);
int ftdi_read_chipid(struct ftdi_context *ftdi, unsigned int *chipid);
- int ftdi_read_eeprom_getsize(struct ftdi_context *ftdi, unsigned char
*eeprom, int maxsize);
- int ftdi_write_eeprom(struct ftdi_context *ftdi, unsigned char *eeprom);
+ int ftdi_write_eeprom(struct ftdi_context *ftdi);
int ftdi_erase_eeprom(struct ftdi_context *ftdi);
int ftdi_read_eeprom_location (struct ftdi_context *ftdi, int eeprom_addr,
unsigned short *eeprom_val);
hooks/post-receive
--
port libftdi to libusb-1.0
--
libftdi-git - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi-git+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx
|