summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2011-09-03 08:26:49 +0200
committerSylvain Munaut <tnt@246tNt.com>2011-11-13 20:26:22 +0100
commit5e6282cdba97e7ef01e584750ffae4a6181ee1bb (patch)
tree9bd30c61c32e4885250e22619d057bd85a6b7f45
parenta5c487aafa98cd567e799382a56cf4c8ba0c3dff (diff)
[HACK] host/layer23: Add local burst processing for cleartext bursts
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r--src/host/layer23/include/osmocom/bb/misc/xcch.h15
-rw-r--r--src/host/layer23/src/misc/Makefile.am2
-rw-r--r--src/host/layer23/src/misc/app_ccch_scan.c101
-rw-r--r--src/host/layer23/src/misc/xcch.c153
4 files changed, 270 insertions, 1 deletions
diff --git a/src/host/layer23/include/osmocom/bb/misc/xcch.h b/src/host/layer23/include/osmocom/bb/misc/xcch.h
new file mode 100644
index 00000000..9fe42957
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/misc/xcch.h
@@ -0,0 +1,15 @@
+/*
+ * xcch.h
+ *
+ * Copyright (c) 2011 Sylvain Munaut <tnt@246tNt.com>
+ */
+
+#ifndef __XCCH_H__
+#define __XCCH_H__
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+int xcch_decode(uint8_t *l2_data, sbit_t *bursts);
+
+#endif /* __XCCH_H__ */
diff --git a/src/host/layer23/src/misc/Makefile.am b/src/host/layer23/src/misc/Makefile.am
index 0b59f389..a581e212 100644
--- a/src/host/layer23/src/misc/Makefile.am
+++ b/src/host/layer23/src/misc/Makefile.am
@@ -5,7 +5,7 @@ LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOC
bin_PROGRAMS = bcch_scan ccch_scan echo_test cell_log cbch_sniff
bcch_scan_SOURCES = ../common/main.c app_bcch_scan.c bcch_scan.c
-ccch_scan_SOURCES = ../common/main.c app_ccch_scan.c rslms.c
+ccch_scan_SOURCES = ../common/main.c app_ccch_scan.c rslms.c xcch.c
echo_test_SOURCES = ../common/main.c app_echo_test.c
cell_log_LDADD = $(LDADD) -lm
cell_log_SOURCES = ../common/main.c app_cell_log.c cell_log.c \
diff --git a/src/host/layer23/src/misc/app_ccch_scan.c b/src/host/layer23/src/misc/app_ccch_scan.c
index f17cfe92..3dc5279c 100644
--- a/src/host/layer23/src/misc/app_ccch_scan.c
+++ b/src/host/layer23/src/misc/app_ccch_scan.c
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <time.h>
+#include <arpa/inet.h>
+
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/rsl.h>
#include <osmocom/gsm/tlv.h>
@@ -32,6 +34,8 @@
#include <osmocom/gsm/gsm48.h>
#include <osmocom/core/signal.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/core/gsmtap_util.h>
+#include <osmocom/core/bits.h>
#include <osmocom/bb/common/logging.h>
#include <osmocom/bb/misc/rslms.h>
@@ -42,6 +46,10 @@
#include <l1ctl_proto.h>
+#include <osmocom/bb/misc/xcch.h>
+
+extern struct gsmtap_inst *gsmtap_inst;
+
enum dch_state_t {
DCH_NONE,
DCH_WAIT_EST,
@@ -59,6 +67,9 @@ static struct {
FILE * fh;
+ sbit_t bursts_dl[116 * 4];
+ sbit_t bursts_ul[116 * 4];
+
struct gsm_sysinfo_freq cell_arfcns[1024];
} app_state;
@@ -465,6 +476,93 @@ int gsm48_rx_bcch(struct msgb *msg, struct osmocom_ms *ms)
return 0;
}
+
+static void
+local_burst_decode(struct l1ctl_burst_ind *bi)
+{
+ int16_t rx_dbm;
+ uint16_t arfcn;
+ uint8_t cbits, tn, lch_idx;
+ int ul, bid, i;
+ sbit_t *bursts;
+ ubit_t bt[116];
+
+ /* Get params (Only for SDCCH and SACCH/{4,8,F,H}) */
+ arfcn = ntohs(bi->band_arfcn);
+ rx_dbm = rxlev2dbm(bi->rx_level);
+
+ ul = !!(arfcn & ARFCN_UPLINK);
+ bursts = ul ? app_state.bursts_ul : app_state.bursts_dl;
+
+ cbits = bi->chan_nr >> 3;
+ tn = bi->chan_nr & 7;
+
+ bid = -1;
+
+ if (cbits == 0x01) { /* TCH/F */
+ lch_idx = 0;
+ if (bi->flags & BI_FLG_SACCH) {
+ uint32_t fn_report;
+ fn_report = (ntohl(bi->frame_nr) - (tn * 13) + 104) % 104;
+ bid = (fn_report - 12) / 26;
+ }
+ } else if ((cbits & 0x1e) == 0x02) { /* TCH/H */
+ lch_idx = cbits & 1;
+ if (bi->flags & BI_FLG_SACCH) {
+ uint32_t fn_report;
+ uint8_t tn_report = (tn & ~1) | lch_idx;
+ fn_report = (ntohl(bi->frame_nr) - (tn_report * 13) + 104) % 104;
+ bid = (fn_report - 12) / 26;
+ }
+ } else if ((cbits & 0x1c) == 0x04) { /* SDCCH/4 */
+ lch_idx = cbits & 3;
+ bid = bi->flags & 3;
+ } else if ((cbits & 0x18) == 0x08) { /* SDCCH/8 */
+ lch_idx = cbits & 7;
+ bid = bi->flags & 3;
+ }
+
+ if (bid == -1)
+ return;
+
+ /* Clear if new set */
+ if (bid == 0)
+ memset(bursts, 0x00, 116 * 4);
+
+ /* Unpack (ignore hu/hl) */
+ osmo_pbit2ubit_ext(bt, 0, bi->bits, 0, 57, 0);
+ osmo_pbit2ubit_ext(bt, 59, bi->bits, 57, 57, 0);
+ bt[57] = bt[58] = 1;
+
+ for (i=0; i<116; i++)
+ bursts[(116*bid)+i] = bt[i] ? - (bi->snr >> 1) : (bi->snr >> 1);
+
+ /* If last, decode */
+ if (bid == 3)
+ {
+ uint8_t l2[23];
+ int rv;
+ rv = xcch_decode(l2, bursts);
+
+ if (rv == 0)
+ {
+ uint8_t chan_type, chan_ts, chan_ss;
+ uint8_t gsmtap_chan_type;
+
+ rsl_dec_chan_nr(bi->chan_nr, &chan_type, &chan_ss, &chan_ts);
+ gsmtap_chan_type = chantype_rsl2gsmtap(
+ chan_type,
+ bi->flags & BI_FLG_SACCH ? 0x40 : 0x00
+ );
+ gsmtap_send(gsmtap_inst,
+ arfcn, chan_ts, gsmtap_chan_type, chan_ss,
+ ntohl(bi->frame_nr), bi->rx_level, bi->snr,
+ l2, sizeof(l2)
+ );
+ }
+ }
+}
+
static char *
gen_filename(struct osmocom_ms *ms, struct l1ctl_burst_ind *bi)
{
@@ -556,6 +654,9 @@ void layer3_rx_burst(struct osmocom_ms *ms, struct msgb *msg)
if (app_state.dch_state == DCH_ACTIVE)
fwrite(bi, sizeof(*bi), 1, app_state.fh);
+ /* Try local decoding */
+ if (app_state.dch_state == DCH_ACTIVE)
+ local_burst_decode(bi);
}
void layer3_app_reset(void)
diff --git a/src/host/layer23/src/misc/xcch.c b/src/host/layer23/src/misc/xcch.c
new file mode 100644
index 00000000..9da34fe8
--- /dev/null
+++ b/src/host/layer23/src/misc/xcch.c
@@ -0,0 +1,153 @@
+/*
+ * xcch.c
+ *
+ * Copyright (c) 2011 Sylvain Munaut <tnt@246tNt.com>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/conv.h>
+
+
+/*
+ * GSM xCCH parity (FIRE code)
+ *
+ * g(x) = (x^23 + 1)(x^17 + x^3 + 1)
+ * = x^40 + x^26 + x^23 + x^17 + x^3 + 1
+ */
+
+
+static int
+xcch_parity_check(ubit_t *d)
+{
+ const uint64_t poly = 0x0004820009ULL;
+ const uint64_t remainder = 0xffffffffffULL;
+ uint64_t crc = 0;
+ int i;
+
+ /* Compute CRC */
+ for (i=0; i<184; i++) {
+ uint64_t bit = d[i] & 1;
+ crc ^= (bit << 39);
+ if (crc & (1ULL<<39)) {
+ crc <<= 1;
+ crc ^= poly;
+ } else {
+ crc <<= 1;
+ }
+ crc &= (1ULL << 40) - 1;
+ }
+
+ crc ^= remainder;
+
+ /* Check it */
+ for (i=0; i<40; i++)
+ if (d[184+i] ^ ((crc >> (39-i)) & 1))
+ return 1;
+
+ return 0;
+}
+
+
+/*
+ * GSM xCCH convolutional coding
+ *
+ * G_0 = 1 + x^3 + x^4
+ * G_1 = 1 + x + x^3 + x^4
+ */
+
+static const uint8_t conv_xcch_next_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const uint8_t conv_xcch_next_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+const struct osmo_conv_code conv_xcch = {
+ .N = 2,
+ .K = 5,
+ .len = 224,
+ .next_output = conv_xcch_next_output,
+ .next_state = conv_xcch_next_state,
+};
+
+
+/*
+ * GSM xCCH interleaving and burst mapping
+ *
+ * Interleaving:
+ *
+ * Given 456 coded input bits, form 4 blocks of 114 bits:
+ *
+ * i(B, j) = c(n, k) k = 0, ..., 455
+ * n = 0, ..., N, N + 1, ...
+ * B = B_0 + 4n + (k mod 4)
+ * j = 2(49k mod 57) + ((k mod 8) div 4)
+ *
+ * Mapping on Burst:
+ *
+ * e(B, j) = i(B, j)
+ * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
+ * e(B, 57) = h_l(B)
+ * e(B, 58) = h_n(B)
+ *
+ * Where hl(B) and hn(B) are bits in burst B indicating flags.
+ */
+
+static void
+xcch_deinterleave(sbit_t *cB, sbit_t *iB)
+{
+ int j, k, B;
+
+ for (k=0; k<456; k++) {
+ B = k & 3;
+ j = 2 * ((49 * k) % 57) + ((k & 7) >> 2);
+ cB[k] = iB[B * 114 + j];
+ }
+}
+
+static void
+xcch_burst_unmap(sbit_t *iB, sbit_t *eB, sbit_t *hl, sbit_t *hn)
+{
+ memcpy(iB, eB, 57);
+ memcpy(iB+57, eB+59, 57);
+
+ if (hl)
+ *hl = eB[57];
+
+ if (hn)
+ *hn = eB[58];
+}
+
+int
+xcch_decode(uint8_t *l2_data, sbit_t *bursts)
+{
+ sbit_t iB[456], cB[456];
+ ubit_t conv[224];
+ int i, rv;
+
+ for (i=0; i<4; i++)
+ xcch_burst_unmap(&iB[i * 114], &bursts[i * 116], NULL, NULL);
+
+ xcch_deinterleave(cB, iB);
+
+ osmo_conv_decode(&conv_xcch, cB, conv);
+
+ rv = xcch_parity_check(conv);
+ if (rv)
+ return -1;
+
+ osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
+
+ return 0;
+}