summaryrefslogtreecommitdiffstats
path: root/src/host/layer23/src/misc
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2010-09-12 15:19:59 +0200
committerSylvain Munaut <tnt@246tNt.com>2010-09-14 21:21:42 +0200
commita268e3ce059d28d61a81915d3dfca6675ae3a219 (patch)
tree9926848a3c6a371999740380bb508a428f86efb8 /src/host/layer23/src/misc
parent02c4650af1dc8e99c3c1e565724072485d61c4b4 (diff)
layer23: Add support for SI1 decoding and imm.ass hopping
The gsm48_decode_freq_list should ideally become something shared between this app and mobile but it has incompatibilities for now ... need to sort that out with Andreas to unify in the future. Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'src/host/layer23/src/misc')
-rw-r--r--src/host/layer23/src/misc/layer3.c98
1 files changed, 79 insertions, 19 deletions
diff --git a/src/host/layer23/src/misc/layer3.c b/src/host/layer23/src/misc/layer3.c
index 3ba47344..74d48eb3 100644
--- a/src/host/layer23/src/misc/layer3.c
+++ b/src/host/layer23/src/misc/layer3.c
@@ -5,6 +5,7 @@
#include <osmocore/msgb.h>
#include <osmocore/rsl.h>
#include <osmocore/tlv.h>
+#include <osmocore/gsm48_ie.h>
#include <osmocore/protocol/gsm_04_08.h>
#include <osmocom/bb/common/logging.h>
@@ -15,9 +16,11 @@
#include <osmocom/bb/common/l1ctl.h>
static struct {
+ int has_si1;
int ccch_mode;
int ccch_enabled;
int rach_count;
+ struct gsm_sysinfo_freq cell_arfcns[1024];
} app_state;
@@ -34,6 +37,17 @@ static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
if (tc != 0)
fprintf(stderr, " on wrong TC");
#endif
+ if (!app_state.has_si1) {
+ struct gsm48_system_information_type_1 *si1 =
+ (struct gsm48_system_information_type_1 *)data;
+
+ gsm48_decode_freq_list(&app_state.cell_arfcns,
+ si1->cell_channel_description,
+ sizeof(si1->cell_channel_description),
+ 0xff, 0x01);
+
+ app_state.has_si1 = 1;
+ }
break;
case GSM48_MT_RR_SYSINFO_2:
fprintf(stderr, "\tSI2");
@@ -172,35 +186,78 @@ 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;
- uint16_t arfcn;
+ int rv;
+
+ /* Discard packet TBF assignement */
+ if (ia->page_mode & 0xf0)
+ return 0;
+
+ /* FIXME: compare RA and GSM time with when we sent RACH req */
rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
- arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
- 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);
+ if (!ia->chan_desc.h0.h) {
+ /* Non-hopping */
+ uint16_t arfcn;
- /* FIXME: compare RA and GSM time with when we sent RACH req */
+ arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
- /* check if we can support this type of channel at the moment */
- if (ch_type != RSL_CHAN_SDCCH4_ACCH || ch_ts != 0 ||
- ia->chan_desc.h0.h == 1) {
- DEBUGPC(DRR, "UNSUPPORTED!\n");
- return 0;
- }
+ 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);
+
+ if (ch_ts >= 4 || ch_subch >= 4) {
+ DEBUGPC(DRR, "UNSUPPORTED!\n");
+ return 0;
+ }
+
+ /* 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);
+ } 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);
- /* request L1 to go to dedicated mode on assigned channel */
- l1ctl_tx_dm_est_req_h0(ms, arfcn, ia->chan_desc.chan_nr,
- ia->chan_desc.h0.tsc);
+ 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);
- /* request L2 to establish the SAPI0 connection */
- gsm48_tx_loc_upd_req(ms, ia->chan_desc.chan_nr);
+ /* 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 (ch_ts >= 4 || ch_subch >= 4) {
+ DEBUGPC(DRR, "UNSUPPORTED!\n");
+ return 0;
+ }
+
+ /* 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);
+ }
DEBUGPC(DRR, "\n");
- return 0;
+ rv = gsm48_tx_loc_upd_req(ms, ia->chan_desc.chan_nr);
+
+ return rv;
}
int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms)
@@ -249,8 +306,11 @@ int gsm48_rx_bcch(struct msgb *msg, struct osmocom_ms *ms)
void layer3_app_reset(void)
{
/* Reset state */
+ app_state.has_si1 = 0;
app_state.ccch_mode = CCCH_MODE_NONE;
app_state.ccch_enabled = 0;
app_state.rach_count = 0;
+
+ memset(&app_state.cell_arfcns, 0x00, sizeof(app_state.cell_arfcns));
}