comparison trau-decode/parse-new16.c @ 107:c6ffb176eaed

trau-decode: new program trau-parse-n
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 21 Dec 2025 20:05:22 +0000
parents trau-decode/parse-main.c@00fd38c7c8fe
children f2009a354444
comparison
equal deleted inserted replaced
106:028307356ba9 107:c6ffb176eaed
1 /*
2 * This program reads a 64 kbit/s timeslot recording file, examines one
3 * of the four 16 kbit/s subslots (selected), looks for GSM 08.60 TRAU
4 * frames, and dumps whatever it finds. The present version is a new one,
5 * put together for the purpose of reverse-engineering Abis output from
6 * Nokia BTS, which exhibits more complex behaviour than what our original
7 * trau-parse program can analyze properly.
8 */
9
10 #include <sys/types.h>
11 #include <sys/file.h>
12 #include <sys/stat.h>
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <strings.h>
18
19 static uint8_t *filebuf;
20 static unsigned total_size;
21
22 static enum {
23 NOT_D144,
24 D144_SYNC,
25 D144_EDATA,
26 } d144_state;
27
28 static void
29 read_ts_file(filename, subslot_arg)
30 char *filename, *subslot_arg;
31 {
32 FILE *inf;
33 struct stat st;
34 int subslot, right_shift;
35 unsigned n;
36 uint8_t *dp;
37 int b;
38
39 inf = fopen(filename, "r");
40 if (!inf) {
41 perror(filename);
42 exit(1);
43 }
44 fstat(fileno(inf), &st);
45 if (!S_ISREG(st.st_mode)) {
46 fprintf(stderr, "error: %s is not a regular file\n", filename);
47 exit(1);
48 }
49 total_size = st.st_size;
50 if (total_size < 160) {
51 fprintf(stderr, "error: %s is too short\n", filename);
52 exit(1);
53 }
54 filebuf = malloc(total_size);
55 if (!filebuf) {
56 perror("malloc of file size");
57 exit(1);
58 }
59 subslot = atoi(subslot_arg);
60 if (subslot < 0 || subslot > 3) {
61 fprintf(stderr, "error: invalid subslot argument\n");
62 exit(1);
63 }
64 right_shift = (3 - subslot) * 2;
65 dp = filebuf;
66 for (n = 0; n < total_size; n++) {
67 b = getc(inf);
68 if (b < 0) {
69 fprintf(stderr,
70 "error: getc() returned EOF contrary to st_size\n");
71 exit(1);
72 }
73 *dp++ = (b >> right_shift) & 3;
74 }
75 fclose(inf);
76 }
77
78 static int
79 check_sync(pos)
80 unsigned pos;
81 {
82 uint8_t *cand = filebuf + pos;
83 unsigned n;
84
85 for (n = 0; n < 8; n++) {
86 if (cand[n])
87 return 0;
88 }
89 if (!(cand[8] & 2))
90 return 0;
91 if (cand[8] == 3 && cand[9] == 3 && cand[10] == 3 &&
92 (d144_state == D144_SYNC || d144_state == D144_EDATA))
93 return 1;
94 for (n = 2; n < 20; n++) {
95 if (!(cand[n * 8] & 2))
96 return 0;
97 }
98 return 1;
99 }
100
101 static void
102 unpack_dibits(in_frame_2bit, frame_bits)
103 uint8_t *in_frame_2bit, *frame_bits;
104 {
105 int i, inb;
106 uint8_t *op;
107
108 op = frame_bits;
109 for (i = 0; i < 160; i++) {
110 inb = in_frame_2bit[i];
111 if (inb & 2)
112 *op++ = 1;
113 else
114 *op++ = 0;
115 if (inb & 1)
116 *op++ = 1;
117 else
118 *op++ = 0;
119 }
120 }
121
122 static unsigned
123 bits_to_num(bits, nbits)
124 uint8_t *bits;
125 unsigned nbits;
126 {
127 unsigned accum;
128 unsigned n;
129
130 accum = 0;
131 for (n = 0; n < nbits; n++) {
132 accum <<= 1;
133 if (*bits)
134 accum |= 1;
135 bits++;
136 }
137 return accum;
138 }
139
140 static void
141 dump_raw_nibbles(dibits, num_dibits)
142 uint8_t *dibits;
143 unsigned num_dibits;
144 {
145 uint8_t *sp = dibits;
146 unsigned remain = num_dibits;
147
148 if (remain >= 2) {
149 while (remain >= 2) {
150 printf("%x", (sp[0] << 2) | sp[1]);
151 sp += 2;
152 remain -= 2;
153 }
154 putchar('\n');
155 }
156 if (remain)
157 printf("dribble %u%u\n", (*sp & 2) >> 1, (*sp & 1) >> 0);
158 }
159
160 static int
161 process_frame(pos)
162 unsigned pos;
163 {
164 uint8_t *frame_2b = filebuf + pos;
165 uint8_t frame_bits[320];
166 unsigned c1_5, c6_11;
167
168 printf("Frame at 0x%x:\n", pos);
169 dump_raw_nibbles(frame_2b, 160);
170 unpack_dibits(frame_2b, frame_bits);
171 printf(" C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18],
172 frame_bits[19], frame_bits[20], frame_bits[21]);
173 c1_5 = bits_to_num(frame_bits + 17, 5);
174 switch (c1_5) {
175 case 0x02:
176 fputs(" (FR UL)", stdout);
177 break;
178 case 0x1C:
179 fputs(" (FR DL)", stdout);
180 break;
181 case 0x1A:
182 fputs(" (EFR)", stdout);
183 break;
184 case 0x10:
185 fputs(" (idle UL)", stdout);
186 break;
187 case 0x0E:
188 fputs(" (idle DL)", stdout);
189 break;
190 case 0x08:
191 fputs(" (data UL)", stdout);
192 break;
193 case 0x16:
194 fputs(" (data DL)", stdout);
195 break;
196 case 0x09:
197 fputs(" (HR data UL)", stdout);
198 break;
199 case 0x17:
200 fputs(" (HR data DL)", stdout);
201 break;
202 case 0x14:
203 fputs(" (D144 sync)", stdout);
204 break;
205 case 0x1F:
206 fputs(" (E-TRAU)", stdout);
207 break;
208 case 0x06:
209 fputs(" (AMR)", stdout);
210 break;
211 }
212 putchar('\n');
213 if (c1_5 == 0x14)
214 d144_state = D144_SYNC;
215 else if (c1_5 == 0x1F &&
216 (d144_state == D144_SYNC || d144_state == D144_EDATA))
217 d144_state = D144_EDATA;
218 else
219 d144_state = NOT_D144;
220 switch (c1_5) {
221 case 0x02:
222 case 0x1C:
223 case 0x1A:
224 case 0x10:
225 case 0x0E:
226 c6_11 = bits_to_num(frame_bits + 22, 6);
227 printf(" C6-C11: %u\n", c6_11);
228 printf(" C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28],
229 frame_bits[29], frame_bits[30], frame_bits[31]);
230 print_fr_efr_frame(frame_bits, c1_5);
231 printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n",
232 frame_bits[310], frame_bits[311], frame_bits[312],
233 frame_bits[313], frame_bits[314], frame_bits[315]);
234 printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316],
235 frame_bits[317], frame_bits[318], frame_bits[319]);
236 return 1;
237 case 0x08:
238 case 0x09:
239 case 0x16:
240 case 0x17:
241 case 0x14:
242 print_data_frame(frame_bits);
243 return 0;
244 case 0x1F:
245 print_edata_frame(frame_bits);
246 return 0;
247 case 0x06:
248 print_amr_frame(frame_bits);
249 return 1;
250 default:
251 printf(" C6-C15: %u%u%u%u%u%u%u%u%u%u\n", frame_bits[22],
252 frame_bits[23], frame_bits[24], frame_bits[25],
253 frame_bits[26], frame_bits[27], frame_bits[28],
254 frame_bits[29], frame_bits[30], frame_bits[31]);
255 printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n",
256 frame_bits[310], frame_bits[311], frame_bits[312],
257 frame_bits[313], frame_bits[314], frame_bits[315]);
258 printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316],
259 frame_bits[317], frame_bits[318], frame_bits[319]);
260 return 0;
261 }
262 }
263
264 static void
265 process_filebuf()
266 {
267 unsigned p, nf_pos = 0, nf_accum = 0;
268 int match, have_t_bits;
269
270 d144_state = NOT_D144;
271 for (p = 0; p < total_size; ) {
272 if ((total_size - p) >= 160)
273 match = check_sync(p);
274 else
275 match = 0;
276 if (match) {
277 if (nf_accum) {
278 printf("Non-frame at 0x%x:\n", nf_pos);
279 dump_raw_nibbles(filebuf + nf_pos, nf_accum);
280 }
281 have_t_bits = process_frame(p);
282 if (have_t_bits && !filebuf[p+158] && !filebuf[p+159]) {
283 puts("advance of 250 us");
284 p += 158;
285 } else
286 p += 160;
287 nf_pos = p;
288 nf_accum = 0;
289 } else {
290 p++;
291 nf_accum++;
292 if (nf_accum >= 160) {
293 printf("Non-frame at 0x%x:\n", nf_pos);
294 dump_raw_nibbles(filebuf + nf_pos, nf_accum);
295 nf_pos = p;
296 nf_accum = 0;
297 }
298 d144_state = NOT_D144;
299 }
300 }
301 if (nf_accum) {
302 printf("Non-frame at 0x%x:\n", nf_pos);
303 dump_raw_nibbles(filebuf + nf_pos, nf_accum);
304 }
305 }
306
307 main(argc, argv)
308 char **argv;
309 {
310 if (argc != 3) {
311 fprintf(stderr, "usage: %s r] binfile subslot\n", argv[0]);
312 exit(1);
313 }
314 read_ts_file(argv[1], argv[2]);
315 process_filebuf();
316 exit(0);
317 }