Add ftdi_eeprom target (currently disabled). Get version info from CMakeLists.txt
[libftdi] / ftdi_eeprom / main.c
1 /***************************************************************************
2                              main.c  -  description
3                            -------------------
4     begin                : Mon Apr  7 12:05:22 CEST 2003
5     copyright            : (C) 2003,2008 by Intra2net AG
6     email                : opensource@intra2net.com
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License version 2 as     *
13  *   published by the Free Software Foundation.                            *
14  *                                                                         *
15  ***************************************************************************/
16
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include <confuse.h>
26 #include <ftdi.h>
27 #include <ftdi_eeprom_version.h>
28
29 int str_to_cbus(char *str, int max_allowed)
30 {
31     #define MAX_OPTION 14
32     const char* options[MAX_OPTION] = {
33      "TXDEN", "PWREN", "RXLED", "TXLED", "TXRXLED", "SLEEP",
34      "CLK48", "CLK24", "CLK12", "CLK6",
35      "IO_MODE", "BITBANG_WR", "BITBANG_RD", "SPECIAL"};
36     int i;
37     max_allowed += 1;
38     if (max_allowed > MAX_OPTION) max_allowed = MAX_OPTION;
39     for (i=0; i<max_allowed; i++) {
40         if (!(strcmp(options[i], str))) {
41             return i;
42         }
43     }
44     printf("WARNING: Invalid cbus option '%s'\n", str);
45     return 0;
46 }
47
48 int main(int argc, char *argv[])
49 {
50     /*
51     configuration options
52     */
53     cfg_opt_t opts[] =
54     {
55         CFG_INT("vendor_id", 0, 0),
56         CFG_INT("product_id", 0, 0),
57         CFG_BOOL("self_powered", cfg_true, 0),
58         CFG_BOOL("remote_wakeup", cfg_true, 0),
59         CFG_STR_LIST("chip_type", "{BM,R,other}", 0),
60         CFG_BOOL("in_is_isochronous", cfg_false, 0),
61         CFG_BOOL("out_is_isochronous", cfg_false, 0),
62         CFG_BOOL("suspend_pull_downs", cfg_false, 0),
63         CFG_BOOL("use_serial", cfg_false, 0),
64         CFG_BOOL("change_usb_version", cfg_false, 0),
65         CFG_INT("usb_version", 0, 0),
66         CFG_INT("max_power", 0, 0),
67         CFG_STR("manufacturer", "Acme Inc.", 0),
68         CFG_STR("product", "USB Serial Converter", 0),
69         CFG_STR("serial", "08-15", 0),
70         CFG_STR("filename", "", 0),
71         CFG_BOOL("flash_raw", cfg_false, 0),
72         CFG_BOOL("high_current", cfg_false, 0),
73         CFG_STR_LIST("cbus0", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
74         CFG_STR_LIST("cbus1", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
75         CFG_STR_LIST("cbus2", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
76         CFG_STR_LIST("cbus3", "{TXDEN,PWREN,RXLED,TXLED,TXRXLED,SLEEP,CLK48,CLK24,CLK12,CLK6,IO_MODE,BITBANG_WR,BITBANG_RD,SPECIAL}", 0),
77         CFG_STR_LIST("cbus4", "{TXDEN,PWRON,RXLED,TXLED,TX_RX_LED,SLEEP,CLK48,CLK24,CLK12,CLK6}", 0),
78         CFG_BOOL("invert_txd", cfg_false, 0),
79         CFG_BOOL("invert_rxd", cfg_false, 0),
80         CFG_BOOL("invert_rts", cfg_false, 0),
81         CFG_BOOL("invert_cts", cfg_false, 0),
82         CFG_BOOL("invert_dtr", cfg_false, 0),
83         CFG_BOOL("invert_dsr", cfg_false, 0),
84         CFG_BOOL("invert_dcd", cfg_false, 0),
85         CFG_BOOL("invert_ri", cfg_false, 0),
86         CFG_END()
87     };
88     cfg_t *cfg;
89
90     /*
91     normal variables
92     */
93     int _read = 0, _erase = 0, _flash = 0;
94     unsigned char eeprom_buf[128];
95     char *filename;
96     int size_check;
97     int i, argc_filename;
98     FILE *fp;
99
100     struct ftdi_context ftdi;
101     struct ftdi_eeprom eeprom;
102
103     printf("\nFTDI eeprom generator v%s\n", EEPROM_VERSION_STRING);
104     printf ("(c) Intra2net AG <opensource@intra2net.com>\n");
105
106     if (argc != 2 && argc != 3)
107     {
108         printf("Syntax: %s [commands] config-file\n", argv[0]);
109         printf("Valid commands:\n");
110         printf("--read-eeprom  Read eeprom and write to -filename- from config-file\n");
111         printf("--erase-eeprom  Erase eeprom\n");
112         printf("--flash-eeprom  Flash eeprom\n");
113         exit (-1);
114     }
115
116     if (argc == 3)
117     {
118         if (strcmp(argv[1], "--read-eeprom") == 0)
119             _read = 1;
120         if (strcmp(argv[1], "--erase-eeprom") == 0)
121             _erase = 1;
122         if (strcmp(argv[1], "--flash-eeprom") == 0)
123             _flash = 1;
124
125         argc_filename = 2;
126     }
127     else
128     {
129         argc_filename = 1;
130     }
131
132     if ((fp = fopen(argv[argc_filename], "r")) == NULL)
133     {
134         printf ("Can't open configuration file\n");
135         exit (-1);
136     }
137     fclose (fp);
138
139     cfg = cfg_init(opts, 0);
140     cfg_parse(cfg, argv[argc_filename]);
141     filename = cfg_getstr(cfg, "filename");
142
143     if (cfg_getbool(cfg, "self_powered") && cfg_getint(cfg, "max_power") > 0)
144         printf("Hint: Self powered devices should have a max_power setting of 0.\n");
145
146     ftdi_init(&ftdi);
147     ftdi_eeprom_initdefaults (&eeprom);
148     eeprom.vendor_id = cfg_getint(cfg, "vendor_id");
149     eeprom.product_id = cfg_getint(cfg, "product_id");
150     char *type = cfg_getstr(cfg, "chip_type");
151     if (!strcmp(type, "BM")) {
152         eeprom.chip_type = TYPE_BM;
153     } else if (!strcmp(type, "R")) {
154         eeprom.chip_type = TYPE_R;
155     } else {
156         eeprom.chip_type = TYPE_AM;
157     }
158
159     eeprom.self_powered = cfg_getbool(cfg, "self_powered");
160     eeprom.remote_wakeup = cfg_getbool(cfg, "remote_wakeup");
161     eeprom.max_power = cfg_getint(cfg, "max_power");
162
163     eeprom.in_is_isochronous = cfg_getbool(cfg, "in_is_isochronous");
164     eeprom.out_is_isochronous = cfg_getbool(cfg, "out_is_isochronous");
165     eeprom.suspend_pull_downs = cfg_getbool(cfg, "suspend_pull_downs");
166
167     eeprom.use_serial = cfg_getbool(cfg, "use_serial");
168     eeprom.change_usb_version = cfg_getbool(cfg, "change_usb_version");
169     eeprom.usb_version = cfg_getint(cfg, "usb_version");
170
171
172     eeprom.manufacturer = cfg_getstr(cfg, "manufacturer");
173     eeprom.product = cfg_getstr(cfg, "product");
174     eeprom.serial = cfg_getstr(cfg, "serial");
175     eeprom.high_current = cfg_getbool(cfg, "high_current");
176     eeprom.cbus_function[0] = str_to_cbus(cfg_getstr(cfg, "cbus0"), 13);
177     eeprom.cbus_function[1] = str_to_cbus(cfg_getstr(cfg, "cbus1"), 13);
178     eeprom.cbus_function[2] = str_to_cbus(cfg_getstr(cfg, "cbus2"), 13);
179     eeprom.cbus_function[3] = str_to_cbus(cfg_getstr(cfg, "cbus3"), 13);
180     eeprom.cbus_function[4] = str_to_cbus(cfg_getstr(cfg, "cbus4"), 9);
181     int invert = 0;
182     if (cfg_getbool(cfg, "invert_rxd")) invert |= INVERT_RXD;
183     if (cfg_getbool(cfg, "invert_txd")) invert |= INVERT_TXD;
184     if (cfg_getbool(cfg, "invert_rts")) invert |= INVERT_RTS;
185     if (cfg_getbool(cfg, "invert_cts")) invert |= INVERT_CTS;
186     if (cfg_getbool(cfg, "invert_dtr")) invert |= INVERT_DTR;
187     if (cfg_getbool(cfg, "invert_dsr")) invert |= INVERT_DSR;
188     if (cfg_getbool(cfg, "invert_dcd")) invert |= INVERT_DCD;
189     if (cfg_getbool(cfg, "invert_ri")) invert |= INVERT_RI;
190     eeprom.invert = invert;
191
192     if (_read > 0 || _erase > 0 || _flash > 0)
193     {
194         i = ftdi_usb_open(&ftdi, eeprom.vendor_id, eeprom.product_id);
195
196         if (i == 0)
197         {
198             printf("EEPROM size: %d\n", ftdi.eeprom_size);
199         }
200         else
201         {
202             printf("Unable to find FTDI devices under given vendor/product id: 0x%X/0x%X\n", eeprom.vendor_id, eeprom.product_id);
203             printf("Error code: %d (%s)\n", i, ftdi_get_error_string(&ftdi));
204             printf("Retrying with default FTDI id.\n");
205
206             i = ftdi_usb_open(&ftdi, 0x0403, 0x6001);
207             if (i != 0)
208             {
209                 printf("Error: %s\n", ftdi.error_str);
210                 exit (-1);
211             }
212         }
213     }
214
215     if (_read > 0)
216     {
217         printf("FTDI read eeprom: %d\n", ftdi_read_eeprom(&ftdi, eeprom_buf));
218
219         ftdi_eeprom_decode(&eeprom, eeprom_buf, ftdi.eeprom_size);
220         /* Debug output */
221         /*
222         const char* chip_types[] = {"other", "BM", "R"};
223         printf("vendor_id = \"%04x\"\n", eeprom.vendor_id);
224         printf("product_id = \"%04x\"\n", eeprom.product_id);
225         printf("chip_type = \"%s\"\n",
226           (eeprom.chip_type > 0x06) || (eeprom.chip_type & 0x01) ? "unknown":
227           chip_types[eeprom.chip_type>>1]);
228         printf("self_powered = \"%s\"\n", eeprom.self_powered?"true":"false");
229         printf("remote_wakeup = \"%s\"\n", eeprom.remote_wakeup?"true":"false");
230         printf("max_power = \"%d\"\n", eeprom.max_power);
231         printf("in_is_isochronous = \"%s\"\n", eeprom.in_is_isochronous?"true":"false");
232         printf("out_is_isochronous = \"%s\"\n", eeprom.out_is_isochronous?"true":"false");
233         printf("suspend_pull_downs = \"%s\"\n", eeprom.suspend_pull_downs?"true":"false");
234         printf("use_serial = \"%s\"\n", eeprom.use_serial?"true":"false");
235         printf("change_usb_version = \"%s\"\n", eeprom.change_usb_version?"true":"false");
236         printf("usb_version = \"%d\"\n", eeprom.usb_version);
237         printf("manufacturer = \"%s\"\n", eeprom.manufacturer);
238         printf("product = \"%s\"\n", eeprom.product);
239         printf("serial = \"%s\"\n", eeprom.serial);
240         */
241
242         if (filename != NULL && strlen(filename) > 0)
243         {
244             FILE *fp = fopen (filename, "wb");
245             fwrite (eeprom_buf, 1, 128, fp);
246             fclose (fp);
247         }
248         else
249         {
250             printf("Warning: Not writing eeprom, you must supply a valid filename\n");
251         }
252
253         goto cleanup;
254     }
255
256     if (_erase > 0)
257     {
258         printf("FTDI erase eeprom: %d\n", ftdi_erase_eeprom(&ftdi));
259     }
260
261     size_check = ftdi_eeprom_build(&eeprom, eeprom_buf);
262
263     if (size_check == -1)
264     {
265         printf ("Sorry, the eeprom can only contain 128 bytes (100 bytes for your strings).\n");
266         printf ("You need to short your string by: %d bytes\n", size_check);
267         goto cleanup;
268     } else if (size_check < 0) {
269         printf ("ftdi_eeprom_build(): error: %d\n", size_check);
270     }
271     else
272     {
273         printf ("Used eeprom space: %d bytes\n", 128-size_check);
274     }
275
276     if (_flash > 0)
277     {
278         if (cfg_getbool(cfg, "flash_raw"))
279         {
280             if (filename != NULL && strlen(filename) > 0)
281             {
282                 FILE *fp = fopen(filename, "rb");
283                 fread(eeprom_buf, 1, 128, fp);
284                 fclose(fp);
285             }
286         }
287         printf ("FTDI write eeprom: %d\n", ftdi_write_eeprom(&ftdi, eeprom_buf));
288     }
289
290     // Write to file?
291     if (filename != NULL && strlen(filename) > 0)
292     {
293         fp = fopen(filename, "w");
294         if (fp == NULL)
295         {
296             printf ("Can't write eeprom file.\n");
297             exit (-1);
298         }
299         else
300             printf ("Writing to file: %s\n", filename);
301
302         fwrite(eeprom_buf, 128, 1, fp);
303         fclose(fp);
304     }
305
306 cleanup:
307     if (_read > 0 || _erase > 0 || _flash > 0)
308     {
309         printf("FTDI close: %d\n", ftdi_usb_close(&ftdi));
310     }
311
312     ftdi_deinit (&ftdi);
313
314     cfg_free(cfg);
315
316     printf("\n");
317     return 0;
318 }