summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/host/layer23/include/osmocom/gsm48_rr.h15
-rw-r--r--src/host/layer23/include/osmocom/lapdm.h6
-rw-r--r--src/host/layer23/include/osmocom/osmocom_data.h6
-rw-r--r--src/host/layer23/include/osmocom/settings.h7
-rw-r--r--src/host/layer23/include/osmocom/support.h1
-rw-r--r--src/host/layer23/src/gsm322.c63
-rw-r--r--src/host/layer23/src/gsm48_rr.c352
-rw-r--r--src/host/layer23/src/lapdm.c139
8 files changed, 433 insertions, 156 deletions
diff --git a/src/host/layer23/include/osmocom/gsm48_rr.h b/src/host/layer23/include/osmocom/gsm48_rr.h
index 74ccb27..16ba2fe 100644
--- a/src/host/layer23/include/osmocom/gsm48_rr.h
+++ b/src/host/layer23/include/osmocom/gsm48_rr.h
@@ -42,6 +42,9 @@
#define L3_ALLOC_SIZE 256
#define L3_ALLOC_HEADROOM 64
+#define RSL_ALLOC_SIZE 256
+#define RSL_ALLOC_HEADROOM 64
+
#define RR_ALLOC_SIZE 256
#define RR_ALLOC_HEADROOM 64
@@ -88,9 +91,8 @@ struct gsm48_rr_meas {
};
struct gsm48_cr_hist {
- uint32_t fn;
- uint8_t chan_req;
- uint8_t valid;
+ uint8_t valid;
+ struct gsm48_req_ref ref;
};
/* RR sublayer instance */
@@ -123,9 +125,10 @@ struct gsm48_rrlayer {
uint8_t wait_assign; /* waiting for assignment state */
uint8_t n_chan_req; /* number left, incl. current */
uint8_t chan_req_val; /* current request value */
- uint8_t chan_req_mask; /* mask of random bits */
+ uint8_t chan_req_mask; /* mask of random bits */
- /* cr_hist must be signed and greater 8 bit, -1 = no value */
+ /* cr_hist */
+ uint8_t cr_ra; /* stores requested ra until confirmed */
struct gsm48_cr_hist cr_hist[3];
/* current channel descriptions */
@@ -143,6 +146,8 @@ struct gsm48_rrlayer {
/* measurements */
struct gsm48_rr_meas meas;
+ uint8_t ind_tx_power; /* last indicated power */
+ uint8_t ind_ta; /* last indicated ta */
/* BA range */
uint8_t ba_ranges;
diff --git a/src/host/layer23/include/osmocom/lapdm.h b/src/host/layer23/include/osmocom/lapdm.h
index 06ac5f8..ab048b8 100644
--- a/src/host/layer23/include/osmocom/lapdm.h
+++ b/src/host/layer23/include/osmocom/lapdm.h
@@ -28,6 +28,8 @@ struct lapdm_msg_ctx {
uint8_t link_id;
uint8_t addr;
uint8_t ctrl;
+ uint8_t ta_ind;
+ uint8_t tx_power_ind;
};
/* TS 04.06 / Section 3.5.2 */
@@ -80,6 +82,10 @@ void lapdm_exit(struct lapdm_entity *le);
int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1ctl_info_dl *l1i);
int l2_ph_data_conf(struct msgb *msg, struct lapdm_entity *le);
+/* L1 confirms channel request */
+int l2_ph_chan_conf(struct msgb *msg, struct osmocom_ms *ms,
+ struct l1ctl_info_dl *dl);
+
/* input into layer2 (from layer 3) */
int rslms_recvmsg(struct msgb *msg, struct osmocom_ms *ms);
diff --git a/src/host/layer23/include/osmocom/osmocom_data.h b/src/host/layer23/include/osmocom/osmocom_data.h
index e4430fc..1be19a3 100644
--- a/src/host/layer23/include/osmocom/osmocom_data.h
+++ b/src/host/layer23/include/osmocom/osmocom_data.h
@@ -57,7 +57,6 @@ enum osmobb_meas_sig {
S_L1CTL_RESET,
S_L1CTL_PM_RES,
S_L1CTL_PM_DONE,
- S_L1CTL_RACH_CONF,
S_L1CTL_CCCH_MODE_CONF,
};
@@ -67,11 +66,6 @@ struct osmobb_meas_res {
uint8_t rx_lev;
};
-struct osmobb_rach_conf {
- struct osmocom_ms *ms;
- uint32_t fn;
-};
-
struct osmobb_ccch_mode_conf {
struct osmocom_ms *ms;
uint8_t ccch_mode;
diff --git a/src/host/layer23/include/osmocom/settings.h b/src/host/layer23/include/osmocom/settings.h
index 95c53a8..e44ee3f 100644
--- a/src/host/layer23/include/osmocom/settings.h
+++ b/src/host/layer23/include/osmocom/settings.h
@@ -24,6 +24,13 @@ struct gsm_settings {
/* call related settings */
uint8_t cw; /* set if call-waiting is allowed */
uint8_t clip, clir;
+
+ /* changing default behavior */
+ uint8_t alter_tx_power;
+ uint8_t alter_tx_power_value;
+ int8_t alter_delay;
+ uint8_t stick;
+ uint16_t stick_arfcn;
};
int gsm_settings_init(struct osmocom_ms *ms);
diff --git a/src/host/layer23/include/osmocom/support.h b/src/host/layer23/include/osmocom/support.h
index ad1ccd7..9af4d1b 100644
--- a/src/host/layer23/include/osmocom/support.h
+++ b/src/host/layer23/include/osmocom/support.h
@@ -86,6 +86,7 @@ struct gsm_support_scan_max {
extern struct gsm_support_scan_max gsm_sup_smax[];
void gsm_support_init(struct osmocom_ms *ms);
+int gsm_support_txpwr(uint8_t tx_power, uint16_t arfcn);
void gsm_support_dump(struct gsm_support *sup,
void (*print)(void *, const char *, ...), void *priv);
diff --git a/src/host/layer23/src/gsm322.c b/src/host/layer23/src/gsm322.c
index 6cbba03..fcc85a7 100644
--- a/src/host/layer23/src/gsm322.c
+++ b/src/host/layer23/src/gsm322.c
@@ -239,7 +239,7 @@ static int gsm322_sync_to_cell(struct gsm322_cellsel *cs)
}
// printf("s->ccch_conf %d\n", cs->si->ccch_conf);
-// l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_FULL);
return l1ctl_tx_fbsb_req(ms, cs->arfcn,
L1CTL_FBSB_F_FB01SB, 100, 0,
cs->ccch_mode);
@@ -2022,17 +2022,19 @@ static int gsm322_store_ba_list(struct gsm322_cellsel *cs,
/* process system information during camping on a cell */
static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
{
- struct gsm48_rrlayer *rr = &ms->rrlayer;
+// struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s = cs->si;
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm322_msg *gm = (struct gsm322_msg *) msg->data;
struct msgb *nmsg;
+#if 0
if (rr->state != GSM48_RR_ST_IDLE) {
LOGP(DCS, LOGL_INFO, "Ignoring in dedicated mode.\n");
return -EBUSY;
}
+#endif
/* Store BA if we have full system info about cells and neigbor cells.
* Depending on the extended bit in the channel description,
@@ -2210,25 +2212,37 @@ static void gsm322_cs_timeout(void *arg)
static int gsm322_cs_powerscan(struct osmocom_ms *ms)
{
struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm_settings *set = &ms->settings;
int i, s = -1, e;
uint8_t mask, flags;
again:
- /* search for first frequency to scan */
mask = GSM322_CS_FLAG_SUPPORT | GSM322_CS_FLAG_POWER;
flags = GSM322_CS_FLAG_SUPPORT;
- if (cs->state == GSM322_C2_STORED_CELL_SEL
- || cs->state == GSM322_C5_CHOOSE_CELL) {
- LOGP(DCS, LOGL_FATAL, "Scanning power for stored BA list.\n");
- mask |= GSM322_CS_FLAG_BA;
- flags |= GSM322_CS_FLAG_BA;
- } else
- LOGP(DCS, LOGL_FATAL, "Scanning power for all frequencies.\n");
- for (i = 0; i <= 1023; i++) {
- if ((cs->list[i].flags & mask) == flags) {
+
+ /* in case of sticking to a cell, we only select it */
+ if (set->stick) {
+ LOGP(DCS, LOGL_FATAL, "Scanning power for sticked cell.\n");
+ i = set->stick_arfcn;
+ if ((cs->list[i].flags & mask) == flags)
s = e = i;
- break;
+ } else {
+ /* search for first frequency to scan */
+ if (cs->state == GSM322_C2_STORED_CELL_SEL
+ || cs->state == GSM322_C5_CHOOSE_CELL) {
+ LOGP(DCS, LOGL_FATAL, "Scanning power for stored BA "
+ "list.\n");
+ mask |= GSM322_CS_FLAG_BA;
+ flags |= GSM322_CS_FLAG_BA;
+ } else
+ LOGP(DCS, LOGL_FATAL, "Scanning power for all "
+ "frequencies.\n");
+ for (i = 0; i <= 1023; i++) {
+ if ((cs->list[i].flags & mask) == flags) {
+ s = e = i;
+ break;
+ }
}
}
@@ -2312,11 +2326,13 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
/* search last frequency to scan (en block) */
e = i;
- for (i = s + 1; i <= 1023; i++) {
- if ((cs->list[i].flags & mask) == flags)
- e = i;
- else
- break;
+ if (!set->stick) {
+ for (i = s + 1; i <= 1023; i++) {
+ if ((cs->list[i].flags & mask) == flags)
+ e = i;
+ else
+ break;
+ }
}
LOGP(DCS, LOGL_INFO, "Scanning frequencies. (%d..%d)\n", s, e);
@@ -2334,7 +2350,6 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
struct osmocom_ms *ms;
struct gsm322_cellsel *cs;
struct osmobb_meas_res *mr;
- struct osmobb_rach_conf *rc;
int i;
int8_t rxlev_db;
@@ -2352,7 +2367,9 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
rxlev_db = mr->rx_lev - 110;
cs->list[i].rxlev_db = rxlev_db;
cs->list[i].flags |= GSM322_CS_FLAG_POWER;
- if (rxlev_db >= ms->support.min_rxlev_db) {
+ /* if minimum level is reached or if we stick to a cell */
+ if (rxlev_db >= ms->support.min_rxlev_db
+ || ms->settings.stick) {
cs->list[i].flags |= GSM322_CS_FLAG_SIGNAL;
LOGP(DCS, LOGL_INFO, "Found signal (frequency %d "
"rxlev %d)\n", i, cs->list[i].rxlev_db);
@@ -2413,13 +2430,7 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
else
gsm322_cs_timeout(cs);
break;
- case S_L1CTL_RACH_CONF:
- rc = signal_data;
- ms = rc->ms;
- gsm48_rr_rach_conf(ms, rc->fn);
- break;
case S_L1CTL_RESET:
- LOGP(DCS, LOGL_INFO, "Reset\n");
break;
}
diff --git a/src/host/layer23/src/gsm48_rr.c b/src/host/layer23/src/gsm48_rr.c
index 2faf38a..92bd2ec 100644
--- a/src/host/layer23/src/gsm48_rr.c
+++ b/src/host/layer23/src/gsm48_rr.c
@@ -206,6 +206,13 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
(sizeof(gsm48_rr_state_names) / sizeof(char *)))
return;
+ /* must check against equal state */
+ if (rr->state == state) {
+ LOGP(DRR, LOGL_INFO, "equal state ? %s\n",
+ gsm48_rr_state_names[rr->state]);
+ return;
+ }
+
LOGP(DRR, LOGL_INFO, "new state %s -> %s\n",
gsm48_rr_state_names[rr->state], gsm48_rr_state_names[state]);
@@ -215,7 +222,7 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
struct msgb *msg, *nmsg;
/* release dedicated mode, if any */
-// tx_ph_dm_rel_req(rr->ms);
+ tx_ph_dm_rel_req(rr->ms);
l1ctl_tx_reset_req(rr->ms, L1CTL_RES_T_FULL);
/* free establish message, if any */
rr->rr_est_req = 0;
@@ -286,6 +293,20 @@ struct msgb *gsm48_l3_msgb_alloc(void)
return msg;
}
+/* allocate GSM 04.06 layer 2 RSL message */
+struct msgb *gsm48_rsl_msgb_alloc(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM,
+ RSL_ALLOC_HEADROOM, "GSM 04.06 RSL");
+ if (!msg)
+ return NULL;
+ msg->l2h = msg->data;
+
+ return msg;
+}
+
/* allocate GSM 04.08 message (RR-SAP) */
struct msgb *gsm48_rr_msgb_alloc(int msg_type)
{
@@ -330,7 +351,7 @@ static int gsm48_send_rsl(struct osmocom_ms *ms, uint8_t msg_type,
}
/* enqueue messages (RSL-SAP) */
-static int gsm48_rx_rll(struct msgb *msg, struct osmocom_ms *ms)
+static int gsm48_rx_rsl(struct msgb *msg, struct osmocom_ms *ms)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
@@ -339,28 +360,6 @@ static int gsm48_rx_rll(struct msgb *msg, struct osmocom_ms *ms)
return 0;
}
-/* input function that L2 calls when sending messages up to L3 */
-static int gsm48_rx_rsl(struct msgb *msg, struct osmocom_ms *ms)
-{
- struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
- int rc = 0;
-
- switch (rslh->msg_discr & 0xfe) {
- case ABIS_RSL_MDISC_RLL:
- rc = gsm48_rx_rll(msg, ms);
- break;
- default:
- /* FIXME: implement this */
- LOGP(DRSL, LOGL_NOTICE, "unknown RSLms msg_discr 0x%02x\n",
- rslh->msg_discr);
- msgb_free(msg);
- rc = -EINVAL;
- break;
- }
-
- return rc;
-}
-
/* dequeue messages (RSL-SAP) */
int gsm48_rsl_dequeue(struct osmocom_ms *ms)
{
@@ -821,33 +820,6 @@ static int gsm48_rr_rx_cm_enq(struct osmocom_ms *ms, struct msgb *msg)
* random access
*/
-/* temporary timer until we have time control over channnel request */
-/* TODO: turn this into a channel activation timeout, later */
-#define RSL_MT_CHAN_CNF 0x19
-#include <osmocom/l1ctl.h>
-int gsm48_rr_rach_conf(struct osmocom_ms *ms, uint32_t fn)
-{
- struct gsm48_rrlayer *rr = &ms->rrlayer;
- struct msgb *msg = msgb_alloc_headroom(23+10, 10, "LAPDm RR");
- struct abis_rsl_rll_hdr *rllh =
- (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rllh));
-
- if (!rr->wait_assign) {
- LOGP(DRR, LOGL_INFO, "RACH confirm ignored, not waiting for "
- "assignment.\n");
- return 0;
- }
- LOGP(DRR, LOGL_INFO, "RACH confirm framenr=%u\n", fn);
- rr->cr_hist[0].valid = 2;
- rr->cr_hist[0].fn = fn;
-
- rllh->c.msg_type = RSL_MT_CHAN_CNF;
- msg->l2h = (unsigned char *)rllh;
- gsm48_rcv_rsl(ms, msg);
-
- return 0;
-}
-
/* start random access */
static int gsm48_rr_chan_req(struct osmocom_ms *ms, int cause, int paging)
{
@@ -889,6 +861,9 @@ static int gsm48_rr_chan_req(struct osmocom_ms *ms, int cause, int paging)
/* 3.3.1.1.2 */
new_rr_state(rr, GSM48_RR_ST_CONN_PEND);
+ /* set assignment state */
+ rr->wait_assign = 0;
+
/* number of retransmissions (with first transmission) */
rr->n_chan_req = s->max_retrans + 1;
@@ -1036,11 +1011,40 @@ int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg)
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s = &ms->cellsel.sel_si;
+ struct gsm_settings *set = &ms->settings;
struct msgb *nmsg;
- struct l1ctl_info_ul *nul;
- struct l1ctl_rach_req *nra;
+ struct abis_rsl_cchan_hdr *ncch;
int slots;
uint8_t chan_req;
+ uint8_t tx_power;
+
+ /* already assigned */
+ if (rr->wait_assign == 2)
+ return 0;
+
+ /* store frame number */
+ if (msg) {
+ struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
+ struct gsm48_req_ref *ref =
+ (struct gsm48_req_ref *) (ch->data + 1);
+
+ if (msgb_l2len(msg) < sizeof(*ch) + sizeof(*ref)) {
+ LOGP(DRR, LOGL_ERROR, "CHAN_CNF too slort\n");
+ return -EINVAL;
+ }
+
+ /* shift history and store */
+ memcpy(&(rr->cr_hist[2]), &(rr->cr_hist[1]),
+ sizeof(struct gsm48_cr_hist));
+ memcpy(&(rr->cr_hist[1]), &(rr->cr_hist[0]),
+ sizeof(struct gsm48_cr_hist));
+ rr->cr_hist[0].valid = 1;
+ rr->cr_hist[0].ref.ra = rr->cr_ra;
+ rr->cr_hist[0].ref.t1 = ref->t1;
+ rr->cr_hist[0].ref.t2 = ref->t2;
+ rr->cr_hist[0].ref.t3_low = ref->t3_low;
+ rr->cr_hist[0].ref.t3_high = ref->t3_high;
+ }
if (cs->ccch_state != GSM322_CCCH_ST_DATA) {
LOGP(DRR, LOGL_INFO, "CCCH channel activation failed.\n");
@@ -1081,7 +1085,7 @@ int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg)
}
rr->n_chan_req--;
- if (!rr->wait_assign) {
+ if (rr->wait_assign == 0) {
/* first random acces, without delay of slots */
slots = 0;
rr->wait_assign = 1;
@@ -1121,47 +1125,62 @@ int gsm48_rr_tx_rand_acc(struct osmocom_ms *ms, struct msgb *msg)
}
}
- /* resend chan_req with new randiom */
-#ifdef TODO
- nmsg = gsm48_rsl_msgb_alloc();
-#else
- nmsg = msgb_alloc_headroom(64, 48, "RAND_ACC");
- struct l1ctl_hdr *l1h;
- nmsg->l1h = msgb_put(nmsg, sizeof(*l1h));
- l1h = (struct l1ctl_hdr *) nmsg->l1h;
- l1h->msg_type = L1CTL_RACH_REQ;
- if (!nmsg)
- return -ENOMEM;
- nul = (struct l1ctl_info_ul *) msgb_put(nmsg, sizeof(*nul));
-#endif
- nra = (struct l1ctl_rach_req *) msgb_put(nmsg, sizeof(*nra));
chan_req = random();
chan_req &= rr->chan_req_mask;
chan_req |= rr->chan_req_val;
- nra->ra = chan_req;
-#warning TODO
- nra->mf_off = 1; // (random() % s->tx_integer) + slots;
- nra->fn51 = (s->ccch_conf == 1) ? 27 : 50;
LOGP(DRR, LOGL_INFO, "RANDOM ACCESS (Tx-integer %d combined %s "
- "S(lots) %d ra 0x%02x offset %d)\n", s->tx_integer,
- (s->ccch_conf == 1) ? "yes": "no", slots, nra->ra, nra->mf_off);
+ "S(lots) %d ra 0x%02x)\n", s->tx_integer,
+ (s->ccch_conf == 1) ? "yes": "no", slots, chan_req);
- /* shift history and store */
- memcpy(&(rr->cr_hist[2]), &(rr->cr_hist[1]),
- sizeof(struct gsm48_cr_hist));
- memcpy(&(rr->cr_hist[1]), &(rr->cr_hist[0]),
- sizeof(struct gsm48_cr_hist));
- rr->cr_hist[0].valid = 1;
- rr->cr_hist[0].chan_req = chan_req;
+ /* (re)send CHANNEL RQD with new randiom */
+ nmsg = gsm48_rsl_msgb_alloc();
+ if (!nmsg)
+ return -ENOMEM;
+ ncch = (struct abis_rsl_cchan_hdr *) msgb_put(nmsg, sizeof(*ncch)
+ + 4 + 2 + 2);
+ rsl_init_cchan_hdr(ncch, RSL_MT_CHAN_RQD);
+ ncch->chan_nr = RSL_CHAN_RACH;
+ ncch->data[0] = RSL_IE_REQ_REFERENCE;
+ ncch->data[1] = chan_req;
+#warning HACK: fn51 and fn_off
+ ncch->data[2] = (s->ccch_conf == 1) ? 27 : 50;
+ ncch->data[3] = 1 + ((random() % s->tx_integer) + slots) / 51;
+printf("%d\n", ncch->data[3]);
+ ncch->data[4] = RSL_IE_ACCESS_DELAY;
+ ncch->data[5] = set->alter_delay; /* (-)=earlier (+)=later */
+ ncch->data[6] = RSL_IE_MS_POWER;
+ if (set->alter_tx_power) {
+ tx_power = set->alter_tx_power_value;
+ LOGP(DRR, LOGL_INFO, "Use alternative tx-power %d (%d dBm)\n",
+ tx_power,
+ ms_pwr_dbm(gsm_arfcn2band(cs->arfcn), tx_power));
+ } else {
+ tx_power = s->ms_txpwr_max_cch;
+ /* power offset in case of DCS1800 */
+ if (s->po && cs->arfcn >= 512 && cs->arfcn <= 885) {
+ LOGP(DRR, LOGL_INFO, "Use MS-TXPWR-MAX-CCH power value "
+ "%d (%d dBm) with offset %d dBm\n", tx_power,
+ ms_pwr_dbm(gsm_arfcn2band(cs->arfcn), tx_power),
+ s->po_value * 2);
+ /* use reserved bits 7,8 for offset (+ X * 2dB) */
+ tx_power |= s->po_value << 6;
+ } else
+ LOGP(DRR, LOGL_INFO, "Use MS-TXPWR-MAX-CCH power value "
+ "%d (%d dBm)\n", tx_power,
+ ms_pwr_dbm(gsm_arfcn2band(cs->arfcn),
+ tx_power));
+ }
+ ncch->data[7] = tx_power;
-#ifdef TODO
- add layer 1 conrols to RSL...
- return gsm48_send_rsl(ms, RSL_MT_CHAN_REQ, nmsg);
-#else
-//#warning disabled!
- return osmo_send_l1(ms, nmsg);
-#endif
+ /* set initial indications */
+ rr->ind_tx_power = s->ms_txpwr_max_cch;
+ rr->ind_ta = set->alter_delay;
+
+ /* store ra until confirmed, then copy it with time into cr_hist */
+ rr->cr_ra = chan_req;
+
+ return rslms_recvmsg(nmsg, ms);
}
/*
@@ -2273,8 +2292,8 @@ static int gsm48_rr_rx_sysinfo6(struct osmocom_ms *ms, struct msgb *msg)
gsm48_decode_si6_rest(s, si->rest_octets, payload_len);
LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 6 (mcc %s mnc %s "
- "lac 0x%04x)\n", gsm_print_mcc(s->mcc),
- gsm_print_mnc(s->mnc), s->lac);
+ "lac 0x%04x SACCH-timeout %d)\n", gsm_print_mcc(s->mcc),
+ gsm_print_mnc(s->mnc), s->lac, s->sacch_radio_link_timeout);
s->si6 = 1;
@@ -2529,19 +2548,21 @@ static int gsm48_match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
int i;
- struct gsm_time tm;
uint8_t ia_t1, ia_t2, ia_t3;
+ uint8_t cr_t1, cr_t2, cr_t3;
for (i = 0; i < 3; i++) {
/* filter confirmed RACH requests only */
- if (rr->cr_hist[i].valid == 2
- && ref->ra == rr->cr_hist[i].chan_req) {
+ if (rr->cr_hist[i].valid && ref->ra == rr->cr_hist[i].ref.ra) {
ia_t1 = ref->t1;
ia_t2 = ref->t2;
ia_t3 = (ref->t3_high << 3) | ref->t3_low;
- gsm_fn2gsmtime(&tm, rr->cr_hist[i].fn);
- if (ia_t1 == (tm.t1 & 0x1f) && ia_t2 == tm.t2
- && ia_t3 == tm.t3) {
+ ref = &rr->cr_hist[i].ref;
+ cr_t1 = ref->t1;
+ cr_t2 = ref->t2;
+ cr_t3 = (ref->t3_high << 3) | ref->t3_low;
+ if (ia_t1 == cr_t1 && ia_t2 == cr_t2
+ && ia_t3 == cr_t3) {
LOGP(DRR, LOGL_INFO, "request %02x matches "
"(fn=%d,%d,%d)\n", ref->ra, ia_t1,
ia_t2, ia_t3);
@@ -2551,7 +2572,7 @@ static int gsm48_match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref)
"but not frame number (IMM.ASS "
"fn=%d,%d,%d != RACH fn=%d,%d,%d)\n",
ref->ra, ia_t1, ia_t2, ia_t3,
- tm.t1 & 0x1f, tm.t2, tm.t3);
+ cr_t1, cr_t2, cr_t3);
}
}
@@ -2614,11 +2635,16 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
}
/* 3.3.1.1.2: ignore assignment while idle */
- if (rr->state != GSM48_RR_ST_CONN_PEND || !rr->wait_assign) {
+ if (rr->state != GSM48_RR_ST_CONN_PEND || rr->wait_assign == 0) {
LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
return 0;
}
+ if (rr->wait_assign == 2) {
+ LOGP(DRR, LOGL_INFO, "Ignoring, channel already assigned.\n");
+ return 0;
+ }
+
/* request ref */
if (gsm48_match_ra(ms, &ia->req_ref)) {
/* channel description */
@@ -2628,7 +2654,7 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
/* mobile allocation */
memcpy(&rr->cd_now.mob_alloc_lv, &ia->mob_alloc_len,
ia->mob_alloc_len + 1);
- rr->wait_assign = 0;
+ rr->wait_assign = 2;
return gsm48_rr_dl_est(ms);
}
LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
@@ -2718,11 +2744,16 @@ static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
}
/* 3.3.1.1.2: ignore assignment while idle */
- if (rr->state != GSM48_RR_ST_CONN_PEND || !rr->wait_assign) {
+ if (rr->state != GSM48_RR_ST_CONN_PEND || rr->wait_assign == 0) {
LOGP(DRR, LOGL_INFO, "Not for us, no request.\n");
return 0;
}
+ if (rr->wait_assign == 2) {
+ LOGP(DRR, LOGL_INFO, "Ignoring, channel already assigned.\n");
+ return 0;
+ }
+
/* request ref 1 */
if (gsm48_match_ra(ms, &ia->req_ref1)) {
/* channel description */
@@ -2732,7 +2763,7 @@ static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
/* mobile allocation */
memcpy(&rr->cd_now.mob_alloc_lv, &ia->mob_alloc_len,
ia->mob_alloc_len + 1);
- rr->wait_assign = 0;
+ rr->wait_assign = 2;
return gsm48_rr_dl_est(ms);
}
/* request ref 1 */
@@ -2744,7 +2775,7 @@ static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
/* mobile allocation */
memcpy(&rr->cd_now.mob_alloc_lv, &ia->mob_alloc_len,
ia->mob_alloc_len + 1);
- rr->wait_assign = 0;
+ rr->wait_assign = 2;
return gsm48_rr_dl_est(ms);
}
LOGP(DRR, LOGL_INFO, "Request, but not for us.\n");
@@ -2763,8 +2794,12 @@ static int gsm48_rr_rx_imm_ass_rej(struct osmocom_ms *ms, struct msgb *msg)
uint8_t t3122_value;
/* 3.3.1.1.2: ignore assignment while idle */
- if (rr->state != GSM48_RR_ST_CONN_PEND || !rr->wait_assign)
+ if (rr->state != GSM48_RR_ST_CONN_PEND || rr->wait_assign == 0)
+ return 0;
+
+ if (rr->wait_assign == 2) {
return 0;
+ }
if (payload_len < 0) {
LOGP(DRR, LOGL_NOTICE, "Short read of IMMEDIATE ASSIGNMENT "
@@ -2961,6 +2996,7 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms)
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s = cs->si;
+ struct gsm_settings *set = &ms->settings;
struct msgb *nmsg;
struct gsm48_hdr *gh;
struct gsm48_pag_rsp *pr;
@@ -3018,23 +3054,36 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms)
memcpy(pr->data, mi + 1, 1 + mi[1]);
}
+ /* reset scheduler */
+ LOGP(DRR, LOGL_INFO, "resetting scheduler\n");
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
+
+ /* setting (new) timing advance */
+ rr->ind_ta = rr->cd_now.ta;
+ LOGP(DRR, LOGL_INFO, "setting indicated ta %d (actual ta %d)\n",
+ rr->ind_ta, rr->ind_ta - set->alter_delay);
+ l1ctl_tx_ph_param_req(ms, rr->ind_ta - set->alter_delay,
+ (set->alter_tx_power) ? set->alter_tx_power_value
+ : rr->ind_tx_power);
+
/* activate channel */
+ LOGP(DRR, LOGL_INFO, "activating channel\n");
#ifdef TODO
RSL_MT_ to activate channel with all the cd_now informations
#else
rsl_dec_chan_nr(rr->cd_now.chan_nr, &ch_type, &ch_subch, &ch_ts);
if ((ch_type != RSL_CHAN_SDCCH8_ACCH
- && ch_type != RSL_CHAN_SDCCH4_ACCH) || ch_ts > 4) {
+ && ch_type != RSL_CHAN_SDCCH4_ACCH) || ch_ts > 4 || ch_subch >= 4) {
printf("Channel type %d, subch %d, ts %d not supported, "
"exitting.\n", ch_type, ch_subch, ch_ts);
exit(-ENOTSUP);
}
if (rr->cd_now.h)
tx_ph_dm_est_req_h1(ms, rr->cd_now.maio, rr->cd_now.hsn,
- ma, ma_len, rr->cd_now.chan_nr, rr->cd_now.tsc, 0);
+ ma, ma_len, rr->cd_now.chan_nr, rr->cd_now.tsc);
else
tx_ph_dm_est_req_h0(ms, rr->cd_now.arfcn, rr->cd_now.chan_nr,
- rr->cd_now.tsc, 0);
+ rr->cd_now.tsc);
#endif
/* start establishmnet */
@@ -3546,8 +3595,10 @@ static int gsm48_rr_rx_pch_agch(struct osmocom_ms *ms, struct msgb *msg)
case GSM48_MT_RR_IMM_ASS_REJ:
return gsm48_rr_rx_imm_ass_rej(ms, msg);
default:
+#if 0
LOGP(DRR, LOGL_NOTICE, "CCCH message type 0x%02x unknown.\n",
sih->system_information);
+#endif
return -EINVAL;
}
}
@@ -3555,7 +3606,31 @@ static int gsm48_rr_rx_pch_agch(struct osmocom_ms *ms, struct msgb *msg)
/* receive ACCH at RR layer */
static int gsm48_rr_rx_acch(struct osmocom_ms *ms, struct msgb *msg)
{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm_settings *set = &ms->settings;
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
struct gsm48_system_information_type_header *sih = msgb_l3(msg);
+ uint8_t ind_ta, ind_tx_power;
+
+ if (msgb_l2len(msg) < sizeof(*rllh) + 2 + 2) {
+ LOGP(DRR, LOGL_ERROR, "Missing TA and TX_POWER IEs\n");
+ return -EINVAL;
+ }
+
+ ind_ta = rllh->data[1];
+ ind_tx_power = rllh->data[3];
+ LOGP(DRR, LOGL_INFO, "Indicated ta %d (actual ta %d)\n",
+ ind_ta, ind_ta - set->alter_delay);
+ LOGP(DRR, LOGL_INFO, "Indicated tx_power %d\n",
+ ind_tx_power);
+ if (ind_ta != rr->ind_ta || ind_tx_power != rr->ind_tx_power) {
+ LOGP(DRR, LOGL_INFO, "setting new ta and tx_power\n");
+ l1ctl_tx_ph_param_req(ms, ind_ta - set->alter_delay,
+ (set->alter_tx_power) ? set->alter_tx_power_value
+ : ind_tx_power);
+ rr->ind_ta = ind_ta;
+ rr->ind_tx_power = ind_tx_power;
+ }
switch (sih->system_information) {
case GSM48_MT_RR_SYSINFO_5:
@@ -3576,6 +3651,7 @@ static int gsm48_rr_rx_acch(struct osmocom_ms *ms, struct msgb *msg)
/* unit data from layer 2 to RR layer */
static int gsm48_rr_unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm322_cellsel *cs = &ms->cellsel;
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
struct tlv_parsed tv;
@@ -3603,7 +3679,10 @@ static int gsm48_rr_unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
set radio link timeout on layer 1
it is the number of subsequent BCCH blocks. (about 1/4 seconds)
#else
- start_loss_timer(cs, s->bcch_radio_link_timeout / 4, 0);
+ /* use maximu loss timer, if to value is not available yet */
+ start_loss_timer(cs, ((rr->state == GSM48_RR_ST_DEDICATED)
+ ? ((s->sacch_radio_link_timeout) ? : 64)
+ : s->bcch_radio_link_timeout) / 4, 0);
#endif
}
@@ -3758,9 +3837,6 @@ static struct dldatastate {
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_REL_PEND),
@@ -3799,7 +3875,7 @@ static struct dldatastate {
#define DLDATASLLEN \
(sizeof(dldatastatelist) / sizeof(struct dldatastate))
-static int gsm48_rcv_rsl(struct osmocom_ms *ms, struct msgb *msg)
+static int gsm48_rcv_rll(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
@@ -3833,6 +3909,55 @@ static int gsm48_rcv_rsl(struct osmocom_ms *ms, struct msgb *msg)
return rc;
}
+static int gsm48_rcv_cch(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
+ int msg_type = ch->c.msg_type;
+ int rc;
+
+ LOGP(DRSL, LOGL_INFO, "(ms %s) Received '%s' from L2 in state "
+ "%s\n", ms->name, get_rsl_name(msg_type),
+ gsm48_rr_state_names[rr->state]);
+
+ if (rr->state == GSM48_RR_ST_CONN_PEND
+ && msg_type == RSL_MT_CHAN_CONF) {
+ rc = gsm48_rr_tx_rand_acc(ms, msg);
+ msgb_free(msg);
+ return rc;
+ }
+
+ LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n");
+ msgb_free(msg);
+ return 0;
+}
+
+
+/* input function for L2 messags up to L3 */
+static int gsm48_rcv_rsl(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
+ int rc = 0;
+
+ switch (rslh->msg_discr & 0xfe) {
+ case ABIS_RSL_MDISC_RLL:
+ rc = gsm48_rcv_rll(ms, msg);
+ break;
+ case ABIS_RSL_MDISC_COM_CHAN:
+ rc = gsm48_rcv_cch(ms, msg);
+ break;
+ default:
+ /* FIXME: implement this */
+ LOGP(DRSL, LOGL_NOTICE, "unknown RSLms msg_discr 0x%02x\n",
+ rslh->msg_discr);
+ msgb_free(msg);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
/* state trasitions for RR-SAP messages from up */
static struct rrdownstate {
uint32_t states;
@@ -4110,12 +4235,13 @@ static int gsm48_rr_connect_cnf(struct osmocom_ms *ms, struct msgbl *msg)
static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = ms->rrlayer;
+ struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
struct msgb *nmsg;
- struct gsm_rr_hdr *nrrh;
+ uint8_t cause = rllh->data[2];
printing of the cause
- switch (msg->l3h[0]) {
+ switch (cause) {
case RLL_CAUSE_SEQ_ERR:
case RLL_CAUSE_UNSOL_DM_RESP_MF:
einige muessen ignoriert werden
diff --git a/src/host/layer23/src/lapdm.c b/src/host/layer23/src/lapdm.c
index eff7aab..9e4b4a1 100644
--- a/src/host/layer23/src/lapdm.c
+++ b/src/host/layer23/src/lapdm.c
@@ -54,6 +54,7 @@
#include <stdint.h>
#include <string.h>
#include <errno.h>
+#include <arpa/inet.h>
#include <osmocore/logging.h>
#include <osmocore/timer.h>
@@ -364,7 +365,7 @@ printf("\n");
return tx_ph_data_req(ms, msg, chan_nr, link_id);
}
-/* Take a Bbis format message from L1 and create RSLms UNIT DATA IND */
+/* Create RSLms various RSLms messages */
static int send_rslms_rll_l3(uint8_t msg_type, struct lapdm_msg_ctx *mctx,
struct msgb *msg)
{
@@ -375,6 +376,28 @@ static int send_rslms_rll_l3(uint8_t msg_type, struct lapdm_msg_ctx *mctx,
return rslms_sendmsg(msg, mctx->dl->entity->ms);
}
+/* Take a B4 format message from L1 and create RSLms UNIT DATA IND */
+static int send_rslms_rll_l3_ui(struct lapdm_msg_ctx *mctx, struct msgb *msg)
+{
+ uint8_t l3_len = msg->tail - (uint8_t *)msgb_l3(msg);
+ struct abis_rsl_rll_hdr *rllh;
+
+ /* Add the RSL + RLL header */
+ msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
+ msgb_push(msg, 2 + 2);
+ rsl_rll_push_hdr(msg, RSL_MT_UNIT_DATA_IND, mctx->chan_nr,
+ mctx->link_id, 1);
+ rllh = (struct abis_rsl_rll_hdr *)msgb_l2(msg);
+
+ rllh->data[0] = RSL_IE_ACCESS_DELAY;
+ rllh->data[1] = mctx->ta_ind;
+
+ rllh->data[2] = RSL_IE_MS_POWER;
+ rllh->data[3] = mctx->tx_power_ind;
+
+ return rslms_sendmsg(msg, mctx->dl->entity->ms);
+}
+
static int send_rll_simple(uint8_t msg_type, struct lapdm_msg_ctx *mctx)
{
struct msgb *msg;
@@ -388,11 +411,15 @@ static int send_rll_simple(uint8_t msg_type, struct lapdm_msg_ctx *mctx)
static int rsl_rll_error(uint8_t cause, struct lapdm_msg_ctx *mctx)
{
struct msgb *msg;
+ uint8_t *tlv;
LOGP(DLAPDM, LOGL_NOTICE, "sending MDL-ERROR-IND %d\n", cause);
msg = rsl_rll_simple(RSL_MT_ERROR_IND, mctx->chan_nr, mctx->link_id, 1);
- msg->l2h = msgb_put(msg, sizeof(struct abis_rsl_rll_hdr) + 1);
- msg->l2h[0] = cause;
+ msg->l2h = msgb_put(msg, sizeof(struct abis_rsl_rll_hdr) + 3);
+ tlv = msg->l2h + sizeof(struct abis_rsl_rll_hdr);
+ tlv[0] = RSL_IE_RLM_CAUSE;
+ tlv[1] = 1;
+ tlv[2] = cause;
return rslms_sendmsg(msg, mctx->dl->entity->ms);
}
@@ -874,7 +901,7 @@ static int lapdm_rx_u(struct msgb *msg, struct lapdm_msg_ctx *mctx)
return 0;
}
msgb_pull_l2h(msg);
- rc = send_rslms_rll_l3(RSL_MT_UNIT_DATA_IND, mctx, msg);
+ rc = send_rslms_rll_l3_ui(mctx, msg);
break;
case LAPDm_U_DISC:
rsl_msg = RSL_MT_REL_IND;
@@ -1502,6 +1529,8 @@ int l2_ph_data_ind(struct msgb *msg, struct lapdm_entity *le, struct l1ctl_info_
LOGP(DLAPDM, LOGL_INFO, "fmt=B4\n");
/* SACCH frames have a two-byte L1 header that
* OsmocomBB L1 doesn't strip */
+ mctx.tx_power_ind = msg->l2h[0] & 0x1f;
+ mctx.ta_ind = msg->l2h[1];
msgb_pull(msg, 2);
msg->l2h += 2;
} else {
@@ -1948,6 +1977,64 @@ static int rslms_rx_rll_rel_req_idle(struct msgb *msg, struct lapdm_datalink *dl
return send_rll_simple(RSL_MT_REL_CONF, &dl->mctx);
}
+/* L3 requests channel in idle state */
+static int rslms_rx_chan_rqd(struct osmocom_ms *ms, struct msgb *msg)
+{
+ struct abis_rsl_cchan_hdr *cch = msgb_l2(msg);
+ int rc;
+
+ if (msgb_l2len(msg) < sizeof(*cch) + 4 + 2 + 2) {
+ LOGP(DRSL, LOGL_ERROR, "Message too short for CHAN RQD!\n");
+ return -EINVAL;
+ }
+ if (cch->data[0] != RSL_IE_REQ_REFERENCE) {
+ LOGP(DRSL, LOGL_ERROR, "Missing REQ REFERENCE IE\n");
+ return -EINVAL;
+ }
+ if (cch->data[4] != RSL_IE_ACCESS_DELAY) {
+ LOGP(DRSL, LOGL_ERROR, "Missing ACCESS_DELAY IE\n");
+ return -EINVAL;
+ }
+ if (cch->data[6] != RSL_IE_MS_POWER) {
+ LOGP(DRSL, LOGL_ERROR, "Missing MS POWER IE\n");
+ return -EINVAL;
+ }
+
+ /* TA = 0 - delay */
+ rc = l1ctl_tx_ph_param_req(ms, 0 - cch->data[5], cch->data[7]);
+
+ rc = tx_ph_rach_req(ms, cch->data[1], cch->data[2], cch->data[3]);
+
+ msgb_free(msg);
+
+ return rc;
+}
+
+/* L1 confirms channel request */
+int l2_ph_chan_conf(struct msgb *msg, struct osmocom_ms *ms,
+ struct l1ctl_info_dl *dl)
+{
+ struct abis_rsl_cchan_hdr *ch;
+ struct gsm_time tm;
+ struct gsm48_req_ref *ref;
+
+ gsm_fn2gsmtime(&tm, htonl(dl->frame_nr));
+
+ msgb_pull_l2h(msg);
+ msg->l2h = msgb_push(msg, sizeof(*ch) + sizeof(*ref));
+ ch = (struct abis_rsl_cchan_hdr *)msg->l2h;
+ rsl_init_cchan_hdr(ch, RSL_MT_CHAN_CONF);
+ ch->chan_nr = RSL_CHAN_RACH;
+ ch->data[0] = RSL_IE_REQ_REFERENCE;
+ ref = (struct gsm48_req_ref *) (ch->data + 1);
+ ref->t1 = tm.t1;
+ ref->t2 = tm.t2;
+ ref->t3_low = tm.t3 & 0x3;
+ ref->t3_high = tm.t3 >> 3;
+
+ return rslms_sendmsg(msg, ms);
+}
+
/* Names for Radio Link Layer Management */
static const struct value_string rsl_msg_names[] = {
{ RSL_MT_DATA_REQ, "RSL_MT_DATA_REQ" },
@@ -1966,6 +2053,8 @@ static const struct value_string rsl_msg_names[] = {
{ RSL_MT_SUSP_CONF, "RSL_MT_SUSP_CONF" },
{ RSL_MT_RES_REQ, "RSL_MT_RES_REQ" },
{ RSL_MT_RECON_REQ, "RSL_MT_RECON_REQ" },
+ { RSL_MT_CHAN_RQD, "RSL_MT_CHAN_RQD" },
+ { RSL_MT_CHAN_CONF, "RSL_MT_CHAN_CONF" },
{ 0, NULL }
};
@@ -2026,8 +2115,6 @@ static struct l2downstate {
/* release in idle state */
{SBIT(LAPDm_STATE_IDLE),
RSL_MT_REL_REQ, rslms_rx_rll_rel_req_idle},
-
- /* FIXME: create and send DISC command */
};
#define L2DOWNSLLEN \
@@ -2044,6 +2131,11 @@ static int rslms_rx_rll(struct msgb *msg, struct osmocom_ms *ms)
int i, supported = 0;
int rc = 0;
+ if (msgb_l2len(msg) < sizeof(*rllh)) {
+ LOGP(DRSL, LOGL_ERROR, "Message too short for RLL hdr!\n");
+ return -EINVAL;
+ }
+
if (rllh->link_id & 0x40)
le = &ms->l2_entity.lapdm_acch;
else
@@ -2085,16 +2177,51 @@ static int rslms_rx_rll(struct msgb *msg, struct osmocom_ms *ms)
return rc;
}
+/* incoming RSLms COMMON CHANNEL message from L3 */
+static int rslms_rx_com_chan(struct msgb *msg, struct osmocom_ms *ms)
+{
+ struct abis_rsl_cchan_hdr *cch = msgb_l2(msg);
+ int msg_type = cch->c.msg_type;
+ int rc = 0;
+
+ if (msgb_l2len(msg) < sizeof(*cch)) {
+ LOGP(DRSL, LOGL_ERROR, "Message too short for COM CHAN hdr!\n");
+ return -EINVAL;
+ }
+
+ switch (msg_type) {
+ case RSL_MT_CHAN_RQD:
+ /* create and send RACH request */
+ rc = rslms_rx_chan_rqd(ms, msg);
+ break;
+ default:
+ LOGP(DRSL, LOGL_NOTICE, "Unknown COMMON CHANNEL msg %d!\n",
+ msg_type);
+ msgb_free(msg);
+ return 0;
+ }
+
+ return rc;
+}
+
/* input into layer2 (from layer 3) */
int rslms_recvmsg(struct msgb *msg, struct osmocom_ms *ms)
{
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
int rc = 0;
+ if (msgb_l2len(msg) < sizeof(*rslh)) {
+ LOGP(DRSL, LOGL_ERROR, "Message too short RSL hdr!\n");
+ return -EINVAL;
+ }
+
switch (rslh->msg_discr & 0xfe) {
case ABIS_RSL_MDISC_RLL:
rc = rslms_rx_rll(msg, ms);
break;
+ case ABIS_RSL_MDISC_COM_CHAN:
+ rc = rslms_rx_com_chan(msg, ms);
+ break;
default:
LOGP(DRSL, LOGL_ERROR, "unknown RSLms message "
"discriminator 0x%02x", rslh->msg_discr);