aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2016-10-23 19:36:14 +0200
committerHarald Welte <laforge@gnumonks.org>2016-10-23 19:36:14 +0200
commitc1b9cab053b1bc8affcdb197acbbca7f854f9957 (patch)
treecc01c8128bf179bd3dbbcb363d4458fe9b4e2fe3
parent4dc14a751b7c9ad0030d2cebb1f87b22bac1d5a4 (diff)
e1cap_dump: Add SC (Super Channel) mode
In the super channel mode, it seems the BTS transmits one byte in each timeslot, accross the entire link. This basically means that if you have a 10 byte long signalling message to be sent, its first byte will be in TS1 up until the tenth byte in TS10. As we are reading in 160 byte chunks from the E1 timeslots, we build a matrix with 160 columns (for each byte) and 24/30 rows (timeslots). So we write 24 times 160 bytes into the matrix. Once we have completed all timeslots, we start to read the matrix by reading byte 0 of each timeslot (in incrementing TS order), next byte 1 of each timeslot, ... until we end up having read 160 times 24 bytes from the matrix. The resulting bitstream needs to be HDLC-synchronized and the resulting messages passed up for further decoding.
-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)