FreeCalypso > hg > gsm-net-reveng
view trau-decode/trau-hr-dump.c @ 49:e579784e5578
trau-parse: restore FR-like display for unknown frames
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 24 Sep 2024 19:49:45 +0000 |
parents | 61181373875d |
children |
line wrap: on
line source
/* * This program reads a 64 kbit/s timeslot recording file, examines one * of the eight 8 kbit/s subslots (selected), looks for the sync pattern of * GSM 08.61, decodes each frame as HRv1 speech and dumps everything it * decodes. */ #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> #include <unistd.h> #include "gsmhr_unpack.h" #include "osmo_bits.h" /* * EFR TRAU parity (also used for HR) * * g(x) = x^3 + x^1 + 1 */ static const struct osmo_crc8gen_code gsm0860_efr_crc3 = { .bits = 3, .poly = 0x3, .init = 0x0, .remainder = 0x7, }; static uint8_t *filebuf; static unsigned total_size; 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 > 7) { fprintf(stderr, "error: invalid subslot argument\n"); exit(1); } right_shift = 7 - subslot; 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) & 1; } 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]) return 0; if (cand[16]) return 0; if (!cand[17]) return 0; for (n = 3; n < 20; n++) { if (!cand[n * 8]) return 0; } return 1; } static int bit_parity(bits, nbits) ubit_t *bits; unsigned nbits; { unsigned n, sum; sum = 0; for (n = 0; n < nbits; n++) sum += bits[n]; return sum & 1; } static void bits2bytes(bits, bytes, nbytes) ubit_t *bits; uint8_t *bytes; unsigned nbytes; { unsigned n, m, acc; for (n = 0; n < nbytes; n++) { acc = 0; for (m = 0; m < 8; m++) { acc <<= 1; acc |= *bits++; } *bytes++ = acc; } } static void process_frame(pos) unsigned pos; { ubit_t *frame = filebuf + pos; ubit_t xc_bits[6], dbits[112]; uint8_t hr_bytes[14]; int16_t params[18]; int crc_stat; printf("Frame at 0x%x:\n", pos); printf(" C1-C4: %u%u%u%u OP %s\n", frame[9], frame[10], frame[11], frame[12], bit_parity(frame + 9, 5) ? "good" : "bad"); bcopy(frame + 14, xc_bits, 2); bcopy(frame + 18, xc_bits + 2, 4); printf(" XC1-XC5: %u%u%u%u%u OP %s\n", xc_bits[0], xc_bits[1], xc_bits[2], xc_bits[3], xc_bits[4], bit_parity(xc_bits, 6) ? "good" : "bad"); bcopy(frame + 22, dbits, 2); bcopy(frame + 25, dbits + 2, 7); bcopy(frame + 33, dbits + 9, 7); bcopy(frame + 41, dbits + 16, 7); bcopy(frame + 49, dbits + 23, 7); bcopy(frame + 57, dbits + 30, 7); bcopy(frame + 65, dbits + 37, 7); bcopy(frame + 76, dbits + 44, 4); bcopy(frame + 81, dbits + 48, 7); bcopy(frame + 89, dbits + 55, 7); bcopy(frame + 97, dbits + 62, 7); bcopy(frame + 105, dbits + 69, 7); bcopy(frame + 113, dbits + 76, 7); bcopy(frame + 121, dbits + 83, 7); bcopy(frame + 129, dbits + 90, 7); bcopy(frame + 137, dbits + 97, 7); bcopy(frame + 145, dbits + 104, 7); dbits[111] = frame[153]; crc_stat = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, dbits, 44, frame + 73); printf(" CRC %s\n", crc_stat ? "bad" : "good"); bits2bytes(dbits, hr_bytes, 14); gsmhr_unpack_ts101318(hr_bytes, params); printf(" R0=%02x LPC=%03x,%03x,%02x Int=%x Mode=%x\n", params[0], params[1], params[2], params[3], params[4], params[5]); printf(params[5] ? " s1=%02x,%03x,%02x" : " s1=%02x,%02x,%02x", params[6], params[7], params[8]); printf(params[5] ? " s2=%x,%03x,%02x" : " s2=%02x,%02x,%02x", params[9], params[10], params[11]); printf(params[5] ? " s3=%x,%03x,%02x" : " s3=%02x,%02x,%02x", params[12], params[13], params[14]); printf(params[5] ? " s4=%x,%03x,%02x\n" : " s4=%02x,%02x,%02x\n", params[15], params[16], params[17]); printf(" C6-C9: %u%u%u%u\n", frame[154], frame[155], frame[156], frame[157]); printf(" T1=%u T2=%u\n", frame[158], frame[159]); } static void process_filebuf() { unsigned p, endp; int sync = 0, match; endp = total_size - 160; for (p = 0; p <= endp; ) { match = check_sync(p); if (match != sync) { printf("# %s frame sync at file offset 0x%x\n", match ? "Acquired" : "Lost", p); } if (match) { process_frame(p); if (!filebuf[p+158] && !filebuf[p+159]) { printf( "# both T bits equal 0, shifting frame alignment\n"); p += 158; } else p += 160; } else p++; sync = match; } } 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); }