Fixes and improvements of RR, MM, CC processes.

This commit is contained in:
Andreas.Eversberg 2010-06-06 18:19:46 +00:00
parent ff555175d1
commit d8cc251cf1
5 changed files with 322 additions and 78 deletions

View File

@ -182,6 +182,7 @@ struct gsm48_mmlayer {
uint8_t lupd_ra_failure;/* random access failed */
uint8_t lupd_rej_cause; /* cause of last reject */
uint8_t lupd_periodic; /* periodic update pending */
uint8_t lupd_retry; /* pending T3211/T3213 to */
/* imsi detach */
uint8_t delay_detach; /* do detach when possible */

View File

@ -1010,6 +1010,7 @@ static int gsm322_a_switch_on(struct osmocom_ms *ms, struct msgb *msg)
struct msgb *nmsg;
if (!subscr->sim_valid) {
LOGP(DSUM, LOGL_INFO, "No SIM inserted\n");
LOGP(DPLMN, LOGL_INFO, "Switch on without SIM.\n");
new_a_state(plmn, GSM322_A6_NO_SIM);
@ -1022,6 +1023,10 @@ static int gsm322_a_switch_on(struct osmocom_ms *ms, struct msgb *msg)
plmn->mcc = subscr->plmn_mcc;
plmn->mnc = subscr->plmn_mnc;
LOGP(DSUM, LOGL_INFO, "Start search of last registered PLMN "
"(mcc=%03d mnc=%02d %s, %s)\n", plmn->mcc, plmn->mnc,
gsm_get_mcc(plmn->mcc),
gsm_get_mnc(plmn->mcc, plmn->mnc));
LOGP(DPLMN, LOGL_INFO, "Use RPLMN (mcc=%03d mnc=%02d "
"%s, %s)\n", plmn->mcc, plmn->mnc,
gsm_get_mcc(plmn->mcc),
@ -1039,6 +1044,7 @@ static int gsm322_a_switch_on(struct osmocom_ms *ms, struct msgb *msg)
}
/* initiate search at cell selection */
LOGP(DSUM, LOGL_INFO, "Search for network\n");
LOGP(DPLMN, LOGL_INFO, "Switch on, start PLMN search first.\n");
nmsg = gsm322_msgb_alloc(GSM322_EVENT_PLMN_SEARCH_START);
@ -1205,6 +1211,7 @@ static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg)
struct msgb *nmsg;
if (!subscr->sim_valid) {
LOGP(DSUM, LOGL_INFO, "No SIM inserted\n");
LOGP(DPLMN, LOGL_INFO, "Switch on without SIM.\n");
new_m_state(plmn, GSM322_M5_NO_SIM);
@ -1219,6 +1226,10 @@ static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg)
plmn->mcc = subscr->plmn_mcc;
plmn->mnc = subscr->plmn_mnc;
LOGP(DSUM, LOGL_INFO, "Start search of last registered PLMN "
"(mcc=%03d mnc=%02d %s, %s)\n", plmn->mcc, plmn->mnc,
gsm_get_mcc(plmn->mcc),
gsm_get_mnc(plmn->mcc, plmn->mnc));
LOGP(DPLMN, LOGL_INFO, "Use RPLMN (mcc=%03d mnc=%02d "
"%s, %s)\n", plmn->mcc, plmn->mnc,
gsm_get_mcc(plmn->mcc),
@ -1236,6 +1247,7 @@ static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg)
}
/* initiate search at cell selection */
LOGP(DSUM, LOGL_INFO, "Search for network\n");
LOGP(DPLMN, LOGL_INFO, "Switch on, start PLMN search first.\n");
vty_notify(ms, "Searching Network, please wait...\n");
@ -1986,7 +1998,7 @@ static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DCS, LOGL_INFO, "Sysinfo of selected cell is "
"updated.\n");
memcpy(&cs->sel_si, s, sizeof(cs->sel_si));
gsm48_sysinfo_dump(s, print_dcs, NULL);
//gsm48_sysinfo_dump(s, print_dcs, NULL);
}
}
@ -2084,7 +2096,7 @@ static int gsm322_c_scan_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
/* stop timer */
stop_cs_timer(cs);
gsm48_sysinfo_dump(s, print_dcs, NULL);
//gsm48_sysinfo_dump(s, print_dcs, NULL);
/* store sysinfo and continue scan */
return gsm322_cs_store(ms);
@ -2679,6 +2691,10 @@ static int gsm322_c_new_plmn(struct osmocom_ms *ms, struct msgb *msg)
cs->mcc = plmn->mcc;
cs->mnc = plmn->mnc;
LOGP(DSUM, LOGL_INFO, "Selecting network (mcc=%03d "
"mnc=%02d %s, %s)\n", cs->mcc, cs->mnc, gsm_get_mcc(cs->mcc),
gsm_get_mnc(cs->mcc, cs->mnc));
/* search for BA list */
ba = gsm322_find_ba_list(cs, plmn->mcc, plmn->mnc);
@ -2697,6 +2713,8 @@ static int gsm322_c_camp_normally(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
struct msgb *nmsg;
LOGP(DSUM, LOGL_INFO, "Camping normally on cell of network\n");
/* tell that we have selected a (new) cell */
nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_CELL_SELECTED);
if (!nmsg)
@ -2714,6 +2732,8 @@ static int gsm322_c_camp_any_cell(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
struct msgb *nmsg;
LOGP(DSUM, LOGL_INFO, "Camping on any cell of network\n");
/* tell that we have selected a (new) cell */
nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_CELL_SELECTED);
if (!nmsg)

View File

@ -1591,6 +1591,12 @@ static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
gsm48_decode_facility(&disc.facility,
TLVP_VAL(&tp, GSM48_IE_FACILITY)-1);
}
/* progress */
if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) {
disc.fields |= MNCC_F_PROGRESS;
gsm48_decode_progress(&disc.progress,
TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1);
}
/* user-user */
if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
disc.fields |= MNCC_F_USERUSER;

View File

@ -51,6 +51,7 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg);
static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate);
static int gsm48_mm_loc_upd_normal(struct osmocom_ms *ms, struct msgb *msg);
static int gsm48_mm_loc_upd_periodic(struct osmocom_ms *ms, struct msgb *msg);
static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg);
/*
* notes
@ -276,7 +277,7 @@ int gsm48_encode_mi(uint8_t *buf, struct msgb *msg, struct osmocom_ms *ms,
break;
}
/* alter MI type */
buf[2] = (buf[2] & 0xf8) | mi_type;
buf[2] = (buf[2] & ~GSM_MI_TYPE_MASK) | mi_type;
if (msg) {
/* MI as LV */
@ -316,6 +317,7 @@ static void timeout_mm_t3211(void *arg)
{
struct gsm48_mmlayer *mm = arg;
LOGP(DSUM, LOGL_INFO, "Location update retry\n");
LOGP(DMM, LOGL_INFO, "timer T3211 (loc. upd. retry delay) has fired\n");
gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3211, NULL);
}
@ -324,6 +326,7 @@ static void timeout_mm_t3212(void *arg)
{
struct gsm48_mmlayer *mm = arg;
LOGP(DSUM, LOGL_INFO, "Periodic location update\n");
LOGP(DMM, LOGL_INFO, "timer T3212 (periodic loc. upd. delay) has "
"fired\n");
@ -339,6 +342,7 @@ static void timeout_mm_t3213(void *arg)
{
struct gsm48_mmlayer *mm = arg;
LOGP(DSUM, LOGL_INFO, "Location update retry\n");
LOGP(DMM, LOGL_INFO, "timer T3213 (delay after RA failure) has "
"fired\n");
gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3213, NULL);
@ -917,11 +921,21 @@ static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate)
if (!bsc_timer_pending(&mm->t3212))
start_mm_t3212(mm, mm->t3212_value);
/* perform pending location update */
if (mm->lupd_retry) {
LOGP(DMM, LOGL_INFO, "Loc. upd. pending (type %d)\n",
mm->lupd_type);
mm->lupd_retry = 0;
gsm48_mm_loc_upd(mm->ms, NULL);
/* must exit, because this function can be called
* recursively
*/
return;
}
if (mm->lupd_periodic) {
struct gsm48_sysinfo *s = &mm->ms->cellsel.sel_si;
LOGP(DMM, LOGL_INFO, "Loc. upd. pending (type %d)\n",
mm->lupd_type);
LOGP(DMM, LOGL_INFO, "Periodic loc. upd. pending "
"(type %d)\n", mm->lupd_type);
mm->lupd_periodic = 0;
if (s->t3212)
gsm48_mm_loc_upd_periodic(mm->ms, NULL);
@ -1438,7 +1452,8 @@ static int gsm48_mm_rx_tmsi_realloc_cmd(struct osmocom_ms *ms, struct msgb *msg)
memcpy(&tmsi, mi+2, 4);
subscr->tmsi = ntohl(tmsi);
subscr->tmsi_valid = 1;
LOGP(DMM, LOGL_INFO, "TMSI 0x%08x assigned.\n", subscr->tmsi);
LOGP(DMM, LOGL_INFO, "TMSI 0x%08x (%u) assigned.\n",
subscr->tmsi, subscr->tmsi);
gsm48_mm_tx_tmsi_reall_cpl(ms);
break;
case GSM_MI_TYPE_IMSI:
@ -1938,6 +1953,7 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s = &cs->sel_si;
struct gsm_subscriber *subscr = &ms->subscr;
struct msgb *nmsg;
/* (re)start only if we still require location update */
if (!mm->lupd_pending) {
@ -1948,21 +1964,26 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
/* must camp normally */
if (cs->state != GSM322_C3_CAMPED_NORMALLY) {
LOGP(DMM, LOGL_INFO, "Loc. upd. not camping normally.\n");
stop:
LOGP(DSUM, LOGL_INFO, "Location update not possible\n");
mm->lupd_pending = 0;
/* send message to PLMN search process */
nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED);
if (!nmsg)
return -ENOMEM;
gsm322_plmn_sendmsg(ms, nmsg);
return 0;
}
/* if LAI is forbidden, don't start */
if (gsm_subscr_is_forbidden_plmn(subscr, cs->sel_mcc, cs->sel_mnc)) {
LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed PLMN.\n");
mm->lupd_pending = 0;
return 0;
goto stop;
}
if (gsm322_is_forbidden_la(ms, cs->sel_mcc,
cs->sel_mnc, cs->sel_lac)) {
LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed LA.\n");
mm->lupd_pending = 0;
return 0;
goto stop;
}
/* 4.4.4.9 if cell is barred, don't start */
@ -1970,10 +1991,11 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
|| (!subscr->acc_barr && !((subscr->acc_class & 0xfbff) &
(s->class_barr ^ 0xffff)))) {
LOGP(DMM, LOGL_INFO, "Loc. upd. no access.\n");
mm->lupd_pending = 0;
return 0;
goto stop;
}
LOGP(DSUM, LOGL_INFO, "Perform location update\n");
return gsm48_mm_tx_loc_upd_req(ms);
}
@ -2199,6 +2221,7 @@ static int gsm48_mm_rx_loc_upd_acc(struct osmocom_ms *ms, struct msgb *msg)
sim: store plmn
#endif
LOGP(DSUM, LOGL_INFO, "Location update accepted\n");
LOGP(DMM, LOGL_INFO, "LOCATION UPDATING ACCEPT (mcc %03d mnc %02d "
"lac 0x%04x)\n", subscr->lai_mcc, subscr->lai_mnc,
subscr->lai_lac);
@ -2225,8 +2248,8 @@ static int gsm48_mm_rx_loc_upd_acc(struct osmocom_ms *ms, struct msgb *msg)
memcpy(&tmsi, mi+2, 4);
subscr->tmsi = ntohl(tmsi);
subscr->tmsi_valid = 1;
LOGP(DMM, LOGL_INFO, "got TMSI 0x%08x\n",
subscr->tmsi);
LOGP(DMM, LOGL_INFO, "got TMSI 0x%08x (%u)\n",
subscr->tmsi, subscr->tmsi);
#ifdef TODO
sim: store tmsi
#endif
@ -2343,10 +2366,12 @@ static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
switch(mm->lupd_rej_cause) {
case GSM48_REJECT_ROAMING_NOT_ALLOWED:
nmsg = gsm322_msgb_alloc(GSM322_EVENT_ROAMING_NA);
break;
case GSM48_REJECT_IMSI_UNKNOWN_IN_HLR:
case GSM48_REJECT_ILLEGAL_MS:
case GSM48_REJECT_ILLEGAL_ME:
nmsg = gsm322_msgb_alloc(GSM322_EVENT_INVALID_SIM);
break;
default:
nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED);
}
@ -2381,7 +2406,7 @@ static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
}
/* 4.2.2 delay a location update */
static int gsm48_mm_loc_upd_delay(struct osmocom_ms *ms, struct msgb *msg)
static int gsm48_mm_loc_upd_delay_per(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_mmlayer *mm = &ms->mmlayer;
@ -2391,6 +2416,17 @@ static int gsm48_mm_loc_upd_delay(struct osmocom_ms *ms, struct msgb *msg)
return 0;
}
/* delay a location update retry */
static int gsm48_mm_loc_upd_delay_retry(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_mmlayer *mm = &ms->mmlayer;
LOGP(DMM, LOGL_INFO, "Schedule a pending periodic loc. upd.\n");
mm->lupd_retry = 1;
return 0;
}
/* process failues as described in the lower part of 4.4.4.9 */
static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
{
@ -2398,6 +2434,8 @@ static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm322_cellsel *cs = &ms->cellsel;
LOGP(DSUM, LOGL_INFO, "Location update failed\n");
/* stop location update timer, if running */
stop_mm_t3210(mm);
@ -2407,6 +2445,7 @@ static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
&& cs->sel_mnc == subscr->lai_mnc
&& cs->sel_lac == subscr->lai_lac) {
if (mm->lupd_attempt < 4) {
LOGP(DSUM, LOGL_INFO, "Try location update later\n");
LOGP(DMM, LOGL_INFO, "Loc. upd. failed, retry #%d\n",
mm->lupd_attempt);
@ -2436,8 +2475,10 @@ static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
#endif
/* start update retry timer (RR connection is released) */
if (mm->lupd_attempt < 4)
if (mm->lupd_attempt < 4) {
mm->start_t3211 = 1;
LOGP(DSUM, LOGL_INFO, "Try location update later\n");
}
/* CS process will trigger: return to MM IDLE */
return 0;
@ -2449,6 +2490,13 @@ static int gsm48_mm_rel_loc_upd_abort(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_mmlayer *mm = &ms->mmlayer;
struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data;
if (rrh->msg_type == GSM48_RR_REL_IND) {
LOGP(DMM, LOGL_INFO, "RR link released after loc. upd.\n");
/* continue with failure handling */
return gsm48_mm_loc_upd_failed(ms, NULL);
}
LOGP(DMM, LOGL_INFO, "Loc. upd. aborted by radio (cause #%d)\n",
rrh->cause);
@ -2527,7 +2575,7 @@ static int gsm48_mm_tx_cm_serv_req(struct osmocom_ms *ms, int rr_prim,
gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_TMSI);
else
gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_IMSI);
msgb_put(nmsg, buf[1]);
msgb_put(nmsg, buf[1]); /* length is part of nsr */
memcpy(&nsr->mi_len, buf + 1, 1 + buf[1]);
/* prio is optional for eMLPP */
@ -2762,6 +2810,8 @@ static int gsm48_mm_init_mm(struct osmocom_ms *ms, struct msgb *msg,
proto = GSM48_PDISC_SMS;
break;
}
#warning HACK: always request SDCCH for test
cause = RR_EST_CAUSE_LOC_UPD;
/* create MM connection instance */
conn = mm_conn_new(mm, proto, mmh->transaction_id, mmh->ref);
@ -3246,88 +3296,124 @@ static struct downstate {
/* 4.2.2.1 Normal service */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_no_rr},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_no_rr},
/* 4.2.2.2 Attempt to update / Loc. Upd. needed */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr}, /* emergency only */
/* 4.2.2.3 Limited service */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
/* 4.2.2.4 No IMSI */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_IMSI),
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
/* 4.2.2.5 PLMN search, normal service */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_no_rr},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_no_rr},
/* 4.2.2.6 PLMN search */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
/* 4.5.1.1 MM Connection (EST) */
{SBIT(GSM48_MM_ST_RR_CONN_RELEASE_NA), ALL_STATES,
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_first},
{SBIT(GSM48_MM_ST_RR_CONN_RELEASE_NA), ALL_STATES,
GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_first},
{SBIT(GSM48_MM_ST_RR_CONN_RELEASE_NA), ALL_STATES,
GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_first},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_more},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_more},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_more},
{SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES,
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_wait},
{SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES,
GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_wait},
{SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES,
GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_wait},
{ALL_STATES, ALL_STATES,
GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_reject},
{ALL_STATES, ALL_STATES,
GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_reject},
{ALL_STATES, ALL_STATES,
GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_reject},
/* 4.5.2.1 MM Connection (DATA) */
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
GSM48_MMCC_DATA_REQ, gsm48_mm_data},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
GSM48_MMSS_DATA_REQ, gsm48_mm_data},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
GSM48_MMSMS_DATA_REQ, gsm48_mm_data},
/* 4.5.2.1 MM Connection (REL) */
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
GSM48_MMCC_REL_REQ, gsm48_mm_release_active},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
GSM48_MMSS_REL_REQ, gsm48_mm_release_active},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
GSM48_MMSMS_REL_REQ, gsm48_mm_release_active},
{SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
GSM48_MMCC_REL_REQ, gsm48_mm_release_wait_add},
{SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
GSM48_MMSS_REL_REQ, gsm48_mm_release_wait_add},
{SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
GSM48_MMSMS_REL_REQ, gsm48_mm_release_wait_add},
{SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN), ALL_STATES,
GSM48_MMCC_REL_REQ, gsm48_mm_release_wait_active},
{SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN), ALL_STATES,
GSM48_MMSS_REL_REQ, gsm48_mm_release_wait_active},
{SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN), ALL_STATES,
GSM48_MMSMS_REL_REQ, gsm48_mm_release_wait_active},
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), ALL_STATES,
GSM48_MMCC_REL_REQ, gsm48_mm_release_wait_rr},
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), ALL_STATES,
GSM48_MMSS_REL_REQ, gsm48_mm_release_wait_rr},
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), ALL_STATES,
GSM48_MMSMS_REL_REQ, gsm48_mm_release_wait_rr},
};
@ -3384,56 +3470,74 @@ static struct rrdatastate {
/* paging */
{SBIT(GSM48_MM_ST_MM_IDLE),
GSM48_RR_EST_IND, gsm48_mm_est},
/* imsi detach */
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D), /* 4.3.4.4 */
GSM48_RR_EST_CNF, gsm48_mm_imsi_detach_sent},
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D), /* 4.3.4.4 (unsuc.) */
GSM48_RR_REL_IND, gsm48_mm_imsi_detach_end},
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D), /* 4.3.4.4 (lost) */
GSM48_RR_ABORT_IND, gsm48_mm_imsi_detach_end},
/* location update */
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_LUPD), /* 4.4.4.1 */
GSM48_RR_EST_CNF, gsm48_mm_est_loc_upd},
{SBIT(GSM48_MM_ST_LOC_UPD_INIT) |
SBIT(GSM48_MM_ST_WAIT_RR_CONN_LUPD), /* 4.4.4.9 */
GSM48_RR_REL_IND, gsm48_mm_rel_loc_upd_abort},
{SBIT(GSM48_MM_ST_LOC_UPD_INIT) |
SBIT(GSM48_MM_ST_WAIT_RR_CONN_LUPD), /* 4.4.4.9 */
GSM48_RR_ABORT_IND, gsm48_mm_rel_loc_upd_abort},
{SBIT(GSM48_MM_ST_LOC_UPD_REJ), /* 4.4.4.7 */
GSM48_RR_REL_IND, gsm48_mm_rel_loc_upd_rej},
{SBIT(GSM48_MM_ST_LOC_UPD_REJ), /* 4.4.4.7 */
GSM48_RR_ABORT_IND, gsm48_mm_rel_loc_upd_rej},
/* MM connection (EST) */
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), /* 4.5.1.1 */
GSM48_RR_EST_CNF, gsm48_mm_est_mm_con},
/* MM connection (DATA) */
{ALL_STATES,
GSM48_RR_DATA_IND, gsm48_mm_data_ind},
/* MM connection (SYNC) */
{SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* 4.5.1.1 */
GSM48_RR_SYNC_IND, gsm48_mm_sync_ind_wait},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE),
GSM48_RR_SYNC_IND, gsm48_mm_sync_ind_active},
/* MM connection (REL/ABORT) */
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON) |
SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* 4.5.1.2 */
GSM48_RR_REL_IND, gsm48_mm_abort_mm_con},
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON) |
SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* 4.5.1.2 */
GSM48_RR_ABORT_IND, gsm48_mm_abort_mm_con},
/* MM connection (REL/ABORT with re-establishment possibility) */
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), /* not supported */
GSM48_RR_REL_IND, gsm48_mm_abort_mm_con},
{SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* not supported */
GSM48_RR_ABORT_IND, gsm48_mm_abort_mm_con},
/* other */
{ALL_STATES,
GSM48_RR_REL_IND, gsm48_mm_rel_other},
{ALL_STATES,
GSM48_RR_ABORT_IND, gsm48_mm_rel_other},
};
@ -3479,22 +3583,31 @@ static struct mmdatastate {
} mmdatastatelist[] = {
{ALL_STATES, /* 4.3.1.2 */
GSM48_MT_MM_TMSI_REALL_CMD, gsm48_mm_rx_tmsi_realloc_cmd},
{ALL_STATES, /* 4.3.2.2 */
GSM48_MT_MM_AUTH_REQ, gsm48_mm_rx_auth_req},
{ALL_STATES, /* 4.3.2.5 */
GSM48_MT_MM_AUTH_REJ, gsm48_mm_rx_auth_rej},
{ALL_STATES, /* 4.3.3.2 */
GSM48_MT_MM_ID_REQ, gsm48_mm_rx_id_req},
{ALL_STATES, /* 4.3.5.2 */
GSM48_MT_MM_ABORT, gsm48_mm_rx_abort},
{ALL_STATES, /* 4.3.6.2 */
GSM48_MT_MM_INFO, gsm48_mm_rx_info},
{SBIT(GSM48_MM_ST_LOC_UPD_INIT), /* 4.4.4.6 */
GSM48_MT_MM_LOC_UPD_ACCEPT, gsm48_mm_rx_loc_upd_acc},
{SBIT(GSM48_MM_ST_LOC_UPD_INIT), /* 4.4.4.7 */
GSM48_MT_MM_LOC_UPD_REJECT, gsm48_mm_rx_loc_upd_rej},
{ALL_STATES, /* 4.5.1.1 */
GSM48_MT_MM_CM_SERV_ACC, gsm48_mm_rx_cm_service_acc},
{ALL_STATES, /* 4.5.1.1 */
GSM48_MT_MM_CM_SERV_REJ, gsm48_mm_rx_cm_service_rej},
};
@ -3653,77 +3766,105 @@ static struct eventstate {
/* 4.2.3 return to MM IDLE */
{ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_no_cell_found},
{ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_return_idle},
/* 4.2.2.1 Normal service */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_plmn_search}, /* 4.2.1.2 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_loc_upd_normal}, /* change */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_upd},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_periodic},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
/* 4.2.2.2 Attempt to update / Loc. upd. needed */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
GSM48_MM_EVENT_USER_PLMN_SEL, gsm48_mm_plmn_search}, /* 4.2.1.2 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_plmn_search}, /* 4.2.1.2 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_loc_upd_normal}, /* change */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_upd},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_periodic},
/* 4.2.2.3 Limited service */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
GSM48_MM_EVENT_USER_PLMN_SEL, gsm48_mm_plmn_search}, /* 4.2.1.2 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_plmn_search}, /* 4.2.1.2 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_loc_upd_normal}, /* if allow. */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay}, /* 4.4.2 */
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
/* 4.2.2.4 No IMSI */
/* 4.2.2.5 PLMN search, normal service */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_no_cell_found}, /* 4.2.1.1 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_cell_selected}, /* 4.2.1.1 */
#warning MUST DELAY
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_upd},
#warning MUST DELAY
GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_upd_delay_retry},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd},
GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd_delay_retry},
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay}, /* 4.4.2 */
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
/* 4.2.2.6 PLMN search */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_no_cell_found}, /* 4.2.1.1 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_cell_selected}, /* 4.2.1.1 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay}, /* 4.4.2 */
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
/* No cell available */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_CELL_AVAIL),
GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_cell_selected}, /* 4.2.1.1 */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_CELL_AVAIL),
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay}, /* 4.4.2 */
GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
/* IMSI detach in other cases */
{SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES, /* silently detach */
GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_end},
{SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
SBIT(GSM48_MM_ST_PROCESS_CM_SERV_P) |
@ -3732,35 +3873,46 @@ static struct eventstate {
SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS) |
SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES, /* we can release */
GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_release},
{SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D) |
SBIT(GSM48_MM_ST_IMSI_DETACH_INIT) |
SBIT(GSM48_MM_ST_IMSI_DETACH_PEND), ALL_STATES, /* ignore */
GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_ignore},
{ALL_STATES, ALL_STATES,
GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_delay},
{GSM48_MM_ST_IMSI_DETACH_INIT, ALL_STATES,
GSM48_MM_EVENT_TIMEOUT_T3220, gsm48_mm_imsi_detach_end},
/* location update in other cases */
{ALL_STATES, ALL_STATES,
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},
/* T3240 timed out */
{SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD) |
SBIT(GSM48_MM_ST_LOC_UPD_REJ), ALL_STATES, /* 4.4.4.8 */
GSM48_MM_EVENT_TIMEOUT_T3240, gsm48_mm_abort_rr},
/* T3230 timed out */
{SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
GSM48_MM_EVENT_TIMEOUT_T3230, gsm48_mm_timeout_mm_con},
/* SIM reports SRES */
{ALL_STATES, ALL_STATES, /* 4.3.2.2 */
GSM48_MM_EVENT_AUTH_RESPONSE, gsm48_mm_tx_auth_rsp},
#if 0
/* change in classmark is reported */
{ALL_STATES, ALL_STATES,

View File

@ -336,6 +336,7 @@ static void timeout_rr_t3126(void *arg)
struct msgb *msg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
struct gsm48_rr_hdr *rrh;
LOGP(DSUM, LOGL_INFO, "Requesting channel failed\n");
if (!msg)
return;
rrh = (struct gsm48_rr_hdr *)msg->data;
@ -722,6 +723,9 @@ static int gsm48_rr_chan_req(struct osmocom_ms *ms, int cause, int paging)
uint8_t chan_req_val, chan_req_mask;
int rc;
LOGP(DSUM, LOGL_INFO, "Establish radio link due to %s request\n",
(paging) ? "paging" : "mobility management");
/* ignore paging, if not camping */
if (paging
&& (!cs->selected || (cs->state != GSM322_C3_CAMPED_NORMALLY
@ -862,6 +866,8 @@ static int gsm48_rr_chan_req(struct osmocom_ms *ms, int cause, int paging)
LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: with unknown "
"establishment cause: %d\n", cause);
undefined:
LOGP(DSUM, LOGL_INFO, "Requesting channel failed\n");
nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
if (!nmsg)
return -ENOMEM;
@ -911,6 +917,7 @@ int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg)
gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
struct gsm48_rr_hdr *rrh;
LOGP(DSUM, LOGL_INFO, "Requesting channel failed\n");
if (!msg)
return -ENOMEM;
rrh = (struct gsm48_rr_hdr *)msg->data;
@ -2838,8 +2845,8 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms)
static int gsm48_rr_estab_cnf(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct msgb *nmsg;
uint8_t *mode;
struct msgb *nmsg;
/* if MM has releases before confirm, we start release */
if (rr->state == GSM48_RR_ST_IDLE) {
@ -2913,6 +2920,8 @@ static int gsm48_rr_est_req(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "T3122 running, rejecting!\n");
cause = RR_REL_CAUSE_T3122;
reject:
LOGP(DSUM, LOGL_INFO, "Establishing radio link not "
"possible\n");
nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND);
if (!nmsg)
return -ENOMEM;
@ -3230,6 +3239,89 @@ for(i=0;i<msgb_l3len(msg);i++)
}
}
/* 3.4.13.3 RR abort in dedicated mode (also in conn. pending mode) */
static int gsm48_rr_abort_req(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
uint8_t *mode;
/* stop pending RACH timer */
stop_rr_t3126(rr);
/* release "normally" if we are in dedicated mode */
if (rr->state == GSM48_RR_ST_DEDICATED) {
struct msgb *nmsg;
LOGP(DRR, LOGL_INFO, "Abort in dedicated state, send release "
"to layer 2.\n");
/* release message */
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);
}
LOGP(DRR, LOGL_INFO, "Abort in connection pending state, return to "
"idle state.\n");
/* return idle */
new_rr_state(rr, GSM48_RR_ST_IDLE);
return 0;
}
/* release confirm in dedicated mode */
static int gsm48_rr_susp_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
if (rr->hando_susp_state || rr->assign_susp_state) {
struct msgb *nmsg;
/* change radio to new channel */
tx_ph_dm_est_req(ms, rr->cd_now.arfcn, rr->cd_now.chan_nr);
/* send DL-ESTABLISH REQUEST */
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
gsm48_send_rsl(ms, RSL_MT_EST_REQ, nmsg);
#ifdef TODO
/* trigger RACH */
if (rr->hando_susp_state) {
gsm48_rr_tx_hando_access(ms);
rr->hando_acc_left = 3;
}
#endif
}
return 0;
}
/* release confirm in dedicated mode (abort) */
static int gsm48_rr_rel_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct msgb *nmsg;
struct gsm48_rr_hdr *nrrh;
LOGP(DSUM, LOGL_INFO, "Requesting channel aborted\n");
/* send release indication */
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 idle */
new_rr_state(rr, GSM48_RR_ST_IDLE);
return 0;
}
/*
* state machines
*/
@ -3240,32 +3332,46 @@ static struct dldatastate {
int type;
int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
} dldatastatelist[] = {
{SBIT(GSM48_RR_ST_IDLE) | SBIT(GSM48_RR_ST_CONN_PEND) |
{SBIT(GSM48_RR_ST_IDLE) |
SBIT(GSM48_RR_ST_CONN_PEND) |
SBIT(GSM48_RR_ST_DEDICATED),
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},
{SBIT(GSM48_RR_ST_IDLE) | SBIT(GSM48_RR_ST_CONN_PEND),
{SBIT(GSM48_RR_ST_IDLE) |
SBIT(GSM48_RR_ST_CONN_PEND),
RSL_MT_EST_CONF, gsm48_rr_estab_cnf},
#if 0
{SBIT(GSM48_RR_ST_DEDICATED),
RSL_MT_EST_CONF, gsm48_rr_estab_cnf_dedicated},
{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),
{SBIT(GSM48_RR_ST_IDLE) |
SBIT(GSM48_RR_ST_CONN_PEND),
RSL_MT_REL_CONF, gsm48_rr_rel_cnf},
#if 0
{SBIT(GSM48_RR_ST_DEDICATED),
RSL_MT_REL_CONF, gsm48_rr_rel_cnf_dedicated},
#endif
{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},
{SBIT(GSM_RRSTATE),
RSL_MT_MDL_ERROR_IND, gsm48_rr_mdl_error_ind},
#endif
@ -3316,11 +3422,15 @@ static struct rrdownstate {
} rrdownstatelist[] = {
{SBIT(GSM48_RR_ST_IDLE), /* 3.3.1.1 */
GSM48_RR_EST_REQ, gsm48_rr_est_req},
{SBIT(GSM48_RR_ST_DEDICATED), /* 3.4.2 */
GSM48_RR_DATA_REQ, gsm48_rr_data_req},
#if 0
{SBIT(GSM48_RR_ST_CONN_PEND) | SBIT(GSM48_RR_ST_DEDICATED),
{SBIT(GSM48_RR_ST_CONN_PEND) |
SBIT(GSM48_RR_ST_DEDICATED), /* 3.4.13.3 */
GSM48_RR_ABORT_REQ, gsm48_rr_abort_req},
#if 0
{SBIT(GSM48_RR_ST_DEDICATED),
GSM48_RR_ACT_REQ, gsm48_rr_act_req},
#endif
@ -3440,7 +3550,6 @@ queue messages (rslms_data_req) if channel changes
flush rach msg in all cases: during sending, after its done, and when aborted
stop timers on abort
debugging. (wenn dies todo erledigt ist, bitte in den anderen code moven)
wird beim abbruch immer der gepufferte cm-service-request entfernt, auch beim verschicken?:
measurement reports
todo rr_sync_ind when receiving ciph, re ass, channel mode modify
@ -3456,25 +3565,6 @@ they queue must be flushed when rr fails
#include <osmocore/utils.h>
#include <osmocore/gsm48.h>
static int gsm48_rr_abort_req(struct osmocom_ms *ms, struct gsm48_rr *rrmsg)
{
struct gsm48_rrlayer *rr = ms->rrlayer;
uint8_t *mode;
stop_rr_t3126(rr);
if (rr->state == GSM48_RR_ST_DEDICATED) {
/* release message */
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);
}
new_rr_state(rr, GSM48_RR_ST_IDLE);
}
static int gsm48_rr_act_req(struct osmocom_ms *ms, struct gsm48_rr *rrmsg)
{
}
@ -3741,31 +3831,6 @@ static int gsm48_rr_rel_ind(struct osmocom_ms *ms, struct msgb *msg)
{
}
static int gsm48_rr_rel_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = ms->rrlayer;
struct msgb *nmsg;
if (rr->hando_susp_state || rr->assign_susp_state) {
struct msgb *msg;
/* change radio to new channel */
tx_ph_dm_est_req(ms, rr->cd_now.arfcn, rr->cd_now.chan_nr);
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
/* send DL-ESTABLISH REQUEST */
gsm48_send_rsl(ms, RSL_MT_EST_REQ, nmsg);
}
if (rr->hando_susp_state) {
gsm48_rr_tx_hando_access(ms);
rr->hando_acc_left = 3;
}
return 0;
}
static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = ms->rrlayer;