diff options
author | Harald Welte <laforge@gnumonks.org> | 2009-06-20 18:15:19 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2009-06-20 19:22:18 +0200 |
commit | fcd2445d05e24c20310790ef0041c8cbe6e6546d (patch) | |
tree | 7cde37b69818798fa0cb712401854f3c358f9ac6 /openbsc/src | |
parent | a865f1b0c99b3c3ed2d0bb5973738024b62630cc (diff) |
Introduce BS and MS power control related functions
* add bts->band field plus corresponding VTY and commandline argument
* add trx->nominal_power and trx->max_power_red fields
* add rsl_chan_bs_power_ctrl() to control TRX RF power for a given TS
* add rsl_chan_ms_power_ctrl() to control MS RF power for a given lchan.
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/abis_rsl.c | 89 | ||||
-rw-r--r-- | openbsc/src/bsc_hack.c | 11 | ||||
-rw-r--r-- | openbsc/src/gsm_data.c | 37 | ||||
-rw-r--r-- | openbsc/src/vty_interface.c | 64 |
4 files changed, 195 insertions, 6 deletions
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 4b2a7fccf..5c1967d38 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -356,6 +356,95 @@ int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type, return abis_rsl_sendmsg(msg); } +int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db) +{ + struct abis_rsl_dchan_hdr *dh; + struct msgb *msg = rsl_msgb_alloc(); + u_int8_t chan_nr = lchan2chan_nr(lchan); + + db = abs(db); + if (db > 30) + return -EINVAL; + + lchan->bs_power = db/2; + if (fpc) + lchan->bs_power |= 0x10; + + dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh)); + init_dchan_hdr(dh, RSL_MT_BS_POWER_CONTROL); + dh->chan_nr = chan_nr; + + msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power); + + msg->trx = lchan->ts->trx; + + return abis_rsl_sendmsg(msg); +} + +/* determine power control level for given dBm value, as indicated + * by the tables in chapter 4.1.1 of GSM TS 05.05 */ +static int ms_pwr_ctl_lvl(struct gsm_bts *bts, unsigned int dbm) +{ + switch (bts->band) { + case GSM_BAND_400: + case GSM_BAND_900: + case GSM_BAND_850: + if (dbm >= 39) + return 0; + else if (dbm < 5) + return 19; + else + return 2 + ((39 - dbm) / 2); + break; + case GSM_BAND_1800: + if (dbm >= 36) + return 29; + else if (dbm >= 34) + return 30; + else if (dbm >= 32) + return 31; + else + return (30 - dbm) / 2; + break; + case GSM_BAND_1900: + if (dbm >= 33) + return 30; + else if (dbm >= 32) + return 31; + else + return (30 - dbm) / 2; + break; + } + return -EINVAL; +} + +int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm) +{ + struct abis_rsl_dchan_hdr *dh; + struct msgb *msg = rsl_msgb_alloc(); + u_int8_t chan_nr = lchan2chan_nr(lchan); + int ctl_lvl; + + ctl_lvl = ms_pwr_ctl_lvl(lchan->ts->trx->bts, dbm); + if (ctl_lvl < 0) + return ctl_lvl; + + lchan->ms_power = ctl_lvl; + + if (fpc) + lchan->ms_power |= 0x20; + + dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh)); + init_dchan_hdr(dh, RSL_MT_MS_POWER_CONTROL); + dh->chan_nr = chan_nr; + + msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power); + + msg->trx = lchan->ts->trx; + + return abis_rsl_sendmsg(msg); +} + /* Chapter 8.4.1 */ #if 0 int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr, diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 0322ff793..43f1011c7 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.c @@ -59,6 +59,7 @@ static int ARFCN = HARDCODED_ARFCN; static int cardnr = 0; static int release_l2 = 0; static enum gsm_bts_type BTS_TYPE = GSM_BTS_TYPE_BS11; +static enum gsm_band BAND = GSM_BAND_900; static const char *database_name = "hlr.sqlite3"; /* The following definitions are for OM and NM packets that we cannot yet @@ -927,6 +928,7 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) static int bootstrap_bts(struct gsm_bts *bts) { + bts->band = BAND; bts->location_area_code = LAC; bts->trx[0].arfcn = ARFCN; @@ -1027,6 +1029,7 @@ static int bootstrap_network(void) /* FIXME: do this dynamic */ bts->ip_access.site_id = 1801; bts->ip_access.bts_id = 0; + bts = &gsmnet->bts[1]; bootstrap_bts(bts); bts->ip_access.site_id = 1800; @@ -1075,7 +1078,7 @@ static void print_help() static void handle_options(int argc, char** argv) { while (1) { - int option_index = 0, c; + int tmp, option_index = 0, c; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"debug", 1, 0, 'd'}, @@ -1092,10 +1095,11 @@ static void handle_options(int argc, char** argv) {"cardnr", 1, 0, 'C'}, {"release-l2", 0, 0, 'R'}, {"timestamp", 0, 0, 'T'}, + {"band", 0, 0, 'b'}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:T", + c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:Tb:", long_options, &option_index); if (c == -1) break; @@ -1147,6 +1151,9 @@ static void handle_options(int argc, char** argv) case 'T': debug_timestamp(1); break; + case 'b': + BAND = gsm_band_parse(atoi(optarg)); + break; default: /* ignore */ break; diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c index e71a6cb0d..80020e509 100644 --- a/openbsc/src/gsm_data.c +++ b/openbsc/src/gsm_data.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <errno.h> #include <openbsc/gsm_data.h> @@ -213,3 +214,39 @@ struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac, } return NULL; } + +char *gsm_band_name(enum gsm_band band) +{ + switch (band) { + case GSM_BAND_400: + return "GSM 400"; + case GSM_BAND_850: + return "GSM 850"; + case GSM_BAND_900: + return "GSM 900"; + case GSM_BAND_1800: + return "DCS 1800"; + case GSM_BAND_1900: + return "PCS 1900"; + } + return "invalid"; +} + +enum gsm_band gsm_band_parse(int mhz) +{ + switch (mhz) { + case 400: + return GSM_BAND_400; + case 850: + return GSM_BAND_850; + case 900: + return GSM_BAND_900; + case 1800: + return GSM_BAND_1800; + case 1900: + return GSM_BAND_1900; + default: + return -EINVAL; + } +} + diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 6597e440f..a2b3e5620 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -112,9 +112,11 @@ static void e1isl_dump_vty(struct vty *vty, struct e1inp_sign_link *e1l) static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) { - vty_out(vty, "BTS %u is of %s type, has LAC %u, BSIC %u, TSC %u and %u TRX%s", - bts->nr, btstype2str(bts->type), bts->location_area_code, - bts->bsic, bts->tsc, bts->num_trx, VTY_NEWLINE); + vty_out(vty, "BTS %u is of %s type in band %s, has LAC %u, " + "BSIC %u, TSC %u and %u TRX%s", + bts->nr, btstype2str(bts->type), gsm_band_name(bts->band), + bts->location_area_code, bts->bsic, bts->tsc, + bts->num_trx, VTY_NEWLINE); if (is_ipaccess_bts(bts)) vty_out(vty, " Unit ID: %u/%u/0%s", bts->ip_access.site_id, bts->ip_access.bts_id, @@ -159,6 +161,10 @@ static void trx_dump_vty(struct vty *vty, struct gsm_bts_trx *trx) { vty_out(vty, "TRX %u of BTS %u is on ARFCN %u%s", trx->nr, trx->bts->nr, trx->arfcn, VTY_NEWLINE); + vty_out(vty, " RF Nominal Power: %d dBm, reduced by %u dB, " + "resulting BS power: %d dBm\n", + trx->nominal_power, trx->max_power_red, + trx->nominal_power - trx->max_power_red); vty_out(vty, " NM State: "); net_dump_nmstate(vty, &trx->nm_state); vty_out(vty, " Baseband Transceiver NM State: "); @@ -297,7 +303,7 @@ DEFUN(show_ts, static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr) { - vty_out(vty, " ID: %lu, Authorized: %d%s", subscr->id, + vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id, subscr->authorized, VTY_NEWLINE); if (subscr->name) vty_out(vty, " Name: '%s'%s", subscr->name, VTY_NEWLINE); @@ -628,10 +634,30 @@ DEFUN(cfg_bts_type, { struct gsm_bts *bts = vty->index; + /* FIXME: implementation */ //bts->type = return CMD_SUCCESS; } +DEFUN(cfg_bts_band, + cfg_bts_band_cmd, + "band BAND", + "Set the frequency band of this BTS\n") +{ + struct gsm_bts *bts = vty->index; + int band = gsm_band_parse(atoi(argv[0])); + + if (band < 0) { + vty_out(vty, "%% BAND %d is not a valid GSM band%s", + band, VTY_NEWLINE); + return CMD_WARNING; + } + + bts->band = band; + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_lac, cfg_bts_lac_cmd, "location_area_code <0-255>", @@ -758,6 +784,34 @@ DEFUN(cfg_trx_arfcn, return CMD_SUCCESS; } +DEFUN(cfg_trx_max_power_red, + cfg_trx_max_power_red_cmd, + "max_power_red <0-100>", + "Reduction of maximum BS RF Power in dB\n") +{ + int maxpwr_r = atoi(argv[0]); + struct gsm_bts_trx *trx = vty->index; + int upper_limit = 12; /* default 12.21 max power red. */ + + /* FIXME: check if our BTS type supports more than 12 */ + if (maxpwr_r < 0 || maxpwr_r > upper_limit) { + vty_out(vty, "%% Power %d dB is not in the valid range%s", + maxpwr_r, VTY_NEWLINE); + return CMD_WARNING; + } + if (maxpwr_r & 1) { + vty_out(vty, "%% Power %d dB is not an even value%s", + maxpwr_r, VTY_NEWLINE); + return CMD_WARNING; + } + + trx->max_power_red = maxpwr_r; + + /* FIXME: make sure we update this using OML */ + + return CMD_SUCCESS; +} + /* per TS configuration */ DEFUN(cfg_ts, cfg_ts_cmd, @@ -884,6 +938,7 @@ int bsc_vty_init(struct gsm_network *net) install_node(&bts_node, dummy_config_write); install_default(BTS_NODE); install_element(BTS_NODE, &cfg_bts_type_cmd); + install_element(BTS_NODE, &cfg_bts_band_cmd); install_element(BTS_NODE, &cfg_bts_lac_cmd); install_element(BTS_NODE, &cfg_bts_tsc_cmd); install_element(BTS_NODE, &cfg_bts_unit_id_cmd); @@ -892,6 +947,7 @@ int bsc_vty_init(struct gsm_network *net) install_node(&trx_node, dummy_config_write); install_default(TRX_NODE); install_element(TRX_NODE, &cfg_trx_arfcn_cmd); + install_element(TRX_NODE, &cfg_trx_max_power_red); install_element(TRX_NODE, &cfg_ts_cmd); install_node(&ts_node, dummy_config_write); |