view cp2102/decode_usb_desc.c @ 91:f4a7ac90cf39

cp2102-decode-ee-desc: decode textual ID strings
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 27 Sep 2023 20:46:30 +0000
parents 3bde280f0986
children
line wrap: on
line source

/*
 * This program reads a CP2102 EEPROM image from an Intel HEX file
 * and decodes the USB descriptors portion thereof.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include "cp210x_defs.h"

u_char eeprom[SIZE_EEPROM];

static void
print_device_desc(desc)
	u_char *desc;
{
	printf("  bLength:            %u", desc[0]);
	if (desc[0] != 18)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  bDescriptorType:    0x%02X", desc[1]);
	if (desc[1] != 0x01)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  bcdUSB:             0x%02X%02X\n", desc[3], desc[2]);
	printf("  bDeviceClass:       0x%02X\n", desc[4]);
	printf("  bDeviceSubClass:    0x%02X\n", desc[5]);
	printf("  bDeviceProtocol:    0x%02X\n", desc[6]);
	printf("  bMaxPacketSize0:    %u\n", desc[7]);
	printf("  idVendor:           0x%02X%02X\n", desc[9], desc[8]);
	printf("  idProduct:          0x%02X%02X\n", desc[11], desc[10]);
	printf("  bcdDevice:          0x%02X%02X\n", desc[13], desc[12]);
	printf("  iManufacturer:      %u\n", desc[14]);
	printf("  iProduct:           %u\n", desc[15]);
	printf("  iSerialNumber:      %u\n", desc[16]);
	printf("  bNumConfigurations: %u\n", desc[17]);
}

static void
print_config_desc(desc)
	u_char *desc;
{
	printf("  bLength:             %u", desc[0]);
	if (desc[0] != 9)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  bDescriptorType:     0x%02X", desc[1]);
	if (desc[1] != 0x02)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  wTotalLength:        %u\n", desc[2] | (desc[3] << 8));
	printf("  bNumInterfaces:      %u\n", desc[4]);
	printf("  bConfigurationValue: 0x%02X\n", desc[5]);
	printf("  iConfiguration:      %u\n", desc[6]);
	printf("  bmAttributes:        0x%02X\n", desc[7]);
	printf("  bMaxPower:           0x%02X (%u mA)\n", desc[8], desc[8] * 2);
}

static void
print_interf_desc(desc)
	u_char *desc;
{
	printf("  bLength:            %u", desc[0]);
	if (desc[0] != 9)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  bDescriptorType:    0x%02X", desc[1]);
	if (desc[1] != 0x04)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  bInterfaceNumber:   %u\n", desc[2]);
	printf("  bAlternateSetting:  0x%02X\n", desc[3]);
	printf("  bNumEndpoints:      %u\n", desc[4]);
	printf("  bInterfaceClass:    0x%02X\n", desc[5]);
	printf("  bInterfaceSubClass: 0x%02X\n", desc[6]);
	printf("  bInterfaceProtocol: 0x%02X\n", desc[7]);
	printf("  iInterface:         %u\n", desc[8]);
}

static void
print_endpoint_desc(desc)
	u_char *desc;
{
	printf("  bLength:          %u", desc[0]);
	if (desc[0] != 7)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  bDescriptorType:  0x%02X", desc[1]);
	if (desc[1] != 0x05)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	printf("  bEndpointAddress: 0x%02X\n", desc[2]);
	printf("  bmAttributes:     0x%02X\n", desc[3]);
	printf("  wMaxPacketSize:   %u\n", desc[4] | (desc[5] << 8));
	printf("  bInterval:        %u\n", desc[6]);
}

static void
print_string_desc_0(desc)
	u_char *desc;
{
	printf("  bLength:         %u", desc[0]);
	if (desc[0] > 8)
		fputs(" (too long!)", stdout);
	else if (desc[0] < 2)
		fputs(" (too short!)", stdout);
	else if (desc[0] & 1)
		fputs(" (odd bogon!)", stdout);
	putchar('\n');
	printf("  bDescriptorType: 0x%02X", desc[1]);
	if (desc[1] != 0x03)
		fputs(" (WRONG!)", stdout);
	putchar('\n');
	if (desc[0] < 4)
		return;
	printf("  wLANGID[0]:      0x%04X\n", desc[2] | (desc[3] << 8));
	if (desc[0] < 6)
		return;
	printf("  wLANGID[1]:      0x%04X\n", desc[4] | (desc[5] << 8));
	if (desc[0] < 8)
		return;
	printf("  wLANGID[2]:      0x%04X\n", desc[6] | (desc[7] << 8));
}

static void
print_string_desc(headline, desc, maxlen)
	char *headline;
	u_char *desc;
	unsigned maxlen;
{
	u_char *sp, *endp;
	unsigned uni;

	if (desc[0] < 2 || desc[0] > maxlen || desc[0] & 1 || desc[1] != 0x03) {
		printf("%s INVALID\n", headline);
		return;
	}
	printf("%s \"", headline);
	endp = desc + desc[0];
	for (sp = desc + 2; sp < endp; sp += 2) {
		uni = sp[0] | (sp[1] << 8);
		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 ihex-file\n", argv[0]);
		exit(1);
	}
	read_intel_hex(argv[1]);
	printf("USB device descriptor at 0x3988:\n");
	print_device_desc(eeprom + 0x388);
	printf("USB configuration descriptor at 0x399A:\n");
	print_config_desc(eeprom + 0x39A);
	printf("USB interface descriptor at 0x39A3:\n");
	print_interf_desc(eeprom + 0x3A3);
	printf("USB endpoint descriptor at 0x39AC:\n");
	print_endpoint_desc(eeprom + 0x3AC);
	printf("USB endpoint descriptor at 0x39B3:\n");
	print_endpoint_desc(eeprom + 0x3B3);
	printf("USB string descriptor 0 at 0x3800:\n");
	print_string_desc_0(eeprom + 0x200);
	print_string_desc("Manuf string:  ", eeprom + 0x3C3, 60);
	print_string_desc("Product string:", eeprom + 0x208, 254);
	print_string_desc("Serial# string:", eeprom + 0x307, 128);
	exit(0);
}