From 1c5dd2c9bbc26902cdad0487e090e97e983b0787 Mon Sep 17 00:00:00 2001 From: Gus Bourg Date: Fri, 2 Dec 2011 10:18:17 +0100 Subject: Add NITZ (timezone) support as part of MM INFO The UTC offset from the operating system will be used by default to calculate the NITZ in MM INFO. However, a "timezone" vty command is added at the BTS level, allowing BTS-specific overrides, e.g. in case BTSs are distributed accross multiple timezones. --- openbsc/include/openbsc/gsm_data_shared.h | 5 +++ openbsc/src/libbsc/bsc_vty.c | 29 ++++++++++++ openbsc/src/libmsc/gsm_04_08.c | 74 ++++++++++++++++++++++--------- 3 files changed, 86 insertions(+), 22 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index f7a85a38b..25e90ede0 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -473,6 +473,11 @@ struct gsm_bts { /* buffers where we put the pre-computed SI */ sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE]; + /* TimeZone hours, mins, and bts specific */ + int tzhr; + int tzmn; + int tz_bts_specific; + /* ip.accesss Unit ID's have Site/BTS/TRX layout */ union { struct { diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 724486ff7..ed74397ec 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -448,6 +448,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) VTY_NEWLINE); vty_out(vty, " training_sequence_code %u%s", bts->tsc, VTY_NEWLINE); vty_out(vty, " base_station_id_code %u%s", bts->bsic, VTY_NEWLINE); + if (bts->tz_bts_specific != 0) + vty_out(vty, " timezone %d %d%s", bts->tzhr, bts->tzmn, VTY_NEWLINE); vty_out(vty, " ms max power %u%s", bts->ms_max_power, VTY_NEWLINE); vty_out(vty, " cell reselection hysteresis %u%s", bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE); @@ -1495,6 +1497,31 @@ DEFUN(cfg_bts_bsic, return CMD_SUCCESS; } +DEFUN(cfg_bts_timezone, + cfg_bts_timezone_cmd, + "timezone <-19-19> (0|15|30|45)", + "Set the Timezone Offset of this BTS\n") +{ + struct gsm_bts *bts = vty->index; + int tzhr = atoi(argv[0]); + int tzmn = atoi(argv[1]); + + bts->tzhr = tzhr; + bts->tzmn = tzmn; + bts->tz_bts_specific=1; + + return CMD_SUCCESS; +} + +DEFUN(cfg_bts_no_timezone, + cfg_bts_no_timezone_cmd, + "no timezone", + "disable bts specific timezone\n") +{ + struct gsm_bts *bts = vty->index; + bts->tz_bts_specific=0; + return CMD_SUCCESS; +} DEFUN(cfg_bts_unit_id, cfg_bts_unit_id_cmd, @@ -2691,6 +2718,8 @@ int bsc_vty_init(const struct log_info *cat) install_element(BTS_NODE, &cfg_bts_tsc_cmd); install_element(BTS_NODE, &cfg_bts_bsic_cmd); install_element(BTS_NODE, &cfg_bts_unit_id_cmd); + install_element(BTS_NODE, &cfg_bts_timezone_cmd); + install_element(BTS_NODE, &cfg_bts_no_timezone_cmd); install_element(BTS_NODE, &cfg_bts_serno_cmd); install_element(BTS_NODE, &cfg_bts_nokia_site_skip_reset_cmd); install_element(BTS_NODE, &cfg_bts_stream_id_cmd); diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index 7bf62b784..7c0d62895 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -610,12 +610,17 @@ static int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb return gsm0408_authorize(conn, msg); } -#if 0 -static uint8_t to_bcd8(uint8_t val) +/* Turn int into semi-octet representation: 98 => 0x89 */ +static uint8_t bcdify(uint8_t value) { - return ((val / 10) << 4) | (val % 10); + uint8_t ret; + + ret = value / 10; + ret |= (value % 10) << 4; + + return ret; } -#endif + /* Section 9.2.15a */ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) @@ -623,13 +628,14 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) struct msgb *msg = gsm48_msgb_alloc(); struct gsm48_hdr *gh; struct gsm_network *net = conn->bts->network; + struct gsm_bts *bts = conn->bts; uint8_t *ptr8; int name_len, name_pad; -#if 0 + time_t cur_t; - struct tm* cur_time; - int tz15min; -#endif + struct tm* gmt_time; + struct tm* local_time; + int tzunits; msg->lchan = conn->lchan; @@ -696,24 +702,48 @@ int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn) } -#if 0 /* Section 10.5.3.9 */ cur_t = time(NULL); - cur_time = gmtime(&cur_t); + gmt_time = gmtime(&cur_t); + ptr8 = msgb_put(msg, 8); ptr8[0] = GSM48_IE_NET_TIME_TZ; - ptr8[1] = to_bcd8(cur_time->tm_year % 100); - ptr8[2] = to_bcd8(cur_time->tm_mon); - ptr8[3] = to_bcd8(cur_time->tm_mday); - ptr8[4] = to_bcd8(cur_time->tm_hour); - ptr8[5] = to_bcd8(cur_time->tm_min); - ptr8[6] = to_bcd8(cur_time->tm_sec); - /* 02.42: coded as BCD encoded signed value in units of 15 minutes */ - tz15min = (cur_time->tm_gmtoff)/(60*15); - ptr8[7] = to_bcd8(tz15min); - if (tz15min < 0) - ptr8[7] |= 0x80; -#endif + ptr8[1] = bcdify(gmt_time->tm_year % 100); + ptr8[2] = bcdify(gmt_time->tm_mon + 1); + ptr8[3] = bcdify(gmt_time->tm_mday); + ptr8[4] = bcdify(gmt_time->tm_hour); + ptr8[5] = bcdify(gmt_time->tm_min); + ptr8[6] = bcdify(gmt_time->tm_sec); + + if (bts->tz_bts_specific) { + /* Convert tzhr and tzmn to units */ + if (bts->tzhr < 0) { + tzunits = ((bts->tzhr/-1)*4); + tzunits = tzunits + (bts->tzmn/15); + ptr8[7] = bcdify(tzunits); + /* Set negative time */ + ptr8[7] |= 0x08; + } + else { + tzunits = bts->tzhr*4; + tzunits = tzunits + (bts->tzmn/15); + ptr8[7] = bcdify(tzunits); + } + } + else { + /* Need to get GSM offset and convert into 15 min units */ + /* This probably breaks if gmtoff returns a value not evenly divisible by 15? */ + local_time = localtime(&cur_t); + tzunits = (local_time->tm_gmtoff/60)/15; + if (tzunits < 0) { + tzunits = tzunits/-1; + ptr8[7] = bcdify(tzunits); + /* Flip it to negative */ + ptr8[7] |= 0x08; + } + else + ptr8[7] = bcdify(tzunits); + } DEBUGP(DMM, "-> MM INFO\n"); -- cgit v1.2.3