summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas.Eversberg2010-05-06 10:48:24 +0200
committerAndreas.Eversberg2010-05-06 10:48:24 +0200
commit2b7d2ed446c9252d6dd7c6a834adb9eb40db1880 (patch)
tree4174018304667fbb1abad3e8fd50b9f581a853e1 /src
parentWork on layer 3 processes: (diff)
downloadosmocom-2b7d2ed446c9252d6dd7c6a834adb9eb40db1880.tar.gz
osmocom-2b7d2ed446c9252d6dd7c6a834adb9eb40db1880.tar.xz
osmocom-2b7d2ed446c9252d6dd7c6a834adb9eb40db1880.zip
- Fixes on MM, RR, cell selection, plmn search processes.
-> Cell selection now requires only one frequency to be scanned, if BA list of that PLMN is known.
Diffstat (limited to 'src')
-rw-r--r--src/host/gsm48-andreas/issues.txt5
-rwxr-xr-xsrc/host/layer23/include/osmocom/gsm322.h5
-rw-r--r--src/host/layer23/include/osmocom/gsm48_rr.h3
-rw-r--r--src/host/layer23/include/osmocom/support.h1
-rwxr-xr-xsrc/host/layer23/src/gsm322.c171
-rw-r--r--src/host/layer23/src/gsm48_mm.c5
-rw-r--r--src/host/layer23/src/gsm48_rr.c250
-rw-r--r--src/host/layer23/src/support.c5
8 files changed, 295 insertions, 150 deletions
diff --git a/src/host/gsm48-andreas/issues.txt b/src/host/gsm48-andreas/issues.txt
index 01ef1c7..ba7bb82 100644
--- a/src/host/gsm48-andreas/issues.txt
+++ b/src/host/gsm48-andreas/issues.txt
@@ -88,6 +88,11 @@ Send request again, if timer expires.
We MUST at least have CRCxx on serial interface.
+power measurements sometimes does not return all measurements. it stops,
+especially if a ccch was requested before. this is not good. power measurement
+must stop all other layer 1 processes!
+
+
diff --git a/src/host/layer23/include/osmocom/gsm322.h b/src/host/layer23/include/osmocom/gsm322.h
index 0159972..9dd96c6 100755
--- a/src/host/layer23/include/osmocom/gsm322.h
+++ b/src/host/layer23/include/osmocom/gsm322.h
@@ -132,6 +132,7 @@ struct gsm322_cellsel {
int state; /* GSM322_Cx_* */
uint16_t arfcn; /* current tuned idle mode arfcn */
+// uint8_t tune_retry;
struct gsm48_sysinfo *si; /* current sysinfo */
struct llist_head event_queue; /* event messages */
@@ -144,12 +145,12 @@ struct gsm322_cellsel {
uint8_t powerscan; /* currently scanning for power */
uint32_t scan_state; /* special state of current scan */
- uint8_t ccch_active; /* set, if ccch is active */
+ uint8_t ccch_sync; /* set, if ccch is synced */
uint8_t selected; /* if a cell is selected */
uint16_t sel_arfcn;
struct gsm48_sysinfo sel_si; /* copy of selected cell, will update */
- uint16_t sel_mcc, sel_mnc, sel_lac;
+ uint16_t sel_mcc, sel_mnc, sel_lac, sel_id;
};
/* GSM 03.22 message */
diff --git a/src/host/layer23/include/osmocom/gsm48_rr.h b/src/host/layer23/include/osmocom/gsm48_rr.h
index ba0bb25..88f44f1 100644
--- a/src/host/layer23/include/osmocom/gsm48_rr.h
+++ b/src/host/layer23/include/osmocom/gsm48_rr.h
@@ -3,6 +3,8 @@
#include "osmocore/protocol/gsm_04_08.h"
+#define GSM_TA_CM 55385
+
/* GSM 04.07 9.1.2 */
#define GSM48_RR_EST_REQ 0x10
#define GSM48_RR_EST_IND 0x12
@@ -141,5 +143,6 @@ struct msgb *gsm48_rr_msgb_alloc(int msg_type);
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
uint16_t *mnc, uint16_t *lac);
int gsm48_rr_enc_cm2(struct osmocom_ms *ms, struct gsm48_classmark2 *cm);
+int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg);
#endif /* _GSM48_RR_H */
diff --git a/src/host/layer23/include/osmocom/support.h b/src/host/layer23/include/osmocom/support.h
index 1a96c14..7b8f7cd 100644
--- a/src/host/layer23/include/osmocom/support.h
+++ b/src/host/layer23/include/osmocom/support.h
@@ -76,6 +76,7 @@ struct gsm_support {
/* radio */
int8_t min_rxlev_db;
uint8_t scan_to;
+ uint8_t sync_to;
};
struct gsm_support_scan_max {
diff --git a/src/host/layer23/src/gsm322.c b/src/host/layer23/src/gsm322.c
index 2a9f3bd..909e30e 100755
--- a/src/host/layer23/src/gsm322.c
+++ b/src/host/layer23/src/gsm322.c
@@ -44,6 +44,9 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any);
static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg);
+//#define SINGLE
+
+#ifdef SINGLE
#warning HACK to stay on one channel
static int already = 0;
int l1ctl_tx_ccch_req_(struct osmocom_ms *ms, uint16_t arfcn)
@@ -53,9 +56,12 @@ int l1ctl_tx_ccch_req_(struct osmocom_ms *ms, uint16_t arfcn)
already = 1;
return l1ctl_tx_ccch_req(ms, arfcn);
}
- ms->cellsel.ccch_active = 1;
+ ms->cellsel.ccch_sync = 1;
return 0;
}
+#else
+#define l1ctl_tx_ccch_req_ l1ctl_tx_ccch_req
+#endif
/*
* notes
@@ -987,6 +993,7 @@ static int gsm322_a_loss_of_radio(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_plmn *plmn = &ms->plmn;
struct gsm322_cellsel *cs = &ms->cellsel;
int found;
+ struct msgb *nmsg;
/* any PLMN available */
found = gsm322_cs_select(ms, 0);
@@ -1008,6 +1015,12 @@ static int gsm322_a_loss_of_radio(struct osmocom_ms *ms, struct msgb *msg)
new_a_state(plmn, GSM322_A4_WAIT_FOR_PLMN);
+ /* Tell cell selection process to handle "no cell found". */
+ nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_cs_sendmsg(ms, nmsg);
+
return 0;
}
@@ -1523,7 +1536,7 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
gsm322_plmn_sendmsg(ms, nmsg);
/* re-tune back to current VPLMN */
- cs->ccch_active = 0;
+ cs->ccch_sync = 0;
l1ctl_tx_ccch_req_(ms, cs->arfcn);
return 0;
@@ -1532,6 +1545,7 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
/* if all frequencies have been searched */
if (!weight) {
struct msgb *nmsg;
+#if 0
int found, any = 0;
LOGP(DCS, LOGL_INFO, "All frequencies scanned.\n");
@@ -1552,7 +1566,7 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
/* tune */
cs->arfcn = found;
cs->si = cs->list[cs->arfcn].sysinfo;
- cs->ccch_active = 0;
+ cs->ccch_sync = 0;
l1ctl_tx_ccch_req_(ms, cs->arfcn);
/* selected PLMN (manual) or any PLMN (auto) */
@@ -1588,20 +1602,23 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
cs->sel_mcc = cs->si->mcc;
cs->sel_mnc = cs->si->mnc;
cs->sel_lac = cs->si->lac;
+ cs->sel_id = cs->si->cell_id;
/* tell CS process about available cell */
- nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_FOUND);
LOGP(DCS, LOGL_INFO, "Cell available.\n");
+ nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_FOUND);
} else {
+#endif
/* unset selected cell */
cs->selected = 0;
memset(&cs->sel_si, 0, sizeof(cs->sel_si));
- cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0;
+ cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id
+ = 0;
/* tell CS process about no cell available */
- nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND);
LOGP(DCS, LOGL_INFO, "No cell available.\n");
- }
+ nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND);
+// }
if (!nmsg)
return -ENOMEM;
gsm322_c_event(ms, nmsg);
@@ -1616,9 +1633,12 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
/* Tune to frequency for a while, to receive broadcasts. */
cs->arfcn = weight & 1023;
- LOGP(DCS, LOGL_INFO, "Scanning frequency %d.\n", cs->arfcn);
- cs->ccch_active = 0;
+ LOGP(DCS, LOGL_INFO, "Scanning frequency %d (rxlev %d).\n", cs->arfcn,
+ cs->list[cs->arfcn].rxlev_db);
+ cs->ccch_sync = 0;
l1ctl_tx_ccch_req_(ms, cs->arfcn);
+// cs->tune_retry = 0;
+ start_cs_timer(cs, ms->support.sync_to, 0);
/* Allocate/clean system information. */
if (cs->list[cs->arfcn].sysinfo)
@@ -1643,6 +1663,9 @@ static int gsm322_cs_store(struct osmocom_ms *ms)
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm48_sysinfo *s = cs->si;
+ struct gsm322_plmn *plmn = &ms->plmn;
+ struct msgb *nmsg;
+ int found, any = 0;
if (cs->state != GSM322_C2_STORED_CELL_SEL
&& cs->state != GSM322_C1_NORMAL_CELL_SEL
@@ -1691,8 +1714,6 @@ static int gsm322_cs_store(struct osmocom_ms *ms)
/* special prositive case for HPLMN search */
if (cs->state == GSM322_HPLMN_SEARCH && s->mcc == subscr->mcc
&& s->mnc == subscr->mnc) {
- struct msgb *nmsg;
-
nmsg = gsm322_msgb_alloc(GSM322_EVENT_HPLMN_FOUND);
LOGP(DCS, LOGL_INFO, "HPLMN cell available.\n");
if (!nmsg)
@@ -1702,8 +1723,72 @@ static int gsm322_cs_store(struct osmocom_ms *ms)
return 0;
}
- /* tune to next cell */
- return gsm322_cs_scan(ms);
+ /* just see, if we search for any cell */
+ if (cs->state == GSM322_C6_ANY_CELL_SEL
+ || cs->state == GSM322_C8_ANY_CELL_RESEL
+ || cs->state == GSM322_C9_CHOOSE_ANY_CELL)
+ any = 1;
+
+ found = gsm322_cs_select(ms, any);
+
+ /* if not found */
+ if (found < 0) {
+ LOGP(DCS, LOGL_INFO, "Cell not suitable and allowable.\n");
+ /* tune to next cell */
+ return gsm322_cs_scan(ms);
+ }
+
+ LOGP(DCS, LOGL_INFO, "Tune to frequency %d.\n", found);
+ /* tune */
+ cs->arfcn = found;
+ cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->ccch_sync = 0;
+ l1ctl_tx_ccch_req_(ms, cs->arfcn);
+
+ /* selected PLMN (manual) or any PLMN (auto) */
+ switch (plmn->mode) {
+ case PLMN_MODE_AUTO:
+ if (plmn->state == GSM322_A4_WAIT_FOR_PLMN) {
+ /* PLMN becomes available */
+ nmsg = gsm322_msgb_alloc(
+ GSM322_EVENT_PLMN_AVAIL);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_plmn_sendmsg(ms, nmsg);
+ }
+ break;
+ case PLMN_MODE_MANUAL:
+ if (plmn->state == GSM322_M3_NOT_ON_PLMN
+ && gsm322_is_plmn_avail(cs, plmn->mcc,
+ plmn->mnc)) {
+ /* PLMN becomes available */
+ nmsg = gsm322_msgb_alloc(
+ GSM322_EVENT_PLMN_AVAIL);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_plmn_sendmsg(ms, nmsg);
+ }
+ break;
+ }
+
+ /* set selected cell */
+ cs->selected = 1;
+ cs->sel_arfcn = cs->arfcn;
+ memcpy(&cs->sel_si, cs->si, sizeof(cs->sel_si));
+ cs->sel_mcc = cs->si->mcc;
+ cs->sel_mnc = cs->si->mnc;
+ cs->sel_lac = cs->si->lac;
+ cs->sel_id = cs->si->cell_id;
+
+ /* tell CS process about available cell */
+ LOGP(DCS, LOGL_INFO, "Cell available.\n");
+ nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_FOUND);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_c_event(ms, nmsg);
+ msgb_free(nmsg);
+
+ return 0;
}
/* process system information when returing to idle mode */
@@ -1789,12 +1874,18 @@ static int gsm322_store_ba_list(struct gsm322_cellsel *cs,
/* process system information during camping on a cell */
static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s = cs->si;
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm322_msg *gm = (struct gsm322_msg *) msg->data;
struct msgb *nmsg;
+ if (rr->state != GSM48_RR_ST_IDLE) {
+ LOGP(DCS, LOGL_INFO, "Ignoring in dedicated mode.\n");
+ return -EBUSY;
+ }
+
/* Store BA if we have full system info about cells and neigbor cells.
* Depending on the extended bit in the channel description,
* we require more or less system informations about neighbor cells
@@ -1861,13 +1952,18 @@ static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
}
}
- /* check if MCC, MNC, LAC changes */
+ /* check if MCC, MNC, LAC, cell ID changes */
if (cs->sel_mcc != s->mcc || cs->sel_mnc != s->mnc
|| cs->sel_lac != s->lac) {
LOGP(DCS, LOGL_NOTICE, "Cell changes location area. "
"This is not good!\n");
goto trigger_resel;
}
+ if (cs->sel_id != s->cell_id) {
+ LOGP(DCS, LOGL_NOTICE, "Cell changes cell ID. "
+ "This is not good!\n");
+ goto trigger_resel;
+ }
return 0;
}
@@ -1929,6 +2025,23 @@ static void gsm322_cs_timeout(void *arg)
struct osmocom_ms *ms = cs->ms;
LOGP(DCS, LOGL_INFO, "Cell selection timer has fired.\n");
+
+ /* if we have no lock, we retry */
+ if (!cs->ccch_sync) {
+#if 0
+ if (++cs->tune_retry < 4) {
+ LOGP(DCS, LOGL_INFO, "No lock, retrying frequency %d.\n", cs->arfcn);
+ start_cs_timer(cs, ms->support.sync_to, 0);
+ l1ctl_tx_ccch_req_(ms, cs->arfcn);
+ return;
+ }
+ LOGP(DCS, LOGL_INFO, "No lock, after trying %d times.\n", cs->tune_retry);
+#else
+ LOGP(DCS, LOGL_INFO, "Sync timeout.\n");
+#endif
+ } else
+ LOGP(DCS, LOGL_INFO, "Read timeout.\n");
+
LOGP(DCS, LOGL_INFO, "Scan frequency %d: Cell not found. (rxlev=%d)\n",
cs->arfcn, cs->list[cs->arfcn].rxlev_db);
@@ -1950,7 +2063,7 @@ static void gsm322_cs_timeout(void *arg)
* power scan process
*/
-/* search for block of unscanned freqeuncies and start scanning */
+/* search for block of unscanned frequencies and start scanning */
static int gsm322_cs_powerscan(struct osmocom_ms *ms)
{
struct gsm322_cellsel *cs = &ms->cellsel;
@@ -1975,8 +2088,10 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
}
}
+#ifdef SINGLE
#warning testing
if (already) s = -1;
+#endif
#if 0
cs->list[ms->test_arfcn].rxlev_db = -50;
cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER;
@@ -2049,7 +2164,7 @@ s = -1;
break;
}
- LOGP(DCS, LOGL_INFO, "Scanning frequecies. (%d..%d)\n", s, e);
+ LOGP(DCS, LOGL_INFO, "Scanning frequencies. (%d..%d)\n", s, e);
/* start scan on radio interface */
cs->powerscan = 1;
@@ -2096,9 +2211,15 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
case S_L1CTL_CCCH_RESP:
ms = signal_data;
cs = &ms->cellsel;
- if (!cs->ccch_active) {
+ if (!cs->ccch_sync) {
LOGP(DCS, LOGL_INFO, "Channel activated.\n");
- cs->ccch_active = 1;
+ stop_cs_timer(cs);
+ cs->ccch_sync = 1;
+
+ /* in dedicated mode */
+ if (ms->rrlayer.state == GSM48_RR_ST_CONN_PEND)
+ return gsm48_rr_tx_rand_acc(ms, NULL);
+
/* set timer for reading BCCH */
if (cs->state == GSM322_C2_STORED_CELL_SEL
|| cs->state == GSM322_C1_NORMAL_CELL_SEL
@@ -2147,7 +2268,7 @@ static int gsm322_c_hplmn_search(struct osmocom_ms *ms, struct msgb *msg)
/* unset selected cell */
cs->selected = 0;
memset(&cs->sel_si, 0, sizeof(cs->sel_si));
- cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0;
+ cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0;
/* start power scan */
return gsm322_cs_powerscan(ms);
@@ -2172,7 +2293,7 @@ static int gsm322_c_stored_cell_sel(struct osmocom_ms *ms, struct gsm322_ba_list
/* unset selected cell */
cs->selected = 0;
memset(&cs->sel_si, 0, sizeof(cs->sel_si));
- cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0;
+ cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0;
/* start power scan */
return gsm322_cs_powerscan(ms);
@@ -2204,7 +2325,7 @@ static int gsm322_c_normal_cell_sel(struct osmocom_ms *ms, struct msgb *msg)
/* unset selected cell */
cs->selected = 0;
memset(&cs->sel_si, 0, sizeof(cs->sel_si));
- cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0;
+ cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0;
/* start power scan */
return gsm322_cs_powerscan(ms);
@@ -2246,7 +2367,7 @@ static int gsm322_c_any_cell_sel(struct osmocom_ms *ms, struct msgb *msg)
/* unset selected cell */
cs->selected = 0;
memset(&cs->sel_si, 0, sizeof(cs->sel_si));
- cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0;
+ cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0;
/* start power scan */
return gsm322_cs_powerscan(ms);
@@ -2366,7 +2487,7 @@ if we return from dedicated mode and we have a ba range, we can use that for cel
/* unset selected cell */
cs->selected = 0;
memset(&cs->sel_si, 0, sizeof(cs->sel_si));
- cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0;
+ cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0;
/* start power scan */
return gsm322_cs_powerscan(ms);
@@ -2460,7 +2581,7 @@ static int gsm322_c_conn_mode_1(struct osmocom_ms *ms, struct msgb *msg)
/* be sure to go to current camping frequency on return */
LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn);
- cs->ccch_active = 0;
+ cs->ccch_sync = 0;
l1ctl_tx_ccch_req_(ms, cs->arfcn);
cs->si = cs->list[cs->arfcn].sysinfo;
@@ -2478,7 +2599,7 @@ static int gsm322_c_conn_mode_2(struct osmocom_ms *ms, struct msgb *msg)
/* be sure to go to current camping frequency on return */
LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn);
- cs->ccch_active = 0;
+ cs->ccch_sync = 0;
l1ctl_tx_ccch_req_(ms, cs->arfcn);
cs->si = cs->list[cs->arfcn].sysinfo;
diff --git a/src/host/layer23/src/gsm48_mm.c b/src/host/layer23/src/gsm48_mm.c
index 2c3803c..1ab766c 100644
--- a/src/host/layer23/src/gsm48_mm.c
+++ b/src/host/layer23/src/gsm48_mm.c
@@ -2443,7 +2443,7 @@ static int gsm48_mm_rel_loc_upd_abort(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
- /* RA was successfull */
+ /* RA was successfull or sent twice */
mm->lupd_ra_failure = 0;
/* continue with failure handling */
@@ -3698,6 +3698,9 @@ static struct eventstate {
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_ignore},
{ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
GSM48_MM_EVENT_TIMEOUT_T3210, gsm48_mm_loc_upd_timeout},
+ {ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
+ GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd_failed},
+ /* 4.4.4.9 c) (but without retry) */
/* SYSINFO event */
{ALL_STATES, ALL_STATES,
GSM48_MM_EVENT_SYSINFO, gsm48_mm_sysinfo},
diff --git a/src/host/layer23/src/gsm48_rr.c b/src/host/layer23/src/gsm48_rr.c
index 360ae5f..5571a78 100644
--- a/src/host/layer23/src/gsm48_rr.c
+++ b/src/host/layer23/src/gsm48_rr.c
@@ -150,6 +150,11 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
(sizeof(gsm48_rr_state_names) / sizeof(char *)))
return;
+ LOGP(DRR, LOGL_INFO, "new state %s -> %s\n",
+ gsm48_rr_state_names[rr->state], gsm48_rr_state_names[state]);
+
+ rr->state = state;
+
if (state == GSM48_RR_ST_IDLE) {
struct msgb *msg, *nmsg;
@@ -179,11 +184,6 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
gsm322_c_event(rr->ms, nmsg);
msgb_free(nmsg);
}
-
- LOGP(DRR, LOGL_INFO, "new state %s -> %s\n",
- gsm48_rr_state_names[rr->state], gsm48_rr_state_names[state]);
-
- rr->state = state;
}
/*
@@ -694,6 +694,7 @@ static int gsm48_rr_rx_cm_enq(struct osmocom_ms *ms, struct msgb *msg)
*/
/* temporary timer until we have time control over channnel request */
+/* TODO: turn this into a channel activation timeout, later */
#define RSL_MT_CHAN_CNF 0x19
#include <osmocom/l1ctl.h>
static void temp_rach_to(void *arg)
@@ -710,18 +711,16 @@ static void temp_rach_to(void *arg)
return;
}
-/* send channel request burst message */
-static int gsm48_rr_tx_chan_req(struct osmocom_ms *ms, int cause, int paging)
+/* start random access */
+static int gsm48_rr_chan_req(struct osmocom_ms *ms, int cause, int paging)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s = cs->si;
struct msgb *nmsg;
- struct l1ctl_info_ul *nul;
- struct l1ctl_rach_req *nra;
struct gsm48_rr_hdr *nrrh;
- uint8_t chan_req, chan_req_val, chan_req_mask;
- int t, rc;
+ uint8_t chan_req_val, chan_req_mask;
+ int rc;
/* ignore paging, if not camping */
if (paging
@@ -750,8 +749,8 @@ static int gsm48_rr_tx_chan_req(struct osmocom_ms *ms, int cause, int paging)
/* 3.3.1.1.2 */
new_rr_state(rr, GSM48_RR_ST_CONN_PEND);
- /* number of retransmissions (without first transmission) */
- rr->n_chan_req = s->max_retrans;
+ /* number of retransmissions (with first transmission) */
+ rr->n_chan_req = s->max_retrans + 1;
/* generate CHAN REQ (9.1.8) */
switch (cause) {
@@ -873,64 +872,30 @@ static int gsm48_rr_tx_chan_req(struct osmocom_ms *ms, int cause, int paging)
return -EINVAL;
}
- rr->wait_assign = 1;
-
- /* create and send RACH msg */
-#ifdef TODO
- nmsg = gsm48_rsl_msgb_alloc();
-#else
- nmsg = msgb_alloc_headroom(64, 48, "RAND_ACC");
- struct l1ctl_hdr *l1h;
- nmsg->l1h = msgb_put(nmsg, sizeof(*l1h));
- l1h = (struct l1ctl_hdr *) nmsg->l1h;
- l1h->msg_type = L1CTL_RACH_REQ;
- if (!nmsg)
- return -ENOMEM;
- nul = (struct l1ctl_info_ul *) msgb_put(nmsg, sizeof(*nul));
-#endif
- nra = (struct l1ctl_rach_req *) msgb_put(nmsg, sizeof(*nra));
-
- chan_req = random();
- chan_req &= chan_req_mask;
- chan_req |= chan_req_val;
- nra->ra = chan_req;
- t = s->tx_integer;
- if (t < 8)
- t = 8;
-#ifdef TODO
- at this point we require chan req to be sent at a given delay
- also we require a confirm from radio part
- nra->delay = random() % t;
-
- LOGP(DRR, LOGL_INFO, "RANDOM ACCESS (ra 0x%02x delay %d)\n", nra->ra,
- nra->delay);
-#else
+// TODO: turn this into the channel activation timer
rr->temp_rach_ti.cb = temp_rach_to;
rr->temp_rach_ti.data = rr;
- bsc_schedule_timer(&rr->temp_rach_ti, 0, 900000);
+ bsc_schedule_timer(&rr->temp_rach_ti, ms->support.sync_to, 0);
- LOGP(DRR, LOGL_INFO, "RANDOM ACCESS (ra 0x%02x)\n", nra->ra);
-#endif
-
- /* store */
+ /* store value, mask and history */
rr->chan_req_val = chan_req_val;
rr->chan_req_mask = chan_req_mask;
rr->cr_hist[2] = -1;
rr->cr_hist[1] = -1;
- rr->cr_hist[0] = chan_req;
+ rr->cr_hist[0] = -1;
-#ifdef TODO
- add layer 1 conrols to RSL...
- return gsm48_send_rsl(ms, RSL_MT_CHAN_REQ, nmsg);
-#else
- return osmo_send_l1(ms, nmsg);
-#endif
+ /* if channel is already active somehow */
+ if (cs->ccch_sync)
+ return gsm48_rr_tx_rand_acc(ms, NULL);
+
+ return 0;
}
-/* send next channel request in conn pend state */
-static int gsm48_rr_rand_acc_cnf(struct osmocom_ms *ms, struct msgb *msg)
+/* send first/next channel request in conn pend state */
+int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s = ms->cellsel.si;
struct msgb *nmsg;
struct l1ctl_info_ul *nul;
@@ -938,6 +903,31 @@ static int gsm48_rr_rand_acc_cnf(struct osmocom_ms *ms, struct msgb *msg)
int slots;
uint8_t chan_req;
+ if (!cs->ccch_sync) {
+ LOGP(DRR, LOGL_INFO, "CCCH channel activation failed.\n");
+
+ if (rr->rr_est_req) {
+ struct msgb *msg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
+ struct gsm48_rr_hdr *rrh;
+
+ if (!msg)
+ return -ENOMEM;
+ rrh = (struct gsm48_rr_hdr *)msg->data;
+ rrh->cause = RR_REL_CAUSE_RA_FAILURE;
+ gsm48_rr_upmsg(ms, msg);
+ }
+
+ new_rr_state(rr, GSM48_RR_ST_IDLE);
+
+ return 0;
+ }
+
+ if (rr->state == GSM48_RR_ST_IDLE) {
+ LOGP(DRR, LOGL_INFO, "MM already released RR.\n");
+
+ return 0;
+ }
+
LOGP(DRR, LOGL_INFO, "RANDOM ACCESS confirm (requests left %d)\n",
rr->n_chan_req);
@@ -950,33 +940,39 @@ static int gsm48_rr_rand_acc_cnf(struct osmocom_ms *ms, struct msgb *msg)
}
rr->n_chan_req--;
- /* table 3.1 */
- switch(s->tx_integer) {
- case 3: case 8: case 14: case 50:
- if (s->ccch_conf != 1) /* not combined CCCH */
- slots = 55;
- else
- slots = 41;
- case 4: case 9: case 16:
- if (s->ccch_conf != 1)
- slots = 76;
- else
- slots = 52;
- case 5: case 10: case 20:
- if (s->ccch_conf != 1)
- slots = 109;
- else
- slots = 58;
- case 6: case 11: case 25:
- if (s->ccch_conf != 1)
- slots = 163;
- else
- slots = 86;
- default:
- if (s->ccch_conf != 1)
- slots = 217;
- else
- slots = 115;
+ if (!rr->wait_assign) {
+ /* first random acces, without delay of slots */
+ slots = 0;
+ rr->wait_assign = 1;
+ } else {
+ /* subsequent random acces, with slots from table 3.1 */
+ switch(s->tx_integer) {
+ case 3: case 8: case 14: case 50:
+ if (s->ccch_conf != 1) /* not combined CCCH */
+ slots = 55;
+ else
+ slots = 41;
+ case 4: case 9: case 16:
+ if (s->ccch_conf != 1)
+ slots = 76;
+ else
+ slots = 52;
+ case 5: case 10: case 20:
+ if (s->ccch_conf != 1)
+ slots = 109;
+ else
+ slots = 58;
+ case 6: case 11: case 25:
+ if (s->ccch_conf != 1)
+ slots = 163;
+ else
+ slots = 86;
+ default:
+ if (s->ccch_conf != 1)
+ slots = 217;
+ else
+ slots = 115;
+ }
}
/* resend chan_req with new randiom */
@@ -1021,6 +1017,7 @@ static int gsm48_rr_rand_acc_cnf(struct osmocom_ms *ms, struct msgb *msg)
add layer 1 conrols to RSL...
return gsm48_send_rsl(ms, RSL_MT_CHAN_REQ, nmsg);
#else
+//#warning disabled!
return osmo_send_l1(ms, nmsg);
#endif
}
@@ -2116,7 +2113,7 @@ static int gsm48_rr_rx_pag_req_1(struct osmocom_ms *ms, struct msgb *msg)
if (payload_len < mi[0] + 1)
goto short_read;
if (gsm_match_mi(ms, mi) > 0)
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
/* second MI */
payload_len -= mi[0] + 1;
mi = pa->data + mi[0] + 1;
@@ -2127,7 +2124,7 @@ static int gsm48_rr_rx_pag_req_1(struct osmocom_ms *ms, struct msgb *msg)
if (payload_len < mi[1] + 2)
goto short_read;
if (gsm_match_mi(ms, mi + 1) > 0)
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
return 0;
}
@@ -2166,7 +2163,7 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
if (ms->subscr.tmsi == ntohl(pa->tmsi1)
&& ms->subscr.tmsi_valid) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1));
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
} else
LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi1));
@@ -2174,7 +2171,7 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
if (ms->subscr.tmsi == ntohl(pa->tmsi2)
&& ms->subscr.tmsi_valid) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2));
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
} else
LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi2));
@@ -2188,7 +2185,7 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
goto short_read;
chan_3 = mi[mi[1] + 2] & 0x03; /* channel needed */
if (gsm_match_mi(ms, mi + 1) > 0)
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
return 0;
}
@@ -2227,7 +2224,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
if (ms->subscr.tmsi == ntohl(pa->tmsi1)
&& ms->subscr.tmsi_valid) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1));
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
} else
LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi1));
@@ -2235,7 +2232,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
if (ms->subscr.tmsi == ntohl(pa->tmsi2)
&& ms->subscr.tmsi_valid) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2));
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
} else
LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi2));
@@ -2243,7 +2240,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
if (ms->subscr.tmsi == ntohl(pa->tmsi3)
&& ms->subscr.tmsi_valid) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi3));
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
} else
LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi3));
@@ -2251,7 +2248,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
if (ms->subscr.tmsi == ntohl(pa->tmsi4)
&& ms->subscr.tmsi_valid) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi4));
- return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1);
+ return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1);
} else
LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi4));
@@ -2360,20 +2357,25 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
gsm48_decode_start_time(&cd, (struct gsm48_start_time *)(st+1));
/* decode channel description */
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT:");
rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
if (ia->chan_desc.h0.h) {
cd.h = 1;
gsm48_decode_chan_h1(&ia->chan_desc, &cd.tsc, &cd.maio,
&cd.hsn);
- LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT (ra=0x%02x, "
- "chan_nr=0x%02x, MAIO=%u, HSN=%u, TS=%u, SS=%u, "
- "TSC=%u)\n", ia->req_ref.ra, ia->chan_desc.chan_nr,
- cd.maio, cd.hsn, ch_ts, ch_subch, cd.tsc);
+ LOGP(DRR, LOGL_INFO, " (ta %d/%dm ra 0x%02x chan_nr 0x%02x "
+ "MAIO %u HSN %u TS %u SS %u TSC %u)\n",
+ ia->timing_advance,
+ ia->timing_advance * GSM_TA_CM / 100,
+ ia->req_ref.ra, ia->chan_desc.chan_nr, cd.maio,
+ cd.hsn, ch_ts, ch_subch, cd.tsc);
} else {
cd.h = 0;
gsm48_decode_chan_h0(&ia->chan_desc, &cd.tsc, &cd.arfcn);
- LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT (ra=0x%02x, "
- "chan_nr=0x%02x, ARFCN=%u, TS=%u, SS=%u, TSC=%u)\n",
+ LOGP(DRR, LOGL_INFO, " (ta %d/%dm ra 0x%02x chan_nr 0x%02x "
+ "ARFCN %u TS %u SS %u TSC %u)\n",
+ ia->timing_advance,
+ ia->timing_advance * GSM_TA_CM / 100,
ia->req_ref.ra, ia->chan_desc.chan_nr, cd.arfcn,
ch_ts, ch_subch, cd.tsc);
}
@@ -2436,38 +2438,46 @@ static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
}
/* decode channel description */
- LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT EXTENDED:");
+ LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT EXTENDED:\n");
rsl_dec_chan_nr(ia->chan_desc1.chan_nr, &ch_type, &ch_subch, &ch_ts);
if (ia->chan_desc1.h0.h) {
cd1.h = 1;
gsm48_decode_chan_h1(&ia->chan_desc1, &cd1.tsc, &cd1.maio,
&cd1.hsn);
- LOGP(DRR, LOGL_INFO, " assignment 1 (ra=0x%02x, "
- "chan_nr=0x%02x, MAIO=%u, HSN=%u, TS=%u, SS=%u, "
- "TSC=%u)\n", ia->req_ref1.ra, ia->chan_desc1.chan_nr,
- cd1.maio, cd1.hsn, ch_ts, ch_subch, cd1.tsc);
+ LOGP(DRR, LOGL_INFO, " assignment 1 (ta %d/%dm ra 0x%02x "
+ "chan_nr 0x%02x MAIO %u HSN %u TS %u SS %u TSC %u)\n",
+ ia->timing_advance1,
+ ia->timing_advance1 * GSM_TA_CM / 100,
+ ia->req_ref1.ra, ia->chan_desc1.chan_nr, cd1.maio,
+ cd1.hsn, ch_ts, ch_subch, cd1.tsc);
} else {
cd1.h = 0;
gsm48_decode_chan_h0(&ia->chan_desc1, &cd1.tsc, &cd1.arfcn);
- LOGP(DRR, LOGL_INFO, " assignment 1 (ra=0x%02x, "
- "chan_nr=0x%02x, ARFCN=%u, TS=%u, SS=%u, TSC=%u)\n",
+ LOGP(DRR, LOGL_INFO, " assignment 1 (ta %d/%dm ra 0x%02x "
+ "chan_nr 0x%02x ARFCN %u TS %u SS %u TSC %u)\n",
+ ia->timing_advance1,
+ ia->timing_advance1 * GSM_TA_CM / 100,
ia->req_ref1.ra, ia->chan_desc1.chan_nr, cd1.arfcn,
ch_ts, ch_subch, cd1.tsc);
}
rsl_dec_chan_nr(ia->chan_desc2.chan_nr, &ch_type, &ch_subch, &ch_ts);
if (ia->chan_desc2.h0.h) {
cd2.h = 1;
- gsm48_decode_chan_h1(&ia->chan_desc2, &cd1.tsc, &cd1.maio,
- &cd1.hsn);
- LOGP(DRR, LOGL_INFO, " assignment 2 (ra=0x%02x, "
- "chan_nr=0x%02x, MAIO=%u, HSN=%u, TS=%u, SS=%u, "
- "TSC=%u)\n", ia->req_ref2.ra, ia->chan_desc2.chan_nr,
- cd2.maio, cd2.hsn, ch_ts, ch_subch, cd2.tsc);
+ gsm48_decode_chan_h1(&ia->chan_desc2, &cd2.tsc, &cd2.maio,
+ &cd2.hsn);
+ LOGP(DRR, LOGL_INFO, " assignment 2 (ta %d/%dm ra 0x%02x "
+ "chan_nr 0x%02x MAIO %u HSN %u TS %u SS %u TSC %u)\n",
+ ia->timing_advance2,
+ ia->timing_advance2 * GSM_TA_CM / 100,
+ ia->req_ref2.ra, ia->chan_desc2.chan_nr, cd2.maio,
+ cd2.hsn, ch_ts, ch_subch, cd2.tsc);
} else {
cd2.h = 0;
gsm48_decode_chan_h0(&ia->chan_desc2, &cd2.tsc, &cd2.arfcn);
- LOGP(DRR, LOGL_INFO, " assignment 2 (ra=0x%02x, "
- "chan_nr=0x%02x, ARFCN=%u, TS=%u, SS=%u, TSC=%u)\n",
+ LOGP(DRR, LOGL_INFO, " assignment 2 (ta %d/%dm ra 0x%02x "
+ "chan_nr 0x%02x ARFCN %u TS %u SS %u TSC %u)\n",
+ ia->timing_advance2,
+ ia->timing_advance2 * GSM_TA_CM / 100,
ia->req_ref2.ra, ia->chan_desc2.chan_nr, cd2.arfcn,
ch_ts, ch_subch, cd2.tsc);
}
@@ -2864,7 +2874,7 @@ static int gsm48_rr_est_req(struct osmocom_ms *ms, struct msgb *msg)
msgb_l3(msg), msgb_l3len(msg));
/* request channel */
- return gsm48_rr_tx_chan_req(ms, rrh->cause, 0);
+ return gsm48_rr_chan_req(ms, rrh->cause, 0);
}
/* send all queued messages down to layer 2 */
@@ -2977,7 +2987,7 @@ static int gsm48_rr_rx_bcch(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
/* when changing/deactivating ccch, ignore pending messages */
- if (!cs->ccch_active)
+ if (!cs->ccch_sync)
return -EINVAL;
switch (sih->system_information) {
@@ -3009,7 +3019,7 @@ static int gsm48_rr_rx_pch_agch(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
/* when changing/deactivating ccch, ignore pending messages */
- if (!cs->ccch_active)
+ if (!cs->ccch_sync)
return -EINVAL;
switch (sih->system_information) {
@@ -3112,7 +3122,7 @@ static struct dldatastate {
RSL_MT_REL_CONF, "REL_CONF", gsm48_rr_rel_cnf_dedicated},
#endif
{SBIT(GSM48_RR_ST_CONN_PEND), /* 3.3.1.1.2 */
- RSL_MT_CHAN_CNF, "CHAN_CNF", gsm48_rr_rand_acc_cnf},
+ RSL_MT_CHAN_CNF, "CHAN_CNF", gsm48_rr_tx_rand_acc},
#if 0
{SBIT(GSM48_RR_ST_DEDICATED),
RSL_MT_CHAN_CNF, "CHAN_CNF", gsm48_rr_rand_acc_cnf_dedicated},
diff --git a/src/host/layer23/src/support.c b/src/host/layer23/src/support.c
index d0d76ca..86b1a1a 100644
--- a/src/host/layer23/src/support.c
+++ b/src/host/layer23/src/support.c
@@ -105,7 +105,8 @@ void gsm_support_init(struct osmocom_ms *ms)
sprintf(sup->imeisv, "0000000000000000");
/* radio */
- sup->min_rxlev_db = -106; // TODO
+ sup->min_rxlev_db = -60; // TODO
+ sup->sync_to = 6; /* how long to wait sync (0.9 s) */
sup->scan_to = 4; /* how long to wait for all sysinfos (>=4 s) */
}
@@ -119,7 +120,7 @@ struct gsm_support_scan_max gsm_sup_smax[] = {
{ 955, 124, 30, 0 },
{ 512, 885, 40, 0 },
#else
- { 955, 125, 1, 0 }, /* we support only one ARFCN */
+// { 955, 125, 1, 0 }, /* we support only one ARFCN */
#endif
{ 0, 0, 0, 0 }
};