FreeCalypso > hg > gsm-net-reveng
comparison trau-decode/trau-hr-dump.c @ 28:9bcdb091c24d
trau-decode: new program trau-hr-dump
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 18 Aug 2024 08:37:02 +0000 |
parents | trau-decode/trau-sync8.c@f508dacf2cf9 |
children | 61181373875d |
comparison
equal
deleted
inserted
replaced
27:f508dacf2cf9 | 28:9bcdb091c24d |
---|---|
1 /* | |
2 * This program reads a 64 kbit/s timeslot recording file, examines one | |
3 * of the eight 8 kbit/s subslots (selected), looks for the sync pattern of | |
4 * GSM 08.61, decodes each frame as HRv1 speech and dumps everything it | |
5 * decodes. | |
6 */ | |
7 | |
8 #include <sys/types.h> | |
9 #include <sys/file.h> | |
10 #include <sys/stat.h> | |
11 #include <stdio.h> | |
12 #include <stdint.h> | |
13 #include <stdlib.h> | |
14 #include <string.h> | |
15 #include <strings.h> | |
16 #include <unistd.h> | |
17 #include "gsmhr_unpack.h" | |
18 #include "osmo_bits.h" | |
19 | |
20 /* | |
21 * EFR TRAU parity (also used for HR) | |
22 * | |
23 * g(x) = x^3 + x^1 + 1 | |
24 */ | |
25 static const struct osmo_crc8gen_code gsm0860_efr_crc3 = { | |
26 .bits = 3, | |
27 .poly = 0x3, | |
28 .init = 0x0, | |
29 .remainder = 0x7, | |
30 }; | |
31 | |
32 static uint8_t *filebuf; | |
33 static unsigned total_size; | |
34 | |
35 static void | |
36 read_ts_file(filename, subslot_arg) | |
37 char *filename, *subslot_arg; | |
38 { | |
39 FILE *inf; | |
40 struct stat st; | |
41 int subslot, right_shift; | |
42 unsigned n; | |
43 uint8_t *dp; | |
44 int b; | |
45 | |
46 inf = fopen(filename, "r"); | |
47 if (!inf) { | |
48 perror(filename); | |
49 exit(1); | |
50 } | |
51 fstat(fileno(inf), &st); | |
52 if (!S_ISREG(st.st_mode)) { | |
53 fprintf(stderr, "error: %s is not a regular file\n", filename); | |
54 exit(1); | |
55 } | |
56 total_size = st.st_size; | |
57 if (total_size < 160) { | |
58 fprintf(stderr, "error: %s is too short\n", filename); | |
59 exit(1); | |
60 } | |
61 filebuf = malloc(total_size); | |
62 if (!filebuf) { | |
63 perror("malloc of file size"); | |
64 exit(1); | |
65 } | |
66 subslot = atoi(subslot_arg); | |
67 if (subslot < 0 || subslot > 7) { | |
68 fprintf(stderr, "error: invalid subslot argument\n"); | |
69 exit(1); | |
70 } | |
71 right_shift = 7 - subslot; | |
72 dp = filebuf; | |
73 for (n = 0; n < total_size; n++) { | |
74 b = getc(inf); | |
75 if (b < 0) { | |
76 fprintf(stderr, | |
77 "error: getc() returned EOF contrary to st_size\n"); | |
78 exit(1); | |
79 } | |
80 *dp++ = (b >> right_shift) & 1; | |
81 } | |
82 fclose(inf); | |
83 } | |
84 | |
85 static int | |
86 check_sync(pos) | |
87 unsigned pos; | |
88 { | |
89 uint8_t *cand = filebuf + pos; | |
90 unsigned n; | |
91 | |
92 for (n = 0; n < 8; n++) { | |
93 if (cand[n]) | |
94 return 0; | |
95 } | |
96 if (!cand[8]) | |
97 return 0; | |
98 if (cand[16]) | |
99 return 0; | |
100 if (!cand[17]) | |
101 return 0; | |
102 for (n = 3; n < 20; n++) { | |
103 if (!cand[n * 8]) | |
104 return 0; | |
105 } | |
106 return 1; | |
107 } | |
108 | |
109 static int | |
110 bit_parity(bits, nbits) | |
111 ubit_t *bits; | |
112 unsigned nbits; | |
113 { | |
114 unsigned n, sum; | |
115 | |
116 sum = 0; | |
117 for (n = 0; n < nbits; n++) | |
118 sum += bits[n]; | |
119 return sum & 1; | |
120 } | |
121 | |
122 static void | |
123 bits2bytes(bits, bytes, nbytes) | |
124 ubit_t *bits; | |
125 uint8_t *bytes; | |
126 unsigned nbytes; | |
127 { | |
128 unsigned n, m, acc; | |
129 | |
130 for (n = 0; n < nbytes; n++) { | |
131 acc = 0; | |
132 for (m = 0; m < 8; m++) { | |
133 acc <<= 1; | |
134 acc |= *bits++; | |
135 } | |
136 *bytes++ = acc; | |
137 } | |
138 } | |
139 | |
140 static void | |
141 process_frame(pos) | |
142 unsigned pos; | |
143 { | |
144 ubit_t *frame = filebuf + pos; | |
145 ubit_t xc_bits[6], dbits[112]; | |
146 uint8_t hr_bytes[14]; | |
147 int16_t params[18]; | |
148 int crc_stat; | |
149 | |
150 printf("Frame at 0x%x:\n", pos); | |
151 printf(" C1-C4: %u%u%u%u OP %s\n", frame[9], frame[10], frame[11], | |
152 frame[12], bit_parity(frame + 9, 5) ? "good" : "bad"); | |
153 bcopy(frame + 14, xc_bits, 2); | |
154 bcopy(frame + 18, xc_bits + 2, 4); | |
155 printf(" XC1-XC5: %u%u%u%u%u OP %s\n", xc_bits[0], xc_bits[1], | |
156 xc_bits[2], xc_bits[3], xc_bits[4], | |
157 bit_parity(xc_bits, 6) ? "good" : "bad"); | |
158 bcopy(frame + 22, dbits, 2); | |
159 bcopy(frame + 25, dbits + 2, 7); | |
160 bcopy(frame + 33, dbits + 9, 7); | |
161 bcopy(frame + 41, dbits + 16, 7); | |
162 bcopy(frame + 49, dbits + 23, 7); | |
163 bcopy(frame + 57, dbits + 30, 7); | |
164 bcopy(frame + 65, dbits + 37, 7); | |
165 bcopy(frame + 76, dbits + 44, 4); | |
166 bcopy(frame + 81, dbits + 48, 7); | |
167 bcopy(frame + 89, dbits + 55, 7); | |
168 bcopy(frame + 97, dbits + 62, 7); | |
169 bcopy(frame + 105, dbits + 69, 7); | |
170 bcopy(frame + 113, dbits + 76, 7); | |
171 bcopy(frame + 121, dbits + 83, 7); | |
172 bcopy(frame + 129, dbits + 90, 7); | |
173 bcopy(frame + 137, dbits + 97, 7); | |
174 bcopy(frame + 145, dbits + 104, 7); | |
175 dbits[111] = frame[153]; | |
176 crc_stat = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, dbits, 44, | |
177 frame + 73); | |
178 printf(" CRC %s\n", crc_stat ? "bad" : "good"); | |
179 bits2bytes(dbits, hr_bytes, 14); | |
180 gsmhr_unpack_ts101318(hr_bytes, params); | |
181 printf(" R0=%02x LPC=%03x,%03x,%02x Int=%x Mode=%x\n", params[0], | |
182 params[1], params[2], params[3], params[4], params[5]); | |
183 printf(params[5] ? " s1=%02x,%03x,%02x" : " s1=%02x,%02x,%02x", | |
184 params[6], params[7], params[8]); | |
185 printf(params[5] ? " s2=%x,%03x,%02x" : " s2=%02x,%02x,%02x", | |
186 params[9], params[10], params[11]); | |
187 printf(params[5] ? " s3=%x,%03x,%02x" : " s3=%02x,%02x,%02x", | |
188 params[12], params[13], params[14]); | |
189 printf(params[5] ? " s4=%x,%03x,%02x\n" : " s4=%02x,%02x,%02x\n", | |
190 params[15], params[16], params[17]); | |
191 printf(" C6-C9: %u%u%u%u\n", frame[154], frame[155], frame[156], | |
192 frame[157]); | |
193 printf(" T1=%u T2=%u\n", frame[158], frame[159]); | |
194 } | |
195 | |
196 static void | |
197 process_filebuf() | |
198 { | |
199 unsigned p, endp; | |
200 int sync = 0, match; | |
201 | |
202 endp = total_size - 160; | |
203 for (p = 0; p < endp; ) { | |
204 match = check_sync(p); | |
205 if (match != sync) { | |
206 printf("# %s frame sync at file offset 0x%x\n", | |
207 match ? "Acquired" : "Lost", p); | |
208 } | |
209 if (match) { | |
210 process_frame(p); | |
211 if (!filebuf[p+158] && !filebuf[p+159]) { | |
212 printf( | |
213 "# both T bits equal 0, shifting frame alignment\n"); | |
214 p += 158; | |
215 } else | |
216 p += 160; | |
217 } else | |
218 p++; | |
219 sync = match; | |
220 } | |
221 } | |
222 | |
223 main(argc, argv) | |
224 char **argv; | |
225 { | |
226 if (argc != 3) { | |
227 fprintf(stderr, "usage: %s binfile subslot\n", argv[0]); | |
228 exit(1); | |
229 } | |
230 read_ts_file(argv[1], argv[2]); | |
231 process_filebuf(); | |
232 exit(0); | |
233 } |