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