Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* CCCH passive sniffer */
- /* (C) 2010-2011 by Holger Hans Peter Freyther
- * (C) 2010 by Harald Welte <laforge@gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
- #include <stdint.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <getopt.h>
- #include <string.h>
- #include <arpa/inet.h>
- #include <osmocom/core/msgb.h>
- #include <osmocom/gsm/rsl.h>
- #include <osmocom/gsm/tlv.h>
- #include <osmocom/gsm/gsm48_ie.h>
- #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/gsm/a5.h>
- #include <osmocom/bb/common/logging.h>
- #include <osmocom/bb/misc/rslms.h>
- #include <osmocom/bb/misc/layer3.h>
- #include <osmocom/bb/common/osmocom_data.h>
- #include <osmocom/bb/common/l1ctl.h>
- #include <osmocom/bb/common/l23_app.h>
- #include <l1ctl_proto.h>
- #include <osmocom/bb/misc/xcch.h>
- #include <codec.h>
- #include "conv_tch_afs.h"
- extern FILE *log_tmsi;
- extern struct gsmtap_inst *gsmtap_inst;
- FILE *d_speech_file;
- const unsigned char amr_nb_magic[6] = { 0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a };
- enum dch_state_t {
- DCH_NONE,
- CCCH_ACTIVE,
- DCH_WAIT_EST,
- DCH_ACTIVE,
- DCH_TCH,
- DCH_WAIT_REL,
- };
- static struct amr{
- uint8_t amr_acs;
- uint8_t start_mode;
- };
- static struct amr_current{
- uint8_t mode;
- uint8_t i;
- };
- static struct {
- int has_si1;
- int has_si3;
- int ccch_mode;
- int neci;
- int sys_count;
- enum dch_state_t dch_state;
- uint8_t dch_nr;
- int dch_badcnt;
- int dch_ciph;
- FILE * fh;
- sbit_t bursts_dl[116 * 4];
- sbit_t bursts_ul[116 * 4];
- sbit_t bursts_ccch[4][116*4];
- sbit_t mI[8][114];
- struct gsm_sysinfo_freq cell_arfcns[1024];
- uint8_t kc[8];
- uint8_t speed_mode;
- struct gsm48_ass_cmd ia;
- } app_state;
- 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, "voice_%04d%02d%02d_%02d%02d_%d_%d_%02x.amr",
- 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;
- }
- static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
- {
- if(app_state.dch_state == DCH_TCH)
- {
- //BCCH- SDCCH - BCCH -TCH
- struct gsm48_ass_cmd *ia;
- uint8_t ch_type, ch_subch, ch_ts;
- ia = &app_state.ia;
- rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
- if (!ia->chan_desc.h0.h) {
- /* Non-hopping */
- uint16_t arfcn;
- arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
- LOGP(DRR, LOGL_NOTICE, "ASS CMD(chan_nr=0x%02x, "
- "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ",
- 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 */
- l1ctl_tx_dm_est_req_h0(ms,
- arfcn, ia->chan_desc.chan_nr, ia->chan_desc.h0.tsc,
- GSM48_CMODE_SPEECH_EFR, 0);
- }
- else
- {
- printf("unsuport hopping!\n");
- }
- return;
- }
- struct gsm48_system_information_type_header *si_hdr;
- si_hdr = (struct gsm48_system_information_type_header *) data;
- /* GSM 05.02 ยง6.3.1.3 Mapping of BCCH data */
- switch (si_hdr->system_information) {
- case GSM48_MT_RR_SYSINFO_1:
- #ifdef BCCH_TC_CHECK
- if (tc != 0)
- LOGP(DRR, LOGL_ERROR, "SI1 on the wrong TC: %d\n", tc);
- #endif
- if (!app_state.has_si1) {
- struct gsm48_system_information_type_1 *si1 =
- (struct gsm48_system_information_type_1 *)data;
- gsm48_decode_freq_list(app_state.cell_arfcns,
- si1->cell_channel_description,
- sizeof(si1->cell_channel_description),
- 0xff, 0x01);
- app_state.has_si1 = 1;
- LOGP(DRR, LOGL_ERROR, "SI1 received.\n");
- }
- break;
- case GSM48_MT_RR_SYSINFO_2:
- #ifdef BCCH_TC_CHECK
- if (tc != 1)
- LOGP(DRR, LOGL_ERROR, "SI2 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_3:
- #ifdef BCCH_TC_CHECK
- if (tc != 2 && tc != 6)
- LOGP(DRR, LOGL_ERROR, "SI3 on the wrong TC: %d\n", tc);
- #endif
- if(!app_state.has_si3)
- {
- if (app_state.ccch_mode == CCCH_MODE_NONE) {
- struct gsm48_system_information_type_3 *si3 =
- (struct gsm48_system_information_type_3 *)data;
- //printf("si3->control_channel_desc.ccch_conf = %d\n",si3->control_channel_desc.ccch_conf);
- switch (si3->control_channel_desc.ccch_conf) {
- case RSL_BCCH_CCCH_CONF_1_C:
- app_state.ccch_mode = CCCH_MODE_COMBINED;
- break;
- case RSL_BCCH_CCCH_CONF_1_NC:
- app_state.ccch_mode = CCCH_MODE_NON_COMBINED;
- break;
- case RSL_BCCH_CCCH_CONF_2_NC:
- app_state.ccch_mode = CCCH_MODE_NON_COMBINED2;
- break;
- case RSL_BCCH_CCCH_CONF_3_NC:
- app_state.ccch_mode = CCCH_MODE_NON_COMBINED4;
- break;
- case RSL_BCCH_CCCH_CONF_4_NC:
- app_state.ccch_mode = CCCH_MODE_NON_COMBINED6;
- break;
- default:
- fprintf(stderr, "\tUnknown CCCH_MODE\n");
- return;
- }
- app_state.neci = si3->cell_sel_par.neci;
- app_state.has_si3 = 1;
- l1ctl_tx_ccch_mode_req(ms, app_state.ccch_mode);
- }
- }
- break;
- case GSM48_MT_RR_SYSINFO_4:
- #ifdef BCCH_TC_CHECK
- if (tc != 3 && tc != 7)
- LOGP(DRR, LOGL_ERROR, "SI4 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_5:
- break;
- case GSM48_MT_RR_SYSINFO_6:
- break;
- case GSM48_MT_RR_SYSINFO_7:
- #ifdef BCCH_TC_CHECK
- if (tc != 7)
- LOGP(DRR, LOGL_ERROR, "SI7 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_8:
- #ifdef BCCH_TC_CHECK
- if (tc != 3)
- LOGP(DRR, LOGL_ERROR, "SI8 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_9:
- #ifdef BCCH_TC_CHECK
- if (tc != 4)
- LOGP(DRR, LOGL_ERROR, "SI9 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_13:
- #ifdef BCCH_TC_CHECK
- if (tc != 4 && tc != 0)
- LOGP(DRR, LOGL_ERROR, "SI13 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_16:
- #ifdef BCCH_TC_CHECK
- if (tc != 6)
- LOGP(DRR, LOGL_ERROR, "SI16 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_17:
- #ifdef BCCH_TC_CHECK
- if (tc != 2)
- LOGP(DRR, LOGL_ERROR, "SI17 on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_2bis:
- #ifdef BCCH_TC_CHECK
- if (tc != 5)
- LOGP(DRR, LOGL_ERROR, "SI2bis on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_2ter:
- #ifdef BCCH_TC_CHECK
- if (tc != 5 && tc != 4)
- LOGP(DRR, LOGL_ERROR, "SI2ter on the wrong TC: %d\n", tc);
- #endif
- break;
- case GSM48_MT_RR_SYSINFO_5bis:
- break;
- case GSM48_MT_RR_SYSINFO_5ter:
- break;
- default:
- app_state.sys_count++;
- if(app_state.sys_count == 2)
- l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
- fprintf(stderr, "\tUnknown SI\n");
- break;
- };
- }
- /**
- * This method used to send a l1ctl_tx_dm_est_req_h0 or
- * a l1ctl_tx_dm_est_req_h1 to the layer1 to follow this
- * assignment. The code has been removed.
- */
- 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;
- uint8_t chan_req_val, chan_req_mask, ra;
- /* Discard packet TBF assignement */
- if (ia->page_mode & 0xf0)
- return 0;
- /* If we're not ready yet, or just busy ... */
- if ((!app_state.has_si1) || (!app_state.has_si3) || (app_state.dch_state != DCH_NONE))
- return 0;
- printf("imm_ra %x,################!\n",ia->req_ref.ra);
- rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
- if (!ia->chan_desc.h0.h) {
- /* Non-hopping */
- uint16_t arfcn;
- arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
- LOGP(DRR, LOGL_NOTICE, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
- "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
- 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;
- uint16_t ma[64], arfcn;
- int i, j, k;
- hsn = ia->chan_desc.h1.hsn;
- maio = ia->chan_desc.h1.maio_low | (ia->chan_desc.h1.maio_high << 2);
- LOGP(DRR, LOGL_NOTICE, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
- "HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
- ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch,
- ia->chan_desc.h1.tsc);
- /* decode mobile allocation */
- ma_len = 0;
- for (i=1, j=0; i<=1024; i++) {
- arfcn = i & 1023;
- if (app_state.cell_arfcns[arfcn].mask & 0x01) {
- k = ia->mob_alloc_len - (j>>3) - 1;
- if (ia->mob_alloc[k] & (1 << (j&7))) {
- ma[ma_len++] = arfcn;
- }
- 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");
- /* 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)
- {
- switch (mode) {
- case 0:
- return "Normal paging";
- case 1:
- return "Extended paging";
- case 2:
- return "Paging reorganization";
- case 3:
- return "Same as before";
- default:
- return "invalid";
- }
- }
- static char *chan_need(int need)
- {
- switch (need) {
- case 0:
- return "any";
- case 1:
- return "sdch";
- case 2:
- return "tch/f";
- case 3:
- return "tch/h";
- default:
- return "invalid";
- }
- }
- static char *mi_type_to_string(int type)
- {
- switch (type) {
- case GSM_MI_TYPE_NONE:
- return "none";
- case GSM_MI_TYPE_IMSI:
- return "imsi";
- case GSM_MI_TYPE_IMEI:
- return "imei";
- case GSM_MI_TYPE_IMEISV:
- return "imeisv";
- case GSM_MI_TYPE_TMSI:
- return "tmsi";
- default:
- return "invalid";
- }
- }
- /**
- * This can contain two MIs. The size checking is a bit of a mess.
- */
- static int gsm48_rx_paging_p1(struct msgb *msg, struct osmocom_ms *ms)
- {
- struct gsm48_paging1 *pag;
- int len1, len2, mi_type, tag;
- char mi_string[GSM48_MI_SIZE];
- /* is there enough room for the header + LV? */
- if (msgb_l3len(msg) < sizeof(*pag) + 2) {
- LOGP(DRR, LOGL_ERROR, "PagingRequest is too short.\n");
- return -1;
- }
- pag = msgb_l3(msg);
- len1 = pag->data[0];
- mi_type = pag->data[1] & GSM_MI_TYPE_MASK;
- if (msgb_l3len(msg) < sizeof(*pag) + 2 + len1) {
- LOGP(DRR, LOGL_ERROR, "PagingRequest with wrong MI\n");
- return -1;
- }
- if (mi_type != GSM_MI_TYPE_NONE) {
- gsm48_mi_to_string(mi_string, sizeof(mi_string), &pag->data[1], len1);
- LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to %s M(%s) \n",
- pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed1),
- mi_type_to_string(mi_type),
- mi_string);
- fputs(mi_string,log_tmsi);
- fputs("\n",log_tmsi);
- }
- /* check if we have a MI type in here */
- if (msgb_l3len(msg) < sizeof(*pag) + 2 + len1 + 3)
- return 0;
- tag = pag->data[2 + len1 + 0];
- len2 = pag->data[2 + len1 + 1];
- mi_type = pag->data[2 + len1 + 2] & GSM_MI_TYPE_MASK;
- if (tag == GSM48_IE_MOBILE_ID && mi_type != GSM_MI_TYPE_NONE) {
- if (msgb_l3len(msg) < sizeof(*pag) + 2 + len1 + 3 + len2) {
- LOGP(DRR, LOGL_ERROR, "Optional MI does not fit here.\n");
- return -1;
- }
- gsm48_mi_to_string(mi_string, sizeof(mi_string), &pag->data[2 + len1 + 2], len2);
- LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to %s M(%s) \n",
- pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed2),
- mi_type_to_string(mi_type),
- mi_string);
- fputs(mi_string,log_tmsi);
- fputs("\n",log_tmsi);
- }
- return 0;
- }
- char temp[20];
- static int gsm48_rx_paging_p2(struct msgb *msg, struct osmocom_ms *ms)
- {
- struct gsm48_paging2 *pag;
- int tag, len, mi_type;
- char mi_string[GSM48_MI_SIZE];
- if (msgb_l3len(msg) < sizeof(*pag)) {
- LOGP(DRR, LOGL_ERROR, "Paging2 message is too small.\n");
- return -1;
- }
- memset(temp,0,sizeof(temp));
- pag = msgb_l3(msg);
- LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to TMSI M(0x%x) \n",
- pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed1), pag->tmsi1);
- memset(temp,0,sizeof(temp));
- sprintf(temp, "%x", ntohl(pag->tmsi1));
- fputs(temp,log_tmsi);
- fputs("\n",log_tmsi);
- LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(0x%x) \n",
- pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed2), ntohl(pag->tmsi2));
- memset(temp,0,sizeof(temp));
- sprintf(temp, "%x", pag->tmsi2);
- fputs( temp,log_tmsi);
- fputs("\n",log_tmsi);
- /* no optional element */
- if (msgb_l3len(msg) < sizeof(*pag) + 3)
- return 0;
- tag = pag->data[0];
- len = pag->data[1];
- mi_type = pag->data[2] & GSM_MI_TYPE_MASK;
- if (tag != GSM48_IE_MOBILE_ID)
- return 0;
- if (msgb_l3len(msg) < sizeof(*pag) + 3 + len) {
- LOGP(DRR, LOGL_ERROR, "Optional MI does not fit in here\n");
- return -1;
- }
- gsm48_mi_to_string(mi_string, sizeof(mi_string), &pag->data[2], len);
- LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to %s M(%s) \n",
- pag_print_mode(pag->pag_mode),
- "n/a ",
- mi_type_to_string(mi_type),
- mi_string);
- fputs(mi_string,log_tmsi);
- fputs("\n",log_tmsi);
- return 0;
- }
- static int gsm48_rx_paging_p3(struct msgb *msg, struct osmocom_ms *ms)
- {
- struct gsm48_paging3 *pag;
- if (msgb_l3len(msg) < sizeof(*pag)) {
- LOGP(DRR, LOGL_ERROR, "Paging3 message is too small.\n");
- return -1;
- }
- pag = msgb_l3(msg);
- LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to TMSI M(0x%x) \n",
- pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed1), pag->tmsi1);
- memset(temp,0,sizeof(temp));
- sprintf(temp, "%x", ntohl(pag->tmsi1));
- fputs(temp,log_tmsi);
- fputs("\n",log_tmsi);
- LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(0x%x) \n",
- pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed2), pag->tmsi2);
- memset(temp,0,sizeof(temp));
- sprintf(temp, "%x", ntohl(pag->tmsi2));
- fputs(temp,log_tmsi);
- fputs("\n",log_tmsi);
- LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to TMSI M(0x%x) \n",
- pag_print_mode(pag->pag_mode),
- "n/a ", pag->tmsi3);
- memset(temp,0,sizeof(temp));
- sprintf(temp, "%x", ntohl(pag->tmsi3));
- fputs(temp,log_tmsi);
- fputs("\n",log_tmsi);
- LOGP(DRR, LOGL_NOTICE, "Paging4: %s chan %s to TMSI M(0x%x) \n",
- pag_print_mode(pag->pag_mode),
- "n/a ", pag->tmsi4);
- memset(temp,0,sizeof(temp));
- sprintf(temp, "%x", ntohl(pag->tmsi4));
- fputs(temp,log_tmsi);
- fputs("\n",log_tmsi);
- return 0;
- }
- int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms)
- {
- struct gsm48_system_information_type_header *sih = msgb_l3(msg);
- int rc = 0;
- if(app_state.dch_state == DCH_TCH)
- {
- //BCCH- SDCCH - BCCH -TCH
- struct gsm48_ass_cmd *ia;
- uint8_t ch_type, ch_subch, ch_ts;
- ia = &app_state.ia;
- rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
- if (!ia->chan_desc.h0.h) {
- /* Non-hopping */
- uint16_t arfcn;
- arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
- LOGP(DRR, LOGL_NOTICE, "ASS CMD(chan_nr=0x%02x, "
- "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ",
- 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 */
- l1ctl_tx_dm_est_req_h0(ms,
- arfcn, ia->chan_desc.chan_nr, ia->chan_desc.h0.tsc,
- GSM48_CMODE_SPEECH_EFR, 0);
- }
- else
- {
- printf("unsuport hopping!\n");
- }
- return 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");
- switch (sih->system_information) {
- case GSM48_MT_RR_PAG_REQ_1:
- gsm48_rx_paging_p1(msg, ms);
- break;
- case GSM48_MT_RR_PAG_REQ_2:
- gsm48_rx_paging_p2(msg, ms);
- break;
- case GSM48_MT_RR_PAG_REQ_3:
- gsm48_rx_paging_p3(msg, ms);
- break;
- case GSM48_MT_RR_IMM_ASS:
- gsm48_rx_imm_ass(msg, ms);
- break;
- case GSM48_MT_RR_NOTIF_NCH:
- /* notification for voice call groups and such */
- break;
- case 0x07:
- /* wireshark know that this is SI2 quater and for 3G interop */
- break;
- default:
- LOGP(DRR, LOGL_NOTICE, "unknown PCH/AGCH type 0x%02x\n",
- sih->system_information);
- rc = -EINVAL;
- }
- return rc;
- }
- 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);
- return 0;
- }
- void tch_deinterleave(ubit_t *mC, int blockOffset)
- {
- int k;
- for (k = 0; k < 456; k++) {
- int B = ( k + blockOffset ) % 8;
- int j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
- mC[k] = app_state.mI[B][j];
- }
- }
- void tch_unmap(const uint16_t *map, size_t mapSize, ubit_t * dest, ubit_t * soure)
- {
- unsigned int i;
- for(i=0; i<mapSize; i++)
- {
- dest[map[i]] = soure[i];
- }
- }
- void tch_map(const uint16_t *map, size_t mapSize, ubit_t * dest, ubit_t * soure)
- {
- unsigned int i;
- for(i=0; i<mapSize; i++)
- {
- dest[i] = soure[map[i]];
- }
- }
- void fillField(ubit_t *mStart, size_t writeIndex, uint64_t value, unsigned length)
- {
- char *dpBase = mStart + writeIndex;
- char *dp = dpBase + length - 1;
- while (dp>=dpBase) {
- *dp-- = value & 0x01;
- value >>= 1;
- }
- }
- uint64_t count_tch = 0;
- uint32_t flag = 0;
- ubit_t hu[8],hl[8];
- static void process_tch_efr(struct osmocom_ms *ms,struct l1ctl_burst_ind *bi)
- {
- int16_t rx_dbm;
- uint16_t arfcn;
- uint32_t fn,B;
- uint8_t cbits, tn, lch_idx;
- int ul, bid, i, k, length;
- sbit_t *bursts, mC[456];
- ubit_t steal_bit[2], bt[116],convu[260],convd[260],tch_raw[260],TCHW[260],EFRBits[244],EFRAMR[8 + 244 +10];
- pbit_t voice[33];
- /* Get params (Only for SDCCH and SACCH/{4,8,F,H}) */
- arfcn = ntohs(bi->band_arfcn);
- rx_dbm = rxlev2dbm(bi->rx_level);
- fn = ntohl(bi->frame_nr);
- ul = !!(arfcn & ARFCN_UPLINK);
- cbits = bi->chan_nr >> 3;
- tn = bi->chan_nr & 7;
- B = -1;
- if(( fn % 13 ) % 4 == 0) flag = 1;
- if(!flag) return;
- //B = count_tch % 8;
- B = ( fn % 13 ) % 8;
- printf("fn % 26 = %d, fn % 13 = %d, B = %d\n",fn%26 , fn%13 , B);
- if (B == -1)
- return;
- /* Unpack (ignore hu/hl) */
- osmo_pbit2ubit_ext(bt, 0, bi->bits, 0, 57, 0);
- osmo_pbit2ubit_ext(bt, 57, bi->bits, 57, 57, 0);
- /* save stealing flags */
- hl[B] = !!(bi->bits[14] & 0x10); // hl 57
- hu[B] = !!(bi->bits[14] & 0x20); // hu 58
- printf("steal_bit %x , %x\n", hl[B],hu[B]);
- /* Convert to softbits */
- for (i=0; i<114; i++)
- app_state.mI[B][i] = bt[i] ? - (bi->snr >> 1) : (bi->snr >> 1);
- count_tch++;
- if((B % 4 ==3)&&(count_tch >= 7)){
- if(B == 3)
- {
- tch_deinterleave(mC, 4);
- }else{
- tch_deinterleave(mC, 0);
- }
- for (k = 0; k < 78; k++) {
- tch_raw[182 + k] = mC[378 +k];
- }
- osmo_conv_decode(&conv_tch_afs_12_2, mC, convu);
- // 3.1.2.1
- // copy class 1 bits u[] to d[]
- for (k = 0; k <= 90; k++) {
- convd[2*k] = convu[k];
- convd[2*k+1] = convu[184-k];
- }
- memcpy(tch_raw,convd,182); // the last 78 bit has been stored!
- //now only process EFR or AMR 12_2, fix me!
- tch_unmap(gsm660_bitorder, 260, TCHW, tch_raw);
- // Remove repeating bits and CRC to get raw EFR frame (244 bits)
- for (k=0; k<71; k++)
- EFRBits[k] = TCHW[k] & 1;
- for (k=73; k<123; k++)
- EFRBits[k-2] = TCHW[k] & 1;
- for (k=125; k<178; k++)
- EFRBits[k-4] = TCHW[k] & 1;
- for (k=180; k<230; k++)
- EFRBits[k-6] = TCHW[k] & 1;
- for (k=232; k<252; k++)
- EFRBits[k-8] = TCHW[k] & 1;
- // Map bits as AMR 12.2k
- tch_map(gsm690_12_2_bitorder, 244, EFRAMR + 8,EFRBits);
- // Put the whole frame (hdr + payload)
- //mVFrameAMR.pack(mPrevGoodFrame);
- //mPrevGoodFrameLength = 32;
- fillField(EFRAMR, 0, 0x3c, 8);
- voice[32] = 0;
- length = osmo_ubit2pbit(voice, EFRAMR, 8 + 244);
- fwrite(voice, 1, 32, d_speech_file);
- }
- }
- static void process_tch_fr(struct osmocom_ms *ms,struct l1ctl_burst_ind *bi)
- {
- int16_t rx_dbm;
- uint16_t arfcn;
- uint32_t fn,B;
- uint8_t cbits, tn, lch_idx;
- int ul, bid, i, k, length;
- sbit_t *bursts, mC[456];
- ubit_t steal_bit[2], bt[116],convu[260],convd[260],tch_raw[260],TCHW[260],EFRBits[244],EFRAMR[8 + 244 +10];
- uint8_t voice[33];
- /* Get params (Only for SDCCH and SACCH/{4,8,F,H}) */
- arfcn = ntohs(bi->band_arfcn);
- rx_dbm = rxlev2dbm(bi->rx_level);
- fn = ntohl(bi->frame_nr);
- ul = !!(arfcn & ARFCN_UPLINK);
- cbits = bi->chan_nr >> 3;
- tn = bi->chan_nr & 7;
- B = -1;
- if(( fn % 13 ) % 4 == 0) flag = 1;
- if(!flag) return;
- //B = count_tch % 8;
- B = ( fn % 13 ) % 8;
- printf("fn % 26 = %d, fn % 13 = %d, B = %d\n",fn%26 , fn%13 , B);
- if (B == -1)
- return;
- /* Unpack (ignore hu/hl) */
- osmo_pbit2ubit_ext(bt, 0, bi->bits, 0, 57, 0);
- osmo_pbit2ubit_ext(bt, 57, bi->bits, 57, 57, 0);
- /* save stealing flags */
- hl[B] = !!(bi->bits[14] & 0x10); // hl 57
- hu[B] = !!(bi->bits[14] & 0x20); // hu 58
- printf("steal_bit %x , %x\n", hl[B],hu[B]);
- /* Convert to softbits */
- for (i=0; i<114; i++)
- app_state.mI[B][i] = bt[i] ? - (bi->snr >> 1) : (bi->snr >> 1);
- count_tch++;
- if((B % 4 ==3)&&(count_tch >= 7)){
- if(B == 3)
- {
- tch_deinterleave(mC, 4);
- }else{
- tch_deinterleave(mC, 0);
- }
- for (k = 0; k < 78; k++) {
- tch_raw[182 + k] = mC[378 +k];
- }
- osmo_conv_decode(&conv_tch_afs_12_2, mC, convu);
- // 3.1.2.1
- // copy class 1 bits u[] to d[]
- for (k = 0; k <= 90; k++) {
- convd[2*k] = convu[k];
- convd[2*k+1] = convu[184-k];
- }
- memcpy(tch_raw,convd,182); // the last 78 bit has been stored!
- //now only process EFR or AMR 12_2, fix me!
- tch_unmap(gsm610_bitorder, 260, TCHW, tch_raw);
- // Remove repeating bits and CRC to get raw EFR frame (244 bits)
- //for (k=0; k<71; k++)
- //EFRBits[k] = TCHW[k] & 1;
- // for (k=73; k<123; k++)
- // EFRBits[k-2] = TCHW[k] & 1;
- //
- //for (k=125; k<178; k++)
- //EFRBits[k-4] = TCHW[k] & 1;
- //
- //for (k=180; k<230; k++)
- //EFRBits[k-6] = TCHW[k] & 1;
- //for (k=232; k<252; k++)
- //EFRBits[k-8] = TCHW[k] & 1;
- // Map bits as AMR 12.2k
- // tch_map(gsm690_12_2_bitorder, 244, EFRAMR + 8,EFRBits);
- // Put the whole frame (hdr + payload)
- //mVFrameAMR.pack(mPrevGoodFrame);
- //mPrevGoodFrameLength = 33;
- fillField(TCHW, 0,0x0d,4);
- memset(voice, 0x00, 33);
- length = osmo_ubit2pbit(voice, TCHW, 260);
- fwrite(voice, 1, 33, d_speech_file);
- }
- }
- static void
- local_burst_decode(struct osmocom_ms *ms,struct l1ctl_burst_ind *bi)
- {
- int16_t rx_dbm;
- uint16_t arfcn;
- uint32_t fn;
- 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);
- fn = ntohl(bi->frame_nr);
- 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;
- printf("SNR is %d\n",bi->snr);
- if (bi->flags & BI_FLG_SACCH) {
- uint32_t fn_report;
- fn_report = (fn - (tn * 13) + 104) % 104;
- bid = (fn_report - 12) / 26;
- printf(" SACCH fn = %d fn_report = %d\n",fn,fn_report);
- }else{
- switch (app_state.speed_mode ) {
- case GSM48_CMODE_SPEECH_EFR:
- process_tch_efr(ms,bi);
- break;
- case GSM48_CMODE_SPEECH_V1:
- process_tch_fr(ms,bi);
- break;
- default:
- {
- printf("mode is %02x",app_state.speed_mode);
- printf("unknown speed mode! %x\n",app_state.speed_mode);
- return;
- }
- }
- }
- } 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 = (fn - (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;
- printf(" SDCCH/4\n");
- } 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;
- /* A5/x */
- if (app_state.dch_ciph) {
- ubit_t ks_dl[114], ks_ul[114], *ks = ul ? ks_ul : ks_dl;
- osmo_a5(app_state.dch_ciph, app_state.kc, fn, ks_dl, ks_ul);
- for (i= 0; i< 57; i++) bt[i] ^= ks[i];
- for (i=59; i<116; i++) bt[i] ^= ks[i-2];
- }
- /* Convert to softbits */
- 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,i;
- struct gsm48_ass_cmd *ia;
- uint8_t ch_type, ch_subch, ch_ts;
- uint8_t chan_req_val, chan_req_mask, ra;
- rv = xcch_decode(l2, bursts);
- if((l2[0] == 0x03) && (l2[4] == 0x2e))
- {
- ia =(struct gsm48_ass_cmd *)&l2[5];
- memcpy(&app_state.ia , ia, sizeof(struct gsm48_ass_cmd));
- app_state.speed_mode = ia->chan_mode.voice_mode;
- /* Clear if new set */
- for(i=0; i<8; i++){
- memset(app_state.mI[i], 0x00, 114);
- }
- /* open speech file and configure d_tch_decoders */
- switch (app_state.speed_mode ) {
- case GSM48_CMODE_SPEECH_V1:
- d_speech_file = fopen( "speech.au.gsm", "wb" );
- break;
- default:
- {
- printf("unknown speed mode! %x\n",app_state.speed_mode);
- d_speech_file = NULL;
- return;
- }
- }
- app_state.dch_state = DCH_TCH;
- l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL); //BCCH- SDCCH - BCCH -TCH
- return;
- if (!ia->chan_desc.h0.h) {
- /* Non-hopping */
- uint16_t arfcn;
- arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
- LOGP(DRR, LOGL_NOTICE, "ASS CMD(chan_nr=0x%02x, "
- "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ",
- 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_SPEECH_EFR, 0);
- }
- #ifdef TCH_HOPPING
- else {
- /* Hopping is not support now! */
- uint8_t maio, hsn, ma_len;
- uint16_t ma[64], arfcn;
- int i, j, k;
- //initialize tch count and flag
- count_tch = 0;
- flag = 0;
- hsn = ia->chan_desc.h1.hsn;
- maio = ia->chan_desc.h1.maio_low | (ia->chan_desc.h1.maio_high << 2);
- LOGP(DRR, LOGL_NOTICE, "ASS CMD( chan_nr=0x%02x, "
- "HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u) ",
- ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch,
- ia->chan_desc.h1.tsc);
- /* decode mobile allocation */
- ma_len = 0;
- for (i=1, j=0; i<=1024; i++) {
- arfcn = i & 1023;
- if (app_state.cell_arfcns[arfcn].mask & 0x01) {
- k = ia->mob_alloc_len - (j>>3) - 1;
- if (ia->mob_alloc[k] & (1 << (j&7))) {
- ma[ma_len++] = arfcn;
- }
- 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_SPEECH_EFR, 0);
- }
- #endif
- }/*else{
- return;
- }
- target sms sniffer
- if( (l2[0] == 0x01)&&(l2[1] == 0x73)&&(l2[10] == 0x05) )
- {
- unsigned int tmsi,object_tmsi;
- tmsi = *(int *)&l2[12];
- for(i =12;i<12+4;i++)
- {
- printf("%x ",l2[i]);
- }
- printf("\n");
- object_tmsi = ntohl(0x97034024);
- printf("object_tmsi is %x, tmsi is %x\n",object_tmsi,tmsi);
- if(tmsi != object_tmsi)
- {
- printf("not match!\n");
- l1ctl_tx_dm_rel_req(ms);
- l1ctl_tx_fbsb_req(ms, ms->test_arfcn,
- L1CTL_FBSB_F_FB01SB, 100, 0,
- app_state.ccch_mode);
- app_state.dch_state = DCH_WAIT_REL;
- app_state.dch_badcnt = 0;
- app_state.dch_ciph = 0;
- if (app_state.fh) {
- fclose(app_state.fh);
- app_state.fh = NULL;
- }
- }else{
- printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
- }
- }
- */
- if (rv == 0)
- {
- uint8_t chan_type, chan_ts, chan_ss;
- uint8_t gsmtap_chan_type;
- /* Send to GSMTAP */
- 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)
- );
- /* Crude CIPH.MOD.COMMAND detect */
- if ((l2[3] == 0x06) && (l2[4] == 0x35) && (l2[5] & 1))
- app_state.dch_ciph = 1 + ((l2[5] >> 1) & 7);
- }
- }
- }
- static void
- ccch_tn_decode(struct l1ctl_burst_ind *bi,uint8_t tn,struct osmocom_ms *ms)
- {
- int16_t rx_dbm;
- uint16_t arfcn;
- uint32_t fn;
- uint8_t cbits, 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);
- //printf("tn is %d\n",tn);
- bursts = app_state.bursts_ccch[tn/2];
- fn = ntohl(bi->frame_nr);
- cbits = bi->chan_nr >> 3;
- bid = -1;
- bid = bi->flags & 3;
- //printf("cbits is %x\n",cbits);
- if ( cbits == 0x12) { /* TCH/F */
- 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;
- /* A5/x */
- if (app_state.dch_ciph) {
- ubit_t ks_dl[114], ks_ul[114], *ks = ul ? ks_ul : ks_dl;
- osmo_a5(app_state.dch_ciph, app_state.kc, fn, ks_dl, ks_ul);
- for (i= 0; i< 57; i++) bt[i] ^= ks[i];
- for (i=59; i<116; i++) bt[i] ^= ks[i-2];
- }
- /* Convert to softbits */
- 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)
- {
- struct msgb *msg;
- msg = msgb_alloc_headroom(30 ,0,"layer3");
- msg->tail =30;
- msg->l3h =l2;
- msg->data_len = msg->len =23;
- gsm48_rx_ccch(msg,ms);
- //struct abis_rsl_rll_hdr *rllh = l2;//l3
- //printf("chan_nr = %x,bi->chan_nr = %x\n",rllh->chan_nr,bi->chan_nr);
- uint8_t chan_type, chan_ts, chan_ss;
- uint8_t gsmtap_chan_type;
- /* Send to GSMTAP */
- 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)
- );
- /* Crude CIPH.MOD.COMMAND detect */
- if ((l2[3] == 0x06) && (l2[4] == 0x35) && (l2[5] & 1))
- app_state.dch_ciph = 1 + ((l2[5] >> 1) & 7);
- }
- }
- }
- static void
- local_ccch_burst_decode(struct l1ctl_burst_ind *bi,struct osmocom_ms *ms)
- {
- uint8_t tn;
- tn = bi->chan_nr & 7;
- ccch_tn_decode(bi,tn,ms);
- }
- 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);
- if (app_state.dch_state == DCH_NONE)
- local_ccch_burst_decode(bi,ms);
- /* 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;
- }
- }
- }
- /* Check for channel end */
- if (app_state.dch_state == DCH_ACTIVE) {
- if (!ul) {
- /* Bad burst counting */
- if (bi->snr < 64)
- {
- app_state.dch_badcnt++;
- printf("sdcch app_state.dch_badcnt++\n");
- }
- 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;
- }
- }
- // when in TCH mode, we only measure the SACCH to kown the link quanlity
- if (app_state.dch_state == DCH_TCH) {
- //printf("app_state.dch_state == DCH_TCH\n");
- if (!ul && (bi->flags & BI_FLG_SACCH)) {
- //printf("TCH SACCH\n");
- /* Bad burst counting */
- if (bi->snr < 40)
- {
- app_state.dch_badcnt++;
- printf("sacch app_state.dch_badcnt++\n");
- }
- 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) {
- printf("The Delicate Channel is released because of bad SNR!\n");
- /* 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;
- app_state.dch_ciph = 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 || app_state.dch_state == DCH_TCH)
- //fwrite(bi, sizeof(*bi), 1, app_state.fh);
- /* Try local decoding */
- if (!ul && (app_state.dch_state == DCH_ACTIVE || app_state.dch_state == DCH_TCH))
- local_burst_decode(ms,bi);
- }
- void layer3_app_reset(void)
- {
- /* Reset state */
- app_state.has_si1 = 0;
- app_state.has_si3 = 0;
- app_state.neci = 0;
- app_state.ccch_mode = CCCH_MODE_NONE;
- app_state.dch_state = DCH_NONE;
- app_state.dch_badcnt = 0;
- app_state.dch_ciph = 0;
- app_state.sys_count= 0;
- if (app_state.fh)
- fclose(app_state.fh);
- app_state.fh = NULL;
- memset(&app_state.cell_arfcns, 0x00, sizeof(app_state.cell_arfcns));
- }
- 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;
- struct osmobb_fbsb_res *fr;
- 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_FBSB_ERR:
- fr=signal_data;
- l1ctl_tx_reset_req(fr->ms, L1CTL_RES_T_FULL);
- /* FIXME: L1CTL_RES_T_FULL doesn't reset dedicated mode
- * (if previously set), so we release it here. */
- l1ctl_tx_dm_rel_req(fr->ms);
- //printf("fr->band_arfcn is %d\n",ntohs(fr->band_arfcn));
- //return l1ctl_tx_fbsb_req(fr->ms, ntohs(fr->band_arfcn),
- // L1CTL_FBSB_F_FB01SB, 100, 0,
- // CCCH_MODE_NONE);
- break;
- case S_L1CTL_RESET:
- if(app_state.dch_state == DCH_ACTIVE) //if we are going TCH,we need rest_sched?
- break;
- ms = signal_data;
- if(app_state.dch_state != DCH_TCH)
- layer3_app_reset();
- return l1ctl_tx_fbsb_req(ms, ms->test_arfcn,
- L1CTL_FBSB_F_FB01SB, 100, 0,
- app_state.ccch_mode);
- break;
- }
- return 0;
- }
- int l23_app_init(struct osmocom_ms *ms)
- {
- osmo_signal_register_handler(SS_L1CTL, &signal_cb, NULL);
- l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
- return layer3_init(ms);
- }
- static int l23_cfg_supported()
- {
- return L23_OPT_TAP | L23_OPT_DBG;
- }
- static int l23_getopt_options(struct option **options)
- {
- static struct option opts [] = {
- {"kc", 1, 0, 'k'},
- };
- *options = opts;
- return ARRAY_SIZE(opts);
- }
- static int l23_cfg_print_help()
- {
- printf("\nApplication specific\n");
- printf(" -k --kc KEY Key to use to try to decipher DCCHs\n");
- return 0;
- }
- static int l23_cfg_handle(int c, const char *optarg)
- {
- switch (c) {
- case 'k':
- if (osmo_hexparse(optarg, app_state.kc, 8) != 8) {
- fprintf(stderr, "Invalid Kc\n");
- exit(-1);
- }
- break;
- default:
- return -1;
- }
- return 0;
- }
- static struct l23_app_info info = {
- .copyright = "Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>\n",
- .contribution = "Contributions by Holger Hans Peter Freyther\n",
- .getopt_string = "k:",
- .cfg_supported = l23_cfg_supported,
- .cfg_getopt_opt = l23_getopt_options,
- .cfg_handle_opt = l23_cfg_handle,
- .cfg_print_help = l23_cfg_print_help,
- };
- struct l23_app_info *l23_app_info()
- {
- return &info;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement