summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/l1ctl_proto.h15
-rwxr-xr-xpre-built/compal_e86.binbin0 -> 53408 bytes
-rwxr-xr-xpre-built/compal_e88.binbin0 -> 52776 bytes
-rwxr-xr-xpre-built/compal_e99.binbin0 -> 53684 bytes
-rwxr-xr-xpre-built/gta0x.binbin0 -> 52812 bytes
-rwxr-xr-xpre-built/pirelli.binbin0 -> 52780 bytes
-rwxr-xr-xpre-built/se_j100.binbin0 -> 53536 bytes
-rw-r--r--src/host/layer23/include/osmocom/bb/common/osmocom_data.h6
-rw-r--r--src/host/layer23/include/osmocom/bb/misc/xcch.h15
-rw-r--r--src/host/layer23/src/common/l1ctl.c39
-rw-r--r--src/host/layer23/src/common/main.c2
-rw-r--r--src/host/layer23/src/misc/Makefile.am6
-rw-r--r--src/host/layer23/src/misc/app_ccch_scan.c628
-rw-r--r--src/host/layer23/src/misc/app_cell_log.c30
-rwxr-xr-xsrc/host/layer23/src/misc/arfcn_sort5
-rw-r--r--src/host/layer23/src/misc/assignment.c150
-rw-r--r--src/host/layer23/src/misc/assignment.h28
-rw-r--r--src/host/layer23/src/misc/cell_log.c604
-rw-r--r--src/host/layer23/src/misc/cellid.c110
-rw-r--r--src/host/layer23/src/misc/xcch.c153
-rw-r--r--src/host/osmocon/osmocon.c76
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h1
-rw-r--r--src/target/firmware/battery/compal_e88.c2
-rw-r--r--src/target/firmware/board/compal_e86/init.c1
-rwxr-xr-xsrc/target/firmware/board/compal_e88/init.c3
-rw-r--r--src/target/firmware/board/compal_e99/init.c3
-rw-r--r--src/target/firmware/board/gta0x/init.c3
-rw-r--r--src/target/firmware/board/pirelli_dpl10/init.c3
-rw-r--r--src/target/firmware/calypso/dsp.c8
-rw-r--r--src/target/firmware/calypso/dsp_sniffcode.c42
-rw-r--r--src/target/firmware/include/inttypes.h1
-rw-r--r--src/target/firmware/include/layer1/prim.h4
-rw-r--r--src/target/firmware/layer1/Makefile2
-rw-r--r--src/target/firmware/layer1/l23_api.c2
-rw-r--r--src/target/firmware/layer1/mframe_sched.c192
-rw-r--r--src/target/firmware/layer1/prim_fbsb.c18
-rw-r--r--src/target/firmware/layer1/prim_sniff.c279
-rw-r--r--src/target_dsp/calypso/Makefile5
-rw-r--r--src/target_dsp/calypso/dsp_patch.lds25
-rw-r--r--src/target_dsp/calypso/dsp_sniff.S175
40 files changed, 2212 insertions, 424 deletions
diff --git a/include/l1ctl_proto.h b/include/l1ctl_proto.h
index 4b9540e9..c696b74f 100644
--- a/include/l1ctl_proto.h
+++ b/include/l1ctl_proto.h
@@ -56,6 +56,7 @@ enum {
L1CTL_TRAFFIC_REQ,
L1CTL_TRAFFIC_CONF,
L1CTL_TRAFFIC_IND,
+ L1CTL_BURST_IND,
};
enum ccch_mode {
@@ -139,6 +140,20 @@ struct l1ctl_traffic_ind {
uint8_t data[TRAFFIC_DATA_LEN];
} __attribute__((packed));
+/* raw burst data. This is following the header */
+#define BI_FLG_DUMMY (1<<4)
+#define BI_FLG_SACCH (1<<5)
+
+struct l1ctl_burst_ind {
+ uint32_t frame_nr;
+ uint16_t band_arfcn; /* ARFCN + band + ul indicator */
+ uint8_t chan_nr; /* GSM 08.58 channel number (9.3.1) */
+ uint8_t flags; /* BI_FLG_xxx + burst_id = 2LSBs */
+ uint8_t rx_level; /* 0 .. 63 in typical GSM notation (dBm+110) */
+ uint8_t snr; /* Reported SNR >> 8 (0-255) */
+ uint8_t bits[15]; /* 114 bits + 2 steal bits. Filled MSB first */
+} __attribute__((packed));
+
/*
* uplink info
*/
diff --git a/pre-built/compal_e86.bin b/pre-built/compal_e86.bin
new file mode 100755
index 00000000..ea8c6870
--- /dev/null
+++ b/pre-built/compal_e86.bin
Binary files differ
diff --git a/pre-built/compal_e88.bin b/pre-built/compal_e88.bin
new file mode 100755
index 00000000..c19f9fd3
--- /dev/null
+++ b/pre-built/compal_e88.bin
Binary files differ
diff --git a/pre-built/compal_e99.bin b/pre-built/compal_e99.bin
new file mode 100755
index 00000000..94f0583c
--- /dev/null
+++ b/pre-built/compal_e99.bin
Binary files differ
diff --git a/pre-built/gta0x.bin b/pre-built/gta0x.bin
new file mode 100755
index 00000000..11c1fe4e
--- /dev/null
+++ b/pre-built/gta0x.bin
Binary files differ
diff --git a/pre-built/pirelli.bin b/pre-built/pirelli.bin
new file mode 100755
index 00000000..caa3956b
--- /dev/null
+++ b/pre-built/pirelli.bin
Binary files differ
diff --git a/pre-built/se_j100.bin b/pre-built/se_j100.bin
new file mode 100755
index 00000000..2b433694
--- /dev/null
+++ b/pre-built/se_j100.bin
Binary files differ
diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
index ab7c2502..7cec8575 100644
--- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
+++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
@@ -92,6 +92,7 @@ enum osmobb_l1ctl_sig {
S_L1CTL_TCH_MODE_CONF,
S_L1CTL_LOSS_IND,
S_L1CTL_NEIGH_PM_IND,
+ S_L1CTL_BURST_IND,
};
enum osmobb_global_sig {
@@ -128,4 +129,9 @@ struct osmobb_neigh_pm_ind {
uint8_t rx_lev;
};
+struct osmobb_msg_ind {
+ struct osmocom_ms *ms;
+ struct msgb *msg;
+};
+
#endif
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/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c
index 521949c1..6c0f2f30 100644
--- a/src/host/layer23/src/common/l1ctl.c
+++ b/src/host/layer23/src/common/l1ctl.c
@@ -237,6 +237,7 @@ printf("Dropping frame with %u bit errors\n", dl->num_biterr);
LOGP(DL1C, LOGL_NOTICE, "Dropping frame with %u bit errors\n",
dl->num_biterr);
msgb_free(msg);
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_LOSS_IND, ms);
return 0;
}
@@ -265,6 +266,41 @@ printf("Dropping frame with %u bit errors\n", dl->num_biterr);
return lapdm_phsap_up(&pp.oph, le);
}
+/* Receive L1CTL_BURST_IND (Data Indication from L1) */
+static int rx_ph_burst_ind(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct l1ctl_burst_ind *bi;
+ struct osmobb_msg_ind mi;
+ uint8_t chan_type, chan_ts, chan_ss;
+ struct gsm_time rx_time;
+ uint16_t arfcn;
+
+ /* Header handling */
+ bi = (struct l1ctl_burst_ind *) msg->l1h;
+
+ rsl_dec_chan_nr(bi->chan_nr, &chan_type, &chan_ss, &chan_ts);
+ gsm_fn2gsmtime(&rx_time, ntohl(bi->frame_nr));
+ arfcn = ntohs(bi->band_arfcn);
+
+ /* Debug print */
+ LOGP(DL1C, LOGL_NOTICE, "BURST IND: @(%6d = %.4u/%.2u/%.2u) (%4d dBm, SNR %3d%s%s)\n",
+ rx_time.fn, rx_time.t1, rx_time.t2, rx_time.t3,
+ (int)bi->rx_level-110, bi->snr,
+ arfcn & ARFCN_UPLINK ? ", UL" : "",
+ bi->flags & BI_FLG_SACCH ? ", SACCH" : ""
+ );
+
+ /* Dispatch signal !HACK! */
+ mi.ms = ms;
+ mi.msg = msg;
+ osmo_signal_dispatch(SS_L1CTL, S_L1CTL_BURST_IND, &mi);
+
+ /* Done with the message */
+ msgb_free(msg);
+
+ return 0;
+}
+
/* Receive L1CTL_DATA_CONF (Data Confirm from L1) */
static int rx_ph_data_conf(struct osmocom_ms *ms, struct msgb *msg)
{
@@ -919,6 +955,9 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
case L1CTL_DATA_IND:
rc = rx_ph_data_ind(ms, msg);
break;
+ case L1CTL_BURST_IND:
+ rc = rx_ph_burst_ind(ms, msg);
+ break;
case L1CTL_DATA_CONF:
rc = rx_ph_data_conf(ms, msg);
break;
diff --git a/src/host/layer23/src/common/main.c b/src/host/layer23/src/common/main.c
index 59cee03d..37811a25 100644
--- a/src/host/layer23/src/common/main.c
+++ b/src/host/layer23/src/common/main.c
@@ -51,7 +51,7 @@ struct log_target *stderr_target;
void *l23_ctx = NULL;
-static char *layer2_socket_path = "/tmp/osmocom_l2";
+static char *layer2_socket_path = "/tmp/osmocom_log";
static char *sap_socket_path = "/tmp/osmocom_sap";
struct llist_head ms_list;
static struct osmocom_ms *ms = NULL;
diff --git a/src/host/layer23/src/misc/Makefile.am b/src/host/layer23/src/misc/Makefile.am
index 0b59f389..ab22c4fe 100644
--- a/src/host/layer23/src/misc/Makefile.am
+++ b/src/host/layer23/src/misc/Makefile.am
@@ -2,12 +2,10 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS)
LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS)
-bin_PROGRAMS = bcch_scan ccch_scan echo_test cell_log cbch_sniff
+bin_PROGRAMS = bcch_scan ccch_scan cell_log
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
-echo_test_SOURCES = ../common/main.c app_echo_test.c
+ccch_scan_SOURCES = ../common/main.c app_ccch_scan.c rslms.c xcch.c
cell_log_LDADD = $(LDADD) -lm
cell_log_SOURCES = ../common/main.c app_cell_log.c cell_log.c \
../../../gsmmap/geo.c
-cbch_sniff_SOURCES = ../common/main.c app_cbch_sniff.c
diff --git a/src/host/layer23/src/misc/app_ccch_scan.c b/src/host/layer23/src/misc/app_ccch_scan.c
index d301b7b7..413ba01f 100644
--- a/src/host/layer23/src/misc/app_ccch_scan.c
+++ b/src/host/layer23/src/misc/app_ccch_scan.c
@@ -1,4 +1,3 @@
-/* CCCH passive sniffer */
/* (C) 2010-2011 by Holger Hans Peter Freyther
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
*
@@ -23,6 +22,12 @@
#include <stdint.h>
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <getopt.h>
+
+#include <arpa/inet.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/rsl.h>
@@ -31,6 +36,9 @@
#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>
@@ -41,27 +49,70 @@
#include <l1ctl_proto.h>
+#include <osmocom/bb/misc/xcch.h>
+
+#include "cellid.c"
+#include "assignment.c"
+
+extern struct gsmtap_inst *gsmtap_inst;
+
+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 has_si3;
+ int ccch_mode;
+
+ enum dch_state_t dch_state;
+ uint8_t dch_nr;
+ int dch_badcnt;
+ int dch_ciph;
+
+ FILE * fh;
+ struct osmocom_ms *ms;
+
+ int sniffing;
+
+ sbit_t bursts_dl[116 * 4];
+ sbit_t bursts_ul[116 * 4];
+
+ struct gsm_sysinfo_freq cell_arfcns[1024];
+
+ uint8_t kc[8];
+ uint8_t wanted_tmsi[4];
+ uint8_t tmsi_matched;
} app_state;
+inline int not_zero(uint8_t *t, unsigned size)
+{
+ unsigned i;
+
+ for (i=0; i<size; i++) {
+ if (t[i])
+ break;
+ }
+
+ if (i == size)
+ return 0;
+ else
+ return 1;
+}
static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
{
struct gsm48_system_information_type_header *si_hdr;
si_hdr = (struct gsm48_system_information_type_header *) data;
+ struct gsm48_system_information_type_3 *si3 =
+ (struct gsm48_system_information_type_3 *) 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;
@@ -76,16 +127,8 @@ static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
}
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.ccch_mode == CCCH_MODE_NONE) {
struct gsm48_system_information_type_3 *si3 =
(struct gsm48_system_information_type_3 *)data;
@@ -97,64 +140,36 @@ static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
l1ctl_tx_ccch_mode_req(ms, app_state.ccch_mode);
}
+
+ if (!app_state.has_si3) {
+ set_cid(si3->lai.digits, si3->lai.lac, si3->cell_identity);
+ LOGP(DRR, LOGL_ERROR, "SI3 received.\n");
+ app_state.has_si3 = 1;
+ }
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_2quater:
break;
case GSM48_MT_RR_SYSINFO_5bis:
break;
@@ -167,66 +182,100 @@ static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
};
}
-
-/**
- * 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)
+void parse_chandesc(struct gsm48_chan_desc *chan_desc,
+ uint8_t mob_alloc_len,
+ const uint8_t *mob_alloc,
+ struct gsm_assignment *ga)
{
- struct gsm48_imm_ass *ia = msgb_l3(msg);
- uint8_t ch_type, ch_subch, ch_ts;
-
- /* Discard packet TBF assignement */
- if (ia->page_mode & 0xf0)
- return 0;
-
- /* FIXME: compare RA and GSM time with when we sent RACH req */
+ ga->chan_nr = chan_desc->chan_nr;
+ ga->h = chan_desc->h0.h;
- rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
-
- if (!ia->chan_desc.h0.h) {
+ if (!ga->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);
-
+ ga->tsc = chan_desc->h0.tsc;
+ ga->h0.band_arfcn = chan_desc->h0.arfcn_low | (chan_desc->h0.arfcn_high << 8);
} else {
/* Hopping */
- uint8_t maio, hsn, ma_len;
- uint16_t ma[64], arfcn;
+ uint16_t 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);
+ ga->tsc = chan_desc->h1.tsc;
+ ga->h1.hsn = chan_desc->h1.hsn;
+ ga->h1.maio = chan_desc->h1.maio_low | (chan_desc->h1.maio_high << 2);
/* decode mobile allocation */
- ma_len = 0;
+ ga->h1.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;
+ k = mob_alloc_len - (j>>3) - 1;
+ if (mob_alloc[k] & (1 << (j&7))) {
+ ga->h1.ma[ga->h1.ma_len++] = arfcn;
}
j++;
}
}
}
+}
- LOGPC(DRR, LOGL_NOTICE, "\n");
- return 0;
+void follow_assignment(struct osmocom_ms *ms, struct gsm_assignment *ga)
+{
+ /* Set state */
+ app_state.dch_state = DCH_WAIT_EST;
+ app_state.dch_nr = ga->chan_nr;
+ app_state.dch_badcnt = 0;
+
+ /* Tune to new channel */
+ if (!ga->h) {
+ l1ctl_tx_dm_est_req_h0(ms,
+ ga->h0.band_arfcn, ga->chan_nr, ga->tsc,
+ GSM48_CMODE_SIGN, 0);
+ } else {
+ l1ctl_tx_dm_est_req_h1(ms,
+ ga->h1.maio, ga->h1.hsn, ga->h1.ma, ga->h1.ma_len,
+ ga->chan_nr, ga->tsc,
+ GSM48_CMODE_SIGN, 0);
+ }
+}
+
+void gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms)
+{
+ struct gsm48_imm_ass *ia = msgb_l3(msg);
+ struct gsm_assignment ga;
+
+ if (app_state.sniffing)
+ return;
+
+ /* only our tmsi */
+ if (!app_state.tmsi_matched && not_zero(app_state.wanted_tmsi, 4))
+ return;
+
+ /* Discard packet TBF assignement */
+ if (ia->page_mode & 0xf0)
+ return;
+
+ /* 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;
+
+ parse_chandesc(&ia->chan_desc, ia->mob_alloc_len, ia->mob_alloc, &ga);
+
+ follow_assignment(ms, &ga);
+}
+
+void gsm48_rx_imm_ass_ext(struct msgb *msg, struct osmocom_ms *ms)
+{
+ struct gsm48_imm_ass_ext *iae = msgb_l3(msg);
+ struct gsm_assignment ga;
+
+ printf("EXT!!!\n");
+ fflush(stdout);
+
+ /* First */
+ parse_chandesc(&iae->chan_desc1, iae->mob_alloc_len, iae->mob_alloc, &ga);
+
+ /* Second */
+ parse_chandesc(&iae->chan_desc2, iae->mob_alloc_len, iae->mob_alloc, &ga);
}
static const char *pag_print_mode(int mode)
@@ -235,7 +284,7 @@ static const char *pag_print_mode(int mode)
case 0:
return "Normal paging";
case 1:
- return "Extended paging";
+ return "Ext.ed paging";
case 2:
return "Paging reorganization";
case 3:
@@ -249,9 +298,9 @@ static char *chan_need(int need)
{
switch (need) {
case 0:
- return "any";
+ return "any ";
case 1:
- return "sdch";
+ return "sdch ";
case 2:
return "tch/f";
case 3:
@@ -267,18 +316,25 @@ static char *mi_type_to_string(int type)
case GSM_MI_TYPE_NONE:
return "none";
case GSM_MI_TYPE_IMSI:
- return "imsi";
+ return "IMSI";
case GSM_MI_TYPE_IMEI:
- return "imei";
+ return "IMEI";
case GSM_MI_TYPE_IMEISV:
- return "imeisv";
+ return "IMEISV";
case GSM_MI_TYPE_TMSI:
- return "tmsi";
+ return "TMSI";
default:
return "invalid";
}
}
+void tmsi_match(uint8_t *t)
+{
+ if(!memcmp(t, app_state.wanted_tmsi, 4)) {
+ app_state.tmsi_matched = 1;
+ }
+}
+
/**
* This can contain two MIs. The size checking is a bit of a mess.
*/
@@ -310,6 +366,7 @@ static int gsm48_rx_paging_p1(struct msgb *msg, struct osmocom_ms *ms)
chan_need(pag->cneed1),
mi_type_to_string(mi_type),
mi_string);
+ tmsi_match(&pag->data[2]);
}
/* check if we have a MI type in here */
@@ -326,11 +383,12 @@ static int gsm48_rx_paging_p1(struct msgb *msg, struct osmocom_ms *ms)
}
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",
+ LOGP(DRR, LOGL_NOTICE, "Paging1: %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);
+ tmsi_match(&pag->data[2 + len1 + 3]);
}
return 0;
}
@@ -347,12 +405,15 @@ static int gsm48_rx_paging_p2(struct msgb *msg, struct osmocom_ms *ms)
}
pag = msgb_l3(msg);
- LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to TMSI M(0x%x) \n",
+ LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(%u) \n",
pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed1), pag->tmsi1);
- LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(0x%x) \n",
+ chan_need(pag->cneed1), ntohl(pag->tmsi1));
+ tmsi_match((uint8_t *)&pag->tmsi1);
+
+ LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(%u) \n",
pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed2), pag->tmsi2);
+ chan_need(pag->cneed1), ntohl(pag->tmsi2));
+ tmsi_match((uint8_t *)&pag->tmsi2);
/* no optional element */
if (msgb_l3len(msg) < sizeof(*pag) + 3)
@@ -371,11 +432,12 @@ static int gsm48_rx_paging_p2(struct msgb *msg, struct osmocom_ms *ms)
}
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",
+ LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to %s M(%s) \n",
pag_print_mode(pag->pag_mode),
- "n/a ",
+ "n/a ",
mi_type_to_string(mi_type),
mi_string);
+ tmsi_match(&pag->data[3]);
return 0;
}
@@ -390,29 +452,151 @@ static int gsm48_rx_paging_p3(struct msgb *msg, struct osmocom_ms *ms)
}
pag = msgb_l3(msg);
- LOGP(DRR, LOGL_NOTICE, "Paging1: %s chan %s to TMSI M(0x%x) \n",
+ LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to TMSI M(%u) \n",
pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed1), pag->tmsi1);
- LOGP(DRR, LOGL_NOTICE, "Paging2: %s chan %s to TMSI M(0x%x) \n",
+ chan_need(pag->cneed1), ntohl(pag->tmsi1));
+ tmsi_match((uint8_t *)&pag->tmsi1);
+
+ LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to TMSI M(%u) \n",
pag_print_mode(pag->pag_mode),
- chan_need(pag->cneed2), pag->tmsi2);
- LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to TMSI M(0x%x) \n",
+ chan_need(pag->cneed1), ntohl(pag->tmsi2));
+ tmsi_match((uint8_t *)&pag->tmsi2);
+
+ LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to TMSI M(%u) \n",
pag_print_mode(pag->pag_mode),
- "n/a ", pag->tmsi3);
- LOGP(DRR, LOGL_NOTICE, "Paging4: %s chan %s to TMSI M(0x%x) \n",
+ chan_need(pag->cneed3), ntohl(pag->tmsi3));
+ tmsi_match((uint8_t *)&pag->tmsi3);
+
+ LOGP(DRR, LOGL_NOTICE, "Paging3: %s chan %s to TMSI M(%u) \n",
pag_print_mode(pag->pag_mode),
- "n/a ", pag->tmsi4);
+ chan_need(pag->cneed4), ntohl(pag->tmsi4));
+ tmsi_match((uint8_t *)&pag->tmsi4);
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, &lt);
+
+ snprintf(buffer, 256, "%s_%04d%02d%02d_%02d%02d_%d_%d_%02x.dat",
+ get_cid_str(),
+ 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;
+ uint16_t arfcn;
+ int ul, do_rel=0;
+
+ /* Header handling */
+ bi = (struct l1ctl_burst_ind *) msg->l1h;
+
+ arfcn = ntohs(bi->band_arfcn);
+ 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;
+ app_state.tmsi_matched = 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++;
+ else if (app_state.dch_badcnt >= 2)
+ app_state.dch_badcnt -= 2;
+ else
+ app_state.dch_badcnt = 0;
+
+ /* Release condition */
+ if (app_state.dch_nr < 0x20)
+ do_rel = app_state.dch_badcnt >= 100;
+ else
+ do_rel = app_state.dch_badcnt >= 6;
+ }
+ }
+
+ /* Save the burst and try decoding */
+ if (app_state.dch_state == DCH_ACTIVE) {
+ local_burst_decode(bi);
+ fwrite(bi, sizeof(*bi), 1, app_state.fh);
+ }
+
+ /* Release ? */
+ if (do_rel) {
+ /* L1 release */
+ l1ctl_tx_dm_rel_req(ms);
+
+ /* tune back to BCCH */
+ 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;
+ }
+
+ /* proceed only on correct TMSI */
+ if (not_zero(app_state.wanted_tmsi, 4) && !app_state.tmsi_matched)
+ return;
+
+ /* reset TMSI match */
+ app_state.tmsi_matched = 0;
+
+ /* releasing everything */
+ app_state.sniffing = 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 (sih->rr_protocol_discriminator != GSM48_PDISC_RR)
- LOGP(DRR, LOGL_ERROR, "PCH pdisc != RR\n");
+ /* 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) {
+ return 0;
+ }
switch (sih->system_information) {
case GSM48_MT_RR_PAG_REQ_1:
@@ -427,6 +611,9 @@ int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms)
case GSM48_MT_RR_IMM_ASS:
gsm48_rx_imm_ass(msg, ms);
break;
+ case GSM48_MT_RR_IMM_ASS_EXT:
+ gsm48_rx_imm_ass_ext(msg, ms);
+ break;
case GSM48_MT_RR_NOTIF_NCH:
/* notification for voice call groups and such */
break;
@@ -444,48 +631,182 @@ 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;
+}
+
+void local_burst_decode(struct l1ctl_burst_ind *bi)
+{
+ 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);
+
+ 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;
+ if (bi->flags & BI_FLG_SACCH) {
+ uint32_t fn_report;
+ fn_report = (fn - (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 = (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;
+ } else if ((cbits & 0x18) == 0x08) { /* SDCCH/8 */
+ lch_idx = cbits & 7;
+ bid = bi->flags & 3;
}
- return 0;
+ 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)
+ {
+ 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);
+ }
+ }
}
void layer3_app_reset(void)
{
/* Reset state */
app_state.has_si1 = 0;
+ app_state.has_si3 = 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;
+ app_state.dch_ciph = 0;
+ app_state.sniffing = 0;
+ app_state.tmsi_matched = 0;
+
+ if (app_state.fh)
+ fclose(app_state.fh);
+ app_state.fh = NULL;
memset(&app_state.cell_arfcns, 0x00, sizeof(app_state.cell_arfcns));
+
+ reset_cid();
}
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;
+ static unsigned loss_count = 0;
if (subsys != SS_L1CTL)
return 0;
switch (signal) {
+ case S_L1CTL_BURST_IND:
+ mi = signal_data;
+ loss_count = 0;
+ layer3_rx_burst(mi->ms, mi->msg);
+ break;
+
case S_L1CTL_RESET:
+ loss_count = 0;
ms = signal_data;
layer3_app_reset();
return l1ctl_tx_fbsb_req(ms, ms->test_arfcn,
L1CTL_FBSB_F_FB01SB, 100, 0,
CCCH_MODE_NONE);
break;
+
+ case S_L1CTL_FBSB_RESP:
+ loss_count = 0;
+ break;
+
+ case S_L1CTL_FBSB_ERR:
+ return l1ctl_tx_fbsb_req(app_state.ms, app_state.ms->test_arfcn,
+ L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_NONE);
+ break;
+ case S_L1CTL_LOSS_IND:
+ loss_count++;
+ if (loss_count > 10) {
+ loss_count = 0;
+ return l1ctl_tx_fbsb_req(app_state.ms, app_state.ms->test_arfcn,
+ L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_NONE);
+ }
+ break;
}
return 0;
}
@@ -495,12 +816,63 @@ 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);
+ app_state.ms = ms;
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 [] = {
+ {"tmsi", 1, 0, 't'},
+ };
+
+ *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");
+ printf(" -t --tmsi TMSI Filter assignments with specified TMSI (paging only)\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;
+ case 't':
+ if (osmo_hexparse(optarg, app_state.wanted_tmsi, 4) != 4) {
+ fprintf(stderr, "Invalid TMSI\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:t:",
+ .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()
diff --git a/src/host/layer23/src/misc/app_cell_log.c b/src/host/layer23/src/misc/app_cell_log.c
index 27290be7..0456a4b8 100644
--- a/src/host/layer23/src/misc/app_cell_log.c
+++ b/src/host/layer23/src/misc/app_cell_log.c
@@ -40,8 +40,12 @@
extern struct log_target *stderr_target;
extern void *l23_ctx;
-char *logname = "/var/log/osmocom.log";
+char *logname = "./osmocom.log";
int RACH_MAX = 2;
+char *scan_band = 0;
+int wait_time = 300;
+int log_gprs = 0;
+int scan_only = 0;
int _scan_work(struct osmocom_ms *ms)
{
@@ -99,7 +103,11 @@ static int l23_getopt_options(struct option **options)
{"gpsd-port", 1, 0, 'p'},
#endif
{"gps", 1, 0, 'g'},
- {"baud", 1, 0, 'b'}
+ {"baud", 1, 0, 'b'},
+ {"band", 1, 0, 'B'},
+ {"log-gprs", 0, 0, 'G'},
+ {"only-scan", 0, 0, 'O'},
+ {"wait-time", 1, 0, 'w'}
};
*options = opts;
@@ -116,6 +124,10 @@ static int l23_cfg_print_help()
printf(" -p --port PORT 2947. gpsd port\n");
printf(" -f --gps DEVICE /dev/ttyACM0. GPS serial device.\n");
printf(" -b --baud BAUDRAT The baud rate of the GPS device\n");
+ printf(" -B --band BAND Select scan band, one of: all (default), 900, 1800, 850, 1900.\n");
+ printf(" -G --log-gprs Log some GPRS if available\n");
+ printf(" -O --only-scan Do a scan and show available ARFCNs, no data logging\n");
+ printf(" -w --wait-time TIME Time to wait in each cell\n");
return 0;
}
@@ -172,6 +184,18 @@ static int l23_cfg_handle(int c, const char *optarg)
g.gps_type = GPS_TYPE_SERIAL;
LOGP(DGPS, LOGL_INFO, "Setting GPS baudrate to %u\n", g.baud);
break;
+ case 'B':
+ scan_band = strdup(optarg);
+ break;
+ case 'G':
+ log_gprs = 1;
+ break;
+ case 'O':
+ scan_only = 1;
+ break;
+ case 'w':
+ wait_time = atoi(optarg);
+ break;
}
return 0;
@@ -182,7 +206,7 @@ cmd_line_error:
static struct l23_app_info info = {
.copyright = "Copyright (C) 2010 Andreas Eversberg\n",
- .getopt_string = "g:p:l:r:nf:b:",
+ .getopt_string = "g:p:l:r:nf:b:B:w:GO",
.cfg_supported = l23_cfg_supported,
.cfg_getopt_opt = l23_getopt_options,
.cfg_handle_opt = l23_cfg_handle,
diff --git a/src/host/layer23/src/misc/arfcn_sort b/src/host/layer23/src/misc/arfcn_sort
new file mode 100755
index 00000000..4d437d59
--- /dev/null
+++ b/src/host/layer23/src/misc/arfcn_sort
@@ -0,0 +1,5 @@
+#!/bin/bash
+for arfcn in `ls *.dat|cut -f7 -d_|sort -g|uniq`; do
+ mkdir -p $arfcn;
+ mv *_${arfcn}_* $arfcn;
+done
diff --git a/src/host/layer23/src/misc/assignment.c b/src/host/layer23/src/misc/assignment.c
new file mode 100644
index 00000000..65122262
--- /dev/null
+++ b/src/host/layer23/src/misc/assignment.c
@@ -0,0 +1,150 @@
+#include <osmocom/gsm/rsl.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/gsm48_ie.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#include "assignment.h"
+
+void parse_assignment(uint8_t *msg, unsigned len, struct gsm_sysinfo_freq *cell_arfcns, struct gsm_assignment *ga)
+{
+ struct gsm48_hdr *hdr;
+ struct gsm48_ass_cmd *ac;
+ struct gsm48_ho_cmd *hoc;
+ struct gsm48_chan_desc *cd;
+ int payload_len = 0;
+ uint8_t *payload_data;
+ struct tlv_parsed tp;
+ uint8_t *ma = 0;
+ uint8_t ma_len;
+ uint8_t ch_type, ch_subch, ch_ts;
+ unsigned i, mask;
+
+ hdr = (struct gsm48_hdr *) msg;
+
+ /* handover */
+ if (hdr->msg_type == 0x2b) {
+ hoc = (struct gsm48_ho_cmd *) hdr->data;
+ cd = &hoc->chan_desc;
+ payload_len = len - 3 - sizeof(*hdr) - sizeof(*hoc);
+ payload_data = hoc->data;
+ }
+
+ /* assignment */
+ if (hdr->msg_type == 0x2e) {
+ ac = (struct gsm48_ass_cmd *) hdr->data;
+ cd = &ac->chan_desc;
+ payload_len = len - 3 - sizeof(*hdr) - sizeof(*ac);
+ payload_data = ac->data;
+ }
+
+ if (!payload_len)
+ return;
+
+ /* Parse TLV in the message */
+ tlv_parse(&tp, &gsm48_rr_att_tlvdef, payload_data, payload_len, 0, 0);
+
+ ma_len = 0;
+ ma = NULL;
+ mask = 0;
+
+ /* Cell channel description */
+ if (TLVP_PRESENT(&tp, GSM48_IE_CELL_CH_DESC)) {
+ const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_CELL_CH_DESC);
+ uint8_t len = TLVP_LEN(&tp, GSM48_IE_CELL_CH_DESC);
+ gsm48_decode_freq_list(cell_arfcns, (uint8_t *) v, len, 0xff, 0x02);
+ mask = 0x02;
+ } else if (TLVP_PRESENT(&tp, GSM48_IE_MA_AFTER)) {
+ /* Mobile allocation */
+ const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_MA_AFTER);
+ uint8_t len = TLVP_LEN(&tp, GSM48_IE_MA_AFTER);
+
+ ma_len = len;
+ ma = (uint8_t *) v;
+ mask = 0x01;
+ } else if (TLVP_PRESENT(&tp, GSM48_IE_FREQ_L_AFTER)) {
+ /* Frequency list after time */
+ const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_FREQ_L_AFTER);
+ uint8_t len = TLVP_LEN(&tp, GSM48_IE_FREQ_L_AFTER);
+ gsm48_decode_freq_list(cell_arfcns, (uint8_t *) v, len, 0xff, 0x04);
+ ma_len = 0;
+ ma = NULL;
+ mask = 0x04;
+ } else {
+ /* Use the old one */
+ for (i=0; i<1024; i++) {
+ cell_arfcns[i].mask &= ~0x02;
+ if (cell_arfcns[i].mask & 0x01) {
+ cell_arfcns[i].mask |= 0x02;
+ mask = 0x02;
+ }
+ }
+ }
+
+ /* Channel mode (HR/FR/EFR/AMR) */
+ if (TLVP_PRESENT(&tp, GSM48_IE_CHANMODE_1)) {
+ const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_CHANMODE_1);
+ //uint8_t len = TLVP_LEN(&tp, GSM48_IE_CHANMODE_1);
+ ga->chan_mode = v[0];
+ }
+
+ /* Multirate configuration */
+ if (TLVP_PRESENT(&tp, GSM48_IE_MUL_RATE_CFG)) {
+ const uint8_t *v = TLVP_VAL(&tp, GSM48_IE_MUL_RATE_CFG);
+ //uint8_t len = TLVP_LEN(&tp, GSM48_IE_MUL_RATE_CFG);
+ ga->rate_conf = v[1];
+ }
+
+ rsl_dec_chan_nr(cd->chan_nr, &ch_type, &ch_subch, &ch_ts);
+
+ ga->h = cd->h0.h;
+ ga->chan_nr = cd->chan_nr;
+
+ if (!ga->h) {
+ /* Non-Hopping */
+ uint16_t arfcn = cd->h0.arfcn_low | (cd->h0.arfcn_high << 8);
+
+ ga->tsc = cd->h0.tsc;
+ ga->h0.band_arfcn = arfcn;
+ } else {
+ /* Hopping */
+ uint16_t arfcn;
+ int i, j, k;
+
+ ga->tsc = cd->h1.tsc;
+ ga->h1.maio = cd->h1.maio_low | (cd->h1.maio_high << 2);;
+ ga->h1.hsn = cd->h1.hsn;
+
+ /* decode mobile allocation */
+ if (ma) {
+ for (i=1, j=0; i<=1024; i++) {
+ arfcn = i & 1023;
+ if (cell_arfcns[arfcn].mask & mask) {
+ k = ma_len - (j>>3) - 1;
+ if (ma[k] & (1 << (j&7))) {
+ ga->h1.ma[ga->h1.ma_len++] = arfcn;
+ }
+ j++;
+ }
+ }
+ if (ga->h1.ma_len == 0) {
+ /* cell information not found */
+ /* just compute ma_len */
+ for (i=0; i<(ma_len*8); i++){
+ int k = i/8;
+
+ if (ma[k] & (1 << (i&7))) {
+ ga->h1.ma_len++;
+ }
+ }
+ }
+ } else {
+ for (i=1, j=0; i<=1024; i++) {
+ arfcn = i & 1023;
+ if (cell_arfcns[arfcn].mask & mask) {
+ ga->h1.ma[ga->h1.ma_len++] = arfcn;
+ }
+ }
+ }
+ }
+}
diff --git a/src/host/layer23/src/misc/assignment.h b/src/host/layer23/src/misc/assignment.h
new file mode 100644
index 00000000..dfe40952
--- /dev/null
+++ b/src/host/layer23/src/misc/assignment.h
@@ -0,0 +1,28 @@
+#ifndef ASSIGNMENT_H
+#define ASSIGNMENT_H
+
+#include <stdint.h>
+#include <osmocom/gsm/gsm48_ie.h>
+
+struct gsm_assignment {
+ int chan_nr;
+ int tsc;
+ int h;
+ union {
+ struct {
+ int band_arfcn;
+ } h0;
+ struct {
+ int maio;
+ int hsn;
+ uint16_t ma[64];
+ int ma_len;
+ } h1;
+ };
+ int chan_mode;
+ int rate_conf;
+};
+
+void parse_assignment(uint8_t *msg, unsigned len, struct gsm_sysinfo_freq *cell_arfcns, struct gsm_assignment *ga);
+
+#endif
diff --git a/src/host/layer23/src/misc/cell_log.c b/src/host/layer23/src/misc/cell_log.c
index aa964f48..b1012132 100644
--- a/src/host/layer23/src/misc/cell_log.c
+++ b/src/host/layer23/src/misc/cell_log.c
@@ -45,20 +45,35 @@
#include <osmocom/bb/misc/cell_log.h>
#include "../../../gsmmap/geo.h"
-#define READ_WAIT 2, 0
+#define READ_WAIT 5, 0
+#define IMM_WAIT 60, 0
#define RACH_WAIT 0, 900000
-#define MIN_RXLEV -106
+#define MIN_RXLEV -90
#define MAX_DIST 2000
+#define NUM_SYSINFO 30
+
+extern int wait_time;
+extern int log_gprs;
+extern int scan_only;
+extern char *scan_band;
+
+#include "cellid.c"
enum {
SCAN_STATE_PM,
SCAN_STATE_SYNC,
- SCAN_STATE_READ,
+ SCAN_STATE_BCCH,
+ SCAN_STATE_READY,
SCAN_STATE_RACH,
};
/* ranges of bands */
-static uint16_t band_range[][2] = {{0, 124}, {512, 885}, {955, 1023}, {0, 0}};
+static uint16_t *band_range = 0;
+static uint16_t range_all[] = {0, 124, 512, 885, 955, 1023, 0, 0};
+static uint16_t range_900[] = {0, 124, 955, 1023, 0, 0};
+static uint16_t range_1800[] = {512, 885, 0, 0};
+static uint16_t range_850[] = {128, 251, 0, 0};
+static uint16_t range_1900[] = {1024, 1322, 0, 0};
#define INFO_FLG_PM 1
#define INFO_FLG_SYNC 2
@@ -75,12 +90,38 @@ static struct osmo_timer_list timer;
static struct pm_info {
uint16_t flags;
int8_t rxlev;
-} pm[1024];
+} pm[1024+299];
+
+enum dch_state_t {
+ DCH_NONE,
+ DCH_WAIT_EST,
+ DCH_ACTIVE,
+ DCH_WAIT_REL,
+};
+
+static struct {
+ uint8_t * si[NUM_SYSINFO];
+ 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;
+
+static int sdcch = 0;
+static int got_data = 0;
+static int stop_raw = 0;
+static int collecting = 0;
+static int short_count;
static int started = 0;
static int state;
static int8_t min_rxlev = MIN_RXLEV;
static int sync_count;
+static int sync_retry;
static int pm_index, pm_gps_valid;
static double pm_gps_x, pm_gps_y, pm_gps_z;
static int arfcn;
@@ -116,6 +157,22 @@ static void start_sync(void);
static void start_rach(void);
static void start_pm(void);
+static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms);
+
+uint16_t index2arfcn(int index)
+{
+ if (index >= 1024)
+ return (index-1024+512) | ARFCN_PCS;
+ return index;
+}
+
+int arfcn2index(uint16_t arfcn)
+{
+ if ((arfcn & ARFCN_PCS) && arfcn >= 512 && arfcn <= 810)
+ return (arfcn & 1023)-512+1024;
+ return arfcn & 1023;
+}
+
static void log_gps(void)
{
if (!g.enable || !g.valid)
@@ -151,7 +208,7 @@ static void log_pm(void)
LOGFILE("[power]\n");
log_time();
log_gps();
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if ((pm[i].flags & INFO_FLG_PM)) {
if (!count)
LOGFILE("arfcn %d", i);
@@ -185,8 +242,9 @@ static void log_sysinfo(void)
if (log_si.ta != 0xff)
sprintf(ta_str, " TA=%d", log_si.ta);
- LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC=%s MNC=%s (%s, %s)%s\n",
- arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
+ rxlev = meas->rxlev / meas->frames - 110;
+ LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d PWR=%ddB MCC=%s MNC=%s (%s, %s)%s\n",
+ arfcn, rxlev, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);
LOGFILE("[sysinfo]\n");
@@ -194,8 +252,8 @@ static void log_sysinfo(void)
log_time();
log_gps();
LOGFILE("bsic %d,%d\n", s->bsic >> 3, s->bsic & 7);
- rxlev = meas->rxlev / meas->frames - 110;
LOGFILE("rxlev %d\n", rxlev);
+ LOGFILE("mcc %s mnc %s\n", gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc));
if (s->si1)
log_frame("si1", s->si1_msg);
if (s->si2)
@@ -217,9 +275,14 @@ static void log_sysinfo(void)
static void timeout_cb(void *arg)
{
+ if (sdcch) {
+ stop_raw = 1;
+ }
switch (state) {
- case SCAN_STATE_READ:
+ case SCAN_STATE_BCCH:
LOGP(DRR, LOGL_INFO, "Timeout reading BCCH\n");
+ case SCAN_STATE_READY:
+ printf("Timeout\n");
start_sync();
break;
case SCAN_STATE_RACH:
@@ -266,7 +329,7 @@ static void start_rach(void)
"(OTHER with NECI)\n", chan_req_val);
} else {
chan_req_mask = 0x1f;
- chan_req_val = 0xe0;
+ chan_req_val = 0xf0;
LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x (OTHER no NECI)\n",
chan_req_val);
}
@@ -305,8 +368,10 @@ static void start_sync(void)
int i, dist = 0;
char dist_str[32] = "";
+ if (sdcch)
+ return;
arfcn = 0xffff;
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if ((pm[i].flags & INFO_FLG_PM)
&& !(pm[i].flags & INFO_FLG_SYNC)) {
if (pm[i].rxlev > rxlev) {
@@ -329,19 +394,30 @@ static void start_sync(void)
sprintf(dist_str, " dist %d", (int)dist);
}
if (dist > MAX_DIST || arfcn == 0xffff || rxlev < min_rxlev) {
+ if (scan_only) {
+ scan_exit();
+ exit(0);
+ }
memset(pm, 0, sizeof(pm));
pm_index = 0;
- sync_count = 0;
+ printf("end of sync\n");
+ wait_time *= 2;
start_pm();
return;
}
pm[arfcn].flags |= INFO_FLG_SYNC;
- LOGP(DSUM, LOGL_INFO, "Sync ARFCN %d (rxlev %d, %d syncs "
- "left)%s\n", arfcn, pm[arfcn].rxlev, sync_count--, dist_str);
memset(&sysinfo, 0, sizeof(sysinfo));
sysinfo.arfcn = arfcn;
state = SCAN_STATE_SYNC;
l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
+ stop_raw = 0;
+ collecting = 0;
+ sync_retry = 0;
+ reset_cid();
+ memset(&app_state.cell_arfcns, 0x00, sizeof(app_state.cell_arfcns));
+ got_data = (log_gprs ? 0 : 1);
+ if (!scan_only)
+ printf("\nARFCN %d: tuning\n", arfcn);
l1ctl_tx_fbsb_req(ms, arfcn, L1CTL_FBSB_F_FB01SB, 100, 0,
CCCH_MODE_NONE);
}
@@ -351,8 +427,8 @@ static void start_pm(void)
uint16_t from, to;
state = SCAN_STATE_PM;
- from = band_range[pm_index][0];
- to = band_range[pm_index][1];
+ from = band_range[2*pm_index+0];
+ to = band_range[2*pm_index+1];
if (from == 0 && to == 0) {
LOGP(DSUM, LOGL_INFO, "Measurement done\n");
@@ -366,7 +442,7 @@ static void start_pm(void)
}
LOGP(DSUM, LOGL_INFO, "Measure from %d to %d\n", from, to);
l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
- l1ctl_tx_pm_req_range(ms, from, to);
+ l1ctl_tx_pm_req_range(ms, index2arfcn(from), index2arfcn(to));
}
static int signal_cb(unsigned int subsys, unsigned int signal,
@@ -374,6 +450,10 @@ static int signal_cb(unsigned int subsys, unsigned int signal,
{
struct osmobb_meas_res *mr;
struct osmobb_fbsb_res *fr;
+ struct osmobb_msg_ind *mi;
+ struct osmocom_ms *ms;
+ static unsigned loss_count = 0;
+
uint16_t index;
if (subsys != SS_L1CTL)
@@ -389,149 +469,83 @@ static int signal_cb(unsigned int subsys, unsigned int signal,
sync_count++;
// printf("rxlev %d = %d (sync_count %d)\n", index, pm[index].rxlev, sync_count);
break;
+ case S_L1CTL_BURST_IND:
+ mi = signal_data;
+ layer3_rx_burst(mi->ms, mi->msg);
+ break;
case S_L1CTL_PM_DONE:
pm_index++;
start_pm();
break;
case S_L1CTL_FBSB_RESP:
- fr = signal_data;
- sysinfo.bsic = fr->bsic;
- state = SCAN_STATE_READ;
- memset(&ms->meas, 0, sizeof(ms->meas));
- memset(&log_si, 0, sizeof(log_si));
- log_si.flags |= INFO_FLG_SYNC;
- log_si.ta = 0xff; /* invalid */
- start_timer(READ_WAIT);
+ loss_count = 0;
+ if (sdcch)
+ break;
+ if (!scan_only)
+ printf("ARFCN %d: got sync\n", arfcn);
+ if (state < SCAN_STATE_BCCH) {
+ state = SCAN_STATE_BCCH;
+ fr = signal_data;
+ ms = fr->ms;
+ sysinfo.bsic = fr->bsic;
+ memset(&ms->meas, 0, sizeof(ms->meas));
+ memset(&log_si, 0, sizeof(log_si));
+ log_si.flags |= INFO_FLG_SYNC;
+ log_si.ta = 0xff; /* invalid */
+ }
+ if (!collecting) {
+ start_timer(READ_WAIT);
+ }
LOGP(DRR, LOGL_INFO, "Synchronized, start reading\n");
break;
case S_L1CTL_FBSB_ERR:
- LOGP(DRR, LOGL_INFO, "Sync failed\n");
- start_sync();
+ if (scan_only || (state < SCAN_STATE_BCCH)) {
+ start_sync();
+ break;
+ }
+ if (sync_retry < wait_time/60) {
+ printf("ARFCN %d: resync\n", arfcn);
+ sync_retry++;
+ fr = signal_data;
+ ms = fr->ms;
+ l1ctl_tx_dm_rel_req(ms);
+ return l1ctl_tx_fbsb_req(ms, arfcn,
+ L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_NONE);
+ }
break;
case S_L1CTL_RESET:
- if (started)
- break;
- started = 1;
- memset(pm, 0, sizeof(pm));
- pm_index = 0;
- sync_count = 0;
- start_pm();
- }
- return 0;
-}
-
-static int ta_result(uint8_t ta)
-{
- stop_timer();
-
- if (ta == 0xff)
- LOGP(DSUM, LOGL_INFO, "Got assignment reject\n");
- else {
- LOGP(DSUM, LOGL_DEBUG, "Got assignment TA = %d\n", ta);
- log_si.ta = ta;
- }
-
- log_sysinfo();
- start_sync();
-
- return 0;
-}
-
-/* match request reference agains request */
-static int match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref)
-{
- uint8_t ia_t1, ia_t2, ia_t3;
-
- /* filter confirmed RACH requests only */
- if (rach_ref.valid && ref->ra == rach_ref.cr) {
- ia_t1 = ref->t1;
- ia_t2 = ref->t2;
- ia_t3 = (ref->t3_high << 3) | ref->t3_low;
- if (ia_t1 == rach_ref.t1 && ia_t2 == rach_ref.t2
- && ia_t3 == rach_ref.t3) {
- LOGP(DRR, LOGL_INFO, "request %02x matches "
- "(fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2,
- ia_t3);
- return 1;
- } else
- LOGP(DRR, LOGL_INFO, "request %02x matches but not "
- "frame number (IMM.ASS fn=%d,%d,%d != RACH "
- "fn=%d,%d,%d)\n", ref->ra, ia_t1, ia_t2, ia_t3,
- rach_ref.t1, rach_ref.t2, rach_ref.t3);
- }
-
- return 0;
-}
-
-/* 9.1.18 IMMEDIATE ASSIGNMENT is received */
-static int imm_ass(struct osmocom_ms *ms, struct msgb *msg)
-{
- struct gsm48_imm_ass *ia = msgb_l3(msg);
-
- LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT:\n");
-
- if (state != SCAN_STATE_RACH) {
- LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
- return 0;
- }
-
- /* request ref */
- if (match_ra(ms, &ia->req_ref)) {
- return ta_result(ia->timing_advance);
- }
- LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
-
- return 0;
-}
-
-/* 9.1.19 IMMEDIATE ASSIGNMENT EXTENDED is received */
-static int imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
-{
- struct gsm48_imm_ass_ext *ia = msgb_l3(msg);
-
- LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT EXTENDED:\n");
-
- if (state != SCAN_STATE_RACH) {
- LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
- return 0;
- }
-
- /* request ref 1 */
- if (match_ra(ms, &ia->req_ref1)) {
- return ta_result(ia->timing_advance1);
- }
- /* request ref 2 */
- if (match_ra(ms, &ia->req_ref2)) {
- return ta_result(ia->timing_advance2);
- }
- LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
-
- return 0;
-}
-
-/* 9.1.20 IMMEDIATE ASSIGNMENT REJECT is received */
-static int imm_ass_rej(struct osmocom_ms *ms, struct msgb *msg)
-{
- struct gsm48_imm_ass_rej *ia = msgb_l3(msg);
- int i;
- struct gsm48_req_ref *req_ref;
-
- LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT:\n");
-
- if (state != SCAN_STATE_RACH) {
- LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
- return 0;
- }
-
- for (i = 0; i < 4; i++) {
- /* request reference */
- req_ref = (struct gsm48_req_ref *)
- (((uint8_t *)&ia->req_ref1) + i * 4);
- LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT "
- "(ref 0x%02x)\n", req_ref->ra);
- if (match_ra(ms, req_ref)) {
- return ta_result(0xff);
+ if (sdcch) {
+ printf("RESET! while sdcch\n");
+ } else {
+ if (started)
+ break;
+ started = 1;
+ loss_count = 0;
+ memset(pm, 0, sizeof(pm));
+ pm_index = 0;
+ start_pm();
}
+ break;
+ case S_L1CTL_LOSS_IND:
+ if (sdcch)
+ break;
+ loss_count++;
+ ms = signal_data;
+ if (loss_count > 10) {
+ loss_count = 0;
+ if (sync_retry > 3) {
+ start_sync();
+ } else {
+ sync_retry++;
+ l1ctl_tx_dm_rel_req(ms);
+ sleep(1);
+ return l1ctl_tx_fbsb_req(ms, arfcn,
+ L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_NONE);
+ }
+ }
+ break;
}
return 0;
@@ -542,17 +556,21 @@ static int pch_agch(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+ if (sdcch || (state != SCAN_STATE_READY))
+ return 0;
+
switch (sih->system_information) {
case GSM48_MT_RR_PAG_REQ_1:
case GSM48_MT_RR_PAG_REQ_2:
case GSM48_MT_RR_PAG_REQ_3:
return 0;
case GSM48_MT_RR_IMM_ASS:
- return imm_ass(ms, msg);
+// return imm_ass(ms, msg);
+ return gsm48_rx_imm_ass(msg, ms);
case GSM48_MT_RR_IMM_ASS_EXT:
- return imm_ass_ext(ms, msg);
+// return imm_ass_ext(ms, msg);
case GSM48_MT_RR_IMM_ASS_REJ:
- return imm_ass_rej(ms, msg);
+// return imm_ass_rej(ms, msg);
default:
return -EINVAL;
}
@@ -564,7 +582,12 @@ static int new_sysinfo(void)
struct gsm48_sysinfo *s = &sysinfo;
/* restart timer */
- start_timer(READ_WAIT);
+ //start_timer(READ_WAIT);
+
+ if (s->si3 && scan_only) {
+ log_sysinfo();
+ start_sync();
+ }
/* mandatory */
if (!s->si1 || !s->si2 || !s->si3 || !s->si4) {
@@ -586,10 +609,11 @@ static int new_sysinfo(void)
LOGP(DRR, LOGL_INFO, "Sysinfo complete\n");
- stop_timer();
+ log_sysinfo();
+
+ state = SCAN_STATE_READY;
- rach_count = 0;
- start_rach();
+ start_timer(IMM_WAIT);
return 0;
}
@@ -599,6 +623,10 @@ static int bcch(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_sysinfo *s = &sysinfo;
struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+ struct gsm48_system_information_type_1 *si1 =
+ (struct gsm48_system_information_type_1 *) msgb_l3(msg);
+ struct gsm48_system_information_type_3 *si3 =
+ (struct gsm48_system_information_type_3 *) msgb_l3(msg);
uint8_t ccch_mode;
if (msgb_l3len(msg) != 23) {
@@ -613,6 +641,10 @@ static int bcch(struct osmocom_ms *ms, struct msgb *msg)
gsm48_decode_sysinfo1(s,
(struct gsm48_system_information_type_1 *) sih,
msgb_l3len(msg));
+ gsm48_decode_freq_list(app_state.cell_arfcns,
+ si1->cell_channel_description,
+ sizeof(si1->cell_channel_description),
+ 0xff, 0x01);
return new_sysinfo();
case GSM48_MT_RR_SYSINFO_2:
if (!memcmp(sih, s->si2_msg, sizeof(s->si2_msg)))
@@ -649,6 +681,7 @@ static int bcch(struct osmocom_ms *ms, struct msgb *msg)
CCCH_MODE_NON_COMBINED;
LOGP(DRR, LOGL_INFO, "Changing CCCH_MODE to %d\n", ccch_mode);
l1ctl_tx_ccch_mode_req(ms, ccch_mode);
+ set_cid(si3->lai.digits, si3->lai.lac, si3->cell_identity);
return new_sysinfo();
case GSM48_MT_RR_SYSINFO_4:
if (!memcmp(sih, s->si4_msg, sizeof(s->si4_msg)))
@@ -679,7 +712,7 @@ static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
}
msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
- if (state != SCAN_STATE_READ && state != SCAN_STATE_RACH) {
+ if (state < SCAN_STATE_BCCH && state != SCAN_STATE_RACH) {
return -EINVAL;
}
@@ -780,6 +813,32 @@ static int rcv_rsl(struct msgb *msg, struct lapdm_entity *le, void *l3ctx)
return rc;
}
+void set_freq_range()
+{
+ if (!scan_band) {
+ band_range = range_all;
+ return;
+ }
+ if (!strcmp(scan_band, "900")) {
+ band_range = range_900;
+ return;
+ }
+ if (!strcmp(scan_band, "1800")) {
+ band_range = range_1800;
+ return;
+ }
+ if (!strcmp(scan_band, "850")) {
+ band_range = range_850;
+ return;
+ }
+ if (!strcmp(scan_band, "1900")) {
+ band_range = range_1900;
+ return;
+ }
+ printf("Bad frequency range\n");
+ exit(-1);
+}
+
int scan_init(struct osmocom_ms *_ms)
{
ms = _ms;
@@ -787,6 +846,8 @@ int scan_init(struct osmocom_ms *_ms)
memset(&timer, 0, sizeof(timer));
lapdm_channel_set_l3(&ms->lapdm_channel, &rcv_rsl, ms);
g.enable = 1;
+ sdcch = 0;
+ set_freq_range();
osmo_gps_init();
if (osmo_gps_open())
g.enable = 0;
@@ -817,3 +878,230 @@ int scan_exit(void)
return 0;
}
+
+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;
+
+ /* If we're busy ... */
+ if (app_state.dch_state != DCH_NONE)
+ return 0;
+
+ /* Discard packet TBF assignement */
+ if (ia->page_mode & 0xf0) {
+ if (got_data) {
+ return 0;
+ } else {
+ got_data = 1;
+ printf("ARFCN %d: got DATA assignment\n", arfcn);
+ }
+ } else {
+ printf("ARFCN %d: got SDCCH assignment\n", arfcn);
+ }
+
+ 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);
+ if (arfcn != _arfcn)
+ printf("ARFCN %d: not jumping to ARFCN %d!\n", arfcn, _arfcn);
+
+ DEBUGP(DRR, "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);
+
+ DEBUGP(DRR, "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++;
+ }
+ }
+
+ if (!ma_len) {
+ if (ia->page_mode & 0xf0)
+ got_data = 0;
+ return -1;
+ }
+
+ /* 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);
+ }
+
+ DEBUGPC(DRR, "\n");
+
+ /* Set state */
+ app_state.dch_state = DCH_WAIT_EST;
+ app_state.dch_nr = ia->chan_desc.chan_nr;
+ app_state.dch_badcnt = 0;
+
+ sdcch = 1;
+ if (!collecting) {
+ collecting = 1;
+ short_count = 0;
+ start_timer(wait_time, 0);
+ }
+
+ return rv;
+}
+
+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, &lt);
+
+ snprintf(buffer, 256, "%s_%04d%02d%02d_%02d%02d_%d_%d_%02x.dat",
+ get_cid_str(),
+ lt.tm_year + 1900, lt.tm_mon, lt.tm_mday,
+ lt.tm_hour, lt.tm_min,
+ 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 l_arfcn;
+ int ul, do_rel=0;
+ static unsigned rcv_frames;
+ static unsigned rcv_snr;
+
+ if (!sdcch)
+ return;
+
+ /* Header handling */
+ bi = (struct l1ctl_burst_ind *) msg->l1h;
+
+ l_arfcn = ntohs(bi->band_arfcn);
+ rx_dbm = rxlev2dbm(bi->rx_level);
+ ul = !!(l_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 > 100) {
+ /* Change state */
+ app_state.dch_state = DCH_ACTIVE;
+ app_state.dch_badcnt = 0;
+ rcv_frames = 0;
+ rcv_snr = 0;
+ printf("ARFCN %d: session begin\n", arfcn);
+
+ /* Open output */
+ app_state.fh = fopen(gen_filename(ms, bi), "wb");
+ } else {
+ /* Abandon ? */
+ //do_rel = (app_state.dch_badcnt++) >= 8;
+ }
+ }
+ }
+
+ /* Check for channel end */
+ if (app_state.dch_state == DCH_ACTIVE) {
+ if (!ul) {
+ /* Bad burst counting */
+ if (bi->snr < 100)
+ app_state.dch_badcnt++;
+ else if (app_state.dch_badcnt >= 2)
+ app_state.dch_badcnt -= 2;
+ else
+ app_state.dch_badcnt = 0;
+
+ /* Release condition */
+ if (bi->chan_nr & 0xe0)
+ do_rel = app_state.dch_badcnt >= 4;
+ }
+
+ if (!ul) {
+ rcv_frames++;
+ rcv_snr += bi->snr;
+
+ /* capture up to 3 minutes */
+ if (rcv_frames >= 40000)
+ do_rel = 1;
+ }
+
+ /* Save the burst */
+ fwrite(bi, sizeof(*bi), 1, app_state.fh);
+ }
+
+ /* SNR check */
+ if (do_rel) {
+ printf("ARFCN %d: session end, frames=%d SNR_avg=%d\n", arfcn, rcv_frames, rcv_snr/rcv_frames);
+ if ((bi->chan_nr & 0xe0) && (rcv_frames < 20))
+ short_count++;
+ rcv_frames = 0;
+ rcv_snr = 0;
+ app_state.dch_state = DCH_NONE;
+ app_state.dch_badcnt = 0;
+ if (app_state.fh) {
+ fclose(app_state.fh);
+ app_state.fh = NULL;
+ }
+ sdcch = 0;
+ if (stop_raw || (short_count > 3)) {
+ collecting = 0;
+ pm[arfcn].flags |= INFO_FLG_SYNC;
+ start_sync();
+ } else {
+ l1ctl_tx_dm_rel_req(ms);
+ l1ctl_tx_fbsb_req(ms, arfcn, L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_NON_COMBINED);
+ }
+ }
+}
+
+void layer3_app_reset(void)
+{
+ /* Reset state */
+ memset(app_state.si, 0, NUM_SYSINFO*sizeof(uint8_t*));
+ app_state.ccch_mode = CCCH_MODE_NONE;
+ app_state.dch_state = DCH_NONE;
+ app_state.dch_badcnt = 0;
+
+ if (app_state.fh)
+ fclose(app_state.fh);
+ app_state.fh = NULL;
+}
+
diff --git a/src/host/layer23/src/misc/cellid.c b/src/host/layer23/src/misc/cellid.c
new file mode 100644
index 00000000..afc53658
--- /dev/null
+++ b/src/host/layer23/src/misc/cellid.c
@@ -0,0 +1,110 @@
+#ifndef _cellid_c_
+#define _cellid_c_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+struct gsm_cell_id {
+ uint16_t mcc;
+ uint16_t mnc;
+ uint16_t lac;
+ uint16_t cid;
+};
+
+static struct gsm_cell_id *_gcid = 0;
+
+static char _gcid_str[32] = "\0";
+
+const char *get_cid_str()
+{
+ if (_gcid)
+ return _gcid_str;
+
+ return "unknown";
+}
+
+void reset_cid()
+{
+ if (_gcid)
+ free(_gcid);
+ _gcid = 0;
+}
+
+void set_cid(uint8_t *digits, uint16_t nlac, uint16_t ncid)
+{
+ if (_gcid)
+ return;
+
+ _gcid = malloc(sizeof(struct gsm_cell_id));
+
+ _gcid->mcc = (digits[0] & 0xf) * 100;
+ _gcid->mcc += (digits[0] >> 4) * 10;
+ _gcid->mcc += (digits[1] & 0xf) * 1;
+
+ if ((digits[1] >> 4) == 0xf) {
+ _gcid->mnc = (digits[2] & 0xf) * 10;
+ _gcid->mnc += (digits[2] >> 4) * 1;
+ } else {
+ _gcid->mnc = (digits[2] & 0xf) * 100;
+ _gcid->mnc += (digits[2] >> 4) * 10;
+ _gcid->mnc += (digits[1] >> 4) * 1;
+ }
+
+ _gcid->lac = ntohs(nlac);
+ _gcid->cid = ntohs(ncid);
+
+ sprintf(_gcid_str, "%d_%d_%.04X_%.04X",
+ _gcid->mcc, _gcid->mnc,
+ _gcid->lac, _gcid->cid);
+
+ printf("Cell ID: %s\n", _gcid_str);
+ fflush(stdout);
+}
+
+void set_cid_from_si6(uint8_t *msg)
+{
+ struct gsm48_system_information_type_6 *si;
+
+ if (_gcid)
+ return;
+
+ si = (struct gsm48_system_information_type_6 *) &msg[5];
+
+ if (((msg[2] & 0x1c) == 0) &&
+ ((msg[4] & 0xfc) != 0) &&
+ (si->rr_protocol_discriminator == 6) &&
+ (si->system_information == 0x1e)) {
+ _gcid = malloc(sizeof(struct gsm_cell_id));
+
+ memset(_gcid, 0, sizeof(struct gsm_cell_id));
+
+ _gcid->cid = ntohs(si->cell_identity);
+
+ _gcid->lac = ntohs(si->lai.lac);
+
+ _gcid->mcc = (si->lai.digits[0] & 0xf) * 100;
+ _gcid->mcc += (si->lai.digits[0] >> 4) * 10;
+ _gcid->mcc += (si->lai.digits[1] & 0xf) * 1;
+
+ if ((si->lai.digits[1] >> 4) == 0xf) {
+ _gcid->mnc = (si->lai.digits[2] & 0xf) * 10;
+ _gcid->mnc += (si->lai.digits[2] >> 4) * 1;
+ } else {
+ _gcid->mnc = (si->lai.digits[2] & 0xf) * 100;
+ _gcid->mnc += (si->lai.digits[2] >> 4) * 10;
+ _gcid->mnc += (si->lai.digits[1] >> 4) * 1;
+ }
+
+ sprintf(_gcid_str, "%d_%d_%.04X_%.04X",
+ _gcid->mcc, _gcid->mnc,
+ _gcid->lac, _gcid->cid);
+
+ printf("Cell ID: %s\n", _gcid_str);
+ fflush(stdout);
+ }
+}
+
+#endif
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;
+}
diff --git a/src/host/osmocon/osmocon.c b/src/host/osmocon/osmocon.c
index 66f24625..cde3044c 100644
--- a/src/host/osmocon/osmocon.c
+++ b/src/host/osmocon/osmocon.c
@@ -130,9 +130,9 @@ struct dnload {
enum dnload_state state;
enum romload_state romload_state;
enum mtk_state mtk_state;
- enum dnload_mode mode, previous_mode;
+ enum dnload_mode mode;
struct osmo_fd serial_fd;
- char *filename, *previous_filename;
+ char *filename;
char *chainload_filename;
int expect_hdlc;
@@ -217,6 +217,45 @@ static const uint8_t mtk_init_cmd[] = { 0xa0, 0x0a, 0x50, 0x05 };
static const uint8_t mtk_init_resp[] = { 0x5f, 0xf5, 0xaf, 0xfa };
static const uint8_t mtk_command[] = { 0xa1, 0xa2, 0xa4, 0xa8 };
+
+static int cable_type = 0;
+
+int serial_up_to_eleven(void)
+{
+ int rv;
+
+ /* Attempt custom baudrate */
+ switch(cable_type) {
+ case 0:
+ rv = osmo_serial_set_baudrate(dnload.serial_fd.fd, B115200);
+ break;
+ case 1:
+ rv = osmo_serial_set_baudrate(dnload.serial_fd.fd, B460800);
+ break;
+ case 2:
+ rv = osmo_serial_set_custom_baudrate(dnload.serial_fd.fd, 406250);
+ }
+ if (rv == 0)
+ return 0;
+
+#ifdef I_HAVE_A_CP210x /* and I know what I'm doing, I swear ! */
+ /* Try closest standard baudrate (CP210x reprogrammed adapters) */
+ rv = osmo_serial_set_baudrate(dnload.serial_fd.fd, B460800);
+ if (rv == 0)
+ return 0;
+#endif
+
+ /* Everything failed */
+ fprintf(stderr, "!!!\n");
+ fprintf(stderr, "!!! ERROR !!!\n");
+ fprintf(stderr, "!!!\n");
+ fprintf(stderr, "!!! Unable to set custom baudrate, please use appropriate cable\n");
+ fprintf(stderr, "!!! ( see wiki http://bb.osmocom.org/trac/wiki/Sniffing )\n");
+ fprintf(stderr, "!!!\n");
+
+ exit(-1);
+}
+
static void beacon_timer_cb(void *p)
{
int rc;
@@ -813,21 +852,22 @@ static int handle_read(void)
dnload.write_ptr = dnload.data;
dnload.expect_hdlc = 1;
+
/* check for romloader chainloading mode used as a workaround
* for the magic on the C139/C140 and J100i */
if (dnload.chainload_filename != NULL) {
printf("Enabled Compal ramloader -> Calypso romloader"
" chainloading mode\n");
bufptr = buffer;
- dnload.previous_filename = dnload.filename;
dnload.filename = dnload.chainload_filename;
- dnload.previous_mode = dnload.mode;
dnload.mode = MODE_ROMLOAD;
osmo_serial_set_baudrate(dnload.serial_fd.fd, ROMLOAD_INIT_BAUDRATE);
tick_timer.cb = &beacon_timer_cb;
tick_timer.data = &tick_timer;
osmo_timer_schedule(&tick_timer, 0, dnload.beacon_interval);
}
+ else
+ serial_up_to_eleven();
} else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) {
printf("Received DOWNLOAD NACK from phone, something went"
" wrong :(\n");
@@ -971,22 +1011,11 @@ static int handle_read_romload(void)
if (!memcmp(buffer, romload_branch_ack,
sizeof(romload_branch_ack))) {
printf("Received branch ack, your code is running now!\n");
+ serial_up_to_eleven();
dnload.serial_fd.when = BSC_FD_READ;
dnload.romload_state = FINISHED;
dnload.write_ptr = dnload.data;
dnload.expect_hdlc = 1;
-
- if (dnload.chainload_filename == NULL)
- break;
-
- /* if using chainloading mode, switch back to the Compal
- * ramloader settings to make sure the auto-reload
- * feature works */
- bufptr = buffer;
- dnload.romload_state = WAITING_IDENTIFICATION;
- dnload.filename = dnload.previous_filename;
- dnload.mode = dnload.previous_mode;
- osmo_serial_set_baudrate(dnload.serial_fd.fd, MODEM_BAUDRATE);
} else if (!memcmp(buffer, romload_branch_nack,
sizeof(romload_branch_nack))) {
printf("Received branch nack, aborting\n");
@@ -1398,16 +1427,15 @@ int main(int argc, char **argv)
{
int opt, flags;
uint32_t tmp_load_address = ROMLOAD_ADDRESS;
- const char *serial_dev = "/dev/ttyUSB1";
- const char *layer2_un_path = "/tmp/osmocom_l2";
+ const char *serial_dev = "/dev/ttyUSB0";
+ const char *layer2_un_path = "/tmp/osmocom_log";
const char *loader_un_path = "/tmp/osmocom_loader";
- dnload.mode = MODE_C123;
+ dnload.mode = MODE_C123xor;
dnload.chainload_filename = NULL;
- dnload.previous_filename = NULL;
dnload.beacon_interval = DEFAULT_BEACON_INTERVAL;
- while ((opt = getopt(argc, argv, "d:hl:p:m:c:s:i:v")) != -1) {
+ while ((opt = getopt(argc, argv, "d:hl:p:m:c:s:i:vCF")) != -1) {
switch (opt) {
case 'p':
serial_dev = optarg;
@@ -1435,6 +1463,12 @@ int main(int argc, char **argv)
case 'i':
dnload.beacon_interval = atoi(optarg) * 1000;
break;
+ case 'C':
+ cable_type = 1;
+ break;
+ case 'F':
+ cable_type = 2;
+ break;
case 'h':
default:
usage(argv[0]);
diff --git a/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h b/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
index 5057ada8..eecc27ce 100644
--- a/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -793,6 +793,7 @@ struct gsm48_rr_status {
#define GSM48_MT_RR_SYSINFO_2bis 0x02
#define GSM48_MT_RR_SYSINFO_2ter 0x03
+#define GSM48_MT_RR_SYSINFO_2quater 0x07
#define GSM48_MT_RR_SYSINFO_5bis 0x05
#define GSM48_MT_RR_SYSINFO_5ter 0x06
#define GSM48_MT_RR_SYSINFO_9 0x04
diff --git a/src/target/firmware/battery/compal_e88.c b/src/target/firmware/battery/compal_e88.c
index 609d4063..dfac1b79 100644
--- a/src/target/firmware/battery/compal_e88.c
+++ b/src/target/firmware/battery/compal_e88.c
@@ -283,6 +283,7 @@ bat_compal_e88_upd_measurements(){
(50+100*(adc-VBAT_empty))/(VBAT_full-VBAT_empty);
}
+#if 0
/* DEBUG */
printf("BAT-ADC: ");
for(i=0;i<MADC_NUM_CHANNELS;i++)
@@ -302,6 +303,7 @@ bat_compal_e88_upd_measurements(){
printf("\tBCICTL2=0x%03x\n",i);
printf("\tbattery-info.flags=0x%08x\n",battery_info.flags);
printf("\tbat_compal_e88_chg_state=%d\n",bat_compal_e88_chg_state);
+#endif
}
/* bat_compal_e88_adc_read() :
diff --git a/src/target/firmware/board/compal_e86/init.c b/src/target/firmware/board/compal_e86/init.c
index 2d463cb2..42873166 100644
--- a/src/target/firmware/board/compal_e86/init.c
+++ b/src/target/firmware/board/compal_e86/init.c
@@ -109,6 +109,7 @@ void board_init(void)
/* initialize MODEM UART to be used for sercomm*/
uart_init(SERCOMM_UART_NR, 1);
+ //uart_baudrate(SERCOMM_UART_NR, UART_460800);
uart_baudrate(SERCOMM_UART_NR, UART_115200);
/* initialize IRDA UART to be used for old-school console code.
diff --git a/src/target/firmware/board/compal_e88/init.c b/src/target/firmware/board/compal_e88/init.c
index 2e957311..db2914f7 100755
--- a/src/target/firmware/board/compal_e88/init.c
+++ b/src/target/firmware/board/compal_e88/init.c
@@ -104,6 +104,7 @@ void board_init(void)
/* initialize MODEM UART to be used for sercomm*/
uart_init(SERCOMM_UART_NR, 1);
+ //uart_baudrate(SERCOMM_UART_NR, UART_460800);
uart_baudrate(SERCOMM_UART_NR, UART_115200);
/* Initialize IRDA UART to be used for old-school console code.
@@ -127,7 +128,7 @@ void board_init(void)
fb_init();
bl_mode_pwl(1);
- bl_level(50);
+ bl_level(0);
/* Initialize keypad driver */
keypad_init(1);
diff --git a/src/target/firmware/board/compal_e99/init.c b/src/target/firmware/board/compal_e99/init.c
index 31eb978d..b69f379a 100644
--- a/src/target/firmware/board/compal_e99/init.c
+++ b/src/target/firmware/board/compal_e99/init.c
@@ -109,6 +109,7 @@ void board_init(void)
/* initialize MODEM UART to be used for sercomm*/
uart_init(SERCOMM_UART_NR, 1);
+ //uart_baudrate(SERCOMM_UART_NR, UART_460800);
uart_baudrate(SERCOMM_UART_NR, UART_115200);
/* initialize IRDA UART to be used for old-school console code.
@@ -130,7 +131,7 @@ void board_init(void)
/* Initialize LCD driver (uses UWire) and backlight */
bl_mode_pwl(1);
- bl_level(50);
+ bl_level(0);
fb_init();
diff --git a/src/target/firmware/board/gta0x/init.c b/src/target/firmware/board/gta0x/init.c
index d125e15f..46e59175 100644
--- a/src/target/firmware/board/gta0x/init.c
+++ b/src/target/firmware/board/gta0x/init.c
@@ -102,6 +102,7 @@ void board_init(void)
/* initialize MODEM UART to be used for sercomm*/
uart_init(SERCOMM_UART_NR, 1);
+ //uart_baudrate(SERCOMM_UART_NR, UART_460800);
uart_baudrate(SERCOMM_UART_NR, UART_115200);
/* Initialize IRDA UART to be used for old-school console code.
@@ -123,7 +124,7 @@ void board_init(void)
/* Initialize LCD driver (uses I2C) and backlight */
bl_mode_pwl(1);
- bl_level(50);
+ bl_level(0);
/* Initialize keypad driver */
keypad_init(1);
diff --git a/src/target/firmware/board/pirelli_dpl10/init.c b/src/target/firmware/board/pirelli_dpl10/init.c
index ef184033..f7aab7a8 100644
--- a/src/target/firmware/board/pirelli_dpl10/init.c
+++ b/src/target/firmware/board/pirelli_dpl10/init.c
@@ -113,6 +113,7 @@ void board_init(void)
/* initialize MODEM UART to be used for sercomm*/
uart_init(SERCOMM_UART_NR, 1);
+ //uart_baudrate(SERCOMM_UART_NR, UART_460800);
uart_baudrate(SERCOMM_UART_NR, UART_115200);
/* Initialize IRDA UART to be used for old-school console code.
@@ -134,7 +135,7 @@ void board_init(void)
/* Initialize LCD driver and backlight (0 is max, 255 min brightness) */
bl_mode_pwl(1);
- bl_level(50);
+ bl_level(255);
fb_init();
diff --git a/src/target/firmware/calypso/dsp.c b/src/target/firmware/calypso/dsp.c
index 1daecb2d..0ca272ec 100644
--- a/src/target/firmware/calypso/dsp.c
+++ b/src/target/firmware/calypso/dsp.c
@@ -85,6 +85,7 @@ struct dsp_section {
#include "dsp_params.c"
#include "dsp_bootcode.c"
#include "dsp_dumpcode.c"
+#include "dsp_sniffcode.c"
struct dsp_api dsp_api = {
.ndb = (T_NDB_MCU_DSP *) BASE_API_NDB,
@@ -204,7 +205,8 @@ static void dsp_set_params(int16_t *param_tab, int param_size)
/* Start DSP up to bootloader */
dsp_pre_boot(dsp_bootcode);
- /* FIXME: Implement Patch download, if any */
+ dputs("Installing DSP sniff patch\n");
+ dsp_bl_upload_sections(dsp_sniffcode);
dputs("Setting some dsp_api.ndb values\n");
dsp_api.ndb->d_background_enable = 0;
@@ -225,7 +227,9 @@ static void dsp_set_params(int16_t *param_tab, int param_size)
dputs("Setting API NDB parameters\n");
for (i = 0; i < param_size; i ++)
*param_ptr++ = param_tab[i];
-
+
+ dsp_api.param->d_gprs_install_address = DSP_SNIFF_PATCH_START;
+
dsp_dump_version();
dputs("Finishing download phase\n");
diff --git a/src/target/firmware/calypso/dsp_sniffcode.c b/src/target/firmware/calypso/dsp_sniffcode.c
new file mode 100644
index 00000000..865ce815
--- /dev/null
+++ b/src/target/firmware/calypso/dsp_sniffcode.c
@@ -0,0 +1,42 @@
+/* Generated from src/target_dsp/calypso/dsp_sniff.bin */
+
+#define _SA_DECL (const uint16_t *)&(const uint16_t [])
+
+static const struct dsp_section dsp_sniffcode[] = {
+ {
+ .addr = 0x015c,
+ .size = 0x0051,
+ .data = _SA_DECL {
+ 0x76f8, 0x3f6b, 0x0160, 0xfc00,
+ 0x76f8, 0x439e, 0x0164, 0xfc00,
+ 0x7711, 0x2000, 0x61f8, 0x3fb0,
+ 0x0001, 0xf820, 0x016d, 0x7711,
+ 0x208a, 0x7311, 0x2114, 0x7699,
+ 0x0000, 0x6d91, 0x7311, 0x2115,
+ 0xf020, 0xb12c, 0xf074, 0xaac3,
+ 0x7211, 0x2114, 0xf495, 0xf495,
+ 0x1281, 0xf845, 0x018a, 0xf010,
+ 0x0001, 0x8081, 0xf074, 0xb74c,
+ 0xf020, 0x018b, 0xf074, 0xaa9f,
+ 0xf073, 0x0178, 0xfc00, 0xe834,
+ 0xf074, 0xa9ea, 0x7213, 0x2115,
+ 0xf495, 0xf495, 0x7093, 0x3fa4,
+ 0x7093, 0x3fa5, 0x7093, 0x3fa7,
+ 0x7093, 0x3fa6, 0x7093, 0x0cce,
+ 0x7712, 0x0ccf, 0x7711, 0x001c,
+ 0x47f8, 0x0011, 0xe589, 0x7313,
+ 0x2115, 0x7211, 0x2114, 0xf495,
+ 0xf495, 0x6be1, 0x0001, 0x0001,
+ 0xfc00,
+ },
+ },
+ { /* Guard */
+ .addr = 0,
+ .size = 0,
+ .data = NULL,
+ },
+};
+
+#undef _SA_DECL
+
+#define DSP_SNIFF_PATCH_START 0x015c
diff --git a/src/target/firmware/include/inttypes.h b/src/target/firmware/include/inttypes.h
new file mode 100644
index 00000000..dcbd6e19
--- /dev/null
+++ b/src/target/firmware/include/inttypes.h
@@ -0,0 +1 @@
+stdint.h \ No newline at end of file
diff --git a/src/target/firmware/include/layer1/prim.h b/src/target/firmware/include/layer1/prim.h
index 30c51ae6..73f7c681 100644
--- a/src/target/firmware/include/layer1/prim.h
+++ b/src/target/firmware/include/layer1/prim.h
@@ -31,4 +31,8 @@ extern const struct tdma_sched_item tch_a_sched_set[];
extern const struct tdma_sched_item tch_d_sched_set[];
extern const struct tdma_sched_item neigh_pm_sched_set[];
+extern const struct tdma_sched_item sniff_xcch_dl_sched_set[];
+extern const struct tdma_sched_item sniff_xcch_ul_sched_set[];
+extern const struct tdma_sched_item sniff_tch_sched_set[];
+
#endif /* _L1_PRIM_H */
diff --git a/src/target/firmware/layer1/Makefile b/src/target/firmware/layer1/Makefile
index 455a444a..59b9ace2 100644
--- a/src/target/firmware/layer1/Makefile
+++ b/src/target/firmware/layer1/Makefile
@@ -5,5 +5,5 @@ layer1_SRCS=avg.c agc.c afc.c toa.c sync.c tdma_sched.c tpu_window.c init.c \
l23_api.c mframe_sched.c sched_gsmtime.c async.c rfch.c apc.c
layer1_SRCS += prim_pm.c prim_rach.c prim_tx_nb.c prim_rx_nb.c prim_fbsb.c \
- prim_freq.c prim_utils.c prim_tch.c
+ prim_freq.c prim_utils.c prim_tch.c prim_sniff.c
diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c
index ae39e634..4aed9ff0 100644
--- a/src/target/firmware/layer1/l23_api.c
+++ b/src/target/firmware/layer1/l23_api.c
@@ -262,7 +262,7 @@ static void l1ctl_rx_dm_est_req(struct msgb *msg)
}
/* figure out which MF tasks to enable */
- l1a_mftask_set(chan_nr2mf_task_mask(ul->chan_nr, NEIGH_MODE_PM));
+ l1a_mftask_set(chan_nr2mf_task_mask(ul->chan_nr, 0));
}
/* receive a L1CTL_DM_FREQ_REQ from L23 */
diff --git a/src/target/firmware/layer1/mframe_sched.c b/src/target/firmware/layer1/mframe_sched.c
index f3a6b433..bdc849a7 100644
--- a/src/target/firmware/layer1/mframe_sched.c
+++ b/src/target/firmware/layer1/mframe_sched.c
@@ -52,6 +52,10 @@ struct mframe_sched_item {
#define NB_QUAD_FH_UL NB_QUAD_UL
#define NEIGH_PM neigh_pm_sched_set
+#define SNIFF_QUAD_DL sniff_xcch_dl_sched_set
+#define SNIFF_QUAD_UL sniff_xcch_ul_sched_set
+#define SNIFF_TCH sniff_tch_sched_set
+
/* BCCH Normal */
static const struct mframe_sched_item mf_bcch_norm[] = {
{ .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 2 },
@@ -88,112 +92,112 @@ static const struct mframe_sched_item mf_ccch_comb[] = {
/* SDCCH/4 in a combined CCCH on C0T0, cannot be FH */
static const struct mframe_sched_item mf_sdcch4_0[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 22 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 22+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 42,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 22 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 22+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 42,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 42+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 42+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch4_1[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 26 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 26+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 46,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 26 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 26+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 46,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 46+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 46+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch4_2[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 32 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 32+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 51+42,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 32 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 32+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 51+42,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 51+42+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 51+42+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch4_3[] = {
- { .sched_set = NB_QUAD_DL, .modulo = 51, .frame_nr = 36 },
- { .sched_set = NB_QUAD_UL, .modulo = 51, .frame_nr = 36+15 },
- { .sched_set = NB_QUAD_DL, .modulo = 2*51, .frame_nr = 51+46,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 36 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 36+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 51+46,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_UL, .modulo = 2*51, .frame_nr = 51+46+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 51+46+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
/* SDCCH/8, can be frequency hopping (FH) */
static const struct mframe_sched_item mf_sdcch8_0[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 0 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 0+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 32,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 0 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 0+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 32,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 32+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 32+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch8_1[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 4 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 4+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 36,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 4 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 4+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 36,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 36+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 36+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch8_2[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 8 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 8+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 40,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 8 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 8+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 40,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 40+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 40+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch8_3[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 12 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 12+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 44,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 12 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 12+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 44,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 44+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 44+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch8_4[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 16 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 16+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+32,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 16 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 16+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 51+32,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+32+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 51+32+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch8_5[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 20 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 20+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+36,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 20 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 20+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 51+36,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+36+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 51+36+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch8_6[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 24 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 24+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+40,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 24 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 24+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 51+40,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+40+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 51+40+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_sdcch8_7[] = {
- { .sched_set = NB_QUAD_FH_DL, .modulo = 51, .frame_nr = 28 },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 51, .frame_nr = 28+15 },
- { .sched_set = NB_QUAD_FH_DL, .modulo = 2*51, .frame_nr = 51+44,
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 51, .frame_nr = 28 },
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 51, .frame_nr = 28+15 },
+ { .sched_set = SNIFF_QUAD_DL, .modulo = 2*51, .frame_nr = 51+44,
.flags = MF_F_SACCH },
- { .sched_set = NB_QUAD_FH_UL, .modulo = 2*51, .frame_nr = 51+44+15,
+ { .sched_set = SNIFF_QUAD_UL, .modulo = 2*51, .frame_nr = 51+44+15,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
@@ -220,73 +224,61 @@ static const struct mframe_sched_item mf_neigh_pm51[] = {
#define TCH_D tch_d_sched_set
static const struct mframe_sched_item mf_tch_f_even[] = {
- { .sched_set = TCH, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 12,
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 0 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 1 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 2 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 3 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 4 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 5 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 6 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 7 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 8 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 9 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 10 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 11 },
+ { .sched_set = SNIFF_TCH, .modulo = 26, .frame_nr = 12,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_tch_f_odd[] = {
- { .sched_set = TCH, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 25,
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 0 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 1 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 2 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 3 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 4 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 5 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 6 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 7 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 8 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 9 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 10 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 11 },
+ { .sched_set = SNIFF_TCH, .modulo = 26, .frame_nr = 25,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_tch_h_0[] = {
- { .sched_set = TCH, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 12,
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 0 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 2 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 4 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 6 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 8 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 10 },
+ { .sched_set = SNIFF_TCH, .modulo = 26, .frame_nr = 12,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
static const struct mframe_sched_item mf_tch_h_1[] = {
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 0 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 1 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 2 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 3 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 4 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 5 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 6 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 7 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 8 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 9 },
- { .sched_set = TCH_D, .modulo = 13, .frame_nr = 10 },
- { .sched_set = TCH, .modulo = 13, .frame_nr = 11 },
- { .sched_set = TCH_A, .modulo = 26, .frame_nr = 25,
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 1 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 3 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 5 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 7 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 9 },
+ { .sched_set = SNIFF_TCH, .modulo = 13, .frame_nr = 11 },
+ { .sched_set = SNIFF_TCH, .modulo = 26, .frame_nr = 25,
.flags = MF_F_SACCH },
{ .sched_set = NULL }
};
diff --git a/src/target/firmware/layer1/prim_fbsb.c b/src/target/firmware/layer1/prim_fbsb.c
index e849240b..6bc0aef4 100644
--- a/src/target/firmware/layer1/prim_fbsb.c
+++ b/src/target/firmware/layer1/prim_fbsb.c
@@ -85,6 +85,9 @@ struct l1a_fb_state {
static struct l1a_fb_state fbs;
static struct mon_state *last_fb = &fbs.mon;
+static uint32_t fbsb_last_fn;
+static uint8_t fbsb_seq;
+
static void dump_mon_state(struct mon_state *fb)
{
#if 0
@@ -487,6 +490,19 @@ static int l1s_fbdet_resp(__unused uint8_t p1, uint8_t attempt,
printf(" delay=%d (fn_offset=%d + 11 - fn=%u - 1\n", delay,
fn_offset, l1s.current_time.fn);
printf(" scheduling next FB/SB detection task with delay %u\n", delay);
+
+ if ((fn_offset-fbsb_last_fn) < 30)
+ fbsb_seq++;
+ fbsb_last_fn = fn_offset;
+
+ if (fbsb_seq > 1) {
+ printf("-- Forcing DSP reset --\n\n");
+ last_fb->attempt = 13;
+ l1s_compl_sched(L1_COMPL_FB);
+ dsp_power_on();
+ l1s_reset();
+ }
+
if (abs(last_fb->freq_diff) < fbs.req.freq_err_thresh2 &&
last_fb->snr > FB1_SNR_THRESH) {
/* synchronize before reading SB */
@@ -553,6 +569,8 @@ void l1s_fbsb_req(uint8_t base_fn, struct l1ctl_fbsb_req *req)
fbs.initial_freq_err = 0;
fbs.fb_retries = 0;
fbs.afc_retries = 0;
+ fbsb_seq = 0;
+ fbsb_last_fn = 0;
/* Make sure we start at a 'center' AFCDAC output value */
afc_reset();
diff --git a/src/target/firmware/layer1/prim_sniff.c b/src/target/firmware/layer1/prim_sniff.c
new file mode 100644
index 00000000..37dcd32a
--- /dev/null
+++ b/src/target/firmware/layer1/prim_sniff.c
@@ -0,0 +1,279 @@
+/* Layer 1 - Sniffing Bursts */
+
+/* (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
+ *
+ * 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.
+ *
+ */
+
+// #define DEBUG
+#undef DEBUG /* Very bw hungry */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <defines.h>
+#include <byteorder.h>
+
+#include <debug.h>
+
+#include <osmocom/gsm/gsm_utils.h>
+
+#include <calypso/dsp.h>
+#include <layer1/agc.h>
+#include <layer1/l23_api.h>
+#include <layer1/rfch.h>
+#include <layer1/sync.h>
+#include <layer1/tdma_sched.h>
+#include <layer1/tpu_window.h>
+
+
+/* ------------------------------------------------------------------------ */
+/* Sniff TASK API */
+/* ------------------------------------------------------------------------ */
+
+#define SNIFF_DSP_TASK 23
+
+#define BASE_API_RAM 0xffd00000
+#define BASE_SNIFF_API_RAM (BASE_API_RAM + (0x2000 - 0x800) * sizeof(uint16_t))
+
+struct sniff_burst {
+ uint16_t toa;
+ uint16_t pm;
+ uint16_t angle;
+ uint16_t snr;
+ uint16_t dummy_ind;
+ uint16_t bits[29];
+};
+
+struct sniff_db {
+ uint16_t w_nb;
+ uint16_t r_nb;
+ struct sniff_burst bursts[4];
+};
+
+struct sniff_api {
+ struct sniff_db db[2];
+ uint16_t db_ptr;
+ uint16_t burst_ptr;
+};
+
+static inline struct sniff_db *
+sniff_get_page(int r_wn /* 0=W, 1=R */)
+{
+ struct sniff_api *sapi = (void*)BASE_SNIFF_API_RAM;
+ int idx = r_wn ? dsp_api.r_page : dsp_api.w_page;
+ return &sapi->db[idx];
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Local state */
+/* ------------------------------------------------------------------------ */
+
+struct sniff_local_db {
+ uint32_t fn;
+ uint8_t w_nb;
+ uint8_t r_nb;
+};
+
+static struct sniff_local_db _ldbs[2];
+
+static inline struct sniff_local_db *
+sniff_get_local_page(int r_wn /* 0=W, 1=R */)
+{
+ struct sniff_local_db *ldb;
+ int idx = r_wn ? dsp_api.r_page : dsp_api.w_page;
+
+ /* Get page */
+ ldb = &_ldbs[idx];
+
+ /* Clear page if it's not properly in sync */
+ if (!r_wn) {
+ if (ldb->fn != l1s.next_time.fn) {
+ memset(ldb, 0x00, sizeof(struct sniff_local_db));
+ ldb->fn = l1s.next_time.fn;
+ }
+ }
+
+ return ldb;
+}
+
+
+/* ------------------------------------------------------------------------ */
+/* Sniff command & response */
+/* ------------------------------------------------------------------------ */
+
+static int
+l1s_sniff_resp(uint8_t ul, uint8_t burst_id, uint16_t p3)
+{
+ struct sniff_db *sp = sniff_get_page(1);
+ struct sniff_local_db *lsp = sniff_get_local_page(1);
+ struct sniff_api *sapi = (void*)BASE_SNIFF_API_RAM;
+
+ struct msgb *msg;
+ struct l1ctl_burst_ind *bi;
+
+ struct gsm_time rx_time;
+ uint16_t rf_arfcn;
+ uint8_t mf_task_id = p3 & 0xff;
+ uint8_t mf_task_flags = p3 >> 8;
+ uint8_t tn;
+
+ int bidx, i;
+
+ /* Debug */
+ printd("Fn: %d - %d - lsp->w_nb: %d - lsp->r_nb: %d - sp->w_nb: %d - sp->r_nb: %d\n",
+ l1s.current_time.fn-1, ul,
+ sp->w_nb, lsp->r_nb,
+ sp->w_nb, sp->r_nb
+ );
+ printd(" -> %d %04hx %04hx | %04hx %04hx %04hx %04hx %04hx\n",
+ dsp_api.r_page,
+ sapi->db_ptr,
+ sapi->burst_ptr,
+ sp->bursts[bidx].toa,
+ sp->bursts[bidx].pm,
+ sp->bursts[bidx].angle,
+ sp->bursts[bidx].snr,
+ sp->bursts[bidx].dummy_ind
+ );
+
+ for (i=0; i<29; i++)
+ printd("%04hx%c", sp->bursts[bidx].bits[i], i==28?'\n':' ');
+
+ /* Burst index in DSP response */
+ bidx = lsp->r_nb++;
+
+ /* The radio parameters for _this_ burst */
+ gsm_fn2gsmtime(&rx_time, l1s.current_time.fn - 1);
+ rfch_get_params(&rx_time, &rf_arfcn, NULL, &tn);
+
+ /* Create message */
+ msg = l1ctl_msgb_alloc(L1CTL_BURST_IND);
+ if (!msg)
+ goto exit;
+
+ bi = (struct l1ctl_burst_ind *) msgb_put(msg, sizeof(*bi));
+
+ /* Meta data */
+ /* Time */
+ bi->frame_nr = htonl(rx_time.fn);
+
+ /* ARFCN */
+ if (ul)
+ rf_arfcn |= ARFCN_UPLINK;
+ bi->band_arfcn = htons(rf_arfcn);
+
+ /* Set Channel Number depending on MFrame Task ID */
+ bi->chan_nr = mframe_task2chan_nr(mf_task_id, tn);
+
+ /* Set burst id */
+ bi->flags = burst_id;
+
+ /* Set SACCH indication */
+ if (mf_task_flags & MF_F_SACCH)
+ bi->flags |= BI_FLG_SACCH;
+
+ /* Set dummy indication */
+ if (sp->bursts[bidx].dummy_ind)
+ bi->flags |= BI_FLG_DUMMY;
+
+ /* DSP measurements */
+ bi->rx_level = dbm2rxlev(agc_inp_dbm8_by_pm(sp->bursts[bidx].pm >> 3)>>3);
+ bi->snr = (sp->bursts[bidx].snr - 1) >> 6;
+
+ /* Pack bits */
+ memset(bi->bits, 0x00, sizeof(bi->bits));
+
+ for (i=0; i<116; i++)
+ {
+ int sbit = 0x0008 << ((3 - (i & 3)) << 2);
+ int sword = i >> 2;
+ int dbit = 1 << (7 - (i & 7));
+ int dbyte = i >> 3;
+
+ if (sp->bursts[bidx].bits[sword] & sbit)
+ bi->bits[dbyte] |= dbit;
+ }
+
+ /* Send it ! */
+ l1_queue_for_l2(msg);
+
+exit:
+ /* mark READ page as being used */
+ dsp_api.r_page_used = 1;
+
+ return 0;
+}
+
+static int
+l1s_sniff_cmd(uint8_t ul, __unused uint8_t burst_id, __unused uint16_t p3)
+{
+ struct sniff_db *sp = sniff_get_page(0);
+ struct sniff_local_db *lsp = sniff_get_local_page(0);
+ uint16_t arfcn;
+ uint8_t tsc, tn;
+
+ printd("CMD: %d %d %d\n", lsp->w_nb);
+
+ sp->w_nb = ++lsp->w_nb;
+ sp->r_nb = 0;
+
+ rfch_get_params(&l1s.next_time, &arfcn, &tsc, &tn);
+
+ dsp_load_rx_task(SNIFF_DSP_TASK, 0, tsc);
+
+ /* enable dummy bursts detection */
+ dsp_api.db_w->d_ctrl_system |= (1 << B_BCCH_FREQ_IND);
+
+ if (ul) {
+ l1s_rx_win_ctrl(arfcn | ARFCN_UPLINK, L1_RXWIN_NB, 3);
+ } else {
+ l1s_rx_win_ctrl(arfcn, L1_RXWIN_NB, 0);
+ }
+
+ return 0;
+}
+
+const struct tdma_sched_item sniff_xcch_dl_sched_set[] = {
+ SCHED_ITEM_DT(l1s_sniff_cmd, 0, 0, 0), SCHED_END_FRAME(),
+ SCHED_ITEM_DT(l1s_sniff_cmd, 0, 0, 1), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -5, 0, 0), SCHED_ITEM_DT(l1s_sniff_cmd, 0, 0, 2), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -5, 0, 1), SCHED_ITEM_DT(l1s_sniff_cmd, 0, 0, 3), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -5, 0, 2), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -5, 0, 3), SCHED_END_FRAME(),
+ SCHED_END_SET()
+};
+
+const struct tdma_sched_item sniff_xcch_ul_sched_set[] = {
+ SCHED_ITEM_DT(l1s_sniff_cmd, 3, 1, 0), SCHED_END_FRAME(),
+ SCHED_ITEM_DT(l1s_sniff_cmd, 3, 1, 1), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -4, 1, 0), SCHED_ITEM_DT(l1s_sniff_cmd, 3, 1, 2), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -4, 1, 1), SCHED_ITEM_DT(l1s_sniff_cmd, 3, 1, 3), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -4, 1, 2), SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -4, 1, 3), SCHED_END_FRAME(),
+ SCHED_END_SET()
+};
+
+const struct tdma_sched_item sniff_tch_sched_set[] = {
+ SCHED_ITEM_DT(l1s_sniff_cmd, 0, 0, 0), SCHED_ITEM_DT(l1s_sniff_cmd, 3, 1, 0), SCHED_END_FRAME(),
+ SCHED_END_FRAME(),
+ SCHED_ITEM(l1s_sniff_resp, -5, 0, 0), SCHED_ITEM(l1s_sniff_resp, -4, 1, 0), SCHED_END_FRAME(),
+ SCHED_END_SET()
+};
+
diff --git a/src/target_dsp/calypso/Makefile b/src/target_dsp/calypso/Makefile
index 40ee4ec5..266da7aa 100644
--- a/src/target_dsp/calypso/Makefile
+++ b/src/target_dsp/calypso/Makefile
@@ -1,4 +1,4 @@
-all: dsp_dump.bin
+all: dsp_dump.bin dsp_sniff.bin
CROSS=tic54x-coff-
@@ -11,5 +11,8 @@ CROSS=tic54x-coff-
dsp_dump.coff: bl_stage3.o dsp_dump.lds
$(CROSS)ld --script dsp_dump.lds bl_stage3.o -o $@
+dsp_sniff.coff: dsp_sniff.o dsp_patch.lds
+ $(CROSS)ld --script dsp_patch.lds dsp_sniff.o -o $@
+
clean:
rm -f *.o *.bin *.coff
diff --git a/src/target_dsp/calypso/dsp_patch.lds b/src/target_dsp/calypso/dsp_patch.lds
new file mode 100644
index 00000000..0695121d
--- /dev/null
+++ b/src/target_dsp/calypso/dsp_patch.lds
@@ -0,0 +1,25 @@
+OUTPUT_FORMAT("coff1-c54x")
+OUTPUT_ARCH("")
+MEMORY
+{
+ dram (RWXI) : ORIGIN = 0x015C, LENGTH = 0x0600
+ apiram (RWXI) : ORIGIN = 0x2000, LENGTH = 0x1000
+}
+SECTIONS
+{
+ . = 0x015C;
+
+ .text :
+ {
+ *(.text)
+ } > dram
+
+
+ . = 0x2000;
+
+ .apiram :
+ {
+ PROVIDE(_api_ram = .);
+ *(.apiram)
+ } > apiram
+}
diff --git a/src/target_dsp/calypso/dsp_sniff.S b/src/target_dsp/calypso/dsp_sniff.S
new file mode 100644
index 00000000..5a323f29
--- /dev/null
+++ b/src/target_dsp/calypso/dsp_sniff.S
@@ -0,0 +1,175 @@
+; DSP Sniffing task patch
+
+;
+; (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
+;
+; 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.
+;
+
+; ----------------------------------------------------------------------------
+; Known symbols
+; ----------------------------------------------------------------------------
+
+ ; Variables
+patch_install_fptr .equ 0x3F6B ; Patch install function ptr
+dsp_page .equ 0x3FB0 ; Current ndb.d_dsp_page
+task_fn_entry .equ 0x4387 + 23 ; Task 23 index in JT_4387
+
+ ; Functions
+a5_setup .equ 0xB12C
+dma_queue_setup .equ 0xB74C
+
+jt4387_exec .equ 0xA9EA
+
+fq_4320_push .equ 0xAA9F
+fq_4330_push .equ 0xAA6C
+fq_4340_push .equ 0xAAC3
+
+
+; ----------------------------------------------------------------------------
+; Our double buffer API
+; ----------------------------------------------------------------------------
+
+ .section .apiram
+
+sniff_db0 .ds 138
+sniff_db1 .ds 138
+sniff_db_ptr .ds 1
+sniff_burst_ptr .ds 1
+
+
+; ----------------------------------------------------------------------------
+; The code itself
+; ----------------------------------------------------------------------------
+
+ .text
+
+;
+; Patch init
+;
+; Called during DSP boot (around the middle)
+;
+patch_init:
+ st #patch_install, *(patch_install_fptr)
+ ret
+
+;
+; Patch install
+;
+; Called after DSP init. That's were the overriding of all the
+; jump tables should be done.
+;
+patch_install:
+ st #sniff_task, *(task_fn_entry)
+ ret
+
+;
+; New sniff task
+;
+; Called by the dispatch code when the value 23 is found in d_task_d
+;
+sniff_task:
+ ; Setup our double buffer zone ptr
+ stm #sniff_db0, AR1
+ bitf *(dsp_page), #1
+ bc 1f, ntc
+ stm #sniff_db1, AR1
+1:
+
+ mvmd AR1, @sniff_db_ptr
+
+ ; Prepare the burst_ptr and burst_counter
+ ; sniff_db_ptr->r_nb = 0
+ st #0, *+AR1
+
+ ; sniff_burst_ptr = sniff_db_ptr + 2;
+ mar *AR1+
+ mvmd AR1, @sniff_burst_ptr
+
+ ; Queue A5 setup in FQ4340
+ ; (needed to make sure the a5 bits are zeroed)
+ ld #a5_setup, 0, A
+ call fq_4340_push
+
+ ; Prepare bursts reception
+ ; (we queue as many many as bursts to RX)
+1:
+ ; Decrement & Check counter
+ mvdm @sniff_db_ptr, AR1
+ nop ; (pipeline conflict)
+ nop ; (pipeline conflict)
+
+ ldu *AR1, A
+ bc 2f, aeq
+ sub #1, A
+ stl A, *AR1
+
+ ; Queue the DMA
+ call dma_queue_setup
+
+ ; Queue Burst handler in FQ4320
+ ld #burst_handler, 0, A
+ call fq_4320_push
+
+ ; Loop
+ b 1b
+2:
+
+ ; Done
+ ret
+
+;
+; Burst data handler
+;
+; Called once the DMA transfer is done and the IQ bits are received.
+; Most maintenance tasks (like cleanup after DMA and inth stuff) are
+; done for us. Only real work goes here.
+;
+burst_handler:
+ ; NB demodulation
+ ld #0x34, A
+ call jt4387_exec
+
+ ; Base burst storage address
+ mvdm @sniff_burst_ptr, AR3
+ nop ; (pipeline conflict)
+ nop ; (pipeline conflict)
+
+ ; Copy "metadata"
+ mvkd @0x3FA4, *AR3+ ; D_TOA
+ mvkd @0x3FA5, *AR3+ ; D_PM
+ mvkd @0x3FA7, *AR3+ ; D_ANGLE
+ mvkd @0x3FA6, *AR3+ ; D_SNR
+ mvkd @0x0CCE, *AR3+ ; dummy burst indicator
+
+ ; Copy the softbits
+ stm #0x0CCF, AR2 ; src
+ stm #28, AR1 ; size-1 (29 words = 116 bits)
+ rpt *(AR1)
+ mvdd *AR2+, *AR3+
+
+ ; Store the new pointer
+ mvmd AR3, @sniff_burst_ptr
+
+ ; Increment received bursts count
+ mvdm @sniff_db_ptr, AR1
+ nop ; (pipeline conflict)
+ nop ; (pipeline conflict)
+ addm #1, *AR1(1)
+
+ ; Done
+ ret