view fteeprom/ftee-decode.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 225dc1d9f2f1
children
line wrap: on
line source

/*
 * This program reads an FTDI EEPROM image from a file (or from stdin)
 * and performs some basic decoding on it.  Only the part of the EEPROM
 * structure that is common for all chips is looked at, and only very
 * shallow decoding is performed, without differentiating by FTDI chip
 * type.  Compared to simply studying EEPROM images in raw hex, the main
 * utility of this program is decoding and displaying the three textual
 * ID strings.
 */

#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>

extern unsigned eeprom_size;
extern u_short eeprom[256];

static unsigned useful_size;

static int
verify_eeprom_chksum()
{
	u_short chksum = 0xAAAA;
	unsigned n;

	for (n = 0; n < useful_size; n++) {
		chksum ^= eeprom[n];
		chksum = (chksum << 1) | (chksum >> 15);
	}
	return (chksum == 0);
}

static void
show_string_desc(headline, ptr_word)
	char *headline;
	unsigned ptr_word;
{
	unsigned start_byte, desc_len;
	unsigned start_word, total_words;
	unsigned head_word, nchars;
	u_short *sp;
	unsigned n, uni;

	if (!ptr_word) {
		printf("%s NULL\n", headline);
		return;
	}
	if (ptr_word & 0x0101) {
inv:		printf("%s INVALID\n", headline);
		return;
	}
	start_byte = ptr_word & 0xFF;
	desc_len = ptr_word >> 8;
	if (useful_size == 64)
		start_byte &= 0x7F;
	start_word = start_byte >> 1;
	total_words = desc_len >> 1;
	if (start_word < 10)
		goto inv;
	if (total_words < 1)
		goto inv;
	if (start_word + total_words >= useful_size)
		goto inv;
	head_word = eeprom[start_word];
	if ((head_word & 0xFF) != desc_len)
		goto inv;
	if ((head_word >> 8) != 0x03)
		goto inv;
	nchars = total_words - 1;
	printf("%s \"", headline);
	sp = eeprom + start_word + 1;
	for (n = 0; n < nchars; n++) {
		uni = *sp++;
		if (uni < 0x20 || uni > 0x7E) {
			printf("\\u%04X", uni);
			continue;
		}
		if (uni == '"' || uni == '\\')
			putchar('\\');
		putchar(uni);
	}
	putchar('"');
	putchar('\n');
}

main(argc, argv)
	char **argv;
{
	if (argc != 2) {
		fprintf(stderr, "usage: %s eeprom-image-file\n", argv[0]);
		exit(1);
	}
	if (strcmp(argv[1], "-"))
		read_eeprom_from_file(argv[1]);
	else
		read_eeprom_from_stdin();
	switch (eeprom_size) {
	case 64:
		printf("EEPROM size: 128 bytes (93C46 or FT232R)\n");
		useful_size = 64;
		break;
	case 128:
		printf("EEPROM size: 256 bytes (93C56)\n");
		useful_size = 128;
		break;
	case 256:
		printf("EEPROM size: 512 bytes (93C66)\n");
		useful_size = 128;
		break;
	default:
		fprintf(stderr,
			"BUG: invalid EEPROM size not caught earlier\n");
		exit(1);
	}
	printf("EEPROM checksum is %s\n",
		verify_eeprom_chksum() ? "good" : "BAD!");
	printf("FTDI byte 00: 0x%02X\n", eeprom[0] & 0xFF);
	printf("FTDI byte 01: 0x%02X\n", eeprom[0] >> 8);
	printf("idVendor:     0x%04X\n", eeprom[1]);
	printf("idProduct:    0x%04X\n", eeprom[2]);
	printf("bcdDevice:    0x%04X\n", eeprom[3]);
	printf("bmAttributes: 0x%02X\n", eeprom[4] & 0xFF);
	printf("bMaxPower:    %u mA\n", (eeprom[4] >> 8) * 2);
	printf("FTDI byte 0A: 0x%02X\n", eeprom[5] & 0xFF);
	printf("FTDI byte 0B: 0x%02X\n", eeprom[5] >> 8);
	printf("bcdUSB word:  0x%04X\n", eeprom[6]);
	show_string_desc("Manuf string:  ", eeprom[7]);
	show_string_desc("Product string:", eeprom[8]);
	show_string_desc("Serial# string:", eeprom[9]);
	exit(0);
}