diff options
-rw-r--r-- | openbsc/include/openbsc/abis_rsl.h | 10 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data_shared.h | 6 | ||||
-rw-r--r-- | openbsc/src/libbsc/abis_rsl.c | 53 | ||||
-rw-r--r-- | openbsc/src/libbsc/bsc_init.c | 2 | ||||
-rw-r--r-- | openbsc/src/libbsc/bts_ipaccess_nanobts.c | 29 |
5 files changed, 87 insertions, 13 deletions
diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index b27595e4a..305d8fa00 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -30,6 +30,7 @@ struct gsm_bts; struct gsm_lchan; struct gsm_subscriber; struct gsm_bts_trx_ts; +struct gsm_power_control; int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type, @@ -83,8 +84,10 @@ int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf); int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type, const uint8_t *data, int len); -int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db); -int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm); +int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db, + struct gsm_power_control *pc); +int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm, + struct gsm_power_control *pc); /* SMSCB functionality */ int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number, @@ -96,7 +99,8 @@ int rsl_nokia_si_begin(struct gsm_bts_trx *trx); int rsl_nokia_si_end(struct gsm_bts_trx *trx); /* required for Nokia BTS power control */ -int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction); +int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, + uint8_t reduction, struct gsm_power_control *pc); int rsl_release_sapis_from(struct gsm_lchan *lchan, int start, diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 864361414..24ab6d8ff 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -455,6 +455,12 @@ struct gsm_bts_model { struct tlv_definition nm_att_tlvdef; + struct { + void (*encode_power_param)(struct msgb *msg, + struct gsm_power_control *pc, + uint8_t msg_type); + } rsl; + struct bitvec features; uint8_t _features_data[128/8]; }; diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 8e9258ca5..f95bc7014 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -283,8 +283,30 @@ int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type, return abis_rsl_sendmsg(msg); } -int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db) +/* Add a (MS|BS) Power Parameter IE to the message */ +static void add_power_params(struct gsm_bts_trx *trx, struct msgb *msg, + struct gsm_power_control *pc, + uint8_t rsl_ie) { + struct gsm_bts *bts = trx->bts; + + /* IE is only present if dynamic power control inside BTS is active */ + if (rsl_ie == RSL_IE_BS_POWER_PARAM && !trx->power_control.dl.dynamic) + return; + if (rsl_ie == RSL_IE_MS_POWER_PARAM && !trx->power_control.ul.dynamic) + return; + /* IE is manufacturer/operator specific, we need an encoder + * function as part of the BTS model */ + if (!bts->model->rsl.encode_power_param) + return; + + bts->model->rsl.encode_power_param(msg, pc, rsl_ie); +} + +int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db, + struct gsm_power_control *pc) +{ + struct gsm_bts_trx *trx = lchan->ts->trx; struct abis_rsl_dchan_hdr *dh; struct msgb *msg; uint8_t chan_nr = gsm_lchan2chan_nr(lchan); @@ -304,20 +326,24 @@ int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db) dh->chan_nr = chan_nr; msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power); + if (pc) + add_power_params(trx, msg, pc, RSL_IE_BS_POWER_PARAM); - msg->dst = lchan->ts->trx->rsl_link; + msg->dst = trx->rsl_link; return abis_rsl_sendmsg(msg); } -int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm) +int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm, + struct gsm_power_control *pc) { + struct gsm_bts_trx *trx = lchan->ts->trx; struct abis_rsl_dchan_hdr *dh; struct msgb *msg; uint8_t chan_nr = gsm_lchan2chan_nr(lchan); int ctl_lvl; - ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, dbm); + ctl_lvl = ms_pwr_ctl_lvl(trx->bts->band, dbm); if (ctl_lvl < 0) return ctl_lvl; @@ -333,8 +359,10 @@ int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm) dh->chan_nr = chan_nr; msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power); + if (pc) + add_power_params(trx, msg, pc, RSL_IE_MS_POWER_PARAM); - msg->dst = lchan->ts->trx->rsl_link; + msg->dst = trx->rsl_link; return abis_rsl_sendmsg(msg); } @@ -453,6 +481,7 @@ static void mr_config_for_bts(struct gsm_lchan *lchan, struct msgb *msg) int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type, uint8_t ho_ref) { + struct gsm_bts_trx *trx = lchan->ts->trx; struct abis_rsl_dchan_hdr *dh; struct msgb *msg; int rc; @@ -470,7 +499,7 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type, ta = lchan->rqd_ta; /* BS11 requires TA shifted by 2 bits */ - if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_BS11) + if (trx->bts->type == GSM_BTS_TYPE_BS11) ta <<= 2; memset(&cd, 0, sizeof(cd)); @@ -525,6 +554,13 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type, msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power); msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power); msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta); + + add_power_params(trx, msg, &trx->power_control.dl, + RSL_IE_BS_POWER_PARAM); + + add_power_params(trx, msg, &trx->power_control.ul, + RSL_IE_MS_POWER_PARAM); + mr_config_for_bts(lchan, msg); msg->dst = lchan->ts->trx->rsl_link; @@ -2163,7 +2199,8 @@ int rsl_nokia_si_end(struct gsm_bts_trx *trx) return abis_rsl_sendmsg(msg); } -int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction) +int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, + uint8_t reduction, struct gsm_power_control *pc) { struct abis_rsl_common_hdr *ch; struct msgb *msg = rsl_msgb_alloc(); @@ -2174,6 +2211,8 @@ int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduc msgb_tv_put(msg, RSL_IE_CHAN_NR, channel); msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */ + if (pc) + add_power_params(trx, msg, pc, RSL_IE_BS_POWER_PARAM); msg->dst = trx->rsl_link; diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 743f4c155..c792e33ef 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -293,7 +293,7 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx) if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) { /* channel unspecific, power reduction in 2 dB steps */ - rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2); + rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2, NULL); rsl_nokia_si_end(trx); } diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts.c b/openbsc/src/libbsc/bts_ipaccess_nanobts.c index dfb5a45bc..2ae37f2d0 100644 --- a/openbsc/src/libbsc/bts_ipaccess_nanobts.c +++ b/openbsc/src/libbsc/bts_ipaccess_nanobts.c @@ -1,6 +1,6 @@ /* ip.access nanoBTS specific code */ -/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> +/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org> * * All Rights Reserved * @@ -44,13 +44,19 @@ extern struct gsm_network *bsc_gsmnet; static int bts_model_nanobts_start(struct gsm_network *net); static void bts_model_nanobts_e1line_bind_ops(struct e1inp_line *line); +static void ipaccess_encode_power_param(struct msgb *msg, + struct gsm_power_control *pc, + uint8_t msg_type); struct gsm_bts_model bts_model_nanobts = { .type = GSM_BTS_TYPE_NANOBTS, .name = "nanobts", .start = bts_model_nanobts_start, .oml_rcvmsg = &abis_nm_rcvmsg, - .e1line_bind_ops = bts_model_nanobts_e1line_bind_ops, + .e1line_bind_ops = bts_model_nanobts_e1line_bind_ops, + .rsl = { + .encode_power_param = ipaccess_encode_power_param, + }, .nm_att_tlvdef = { .def = { /* ip.access specifics */ @@ -717,3 +723,22 @@ static void bts_model_nanobts_e1line_bind_ops(struct e1inp_line *line) { e1inp_line_bind_ops(line, &ipaccess_e1inp_line_ops); } + +static void ipaccess_encode_power_param(struct msgb *msg, + struct gsm_power_control *pc, + uint8_t rsl_ie) +{ + uint8_t buf[4]; + + if (rsl_ie == RSL_IE_BS_POWER_PARAM) + buf[0] = RSL_IPAC_EIE_BS_PWR_CTL; + else + buf[0] = RSL_IPAC_EIE_MS_PWR_CTL; + + buf[1] = pc->rxlev.lower & 0x3f; + buf[2] = pc->rxlev.upper & 0x3f; + buf[3] = (pc->rxqual.lower & 7) << 4; + buf[3] |= (pc->rxqual.upper & 7); + + msgb_tlv_put(msg, rsl_ie, sizeof(buf), buf); +} |