view ffstools/caltools/c1xx-calextr.c @ 294:1416fe200069

c1xx-calextr started
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 18 Nov 2017 17:12:20 +0000
parents
children 77d561735b07
line wrap: on
line source

/*
 * This program parses Compal's proprietary data structure that contains
 * the factory RF calibration values among other data, locates those RF
 * calibration records, extracts their essential content (Rx GMagic and
 * Tx APC values) and writes this calibration out in the form of FreeCalypso
 * ASCII RF tables.
 */

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

#define	COMPAL_SECTOR_LENGTH	0x2000

u_char sector[COMPAL_SECTOR_LENGTH];
u_char endmarker[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
u_char record_magic[4] = {0xAA, 0x00, 0x00, 0x00};

struct band {
	char		*name;
	unsigned	compal_record_id;
	unsigned	record_length;
	unsigned	magic2_offset;
	unsigned	start_plnum;
	unsigned	end_plnum;
} bands[] = {
	{"900",  0x00, 0x94, 0x54, 5, 19},
	{"1800", 0x01, 0xC8, 0x74, 0, 15},
	{"1900", 0x02, 0xB4, 0x68, 0, 15},
	{"850",  0x18, 0x88, 0x4C, 5, 19},
};

read_binfile(filename, offset_arg)
	char *filename, *offset_arg;
{
	int fd, cc;
	u_long offset;
	char *endp;

	fd = open(filename, O_RDONLY);
	if (fd < 0) {
		perror(filename);
		exit(1);
	}
	offset = strtoul(offset_arg, &endp, 0);
	if (*endp) {
		fprintf(stderr, "error: invalid offset argument \"%s\"\n",
			offset_arg);
		exit(1);
	}
	lseek(fd, offset, SEEK_SET);
	cc = read(fd, sector, COMPAL_SECTOR_LENGTH);
	if (cc != COMPAL_SECTOR_LENGTH) {
		fprintf(stderr,
"error: unable to read Compal sector of %d bytes from %s at offset %s\n",
			COMPAL_SECTOR_LENGTH, filename, offset_arg);
		exit(1);
	}
	close(fd);
}

process_band_record(band, offset)
	struct band *band;
	unsigned offset;
{
	u_char *record;

	record = sector + offset + 8;
	if (bcmp(record, record_magic, 4)) {
		printf("bad magic1, skipping\n");
		return(-1);
	}
	if (bcmp(record + band->magic2_offset, record_magic, 4)) {
		printf("bad magic2, skipping\n");
		return(-1);
	}
	if (bcmp(record + band->magic2_offset + 8, record_magic, 4)) {
		printf("bad magic3, skipping\n");
		return(-1);
	}
	/* Rx GMagic and Tx levels extraction to be filled */
	return(0);
}

main(argc, argv)
	char **argv;
{
	unsigned offset, next_offset;
	u_char *header;
	unsigned hdr_words[4];
	struct band *band;
	int i;

	if (argc != 3) {
		fprintf(stderr, "usage: %s binfile offset\n", argv[0]);
		exit(1);
	}
	read_binfile(argv[1], argv[2]);
	for (offset = 0; ; offset = next_offset) {
		if (offset > COMPAL_SECTOR_LENGTH - 12)
			break;
		header = sector + offset;
		if (!bcmp(header, endmarker, 8))
			break;
		for (i = 0; i < 4; i++)
			hdr_words[i] = header[i*2] | (header[i*2+1] << 8);
		if (!hdr_words[3]) {
			fprintf(stderr,
		"error at offset 0x%X: rounded record length word is 0\n",
				offset);
			exit(1);
		}
		if (hdr_words[3] & 3) {
			fprintf(stderr,
"error at offset 0x%X: rounded record length word is not aligned to 4\n",
				offset);
			exit(1);
		}
		if (hdr_words[3] > COMPAL_SECTOR_LENGTH - offset - 8) {
			fprintf(stderr,
"error at offset 0x%X: rounded record length spills past end of sector\n",
				offset);
			exit(1);
		}
		if (hdr_words[2] > hdr_words[3]) {
			fprintf(stderr,
	"error at offset 0x%X: native record length is greater than rounded\n",
				offset);
			exit(1);
		}
		next_offset = offset + 8 + hdr_words[3];
		if (hdr_words[0] != 0x000C)
			continue;
		for (band = bands; band->name; band++)
			if (hdr_words[1] == band->compal_record_id)
				break;
		if (!band->name)
			continue;
		printf("Found %s MHz calibration record at offset 0x%X\n",
			band->name, offset);
		if (hdr_words[2] != band->record_length) {
			printf("Oops, wrong length, skipping\n");
			continue;
		}
		process_band_record(band, offset);
	}
	exit(0);
}