aboutsummaryrefslogtreecommitdiffstats
path: root/src/e1cap_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/e1cap_dump.c')
-rw-r--r--src/e1cap_dump.c73
1 files changed, 72 insertions, 1 deletions
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 <stdio.h>
#include <time.h>
#include <unistd.h>
+#include <string.h>
#include <sys/time.h>
@@ -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)