814d1246ffeff78a3c48132c47ab6003bfff0028
[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];                  // TODO: Kill this and look for other hardcoded places of 128 bytes
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 (&ftdi, "Acme Inc.", "FTDI Chip", NULL);
148     eeprom = ftdi.eeprom;
149
150     eeprom->vendor_id = cfg_getint(cfg, "vendor_id");
151     eeprom->product_id = cfg_getint(cfg, "product_id");
152     char *type = cfg_getstr(cfg, "chip_type");
153     if (!strcmp(type, "BM")) {
154         ftdi.type = TYPE_BM;
155     } else if (!strcmp(type, "R")) {
156         ftdi.type = TYPE_R;
157     } else {
158         ftdi.type = TYPE_AM;
159     }
160
161     eeprom->self_powered = cfg_getbool(cfg, "self_powered");
162     eeprom->remote_wakeup = cfg_getbool(cfg, "remote_wakeup");
163     eeprom->max_power = cfg_getint(cfg, "max_power");
164
165     eeprom->in_is_isochronous = cfg_getbool(cfg, "in_is_isochronous");
166     eeprom->out_is_isochronous = cfg_getbool(cfg, "out_is_isochronous");
167     eeprom->suspend_pull_downs = cfg_getbool(cfg, "suspend_pull_downs");
168
169     eeprom->use_serial = cfg_getbool(cfg, "use_serial");
170     eeprom->use_usb_version = cfg_getbool(cfg, "change_usb_version");
171     eeprom->usb_version = cfg_getint(cfg, "usb_version");
172
173
174     eeprom->manufacturer = cfg_getstr(cfg, "manufacturer");
175     eeprom->product = cfg_getstr(cfg, "product");
176     eeprom->serial = cfg_getstr(cfg, "serial");
177     eeprom->high_current = cfg_getbool(cfg, "high_current");
178     eeprom->cbus_function[0] = str_to_cbus(cfg_getstr(cfg, "cbus0"), 13);
179     eeprom->cbus_function[1] = str_to_cbus(cfg_getstr(cfg, "cbus1"), 13);
180     eeprom->cbus_function[2] = str_to_cbus(cfg_getstr(cfg, "cbus2"), 13);
181     eeprom->cbus_function[3] = str_to_cbus(cfg_getstr(cfg, "cbus3"), 13);
182     eeprom->cbus_function[4] = str_to_cbus(cfg_getstr(cfg, "cbus4"), 9);
183     int invert = 0;
184     if (cfg_getbool(cfg, "invert_rxd")) invert |= INVERT_RXD;
185     if (cfg_getbool(cfg, "invert_txd")) invert |= INVERT_TXD;
186     if (cfg_getbool(cfg, "invert_rts")) invert |= INVERT_RTS;
187     if (cfg_getbool(cfg, "invert_cts")) invert |= INVERT_CTS;
188     if (cfg_getbool(cfg, "invert_dtr")) invert |= INVERT_DTR;
189     if (cfg_getbool(cfg, "invert_dsr")) invert |= INVERT_DSR;
190     if (cfg_getbool(cfg, "invert_dcd")) invert |= INVERT_DCD;
191     if (cfg_getbool(cfg, "invert_ri")) invert |= INVERT_RI;
192     eeprom->invert = invert;
193
194     if (_read > 0 || _erase > 0 || _flash > 0)
195     {
196         i = ftdi_usb_open(&ftdi, eeprom->vendor_id, eeprom->product_id);
197
198         if (i == 0)
199         {
200             printf("EEPROM size: %d\n", eeprom->size);
201         }
202         else
203         {
204             printf("Unable to find FTDI devices under given vendor/product id: 0x%X/0x%X\n", eeprom->vendor_id, eeprom->product_id);
205             printf("Error code: %d (%s)\n", i, ftdi_get_error_string(&ftdi));
206             printf("Retrying with default FTDI id.\n");
207
208             i = ftdi_usb_open(&ftdi, 0x0403, 0x6001);
209             if (i != 0)
210             {
211                 printf("Error: %s\n", ftdi.error_str);
212                 exit (-1);
213             }
214         }
215     }
216
217     if (_read > 0)
218     {
219         printf("FTDI read eeprom: %d\n", ftdi_read_eeprom(&ftdi));
220
221         ftdi_eeprom_decode(&ftdi, 0);
222         /* Debug output */
223         /*
224         const char* chip_types[] = {"other", "BM", "R"};
225         printf("vendor_id = \"%04x\"\n", eeprom->vendor_id);
226         printf("product_id = \"%04x\"\n", eeprom->product_id);
227         printf("chip_type = \"%s\"\n",
228           (eeprom->chip_type > 0x06) || (eeprom->chip_type & 0x01) ? "unknown":
229           chip_types[eeprom->chip_type>>1]);
230         printf("self_powered = \"%s\"\n", eeprom->self_powered?"true":"false");
231         printf("remote_wakeup = \"%s\"\n", eeprom->remote_wakeup?"true":"false");
232         printf("max_power = \"%d\"\n", eeprom->max_power);
233         printf("in_is_isochronous = \"%s\"\n", eeprom->in_is_isochronous?"true":"false");
234         printf("out_is_isochronous = \"%s\"\n", eeprom->out_is_isochronous?"true":"false");
235         printf("suspend_pull_downs = \"%s\"\n", eeprom->suspend_pull_downs?"true":"false");
236         printf("use_serial = \"%s\"\n", eeprom->use_serial?"true":"false");
237         printf("change_usb_version = \"%s\"\n", eeprom->change_usb_version?"true":"false");
238         printf("usb_version = \"%d\"\n", eeprom->usb_version);
239         printf("manufacturer = \"%s\"\n", eeprom->manufacturer);
240         printf("product = \"%s\"\n", eeprom->product);
241         printf("serial = \"%s\"\n", eeprom->serial);
242         */
243
244         if (filename != NULL && strlen(filename) > 0)
245         {
246             FILE *fp = fopen (filename, "wb");
247             fwrite (eeprom_buf, 1, 128, fp);
248             fclose (fp);
249         }
250         else
251         {
252             printf("Warning: Not writing eeprom, you must supply a valid filename\n");
253         }
254
255         goto cleanup;
256     }
257
258     if (_erase > 0)
259     {
260         printf("FTDI erase eeprom: %d\n", ftdi_erase_eeprom(&ftdi));
261     }
262
263     size_check = ftdi_eeprom_build(&ftdi);
264
265     if (size_check == -1)
266     {
267         printf ("Sorry, the eeprom can only contain 128 bytes (100 bytes for your strings).\n");
268         printf ("You need to short your string by: %d bytes\n", size_check);
269         goto cleanup;
270     } else if (size_check < 0) {
271         printf ("ftdi_eeprom_build(): error: %d\n", size_check);
272     }
273     else
274     {
275         printf ("Used eeprom space: %d bytes\n", 128-size_check);
276     }
277
278     if (_flash > 0)
279     {
280         if (cfg_getbool(cfg, "flash_raw"))
281         {
282             if (filename != NULL && strlen(filename) > 0)
283             {
284                 FILE *fp = fopen(filename, "rb");
285                 fread(eeprom_buf, 1, 128, fp);
286                 fclose(fp);
287             }
288         }
289         printf ("FTDI write eeprom: %d\n", ftdi_write_eeprom(&ftdi));
290     }
291
292     // Write to file?
293     if (filename != NULL && strlen(filename) > 0)
294     {
295         fp = fopen(filename, "w");
296         if (fp == NULL)
297         {
298             printf ("Can't write eeprom file.\n");
299             exit (-1);
300         }
301         else
302             printf ("Writing to file: %s\n", filename);
303
304         fwrite(eeprom_buf, 128, 1, fp);
305         fclose(fp);
306     }
307
308 cleanup:
309     if (_read > 0 || _erase > 0 || _flash > 0)
310     {
311         printf("FTDI close: %d\n", ftdi_usb_close(&ftdi));
312     }
313
314     ftdi_deinit (&ftdi);
315
316     cfg_free(cfg);
317
318     printf("\n");
319     return 0;
320 }