libftdi-git Archives

Subject: port libftdi to libusb-1.0 branch, eeprom-new, updated. v0.17-126-g10186c1

From: libftdi-git@xxxxxxxxxxxxxxxxxxxxxxx
To: libftdi-git@xxxxxxxxxxxxxxxxxxxxxxx
Date: Mon, 20 Sep 2010 15:45:23 +0200 (CEST)
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   

Current Thread
  • port libftdi to libusb-1.0 branch, eeprom-new, updated. v0.17-126-g10186c1, libftdi-git <=