diff --git a/src/e1cap_dump.c b/src/e1cap_dump.c index 48741f4..7bbb71e 100644 --- a/src/e1cap_dump.c +++ b/src/e1cap_dump.c @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -17,8 +18,20 @@ struct e1_recorder g_recorder; enum mode { MODE_PRINT, MODE_BIN, + MODE_SC, }; +#define MAX_TS 32 +#define CHUNK_BYTES 160 + +/* Ericsson super-channel */ +struct sc_state { + uint8_t ts_data[MAX_TS][CHUNK_BYTES]; + uint8_t num_ts; +}; + +static struct sc_state g_sc_state[2]; + static enum mode g_mode = MODE_PRINT; static int g_filter_line = -1; static int g_filter_slot = -1; @@ -39,6 +52,58 @@ static char *timeval2str(struct timeval *tv) return buf; } +static int all_bytes_are(unsigned char ch, const uint8_t *data, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (data[i] != ch) + return 0; + } + return 1; +} + +static void handle_sc_out(struct sc_state *scs) +{ + uint8_t out[scs->num_ts * CHUNK_BYTES]; + int i, j, k = 0; + + /* re-shuffle the data from columns to lines */ + for (i = 0; i < CHUNK_BYTES; i++) { + for (j = 1; j < scs->num_ts; j++) + out[k++] = scs->ts_data[j][i]; + } + printf("%s\n", osmo_hexdump_nospc(out, scs->num_ts * CHUNK_BYTES)); +} + +static void handle_sc_in(struct osmo_e1cap_pkthdr *pkt, const uint8_t *data, unsigned int len) +{ + struct sc_state *scs; + + if (pkt->line_nr >= ARRAY_SIZE(g_sc_state)) { + fprintf(stderr, "Line number out of range\n"); + exit(1); + } + + scs = &g_sc_state[pkt->line_nr]; + if (pkt->ts_nr >= ARRAY_SIZE(scs->ts_data)) { + fprintf(stderr, "Timeslot number out of range\n"); + exit(1); + } + + if (len != sizeof(scs->ts_data[pkt->ts_nr])) { + fprintf(stderr, "Insufficient data\n"); + exit(1); + } + + memcpy(scs->ts_data[pkt->ts_nr], data, len); + if (pkt->ts_nr-1 > scs->num_ts) + scs->num_ts = pkt->ts_nr-1; + if (pkt->ts_nr == scs->num_ts) + handle_sc_out(scs); +} + + static void handle_data(struct osmo_e1cap_pkthdr *pkt, const uint8_t *data, int len) { switch (g_mode) { @@ -52,6 +117,9 @@ static void handle_data(struct osmo_e1cap_pkthdr *pkt, const uint8_t *data, int case MODE_BIN: write(1, data, len); break; + case MODE_SC: + handle_sc_in(pkt, data, len); + break; } } @@ -68,7 +136,7 @@ static int handle_options(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "l:s:bu:")) != -1) { + while ((opt = getopt(argc, argv, "l:s:bSu:")) != -1) { switch (opt) { case 'l': /* Filter on E1 Line Number */ g_filter_line = atoi(optarg); @@ -79,6 +147,9 @@ static int handle_options(int argc, char **argv) case 'b': /* Raw binary output mode (for piping) */ g_mode = MODE_BIN; break; + case 'S': /* Super Channel Mode */ + g_mode = MODE_SC; + break; case 'u': /* 16k Sub-channel demux + filter */ g_filter_subslot = atoi(optarg); if (g_filter_subslot < 0 || g_filter_subslot > 3)