FreeCalypso > hg > gsm-net-reveng
view tfo/tfo-trace-msg.c @ 56:b32b644b7d96
d144/nokia-tcsm2-atrau.bin: captured A-TRAU output from
Nokia TCSM2, fed with ul-input from Ater
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 25 Sep 2024 07:42:04 +0000 |
parents | f6bb790e186a |
children |
line wrap: on
line source
/* * This program reads a raw binary file that contains a recording of * a T1/E1 timeslot on the MSC side of a TRAU, analyzes it looking for * TFO IS messages, and prints whatever it finds. */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #define MAX_EXT_WORDS 5 static uint8_t is_hunt_buf[320]; static int is_state; static unsigned is_hunt_fill; static unsigned is_offset; static unsigned is_file_offset; static unsigned is_bit_count; static uint32_t is_rx_word, is_cmd, is_ext_words[MAX_EXT_WORDS]; static unsigned is_ext_count; static const u_char hdr_pattern[20] = {0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1}; static void is_rx_hunt(cur_file_offset) unsigned cur_file_offset; { unsigned offset, n; for (offset = 0; offset < 16; offset++) { for (n = 0; n < 20; n++) if ((is_hunt_buf[offset + n*16] & 1) != hdr_pattern[n]) break; if (n == 20) break; } if (n != 20) return; is_offset = offset; is_file_offset = cur_file_offset - 19*16 + offset; is_state = 1; is_bit_count = 0; is_rx_word = 0; is_hunt_fill = 0; } static void is_process_cmd() { int cont; printf("0x%x: ", is_file_offset); is_cmd = is_rx_word; switch (is_cmd) { case 0x05D: printf("IS_REQ\n"); cont = 1; break; case 0x0BA: printf("IS_ACK\n"); cont = 1; break; case 0x0E7: printf("IS_IPE\n"); cont = 1; break; case 0x129: printf("IS_FILL\n"); cont = 0; break; case 0x174: printf("IS_DUP\n"); cont = 0; break; case 0x193: printf("IS_SYL\n"); cont = 0; break; default: printf("unknown IS_Command 0x%03X\n", (unsigned) is_cmd); cont = 0; } if (cont) { is_state = 2; is_bit_count = 0; is_rx_word = 0; is_ext_count = 0; } else is_state = 0; } static void process_tfo_req_ack(reqack) char *reqack; { if (is_ext_count < 2) return; if (is_ext_words[0] != 0x5394B) /* GSM System ID */ return; printf(" TFO_%s: List_Ind=%u Sig=0x%02X CoID=0x%X CRC=%u\n", reqack, (is_ext_words[1] >> 18) & 1, (is_ext_words[1] >> 10) & 0xFF, (is_ext_words[1] >> 5) & 0xF, (is_ext_words[1] >> 2) & 7); } static void is_process_high_level() { switch (is_cmd) { case 0x05D: process_tfo_req_ack("REQ"); break; case 0x0BA: process_tfo_req_ack("ACK"); break; } } static void is_process_ext() { printf(" IS_Extension: 0x%05X", (unsigned) is_rx_word); if (is_rx_word & 0x80200) { printf(" (bad sync)\n"); is_state = 0; return; } if (is_ext_count < MAX_EXT_WORDS) is_ext_words[is_ext_count++] = is_rx_word; switch (is_rx_word & 3) { case 0: printf(" (final)\n"); is_state = 0; is_process_high_level(); return; case 3: printf(" (continue)\n"); is_state = 2; is_bit_count = 0; is_rx_word = 0; return; default: printf(" (bad EX)\n"); is_state = 0; } } static void is_rx_process(input, cur_file_offset) uint8_t *input; unsigned cur_file_offset; { unsigned new_bit; memmove(is_hunt_buf, is_hunt_buf + 16, 304); memcpy(is_hunt_buf + 304, input, 16); if (!is_state) { if (is_hunt_fill < 20) is_hunt_fill++; if (is_hunt_fill == 20) is_rx_hunt(cur_file_offset); return; } new_bit = input[is_offset] & 1; is_rx_word <<= 1; is_rx_word |= new_bit; is_bit_count++; if (is_state == 1 && is_bit_count == 10) is_process_cmd(); else if (is_state == 2 && is_bit_count == 20) is_process_ext(); } main(argc, argv) char **argv; { FILE *inf; uint8_t chunk[16]; unsigned file_offset; int cc; if (argc != 2) { fprintf(stderr, "usage: %s pcm-capture-file\n", argv[0]); exit(1); } inf = fopen(argv[1], "r"); if (!inf) { perror(argv[1]); exit(1); } for (file_offset = 0; ; file_offset += 16) { cc = fread(chunk, 1, 16, inf); if (cc == 0) break; if (cc != 16) { fprintf(stderr, "error: read of 16 bytes returned %d\n", cc); exit(1); } is_rx_process(chunk, file_offset); } exit(0); }