├── .gitignore ├── Changelog ├── LICENSE.txt ├── Makefile ├── debian ├── .gitignore ├── changelog ├── compat ├── control ├── copyright ├── install └── rules └── ft232r_prog.c /.gitignore: -------------------------------------------------------------------------------- 1 | /ft232r_prog 2 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | Version 1.25: (courtesy of David Pello) 2 | -- use inttypes.h for portable int/short/long types and sizes 3 | Version 1.24: (courtesy of Nils Eilers) 4 | -- fixed exit code on success to be 0 instead of EINVAL 5 | -- added --self-powered flag 6 | Version 1.23: 7 | -- added GPLv2 licensing. 8 | Version 1.22: 9 | -- try again to preserve USB version from eeprom. 10 | Version 1.21: 11 | -- preserve USB version from eeprom; libusb no longer does this correctly (sigh). 12 | Version 1.10: 13 | -- now able to invert _all_ the serial and handshake lines (not just DTR). 14 | (courtesy of Jonas Meyer, thanks!) 15 | Version 1.09: 16 | Version 1.08: 17 | -- fix compiler warning from newer gcc 18 | -- Makefile fixes for latest Ubuntu & binutils 19 | Version 1.06: 20 | -- fix libftdi-0.19 API breakage by not using "BM_type_chip" from libftdi0-0.18. 21 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | GNU GENERAL PUBLIC LICENSE 3 | Version 2, June 1991 4 | 5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 6 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | Preamble 11 | 12 | The licenses for most software are designed to take away your 13 | freedom to share and change it. By contrast, the GNU General Public 14 | License is intended to guarantee your freedom to share and change free 15 | software--to make sure the software is free for all its users. This 16 | General Public License applies to most of the Free Software 17 | Foundation's software and to any other program whose authors commit to 18 | using it. (Some other Free Software Foundation software is covered by 19 | the GNU Library General Public License instead.) You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | this service if you wish), that you receive source code or can get it 26 | if you want it, that you can change the software or use pieces of it 27 | in new free programs; and that you know you can do these things. 28 | 29 | To protect your rights, we need to make restrictions that forbid 30 | anyone to deny you these rights or to ask you to surrender the rights. 31 | These restrictions translate to certain responsibilities for you if you 32 | distribute copies of the software, or if you modify it. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must give the recipients all the rights that 36 | you have. You must make sure that they, too, receive or can get the 37 | source code. And you must show them these terms so they know their 38 | rights. 39 | 40 | We protect your rights with two steps: (1) copyright the software, and 41 | (2) offer you this license which gives you legal permission to copy, 42 | distribute and/or modify the software. 43 | 44 | Also, for each author's protection and ours, we want to make certain 45 | that everyone understands that there is no warranty for this free 46 | software. If the software is modified by someone else and passed on, we 47 | want its recipients to know that what they have is not the original, so 48 | that any problems introduced by others will not reflect on the original 49 | authors' reputations. 50 | 51 | Finally, any free program is threatened constantly by software 52 | patents. We wish to avoid the danger that redistributors of a free 53 | program will individually obtain patent licenses, in effect making the 54 | program proprietary. To prevent this, we have made it clear that any 55 | patent must be licensed for everyone's free use or not licensed at all. 56 | 57 | The precise terms and conditions for copying, distribution and 58 | modification follow. 59 | 60 | GNU GENERAL PUBLIC LICENSE 61 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 62 | 63 | 0. This License applies to any program or other work which contains 64 | a notice placed by the copyright holder saying it may be distributed 65 | under the terms of this General Public License. The "Program", below, 66 | refers to any such program or work, and a "work based on the Program" 67 | means either the Program or any derivative work under copyright law: 68 | that is to say, a work containing the Program or a portion of it, 69 | either verbatim or with modifications and/or translated into another 70 | language. (Hereinafter, translation is included without limitation in 71 | the term "modification".) Each licensee is addressed as "you". 72 | 73 | Activities other than copying, distribution and modification are not 74 | covered by this License; they are outside its scope. The act of 75 | running the Program is not restricted, and the output from the Program 76 | is covered only if its contents constitute a work based on the 77 | Program (independent of having been made by running the Program). 78 | Whether that is true depends on what the Program does. 79 | 80 | 1. You may copy and distribute verbatim copies of the Program's 81 | source code as you receive it, in any medium, provided that you 82 | conspicuously and appropriately publish on each copy an appropriate 83 | copyright notice and disclaimer of warranty; keep intact all the 84 | notices that refer to this License and to the absence of any warranty; 85 | and give any other recipients of the Program a copy of this License 86 | along with the Program. 87 | 88 | You may charge a fee for the physical act of transferring a copy, and 89 | you may at your option offer warranty protection in exchange for a fee. 90 | 91 | 2. You may modify your copy or copies of the Program or any portion 92 | of it, thus forming a work based on the Program, and copy and 93 | distribute such modifications or work under the terms of Section 1 94 | above, provided that you also meet all of these conditions: 95 | 96 | a) You must cause the modified files to carry prominent notices 97 | stating that you changed the files and the date of any change. 98 | 99 | b) You must cause any work that you distribute or publish, that in 100 | whole or in part contains or is derived from the Program or any 101 | part thereof, to be licensed as a whole at no charge to all third 102 | parties under the terms of this License. 103 | 104 | c) If the modified program normally reads commands interactively 105 | when run, you must cause it, when started running for such 106 | interactive use in the most ordinary way, to print or display an 107 | announcement including an appropriate copyright notice and a 108 | notice that there is no warranty (or else, saying that you provide 109 | a warranty) and that users may redistribute the program under 110 | these conditions, and telling the user how to view a copy of this 111 | License. (Exception: if the Program itself is interactive but 112 | does not normally print such an announcement, your work based on 113 | the Program is not required to print an announcement.) 114 | 115 | These requirements apply to the modified work as a whole. If 116 | identifiable sections of that work are not derived from the Program, 117 | and can be reasonably considered independent and separate works in 118 | themselves, then this License, and its terms, do not apply to those 119 | sections when you distribute them as separate works. But when you 120 | distribute the same sections as part of a whole which is a work based 121 | on the Program, the distribution of the whole must be on the terms of 122 | this License, whose permissions for other licensees extend to the 123 | entire whole, and thus to each and every part regardless of who wrote it. 124 | 125 | Thus, it is not the intent of this section to claim rights or contest 126 | your rights to work written entirely by you; rather, the intent is to 127 | exercise the right to control the distribution of derivative or 128 | collective works based on the Program. 129 | 130 | In addition, mere aggregation of another work not based on the Program 131 | with the Program (or with a work based on the Program) on a volume of 132 | a storage or distribution medium does not bring the other work under 133 | the scope of this License. 134 | 135 | 3. You may copy and distribute the Program (or a work based on it, 136 | under Section 2) in object code or executable form under the terms of 137 | Sections 1 and 2 above provided that you also do one of the following: 138 | 139 | a) Accompany it with the complete corresponding machine-readable 140 | source code, which must be distributed under the terms of Sections 141 | 1 and 2 above on a medium customarily used for software interchange; or, 142 | 143 | b) Accompany it with a written offer, valid for at least three 144 | years, to give any third party, for a charge no more than your 145 | cost of physically performing source distribution, a complete 146 | machine-readable copy of the corresponding source code, to be 147 | distributed under the terms of Sections 1 and 2 above on a medium 148 | customarily used for software interchange; or, 149 | 150 | c) Accompany it with the information you received as to the offer 151 | to distribute corresponding source code. (This alternative is 152 | allowed only for noncommercial distribution and only if you 153 | received the program in object code or executable form with such 154 | an offer, in accord with Subsection b above.) 155 | 156 | The source code for a work means the preferred form of the work for 157 | making modifications to it. For an executable work, complete source 158 | code means all the source code for all modules it contains, plus any 159 | associated interface definition files, plus the scripts used to 160 | control compilation and installation of the executable. However, as a 161 | special exception, the source code distributed need not include 162 | anything that is normally distributed (in either source or binary 163 | form) with the major components (compiler, kernel, and so on) of the 164 | operating system on which the executable runs, unless that component 165 | itself accompanies the executable. 166 | 167 | If distribution of executable or object code is made by offering 168 | access to copy from a designated place, then offering equivalent 169 | access to copy the source code from the same place counts as 170 | distribution of the source code, even though third parties are not 171 | compelled to copy the source along with the object code. 172 | 173 | 4. You may not copy, modify, sublicense, or distribute the Program 174 | except as expressly provided under this License. Any attempt 175 | otherwise to copy, modify, sublicense or distribute the Program is 176 | void, and will automatically terminate your rights under this License. 177 | However, parties who have received copies, or rights, from you under 178 | this License will not have their licenses terminated so long as such 179 | parties remain in full compliance. 180 | 181 | 5. You are not required to accept this License, since you have not 182 | signed it. However, nothing else grants you permission to modify or 183 | distribute the Program or its derivative works. These actions are 184 | prohibited by law if you do not accept this License. Therefore, by 185 | modifying or distributing the Program (or any work based on the 186 | Program), you indicate your acceptance of this License to do so, and 187 | all its terms and conditions for copying, distributing or modifying 188 | the Program or works based on it. 189 | 190 | 6. Each time you redistribute the Program (or any work based on the 191 | Program), the recipient automatically receives a license from the 192 | original licensor to copy, distribute or modify the Program subject to 193 | these terms and conditions. You may not impose any further 194 | restrictions on the recipients' exercise of the rights granted herein. 195 | You are not responsible for enforcing compliance by third parties to 196 | this License. 197 | 198 | 7. If, as a consequence of a court judgment or allegation of patent 199 | infringement or for any other reason (not limited to patent issues), 200 | conditions are imposed on you (whether by court order, agreement or 201 | otherwise) that contradict the conditions of this License, they do not 202 | excuse you from the conditions of this License. If you cannot 203 | distribute so as to satisfy simultaneously your obligations under this 204 | License and any other pertinent obligations, then as a consequence you 205 | may not distribute the Program at all. For example, if a patent 206 | license would not permit royalty-free redistribution of the Program by 207 | all those who receive copies directly or indirectly through you, then 208 | the only way you could satisfy both it and this License would be to 209 | refrain entirely from distribution of the Program. 210 | 211 | If any portion of this section is held invalid or unenforceable under 212 | any particular circumstance, the balance of the section is intended to 213 | apply and the section as a whole is intended to apply in other 214 | circumstances. 215 | 216 | It is not the purpose of this section to induce you to infringe any 217 | patents or other property right claims or to contest validity of any 218 | such claims; this section has the sole purpose of protecting the 219 | integrity of the free software distribution system, which is 220 | implemented by public license practices. Many people have made 221 | generous contributions to the wide range of software distributed 222 | through that system in reliance on consistent application of that 223 | system; it is up to the author/donor to decide if he or she is willing 224 | to distribute software through any other system and a licensee cannot 225 | impose that choice. 226 | 227 | This section is intended to make thoroughly clear what is believed to 228 | be a consequence of the rest of this License. 229 | 230 | 8. If the distribution and/or use of the Program is restricted in 231 | certain countries either by patents or by copyrighted interfaces, the 232 | original copyright holder who places the Program under this License 233 | may add an explicit geographical distribution limitation excluding 234 | those countries, so that distribution is permitted only in or among 235 | countries not thus excluded. In such case, this License incorporates 236 | the limitation as if written in the body of this License. 237 | 238 | 9. The Free Software Foundation may publish revised and/or new versions 239 | of the General Public License from time to time. Such new versions will 240 | be similar in spirit to the present version, but may differ in detail to 241 | address new problems or concerns. 242 | 243 | Each version is given a distinguishing version number. If the Program 244 | specifies a version number of this License which applies to it and "any 245 | later version", you have the option of following the terms and conditions 246 | either of that version or of any later version published by the Free 247 | Software Foundation. If the Program does not specify a version number of 248 | this License, you may choose any version ever published by the Free Software 249 | Foundation. 250 | 251 | 10. If you wish to incorporate parts of the Program into other free 252 | programs whose distribution conditions are different, write to the author 253 | to ask for permission. For software which is copyrighted by the Free 254 | Software Foundation, write to the Free Software Foundation; we sometimes 255 | make exceptions for this. Our decision will be guided by the two goals 256 | of preserving the free status of all derivatives of our free software and 257 | of promoting the sharing and reuse of software generally. 258 | 259 | NO WARRANTY 260 | 261 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 262 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 263 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 264 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 265 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 266 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 267 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 268 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 269 | REPAIR OR CORRECTION. 270 | 271 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 272 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 273 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 274 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 275 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 276 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 277 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 278 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 279 | POSSIBILITY OF SUCH DAMAGES. 280 | 281 | END OF TERMS AND CONDITIONS 282 | 283 | How to Apply These Terms to Your New Programs 284 | 285 | If you develop a new program, and you want it to be of the greatest 286 | possible use to the public, the best way to achieve this is to make it 287 | free software which everyone can redistribute and change under these terms. 288 | 289 | To do so, attach the following notices to the program. It is safest 290 | to attach them to the start of each source file to most effectively 291 | convey the exclusion of warranty; and each file should have at least 292 | the "copyright" line and a pointer to where the full notice is found. 293 | 294 | 295 | Copyright (C) 296 | 297 | This program is free software; you can redistribute it and/or modify 298 | it under the terms of the GNU General Public License as published by 299 | the Free Software Foundation; either version 2 of the License, or 300 | (at your option) any later version. 301 | 302 | This program is distributed in the hope that it will be useful, 303 | but WITHOUT ANY WARRANTY; without even the implied warranty of 304 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 305 | GNU General Public License for more details. 306 | 307 | You should have received a copy of the GNU General Public License 308 | along with this program; if not, write to the Free Software 309 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 310 | 311 | 312 | Also add information on how to contact you by electronic and paper mail. 313 | 314 | If the program is interactive, make it output a short notice like this 315 | when it starts in an interactive mode: 316 | 317 | Gnomovision version 69, Copyright (C) year name of author 318 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 319 | This is free software, and you are welcome to redistribute it 320 | under certain conditions; type `show c' for details. 321 | 322 | The hypothetical commands `show w' and `show c' should show the appropriate 323 | parts of the General Public License. Of course, the commands you use may 324 | be called something other than `show w' and `show c'; they could even be 325 | mouse-clicks or menu items--whatever suits your program. 326 | 327 | You should also get your employer (if you work as a programmer) or your 328 | school, if any, to sign a "copyright disclaimer" for the program, if 329 | necessary. Here is a sample; alter the names: 330 | 331 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 332 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 333 | 334 | , 1 April 1989 335 | Ty Coon, President of Vice 336 | 337 | This General Public License does not permit incorporating your program into 338 | proprietary programs. If your program is a subroutine library, you may 339 | consider it more useful to permit linking proprietary applications with the 340 | library. If this is what you want to do, use the GNU Library General 341 | Public License instead of this License. 342 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -Wall -O2 -s -Werror 2 | LDFLAGS = -lusb -lftdi -s 3 | PROG = ft232r_prog 4 | 5 | all: $(PROG) 6 | 7 | $(PROG): $(PROG).c 8 | $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) 9 | 10 | clean: 11 | rm -f $(PROG) 12 | -------------------------------------------------------------------------------- /debian/.gitignore: -------------------------------------------------------------------------------- 1 | /files 2 | /ftdi-ft232r.debhelper.log 3 | /ftdi-ft232r.substvars 4 | /ftdi-ft232r 5 | /tmp 6 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | ftdi-ft232r (1.25) unstable; urgency=low 2 | 3 | * Merge changes from upstream. 4 | 5 | -- Ed Swierk Mon, 24 Sep 2018 19:15:02 -0700 6 | 7 | ftdi-ft232r (1.2.4) unstable; urgency=low 8 | 9 | * Initial release. 10 | 11 | -- Ed Swierk Tue, 31 Mar 2015 10:19:02 -0700 12 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: ftdi-ft232r 2 | Section: misc 3 | Priority: optional 4 | Maintainer: Ed Swierk 5 | Build-Depends: debhelper (>= 9), libftdi-dev 6 | Standards-Version: 3.8.4 7 | 8 | Package: ftdi-ft232r 9 | Architecture: any 10 | Depends: ${shlibs:Depends}, ${misc:Depends} 11 | Description: Tool for configuring the FT232R chip 12 | This package provides a tool for reconfiguring the FTDI FT232R chip, 13 | eliminating the need for FTDI's MProg/FTProg (MS-Windows) packages. 14 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Copyright 2010-2013 Mark Lord 2 | -------------------------------------------------------------------------------- /debian/install: -------------------------------------------------------------------------------- 1 | usr/bin/ft232r_prog 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | #export DH_VERBOSE=1 4 | 5 | %: 6 | dh $@ 7 | 8 | override_dh_auto_install: 9 | install -D ft232r_prog debian/tmp/usr/bin/ft232r_prog 10 | -------------------------------------------------------------------------------- /ft232r_prog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ft232r_prog.c by Mark Lord. Copyright 2010-2013. 3 | * 4 | * This is a Linux command-line alternative to the FTDI MProg/FTProg utilities. 5 | * It is known to work only for FT232R chips at this time. 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2, or (at your option) 10 | * any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; see the file LICENSE.txt. If not, write to 19 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #define MYVERSION "1.25" 32 | 33 | static struct ftdi_context ftdi; 34 | static int verbose = 0; 35 | static const char *save_path = NULL, *restore_path = NULL; 36 | 37 | enum cbus_mode { 38 | cbus_txden = 0, 39 | cbus_pwren = 1, 40 | cbus_rxled = 2, 41 | cbus_txled = 3, 42 | cbus_txrxled = 4, 43 | cbus_sleep = 5, 44 | cbus_clk48 = 6, 45 | cbus_clk24 = 7, 46 | cbus_clk12 = 8, 47 | cbus_clk6 = 9, 48 | cbus_io = 10, 49 | cbus_wr = 11, 50 | cbus_rd = 12, 51 | cbus_rxf = 13, 52 | }; 53 | 54 | static const char *cbus_mode_strings[] = { 55 | "TxDEN", 56 | "PwrEn", 57 | "RxLED", 58 | "TxLED", 59 | "TxRxLED", 60 | "Sleep", 61 | "Clk48", 62 | "Clk24", 63 | "Clk12", 64 | "Clk6", 65 | "IO", 66 | "WR", 67 | "RD", 68 | "RxF", 69 | NULL 70 | }; 71 | 72 | enum arg_type { 73 | arg_help, 74 | arg_dump, 75 | arg_verbose, 76 | arg_save, 77 | arg_restore, 78 | arg_cbus0, 79 | arg_cbus1, 80 | arg_cbus2, 81 | arg_cbus3, 82 | arg_cbus4, 83 | arg_manufacturer, 84 | arg_product, 85 | arg_old_serno, 86 | arg_new_serno, 87 | arg_self_powered, 88 | arg_max_bus_power, 89 | arg_high_current_io, 90 | arg_suspend_pull_down, 91 | arg_old_vid, 92 | arg_old_pid, 93 | arg_new_vid, 94 | arg_new_pid, 95 | arg_invert_txd, 96 | arg_invert_rxd, 97 | arg_invert_rts, 98 | arg_invert_cts, 99 | arg_invert_dtr, 100 | arg_invert_dsr, 101 | arg_invert_dcd, 102 | arg_invert_ri, 103 | }; 104 | 105 | static const char *arg_type_strings[] = { 106 | "--help", 107 | "--dump", 108 | "--verbose", 109 | "--save", 110 | "--restore", 111 | "--cbus0", 112 | "--cbus1", 113 | "--cbus2", 114 | "--cbus3", 115 | "--cbus4", 116 | "--manufacturer", 117 | "--product", 118 | "--old-serial-number", 119 | "--new-serial-number", 120 | "--self-powered", 121 | "--max-bus-power", 122 | "--high-current-io", 123 | "--suspend-pull-down", 124 | "--old-vid", 125 | "--old-pid", 126 | "--new-vid", 127 | "--new-pid", 128 | "--invert_txd", 129 | "--invert_rxd", 130 | "--invert_rts", 131 | "--invert_cts", 132 | "--invert_dtr", 133 | "--invert_dsr", 134 | "--invert_dcd", 135 | "--invert_ri", 136 | NULL 137 | }; 138 | 139 | static const char *arg_type_help[] = { 140 | " # (show this help text)", 141 | " # (dump eeprom settings to stdout))", 142 | "# (show debug info and raw eeprom contents)", 143 | " # (save original eeprom contents to file)", 144 | "# (restore initial eeprom contents from file)", 145 | "", 146 | "", 147 | "", 148 | "", 149 | "", 150 | " # (new USB manufacturer string)", 151 | " # (new USB product name string)", 152 | " # (current serial number of device to be reprogrammed)", 153 | " # (new USB serial number string)", 154 | " [on|off] # (self powered)", 155 | " # (max bus current in milli-amperes)", 156 | " [on|off] # (enable high [6mA @ 5V] drive current on CBUS pins)", 157 | "[on|off] # (force I/O pins into logic low state on suspend)", 158 | " # (current vendor id of device to be reprogrammed, eg. 0x0403)", 159 | " # (current product id of device to be reprogrammed, eg. 0x6001)", 160 | " # (new/custom vendor id to be programmed)", 161 | " # (new/custom product id be programmed)", 162 | " Inverts the current value of TXD", 163 | " Inverts the current value of RXD", 164 | " Inverts the current value of RTS", 165 | " Inverts the current value of CTS", 166 | " Inverts the current value of DTR", 167 | " Inverts the current value of DSR", 168 | " Inverts the current value of DCD", 169 | " Inverts the current value of RI", 170 | }; 171 | 172 | static const char *bool_strings[] = { 173 | "off", 174 | "on", 175 | "0", 176 | "1", 177 | "no", 178 | "yes", 179 | "disable", 180 | "enable", 181 | }; 182 | 183 | struct eeprom_fields { 184 | unsigned char byte01; 185 | unsigned char high_current_io; /* bool */ 186 | unsigned char load_d2xx_driver; /* bool */ 187 | unsigned char txd_inverted; /* bool */ 188 | unsigned char rxd_inverted; /* bool */ 189 | unsigned char rts_inverted; /* bool */ 190 | unsigned char cts_inverted; /* bool */ 191 | unsigned char dtr_inverted; /* bool */ 192 | unsigned char dsr_inverted; /* bool */ 193 | unsigned char dcd_inverted; /* bool */ 194 | unsigned char ri_inverted; /* bool */ 195 | unsigned char pnp_enabled; /* bool */ 196 | enum cbus_mode cbus[5]; 197 | unsigned char extras[112]; /* extra, undefined fields */ 198 | struct ftdi_eeprom libftdi; /* stuff known to libftdi */ 199 | unsigned char BM_type_chip; /* from libftdi-0.18, missing in 0.19 */ 200 | 201 | /* These are not actually eeprom values; here for convenience */ 202 | uint16_t old_vid; 203 | uint16_t old_pid; 204 | const char *old_serno; 205 | uint16_t new_vid; 206 | uint16_t new_pid; 207 | }; 208 | 209 | static void dumpmem (const char *msg, void *addr, int len) 210 | { 211 | char *data = addr, hex[3 * 16 + 1], ascii[17]; 212 | uint32_t i, offset = 0; 213 | 214 | if (msg) 215 | printf("%s:\n", msg); 216 | for (i = 0; i < len;) { 217 | uint32_t i16 = i % 16; 218 | unsigned char c = data[i]; 219 | sprintf(hex + (3 * i16), " %02x", c); 220 | ascii[i16] = (c < ' ' || c > '~') ? '.' : c; 221 | if (++i == len || i16 == 15) { 222 | ascii[i16 + 1] = '\0'; 223 | for (; i16 != 15; ++i16) 224 | strcat(hex, " "); 225 | printf("%04x:%s %s\n", offset, hex, ascii); 226 | offset = i; 227 | } 228 | } 229 | } 230 | 231 | static uint16_t calc_crc (void *addr, int len) 232 | { 233 | uint32_t i; 234 | uint16_t crc = 0xaaaa; 235 | unsigned char *d8 = addr; 236 | 237 | for (i = 0; i < len - 2; i += 2) { 238 | crc ^= d8[i] | (d8[i+1] << 8); 239 | crc = (crc << 1) | (crc >> 15); 240 | } 241 | return crc; 242 | } 243 | 244 | static void do_deinit (void) 245 | { 246 | ftdi_deinit(&ftdi); 247 | } 248 | 249 | static void do_close (void) 250 | { 251 | ftdi_usb_close(&ftdi); 252 | } 253 | 254 | static uint16_t verify_crc (void *addr, int len) 255 | { 256 | uint16_t crc = calc_crc(addr, len); 257 | unsigned char *d8 = addr; 258 | uint16_t actual = d8[len-2] | (d8[len-1] << 8); 259 | 260 | if (crc != actual) { 261 | fprintf(stderr, "Bad CRC: crc=0x%04x, actual=0x%04x\n", crc, actual); 262 | exit(EINVAL); 263 | } 264 | if (verbose) printf("CRC: Okay (0x%04x)\n", crc); 265 | return crc; 266 | } 267 | 268 | static uint16_t update_crc (void *addr, int len) 269 | { 270 | uint16_t crc = calc_crc(addr, len); 271 | unsigned char *d8 = addr; 272 | 273 | d8[len-2] = crc; 274 | d8[len-1] = crc >> 8; 275 | return crc; 276 | } 277 | 278 | static int match_arg (const char *arg, const char **possibles) 279 | { 280 | int i; 281 | 282 | for (i = 0; possibles[i]; ++i) { 283 | if (0 == strcasecmp(possibles[i], arg)) 284 | return i; 285 | } 286 | fprintf(stderr, "unrecognized arg: \"%s\"\n", arg); 287 | exit(EINVAL); 288 | return -1; /* never reached */ 289 | } 290 | 291 | static unsigned long unsigned_val (const char *arg, unsigned long max) 292 | { 293 | unsigned long val; 294 | 295 | errno = 0; 296 | val = strtoul(arg, NULL, 0); 297 | if (errno || val > max) { 298 | fprintf(stderr, "%s: bad value (max=0x%lx)\n", arg, max); 299 | exit(EINVAL); 300 | } 301 | return val; 302 | } 303 | 304 | static void ee_dump (struct eeprom_fields *ee) 305 | { 306 | uint32_t c; 307 | 308 | printf(" eeprom_size = %d\n", ee->libftdi.size); 309 | printf(" vendor_id = 0x%04x\n", ee->libftdi.vendor_id); 310 | printf(" product_id = 0x%04x\n", ee->libftdi.product_id); 311 | printf(" self_powered = %d\n", ee->libftdi.self_powered); 312 | printf(" remote_wakeup = %d\n", ee->libftdi.remote_wakeup); 313 | printf("suspend_pull_downs = %d\n", ee->libftdi.suspend_pull_downs); 314 | printf(" max_bus_power = %d mA\n", 2 * ee->libftdi.max_power); 315 | printf(" manufacturer = %s\n", ee->libftdi.manufacturer); 316 | printf(" product = %s\n", ee->libftdi.product); 317 | printf(" serialnum = %s\n", ee->libftdi.serial); 318 | printf(" high_current_io = %u\n", ee->high_current_io); 319 | printf(" load_d2xx_driver = %u\n", ee->load_d2xx_driver); 320 | printf(" txd_inverted = %u\n", ee->txd_inverted); 321 | printf(" rxd_inverted = %u\n", ee->rxd_inverted); 322 | printf(" rts_inverted = %u\n", ee->rts_inverted); 323 | printf(" cts_inverted = %u\n", ee->cts_inverted); 324 | printf(" dtr_inverted = %u\n", ee->dtr_inverted); 325 | printf(" dsr_inverted = %u\n", ee->dsr_inverted); 326 | printf(" dcd_inverted = %u\n", ee->dcd_inverted); 327 | printf(" ri_inverted = %u\n", ee->ri_inverted); 328 | 329 | for (c = 0; c < 5; ++c) 330 | printf(" cbus[%u] = %s\n", c, cbus_mode_strings[ee->cbus[c]]); 331 | 332 | if (verbose) { 333 | /* These fields are non-applicable for FT232R devices */ 334 | printf(" usb_version = %d\n", ee->libftdi.usb_version); 335 | printf(" use_serialnum = %d (n/a)\n", ee->libftdi.use_serial); 336 | printf("change_usb_version = %d (n/a)\n", ee->libftdi.change_usb_version); 337 | printf(" pnp_enabled = %u (n/a)\n", ee->pnp_enabled); 338 | printf(" BM_type_chip = 0x%02x (n/a)\n", ee->BM_type_chip); 339 | printf(" in_is_isochronous = %d (n/a)\n", ee->libftdi.in_is_isochronous); 340 | printf("out_is_isochronous = %d (n/a)\n", ee->libftdi.out_is_isochronous); 341 | } 342 | }; 343 | 344 | static uint32_t calc_extras_offset (unsigned char *eeprom) 345 | { 346 | uint32_t str1 = (eeprom[0x0e] & 0x7f) + eeprom[0x0f]; 347 | uint32_t str2 = (eeprom[0x10] & 0x7f) + eeprom[0x11]; 348 | uint32_t str3 = (eeprom[0x12] & 0x7f) + eeprom[0x13]; 349 | uint32_t offset; 350 | 351 | if (str3 > str2) 352 | offset = (str3 > str1) ? str3 : str1; 353 | else 354 | offset = (str2 > str1) ? str2 : str1; 355 | return offset; 356 | } 357 | 358 | static uint32_t encode_string (void *eeprom, int desc, int offset, char *s) 359 | { 360 | unsigned char c, *u8 = eeprom, slen = (strlen(s) + 1) * 2; 361 | 362 | if (!s || !*s) 363 | return offset; 364 | u8[desc + 0] = offset | 0x80; /* offset of string */ 365 | u8[desc + 1] = slen; /* length */ 366 | 367 | u8[offset++] = slen; /* length */ 368 | u8[offset++] = 0x03; /* "type" == string */ 369 | while ((c = *s++)) { 370 | u8[offset++] = c; 371 | u8[offset++] = 0; 372 | } 373 | return offset; 374 | } 375 | 376 | static void ft232r_eprom_build (struct eeprom_fields *ee, unsigned char *eeprom) 377 | { 378 | uint32_t len = ee->libftdi.size; 379 | int offset = 0x18; 380 | 381 | memset(eeprom, 0, len); 382 | if (strlen(ee->libftdi.serial) > 16) { 383 | fprintf(stderr, "Serial number string exceeds limit of 16 chars, aborting.\n"); 384 | exit(EINVAL); 385 | } 386 | if ((strlen(ee->libftdi.manufacturer) + strlen(ee->libftdi.product) + strlen(ee->libftdi.serial)) > 46) { 387 | fprintf(stderr, "Total string sizes exceed limit of 46 chars, aborting.\n"); 388 | exit(EINVAL); 389 | } 390 | offset = encode_string(eeprom, 0x0e, offset, ee->libftdi.manufacturer); 391 | offset = encode_string(eeprom, 0x10, offset, ee->libftdi.product); 392 | offset = encode_string(eeprom, 0x12, offset, ee->libftdi.serial); 393 | eeprom[0x02] = ee->libftdi.vendor_id; 394 | eeprom[0x03] = ee->libftdi.vendor_id >> 8; 395 | eeprom[0x04] = ee->libftdi.product_id; 396 | eeprom[0x05] = ee->libftdi.product_id >> 8; 397 | eeprom[0x07] = ee->BM_type_chip; 398 | eeprom[0x08] = 0x80; 399 | if (ee->libftdi.remote_wakeup) 400 | eeprom[0x08] |= 0x20; 401 | if (ee->libftdi.self_powered) 402 | eeprom[0x08] |= 0x40; 403 | eeprom[0x09] = ee->libftdi.max_power; 404 | if (ee->libftdi.in_is_isochronous) 405 | eeprom[0x0a] |= 0x01; 406 | if (ee->libftdi.out_is_isochronous) 407 | eeprom[0x0a] |= 0x02; 408 | if (ee->libftdi.suspend_pull_downs) 409 | eeprom[0x0a] |= 0x04; 410 | if (ee->libftdi.use_serial) 411 | eeprom[0x0a] |= 0x08; 412 | if (ee->libftdi.change_usb_version) 413 | eeprom[0x0a] |= 0x10; 414 | eeprom[0x0c] = ee->libftdi.usb_version; 415 | eeprom[0x0d] = ee->libftdi.usb_version >> 8; 416 | } 417 | 418 | /* 419 | * There are some undefined "extra features" bytes after the strings. 420 | * So blindly preserve them from the original eeprom image. 421 | */ 422 | static void ee_encode_extras (unsigned char *eeprom, int len, struct eeprom_fields *ee) 423 | { 424 | uint32_t extras_offset = calc_extras_offset(eeprom); 425 | 426 | memcpy(eeprom + extras_offset, ee->extras, len - extras_offset - 2); 427 | if (ee->pnp_enabled) 428 | eeprom[extras_offset + 2] |= 1; 429 | else 430 | eeprom[extras_offset + 2] &= ~1; 431 | } 432 | 433 | static uint16_t ee_encode (unsigned char *eeprom, int len, struct eeprom_fields *ee) 434 | { 435 | int ret; 436 | 437 | memset(eeprom, 0, len); 438 | ee->libftdi.size = len; 439 | 440 | if (ee->new_vid) 441 | ee->libftdi.vendor_id = ee->new_vid; 442 | if (ee->new_pid) 443 | ee->libftdi.product_id = ee->new_pid; 444 | 445 | /* Unfortunately, ftdi_eeprom_build() is buggy and puts things in the wrong places */ 446 | if (0) { 447 | ret = ftdi_eeprom_build(&ee->libftdi, eeprom); 448 | if (ret < 0) { 449 | fprintf(stderr, "ftdi_eeprom_build() failed, ret=%d\n", ret); 450 | exit(EINVAL); 451 | } 452 | printf("ftdi_eeprom_build() ret=%d\n", ret); 453 | } else { 454 | ft232r_eprom_build(ee, eeprom); 455 | } 456 | eeprom[1] = ee->byte01; 457 | if (ee->high_current_io) 458 | eeprom[0x00] |= 0x04; 459 | if (ee->load_d2xx_driver) 460 | eeprom[0x00] |= 0x08; 461 | if (ee->txd_inverted) 462 | eeprom[0x0b] |= 0x01; 463 | if (ee->rxd_inverted) 464 | eeprom[0x0b] |= 0x02; 465 | if (ee->rts_inverted) 466 | eeprom[0x0b] |= 0x04; 467 | if (ee->cts_inverted) 468 | eeprom[0x0b] |= 0x08; 469 | if (ee->dtr_inverted) 470 | eeprom[0x0b] |= 0x10; 471 | if (ee->dsr_inverted) 472 | eeprom[0x0b] |= 0x20; 473 | if (ee->dcd_inverted) 474 | eeprom[0x0b] |= 0x40; 475 | if (ee->ri_inverted) 476 | eeprom[0x0b] |= 0x80; 477 | eeprom[0x14] = (ee->cbus[1] << 4) | ee->cbus[0]; 478 | eeprom[0x15] = (ee->cbus[3] << 4) | ee->cbus[2]; 479 | eeprom[0x16] = ee->cbus[4]; 480 | ee_encode_extras(eeprom, len, ee); 481 | return update_crc(eeprom, len); 482 | } 483 | 484 | /* 485 | * There are some undefined "extra features" bytes after the strings. 486 | * So blindly preserve them from the original eeprom image. 487 | */ 488 | static void ee_decode_extras (unsigned char *eeprom, int len, struct eeprom_fields *ee) 489 | { 490 | uint32_t extras_offset = calc_extras_offset(eeprom); 491 | 492 | memcpy(ee->extras, eeprom + extras_offset, len - extras_offset - 2); 493 | ee->pnp_enabled = eeprom[extras_offset + 2] & 0x01; 494 | } 495 | 496 | static void ee_decode (unsigned char *eeprom, int len, struct eeprom_fields *ee) 497 | { 498 | memset(ee, 0, sizeof(*ee)); 499 | if (eeprom[0] & 0x04) 500 | ee->high_current_io = 1; 501 | if (eeprom[0x00] & 0x08) 502 | ee->load_d2xx_driver = 1; 503 | ee->byte01 = eeprom[0x01]; 504 | if (eeprom[0x0b] & 0x01) 505 | ee->txd_inverted = 1; 506 | if (eeprom[0x0b] & 0x02) 507 | ee->rxd_inverted = 1; 508 | if (eeprom[0x0b] & 0x04) 509 | ee->rts_inverted = 1; 510 | if (eeprom[0x0b] & 0x08) 511 | ee->cts_inverted = 1; 512 | if (eeprom[0x0b] & 0x10) 513 | ee->dtr_inverted = 1; 514 | if (eeprom[0x0b] & 0x20) 515 | ee->dsr_inverted = 1; 516 | if (eeprom[0x0b] & 0x40) 517 | ee->dcd_inverted = 1; 518 | if (eeprom[0x0b] & 0x80) 519 | ee->ri_inverted = 1; 520 | ee->cbus[0] = eeprom[0x14] & 0xf; 521 | ee->cbus[1] = eeprom[0x14] >> 4; 522 | ee->cbus[2] = eeprom[0x15] & 0xf; 523 | ee->cbus[3] = eeprom[0x15] >> 4; 524 | ee->cbus[4] = eeprom[0x16] & 0xf; 525 | ee_decode_extras(eeprom, len, ee); 526 | 527 | /* Use libftdi to decode the remaining fields, which it knows about */ 528 | if (ftdi_eeprom_decode(&ee->libftdi, eeprom, len)) { 529 | fprintf(stderr, "ftdi_eeprom_decode() failed\n"); 530 | exit(EINVAL); 531 | } 532 | ee->BM_type_chip = eeprom[0x07]; /* buggy ftdi_eeprom_decode() */ 533 | if (eeprom[0x0a] & 0x10) /* more buggy ftdi_eeprom_decode() */ 534 | ee->libftdi.change_usb_version = 1; 535 | else 536 | ee->libftdi.change_usb_version = 0; 537 | ee->libftdi.usb_version = (eeprom[0x0d] << 8) | eeprom[0x0c];; 538 | } 539 | 540 | static const char *myname; 541 | 542 | static void show_help (FILE *fp) 543 | { 544 | int i; 545 | 546 | fprintf(fp, "\nUsage: %s [ ]..\n", myname); 547 | fprintf(fp, "\nwhere must be any of:\n"); 548 | 549 | for (i = 0; arg_type_strings[i]; ++i) { 550 | const char *val = arg_type_help[i]; 551 | fprintf(fp, " %s", arg_type_strings[i]); 552 | if (val) { 553 | if (*val) { 554 | fprintf(fp, " %s", val); 555 | } else { /* cbus args */ 556 | int j; 557 | fprintf(fp, " ["); 558 | for (j = 0; cbus_mode_strings[j];) { 559 | fprintf(fp, "%s", cbus_mode_strings[j]); 560 | if (cbus_mode_strings[++j]) 561 | fprintf(fp, "|"); 562 | } 563 | fprintf(fp, "]"); 564 | } 565 | } 566 | fputc('\n', fp); 567 | } 568 | fputc('\n', fp); 569 | } 570 | 571 | static uint16_t ee_read_and_verify (void *eeprom, int len) 572 | { 573 | if (ftdi_read_eeprom(&ftdi, eeprom)) { 574 | fprintf(stderr, "ftdi_read_eeprom() failed: %s\n", ftdi_get_error_string(&ftdi)); 575 | exit(EIO); 576 | } 577 | return verify_crc(eeprom, len); 578 | } 579 | 580 | static void process_args (int argc, char *argv[], struct eeprom_fields *ee) 581 | { 582 | int i; 583 | 584 | for (i = 1; i < argc;) { 585 | int arg; 586 | arg = match_arg(argv[i++], arg_type_strings); 587 | switch (arg) { 588 | case arg_help: 589 | show_help(stdout); 590 | exit(1); 591 | case arg_dump: 592 | continue; 593 | case arg_verbose: 594 | verbose = 1; 595 | continue; 596 | case arg_invert_txd: 597 | ee->txd_inverted = !ee->txd_inverted; 598 | continue; 599 | case arg_invert_rxd: 600 | ee->rxd_inverted = !ee->rxd_inverted; 601 | continue; 602 | case arg_invert_rts: 603 | ee->rts_inverted = !ee->rts_inverted; 604 | continue; 605 | case arg_invert_cts: 606 | ee->cts_inverted = !ee->cts_inverted; 607 | continue; 608 | case arg_invert_dtr: 609 | ee->dtr_inverted = !ee->dtr_inverted; 610 | continue; 611 | case arg_invert_dsr: 612 | ee->dsr_inverted = !ee->dsr_inverted; 613 | continue; 614 | case arg_invert_dcd: 615 | ee->dcd_inverted = !ee->dcd_inverted; 616 | continue; 617 | case arg_invert_ri: 618 | ee->ri_inverted = !ee->ri_inverted; 619 | continue; 620 | } 621 | if (i == argc) { 622 | fprintf(stderr, "%s: missing %s value\n", argv[i-2], argv[i-1]); 623 | exit(EINVAL); 624 | } 625 | switch (arg) { 626 | case arg_save: 627 | save_path = argv[i++]; 628 | break; 629 | case arg_restore: 630 | restore_path = argv[i++]; 631 | break; 632 | case arg_cbus0: 633 | case arg_cbus1: 634 | case arg_cbus2: 635 | case arg_cbus3: 636 | case arg_cbus4: 637 | ee->cbus[arg - arg_cbus0] = match_arg(argv[i++], cbus_mode_strings); 638 | break; 639 | case arg_manufacturer: 640 | ee->libftdi.manufacturer = argv[i++]; 641 | break; 642 | case arg_product: 643 | ee->libftdi.product = argv[i++]; 644 | break; 645 | case arg_new_serno: 646 | ee->libftdi.serial = argv[i++]; 647 | break; 648 | case arg_high_current_io: 649 | ee->high_current_io = match_arg(argv[i++], bool_strings) & 1; 650 | break; 651 | case arg_self_powered: 652 | ee->libftdi.self_powered = match_arg(argv[i++], bool_strings) & 1; 653 | break; 654 | case arg_max_bus_power: 655 | ee->libftdi.max_power = unsigned_val(argv[i++], 0x1ff) / 2; 656 | break; 657 | case arg_suspend_pull_down: 658 | ee->libftdi.suspend_pull_downs = unsigned_val(argv[i++], 0xff); 659 | break; 660 | case arg_old_vid: 661 | ee->old_vid = unsigned_val(argv[i++], 0xffff); 662 | break; 663 | case arg_old_pid: 664 | ee->old_pid = unsigned_val(argv[i++], 0xffff); 665 | break; 666 | case arg_old_serno: 667 | ee->old_serno = argv[i++]; 668 | break; 669 | case arg_new_vid: 670 | ee->new_vid = unsigned_val(argv[i++], 0xffff); 671 | break; 672 | case arg_new_pid: 673 | ee->new_pid = unsigned_val(argv[i++], 0xffff); 674 | break; 675 | default: 676 | fprintf(stderr, "bad args\n"); 677 | exit(EINVAL); 678 | } 679 | } 680 | } 681 | 682 | static void save_eeprom_to_file (const char *path, void *eeprom, int len) 683 | { 684 | int count, fd = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0644); 685 | 686 | if (fd == -1) { 687 | int err = errno; 688 | perror(path); 689 | exit(err); 690 | } 691 | count = write(fd, eeprom, len); 692 | if (count < 0) { 693 | int err = errno; 694 | perror(path); 695 | exit(err); 696 | } 697 | close(fd); 698 | if (count != len) { 699 | fprintf(stderr, "%s: wrong size, wrote %d/%d bytes\n", path, count, len); 700 | exit(EINVAL); 701 | } 702 | printf("%s: wrote %d bytes\n", path, count); 703 | } 704 | 705 | static void restore_eeprom_from_file (const char *path, void *eeprom, int len, int max) 706 | { 707 | int count, fd = open(path, O_RDONLY); 708 | 709 | if (fd == -1) { 710 | int err = errno; 711 | perror(path); 712 | exit(err); 713 | } 714 | count = read(fd, eeprom, max); 715 | if (count < 0) { 716 | int err = errno; 717 | perror(path); 718 | exit(err); 719 | } 720 | close(fd); 721 | if (count != len ) { 722 | fprintf(stderr, "%s: wrong size, read %d/%d bytes\n", path, count, len); 723 | exit(EINVAL); 724 | } 725 | printf("%s: read %d bytes\n", path, count); 726 | verify_crc(eeprom, len); 727 | } 728 | 729 | int main (int argc, char *argv[]) 730 | { 731 | const char *slash; 732 | unsigned char old[256] = {0,}, new[256] = {0,}; 733 | uint16_t new_crc; 734 | struct eeprom_fields ee; 735 | uint32_t len = 128; 736 | 737 | myname = argv[0]; 738 | slash = strrchr(myname, '/'); 739 | if (slash) 740 | myname = slash + 1; 741 | 742 | printf("\n%s: version %s, by Mark Lord.\n", myname, MYVERSION); 743 | if (argc < 2) { 744 | show_help(stdout); 745 | exit(0); 746 | } 747 | 748 | ftdi_init(&ftdi); 749 | atexit(&do_deinit); 750 | 751 | memset(&ee, 0, sizeof(ee)); 752 | ee.old_vid = 0x0403;; /* default; override with --old_vid arg */ 753 | ee.old_pid = 0x6001; /* default; override with --old_pid arg */ 754 | process_args(argc, argv, &ee); /* handle --help and --old-* args */ 755 | 756 | if (ftdi_usb_open_desc(&ftdi, ee.old_vid, ee.old_pid, NULL, ee.old_serno)) { 757 | fprintf(stderr, "ftdi_usb_open() failed for %04x:%04x:%s %s\n", 758 | ee.old_vid, ee.old_pid, ee.old_serno ? ee.old_serno : "", ftdi_get_error_string(&ftdi)); 759 | exit(ENODEV); 760 | } 761 | atexit(&do_close); 762 | 763 | /* First, read the original eeprom from the device */ 764 | (void) ee_read_and_verify(old, len); 765 | if (verbose) dumpmem("existing eeprom", old, len); 766 | 767 | /* Save old contents to a file, if requested (--save) */ 768 | if (save_path) 769 | save_eeprom_to_file(save_path, old, len); 770 | 771 | /* Restore contents from a file, if requested (--restore) */ 772 | if (restore_path) { 773 | restore_eeprom_from_file(restore_path, new, len, sizeof(new)); 774 | if (verbose) dumpmem(restore_path, new, len); 775 | /* Decode file contents into ee struct */ 776 | ee_decode(new, len, &ee); 777 | } else { 778 | /* Decode eeprom contents into ee struct */ 779 | ee_decode(old, len, &ee); 780 | 781 | /* Reencode without any changes, to ensure we can reconstruct the original eeprom from ee */ 782 | new_crc = ee_encode(new, len, &ee); 783 | if (memcmp(old, new, len)) { 784 | if (verbose) dumpmem("reconstructed eeprom", new, len); 785 | fprintf(stderr, "eeprom reconstruction self-test failed, aborting.\n"); 786 | exit(EINVAL); 787 | } 788 | } 789 | 790 | /* process args, and dump new settings */ 791 | process_args(argc, argv, &ee); /* Handle value-change args */ 792 | ee_dump(&ee); 793 | 794 | /* Build new eeprom image */ 795 | new_crc = ee_encode(new, len, &ee); 796 | 797 | /* If different from original, then write it back to the device */ 798 | if (0 == memcmp(old, new, len)) { 799 | printf("No change from existing eeprom contents.\n"); 800 | } else { 801 | if (verbose) dumpmem("new eeprom", new, len); 802 | printf("Rewriting eeprom with new contents.\n"); 803 | if (ftdi_write_eeprom(&ftdi, new)) { 804 | fprintf(stderr, "ftdi_write_eeprom() failed: %s\n", ftdi_get_error_string(&ftdi)); 805 | exit(EIO); 806 | } 807 | /* Read it back again, and check for differences */ 808 | if (ee_read_and_verify(new, len) != new_crc) { 809 | fprintf(stderr, "Readback test failed, results may be botched\n"); 810 | exit(EINVAL); 811 | } 812 | ftdi_usb_reset(&ftdi); /* reset the device to force it to load the new settings */ 813 | } 814 | return 0; 815 | } 816 | --------------------------------------------------------------------------------