summaryrefslogtreecommitdiffstats
path: root/src/host/layer23/src/mobile/gsm48_rr.c
diff options
context:
space:
mode:
authorAndreas.Eversberg <jolly@eversberg.eu>2010-09-26 10:35:46 +0000
committerAndreas.Eversberg <jolly@eversberg.eu>2010-09-26 10:35:46 +0000
commit4ed601ae4e48e8d480c3e0f5e82160434e6a32c8 (patch)
treef3ec61df2af05361485c3e8377793a145f351558 /src/host/layer23/src/mobile/gsm48_rr.c
parent4c11da77906c6a7ca08b739b02c7475ec07d4577 (diff)
[layer23] Adding application generated measurement report
The cell provides SYSTEM INFORMATION 5* and 6. These are used to create a list of neighbor cells to monitor. Because there is no neighbor cell monitoring supported by layer1, the list has no valid results yet. Currently the average RX level of received frames are used to generate a new report every second. The report is transmitted to layer1 and used there whenever a measurement report has to be transmitted. The timing advance and the current transmit power (as requested by network), is included with every report.
Diffstat (limited to 'src/host/layer23/src/mobile/gsm48_rr.c')
-rw-r--r--src/host/layer23/src/mobile/gsm48_rr.c319
1 files changed, 239 insertions, 80 deletions
diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c
index 24360274..333b379b 100644
--- a/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/src/host/layer23/src/mobile/gsm48_rr.c
@@ -79,12 +79,13 @@
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/mobile/vty.h>
-static void start_rr_t_monitor(struct gsm48_rrlayer *rr, int sec, int micro);
-static void stop_rr_t_monitor(struct gsm48_rrlayer *rr);
+static void start_rr_t_meas(struct gsm48_rrlayer *rr, int sec, int micro);
+static void stop_rr_t_meas(struct gsm48_rrlayer *rr);
static void stop_rr_t_starting(struct gsm48_rrlayer *rr);
static void stop_rr_t3124(struct gsm48_rrlayer *rr);
static int gsm48_rcv_rsl(struct osmocom_ms *ms, struct msgb *msg);
static int gsm48_rr_dl_est(struct osmocom_ms *ms);
+static int gsm48_rr_tx_meas_rep(struct osmocom_ms *ms);
/*
* support
@@ -322,6 +323,7 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state)
/* release dedicated mode, if any */
l1ctl_tx_dm_rel_req(rr->ms);
+ rr->dm_est = 0;
l1ctl_tx_reset_req(rr->ms, L1CTL_RES_T_FULL);
/* free establish message, if any */
rr->rr_est_req = 0;
@@ -495,8 +497,6 @@ int gsm48_rsl_dequeue(struct osmocom_ms *ms)
int gsm48_rr_start_monitor(struct osmocom_ms *ms)
{
ms->rrlayer.monitor = 1;
- memset(&ms->meas, 0, sizeof(&ms->meas));
- start_rr_t_monitor(&ms->rrlayer, 1, 0);
return 0;
}
@@ -504,8 +504,6 @@ int gsm48_rr_start_monitor(struct osmocom_ms *ms)
int gsm48_rr_stop_monitor(struct osmocom_ms *ms)
{
ms->rrlayer.monitor = 0;
- memset(&ms->meas, 0, sizeof(&ms->meas));
- stop_rr_t_monitor(&ms->rrlayer);
return 0;
}
@@ -515,7 +513,7 @@ int gsm48_rr_stop_monitor(struct osmocom_ms *ms)
*/
/* special timer to monitor measurements */
-static void timeout_rr_monitor(void *arg)
+static void timeout_rr_meas(void *arg)
{
struct gsm48_rrlayer *rr = arg;
struct gsm322_cellsel *cs = &rr->ms->cellsel;
@@ -526,7 +524,7 @@ static void timeout_rr_monitor(void *arg)
char text[256];
if (!cs->selected) {
- sprintf(text, "MON: no cell selected");
+ return;
} else if (!meas->frames) {
sprintf(text, "MON: no cell info");
} else {
@@ -550,10 +548,14 @@ static void timeout_rr_monitor(void *arg)
sprintf(text + strlen(text), "/%d", ch_subch);
}
}
- vty_notify(rr->ms, "%s\n", text);
+ LOGP(DRR, LOGL_INFO, "%s\n", text);
+ if (rr->monitor)
+ vty_notify(rr->ms, "%s\n", text);
+ if (rr->dm_est)
+ gsm48_rr_tx_meas_rep(rr->ms);
memset(meas, 0, sizeof(*meas));
- start_rr_t_monitor(rr, 1, 0);
+ start_rr_t_meas(rr, 1, 0);
}
/* special timer to assign / handover when starting time is reached */
@@ -645,11 +647,11 @@ static void timeout_rr_t3126(void *arg)
new_rr_state(rr, GSM48_RR_ST_IDLE);
}
-static void start_rr_t_monitor(struct gsm48_rrlayer *rr, int sec, int micro)
+static void start_rr_t_meas(struct gsm48_rrlayer *rr, int sec, int micro)
{
- rr->t_monitor.cb = timeout_rr_monitor;
- rr->t_monitor.data = rr;
- bsc_schedule_timer(&rr->t_monitor, sec, micro);
+ rr->t_meas.cb = timeout_rr_meas;
+ rr->t_meas.data = rr;
+ bsc_schedule_timer(&rr->t_meas, sec, micro);
}
static void start_rr_t_rel_wait(struct gsm48_rrlayer *rr, int sec, int micro)
@@ -706,11 +708,11 @@ 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_monitor(struct gsm48_rrlayer *rr)
+static void stop_rr_t_meas(struct gsm48_rrlayer *rr)
{
- if (bsc_timer_pending(&rr->t_monitor)) {
- LOGP(DRR, LOGL_INFO, "stopping pending timer T_monitor\n");
- bsc_del_timer(&rr->t_monitor);
+ if (bsc_timer_pending(&rr->t_meas)) {
+ LOGP(DRR, LOGL_INFO, "stopping pending timer T_meas\n");
+ bsc_del_timer(&rr->t_meas);
}
}
@@ -1704,11 +1706,46 @@ static int gsm48_decode_si6_rest(struct gsm48_sysinfo *s, uint8_t *si,
}
/* send sysinfo event to other layers */
-static int gsm48_send_sysinfo(struct osmocom_ms *ms, uint8_t type)
+static int gsm48_new_sysinfo(struct osmocom_ms *ms, uint8_t type)
{
+ struct gsm48_sysinfo *s = ms->cellsel.si;
struct msgb *nmsg;
struct gsm322_msg *em;
+ /* update list of measurements, if BA(SACCH) is complete and new */
+ if (s
+ && (type == GSM48_MT_RR_SYSINFO_5
+ || type == GSM48_MT_RR_SYSINFO_5bis
+ || type == GSM48_MT_RR_SYSINFO_5ter)
+ && s->si5
+ && (!s->nb_ext_ind_si5
+ || (s->si5bis && s->nb_ext_ind_si5 && !s->nb_ext_ind_si5bis)
+ || (s->si5bis && s->si5ter && s->nb_ext_ind_si5
+ && s->nb_ext_ind_si5bis))) {
+ struct gsm48_rr_meas *rrmeas = &ms->rrlayer.meas;
+ int n = 0, i;
+
+ LOGP(DRR, LOGL_NOTICE, "Complete set of SI5* for BA(%d)\n",
+ s->nb_ba_ind_si5);
+ rrmeas->nc_num = 0;
+ for (i = 1; i <= 1024; i++) {
+ if ((s->freq[i & 1023].mask & FREQ_TYPE_REP)) {
+ if (n == 32) {
+ LOGP(DRR, LOGL_NOTICE, "SI5* report "
+ "exceeds 32 BCCHs\n");
+ break;
+ }
+ LOGP(DRR, LOGL_NOTICE, "SI5* report arfcn %d\n",
+ i & 1023);
+ rrmeas->nc_arfcn[n] = i & 1023;
+ rrmeas->nc_rxlev[n] = -128;
+ n++;
+ }
+ }
+ rrmeas->nc_num = n;
+ }
+
+ /* send sysinfo event to other layers */
nmsg = gsm322_msgb_alloc(GSM322_EVENT_SYSINFO);
if (!nmsg)
return -ENOMEM;
@@ -1762,7 +1799,7 @@ static int gsm48_rr_rx_sysinfo1(struct osmocom_ms *ms, struct msgb *msg)
s->si1 = 1;
- return gsm48_send_sysinfo(ms, si->header.system_information);
+ return gsm48_new_sysinfo(ms, si->header.system_information);
}
/* receive "SYSTEM INFORMATION 2" message (9.1.32) */
@@ -1797,13 +1834,13 @@ static int gsm48_rr_rx_sysinfo2(struct osmocom_ms *ms, struct msgb *msg)
decode_freq_list(&ms->support, s->freq, si->bcch_frequency_list,
sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_NCELL_2);
/* NCC Permitted */
- s->nb_ncc_permitted = si->ncc_permitted;
+ s->nb_ncc_permitted_si2 = si->ncc_permitted;
/* RACH Control Parameter */
gsm48_decode_rach_ctl_neigh(s, &si->rach_control);
s->si2 = 1;
- return gsm48_send_sysinfo(ms, si->header.system_information);
+ return gsm48_new_sysinfo(ms, si->header.system_information);
}
/* receive "SYSTEM INFORMATION 2bis" message (9.1.33) */
@@ -1837,14 +1874,13 @@ static int gsm48_rr_rx_sysinfo2bis(struct osmocom_ms *ms, struct msgb *msg)
s->nb_ba_ind_si2bis = (si->bcch_frequency_list[0] >> 5) & 1;
decode_freq_list(&ms->support, s->freq,
si->bcch_frequency_list,
- sizeof(si->bcch_frequency_list), 0x8e,
- FREQ_TYPE_NCELL_2bis);
+ sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_NCELL_2bis);
/* RACH Control Parameter */
gsm48_decode_rach_ctl_neigh(s, &si->rach_control);
s->si2bis = 1;
- return gsm48_send_sysinfo(ms, si->header.system_information);
+ return gsm48_new_sysinfo(ms, si->header.system_information);
}
/* receive "SYSTEM INFORMATION 2ter" message (9.1.34) */
@@ -1875,14 +1911,15 @@ static int gsm48_rr_rx_sysinfo2ter(struct osmocom_ms *ms, struct msgb *msg)
/* Neighbor Cell Description 2 */
s->nb_multi_rep_si2ter = (si->ext_bcch_frequency_list[0] >> 6) & 3;
+ s->nb_ba_ind_si2ter = (si->ext_bcch_frequency_list[0] >> 5) & 1;
decode_freq_list(&ms->support, s->freq,
si->ext_bcch_frequency_list,
sizeof(si->ext_bcch_frequency_list), 0x8e,
- FREQ_TYPE_NCELL_2ter);
+ FREQ_TYPE_NCELL_2ter);
s->si2ter = 1;
- return gsm48_send_sysinfo(ms, si->header.system_information);
+ return gsm48_new_sysinfo(ms, si->header.system_information);
}
/* receive "SYSTEM INFORMATION 3" message (9.1.35) */
@@ -1939,7 +1976,7 @@ static int gsm48_rr_rx_sysinfo3(struct osmocom_ms *ms, struct msgb *msg)
l1ctl_tx_ccch_mode_req(ms, cs->ccch_mode);
}
- return gsm48_send_sysinfo(ms, si->header.system_information);
+ return gsm48_new_sysinfo(ms, si->header.system_information);
}
/* receive "SYSTEM INFORMATION 4" message (9.1.36) */
@@ -2015,7 +2052,7 @@ static int gsm48_rr_rx_sysinfo4(struct osmocom_ms *ms, struct msgb *msg)
s->si4 = 1;
- return gsm48_send_sysinfo(ms, si->header.system_information);
+ return gsm48_new_sysinfo(ms, si->header.system_information);
}
/* receive "SYSTEM INFORMATION 5" message (9.1.37) */
@@ -2052,7 +2089,7 @@ static int gsm48_rr_rx_sysinfo5(struct osmocom_ms *ms, struct msgb *msg)
s->si5 = 1;
- return gsm48_send_sysinfo(ms, si->system_information);
+ return gsm48_new_sysinfo(ms, si->system_information);
}
/* receive "SYSTEM INFORMATION 5bis" message (9.1.38) */
@@ -2090,7 +2127,7 @@ static int gsm48_rr_rx_sysinfo5bis(struct osmocom_ms *ms, struct msgb *msg)
s->si5bis = 1;
- return gsm48_send_sysinfo(ms, si->system_information);
+ return gsm48_new_sysinfo(ms, si->system_information);
}
/* receive "SYSTEM INFORMATION 5ter" message (9.1.39) */
@@ -2121,12 +2158,14 @@ static int gsm48_rr_rx_sysinfo5ter(struct osmocom_ms *ms, struct msgb *msg)
memcpy(s->si5t_msg, si, MIN(msgb_l3len(msg), sizeof(s->si5t_msg)));
/* Neighbor Cell Description */
+ s->nb_multi_rep_si5ter = (si->bcch_frequency_list[0] >> 6) & 3;
+ s->nb_ba_ind_si5ter = (si->bcch_frequency_list[0] >> 5) & 1;
decode_freq_list(&ms->support, s->freq, si->bcch_frequency_list,
- sizeof(si->bcch_frequency_list), 0xce, FREQ_TYPE_REP_5ter);
+ sizeof(si->bcch_frequency_list), 0x8e, FREQ_TYPE_REP_5ter);
s->si5ter = 1;
- return gsm48_send_sysinfo(ms, si->system_information);
+ return gsm48_new_sysinfo(ms, si->system_information);
}
/* receive "SYSTEM INFORMATION 6" message (9.1.39) */
@@ -2163,7 +2202,7 @@ static int gsm48_rr_rx_sysinfo6(struct osmocom_ms *ms, struct msgb *msg)
/* Cell Options (SACCH) */
gsm48_decode_cellopt_sacch(s, &si->cell_options);
/* NCC Permitted */
- s->nb_ncc_permitted = si->ncc_permitted;
+ s->nb_ncc_permitted_si6 = si->ncc_permitted;
/* SI 6 Rest Octets */
if (payload_len >= 4)
gsm48_decode_si6_rest(s, si->rest_octets, payload_len);
@@ -2174,7 +2213,7 @@ static int gsm48_rr_rx_sysinfo6(struct osmocom_ms *ms, struct msgb *msg)
s->si6 = 1;
- return gsm48_send_sysinfo(ms, si->system_information);
+ return gsm48_new_sysinfo(ms, si->system_information);
}
/*
@@ -2484,6 +2523,7 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
#endif
memset(&cd, 0, sizeof(cd));
+ cd.ind_tx_power = rr->cd_now.ind_tx_power;
if (ma_len < 0 /* mobile allocation IE must be included */
|| ia->mob_alloc_len > ma_len) { /* short read of IE */
@@ -2579,7 +2619,9 @@ static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
#endif
memset(&cd1, 0, sizeof(cd1));
+ cd1.ind_tx_power = rr->cd_now.ind_tx_power;
memset(&cd2, 0, sizeof(cd2));
+ cd2.ind_tx_power = rr->cd_now.ind_tx_power;
if (ma_len < 0 /* mobile allocation IE must be included */
|| ia->mob_alloc_len > ma_len) { /* short read of IE */
@@ -2780,14 +2822,91 @@ static int gsm48_rr_rx_add_ass(struct osmocom_ms *ms, struct msgb *msg)
static int gsm48_rr_tx_meas_rep(struct osmocom_ms *ms)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
- struct gsm48_rr_meas *meas = &rr->meas;
+ struct gsm48_sysinfo *s = ms->cellsel.si;
+ struct rx_meas_stat *meas = &rr->ms->meas;
+ struct gsm48_rr_meas *rrmeas = &rr->meas;
struct msgb *nmsg;
struct gsm48_hdr *gh;
struct gsm48_meas_res *mr;
+ uint8_t serv_rxlev_full = 0, serv_rxlev_sub = 0, serv_rxqual_full = 0,
+ serv_rxqual_sub = 0;
+ uint8_t ta, tx_power;
+ uint8_t rep_ba = 0, rep_valid = 0, meas_valid = 0, multi_rep = 0;
+ uint8_t n = 0, rxlev_nc[6], bsic_nc[6], bcch_f_nc[6];
+
+ /* just in case! */
+ if (!s)
+ return -EINVAL;
+
+ /* check if SI5* is completely received, check BA-IND */
+ if (s->si5
+ && (!s->nb_ext_ind_si5
+ || (s->si5bis && s->nb_ext_ind_si5 && !s->nb_ext_ind_si5bis)
+ || (s->si5bis && s->si5ter && s->nb_ext_ind_si5
+ && s->nb_ext_ind_si5bis))) {
+ rep_ba = s->nb_ba_ind_si5;
+ if ((s->si5bis && s->nb_ext_ind_si5
+ && s->nb_ba_ind_si5bis != rep_ba)
+ || (s->si5bis && s->si5ter && s->nb_ext_ind_si5
+ && s->nb_ext_ind_si5bis && s->nb_ba_ind_si5ter != rep_ba)) {
+ LOGP(DRR, LOGL_NOTICE, "BA-IND missmatch on SI5*");
+ } else
+ rep_valid = 1;
+ }
+
+ /* check for valid measurements, any frame must exist */
+ if (meas->frames) {
+ meas_valid = 1;
+ serv_rxlev_full = serv_rxlev_sub = meas->rxlev / meas->frames;
+ serv_rxqual_full = serv_rxqual_sub = 0; // FIXME
+ }
+
+ memset(&rxlev_nc, 0, sizeof(rxlev_nc));
+ memset(&bsic_nc, 0, sizeof(bsic_nc));
+ memset(&bcch_f_nc, 0, sizeof(bcch_f_nc));
+ if (rep_valid) {
+ int8_t strongest, current;
+ uint8_t ncc;
+ int i, index;
+
+ /* multiband reporting, if not: 0 = normal reporting */
+ if (s->si5 && s->si5bis && s->si5ter && s->nb_ext_ind_si5
+ && s->nb_ext_ind_si5bis)
+ multi_rep = s->nb_multi_rep_si5ter;
+
+ /* get 6 strongest measurements */
+ // FIXME: multiband report
+ strongest = 127; /* infinite */
+ for (n = 0; n < 6; n++) {
+ current = -128; /* -infinite */
+ index = 0;
+ for (i = 0; i < rrmeas->nc_num; i++) {
+ /* only check if NCC is permitted */
+ ncc = rrmeas->nc_bsic[i] >> 3;
+ if ((s->nb_ncc_permitted_si6 & (1 << ncc))
+ && rrmeas->nc_rxlev[i] > current
+ && rrmeas->nc_rxlev[i] < strongest) {
+ current = rrmeas->nc_rxlev[i];
+ index = i;
+ }
+ }
+ if (current == -128) /* no more found */
+ break;
+ rxlev_nc[n] = rrmeas->nc_rxlev[index] + 110;
+ bsic_nc[n] = rrmeas->nc_bsic[index];
+ bcch_f_nc[n] = index;
+ }
+ }
nmsg = gsm48_l3_msgb_alloc();
if (!nmsg)
return -ENOMEM;
+
+ /* use indicated tx-power and TA (not the altered ones) */
+ tx_power = rr->cd_now.ind_tx_power;
+ // FIXME: degrade power to the max supported level
+ ta = rr->cd_now.ind_ta;
+
gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
mr = (struct gsm48_meas_res *) msgb_put(nmsg, sizeof(*mr));
@@ -2795,51 +2914,68 @@ static int gsm48_rr_tx_meas_rep(struct osmocom_ms *ms)
gh->msg_type = GSM48_MT_RR_MEAS_REP;
/* measurement results */
- mr->rxlev_full = meas->rxlev_full;
- mr->rxlev_sub = meas->rxlev_sub;
- mr->rxqual_full = meas->rxqual_full;
- mr->rxqual_sub = meas->rxqual_sub;
- mr->dtx_used = meas->dtx;
- mr->ba_used = meas->ba;
- mr->meas_valid = meas->meas_valid;
- if (meas->ncell_na) {
+ mr->rxlev_full = serv_rxlev_full;
+ mr->rxlev_sub = serv_rxlev_sub;
+ mr->rxqual_full = serv_rxqual_full;
+ mr->rxqual_sub = serv_rxqual_sub;
+ mr->dtx_used = 0; // FIXME: no DTX yet
+ mr->ba_used = rep_ba;
+ mr->meas_valid = !meas_valid; /* 0 = valid */
+ if (rep_valid) {
+ mr->no_nc_n_hi = n >> 2;
+ mr->no_nc_n_lo = n & 3;
+ } else {
/* no results for serving cells */
mr->no_nc_n_hi = 1;
mr->no_nc_n_lo = 3;
- } else {
- mr->no_nc_n_hi = meas->count >> 2;
- mr->no_nc_n_lo = meas->count & 3;
- }
- mr->rxlev_nc1 = meas->rxlev_nc[0];
- mr->rxlev_nc2_hi = meas->rxlev_nc[1] >> 1;
- mr->rxlev_nc2_lo = meas->rxlev_nc[1] & 1;
- mr->rxlev_nc3_hi = meas->rxlev_nc[2] >> 2;
- mr->rxlev_nc3_lo = meas->rxlev_nc[2] & 3;
- mr->rxlev_nc4_hi = meas->rxlev_nc[3] >> 3;
- mr->rxlev_nc4_lo = meas->rxlev_nc[3] & 7;
- mr->rxlev_nc5_hi = meas->rxlev_nc[4] >> 4;
- mr->rxlev_nc5_lo = meas->rxlev_nc[4] & 15;
- mr->rxlev_nc6_hi = meas->rxlev_nc[5] >> 5;
- mr->rxlev_nc6_lo = meas->rxlev_nc[5] & 31;
- mr->bsic_nc1_hi = meas->bsic_nc[0] >> 3;
- mr->bsic_nc1_lo = meas->bsic_nc[0] & 7;
- mr->bsic_nc2_hi = meas->bsic_nc[1] >> 4;
- mr->bsic_nc2_lo = meas->bsic_nc[1] & 15;
- mr->bsic_nc3_hi = meas->bsic_nc[2] >> 5;
- mr->bsic_nc3_lo = meas->bsic_nc[2] & 31;
- mr->bsic_nc4 = meas->bsic_nc[3];
- mr->bsic_nc5 = meas->bsic_nc[4];
- mr->bsic_nc6 = meas->bsic_nc[5];
- mr->bcch_f_nc1 = meas->bcch_f_nc[0];
- mr->bcch_f_nc2 = meas->bcch_f_nc[1];
- mr->bcch_f_nc3 = meas->bcch_f_nc[2];
- mr->bcch_f_nc4 = meas->bcch_f_nc[3];
- mr->bcch_f_nc5_hi = meas->bcch_f_nc[4] >> 1;
- mr->bcch_f_nc5_lo = meas->bcch_f_nc[4] & 1;
- mr->bcch_f_nc6_hi = meas->bcch_f_nc[5] >> 2;
- mr->bcch_f_nc6_lo = meas->bcch_f_nc[5] & 3;
-
- return gsm48_send_rsl(ms, RSL_MT_UNIT_DATA_REQ, nmsg);
+ }
+ mr->rxlev_nc1 = rxlev_nc[0];
+ mr->rxlev_nc2_hi = rxlev_nc[1] >> 1;
+ mr->rxlev_nc2_lo = rxlev_nc[1] & 1;
+ mr->rxlev_nc3_hi = rxlev_nc[2] >> 2;
+ mr->rxlev_nc3_lo = rxlev_nc[2] & 3;
+ mr->rxlev_nc4_hi = rxlev_nc[3] >> 3;
+ mr->rxlev_nc4_lo = rxlev_nc[3] & 7;
+ mr->rxlev_nc5_hi = rxlev_nc[4] >> 4;
+ mr->rxlev_nc5_lo = rxlev_nc[4] & 15;
+ mr->rxlev_nc6_hi = rxlev_nc[5] >> 5;
+ mr->rxlev_nc6_lo = rxlev_nc[5] & 31;
+ mr->bsic_nc1_hi = bsic_nc[0] >> 3;
+ mr->bsic_nc1_lo = bsic_nc[0] & 7;
+ mr->bsic_nc2_hi = bsic_nc[1] >> 4;
+ mr->bsic_nc2_lo = bsic_nc[1] & 15;
+ mr->bsic_nc3_hi = bsic_nc[2] >> 5;
+ mr->bsic_nc3_lo = bsic_nc[2] & 31;
+ mr->bsic_nc4 = bsic_nc[3];
+ mr->bsic_nc5 = bsic_nc[4];
+ mr->bsic_nc6 = bsic_nc[5];
+ mr->bcch_f_nc1 = bcch_f_nc[0];
+ mr->bcch_f_nc2 = bcch_f_nc[1];
+ mr->bcch_f_nc3 = bcch_f_nc[2];
+ mr->bcch_f_nc4 = bcch_f_nc[3];
+ mr->bcch_f_nc5_hi = bcch_f_nc[4] >> 1;
+ mr->bcch_f_nc5_lo = bcch_f_nc[4] & 1;
+ mr->bcch_f_nc6_hi = bcch_f_nc[5] >> 2;
+ mr->bcch_f_nc6_lo = bcch_f_nc[5] & 3;
+
+ LOGP(DRR, LOGL_INFO, "MEAS REP: pwr=%d TA=%d meas-invalid=%d "
+ "rxlev-full=%d rxlev-sub=%d rxqual-full=%d rxqual-sub=%d "
+ "dtx %d ba %d no-ncell-n %d\n", tx_power, ta, mr->meas_valid,
+ mr->rxlev_full - 110, mr->rxlev_sub - 110,
+ mr->rxqual_full, mr->rxqual_sub, mr->dtx_used, mr->ba_used,
+ (mr->no_nc_n_hi << 2) | mr->no_nc_n_lo);
+
+ msgb_tv16_push(nmsg, RSL_IE_L3_INFO,
+ nmsg->tail - (uint8_t *)msgb_l3(nmsg));
+ msgb_push(nmsg, 2 + 2);
+ nmsg->data[0] = RSL_IE_ACCESS_DELAY;
+ nmsg->data[1] = ta;
+ nmsg->data[2] = RSL_IE_MS_POWER;
+ nmsg->data[3] = tx_power;
+ rsl_rll_push_hdr(nmsg, RSL_MT_UNIT_DATA_REQ, rr->cd_now.chan_nr,
+ 0x40, 1);
+
+ return rslms_recvmsg(nmsg, ms);
}
/*
@@ -2917,6 +3053,8 @@ static int gsm48_rr_activate_channel(struct osmocom_ms *ms,
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm_settings *set = &ms->settings;
+ struct gsm48_sysinfo *s = ms->cellsel.si;
+ struct rx_meas_stat *meas = &ms->meas;
uint8_t ch_type, ch_subch, ch_ts;
/* setting (new) timing advance */
@@ -2925,6 +3063,17 @@ static int gsm48_rr_activate_channel(struct osmocom_ms *ms,
l1ctl_tx_param_req(ms, cd->ind_ta - set->alter_delay,
(set->alter_tx_power) ? set->alter_tx_power_value
: cd->ind_tx_power);
+ /* setting initial (invalid) measurement report, resetting SI5* */
+ if (s) {
+ memset(s->si5_msg, 0, sizeof(s->si5_msg));
+ memset(s->si5b_msg, 0, sizeof(s->si5b_msg));
+ memset(s->si5t_msg, 0, sizeof(s->si5t_msg));
+ memset(meas, 0, sizeof(*meas));
+ }
+ rr->meas.nc_num = 0;
+ stop_rr_t_meas(rr);
+ start_rr_t_meas(rr, 1, 0);
+ gsm48_rr_tx_meas_rep(ms);
/* establish */
LOGP(DRR, LOGL_INFO, "establishing channel in dedicated mode\n");
@@ -2940,6 +3089,7 @@ static int gsm48_rr_activate_channel(struct osmocom_ms *ms,
ma, ma_len, cd->chan_nr, cd->tsc);
else
l1ctl_tx_dm_est_req_h0(ms, cd->arfcn, cd->chan_nr, cd->tsc);
+ rr->dm_est = 1;
if (rr->cipher_on)
l1ctl_tx_crypto_req(ms, rr->cipher_type + 1, subscr->key, 8);
@@ -3556,7 +3706,9 @@ static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "ASSIGNMENT COMMAND\n");
memset(cda, 0, sizeof(*cda));
+ cda->ind_tx_power = rr->cd_now.ind_tx_power;
memset(cdb, 0, sizeof(*cdb));
+ cdb->ind_tx_power = rr->cd_now.ind_tx_power;
if (payload_len < 0) {
LOGP(DRR, LOGL_NOTICE, "Short read of ASSIGNMENT COMMAND "
@@ -3909,7 +4061,9 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "HANDOVER COMMAND\n");
memset(cda, 0, sizeof(*cda));
+ cda->ind_tx_power = rr->cd_now.ind_tx_power;
memset(cdb, 0, sizeof(*cdb));
+ cdb->ind_tx_power = rr->cd_now.ind_tx_power;
if (payload_len < 0) {
LOGP(DRR, LOGL_NOTICE, "Short read of HANDOVER COMMAND "
@@ -4264,6 +4418,7 @@ static int gsm48_rr_susp_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DRR, LOGL_INFO, "suspension coplete, leaving dedicated "
"mode\n");
l1ctl_tx_dm_rel_req(ms);
+ rr->dm_est = 0;
l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
/* store current channel descriptions */
@@ -4791,6 +4946,7 @@ static int gsm48_rr_mdl_error_ind(struct osmocom_ms *ms, struct msgb *msg)
/* deactivate channel */
l1ctl_tx_dm_rel_req(ms);
+ rr->dm_est = 0;
l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
switch (rr->modify_state) {
@@ -5041,6 +5197,8 @@ int gsm48_rr_init(struct osmocom_ms *ms)
osmol2_register_handler(ms, &gsm48_rx_rsl);
+ start_rr_t_meas(rr, 1, 0);
+
return 0;
}
@@ -5062,7 +5220,7 @@ int gsm48_rr_exit(struct osmocom_ms *ms)
rr->rr_est_msg = NULL;
}
- stop_rr_t_monitor(rr);
+ stop_rr_t_meas(rr);
stop_rr_t_starting(rr);
stop_rr_t_rel_wait(rr);
stop_rr_t3110(rr);
@@ -5092,6 +5250,7 @@ static void timeout_rr_t3124(void *arg)
/* change radio to old channel */
tx_ph_dm_est_req(ms, rr->cd_now.arfcn, rr->cd_now.chan_nr,
rr->cd_now.tsc);
+ rr->dm_est = 1;
/* re-establish old link */
nmsg = gsm48_l3_msgb_alloc();
@@ -5138,6 +5297,7 @@ static int gsm48_rr_rand_acc_cnf_dedicated(struct osmocom_ms *ms, struct msgb *m
start_rr_t3124(rr, GSM_T3124_675);
else
start_rr_t3124(rr, GSM_T3124_320);
+ }
if (!rr->n_chan_req) {
start_rr_t3126(rr, 5, 0); /* TODO improve! */
return 0;
@@ -5151,4 +5311,3 @@ static int gsm48_rr_rand_acc_cnf_dedicated(struct osmocom_ms *ms, struct msgb *m
#endif
-