From 5e6282cdba97e7ef01e584750ffae4a6181ee1bb Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 3 Sep 2011 08:26:49 +0200 Subject: [HACK] host/layer23: Add local burst processing for cleartext bursts Signed-off-by: Sylvain Munaut --- src/host/layer23/include/osmocom/bb/misc/xcch.h | 15 +++ src/host/layer23/src/misc/Makefile.am | 2 +- src/host/layer23/src/misc/app_ccch_scan.c | 101 ++++++++++++++++ src/host/layer23/src/misc/xcch.c | 153 ++++++++++++++++++++++++ 4 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 src/host/layer23/include/osmocom/bb/misc/xcch.h create mode 100644 src/host/layer23/src/misc/xcch.c 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 + */ + +#ifndef __XCCH_H__ +#define __XCCH_H__ + +#include +#include + +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 #include +#include + #include #include #include @@ -32,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -42,6 +46,10 @@ #include +#include + +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 + */ + +#include +#include +#include + +#include +#include + + +/* + * 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; +} -- cgit v1.2.3