FreeCalypso > hg > fc-usbser-tools
view fteeprom/ftee-gen232r.c @ 100:29bff463402e
doc/CP2102-EEPROM-format: part number byte confirmed
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 28 Sep 2023 05:39:44 +0000 |
parents | 66cbbd7d85cf |
children |
line wrap: on
line source
/* * This program constructs a configuration EEPROM image for an FT232R chip * based on a configuration source file giving various settings. */ #include <sys/types.h> #include <ctype.h> #include <string.h> #include <strings.h> #include <stdio.h> #include <stdlib.h> extern FILE *open_eeprom_config_file(); u_short vid = 0x0403, pid = 0x6001; char *manuf, *product; u_char byte00 = 0x00, byte01 = 0x40; u_char byte08 = 0x80, byte0A = 0x00, byte0B = 0x00; unsigned maxpower = 90; u_short usb_version = 0x0200; u_char cbusconf[5] = {3, 2, 0, 1, 5}; u_short eeprom[64]; unsigned eeprom_string_ptr = 0x0C; static void take_one_arg(arg) char *arg; { char *cp; for (cp = arg; *cp && !isspace(*cp); cp++) ; if (*cp) *cp = '\0'; } static void ftdi_chip_setting(arg, filename_for_errs, lineno) char *arg, *filename_for_errs; { take_one_arg(arg); if (!strcasecmp(arg, "FT232R")) return; fprintf(stderr, "%s line %d: config is for wrong FTDI chip\n", filename_for_errs, lineno); exit(1); } static void read_config_file(filename) char *filename; { FILE *inf; char linebuf[1024]; int lineno; char *cp, *np; inf = open_eeprom_config_file(filename); if (!inf) { perror(filename); exit(1); } for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { cp = index(linebuf, '\n'); if (!cp) { fprintf(stderr, "%s line %d: too long or unterminated\n", filename, lineno); exit(1); } *cp = '\0'; for (cp = linebuf; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') continue; for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: \"%s\" setting without argument\n", filename, lineno, np); exit(1); } if (!strcmp(np, "vid")) vid = strtoul(cp, 0, 16); else if (!strcmp(np, "pid")) pid = strtoul(cp, 0, 16); else if (!strcmp(np, "manuf")) manuf = strdup(cp); else if (!strcmp(np, "product")) product = strdup(cp); else if (!strcmp(np, "byte00")) byte00 = strtoul(cp, 0, 16); else if (!strcmp(np, "byte01")) byte01 = strtoul(cp, 0, 16); else if (!strcmp(np, "byte08")) byte08 = strtoul(cp, 0, 16); else if (!strcmp(np, "byte0A")) byte0A = strtoul(cp, 0, 16); else if (!strcmp(np, "byte0B")) byte0B = strtoul(cp, 0, 16); else if (!strcmp(np, "maxpower")) maxpower = strtoul(cp, 0, 10); else if (!strcmp(np, "usbver")) usb_version = strtoul(cp, 0, 16); else if (!strcmp(np, "cbus0")) cbusconf[0] = strtoul(cp, 0, 16); else if (!strcmp(np, "cbus1")) cbusconf[1] = strtoul(cp, 0, 16); else if (!strcmp(np, "cbus2")) cbusconf[2] = strtoul(cp, 0, 16); else if (!strcmp(np, "cbus3")) cbusconf[3] = strtoul(cp, 0, 16); else if (!strcmp(np, "cbus4")) cbusconf[4] = strtoul(cp, 0, 16); else if (!strcmp(np, "ftdi-chip")) ftdi_chip_setting(cp, filename, lineno); else { fprintf(stderr, "%s line %d: unknown \"%s\" setting\n", filename, lineno, np); exit(1); } } fclose(inf); if (!manuf) { fprintf(stderr, "error: manuf not set in %s\n", filename); exit(1); } if (!product) { fprintf(stderr, "error: product not set in %s\n", filename); exit(1); } } static int write_string(str) char *str; { unsigned longlen, startptr; if (63 - eeprom_string_ptr < strlen(str) + 1) { fprintf(stderr, "error: strings are too long\n"); exit(1); } longlen = strlen(str) * 2 + 2; startptr = eeprom_string_ptr; eeprom[eeprom_string_ptr++] = 0x0300 | longlen; while (*str) eeprom[eeprom_string_ptr++] = *str++; return (longlen << 8) | 0x80 | (startptr << 1); } static void fill_eeprom(serial) char *serial; { u_char byte09; if (serial) byte0A |= 0x08; else byte0A &= 0xF7; byte09 = maxpower / 2; eeprom[0] = (byte01 << 8) | byte00; eeprom[1] = vid; eeprom[2] = pid; eeprom[3] = 0x0600; eeprom[4] = (byte09 << 8) | byte08; eeprom[5] = (byte0B << 8) | byte0A; eeprom[6] = usb_version; eeprom[7] = write_string(manuf); eeprom[8] = write_string(product); if (serial) eeprom[9] = write_string(serial); else eeprom[9] = 0; eeprom[10] = (cbusconf[3] << 12) | (cbusconf[2] << 8) | (cbusconf[1] << 4) | cbusconf[0]; eeprom[11] = cbusconf[4]; } static void do_checksum() { u_short chksum = 0xAAAA; unsigned n; for (n = 0; n < 63; n++) { chksum ^= eeprom[n]; chksum = (chksum << 1) | (chksum >> 15); } eeprom[63] = chksum; } static void emit_output() { unsigned n, col; for (n = 0; n < 64; n++) { col = n & 7; if (col == 0) printf("%02X:", n * 2); printf(" %04X", eeprom[n]); if (col == 7) putchar('\n'); } } main(argc, argv) char **argv; { if (argc < 2 || argc > 3) { fprintf(stderr, "usage: %s config-file [serial-num]\n", argv[0]); exit(1); } read_config_file(argv[1]); fill_eeprom(argv[2]); do_checksum(); emit_output(); exit(0); }