*
*/
+/* Very short description of some of the procedures:
+ *
+ * A radio ressource request causes sendig a channel request on RACH.
+ * After receiving of an immediate assignment the link will be establised.
+ * After the link is established, the dedicated mode is entered and confirmed.
+ *
+ * A Paging request also triggers the channel request as above...
+ * After the link is established, the dedicated mode is entered and indicated.
+ *
+ * During dedicated mode, messages are transferred.
+ *
+ * When an assignment command or a handover command is received, the current
+ * link is released. After release, the new channel is activated and the
+ * link is established again. After link is establised, pending messages from
+ * radio ressource are sent.
+ *
+ * When the assignment or handover fails, the old channel is activate and the
+ * link is established again. Also pending messages are sent.
+ *
+ */
+
/*
* state transition
*/
rr->state = state;
}
+/*
+ * messages
+ */
+
+/* allocate GSM 04.08 radio ressource message (RR to L2) */
+static struct msgb *gsm48_rr_msgb_alloc(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_alloc_headroom(GSM48_RR_ALLOC_SIZE, GSM48_RR_ALLOC_HEADROOM,
+ "GSM 04.08 RR");
+ if (!msg)
+ return NULL;
+
+ return msg;
+}
+
+/* queue message L2 -> RR */
+int gsm48_rr_upmsg(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm_rrlayer *rr = ms->rrlayer;
+
+ msgb_enqueue(&rr->up_queue, msg);
+}
+
/*
* timers handling
*/
mmh = (struct gsm_mm_hdr *)msg->data;
mmh->msg_type RR_REL_IND;
mmh->cause = GSM_MM_CAUSE_RA_FAILURE;
- rr_rcvmsg(ms, msg);
+ gsm48_mm_upmsg(ms, msg);
}
new_rr_state(rr, GSM_RRSTATE_IDLE);
static int gsm_rr_tx_rr_status(struct osmocom_ms *ms, uint8_t cause)
{
struct gsm_rrlayer *rr = ms->rrlayer;
- struct msgb *msg = gsm48_rr_msgb_alloc();
+ struct msgb *msg;
struct gsm48_hdr *gh;
struct gsm48_rr_status *st;
+ msg = gsm48_rr_msgb_alloc();
if (!msg)
return -ENOMEM;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
{
struct gsm_rrlayer *rr = ms->rrlayer;
struct gsm_subscriber *subcr = ms->subscr;
- struct msgb *msg = gsm48_rr_msgb_alloc();
+ struct msgb *msg;
struct gsm48_hdr *gh;
u_int8_t buf[11], *ie;
+ msg = gsm48_rr_msgb_alloc();
if (!msg)
return -ENOMEM;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
{
struct gsm_rrlayer *rr = ms->rrlayer;
struct gsm_support *sup = ms->support;
- struct msgb *msg = gsm48_rr_msgb_alloc();
+ struct msgb *msg;
struct gsm48_hdr *gh;
struct gsm48_cm_change *cc;
int len;
uint8_t buf[14];
+ msg = gsm48_rr_msgb_alloc();
if (!msg)
return -ENOMEM;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
mmh = (struct gsm_mm_hdr *)msg->data;
mmh->msg_type RR_REL_IND;
mmh->cause = GSM_MM_CAUSE_UNDEFINED;
- rr_rcvmsg(ms, msg);
+ gsm48_mm_upmsg(ms, msg);
new_rr_state(rr, GSM_RRSTATE_IDLE);
return -EINVAL;
}
static int gsm_rr_rand_acc_cnf(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm_rrlayer *rr = ms->rrlayer;
- struct msgb *newmsg;
+ struct msgb *nmsg;
int s;
if (!rr->n_chan_req) {
s = 115;
/* resend chan_req */
- newmsg = msgb_alloc_headroom(20, 16, "CHAN_REQ");
- if (!newmsg)
+ nmsg = msgb_alloc_headroom(20, 16, "CHAN_REQ");
+ if (!nmsg)
return -ENOMEM;
- *msgb_put(newmsg, 1) = rr->chan_req;
- *msgb_put(newmsg, 1) = (random() % ms->si.tx_integer) + s; /* delay */
+ *msgb_put(nmsg, 1) = rr->chan_req;
+ *msgb_put(nmsg, 1) = (random() % ms->si.tx_integer) + s; /* delay */
rr->cr_hist[3] = rr->cr_hist[2];
rr->cr_hist[2] = rr->cr_hist[1];
rr->cr_hist[1] = chan_req;
- return rslms_tx_rll_req_l3(ms, RSL_MT_RAND_ACC_REQ, chan_nr, 0, newmsg);
+ return rslms_tx_rll_req_l3(ms, RSL_MT_RAND_ACC_REQ, chan_nr, 0, nmsg);
}
/*
struct gsm48_system_information_type_1 *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 1 message.\n");
if (payload_len)
gsm48_decode_si1_rest(si->rest_octets, payload_len);
+ si->si1 = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_2 *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 2 message.\n");
/* RACH Control Parameter */
gsm48_decode_rach_ctl_neigh(s, si->rach_control);
+ si->si2 = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_2bis *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 2bis message.\n");
/* RACH Control Parameter */
gsm48_decode_rach_ctl_neigh(s, si->rach_control);
+ si->si2bis = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_2ter *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 2ter message.\n");
gsm48_decode_freq_list(s->freq, si->ext_bcch_frequency_list,
sizeof(si->ext_bcch_frequency_list), 0x8e, FREQ_TYPE_NCELL_2ter);
+ si->si2ter = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_3 *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 3 message.\n");
/* Cell Identity */
s->cell_identity = ntohl(si->cell_identity);
/* LAI */
- gsm48_decode_lai(si->lai, s->mcc, s->mnc, s->lac);
+ gsm48_decode_lai(si->lai, &s->mcc, &s->mnc, &s->lac);
/* Control Channel Description */
gsm48_decode_ccd(s, si->control_channel_desc);
/* Cell Options (BCCH) */
if (payload_len >= 4)
gsm48_decode_si3_rest(si->rest_octets, payload_len);
+ si->si3 = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
uint8_t *data = si->data;
+ struct msgb *nmsg;
todo: si has different header in structures
if (payload_len < 0) {
return -EINVAL;
}
/* LAI */
- gsm48_decode_lai(si->lai, s->mcc, s->mnc, s->lac);
+ gsm48_decode_lai(si->lai, &s->mcc, &s->mnc, &s->lac);
/* Cell Selection Parameters */
gsm48_decode_cell_sel_param(s, si->cell_sel_par);
/* RACH Control Parameter */
if (payload_len > 0)
gsm48_decode_si3_rest(data, payload_len);
+ si->si4 = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_5 *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 5 message.\n");
gsm48_decode_freq_list(s->freq, si->bcch_frequency_list,
sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_REP_5);
+ si->si5 = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_5bis *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 5bis message.\n");
gsm48_decode_freq_list(s->freq, si->bcch_frequency_list,
sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_REP_5bis);
+ si->si5bis = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_5ter *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 5ter message.\n");
gsm48_decode_freq_list(s->freq, si->bcch_frequency_list,
sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_REP_5ter);
+ si->si5ter = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
struct gsm48_system_information_type_6 *si = msgb_l3(msg);
struct gsm48_sysinfo *s = ms->sysinfo;
int payload_len = msgb_l3len(msg) - sizeof(*si);
+ struct msgb *nmsg;
if (payload_len < 0) {
DEBUGP(DRR, "Short read of SYSTEM INFORMATION 6 message.\n");
/* Cell Identity */
s->cell_identity = ntohl(si->cell_identity);
/* LAI */
- gsm48_decode_lai(si->lai, s->mcc, s->mnc, s->lac);
+ gsm48_decode_lai(si->lai, &s->mcc, &s->mnc, &s->lac);
/* Cell Options (SACCH) */
gsm48_decode_cellopt_sacch(s, si->control_channel_desc);
/* NCC Permitted */
if (payload_len >= 4)
gsm48_decode_si6_rest(si->rest_octets, payload_len);
+ si->si6 = 1;
+
+ nmsg = gsm58_msgb_alloc(GSM58_EVENT_SYSINFO);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_sendmsg(ms, nmsg);
+
return 0;
}
static int gsm_match_mi(struct osmocom_ms *ms, u_int8_t mi)
{
char imsi[16];
- u_int32_t tmsi;
+ uint32_t tmsi;
if (mi[0] < 1)
return 0;
struct gsm_rrlayer *rr = ms->rrlayer;
struct gsm48_rr_paging2 *pa = msgb_l3(msg);
int payload_len = msgb_l3len(msg) - sizeof(*pa);
- u_int32_t tmsi;
+ uint32_t tmsi;
int chan_first, chan_second, chan_third;
/* 3.3.1.1.2: ignore paging while establishing */
struct gsm_rrlayer *rr = ms->rrlayer;
struct gsm48_rr_paging3 *pa = msgb_l3(msg);
int payload_len = msgb_l3len(msg) - sizeof(*pa);
- u_int32_t tmsi;
+ uint32_t tmsi;
int chan_first, chan_second, chan_third, chan_fourth;
/* 3.3.1.1.2: ignore paging while establishing */
static int gsm_rr_tx_ass_cpl(struct osmocom_ms *ms, uint8_t cause)
{
struct gsm_rrlayer *rr = ms->rrlayer;
- struct msgb *msg = gsm48_rr_msgb_alloc();
+ struct msgb *msg;
struct gsm48_hdr *gh;
struct gsm48_ass_cpl *ac;
+ msg = gsm48_rr_msgb_alloc();
if (!msg)
return -ENOMEM;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
static int gsm_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause)
{
struct gsm_rrlayer *rr = ms->rrlayer;
- struct msgb *msg = gsm48_rr_msgb_alloc();
+ struct msgb *msg;
struct gsm48_hdr *gh;
struct gsm48_ass_fail *ac;
+ msg = gsm48_rr_msgb_alloc();
if (!msg)
return -ENOMEM;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
/* request ref */
if (gsm_match_ra(ms, ia->req_ref)) {
/* channel description */
+todo channel structure and right management of channel IEs
memset(&rr->chan_desc, 0, sizeof(cd));
- memcpy(rr->chan_desc.chan_desc, ia->chan_desc, 3);
/* timing advance */
rr->timing_advance = ia->timing_advance;
/* mobile allocation */
{
struct gsm_rrlayer *rr = ms->rrlayer;
struct gsm_rr_meas *meas = &rr->meas;
- struct msgb *msg = gsm48_rr_msgb_alloc();
+ struct msgb *msg;
struct gsm48_hdr *gh;
struct gsm48_meas_res *mr;
+ msg = gsm48_rr_msgb_alloc();
if (!msg)
return -ENOMEM;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
/* the link is established */
static int gsm_rr_estab_cnf(struct osmocom_ms *ms, struct msgb *msg)
{
- struct msgb *newmsg;
- struct gsm_mm_hdr *newmmh;
+ struct msgb *nmsg;
+ struct gsm_mm_hdr *nmmh;
/* if MM has releases before confirm, we start release */
if (rr->state == GSM_RRSTATE_IDLE) {
/* release message */
- newmsg = gsm48_rr_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_rr_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
/* start release */
- return rslms_tx_rll_req_l3(ms, RSL_MT_REL_REQ, 0, 0, newmsg);
+ return rslms_tx_rll_req_l3(ms, RSL_MT_REL_REQ, 0, 0, nmsg);
}
/* 3.3.1.1.4 */
new_rr_state(rr, GSM_RRSTATE_DEDICATED);
/* send confirm to upper layer */
- newmsg = gsm48_mm_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_mm_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
- newmmh = (struct gsm_mm_hdr *)newmsg->data;
- newmmh->msg_type = (rr->rr_est_req) ? RR_EST_CNF : RR_EST_IND;
- return rr_rcvmsg(ms, newmsg);
+ nmmh = (struct gsm_mm_hdr *)nmsg->data;
+ nmmh->msg_type = (rr->rr_est_req) ? RR_EST_CNF : RR_EST_IND;
+ return gsm48_mm_upmsg(ms, nmsg);
}
/* the link is released */
/* 3.3.1.1.3.2 */
if (timer_pending(rr->t3122)) {
if (rrmsg->cause != RR_EST_CAUSE_EMERGENCY) {
- struct msgb *newmsg;
- struct gsm_mm_hdr *newmmh;
+ struct msgb *nmsg;
+ struct gsm_mm_hdr *nmmh;
- newmsg = gsm48_mm_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_mm_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
- newmmh = (struct gsm_mm_hdr *)newmsg->data;
- newmmh->msg_type RR_REL_IND;
- newmmh->cause = GSM_MM_CAUSE_T3122_PEND;
- return rr_rcvmsg(ms, newmsg);
+ nmmh = (struct gsm_mm_hdr *)nmsg->data;
+ nmmh->msg_type RR_REL_IND;
+ nmmh->cause = GSM_MM_CAUSE_T3122_PEND;
+ return gsm48_mm_upmsg(ms, nmsg);
} else
stop_rr_t3122(rr);
}
if (!(ms->access_class & ms->si.access_class)) {
reject:
if (!ms->opt.access_class_override) {
- struct msgb *newmsg;
- struct gsm_mm_hdr *newmmh;
+ struct msgb *nmsg;
+ struct gsm_mm_hdr *nmmh;
- newmsg = gsm48_mm_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_mm_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
- newmmh = (struct gsm_mm_hdr *)newmsg->data;
- newmmh->msg_type RR_REL_IND;
- newmmh->cause = GSM_MM_CAUSE_NOT_AUTHORIZED;
- return rr_rcvmsg(ms, newmsg);
+ nmmh = (struct gsm_mm_hdr *)nmsg->data;
+ nmmh->msg_type RR_REL_IND;
+ nmmh->cause = GSM_MM_CAUSE_NOT_AUTHORIZED;
+ return gsm48_mm_upmsg(ms, nmsg);
}
}
} else {
}
/* push header */
- msgb_push(msg, sizeof(struct gsm_mm_hdr));
- mmh = (struct gsm_mm_hdr *)msg->data;
+ msgb_push(msg, sizeof(struct gsm48_mm_hdr));
+ mmh = (struct gsm48_mm_hdr *)msg->data;
mmh->msg_type = RR_DATA_IND;
- /* forward message */
- return rr_rcvmsg(ms, msg);
+
+ return gsm48_mm_upmsg(ms, msg);
}
/* unit data from layer 2 to RR layer */
-complete
--------------------------------------------------------------------------------
-uncomplete
-
+the process above is complete
+------------------------------------------------------------------------------
+incomplete
#include <osmocore/protocol/gsm_04_08.h>
#include <osmocore/msgb.h>
+#include <osmocore/utils.h>
#include <osmocore/gsm48.h>
-static struct rr_names {
- char *name;
- int value;
-} rr_names[] = {
- { "RR_EST_REQ", RR_EST_REQ },
- { "RR_EST_IND", RR_EST_IND },
- { "RR_EST_CNF", RR_EST_CNF },
- { "RR_REL_IND", RR_REL_IND },
- { "RR_SYNC_IND", RR_SYNC_IND },
- { "RR_DATA_REQ", RR_DATA_REQ },
- { "RR_DATA_IND", RR_DATA_IND },
- { "RR_UNIT_DATA_IND", RR_UNIT_DATA_IND },
- { "RR_ABORT_REQ", RR_ABORT_REQ },
- { "RR_ABORT_IND", RR_ABORT_IND },
- { "RR_ACT_REQ", RR_ACT_REQ },
-
- {NULL, 0}
+static const struct value_string rr_names[] = {
+ { RR_EST_REQ, "RR_EST_REQ" },
+ { RR_EST_IND, "RR_EST_IND" },
+ { RR_EST_CNF, "RR_EST_CNF" },
+ { RR_REL_IND, "RR_REL_IND" },
+ { RR_SYNC_IND, "RR_SYNC_IND" },
+ { RR_DATA_REQ, "RR_DATA_REQ" },
+ { RR_DATA_IND, "RR_DATA_IND" },
+ { RR_UNIT_DATA_IND, "RR_UNIT_DATA_IND" },
+ { RR_ABORT_REQ, "RR_ABORT_REQ" },
+ { RR_ABORT_IND, "RR_ABORT_IND" },
+ { RR_ACT_REQ, "RR_ACT_REQ" },
+ { 0, NULL }
};
-char *get_rr_name(int value)
+const char *get_rr_name(int value)
{
- int i;
-
- for (i = 0; rr_names[i].name; i++) {
- if (rr_names[i].value == value)
- return rr_names[i].name;
- }
-
- return "RR_Unknown";
+ return get_value_string(rr_names, value);
}
-static int rr_rcvmsg(struct osmocom_ms *ms,
+move to mm
+static int gsm48_mm_upmsg(struct osmocom_ms *ms,
int msg_type, struct gsm_mncc *rrmsg)
{
struct msgb *msg;
+#if 0
DEBUGP(DRR, "(MS %s) Sending '%s' to MM.\n", ms->name,
get_rr_name(msg_type));
+#endif
rrmsg->msg_type = msg_type;
/* state trasitions for radio ressource messages (upper layer) */
static struct rrdownstate {
- u_int32_t states;
+ uint32_t states;
int type;
int (*rout) (struct osmocom_ms *ms, struct gsm_dl *rrmsg);
} rrdownstatelist[] = {
#define RRDOWNSLLEN \
(sizeof(rrdownstatelist) / sizeof(struct rrdownstate))
-static int gsm_send_rr(struct osmocom_ms *ms, struct gsm_rr *msg)
+static int gsm48_rr_sendmsg(struct osmocom_ms *ms, struct gsm_rr *msg)
{
struct gsm_mm_hdr *mmh = msgb->data;
int msg_type = mmh->msg_type;
DEBUGP(DRR, "(ms %s) Sending '%s' to DL in state %s\n", ms->name,
- gsm0408_rr_msg_names[msg_type], mm_state_names[mm->state]);
+ gsm48_rr_msg_name(msg_type), mm_state_names[mm->state]);
/* find function for current state and message */
for (i = 0; i < RRDOWNSLLEN; i++)
break;
if (i == RRDOWNSLLEN) {
DEBUGP(DRR, "Message unhandled at this state.\n");
+ free_msgb(msg);
+todo: in all functions of this type: free_msgb must be called if unhandled.
return 0;
}
memcpy(&rr->chan_desc, cd, sizeof(cd));
/* start suspension of current link */
- newmsg = gsm48_rr_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_rr_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
rslms_tx_rll_req_l3(ms, RSL_MT_SUSP_REQ, rr->chan_desc.chan_nr, 0, msg);
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)
+{
+ *arfcn = (cd->bcch_hi << 8) + cd->bcch_lo;
+ *ncc = cd->ncc;
+ *bcc = cd->bcc;
+}
+
+/* decode "Power Command" (10.5.2.28) and (10.5.2.28a) */
+static int gsm48_decode_power_cmd_acc(struct gsm48_power_cmd *pc, uint8_t *power_level uint8_t *atc)
+{
+ *power_level = pc->power_level;
+ if (atc) /* only in case of 10.5.2.28a */
+ *atc = pc->atc;
+}
+
+/* decode "Synchronization Indication" (10.5.2.39) */
+static int gsm48_decode_power_cmd_acc(struct gsm_rrlayer *rr, struct gsm_rr_sync_ind *si)
+{
+ rr->ho_sync_ind = si->si;
+ rr->ho_rot = si->rot;
+ rr->ho_nci = si->nci;
+}
+
/* receiving HANDOVER COMMAND message (9.1.15) */
static int gsm_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
{
}
tlv_parse(&tp, &rsl_att_tlvdef, ho->data, payload_len, 0, 0);
-
-
+ /* decode Cell Description */
+ gsm_decode_cell_desc(&ho->cell_desc, &cd.bcch_arfcn, &cd.ncc, &cd.bcc);
+ /* Channel Description */
+ memcpy(&rr->chan_desc.chan_desc, ho->chan_desc, 3);
+ /* Handover Reference */
+ rr->hando_ref = ho->ho_ref;
+ /* Power Command and access type */
+ gsm_decode_power_cmd_acc((struct gsm48_power_cmd *)&ho->power_command,
+ &cd.power_level, cd.atc);
+ /* Synchronization Indication */
+ if (TLVP_PRESENT(&tp, GSM48_IE_SYNC_IND))
+ gsm48_decode_sync_ind(rr,
+ TLVP_VAL(&tp, GSM48_IE_MOBILE_ALLOC)-1, &cd);
+ /* Frequency Sort List */
+ if (TLVP_PRESENT(&tp, GSM48_IE_FREQ_SHORT_LIST))
+ gsm48_decode_freq_list(s->freq,
+ TLVP_VAL(&tp, GSM48_IE_MOBILE_ALLOC),
+ *(TLVP_VAL(&tp, GSM48_IE_MOBILE_ALLOC)-1),
+ 0xce, FREQ_TYPE_SERV);
today: more IE parsing
memcpy(&rr->chan_desc, cd, sizeof(cd));
/* start suspension of current link */
- newmsg = gsm48_rr_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_rr_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
rslms_tx_rll_req_l3(ms, RSL_MT_SUSP_REQ, rr->chan_desc.chan_nr, 0, msg);
/* change radio to new channel */
tx_ph_dm_est_req(ms, arfcn, rr->chan_desc.chan_desc.chan_nr);
- newmsg = gsm48_rr_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_rr_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
/* send DL-ESTABLISH REQUEST */
- rslms_tx_rll_req_l3(ms, RSL_MT_EST_REQ, rr->chan_desc.chan_desc.chan_nr, 0, newmsg);
+ rslms_tx_rll_req_l3(ms, RSL_MT_EST_REQ, rr->chan_desc.chan_desc.chan_nr, 0, nmsg);
}
if (rr->hando_susp_state) {
static int gsm_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm_rrlayer *rr = ms->rrlayer;
- struct msgb *newmsg;
- struct gsm_mm_hdr *newmmh;
+ struct msgb *nmsg;
+ struct gsm_mm_hdr *nmmh;
if (rr->hando_susp_state || rr->assign_susp_state) {
if (!rr->resume_last_state) {
tx_ph_dm_est_req(ms, arfcn, rr->chan_desc.chan_desc.chan_nr);
/* re-establish old link */
- newmsg = gsm48_rr_msgb_alloc();
- if (!newmsg)
+ nmsg = gsm48_rr_msgb_alloc();
+ if (!nmsg)
return -ENOMEM;
- return rslms_tx_rll_req_l3(ms, RSL_MT_EST_REQ, rr->chan_desc.chan_desc.chan_nr, 0, newmsg);
+ return rslms_tx_rll_req_l3(ms, RSL_MT_EST_REQ, rr->chan_desc.chan_desc.chan_nr, 0, nmsg);
}
rr->resume_last_state = 0;
}
tx_ph_dm_rel_req(ms, arfcn, rr->chan_desc.chan_desc.chan_nr);
/* send abort ind to upper layer */
- newmsg = gsm48_mm_msgb_alloc();
+ nmsg = gsm48_mm_msgb_alloc();
if (!msg)
return -ENOMEM;
- newmmh = (struct gsm_mm_hdr *)newmsg->data;
- newmmh->msg_type = RR_ABORT_IND;
- newmmh->cause = GSM_MM_CAUSE_LINK_FAILURE;
- return rr_rcvmsg(ms, msg);
+ nmmh = (struct gsm_mm_hdr *)nmsg->data;
+ nmmh->msg_type = RR_ABORT_IND;
+ nmmh->cause = GSM_MM_CAUSE_LINK_FAILURE;
+ return gsm48_mm_upmsg(ms, msg);
}
/* state trasitions for link layer messages (lower layer) */
static struct dldatastate {
- u_int32_t states;
+ uint32_t states;
int type;
int (*rout) (struct osmocom_ms *ms, struct gsm_dl *dlmsg);
} dldatastatelist[] = {
#define DLDATASLLEN \
(sizeof(dldatastatelist) / sizeof(struct dldatastate))
-static int gsm_rcv_dl(struct osmocom_ms *ms, struct gsm_dl *dlmsg)
+static int gsm48_rcv_dl(struct osmocom_ms *ms, struct gsm_dl *dlmsg)
{
int msg_type = dlmsg->msg_type;
DEBUGP(DRR, "(ms %s) Received '%s' from DL in state %s\n", ms->name,
- gsm0408_dl_msg_names[msg_type], mm_state_names[mm->state]);
+ gsm48_dl_msg_name(msg_type), mm_state_names[mm->state]);
/* find function for current state and message */
for (i = 0; i < DLDATASLLEN; i++)
break;
if (i == DLDATASLLEN) {
DEBUGP(DRR, "Message unhandled at this state.\n");
+ free_msgb(msg);
return 0;
}
return rc;
}
+/* dequeue messages from dl */
+int gsm48_rr_queue(struct osmocom_ms *ms)
+{
+ struct gsm_rrlayer *rr = ms->rrlayer;
+ struct msgb *msg;
+ int work = 0;
+
+ while ((msg = msgb_dequeue(&rr->up_queue))) {
+ /* msg is freed there */
+ gsm48_rcv_dl(ms, msg);
+ work = 1; /* work done */
+ }
+
+ return work;
+}
+
static void timeout_rr_t3124(void *arg)
{
struct gsm_rrlayer *rr = arg;
return NULL;
rr->ms = ms;
- init queues
-
- init timers
+ INIT_LLIST_HEAD(&rr->up_queue);
return;
}
/* send HANDOVER ACCESS burst (9.1.14) */
static int gsm_rr_tx_hando_access(struct osmocom_ms *ms)
{
- newmsg = msgb_alloc_headroom(20, 16, "HAND_ACCESS");
- if (!newmsg)
+ nmsg = msgb_alloc_headroom(20, 16, "HAND_ACCESS");
+ if (!nmsg)
return -ENOMEM;
- *msgb_put(newmsg, 1) = rr->hando_ref;
- return rslms_tx_rll_req_l3(ms, RSL_MT_RAND_ACC_REQ, chan_nr, 0, newmsg);
+ *msgb_put(nmsg, 1) = rr->hando_ref;
+ return rslms_tx_rll_req_l3(ms, RSL_MT_RAND_ACC_REQ, chan_nr, 0, nmsg);
}
+
/* send next channel request in dedicated state */
static int gsm_rr_rand_acc_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm_rrlayer *rr = ms->rrlayer;
- struct msgb *newmsg;
+ struct msgb *nmsg;
int s;
if (!rr->hando_susp_state) {