From 431471dd7c209476aac214440fd620c6272e8b00 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sat, 3 Sep 2011 00:27:12 +0200 Subject: [HACK] host/layer23: Wire application logic for a simple demo sniff app This listen for IMM.ASS and follows them Signed-off-by: Sylvain Munaut --- src/host/layer23/src/misc/app_ccch_scan.c | 166 +++++++++++++++++++++++++++--- 1 file changed, 151 insertions(+), 15 deletions(-) diff --git a/src/host/layer23/src/misc/app_ccch_scan.c b/src/host/layer23/src/misc/app_ccch_scan.c index f92b13ba..7bc85bf1 100644 --- a/src/host/layer23/src/misc/app_ccch_scan.c +++ b/src/host/layer23/src/misc/app_ccch_scan.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -41,12 +42,24 @@ #include +enum dch_state_t { + DCH_NONE, + DCH_WAIT_EST, + DCH_ACTIVE, + DCH_WAIT_REL, +}; + static struct { - int has_si1; - int ccch_mode; - int ccch_enabled; - int rach_count; - struct gsm_sysinfo_freq cell_arfcns[1024]; + int has_si1; + int ccch_mode; + + enum dch_state_t dch_state; + uint8_t dch_nr; + int dch_badcnt; + + FILE * fh; + + struct gsm_sysinfo_freq cell_arfcns[1024]; } app_state; @@ -177,12 +190,15 @@ static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms) { struct gsm48_imm_ass *ia = msgb_l3(msg); uint8_t ch_type, ch_subch, ch_ts; + int rv; /* Discard packet TBF assignement */ if (ia->page_mode & 0xf0) return 0; - /* FIXME: compare RA and GSM time with when we sent RACH req */ + /* If we're not ready yet, or just busy ... */ + if ((!app_state.has_si1) || (app_state.dch_state != DCH_NONE)) + return 0; rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts); @@ -197,6 +213,10 @@ static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms) ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch, ia->chan_desc.h0.tsc); + /* request L1 to go to dedicated mode on assigned channel */ + rv = l1ctl_tx_dm_est_req_h0(ms, + arfcn, ia->chan_desc.chan_nr, ia->chan_desc.h0.tsc, + GSM48_CMODE_SIGN, 0); } else { /* Hopping */ uint8_t maio, hsn, ma_len; @@ -223,10 +243,22 @@ static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms) j++; } } + + /* request L1 to go to dedicated mode on assigned channel */ + rv = l1ctl_tx_dm_est_req_h1(ms, + maio, hsn, ma, ma_len, + ia->chan_desc.chan_nr, ia->chan_desc.h1.tsc, + GSM48_CMODE_SIGN, 0); } LOGPC(DRR, LOGL_NOTICE, "\n"); - return 0; + + /* Set state */ + app_state.dch_state = DCH_WAIT_EST; + app_state.dch_nr = ia->chan_desc.chan_nr; + app_state.dch_badcnt = 0; + + return rv; } static const char *pag_print_mode(int mode) @@ -411,6 +443,10 @@ int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms) struct gsm48_system_information_type_header *sih = msgb_l3(msg); int rc = 0; + /* CCCH marks the end of WAIT_REL */ + if (app_state.dch_state == DCH_WAIT_REL) + app_state.dch_state = DCH_NONE; + if (sih->rr_protocol_discriminator != GSM48_PDISC_RR) LOGP(DRR, LOGL_ERROR, "PCH pdisc != RR\n"); @@ -444,19 +480,109 @@ int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms) int gsm48_rx_bcch(struct msgb *msg, struct osmocom_ms *ms) { + /* BCCH marks the end of WAIT_REL */ + if (app_state.dch_state == DCH_WAIT_REL) + app_state.dch_state = DCH_NONE; + /* FIXME: we have lost the gsm frame time until here, need to store it * in some msgb context */ //dump_bcch(dl->time.tc, ccch->data); dump_bcch(ms, 0, msg->l3h); - /* Req channel logic */ - if (app_state.ccch_enabled && (app_state.rach_count < 2)) { - l1ctl_tx_rach_req(ms, app_state.rach_count, 0, - app_state.ccch_mode == CCCH_MODE_COMBINED); - app_state.rach_count++; + return 0; +} + +static char * +gen_filename(struct osmocom_ms *ms, struct l1ctl_burst_ind *bi) +{ + static char buffer[256]; + time_t d; + struct tm lt; + + time(&d); + localtime_r(&d, <); + + snprintf(buffer, 256, "bursts_%04d%02d%02d_%02d%02d_%d_%d_%02x.dat", + lt.tm_year + 1900, lt.tm_mon, lt.tm_mday, + lt.tm_hour, lt.tm_min, + ms->test_arfcn, + ntohl(bi->frame_nr), + bi->chan_nr + ); + + return buffer; +} + +void layer3_rx_burst(struct osmocom_ms *ms, struct msgb *msg) +{ + struct l1ctl_burst_ind *bi; + int16_t rx_dbm; + uint16_t arfcn; + int ul, do_rel=0; + + /* Header handling */ + bi = (struct l1ctl_burst_ind *) msg->l1h; + + arfcn = ntohs(bi->band_arfcn); + rx_dbm = rxlev2dbm(bi->rx_level); + ul = !!(arfcn & ARFCN_UPLINK); + + /* Check for channel start */ + if (app_state.dch_state == DCH_WAIT_EST) { + if (bi->chan_nr == app_state.dch_nr) { + if (bi->snr > 64) { + /* Change state */ + app_state.dch_state = DCH_ACTIVE; + app_state.dch_badcnt = 0; + + /* Open output */ + app_state.fh = fopen(gen_filename(ms, bi), "wb"); + } else { + /* Abandon ? */ + do_rel = (app_state.dch_badcnt++) >= 4; + } + } } - return 0; + /* Check for channel end */ + if (app_state.dch_state == DCH_ACTIVE) { + if (!ul) { + /* Bad burst counting */ + if (bi->snr < 64) + app_state.dch_badcnt++; + else if (app_state.dch_badcnt >= 2) + app_state.dch_badcnt -= 2; + else + app_state.dch_badcnt = 0; + + /* Release condition */ + do_rel = app_state.dch_badcnt >= 6; + } + } + + /* Release ? */ + if (do_rel) { + /* L1 release */ + l1ctl_tx_dm_rel_req(ms); + l1ctl_tx_fbsb_req(ms, ms->test_arfcn, + L1CTL_FBSB_F_FB01SB, 100, 0, + app_state.ccch_mode); + + /* Change state */ + app_state.dch_state = DCH_WAIT_REL; + app_state.dch_badcnt = 0; + + /* Close output */ + if (app_state.fh) { + fclose(app_state.fh); + app_state.fh = NULL; + } + } + + /* Save the burst */ + if (app_state.dch_state == DCH_ACTIVE) + fwrite(bi, sizeof(*bi), 1, app_state.fh); + } void layer3_app_reset(void) @@ -464,8 +590,12 @@ void layer3_app_reset(void) /* Reset state */ app_state.has_si1 = 0; app_state.ccch_mode = CCCH_MODE_NONE; - app_state.ccch_enabled = 0; - app_state.rach_count = 0; + app_state.dch_state = DCH_NONE; + app_state.dch_badcnt = 0; + + if (app_state.fh) + fclose(app_state.fh); + app_state.fh = NULL; memset(&app_state.cell_arfcns, 0x00, sizeof(app_state.cell_arfcns)); } @@ -474,11 +604,17 @@ static int signal_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { struct osmocom_ms *ms; + struct osmobb_msg_ind *mi; if (subsys != SS_L1CTL) return 0; switch (signal) { + case S_L1CTL_BURST_IND: + mi = signal_data; + layer3_rx_burst(mi->ms, mi->msg); + break; + case S_L1CTL_RESET: ms = signal_data; layer3_app_reset(); -- cgit v1.2.3