FreeCalypso > hg > gsm-net-reveng
view trau-decode/parse-main.c @ 48:3d8cb2631812
trau-parse: show more info from AMR No_Speech frames
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 24 Sep 2024 19:40:47 +0000 |
parents | 7119884f6afe |
children | e579784e5578 |
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. */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> static unsigned file_offset; static int include_raw; static enum { HUNT_FOR_0, HUNT_FOUND_0, GOT_8_ZEROS, SYNCED } state; static enum { NOT_D144, D144_SYNC, D144_EDATA, } d144_state; static unsigned hunt_for_0_count, frame_pos_count; static uint8_t in_frame_2bit[160], frame_bits[320], d_bits[260]; static void unpack_dibits() { 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 collect_d_bits() { bcopy(frame_bits + 33, d_bits, 15); bcopy(frame_bits + 49, d_bits + 15, 15); bcopy(frame_bits + 65, d_bits + 30, 15); bcopy(frame_bits + 81, d_bits + 45, 15); bcopy(frame_bits + 97, d_bits + 60, 15); bcopy(frame_bits + 113, d_bits + 75, 15); bcopy(frame_bits + 129, d_bits + 90, 15); bcopy(frame_bits + 145, d_bits + 105, 15); bcopy(frame_bits + 161, d_bits + 120, 15); bcopy(frame_bits + 177, d_bits + 135, 15); bcopy(frame_bits + 193, d_bits + 150, 15); bcopy(frame_bits + 209, d_bits + 165, 15); bcopy(frame_bits + 225, d_bits + 180, 15); bcopy(frame_bits + 241, d_bits + 195, 15); bcopy(frame_bits + 257, d_bits + 210, 15); bcopy(frame_bits + 273, d_bits + 225, 15); bcopy(frame_bits + 289, d_bits + 240, 15); bcopy(frame_bits + 305, d_bits + 255, 5); } static void print_fr_efr_frame(c1_5) unsigned c1_5; { switch (c1_5) { case 0x02: case 0x1C: collect_d_bits(); print_fr_frame(d_bits); break; case 0x1A: collect_d_bits(); check_efr_crc(d_bits); print_efr_frame(d_bits); break; } } static void print_data_subframe(nf, bits) uint8_t *bits; { unsigned nb; printf(" Data frame %d:", nf); for (nb = 0; nb < 9; nb++) { printf(" %02X", bits_to_num(bits, 8)); bits += 8; } putchar('\n'); } static void print_data_frame() { print_data_subframe(0, frame_bits + 4 * 8); print_data_subframe(1, frame_bits + 13 * 8); print_data_subframe(2, frame_bits + 22 * 8); print_data_subframe(3, frame_bits + 31 * 8); } static void dump_raw_frame() { uint8_t *sp = frame_bits; unsigned n, m, d; for (n = 0; n < 80; n++) { d = 0; for (m = 0; m < 4; m++) { d <<= 1; d |= *sp++; } printf("%x", d); } putchar('\n'); } static void process_frame() { unsigned c1_5, c6_11; printf("Frame at 0x%x:\n", file_offset - 159); if (include_raw) dump_raw_frame(); 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(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]); break; case 0x08: case 0x09: case 0x16: case 0x17: case 0x14: 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]); print_data_frame(); break; case 0x1F: printf(" C6-C13: %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]); printf(" M1=%u M2=%u\n", frame_bits[30], frame_bits[31]); break; case 0x06: c6_11 = bits_to_num(frame_bits + 22, 6); printf(" C6-C11: %u\n", c6_11); printf(" RIF=%u C13=%u Config_Prot=%u%u%u Msg_No=%u%u\n", frame_bits[28], frame_bits[29], frame_bits[30], frame_bits[31], frame_bits[33], frame_bits[34], frame_bits[35]); printf(" DTXd=%u TFOE=%u FClass=%u%u CMI/CMR=%u%u%u\n", frame_bits[36], frame_bits[37], frame_bits[38], frame_bits[39], frame_bits[40], frame_bits[41], frame_bits[42]); if (!frame_bits[38] && !frame_bits[39]) printf(" No_Spch_Class=%u%u%u CMI=%u%u%u CMR=%u%u%u\n", frame_bits[76], frame_bits[77], frame_bits[78], frame_bits[79], frame_bits[81], frame_bits[82], frame_bits[83], frame_bits[84], frame_bits[85]); printf(" T1=%u T2=%u T3=%u T4=%u\n", frame_bits[316], frame_bits[317], frame_bits[318], frame_bits[319]); break; 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]); } } static int check_sync_zeros() { int i; for (i = 0; i < 16; i++) { if (frame_bits[i]) return 0; } return 1; } static int check_sync_ones() { int i; for (i = 1; i < 20; i++) { if (!frame_bits[i*16]) return 0; } return 1; } static void check_sync() { int sync_res; if (d144_state == D144_EDATA) sync_res = check_sync_zeros() && frame_bits[16]; else sync_res = check_sync_zeros() && check_sync_ones(); if (sync_res) return; printf("Bad frame sync, returning to hunt state\n"); state = HUNT_FOR_0; } static void byte_input(inb) { switch (state) { case HUNT_FOR_0: if (inb != 0) return; state = HUNT_FOUND_0; hunt_for_0_count = 1; return; case HUNT_FOUND_0: if (inb != 0) { state = HUNT_FOR_0; return; } hunt_for_0_count++; if (hunt_for_0_count >= 8) state = GOT_8_ZEROS; return; case GOT_8_ZEROS: if (inb & 2) { printf("Found frame sync at file offset 0x%x\n", file_offset - 8); bzero(in_frame_2bit, 8); in_frame_2bit[8] = inb; frame_pos_count = 9; state = SYNCED; return; } if (inb != 0) state = HUNT_FOR_0; return; case SYNCED: in_frame_2bit[frame_pos_count++] = inb; if (frame_pos_count < 160) return; frame_pos_count = 0; unpack_dibits(); process_frame(); check_sync(); return; default: fprintf(stderr, "BUG: bad sync state\n"); abort(); } } main(argc, argv) char **argv; { char *filename, *subslot_arg; FILE *inf; int subslot, right_shift; int inb; switch (argc) { case 3: filename = argv[1]; subslot_arg = argv[2]; include_raw = 0; break; case 4: if (strcmp(argv[1], "-r")) goto usage; filename = argv[2]; subslot_arg = argv[3]; include_raw = 1; break; default: usage: fprintf(stderr, "usage: %s [-r] binfile subslot\n", argv[0]); exit(1); } inf = fopen(filename, "r"); if (!inf) { perror(filename); 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; state = HUNT_FOR_0; d144_state = NOT_D144; for (file_offset = 0; ; file_offset++) { inb = getc(inf); if (inb < 0) break; inb >>= right_shift; inb &= 3; byte_input(inb); } exit(0); }