comparison amrconv/tw5c-dump.c @ 593:fd6a394ab4cd

amrconv: new program tw5c-dump
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 18 Nov 2025 07:34:23 +0000
parents
children
comparison
equal deleted inserted replaced
592:24aba0e7aa35 593:fd6a394ab4cd
1 /*
2 * This program reads a TW-TS-005 Annex C hexadecimal file
3 * and dumps all frames in human-readable form.
4 */
5
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <strings.h>
11 #include <unistd.h>
12 #include "../libtest/tw5reader.h"
13 #include "amr_defs.h"
14
15 extern char *amr_mode_names[16];
16 extern const uint8_t pl_total_bytes_oa[9], pl_total_bytes_bwe[9];
17
18 static char *infname;
19 static int is_bwe;
20
21 static void
22 process_cmdline(argc, argv)
23 char **argv;
24 {
25 int opt;
26 extern int optind;
27
28 while ((opt = getopt(argc, argv, "b")) != EOF) {
29 switch (opt) {
30 case 'b':
31 is_bwe = 1;
32 continue;
33 default:
34 usage:
35 fprintf(stderr, "usage: %s [-b] hex-file\n", argv[0]);
36 exit(1);
37 }
38 }
39 if (argc != optind + 1)
40 goto usage;
41 infname = argv[optind];
42 }
43
44 static void
45 if1_bwe_to_oa(in, out, mode)
46 uint8_t *in, *out;
47 unsigned mode;
48 {
49 unsigned out_len, n;
50
51 out_len = pl_total_bytes_oa[mode] - 2;
52 for (n = 0; n < out_len; n++)
53 out[n] = (in[n+1] << 2) | (in[n+2] >> 6);
54 }
55
56 static void
57 process_file()
58 {
59 FILE *hexf;
60 unsigned lineno;
61 uint8_t frame[TWTS005_MAX_FRAME];
62 unsigned frame_len, base_len, cmr, ft, q, sid_byte, sti, sid_mode;
63 const uint8_t *pl_len_table;
64 uint8_t frm_to_oa[MAX_IF1_BYTES];
65 uint8_t ser_bits[MAX_SERIAL_SIZE];
66 uint16_t params[MAX_PRM_SIZE];
67 unsigned ptr;
68 int rc;
69
70 hexf = fopen(infname, "r");
71 if (!hexf) {
72 perror(infname);
73 exit(1);
74 }
75 lineno = 0;
76 for (;;) {
77 rc = twts005_read_frame(hexf, &lineno, frame, &frame_len);
78 if (rc < 0) {
79 fprintf(stderr, "%s line %u: not valid TW-TS-005\n",
80 infname, lineno);
81 exit(1);
82 }
83 if (!rc)
84 break;
85 if (frame_len == 0) {
86 printf("line %u: NULL frame\n", lineno);
87 continue;
88 }
89 if (frame_len < 2) {
90 inv_payload: fprintf(stderr,
91 "%s line %u: payload is not valid AMR %s\n",
92 infname, lineno, is_bwe ? "BWE" : "OA");
93 exit(1);
94 }
95 cmr = frame[0] >> 4;
96 if (cmr > MR122 && cmr != MODE_NO_DATA)
97 goto inv_payload;
98 if (is_bwe) {
99 if (frame[0] & 0x08)
100 goto inv_payload;
101 ft = ((frame[0] & 0x07) << 1) |
102 ((frame[1] & 0x80) >> 7);
103 q = (frame[1] & 0x40) >> 6;
104 pl_len_table = pl_total_bytes_bwe;
105 } else {
106 if (frame[1] & 0x80)
107 goto inv_payload;
108 ft = (frame[1] & 0x78) >> 3;
109 q = (frame[1] & 0x04) >> 2;
110 pl_len_table = pl_total_bytes_oa;
111 }
112 if (ft <= MRDTX)
113 base_len = pl_len_table[ft];
114 else if (ft == MODE_NO_DATA)
115 base_len = 2;
116 else
117 goto inv_payload;
118 if (frame_len < base_len)
119 goto inv_payload;
120 printf("line %u: CMR=%u (%s) FT=%u (%s) Q=%u\n", lineno, cmr,
121 amr_mode_names[cmr], ft, amr_mode_names[ft], q);
122 if (ft != MODE_NO_DATA) {
123 if (is_bwe) {
124 if1_bwe_to_oa(frame, frm_to_oa, ft);
125 amr_if1_unpack(frm_to_oa, ser_bits, ft);
126 } else {
127 amr_if1_unpack(frame + 2, ser_bits, ft);
128 }
129 reassemble_amr_params(ser_bits, params, ft);
130 dump_amr_params(params, ft);
131 }
132 if (ft == MRDTX) {
133 sid_byte = is_bwe ? frm_to_oa[4] : frame[6];
134 sti = (sid_byte & 0x10) >> 4;
135 sid_mode = 0;
136 if (sid_byte & 0x08)
137 sid_mode |= 1;
138 if (sid_byte & 0x04)
139 sid_mode |= 2;
140 if (sid_byte & 0x02)
141 sid_mode |= 4;
142 printf(" SID_%s Mode=%u (%s)\n",
143 sti ? "UPDATE" : "FIRST", sid_mode,
144 amr_mode_names[sid_mode]);
145 }
146 if (is_bwe)
147 continue;
148 /* TW-TS-006 extensions */
149 if (frame[0] & 0x08)
150 printf(" RIF=%u\n", (frame[0] & 0x04) >> 2);
151 ptr = base_len;
152 if ((ft == MODE_NO_DATA) && (frame[1] & 0x02)) {
153 fputs(" FT15 ext octet: ", stdout);
154 if (ptr >= frame_len) {
155 puts("indicated, but not present");
156 continue;
157 }
158 /* repurpose sti and sid_mode vars */
159 sti = (frame[ptr] & 0x80) >> 7;
160 sid_mode = frame[ptr] & 7;
161 printf("%s, Mode=%u (%s)\n", sti ? "Onset" : "No_Data",
162 sid_mode, amr_mode_names[sid_mode]);
163 ptr++;
164 }
165 if (frame[0] & 0x02) {
166 if (ptr >= frame_len) {
167 puts(" TA+DTXd+TFOE octet missing!");
168 continue;
169 }
170 printf(" TA=%u DTXd=%u TFOE=%u\n", frame[ptr] >> 2,
171 (frame[ptr] & 0x02) >> 1, frame[ptr] & 0x01);
172 ptr++;
173 }
174 if (frame[0] & 0x01)
175 puts(" Rel4 Config_Prot present, not decoded");
176 if ((ft == MODE_NO_DATA) && (frame[1] & 0x01))
177 puts(" Rel5 GCF, not decoded");
178 }
179 }
180
181 main(argc, argv)
182 char **argv;
183 {
184 process_cmdline(argc, argv);
185 process_file();
186 exit(0);
187 }