view trau-decode/extr-main.c @ 14:98c0881c2af0

tfo/find-is-hdr: move here from freecalypso-reveng This little program was developed in freecalypso-reveng Hg repository in 2023-03, when we didn't have a separate repository for network-side reverse eng, but now that we do have separate repositories for FreeCalypso (mobile side) vs network side reverse eng, move TFO RE work to the proper place.
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 24 May 2024 21:18:22 +0000
parents 0565aaa84b17
children
line wrap: on
line source

/*
 * This program reads a 64 kbit/s timeslot recording file with a focus
 * on a single sub-timeslot just like trau-parse, but it needs to be
 * invoked with a starting and ending offset for the frame-aligned
 * portion of interest (found with trau-parse), and it saves (converts)
 * the selected stream of TRAU-UL frames to a Themyscira gsmx file.
 */

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

static void
reduce_to_subslot(buf, right_shift)
	uint8_t *buf;
{
	unsigned n;

	for (n = 0; n < 160; n++) {
		buf[n] >>= right_shift;
		buf[n] &= 3;
	}
}

static void
unpack_dibits(dibits, frame_bits)
	uint8_t *dibits, *frame_bits;
{
	int i, inb;
	uint8_t *op;

	op = frame_bits;
	for (i = 0; i < 160; i++) {
		inb = dibits[i];
		if (inb & 2)
			*op++ = 1;
		else
			*op++ = 0;
		if (inb & 1)
			*op++ = 1;
		else
			*op++ = 0;
	}
}

static unsigned
bits_to_num(bits, nbits)
	uint8_t *bits;
	unsigned nbits;
{
	unsigned accum;
	unsigned n;

	accum = 0;
	for (n = 0; n < nbits; n++) {
		accum <<= 1;
		if (*bits)
			accum |= 1;
		bits++;
	}
	return accum;
}

static void
collect_d_bits(frame_bits, d_bits)
	uint8_t *frame_bits, *d_bits;
{
	bcopy(frame_bits + 33, d_bits, 15);
	bcopy(frame_bits + 49, d_bits + 15, 15);
	bcopy(frame_bits + 65, d_bits + 30, 15);
	bcopy(frame_bits + 81, d_bits + 45, 15);
	bcopy(frame_bits + 97, d_bits + 60, 15);
	bcopy(frame_bits + 113, d_bits + 75, 15);
	bcopy(frame_bits + 129, d_bits + 90, 15);
	bcopy(frame_bits + 145, d_bits + 105, 15);
	bcopy(frame_bits + 161, d_bits + 120, 15);
	bcopy(frame_bits + 177, d_bits + 135, 15);
	bcopy(frame_bits + 193, d_bits + 150, 15);
	bcopy(frame_bits + 209, d_bits + 165, 15);
	bcopy(frame_bits + 225, d_bits + 180, 15);
	bcopy(frame_bits + 241, d_bits + 195, 15);
	bcopy(frame_bits + 257, d_bits + 210, 15);
	bcopy(frame_bits + 273, d_bits + 225, 15);
	bcopy(frame_bits + 289, d_bits + 240, 15);
	bcopy(frame_bits + 305, d_bits + 255, 5);
}

static void
process_frame(cur_offset, dibits, outf)
	u_long cur_offset;
	uint8_t *dibits;
	FILE *outf;
{
	uint8_t frame_bits[320], d_bits[260];
	unsigned c1_5;

	unpack_dibits(dibits, frame_bits);
	if (frame_bits[28]) {			/* C12 aka BFI */
		putc(0xBF, outf);
		putc(frame_bits[31], outf);	/* C15 aka TAF */
		return;
	}
	collect_d_bits(frame_bits, d_bits);
	c1_5 = bits_to_num(frame_bits + 17, 5);
	switch (c1_5) {
	case 0x02:
		convert_fr_frame(d_bits, outf);
		break;
	case 0x1A:
		convert_efr_frame(d_bits, outf);
		break;
	default:
		fprintf(stderr,
			"error: unknown frame type 0x%x at file offset 0x%lx\n",
			c1_5, cur_offset);
		exit(1);
	}
}

main(argc, argv)
	char **argv;
{
	FILE *inf, *outf;
	int subslot, right_shift;
	u_long start_offset, end_offset, cur_offset;
	uint8_t readbuf[160];
	int cc;

	if (argc != 6) {
		fprintf(stderr, "usage: %s binfile subslot start end outfile\n",
			argv[0]);
		exit(1);
	}
	inf = fopen(argv[1], "r");
	if (!inf) {
		perror(argv[1]);
		exit(1);
	}
	subslot = atoi(argv[2]);
	if (subslot < 0 || subslot > 3) {
		fprintf(stderr, "error: invalid subslot argument\n");
		exit(1);
	}
	right_shift = (3 - subslot) * 2;
	start_offset = strtoul(argv[3], 0, 0);
	fseek(inf, start_offset, SEEK_SET);
	end_offset = strtoul(argv[4], 0, 0);
	outf = fopen(argv[5], "w");
	if (!outf) {
		perror(argv[5]);
		exit(1);
	}
	for (cur_offset = start_offset; ; cur_offset += 160) {
		if (end_offset && cur_offset >= end_offset)
			break;
		cc = fread(readbuf, 1, 160, inf);
		if (cc < 160)
			break;
		reduce_to_subslot(readbuf, right_shift);
		process_frame(cur_offset, readbuf, outf);
	}
	exit(0);
}