summaryrefslogtreecommitdiffstats
path: root/src/host/layer23
diff options
context:
space:
mode:
authorAndreas.Eversberg2010-06-12 18:16:54 +0200
committerAndreas.Eversberg2010-06-12 18:16:54 +0200
commit247ec7acf3a2f73ed203565af1cfd604fc1ebdac (patch)
treeb5316d1ab3b24fd20dc0c0d459bf2e9f40e7b09e /src/host/layer23
parentFixed CM SERVICE REQUEST message. (diff)
downloadosmocom-247ec7acf3a2f73ed203565af1cfd604fc1ebdac.tar.gz
osmocom-247ec7acf3a2f73ed203565af1cfd604fc1ebdac.tar.xz
osmocom-247ec7acf3a2f73ed203565af1cfd604fc1ebdac.zip
Radio ressources now has functions for release of radio link.
The "BA range" is used for cell re-selection. Due to layer 1 issues, the process gets stuck very often or looses synchronization. After location update, I can now make a call via VTY on SDCCH: Call control sends SETUP request after requesting an MM connection. My phone on the network side rang!! Call control fails and requires further debugging...
Diffstat (limited to 'src/host/layer23')
-rw-r--r--src/host/layer23/include/osmocom/gsm48_rr.h8
-rw-r--r--src/host/layer23/src/app_mobile.c4
-rw-r--r--src/host/layer23/src/gsm322.c20
-rw-r--r--src/host/layer23/src/gsm48_rr.c355
4 files changed, 291 insertions, 96 deletions
diff --git a/src/host/layer23/include/osmocom/gsm48_rr.h b/src/host/layer23/include/osmocom/gsm48_rr.h
index 88f44f1..dd87ed0 100644
--- a/src/host/layer23/include/osmocom/gsm48_rr.h
+++ b/src/host/layer23/include/osmocom/gsm48_rr.h
@@ -53,6 +53,7 @@ struct gsm48_rr_hdr {
#define GSM48_RR_ST_IDLE 0
#define GSM48_RR_ST_CONN_PEND 1
#define GSM48_RR_ST_DEDICATED 2
+#define GSM48_RR_ST_REL_PEND 3
/* channel description */
struct gsm48_rr_cd {
@@ -96,6 +97,8 @@ struct gsm48_rrlayer {
struct llist_head downqueue;
/* timers */
+ struct timer_list t_rel_wait; /* wait for L2 to transmit UA */
+ struct timer_list t3110;
struct timer_list t3122;
struct timer_list t3124;
struct timer_list t3126;
@@ -131,6 +134,10 @@ struct gsm48_rrlayer {
/* measurements */
struct gsm48_rr_meas meas;
+
+ /* BA range */
+ uint8_t ba_ranges;
+ uint32_t ba_range[16];
};
const char *get_rr_name(int value);
@@ -144,5 +151,6 @@ 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);
+int gsm48_rr_los(struct osmocom_ms *ms);
#endif /* _GSM48_RR_H */
diff --git a/src/host/layer23/src/app_mobile.c b/src/host/layer23/src/app_mobile.c
index f11e47f..bb97bbf 100644
--- a/src/host/layer23/src/app_mobile.c
+++ b/src/host/layer23/src/app_mobile.c
@@ -139,8 +139,8 @@ int l23_app_init(struct osmocom_ms *ms)
{
int rc;
- log_parse_category_mask(stderr_target, "DRSL:DLAPDM:DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG:DSUM");
-// log_parse_category_mask(stderr_target, "DRR:DMM:DCC:DMNCC:DPAG:DSUM");
+// log_parse_category_mask(stderr_target, "DRSL:DLAPDM:DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG:DSUM");
+ log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG:DSUM");
srand(time(NULL));
diff --git a/src/host/layer23/src/gsm322.c b/src/host/layer23/src/gsm322.c
index 661a824..e9c63d0 100644
--- a/src/host/layer23/src/gsm322.c
+++ b/src/host/layer23/src/gsm322.c
@@ -2254,6 +2254,8 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
/* start scan on radio interface */
cs->powerscan = 1;
+#warning TESTING!!!!
+usleep(300000);
return l1ctl_tx_pm_req_range(ms, s, e);
}
@@ -2359,9 +2361,7 @@ static void gsm322_cs_loss(void *arg)
msgb_free(nmsg);
} else {
LOGP(DCS, LOGL_INFO, "Trigger RR abort.\n");
-#ifdef TODO
- must trigger RR abort.
-#endif
+ gsm48_rr_los(ms);
}
}
@@ -2598,25 +2598,23 @@ struct gsm322_ba_list *gsm322_cs_ba_range(struct osmocom_ms *ms,
static int gsm322_cs_choose(struct osmocom_ms *ms)
{
struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm322_ba_list *ba = NULL;
int i;
-#ifdef TODO
-what we have todo here:
-if we return from dedicated mode and we have a ba range, we can use that for cell reselection
- if (message->ranges)
- ba = gsm322_cs_ba_range(ms, message->range, message->ranges);
+ /* NOTE: The call to this function is synchron to RR layer, so
+ * we may access the BA range there.
+ */
+ if (rr->ba_ranges)
+ ba = gsm322_cs_ba_range(ms, rr->ba_range, rr->ba_ranges);
else {
LOGP(DCS, LOGL_INFO, "No BA range(s), try sysinfo.\n");
-#endif
/* get and update BA of last received sysinfo 5* */
ba = gsm322_cs_sysinfo_sacch(ms);
if (!ba)
ba = gsm322_find_ba_list(cs, cs->sel_si.mcc,
cs->sel_si.mnc);
-#ifdef TODO
}
-#endif
if (!ba) {
struct msgb *nmsg;
diff --git a/src/host/layer23/src/gsm48_rr.c b/src/host/layer23/src/gsm48_rr.c
index 2640ef0..8069746 100644
--- a/src/host/layer23/src/gsm48_rr.c
+++ b/src/host/layer23/src/gsm48_rr.c
@@ -1,3 +1,4 @@
+#warning rr on MDL error handling (as specified in 04.08 / 04.06)
/*
* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
*
@@ -135,6 +136,58 @@ static int gsm48_decode_start_time(struct gsm48_rr_cd *cd,
return 0;
}
+/* decode "BA Range" (10.5.2.1a) */
+static int gsm48_decode_ba_range(const uint8_t *ba, uint8_t ba_len,
+ uint32_t *range, uint8_t *ranges, int max_ranges)
+{
+ /* ba = pointer to IE without IE type and length octets
+ * ba_len = number of octets
+ * range = pointer to store decoded range
+ * ranges = number of ranges decoded
+ * max_ranges = maximum number of decoded ranges that can be stored
+ */
+ uint16_t lower, higher;
+ int i, n, required_octets;
+
+ /* find out how much ba ranges will be decoded */
+ n = *ba++;
+ ba_len --;
+ required_octets = 5 * (n >> 1) + 3 * (n & 1);
+ if (required_octets > ba_len) {
+ LOGP(DRR, LOGL_NOTICE, "BA range IE too short: %d ranges "
+ "require %d octets, but only %d octets remain.\n",
+ n, required_octets, ba_len);
+ *ranges = 0;
+ return -EINVAL;
+ }
+ if (max_ranges > n)
+ LOGP(DRR, LOGL_NOTICE, "BA range %d exceed the maximum number "
+ "of ranges supported by this mobile (%d).\n",
+ n, max_ranges);
+ n = max_ranges;
+
+ /* decode ranges */
+ for (i = 0; i < n; i++) {
+ if (!(i & 1)) {
+ /* decode even range number */
+ lower = *ba++ << 2;
+ lower |= (*ba >> 6);
+ higher = (*ba++ & 0x3f) << 4;
+ higher |= *ba >> 4;
+ } else {
+ lower = (*ba++ & 0x0f) << 6;
+ lower |= *ba >> 2;
+ higher = (*ba++ & 0x03) << 8;
+ higher |= *ba++;
+ /* decode odd range number */
+ }
+ *range++ = (higher << 16) | lower;
+ }
+ *ranges = n;
+
+ return 0;
+}
+
/*
* state transition
*/
@@ -143,6 +196,7 @@ static const char *gsm48_rr_state_names[] = {
"IDLE",
"CONN PEND",
"DEDICATED",
+ "REL PEND",
};
static void new_rr_state(struct gsm48_rrlayer *rr, int state)
@@ -184,6 +238,8 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
return;
gsm322_c_event(rr->ms, nmsg);
msgb_free(nmsg);
+ /* reset any BA range */
+ rr->ba_ranges = 0;
}
}
@@ -321,6 +377,41 @@ int gsm48_rsl_dequeue(struct osmocom_ms *ms)
* timers handling
*/
+/* special timer to ensure that UA is sent before disconnecting channel */
+static void timeout_rr_t_rel_wait(void *arg)
+{
+ struct gsm48_rrlayer *rr = arg;
+
+ LOGP(DRR, LOGL_INFO, "L2 release timer has fired, done waiting\n");
+
+ /* return to idle now */
+ new_rr_state(rr, GSM48_RR_ST_IDLE);
+}
+
+/* 3.4.13.1.1: Timeout of T3110 */
+static void timeout_rr_t3110(void *arg)
+{
+ struct gsm48_rrlayer *rr = arg;
+ struct osmocom_ms *ms = rr->ms;
+ struct msgb *nmsg;
+ uint8_t *mode;
+
+ LOGP(DRR, LOGL_INFO, "timer T3110 has fired, release locally\n");
+
+ new_rr_state(rr, GSM48_RR_ST_REL_PEND);
+
+ /* disconnect the main signalling link */
+ nmsg = gsm48_l3_msgb_alloc();
+ if (!nmsg)
+ return;
+ mode = msgb_put(nmsg, 2);
+ mode[0] = RSL_IE_RELEASE_MODE;
+ mode[1] = 1; /* local release */
+ gsm48_send_rsl(ms, RSL_MT_REL_REQ, nmsg);
+
+ return;
+}
+
static void timeout_rr_t3122(void *arg)
{
LOGP(DRR, LOGL_INFO, "timer T3122 has fired\n");
@@ -347,6 +438,22 @@ static void timeout_rr_t3126(void *arg)
new_rr_state(rr, GSM48_RR_ST_IDLE);
}
+static void start_rr_t_rel_wait(struct gsm48_rrlayer *rr, int sec, int micro)
+{
+ LOGP(DRR, LOGL_INFO, "starting T_rel_wait with %d seconds\n", sec);
+ rr->t_rel_wait.cb = timeout_rr_t_rel_wait;
+ rr->t_rel_wait.data = rr;
+ bsc_schedule_timer(&rr->t_rel_wait, sec, micro);
+}
+
+static void start_rr_t3110(struct gsm48_rrlayer *rr, int sec, int micro)
+{
+ LOGP(DRR, LOGL_INFO, "starting T3110 with %d seconds\n", sec);
+ rr->t3110.cb = timeout_rr_t3110;
+ rr->t3110.data = rr;
+ bsc_schedule_timer(&rr->t3110, sec, micro);
+}
+
static void start_rr_t3122(struct gsm48_rrlayer *rr, int sec, int micro)
{
LOGP(DRR, LOGL_INFO, "starting T3122 with %d seconds\n", sec);
@@ -363,6 +470,22 @@ static void start_rr_t3126(struct gsm48_rrlayer *rr, int sec, int micro)
bsc_schedule_timer(&rr->t3126, sec, micro);
}
+static void stop_rr_t_rel_wait(struct gsm48_rrlayer *rr)
+{
+ if (bsc_timer_pending(&rr->t_rel_wait)) {
+ LOGP(DRR, LOGL_INFO, "stopping pending timer T_rel_wait\n");
+ bsc_del_timer(&rr->t_rel_wait);
+ }
+}
+
+static void stop_rr_t3110(struct gsm48_rrlayer *rr)
+{
+ if (bsc_timer_pending(&rr->t3110)) {
+ LOGP(DRR, LOGL_INFO, "stopping pending timer T3110\n");
+ bsc_del_timer(&rr->t3110);
+ }
+}
+
static void stop_rr_t3122(struct gsm48_rrlayer *rr)
{
if (bsc_timer_pending(&rr->t3122)) {
@@ -2762,6 +2885,49 @@ static int gsm48_rr_tx_meas_rep(struct osmocom_ms *ms)
* link establishment and release
*/
+/* process "Loss Of Signal" */
+int gsm48_rr_los(struct osmocom_ms *ms)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ uint8_t *mode;
+ struct msgb *nmsg;
+ struct gsm48_rr_hdr *nrrh;
+
+ LOGP(DSUM, LOGL_INFO, "Radio link lost signal\n");
+
+ if (rr->state == GSM48_RR_ST_CONN_PEND) {
+ LOGP(DRR, LOGL_INFO, "LOS during RACH request\n");
+
+ /* stop pending RACH timer */
+ stop_rr_t3126(rr);
+ } else {
+ LOGP(DRR, LOGL_INFO, "LOS during dedicated mode, release "
+ "locally\n");
+
+ new_rr_state(rr, GSM48_RR_ST_REL_PEND);
+
+ /* release message */
+ nmsg = gsm48_l3_msgb_alloc();
+ if (!nmsg)
+ return -ENOMEM;
+ mode = msgb_put(nmsg, 2);
+ mode[0] = RSL_IE_RELEASE_MODE;
+ mode[1] = 1; /* local release */
+ /* start release */
+ return gsm48_send_rsl(ms, RSL_MT_REL_REQ, nmsg);
+ }
+
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->cause = RR_REL_CAUSE_UNDEFINED;
+ gsm48_rr_upmsg(ms, nmsg);
+
+ return 0;
+}
+
/* activate link and send establish request */
static int gsm48_rr_dl_est(struct osmocom_ms *ms)
{
@@ -2849,7 +3015,7 @@ static int gsm48_rr_estab_cnf(struct osmocom_ms *ms, struct msgb *msg)
struct msgb *nmsg;
/* if MM has releases before confirm, we start release */
- if (rr->state == GSM48_RR_ST_IDLE) {
+ if (rr->state == GSM48_RR_ST_REL_PEND) {
LOGP(DRR, LOGL_INFO, "MM already released RR.\n");
/* release message */
nmsg = gsm48_l3_msgb_alloc();
@@ -2873,29 +3039,80 @@ static int gsm48_rr_estab_cnf(struct osmocom_ms *ms, struct msgb *msg)
return gsm48_rr_upmsg(ms, nmsg);
}
-/* the link is released */
-static int gsm48_rr_rel_cnf(struct osmocom_ms *ms, struct msgb *msg)
+/* the link is released in pending state (by l2) */
+static int gsm48_rr_rel_ind(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct msgb *nmsg;
+ struct gsm48_rr_hdr *nrrh;
- /* deactivate channel */
- LOGP(DRR, LOGL_INFO, "deactivating channel (arfcn %d)\n",
- rr->cd_now.arfcn);
-#ifdef TODO
- release and give new arfcn
- tx_ph_dm_rel_req(ms, arfcn, rr->chan_desc.chan_desc.chan_nr);
-#else
- l1ctl_tx_fbsb_req(ms, rr->cd_now.arfcn, 0x07, 100, 0);
-#endif
+ LOGP(DSUM, LOGL_INFO, "Radio link is released\n");
- /* do nothing, because we aleady IDLE
- * or we received the rel cnf of the last connection
- * while already requesting a new one (CONN PEND)
- */
+ /* send inication to upper layer */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->cause = RR_REL_CAUSE_UNDEFINED;
+ gsm48_rr_upmsg(ms, nmsg);
+
+ /* start release timer, so UA will be transmitted */
+ start_rr_t_rel_wait(rr, 1, 500000);
+
+ /* pending release */
+ new_rr_state(rr, GSM48_RR_ST_REL_PEND);
return 0;
}
+/* 9.1.7 CHANNEL RELEASE is received */
+static int gsm48_rr_rx_chan_rel(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ struct gsm48_chan_rel *cr = (struct gsm48_chan_rel *)gh->data;
+ int payload_len = msgb_l3len(msg) - sizeof(*gh) - sizeof(*cr);
+ struct tlv_parsed tp;
+ struct msgb *nmsg;
+ uint8_t *mode;
+
+ if (payload_len < 0) {
+ LOGP(DRR, LOGL_NOTICE, "Short read of CHANNEL RELEASE "
+ "message.\n");
+ return gsm48_rr_tx_rr_status(ms,
+ GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
+ }
+ tlv_parse(&tp, &gsm48_rr_att_tlvdef, cr->data, payload_len, 0, 0);
+
+ LOGP(DRR, LOGL_INFO, "channel release request with cause 0x%02x)\n",
+ cr->rr_cause);
+
+ /* BA range */
+ if (TLVP_PRESENT(&tp, GSM48_IE_BA_RANGE)) {
+ gsm48_decode_ba_range(TLVP_VAL(&tp, GSM48_IE_BA_RANGE),
+ *(TLVP_VAL(&tp, GSM48_IE_BA_RANGE) - 1), rr->ba_range,
+ &rr->ba_ranges,
+ sizeof(rr->ba_range) / sizeof(rr->ba_range[0]));
+ /* NOTE: the ranges are kept until IDLE state is returned
+ * (see new_rr_state)
+ */
+ }
+
+ new_rr_state(rr, GSM48_RR_ST_REL_PEND);
+
+ /* start T3110, so that two DISCs can be sent due to T200 timeout */
+ start_rr_t3110(rr, 1, 500000);
+
+ /* disconnect the main signalling link */
+ nmsg = gsm48_l3_msgb_alloc();
+ if (!nmsg)
+ return -ENOMEM;
+ mode = msgb_put(nmsg, 2);
+ mode[0] = RSL_IE_RELEASE_MODE;
+ mode[1] = 0; /* normal release */
+ return gsm48_send_rsl(ms, RSL_MT_REL_REQ, nmsg);
+}
+
/*
* radio ressource requests
*/
@@ -2933,6 +3150,13 @@ static int gsm48_rr_est_req(struct osmocom_ms *ms, struct msgb *msg)
stop_rr_t3122(rr);
}
+ /* if state is not idle */
+ if (rr->state != GSM48_RR_ST_IDLE) {
+ LOGP(DRR, LOGL_INFO, "We are not IDLE yet, rejecting!\n");
+ cause = RR_REL_CAUSE_TRY_LATER;
+ goto reject;
+ }
+
/* cell selected */
if (!cs->selected) {
LOGP(DRR, LOGL_INFO, "No cell selected, rejecting!\n");
@@ -3076,6 +3300,9 @@ static int gsm48_rr_data_ind(struct osmocom_ms *ms, struct msgb *msg)
rc = gsm48_rr_rx_freq_redef(ms, msg);
break;
#endif
+ case GSM48_MT_RR_CHAN_REL:
+ rc = gsm48_rr_rx_chan_rel(ms, msg);
+ break;
default:
LOGP(DRR, LOGL_NOTICE, "Message type 0x%02x unknown.\n",
gh->msg_type);
@@ -3254,6 +3481,9 @@ static int gsm48_rr_abort_req(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "Abort in dedicated state, send release "
"to layer 2.\n");
+
+ new_rr_state(rr, GSM48_RR_ST_REL_PEND);
+
/* release message */
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
@@ -3267,7 +3497,7 @@ static int gsm48_rr_abort_req(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "Abort in connection pending state, return to "
"idle state.\n");
/* return idle */
- new_rr_state(rr, GSM48_RR_ST_IDLE);
+ new_rr_state(rr, GSM48_RR_ST_REL_PEND);
return 0;
}
@@ -3300,8 +3530,8 @@ static int gsm48_rr_susp_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
-/* release confirm in dedicated mode (abort) */
-static int gsm48_rr_rel_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
+/* release confirm */
+static int gsm48_rr_rel_cnf(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct msgb *nmsg;
@@ -3309,6 +3539,9 @@ static int gsm48_rr_rel_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DSUM, LOGL_INFO, "Requesting channel aborted\n");
+ /* stop T3211 if running */
+ stop_rr_t3110(rr);
+
/* send release indication */
nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
if (!nmsg)
@@ -3332,16 +3565,23 @@ static struct dldatastate {
int type;
int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
} dldatastatelist[] = {
+ /* data transfer */
{SBIT(GSM48_RR_ST_IDLE) |
SBIT(GSM48_RR_ST_CONN_PEND) |
- SBIT(GSM48_RR_ST_DEDICATED),
+ SBIT(GSM48_RR_ST_DEDICATED) |
+ SBIT(GSM48_RR_ST_REL_PEND),
RSL_MT_UNIT_DATA_IND, gsm48_rr_unit_data_ind},
{SBIT(GSM48_RR_ST_DEDICATED), /* 3.4.2 */
RSL_MT_DATA_IND, gsm48_rr_data_ind},
+ /* esablish */
+ {SBIT(GSM48_RR_ST_CONN_PEND), /* 3.3.1.1.2 */
+ RSL_MT_CHAN_CNF, gsm48_rr_tx_rand_acc},
+
{SBIT(GSM48_RR_ST_IDLE) |
- SBIT(GSM48_RR_ST_CONN_PEND),
+ SBIT(GSM48_RR_ST_CONN_PEND) |
+ SBIT(GSM48_RR_ST_REL_PEND),
RSL_MT_EST_CONF, gsm48_rr_estab_cnf},
#if 0
@@ -3351,23 +3591,19 @@ static struct dldatastate {
{SBIT(GSM_RRSTATE),
RSL_MT_CONNECT_CNF, gsm48_rr_connect_cnf},
- {SBIT(GSM_RRSTATE),
- RSL_MT_RELEASE_IND, gsm48_rr_rel_ind},
#endif
- {SBIT(GSM48_RR_ST_IDLE) |
- SBIT(GSM48_RR_ST_CONN_PEND),
- RSL_MT_REL_CONF, gsm48_rr_rel_cnf},
-
+ /* release */
{SBIT(GSM48_RR_ST_DEDICATED),
- RSL_MT_REL_CONF, gsm48_rr_rel_cnf_dedicated},
+ RSL_MT_REL_IND, gsm48_rr_rel_ind},
+
+ {SBIT(GSM48_RR_ST_REL_PEND),
+ RSL_MT_REL_CONF, gsm48_rr_rel_cnf},
+ /* suspenion */
{SBIT(GSM48_RR_ST_DEDICATED),
RSL_MT_SUSP_CONF, gsm48_rr_susp_cnf_dedicated},
- {SBIT(GSM48_RR_ST_CONN_PEND), /* 3.3.1.1.2 */
- RSL_MT_CHAN_CNF, gsm48_rr_tx_rand_acc},
-
#if 0
{SBIT(GSM48_RR_ST_DEDICATED),
RSL_MT_CHAN_CNF, gsm48_rr_rand_acc_cnf_dedicated},
@@ -3420,7 +3656,8 @@ static struct rrdownstate {
int type;
int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
} rrdownstatelist[] = {
- {SBIT(GSM48_RR_ST_IDLE), /* 3.3.1.1 */
+ /* NOTE: If not IDLE, it is rejected there. */
+ {ALL_STATES, /* 3.3.1.1 */
GSM48_RR_EST_REQ, gsm48_rr_est_req},
{SBIT(GSM48_RR_ST_DEDICATED), /* 3.4.2 */
@@ -3511,6 +3748,8 @@ int gsm48_rr_exit(struct osmocom_ms *ms)
rr->rr_est_msg = NULL;
}
+ stop_rr_t_rel_wait(rr);
+ stop_rr_t3110(rr);
stop_rr_t3122(rr);
stop_rr_t3126(rr);
@@ -3676,52 +3915,6 @@ static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
-/* decode "BA Range" (10.5.2.1a) */
-static int gsm48_decode_ba_range(uint8_t *ba, uint8_t, ba_len, uint32_t *range,
- uint8_t *ranges, int max_ranges)
-{
- /* ba = pointer to IE without IE type and length octets
- * ba_len = number of octets
- * range = pointer to store decoded range
- * ranges = number of ranges decoded
- * max_ranges = maximum number of decoded ranges that can be stored
- */
- uint16_t lower, higher;
- int i, n, required_octets;
-
- /* find out how much ba ranges will be decoded */
- n = *ba++;
- ba_len --;
- required_octets = 5 * (n >> 1) + 3 * (n & 1);
- if (required_octets > n) {
- *ranges = 0;
- return -EINVAL;
- }
- if (max_ranges > n)
- n = max_ranges;
-
- /* decode ranges */
- for (i = 0; i < n; i++) {
- if (!(i & 1)) {
- /* decode even range number */
- lower = *ba++ << 2;
- lower |= (*ba >> 6);
- higher = (*ba++ & 0x3f) << 4;
- higher |= *ba >> 4;
- } else {
- lower = (*ba++ & 0x0f) << 6;
- lower |= *ba >> 2;
- higher = (*ba++ & 0x03) << 8;
- higher |= *ba++;
- /* decode odd range number */
- }
- *range++ = (higher << 16) | lower;
- }
- *ranges = n;
-
- return 0;
-}
-
/* decode "Cell Description" (10.5.2.2) */
static int gsm48_decode_cell_desc(struct gsm48_cell_desc *cd, uint16_t *arfcn, uint8_t *ncc uint8_t *bcc)
@@ -3827,10 +4020,6 @@ static int gsm48_rr_connect_cnf(struct osmocom_ms *ms, struct msgbl *msg)
{
}
-static int gsm48_rr_rel_ind(struct osmocom_ms *ms, struct msgb *msg)
-{
-}
-
static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = ms->rrlayer;
@@ -3898,7 +4087,7 @@ static void timeout_rr_t3124(void *arg)
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
- return gsm48_send_rsl(ms, RSL_MT_EST_REQ, nmsg);
+ return gsm48_send_rsl(ms, RSL_MT_REEST_REQ, nmsg);
todo
}