view rvinterf/libprint/gpf_tst.c @ 995:74024eb17e04

fc-loadtool help: improve language regarding 16 MiB flash chips In FC project history, 16 MiB flash originally meant Pirelli DP-L10. Then we got FCDEV3B with the same flash (our own design), but now we are discovering more Calypso devices that used such large flash, both late Calypso era (Sony Ericsson K2x0) as well as much earlier ones (FIC FLUID devices.txt file with 2004 dates, Leonardo+ rev 5). Hence we need to migrate to more generic or neutral language in associated documentation, without giving elevated status to specific examples that drove our early project history.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 03 Dec 2023 21:11:12 +0000
parents 4d2e6a2dd1a1
children
line wrap: on
line source

/*
 * This libprint module (one public function plus many internal subfunctions)
 * implements printing/formatting of GPF TST interface packets, which can be
 * traces, sysprims, protocol stack primitives or unrecognized packet format.
 */

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

static int
basic_checks(rxpkt, rxpkt_len)
	u_char *rxpkt;
	unsigned rxpkt_len;
{
	int i, c;

	if (rxpkt_len < 17)
		return(0);
	/* check version bits in the header byte */
	if ((rxpkt[1] & 0xC0) != 0x80)
		return(0);
	/* check the length */
	c = rxpkt[2] | rxpkt[3] << 8;
	if (c + 4 != rxpkt_len)
		return(0);
	/* ensure that the "from" and "to" are printable ASCII */
	for (i = 8; i < 16; i++) {
		c = rxpkt[i];
		if (c < ' ' || c > '~')
			return(0);
	}
	/* basic checks pass */
	return(1);
}

static int
psprim_extra_checks(rxpkt, rxpkt_len)
	u_char *rxpkt;
	unsigned rxpkt_len;
{
	int i, c;

	if (rxpkt_len < 24)
		return(0);
	/* "original rcvr" field needs to be printable ASCII */
	for (i = 16; i < 20; i++) {
		c = rxpkt[i];
		if (c < ' ' || c > '~')
			return(0);
	}
	/* checks pass */
	return(1);
}

static void
print_malformed(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont)
	u_char *rxpkt;
	unsigned rxpkt_len;
	char *extra_prefix;
	void (*outfunc_head)(), (*outfunc_cont)();
{
	char headline[80];

	sprintf(headline, "%sGPF unrecognized packet format", extra_prefix);
	outfunc_head(headline);
	packet_hex_dump(rxpkt, rxpkt_len, outfunc_cont);
}

static void
print_malloc_fail(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont)
	u_char *rxpkt;
	unsigned rxpkt_len;
	char *extra_prefix;
	void (*outfunc_head)(), (*outfunc_cont)();
{
	char headline[80];

	sprintf(headline, "%sGPF packet, failed malloc in formatting",
		extra_prefix);
	outfunc_head(headline);
	packet_hex_dump(rxpkt, rxpkt_len, outfunc_cont);
}

static int
entity_name_well_formed(p)
	char *p;
{
	int i, len;

	if (!isupper(p[0]))
		return(0);
	for (i = 0; i < 4; i++)
		if (!isalnum(p[i]))
			break;
	len = i;
	for (; i < 4; i++)
		if (p[i] != ' ')
			return(0);
	return(len);
}

static void
print_entity_name(raw, outp)
	char *raw, **outp;
{
	int len;

	len = entity_name_well_formed(raw);
	if (len) {
		sprintf(*outp, "%.*s", len, raw);
		*outp += len;
	} else {
		sprintf(*outp, "\"%.4s\"", raw);
		*outp += 6;
	}
}

static void
print_common_hdr(rxpkt, outp, typestr, extra_prefix)
	u_char *rxpkt;
	char **outp, *typestr, *extra_prefix;
{
	sprintf(*outp, "%sGPF %s id=%02X ts=%02X%02X%02X%02X ", extra_prefix,
		typestr, rxpkt[1], rxpkt[7], rxpkt[6], rxpkt[5], rxpkt[4]);
	*outp = index(*outp, '\0');
	print_entity_name(rxpkt + 8, outp);
	*(*outp)++ = '-';
	*(*outp)++ = '>';
	print_entity_name(rxpkt + 12, outp);
	*(*outp)++ = ' ';
}

static void
format_text(rxpkt, rxpkt_len, start_off, outp)
	u_char *rxpkt;
	unsigned rxpkt_len, start_off;
	char *outp;
{
	*outp++ = '\"';
	safe_print_trace(rxpkt + start_off, rxpkt_len - start_off, outp);
	outp = index(outp, '\0');
	*outp++ = '\"';
	*outp = '\0';
}

static void
format_compressed_trace(rxpkt, rxpkt_len, start_off, outp)
	u_char *rxpkt;
	unsigned rxpkt_len, start_off;
	char *outp;
{
	int i;

	i = start_off + 1;
	sprintf(outp, "%d", rxpkt[i+1] << 8 | rxpkt[i]);
	outp = index(outp, '\0');
	i += 4;
	for (; i < rxpkt_len; i++) {
		sprintf(outp, " %02X", rxpkt[i]);
		outp += 3;
	}
	*outp = '\0';
}

static void
format_trace(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont)
	u_char *rxpkt;
	unsigned rxpkt_len;
	char *extra_prefix;
	void (*outfunc_head)(), (*outfunc_cont)();
{
	char *outbuf, *outp;
	int i;

	outbuf = malloc(rxpkt_len * 4 + strlen(extra_prefix) + 1);
	if (!outbuf) {
		print_malloc_fail(rxpkt, rxpkt_len, extra_prefix, outfunc_head,
				  outfunc_cont);
		return;
	}
	outp = outbuf;
	print_common_hdr(rxpkt, &outp, "trace", extra_prefix);
	i = 16;
	if (rxpkt[i] < 0x20) {
		sprintf(outp, "tc=%02X ", rxpkt[i]);
		outp += 6;
		i++;
	}
	if (rxpkt_len - i >= 5 && rxpkt[i] == '%' &&
	    !rxpkt[i+3] && !rxpkt[i+4])
		format_compressed_trace(rxpkt, rxpkt_len, i, outp);
	else
		format_text(rxpkt, rxpkt_len, i, outp);
	outfunc_head(outbuf);
	free(outbuf);
}

static void
format_sysprim(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont)
	u_char *rxpkt;
	unsigned rxpkt_len;
	char *extra_prefix;
	void (*outfunc_head)(), (*outfunc_cont)();
{
	char *outbuf, *outp;

	outbuf = malloc(rxpkt_len * 4 + strlen(extra_prefix) + 1);
	if (!outbuf) {
		print_malloc_fail(rxpkt, rxpkt_len, extra_prefix, outfunc_head,
				  outfunc_cont);
		return;
	}
	outp = outbuf;
	print_common_hdr(rxpkt, &outp, "sysprim", extra_prefix);
	format_text(rxpkt, rxpkt_len, 16, outp);
	outfunc_head(outbuf);
	free(outbuf);
}

static void
format_psprim(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont)
	u_char *rxpkt;
	unsigned rxpkt_len;
	char *extra_prefix;
	void (*outfunc_head)(), (*outfunc_cont)();
{
	char headline[80];
	char *outp = headline;

	print_common_hdr(rxpkt, &outp, "PSprim", extra_prefix);
	/* original destination */
	*outp++ = '(';
	print_entity_name(rxpkt + 16, &outp);
	*outp++ = ')';
	/* opcode and data length */
	sprintf(outp, " %02X%02X%02X%02X len=%u",
		rxpkt[23], rxpkt[22], rxpkt[21], rxpkt[20], rxpkt_len - 24);
	outfunc_head(headline);
	packet_hex_dump(rxpkt + 24, rxpkt_len - 24, outfunc_cont);
}

void
format_gpf_packet(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont)
	u_char *rxpkt;
	unsigned rxpkt_len;
	char *extra_prefix;
	void (*outfunc_head)(), (*outfunc_cont)();
{
	if (!basic_checks(rxpkt, rxpkt_len)) {
		print_malformed(rxpkt, rxpkt_len, extra_prefix, outfunc_head,
				outfunc_cont);
		return;
	}
	/* dispatch by type */
	switch (rxpkt[1] & 0x30) {
	case 0x10:
		/* PS primitive */
		if (psprim_extra_checks(rxpkt, rxpkt_len))
			format_psprim(rxpkt, rxpkt_len, extra_prefix,
					outfunc_head, outfunc_cont);
		else
			print_malformed(rxpkt, rxpkt_len, extra_prefix,
					outfunc_head, outfunc_cont);
		return;
	case 0x20:
		/* trace */
		format_trace(rxpkt, rxpkt_len, extra_prefix, outfunc_head,
				outfunc_cont);
		return;
	case 0x30:
		/* system primitive */
		format_sysprim(rxpkt, rxpkt_len, extra_prefix, outfunc_head,
				outfunc_cont);
		return;
	default:
		print_malformed(rxpkt, rxpkt_len, extra_prefix, outfunc_head,
				outfunc_cont);
	}
}