FreeCalypso > hg > fc-usbser-tools
view fteeprom/ftee-decode.c @ 87:4393e1b4b245
cp2102-decode-ee-desc: decode config descriptor
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 27 Sep 2023 19:15:29 +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); }