changeset 163:568e2a2b49c8

tiaud-decomp utility written
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 18 Mar 2017 05:47:32 +0000 (2017-03-18)
parents ce7479d28b02
children 959ff9f59568
files .hgignore ffstools/tiaud/Makefile ffstools/tiaud/binstruct.h ffstools/tiaud/decomp.c
diffstat 4 files changed, 190 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Mar 17 08:28:21 2017 +0000
+++ b/.hgignore	Sat Mar 18 05:47:32 2017 +0000
@@ -6,6 +6,7 @@
 \.srec$
 
 ^ffstools/cal2text/fc-cal2text$
+^ffstools/tiaud/decomp$
 ^ffstools/tiffs-rd/tiffs$
 ^ffstools/tiffs-wrappers/mokoffs$
 ^ffstools/tiffs-wrappers/pirffs$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ffstools/tiaud/Makefile	Sat Mar 18 05:47:32 2017 +0000
@@ -0,0 +1,11 @@
+CC=	gcc
+CFLAGS=	-O2
+PROGS=	decomp
+
+all:	${PROGS}
+
+decomp:	decomp.c
+	${CC} ${CFLAGS} -o $@ $@.c
+
+clean:
+	rm -f ${PROGS}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ffstools/tiaud/binstruct.h	Sat Mar 18 05:47:32 2017 +0000
@@ -0,0 +1,32 @@
+/*
+ * The binary structure of /aud/*.cfg audio mode config files
+ * written and read by TI's TCS211 firmware is defined here.
+ */
+
+struct audio_cfg_bin {
+	uint8_t		voice_path;
+	uint8_t		pad1[3];
+	uint8_t		mic_mode;
+	uint8_t		pad2[3];
+	int8_t		mic_bytes[4];
+	uint16_t	mic_fir[32];
+	uint8_t		speaker_mode;
+	uint8_t		pad3[3];
+	int8_t		speaker_bytes[4];
+	uint16_t	speaker_fir[32];
+	int8_t		sidetone_gain;
+	uint8_t		pad4[3];
+	uint16_t	aec_words[6];
+};
+
+/* mic_mode byte */
+#define AUDIO_MICROPHONE_HANDHELD   (0)
+#define AUDIO_MICROPHONE_HANDFREE   (1)
+#define AUDIO_MICROPHONE_HEADSET    (2)
+
+/* speaker_mode byte */
+#define AUDIO_SPEAKER_HANDHELD          (0)
+#define AUDIO_SPEAKER_HANDFREE          (1)
+#define AUDIO_SPEAKER_HEADSET           (2)
+#define AUDIO_SPEAKER_BUZZER            (3)
+#define AUDIO_SPEAKER_HANDHELD_HANDFREE (4)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ffstools/tiaud/decomp.c	Sat Mar 18 05:47:32 2017 +0000
@@ -0,0 +1,146 @@
+/*
+ * This utility decompiles a binary /aud/*.cfg file read out of FFS
+ * into our ASCII text representation.
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <endian.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "binstruct.h"
+
+struct audio_cfg_bin bin;
+FILE *outf;
+
+read_bin_file(filename)
+	char *filename;
+{
+	int fd;
+	struct stat st;
+
+	fd = open(filename, O_RDONLY);
+	if (fd < 0) {
+		perror(filename);
+		exit(1);
+	}
+	fstat(fd, &st);
+	if (!S_ISREG(st.st_mode)) {
+		fprintf(stderr, "%s is not a regular file\n", filename);
+		exit(1);
+	}
+	if (st.st_size != sizeof(struct audio_cfg_bin)) {
+		fprintf(stderr, "%s has the wrong length\n", filename);
+		exit(1);
+	}
+	read(fd, &bin, sizeof bin);
+	close(fd);
+}
+
+emit_fir(table)
+	uint16_t *table;
+{
+	int i;
+
+	for (i = 0; i < 31; i++) {
+		if ((i % 8) == 0)
+			fprintf(outf, "\tfir %2d", i);
+		fprintf(outf, " 0x%04X", le16toh(table[i]));
+		if (i == 7 || i == 15 || i == 23 || i == 30)
+			putc('\n', outf);
+	}
+}
+
+emit_ascii()
+{
+	int i;
+
+	fprintf(outf, "voice-path %u\n", bin.voice_path);
+
+	switch (bin.mic_mode) {
+	case AUDIO_MICROPHONE_HANDHELD:
+		fprintf(outf, "mic default {\n");
+		break;
+	case AUDIO_MICROPHONE_HANDFREE:
+		fprintf(outf, "mic aux {\n");
+		break;
+	case AUDIO_MICROPHONE_HEADSET:
+		fprintf(outf, "mic headset {\n");
+		break;
+	default:
+		fprintf(stderr, "error: unknown microphone mode 0x%02X\n",
+			bin.mic_mode);
+		exit(1);
+	}
+	fprintf(outf, "\tgain %d\n", bin.mic_bytes[0]);
+	if (bin.mic_mode == AUDIO_MICROPHONE_HANDFREE) {
+		fprintf(outf, "\textra-gain %d\n", bin.mic_bytes[1]);
+		fprintf(outf, "\toutput-bias %d\n", bin.mic_bytes[2]);
+	} else
+		fprintf(outf, "\toutput-bias %d\n", bin.mic_bytes[1]);
+	emit_fir(bin.mic_fir);
+	fputs("}\n", outf);
+
+	switch (bin.speaker_mode) {
+	case AUDIO_SPEAKER_HANDHELD:
+		fprintf(outf, "speaker ear {\n");
+		break;
+	case AUDIO_SPEAKER_HANDFREE:
+		fprintf(outf, "speaker aux {\n");
+		break;
+	case AUDIO_SPEAKER_HEADSET:
+		fprintf(outf, "speaker headset {\n");
+		break;
+	case AUDIO_SPEAKER_BUZZER:
+		fprintf(outf, "speaker buzzer {\n");
+		break;
+	case AUDIO_SPEAKER_HANDHELD_HANDFREE:
+		fprintf(outf, "speaker ear+aux {\n");
+		break;
+	default:
+		fprintf(stderr, "error: unknown speaker mode 0x%02X\n",
+			bin.speaker_mode);
+		exit(1);
+	}
+	if (bin.speaker_mode != AUDIO_SPEAKER_BUZZER) {
+		fprintf(outf, "\tgain %d\n", bin.speaker_bytes[0]);
+		fprintf(outf, "\taudio-filter %d\n", bin.speaker_bytes[1]);
+		emit_fir(bin.speaker_fir);
+	} else
+		fprintf(outf, "\tactivate %d\n", bin.speaker_bytes[0]);
+	fputs("}\n", outf);
+
+	fprintf(outf, "sidetone %d\n", bin.sidetone_gain);
+	fputs("aec", outf);
+	for (i = 0; i < 5; i++) {
+		putc(' ', outf);
+		if (bin.aec_words[i])
+			fprintf(outf, "0x%X", le16toh(bin.aec_words[i]));
+		else
+			putc('0', outf);
+	}
+	putc('\n', outf);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr, "usage: %s infile [outfile]\n", argv[0]);
+		exit(1);
+	}
+	read_bin_file(argv[1]);
+	if (argc > 2) {
+		outf = fopen(argv[2], "w");
+		if (!outf) {
+			perror(argv[2]);
+			exit(1);
+		}
+	} else
+		outf = stdout;
+	emit_ascii();
+	exit(0);
+}