view fteeprom/ftee-gen2232h.c @ 68:5cbde3c80c24

fteeprom-{erase,prog}: detach logic: change to detach by default As it turns out, detaching all ttyUSB interfaces of a multichannel device does not require outside knowledge of how many channels there are, as in our previous -d option design that is being removed here - instead we can read the bNumInterfaces constant from the USB device's config descriptor and thus know how many interfaces there are in total. Based on this discovery, change the design of fteeprom-{erase,prog} as follows: * remove -d option; * flip the default to where we detach all interfaces by default; * add -n option to NOT detach any interfaces.
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 13 Sep 2023 06:37:03 +0000
parents b2c891299e83
children d069e2a6760e
line wrap: on
line source

#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_char group0, group1, group2, group3;

u_short eeprom[128];
u_char eeprom_chip = 0x46;
unsigned eeprom_size, eeprom_string_ptr;

process_cmdline(argc, argv)
	char **argv;
{
	int c;
	extern int optind;

	while ((c = getopt(argc, argv, "bB")) != EOF) {
		switch (c) {
		case 'b':
			eeprom_chip = 0x56;
			continue;
		case 'B':
			eeprom_chip = 0x66;
			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];
}

init_eeprom_size()
{
	if (eeprom_chip == 0x46) {
		eeprom_size = 64;
		eeprom_string_ptr = 0x0D;
	} else {
		eeprom_size = 128;
		eeprom_string_ptr = 0x4D;
	}
}

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, "group0"))
			group0 = strtoul(cp, 0, 16);
		else if (!strcmp(np, "group1"))
			group1 = strtoul(cp, 0, 16);
		else if (!strcmp(np, "group2"))
			group2 = strtoul(cp, 0, 16);
		else if (!strcmp(np, "group3"))
			group3 = strtoul(cp, 0, 16);
		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);
	}
}

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);
}

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] = 0x0700;
	eeprom[4] = (byte09 << 8) | byte08;
	eeprom[5] = byte0A;
	eeprom[6] = (group3 << 12) | (group2 << 8) | (group1 << 4) | group0;
	eeprom[7] = write_string(manuf);
	eeprom[8] = write_string(product);
	if (serial)
		eeprom[9] = write_string(serial);
	else
		eeprom[9] = 0;
	eeprom[12] = eeprom_chip;
}

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;
}

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);
}