changeset 137:b7ea278390eb

gsmfr-cvt-dlcap: support new FC TCH DL recording format
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 13 Dec 2022 04:37:45 +0000
parents 8eb0e7a39409
children 68215020852b
files frtest/cvt-dlcap.c
diffstat 1 files changed, 68 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/frtest/cvt-dlcap.c	Sun Dec 11 22:20:36 2022 +0000
+++ b/frtest/cvt-dlcap.c	Tue Dec 13 04:37:45 2022 +0000
@@ -9,8 +9,8 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
-
-static const char bfi_marker[2] = {0xBF, 0x00};
+#include <string.h>
+#include <strings.h>
 
 static
 decode_hex_digit(ch)
@@ -23,16 +23,49 @@
 		return(ch - 'a' + 10);
 }
 
+static
+parse_classic_part(line, status_words, tidsp_bytes)
+	char *line;
+	u_short *status_words;
+	u_char *tidsp_bytes;
+{
+	char *cp;
+	int i;
+
+	/* grok DSP status words */
+	cp = line;
+	for (i = 0; i < 3; i++) {
+		if (!isxdigit(cp[0]) || !isxdigit(cp[1]) ||
+		    !isxdigit(cp[2]) || !isxdigit(cp[3]))
+			return -1;
+		status_words[i] = (decode_hex_digit(cp[0]) << 12) |
+				  (decode_hex_digit(cp[1]) << 8) |
+				  (decode_hex_digit(cp[2]) << 4) |
+				   decode_hex_digit(cp[3]);
+		cp += 4;
+		if (*cp++ != ' ')
+			return -1;
+	}
+	/* read the frame bits */
+	for (i = 0; i < 33; i++) {
+		if (!isxdigit(cp[0]) || !isxdigit(cp[1]))
+			return -1;
+		tidsp_bytes[i] = (decode_hex_digit(cp[0]) << 4) |
+				  decode_hex_digit(cp[1]);
+		cp += 2;
+	}
+	return 0;
+}
+
 main(argc, argv)
 	char **argv;
 {
 	FILE *inf, *outf;
 	char linebuf[128];
-	int lineno;
-	char *cp;
-	int i;
+	int lineno, rc;
 	u_short status_words[3];
-	u_char tidsp_bytes[33], libgsm_bytes[33];
+	u_char tidsp_bytes[33], libgsm_bytes[33], bfi[2];
+	unsigned fn_mod_104;
 
 	if (argc != 3) {
 		fprintf(stderr, "usage: %s infile outfile\n", argv[0]);
@@ -49,36 +82,39 @@
 		exit(1);
 	}
 	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
-		/* grok DSP status words */
-		cp = linebuf;
-		for (i = 0; i < 3; i++) {
-			if (!isxdigit(cp[0]) || !isxdigit(cp[1]) ||
-			    !isxdigit(cp[2]) || !isxdigit(cp[3])) {
+		/* support both old and new formats */
+		if (isxdigit(linebuf[0]) && isxdigit(linebuf[1]) &&
+		    isxdigit(linebuf[2]) && isxdigit(linebuf[3])) {
+			rc = parse_classic_part(linebuf, status_words,
+						tidsp_bytes);
+			if (rc < 0) {
 invalid:			fprintf(stderr,
-				    "error: %s is not in the expected format\n",
-						argv[1]);
+				"error: %s is not in the expected format\n",
+					argv[1]);
 				exit(1);
 			}
-			status_words[i] = (decode_hex_digit(cp[0]) << 12) |
-					  (decode_hex_digit(cp[1]) << 8) |
-					  (decode_hex_digit(cp[2]) << 4) |
-					   decode_hex_digit(cp[3]);
-			cp += 4;
-			if (*cp++ != ' ')
+			fn_mod_104 = 0;		/* won't have TAF */
+		} else if (!strncmp(linebuf, "FR ", 3)) {
+			rc = parse_classic_part(linebuf + 3, status_words,
+						tidsp_bytes);
+			if (rc < 0)
+				goto invalid;
+			if (linebuf[84] != ' ')
+				goto invalid;
+			if (!isdigit(linebuf[85]))
 				goto invalid;
-		}
-		/* read the frame bits */
-		for (i = 0; i < 33; i++) {
-			if (!isxdigit(cp[0]) || !isxdigit(cp[1]))
-				goto invalid;
-			tidsp_bytes[i] = (decode_hex_digit(cp[0]) << 4) |
-					  decode_hex_digit(cp[1]);
-			cp += 2;
-		}
-		/* bit 2 of status word 0 is BFI */
-		if (status_words[0] & 0x0004)
-			fwrite(bfi_marker, 1, 2, outf);
-		else {
+			fn_mod_104 = strtoul(linebuf + 85, 0, 10);
+		} else
+			goto invalid;
+		/*
+		 * Bit 15 of status word 0 is buffer validity flag,
+		 * bit 2 is BFI.
+		 */
+		if (!(status_words[0] & 0x8000) || (status_words[0] & 0x0004)) {
+			bfi[0] = 0xBF;
+			bfi[1] = fn_mod_104 == 60;
+			fwrite(bfi, 1, 2, outf);
+		} else {
 			gsm0610_tidsp_to_libgsm(tidsp_bytes, libgsm_bytes);
 			fwrite(libgsm_bytes, 1, 33, outf);
 		}