The branch, eeprom-new has been updated
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 97c6b5f63d77f28968f4ad19c6901f11598898c9 (commit)
- Log -----------------------------------------------------------------
commit 10186c1fa4b660a1fed39b66f1fa2ad9cfe29b19
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 17 15:15:14 2010 +0200
Write to EEPROM direct when trying to detect EEPROM size
commit e27531f4c4b739744c48872eb5f940883d207ab6
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 16 11:55:20 2010 +0200
Warn user about missing FT4232H-specific EEPROM settings
commit 398d7b972ecf5c933d3487da4bac543ba2859fe9
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 16 11:49:05 2010 +0200
examples/eeprom.c: Remove unused variable
commit b4d19dead949a262c14af0a4515e7fbceac69373
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 15 17:33:39 2010 +0200
EEPROM: Add missing closing brace
commit d45d6648ad017652e18aefc65c1300c5392b2f8e
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 15 17:32:48 2010 +0200
EEPROM: Null out buffer after allocation
commit 6e6a1c3fab17eceb680cae1b01d027030ed1e728
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 15 17:31:01 2010 +0200
FT2232H: Handle suspend_pull_downs when encoding
commit a886436ae0a98e39376383b176f05382009290e7
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 15 16:19:53 2010 +0200
Decoded max_power is in mA and 90 mA for TYPE_R and 100mA else
commit c6b94478680a22e4659431773f67e361fb6c527c
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 15 13:20:31 2010 +0200
Fix decoding of FT(2|4)232H channel A type
commit 0091182efcba6f7369b678e429ac936296997aa2
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 17:11:47 2010 +0200
Add option to write eeprom
commit a661e3e44b5df0dd84ddd1a5396a880a0063fe67
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 17:05:38 2010 +0200
ftdi_write_eeprom_location access to checksum protected area will produce
checksum errors, so check - access is about byte 0xff - eeprom chip is of type
93c66, so high area exists - ftdi device can handle 93c66
commit bf2f6ef7f73ba0a1bf3f04db4435ce2014231ba3
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 16:07:56 2010 +0200
use_serial is used in all devices beside AM types. So move out of the
switch(ftdi->type) construct
commit bb5ec68a9a7e2218b0e5852d62e878201dd4d653
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 15:50:54 2010 +0200
max_power eeprom value is in 2 mA Steps
commit 802a949e535f479b694ee04d49c071900314ce91
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 15:49:55 2010 +0200
Use the PNP flag as seen with FTD2XX
commit f14f84d3ab33c785903e5b4fb615076f9cbcefad
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 15:21:16 2010 +0200
Document ftdi_eeprom_initdefaults Add return value to
ftdi_eeprom_initdefaults
commit 74e8e79d4e311001d0f890cdf0219d84b58bb70a
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 15:11:47 2010 +0200
Handle manufacturer/product/serial strings internal Set these string as
arguments to ftdi_eeprom_build Remove exported function ftdi_eeprom_free
commit a35aa9bdfbb149efe72c32727a0ebfe3585465f8
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Tue Sep 14 14:46:02 2010 +0200
Provide internal eeprom structure buffer with internal byte buffer Purge
external eeprom structure buffer and eeprom read/write byte buffer from API
commit f38b0866c6725ff41e23dcef0d0da7ea0ece2031
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Mon Sep 13 16:57:32 2010 +0200
Use allocated ftdi structure
commit 4fb2ebbb87a4bdb1ca3e2d7768c87f7a228fe784
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 23:20:48 2010 +0200
Initialize use_defaults
commit 13f00d3cd7a7cef13df7b1ecc0b0f0c678456cca
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 23:20:05 2010 +0200
Correct the CBUS decode string arrays
commit 2db3a766fd94a852d95f46efadf3a0dacccd29f5
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 22:54:39 2010 +0200
Example for the EEPROM API
commit 7345e9551c75957b19de981846bc975c487dee09
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 22:41:35 2010 +0200
Add description of EEPROM Structure as decoded by now. Please comment!
commit a49800437bffd7b155971f0a51316644deee8ba5
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 22:40:29 2010 +0200
Fix and verbose decode of TYPE_R CBUS functions and pin inversion
commit 38801bf8af278a43149862ab7a07128f8c4d5aab
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:59:40 2010 +0200
Release values in EEPROM structure are not user changable. Remove it from
the ftdi_eeprom structure
commit 2c2953e66c7167e76fe64633435a5b232a8efc40
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:56:07 2010 +0200
CBUS Mus has 0xd as highest number
commit cbf65673d6b8d20707b029eaac1e44b28f667c3d
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:55:36 2010 +0200
Add a lost comment
commit 3802140cfb91928c3a168ea42d62c61d1c69cb32
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:53:20 2010 +0200
Build EEPROM type specific bytes and bites in a switch construct
commit 93738c7952c0ed4b83a459ae2ab9054dc2f7bfad
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:47:55 2010 +0200
Fix writing the strings
commit f75bf1391d34f5dfd8b277030f314758cacf4ed7
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:40:28 2010 +0200
when building the eeprom image, use the actual determined eeprom size
commit 6123f7abcc98374ffcfa00bf5eb3bfe9062ada50
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:38:28 2010 +0200
Set eeprom->release when building the eeprom content from the chip type Add
releases for TYPE_2232H and TYPE_4232H
commit eb498cffdb0283ab81756a99ff31fb92690c2c4c
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:36:11 2010 +0200
eeprom->channel_a_type must be initialized
commit aa099f46f01d68f020796b4e5806b3bde7d6e03f
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 21:35:44 2010 +0200
Fix logic flow after
commit 2cde7c524141286c424de68e46710f9e3dbf838d
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 19:35:58 2010 +0200
Next try to get the VCP/D2XX logic right. TYPE_R in inverted
commit ca41c8ee8dcc93a431fbc0b6746b5ea246d511f9
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 15:34:04 2010 +0200
A set bit means load D2XX driver. Revers logic and names
commit 71ba2c2cc274bbe898f4a00b0cd175439ea6609f
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 15:27:25 2010 +0200
Get the test on TYPE_R for unexpected In-Endpoint sizes right
commit 87f66e30002a1d48b7f1b835944c0dc4342ff077
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 15:25:31 2010 +0200
TYPE_E EEPROM Byte 1 bit 4 is expected to be IN Endpoint size Request user
feedback if unexpected values seen
commit 75388926b7825ede2b111e86ab8d003b95d8d554
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 15:18:28 2010 +0200
EEPROM bit for high current IO seems at different bits for TYPE_R and
TYPE_2232C
commit b1859923f302ce55de34bbd74538c72b5aef47f5
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 14:47:48 2010 +0200
The USB Version seems to be always set in EEPROM EEPROM byte[0x0a] bit 4
(change_usb_version) was never seen set. Remove it and request user report if
ever seen set
commit 53c7c901d93038e5357caf52d460a65b3148e4bf
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 14:06:28 2010 +0200
Temporary remove CBUS settings
commit b641e5ee64bf900594fede686f34f66c76802760
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 13:31:17 2010 +0200
max_power EEPROM default is 100 mA
commit 2b9a3c8226573d507149b8ca6e5a925229dd691d
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 13:24:57 2010 +0200
ftdi_eeprom_build needs to know EEPROM chip type
commit 99404ad5ac076785991e179d3ce9332857a0ca7f
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 13:20:37 2010 +0200
When erasing EEPROM, detect chip type (none,internal,93xc46|56|66)
commit 6cd4f92217aa33f3b8c6c304ceeb893ec913c71c
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 12:41:00 2010 +0200
Decode connected chip
commit 1cd815ad0747825fc41829d4a668a235a715bafa
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 11:32:47 2010 +0200
max_power in mA is EEPROM[0x09]*2
commit 7e76a5ef2b1022adab883bf1202c34d3f6b4b2c2
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 11:21:54 2010 +0200
FT2232C has version 0x0500 in EEPROM as default
commit 6855afda867f75e0265d815c411a180a0abc139b
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 11:20:08 2010 +0200
Comprare ftdi->type and do not set it in EEPROM Structure initialization
commit e5d95e9cf85c2b19b30c224cfe6c65d29b041e82
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 11:17:46 2010 +0200
All x232 type have (at least) two USB channels
commit f456288064f8a671c6a2125f3fabb6c1ae5cf250
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 11:16:52 2010 +0200
EEPROM Size check must cope with different types
commit 45619eaa83e12b54afa2b4b4cd67b8293778dcb9
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 11:09:38 2010 +0200
Define the CBUS Multiplexer as an ENUM
commit a02587d5f941d4e7fe8397e3615325251162dedd
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 00:55:00 2010 +0200
Revisit eeprom_initdefualts Symbolic constant for USE_SERIAL_NUM
commit fb9bfdd1a9d3256cf8e729b5f8827d23a5a6b9b5
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 00:25:06 2010 +0200
More verbosity for remote wake up, pull low and suspend on dbus7
commit 02e4a740e847307c069bf0f58b24c72d6f239183
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Fri Sep 10 00:24:00 2010 +0200
Evaluate eeprom Byte 0 Bit 7: Suspend on DBUS7 low
commit db099ec562c4e0199c6ec2c71020612e3623f036
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 23:33:11 2010 +0200
Decode the x232H specific port functions
commit e107f5092fa731fad1aa900b5c736fcb97c76d47
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 23:10:42 2010 +0200
Fix channel mode specific bits, noisy output
commit 2938669c3789b6587f6db2fa2192706d6d830580
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 23:03:46 2010 +0200
Channel Mode is encoded in bits 0..2, VCP is bit 3 Noisy decode
commit 308f1fa790ebee51f6a4d2f5dd4ed3611745489b
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 22:41:51 2010 +0200
EEPROM: Evaluate the channel specific settings
commit 3d7ba8719da16c784a3c6e13c5976810073ff8bb
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 22:32:39 2010 +0200
EEPROM: Fix typos around high_cuttent_drive and make code comipile again.
Will care for initializing and encoding later
commit 85394e6249329e13fd8530a5aeb72355c5340d62
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 22:29:16 2010 +0200
EEPROM High current bit is byte 0 Bit 4 for a and Byte 1 bit 4 for b
commit 49a6bc10a1c75b1595572e67910c53e09752a6f2
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 22:15:21 2010 +0200
On FT2232D, eeprom->change_usb_version was not set with changed version
commit 07851949856f2d82e71ce5be0c62f8f51d5cd506
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 22:10:47 2010 +0200
EEPROM: CBUS functions only work on TYPE_R devices
commit cecb9cb2c8bb9d7c71ae4a5c21c45203148afe0e
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Thu Sep 9 22:07:50 2010 +0200
WWPROM: Invert datalines only works on FT232R
commit d60d79c508f57f711a2375b1c154023d58581563
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 19:43:30 2010 +0200
Remove forgotten print formatter
commit 947d9552b56eb04ad630e88a4c99a3668e8f4873
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 19:41:40 2010 +0200
Fill out control structure for EEPROM decoding
commit 42ae7c628196dcda467ece62d2f4e04bc77bc8c4
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 19:13:21 2010 +0200
Fix a wrong argument
commit 8d3fe5c92a771cb501084d17c6ff49904d5c43d9
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 19:12:50 2010 +0200
Unconditionally set/reset eeprom values
commit 84ec032f8e8d467b87419a32435c120276d9a1ca
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 19:07:48 2010 +0200
When reading EEPROM strings, clip active, as rollover doesn't work for the
FT2232R
commit 065edc587bed136ef4a1cca5980f116c69e9ae00
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 19:07:15 2010 +0200
Add missing clause
commit f6ef2983ec626387a30502e0369ef4d79cb1bdce
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 19:01:39 2010 +0200
On request, dump arguments during EEPROM decoding
commit 564b271685e24105db5c69a10bbc682efd90e919
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 18:16:59 2010 +0200
Chip Type dependend code must be evaluated type dependant
commit 642f94997c2614312fb371c6a3712b4c6bc5d0c0
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 18:08:17 2010 +0200
EEPROM [6] and [7] seems more used like a release variable. Name accordingly
commit efc843050e8d0eaef34cef36db7c4acfec7830ff
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 17:57:18 2010 +0200
EEPROM[02] is VID, so high_current must be defined somewhere else
commit acc1fa05ce669aa2c5f35b51053d9ca59ffd392b
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 17:55:00 2010 +0200
On 93xx46, the Manufacturer/Product/Vendor Pointer gets clipped anyways, so
don't clip to get things right on 93xx56 and 93x66 Only write strings if
allocation succeeded
commit 8080d2ceab3809d25d5bc6799dce499e068308d8
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 16:11:19 2010 +0200
Don't erase the EEPROM size
commit f5b8b5b3b28340d1ae710a8d2af0192ab1d28a02
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 16:10:41 2010 +0200
Remove dead code.
commit f2cd9fd5d8cac4ca8c94e4f5e6560b4967c87be5
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 16:02:48 2010 +0200
For EEPROM decoding, use the evaluated EEPROM size. FT223R is special case,
as the EEPROM holds more information than is used for the checksum
commit 1bc78a0512f5909dcbe974a901f6ccd94c2a974b
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 16:01:32 2010 +0200
Remove ftdi_eeprom_getsize also from the CPP Wrapper
commit 2d543486ed96287e3d0f8f33d82321dfc2f835d0
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 15:50:06 2010 +0200
Remove ftdi_read_eeprom_getsize() function. Integrate in into the
ftdi_read_eeprom() function. On ftdi_eeprom_write() another approach is needed
commit 3d6d20c0add502b5c93c1bda8331711262791440
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 15:16:54 2010 +0200
We need to handle at max 256 Bytes on an attached 93xx66 EEPROM
commit 6e73861dd69c21fd9eb56095f09ff2baaca8694c
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 14:58:43 2010 +0200
Correct ftdi_eeprom_free()
commit cc9c9d58811e9efb38d274b5ce3baacfedd0b5d6
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 13:16:33 2010 +0200
Use ftdi_error_return for EEPROM error returns
commit c0a96aed965e1010f131aaac4d7025ebf00c35dd
Author: Uwe Bonnes <bon@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Date: Wed Sep 8 12:00:31 2010 +0200
Let the eeprom functions work on the ftdi_context, not the ftdi_eeprom
structure
-----------------------------------------------------------------------
Summary of changes:
bindings/ftdi.i | 6 +-
doc/EEPROM-structure | 89 ++++
examples/CMakeLists.txt | 2 +
examples/eeprom.c | 207 ++++++++++
ftdipp/ftdi.cpp | 20 +-
ftdipp/ftdi.hpp | 4 +-
src/ftdi.c | 1028 ++++++++++++++++++++++++++++++++---------------
src/ftdi.h | 217 ++++++-----
8 files changed, 1137 insertions(+), 436 deletions(-)
create mode 100644 doc/EEPROM-structure
create mode 100644 examples/eeprom.c
diff --git a/bindings/ftdi.i b/bindings/ftdi.i
index 1fc2a59..6e56cfe 100644
--- a/bindings/ftdi.i
+++ b/bindings/ftdi.i
@@ -39,12 +39,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..731c559
--- /dev/null
+++ b/doc/EEPROM-structure
@@ -0,0 +1,89 @@
+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 | VID-LSB(all)
+03 | VID-MSB(all)
+04 | PID-LSB(all)
+05 | PID-MSB(all)
+06 | REL-LSB (not tested on TYPE_AM, TYPE_BM and TYPE_4232H)
+07 | REL-MSB (not tested on TYPE_AM, TYPE_BM and TYPE_4232H)
+ |
+08.4 | Self-Wakeup
+08.5 | Remote-Wakeup
+08.6 | Self-Powered
+08.7 | Always 1
+ |
+09 | MaxPower(maA/2)
+ |
+Byte.BIT| TYPE_AM TYPE_BM TYPE_2232C TYPE_R TYPE_2232H
TYPE_4232H
+0a.0 | 0 IsoIn
+0a.1 | 0 IsoOut
+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
+ |
+0b | TYPE_R Bitmask Invert, 0 else
+
+Byte | TYPE_AM TYPE_BM TYPE_2232C TYPE_R TYPE_2232H
TYPE_4232H
+0c | ? USB-VER-LSB USB-VER-LSB 0 ? ?
+0d | ? USB-VER-MSB USB-VER-MSB 0 ? ?
+On several FT2232H different values were observed
+
+
+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
+
+17 UA UA UA 0 0 0
+18 UA UA UA VENDOR CHIP CHIP
+19 UA UA UA VENDOR 0 0
+
+1a UA(all)
+
+Mprog doesn's seem to write this:
+After last string
+0x02 0x03 0x01 with PnP == 0
\ No newline at end of file
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/eeprom.c b/examples/eeprom.c
new file mode 100644
index 0000000..be34db2
--- /dev/null
+++ b/examples/eeprom.c
@@ -0,0 +1,207 @@
+/* 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;
+ 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;
+
+ 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-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);
+ if (f < 0)
+ {
+ fprintf(stderr, "Erase failed: %s",
+ ftdi_get_error_string(ftdi));
+ return -2;
+ }
+ if (ftdi->eeprom->chip == -1)
+ fprintf(stderr, "No EEPROM\n");
+ else if (ftdi->eeprom->chip == 0)
+ fprintf(stderr, "Internal EEPROM\n");
+ else
+ fprintf(stderr, "Found 93x%02x\n",ftdi->eeprom->chip);
+ return 0;
+ }
+
+ if(use_defaults)
+ {
+ ftdi_eeprom_initdefaults(ftdi, "IKDA", "FTDIJTAF", "0001");
+ ftdi->eeprom->max_power = 500;
+ 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");
+ ftdi->eeprom->max_power = 500;
+ f = ftdi_erase_eeprom(ftdi);
+ if (ftdi->eeprom->chip == -1)
+ fprintf(stderr, "No EEPROM\n");
+ else if (ftdi->eeprom->chip == 0)
+ fprintf(stderr, "Internal EEPROM\n");
+ else
+ fprintf(stderr, "Found 93x%02x\n",ftdi->eeprom->chip);
+ 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);
+ }
+ }
+
+
+ fprintf(stderr, "Chip type %d ftdi_eeprom_size: %d\n", ftdi->type,
ftdi->eeprom->size);
+ buf = ftdi->eeprom->buf;
+ if (ftdi->type == TYPE_R)
+ size = 0xa0;
+ else
+ size = ftdi->eeprom->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/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 6cb8f93..2ac4bc2 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/src/ftdi.c b/src/ftdi.c
index 30b5b55..654a8ac 100644
--- a/src/ftdi.c
+++ b/src/ftdi.c
@@ -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;
@@ -101,7 +103,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);
}
@@ -2153,91 +2179,94 @@ 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 eeprom Pointer to ftdi_eeprom
+ \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
+
+ \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 -1: eeprom size (128 bytes) exceeded by custom strings
@@ -2245,17 +2274,32 @@ void ftdi_eeprom_free(struct ftdi_eeprom *eeprom)
\retval -3: Invalid cbus function setting
\retval -4: Chip doesn't support invert
\retval -5: Chip doesn't support high current drive
+ \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, k;
unsigned short checksum, value;
unsigned char manufacturer_size = 0, product_size = 0, serial_size = 0;
int size_check;
- const int cbus_max[5] = {13, 13, 13, 13, 9};
+ struct ftdi_eeprom *eeprom;
+ 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(-5,"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);
@@ -2264,43 +2308,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)
+ size_check = 0x80;
+ switch(ftdi->type)
{
- if (eeprom->invert) return -4;
- if (eeprom->high_current) return -5;
+ case TYPE_2232H:
+ case TYPE_4232H:
+ size_check -= 4;
+ case TYPE_R:
+ size_check -= 4;
+ case TYPE_2232C:
+ size_check -= 4;
+ case TYPE_AM:
+ case TYPE_BM:
+ size_check -= 0x14*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;
+ /* Space for the string type and pointer bytes */
+ size_check -= -9;
+
// eeprom size exceeded?
if (size_check < 0)
return (-1);
// 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;
@@ -2311,7 +2349,7 @@ 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;
@@ -2324,6 +2362,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;
}
@@ -2341,102 +2385,254 @@ 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;
-
- // 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;
+ output[0x09] = eeprom->max_power>>1;
+
+ if(ftdi->type != TYPE_AM)
+ {
+ // 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;
+ }
- // 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)
+ // 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)
{
- output[0x0C] = eeprom->usb_version;
- output[0x0D] = eeprom->usb_version >> 8;
+ 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) */
+ k = 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++ & k] = manufacturer_size*2 + 2;
+ output[i++ & k] = 0x03; // type: string
+ for (j = 0; j < manufacturer_size; j++)
+ {
+ output[i & k] = eeprom->manufacturer[j], i++;
+ output[i & k] = 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 & k] = product_size*2 + 2, i++;
+ output[i & k] = 0x03, i++;
+ for (j = 0; j < product_size; j++)
+ {
+ output[i & k] = eeprom->product[j], i++;
+ output[i & k] = 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 & k] = serial_size*2 + 2, i++;
+ output[i & k] = 0x03, i++;
+ for (j = 0; j < serial_size; j++)
+ {
+ output[i & k] = eeprom->serial[j], i++;
+ output[i & k] = 0x00, i++;
}
- if (eeprom->size >= 256) i = 0x80;
+ output[i & k] = 0x02; /* as seen when written with FTD2XX */
+ i++;
+ output[i & k] = 0x03; /* as seen when written with FTD2XX */
+ i++;
+ output[i & k] = eeprom->is_not_pnp; /* as seen when written with FTD2XX */
+ i++;
+ output[0x13] = serial_size*2 + 2;
- // 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++)
+ if(ftdi->type > TYPE_AM) /*use_serial not used in AM devices*/
{
- output[i] = eeprom->manufacturer[j], i++;
- output[i] = 0x00, i++;
+ if (eeprom->use_serial == USE_SERIAL_NUM )
+ output[0x0A] |= USE_SERIAL_NUM;
+ else
+ output[0x0A] &= ~USE_SERIAL_NUM;
}
+ /* Fixme: ftd2xx seems to append 0x02, 0x03 and 0x01 for PnP = 0 or 0x00
else */
+ // calculate checksum
- // 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++)
+ /* Bytes and Bits specific to (some) types
+ Write linear, as this allows easier fixing*/
+ switch(ftdi->type)
{
- output[i] = eeprom->product[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;
+ output[0x14] = eeprom->chip;
+ 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 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++)
- {
- output[i] = eeprom->serial[j], i++;
- output[i] = 0x00, i++;
+ 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;
+ 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)
+ output[0x01] |= SUSPEND_DBUS7;
+ else
+ output[0x01] &= ~SUSPEND_DBUS7;
+
+ 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
@@ -2460,48 +2656,32 @@ int ftdi_eeprom_build(struct ftdi_eeprom *eeprom,
unsigned char *output)
/**
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
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;
+ int eeprom_size;
+ struct ftdi_eeprom *eeprom;
+ unsigned char *buf = ftdi->eeprom->buf;
+ int release;
- // eeprom size exceeded?
- if (size_check < 0)
- return (-1);
-#endif
-
- // empty eeprom struct
- memset(eeprom, 0, sizeof(struct ftdi_eeprom));
-
- // Addr 00: High current IO
- eeprom->high_current = (buf[0x02] & HIGH_CURRENT_DRIVE);
+ if (ftdi == NULL)
+ ftdi_error_return(-1,"No context");
+ if (ftdi->eeprom == NULL)
+ ftdi_error_return(-1,"No eeprom structure");
+
+ eeprom = ftdi->eeprom;
+ eeprom_size = eeprom->size;
// Addr 02: Vendor ID
eeprom->vendor_id = buf[0x02] + (buf[0x03] << 8);
@@ -2509,31 +2689,15 @@ 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];
@@ -2543,82 +2707,88 @@ int ftdi_eeprom_decode(struct ftdi_eeprom *eeprom,
unsigned char *buf, int size)
// Bit 6: 0 - reserved
// Bit 5: 0 - reserved
// Bit 4: 1 - Change USB version
+ // Not seen on FT2232(D)
// 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;
+ if(buf[0x0A]&0x10)
+ fprintf(stderr,
+ "EEPROM byte[0x0a] Bit 4 unexpected set. If this happened with
the EEPROM\n"
+ "programmed by FTDI tools, please report to
libftdi@xxxxxxxxxxxxxxxxxxxxxxx\n");
- // 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++)
- {
- 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++)
+ if (serial_size > 0)
{
- 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;
@@ -2637,9 +2807,165 @@ 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;
+
+ 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_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"};
+ int i;
+
+ 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
+ fprintf(stdout,"C%d BB Function: %s\n", i,
+ cbus_BB[i]);
+ }
+ }
+ }
return 0;
}
@@ -2669,25 +2995,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;
}
@@ -2743,57 +3084,53 @@ 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,
@@ -2807,19 +3144,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)
@@ -2829,7 +3167,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;
@@ -2852,15 +3190,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..4132d8a 100644
--- a/src/ftdi.h
+++ b/src/ftdi.h
@@ -19,7 +19,8 @@
#include <libusb.h>
-#define FTDI_DEFAULT_EEPROM_SIZE 128
+/* Evne 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,95 @@ 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;
+ /** 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 46 for 93xx46, 56 for 93xx56 and 66 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,8 +307,8 @@ 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;
@@ -235,33 +325,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 +348,27 @@ struct ftdi_device_list
/** Invert RI# */
#define INVERT_RI 0x80
-/** High current drive. */
-#define HIGH_CURRENT_DRIVE 0x04
-
-/**
- \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;
+/** Interface Mode. */
+#define CHANNEL_IS_UART 0x0
+#define CHANNEL_IS_245 0x1
+#define CHANNEL_IS_CPU 0x2
+#define CHANNEL_IS_OPTO 0x4
- /** use serial */
- int use_serial;
- /** fake usb version */
- int change_usb_version;
- /** usb version */
- int usb_version;
- /** maximum power */
- int max_power;
+#define DRIVE_4MA 0
+#define DRIVE_8MA 1
+#define DRIVE_12MA 2
+#define DRIVE_16MA 3
+#define SLOW_SLEW 4
+#define IS_SCHMITT 8
- /** manufacturer name */
- char *manufacturer;
- /** product name */
- char *product;
- /** serial number */
- char *serial;
+/** Driver Type. */
+#define DRIVER_VCP 0x08
- /* 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 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 +471,16 @@ 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 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);
+ /* 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);
- /* "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
|