FreeCalypso > hg > gsm-net-reveng
view trau-decode/parse-new16.c @ 115:62b3b916c0a4 default tip
trau-decode: add inst-progs list
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Mon, 22 Dec 2025 08:37:22 +0000 |
| parents | 382a80f91149 |
| children |
line wrap: on
line source
/* * This program reads a 64 kbit/s timeslot recording file, examines one * of the four 16 kbit/s subslots (selected), looks for GSM 08.60 TRAU * frames, and dumps whatever it finds. The present version is a new one, * put together for the purpose of reverse-engineering Abis output from * Nokia BTS, which exhibits more complex behaviour than what our original * trau-parse program can analyze properly. */ #include <sys/types.h> #include <sys/file.h> #include <sys/stat.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> static uint8_t *filebuf; static unsigned total_size; static enum { NOT_D144, D144_SYNC, D144_EDATA, } d144_state; static void read_ts_file(filename, subslot_arg) char *filename, *subslot_arg; { FILE *inf; struct stat st; int subslot, right_shift; unsigned n; uint8_t *dp; int b; inf = fopen(filename, "r"); if (!inf) { perror(filename); exit(1); } fstat(fileno(inf), &st); if (!S_ISREG(st.st_mode)) { fprintf(stderr, "error: %s is not a regular file\n", filename); exit(1); } total_size = st.st_size; if (total_size < 160) { fprintf(stderr, "error: %s is too short\n", filename); exit(1); } filebuf = malloc(total_size); if (!filebuf) { perror("malloc of file size"); exit(1); } subslot = atoi(subslot_arg); if (subslot < 0 || subslot > 3) { fprintf(stderr, "error: invalid subslot argument\n"); exit(1); } right_shift = (3 - subslot) * 2; dp = filebuf; for (n = 0; n < total_size; n++) { b = getc(inf); if (b < 0) { fprintf(stderr, "error: getc() returned EOF contrary to st_size\n"); exit(1); } *dp++ = (b >> right_shift) & 3; } fclose(inf); } static int check_sync(pos) unsigned pos; { uint8_t *cand = filebuf + pos; unsigned n; for (n = 0; n < 8; n++) { if (cand[n]) return 0; } if (!(cand[8] & 2)) return 0; if (cand[8] == 3 && cand[9] == 3 && cand[10] == 3 && (d144_state == D144_SYNC || d144_state == D144_EDATA)) return 1; for (n = 2; n < 20; n++) { if (!(cand[n * 8] & 2)) return 0; } return 1; } static void unpack_dibits(in_frame_2bit, frame_bits) uint8_t *in_frame_2bit, *frame_bits; { int i, inb; uint8_t *op; op = frame_bits; for (i = 0; i < 160; i++) { inb = in_frame_2bit[i]; if (inb & 2) *op++ = 1; else *op++ = 0; if (inb & 1) *op++ = 1; else *op++ = 0; } } static unsigned bits_to_num(bits, nbits) uint8_t *bits; unsigned nbits; { unsigned accum; unsigned n; accum = 0; for (n = 0; n < nbits; n++) { accum <<= 1; if (*bits) accum |= 1; bits++; } return accum; } static void dump_raw_nibbles(dibits, num_dibits) uint8_t *dibits; unsigned num_dibits; { uint8_t *sp = dibits; unsigned remain = num_dibits; if (remain >= 2) { while (remain >= 2) { printf("%x", (sp[0] << 2) | sp[1]); sp += 2; remain -= 2; } putchar('\n'); } if (remain) printf("dribble %u%u\n", (*sp & 2) >> 1, (*sp & 1) >> 0); } static int process_frame(pos) unsigned pos; { uint8_t *frame_2b = filebuf + pos; uint8_t frame_bits[320]; unsigned c1_5, c6_11; printf("Frame at 0x%x:\n", pos); dump_raw_nibbles(frame_2b, 160); unpack_dibits(frame_2b, frame_bits); printf(" C1-C5: %u%u%u%u%u", frame_bits[17], frame_bits[18], frame_bits[19], frame_bits[20], frame_bits[21]); c1_5 = bits_to_num(frame_bits + 17, 5); switch (c1_5) { case 0x02: fputs(" (FR UL)", stdout); break; case 0x1C: fputs(" (FR DL)", stdout); break; case 0x1A: fputs(" (EFR)", stdout); break; case 0x10: fputs(" (idle UL)", stdout); break; case 0x0E: fputs(" (idle DL)", stdout); break; case 0x08: fputs(" (data UL)", stdout); break; case 0x16: fputs(" (data DL)", stdout); break; case 0x09: fputs(" (HR data UL)", stdout); break; case 0x17: fputs(" (HR data DL)", stdout); break; case 0x14: fputs(" (D144 sync)", stdout); break; case 0x1F: fputs(" (E-TRAU)", stdout); break; case 0x06: fputs(" (AMR)", stdout); break; } putchar('\n'); if (c1_5 == 0x14) d144_state = D144_SYNC; else if (c1_5 == 0x1F && (d144_state == D144_SYNC || d144_state == D144_EDATA)) d144_state = D144_EDATA; else d144_state = NOT_D144; switch (c1_5) { case 0x02: case 0x1C: case 0x1A: case 0x10: case 0x0E: c6_11 = bits_to_num(frame_bits + 22, 6); printf(" C6-C11: %u\n", c6_11); printf(" C12=%u C13=%u C14=%u C15=%u\n", frame_bits[28], frame_bits[29], frame_bits[30], frame_bits[31]); print_fr_efr_frame(frame_bits, c1_5); printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", frame_bits[310], frame_bits[311], frame_bits[312], frame_bits[313], frame_bits[314], frame_bits[315]); printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317], frame_bits[318], frame_bits[319]); return 1; case 0x08: case 0x09: case 0x16: case 0x17: case 0x14: print_data_frame(frame_bits); return 0; case 0x1F: print_edata_frame(frame_bits); return 0; case 0x06: print_amr_frame(frame_bits); return 1; default: printf(" C6-C15: %u%u%u%u%u%u%u%u%u%u\n", frame_bits[22], frame_bits[23], frame_bits[24], frame_bits[25], frame_bits[26], frame_bits[27], frame_bits[28], frame_bits[29], frame_bits[30], frame_bits[31]); printf(" C16=%u C17=%u C18=%u C19=%u C20=%u C21=%u\n", frame_bits[310], frame_bits[311], frame_bits[312], frame_bits[313], frame_bits[314], frame_bits[315]); printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317], frame_bits[318], frame_bits[319]); return 0; } } static void process_filebuf() { unsigned p, nf_pos = 0, nf_accum = 0; int match, have_t_bits; d144_state = NOT_D144; for (p = 0; p < total_size; ) { if ((total_size - p) >= 160) match = check_sync(p); else match = 0; if (match) { if (nf_accum) { printf("Non-frame at 0x%x:\n", nf_pos); dump_raw_nibbles(filebuf + nf_pos, nf_accum); } have_t_bits = process_frame(p); if (have_t_bits && filebuf[p+158] == 0 && filebuf[p+159] == 0) { puts("advance of 250 us"); p += 158; } else if (have_t_bits && filebuf[p+158] == 3 && filebuf[p+159] == 0) { puts("advance of 125 us"); p += 159; } else p += 160; nf_pos = p; nf_accum = 0; } else { p++; nf_accum++; if (nf_accum >= 160) { printf("Non-frame at 0x%x:\n", nf_pos); dump_raw_nibbles(filebuf + nf_pos, nf_accum); nf_pos = p; nf_accum = 0; } d144_state = NOT_D144; } } if (nf_accum) { printf("Non-frame at 0x%x:\n", nf_pos); dump_raw_nibbles(filebuf + nf_pos, nf_accum); } } main(argc, argv) char **argv; { if (argc != 3) { fprintf(stderr, "usage: %s binfile subslot\n", argv[0]); exit(1); } read_ts_file(argv[1], argv[2]); process_filebuf(); exit(0); }
