diff efrtest/dlcap-sync.c @ 468:4104b0390fab

efrtest: new program gsmefr-dlcap-sync
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 13 May 2024 07:21:09 +0000
parents
children d80ccb3c3970
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/efrtest/dlcap-sync.c	Mon May 13 07:21:09 2024 +0000
@@ -0,0 +1,138 @@
+/*
+ * This program reads a TCH/EFS downlink capture file from a FreeCalypso GSM MS
+ * that was produced in a session in which seqsync PCMA or PCMU input was fed
+ * into the test call from IP-PSTN side.  It looks for EFR DHF followed by
+ * specific frame patterns indicating how the seqsync input was transcoded
+ * by the alien GSM network, and reports its findings.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+static const uint8_t efr_dhf[31] = {
+0xC0,0x85,0xEB,0x49,0x0F,0xAA,0xD6,0x03,0xE3,0xA1,0x86,0x07,0xB0,0xC4,0x2C,0x08,
+0x04,0x80,0x55,0x80,0x00,0x00,0x00,0x00,0x03,0x6B,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const uint8_t mr122_dhf[31] = {
+0xC0,0x85,0x4D,0xB9,0x6A,0xAA,0xD6,0x00,0x00,0x00,0x00,0x01,0xB5,0x87,0xF6,0x68,
+0x37,0x94,0x09,0x00,0x41,0x58,0x54,0xF1,0x0F,0x6B,0x02,0x40,0x3C,0x7E,0xA0,
+};
+
+extern const uint8_t sync_from_pcma[320*31];
+extern const uint8_t sync_from_pcmu[320*31];
+
+static int
+check_for_match(input, table)
+	const uint8_t *input, *table;
+{
+	unsigned n;
+
+	for (n = 0; n < 320; n++) {
+		if (!bcmp(input, table + n * 31, 31))
+			return n;
+	}
+	return -1;
+}
+
+main(argc, argv)
+	char **argv;
+{
+	FILE *inf;
+	char linebuf[128];
+	int lineno, rc;
+	uint16_t status_words[3];
+	uint8_t tidsp_bytes[33], efr_bytes[31];
+	const uint8_t *match_table;
+	int dhf_state;
+	char *dhf_name;
+
+	if (argc != 3) {
+usage:		fprintf(stderr, "usage: %s dlcap-file alaw|ulaw\n", argv[0]);
+		exit(1);
+	}
+	inf = fopen(argv[1], "r");
+	if (!inf) {
+		perror(argv[1]);
+		exit(1);
+	}
+	if (!strcmp(argv[2], "alaw"))
+		match_table = sync_from_pcma;
+	else if (!strcmp(argv[2], "ulaw"))
+		match_table = sync_from_pcmu;
+	else
+		goto usage;
+	dhf_state = 0;
+	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
+		/* support both old and new formats */
+		if (isxdigit(linebuf[0]) && isxdigit(linebuf[1]) &&
+		    isxdigit(linebuf[2]) && isxdigit(linebuf[3])) {
+			rc = parse_dlcap_common(linebuf, status_words,
+						tidsp_bytes);
+			if (rc < 0) {
+invalid:			fprintf(stderr,
+				"error: %s is not in the expected format\n",
+					argv[1]);
+				exit(1);
+			}
+		} else if (!strncmp(linebuf, "EFR ", 4)) {
+			rc = parse_dlcap_common(linebuf + 4, status_words,
+						tidsp_bytes);
+			if (rc < 0)
+				goto invalid;
+			if (linebuf[85] != ' ')
+				goto invalid;
+			if (!isdigit(linebuf[86]))
+				goto invalid;
+		} else
+			goto invalid;
+		if ((status_words[0] & 0xC204) != 0xC000) {
+			dhf_state = 0;
+			continue;
+		}
+		efr_tidsp_to_std(tidsp_bytes, efr_bytes);
+		if (!bcmp(efr_bytes, efr_dhf, 31)) {
+			dhf_state = 1;
+			continue;
+		}
+		if (!bcmp(efr_bytes, mr122_dhf, 31)) {
+			dhf_state = 2;
+			continue;
+		}
+		if (!dhf_state)
+			continue;
+		rc = check_for_match(efr_bytes, match_table);
+		if (rc >= 0 && rc <= 159) {
+			printf(
+			    "line %d: match to standard EFR with offset %d\n",
+				lineno, rc);
+			if (dhf_state == 2)
+				printf("... but preceded by MR122 DHF!\n");
+		} else if (rc >= 160 && rc <= 279) {
+			printf("line %d: match to AMR-EFR with offset %d\n",
+				lineno, rc - 160);
+			if (dhf_state == 2)
+				printf("... but preceded by MR122 DHF!\n");
+		} else if (rc >= 280 && rc <= 319) {
+			printf("line %d: match to AMR-EFR with offset %d\n",
+				lineno, rc - 160);
+			switch (dhf_state) {
+			case 1:
+				dhf_name = "EFR";
+				break;
+			case 2:
+				dhf_name = "MR122";
+				break;
+			default:
+				dhf_name = "???";
+			}
+			printf("previous frame was %s DHF\n", dhf_name);
+		}
+		dhf_state = 0;
+	}
+	exit(0);
+}