diff fteeprom/ftee-decode.c @ 65:225dc1d9f2f1

ftee-decode program written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 12 Sep 2023 22:23:30 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fteeprom/ftee-decode.c	Tue Sep 12 22:23:30 2023 +0000
@@ -0,0 +1,133 @@
+/*
+ * 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);
+}