FreeCalypso > hg > fc-usbser-tools
view fteeprom/ftee-gen2232c.c @ 106:de3b299561b3
udev: add rules file that works on my system
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 05 Oct 2023 01:08:28 +0000 |
parents | 66cbbd7d85cf |
children |
line wrap: on
line source
/* * This program constructs a configuration EEPROM image for FT2232C/D chips * 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> #include <unistd.h> extern FILE *open_eeprom_config_file(); char *configfile, *serial; u_short vid = 0x0403, pid = 0x6010; char *manuf, *product; u_char byte00 = 0x08, byte01 = 0x08; u_char byte08 = 0x80, byte0A = 0x00; unsigned maxpower = 100; u_short usb_version = 0x0200; u_short eeprom[128]; u_char eeprom_chip = 0x46, eeprom_chip_cmdline; unsigned eeprom_size, eeprom_string_ptr; static void process_cmdline(argc, argv) char **argv; { int c; extern int optind; while ((c = getopt(argc, argv, "bBs")) != EOF) { switch (c) { case 'b': eeprom_chip = eeprom_chip_cmdline = 0x56; continue; case 'B': eeprom_chip = eeprom_chip_cmdline = 0x66; continue; case 's': eeprom_chip = eeprom_chip_cmdline = 0x46; continue; default: /* error msg already printed */ exit(1); } } if (argc < optind + 1 || argc > optind + 2) { fprintf(stderr, "usage: %s [options] config-file [serial-num]\n", argv[0]); exit(1); } configfile = argv[optind]; serial = argv[optind+1]; } 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, "FT2232C")) return; if (!strcasecmp(arg, "FT2232D")) return; if (!strcasecmp(arg, "FT2232x")) return; fprintf(stderr, "%s line %d: config is for wrong FTDI chip\n", filename_for_errs, lineno); exit(1); } static void eeprom_setting(arg, filename_for_errs, lineno) char *arg, *filename_for_errs; { take_one_arg(arg); if (!strcasecmp(arg, "93C46")) eeprom_chip = 0x46; else if (!strcasecmp(arg, "93C56")) eeprom_chip = 0x56; else if (!strcasecmp(arg, "93C66")) eeprom_chip = 0x66; else { fprintf(stderr, "%s line %d: invalid eeprom setting\n", filename_for_errs, lineno); exit(1); } if (eeprom_chip_cmdline && eeprom_chip_cmdline != eeprom_chip) { fprintf(stderr, "%s line %d: eeprom setting disagrees with command line option\n", filename_for_errs, lineno); exit(1); } } static void read_config_file() { FILE *inf; char linebuf[1024]; int lineno; char *cp, *np; inf = open_eeprom_config_file(configfile); if (!inf) { perror(configfile); 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", configfile, 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", configfile, 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, "maxpower")) maxpower = strtoul(cp, 0, 10); else if (!strcmp(np, "usbver")) usb_version = strtoul(cp, 0, 16); else if (!strcmp(np, "ftdi-chip")) ftdi_chip_setting(cp, configfile, lineno); else if (!strcmp(np, "eeprom")) eeprom_setting(cp, configfile, lineno); else { fprintf(stderr, "%s line %d: unknown \"%s\" setting\n", configfile, lineno, np); exit(1); } } fclose(inf); if (!manuf) { fprintf(stderr, "error: manuf not set in %s\n", configfile); exit(1); } if (!product) { fprintf(stderr, "error: product not set in %s\n", configfile); exit(1); } } static void init_eeprom_size() { if (eeprom_chip == 0x46) { eeprom_size = 64; eeprom_string_ptr = 0x0B; } else { eeprom_size = 128; eeprom_string_ptr = 0x4B; } } static int write_string(str) char *str; { unsigned longlen, startptr; if (eeprom_size - 1 - 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() { 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] = 0x0500; eeprom[4] = (byte09 << 8) | byte08; eeprom[5] = 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] = eeprom_chip; } static void do_checksum() { u_short chksum = 0xAAAA; unsigned n; for (n = 0; n < eeprom_size - 1; n++) { chksum ^= eeprom[n]; chksum = (chksum << 1) | (chksum >> 15); } eeprom[n] = chksum; } static void emit_output() { unsigned n, col; for (n = 0; n < eeprom_size; 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; { process_cmdline(argc, argv); read_config_file(); init_eeprom_size(); fill_eeprom(); do_checksum(); emit_output(); exit(0); }