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...
This commit is contained in:
parent
78f6fb7713
commit
247ec7acf3
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
/* release */
|
||||
{SBIT(GSM48_RR_ST_DEDICATED),
|
||||
RSL_MT_REL_IND, gsm48_rr_rel_ind},
|
||||
|
||||
{SBIT(GSM48_RR_ST_REL_PEND),
|
||||
RSL_MT_REL_CONF, gsm48_rr_rel_cnf},
|
||||
|
||||
{SBIT(GSM48_RR_ST_DEDICATED),
|
||||
RSL_MT_REL_CONF, gsm48_rr_rel_cnf_dedicated},
|
||||
|
||||
/* 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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue