Attached is a patch to support sending time to the device.
It adds two per-bts configuration elements: tzunits and tzdir.
tzunits are the number of units from GMT. Each unit represents 15
minutes of time.
tzdir is the direction of the units from GMT. tzdir 0 means
GMT-tzunits and tzdir 1 means GMT+tzunits.
So for example, if you're GMT+1 you want:
bts 0
type nanobts
band PCS1900
cell_identity 0
location_area_code 1
training_sequence_code 7
base_station_id_code 63
tzunits 4
tzdir 1
ms max power 15
cell reselection hysteresis 4
Thanks,
Gus
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index f7a85a3..ff30be9 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -473,6 +473,12 @@ struct gsm_bts {
/* buffers where we put the pre-computed SI */
sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE];
+ /* TimeZone Units - in GSM each unit represents 15 minutes */
+ int tzunits;
+
+ /* TimeZone Direction - 0 for GMT- and 1 for GMT+ */
+ int tzdir;
+
/* 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 724486f..7818224 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);
+ vty_out(vty, " tzunits %d%s", bts->tzunits, VTY_NEWLINE);
+ vty_out(vty, " tzdir %d%s", bts->tzdir, 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,41 @@ DEFUN(cfg_bts_bsic,
return CMD_SUCCESS;
}
+DEFUN(cfg_bts_tzunits,
+ cfg_bts_tzunits_cmd,
+ "tzunits <0-79>",
+ "Set the Timezone Offset of this BTS\n")
+{
+ struct gsm_bts *bts = vty->index;
+ int tzunits = atoi(argv[0]);
+
+ if (tzunits < 0 || tzunits > 0x3f) {
+ vty_out(vty, "%% Timezone Units %d is not in the valid range (0-79)%s",
+ tzunits, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ bts->tzunits = tzunits;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_tzdir,
+ cfg_bts_tzdir_cmd,
+ "tzdir <0-1>",
+ "Set the Timezone Direction of this BTS\n")
+{
+ struct gsm_bts *bts = vty->index;
+ int tzdir = atoi(argv[0]);
+
+ if (tzdir < 0 || tzdir > 0x3f) {
+ vty_out(vty, "%% Timezone Units %d is not in the valid range (0-1)%s",
+ tzdir, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ bts->tzdir = tzdir;
+
+ return CMD_SUCCESS;
+}
DEFUN(cfg_bts_unit_id,
cfg_bts_unit_id_cmd,
@@ -2691,6 +2728,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_tzunits_cmd);
+ install_element(BTS_NODE, &cfg_bts_tzdir_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 7bf62b7..f5313dd 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,18 @@ 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
+ int gmyear;
+ int gmmon;
+ int gmday;
+ int gmhour;
+ int gmmin;
+ int gmsec;
msg->lchan = conn->lchan;
@@ -696,24 +706,38 @@ 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);
+
+ gmyear = cur_time->tm_year;
+ gmmon = cur_time->tm_mon;
+ gmday = cur_time->tm_mday;
+ gmhour = cur_time->tm_hour;
+ gmmin = cur_time->tm_min;
+ gmsec = cur_time->tm_sec;
+
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
+ DEBUGP(DMM, "MM Time Update Info -> YEAR : %d\n", gmyear);
+ DEBUGP(DMM, "MM Time Update Info -> MON : %d\n", gmmon);
+ DEBUGP(DMM, "MM Time Update Info -> DAY : %d\n", gmday);
+ DEBUGP(DMM, "MM Time Update Info -> HOUR : %d\n", gmhour);
+ DEBUGP(DMM, "MM Time Update Info -> MIN : %d\n", gmmin);
+ DEBUGP(DMM, "MM Time Update Info -> SEC : %d\n", gmsec);
+
+ ptr8[1] = bcdify(gmyear % 100);
+ ptr8[2] = bcdify(gmmon + 1);
+ ptr8[3] = bcdify(gmday);
+ ptr8[4] = bcdify(gmhour);
+ ptr8[5] = bcdify(gmmin);
+ ptr8[6] = bcdify(gmsec);
+ ptr8[7] = bcdify(bts->tzunits);
+
+ if(bts->tzdir == 0)
+ {
+ ptr8[7] |= 0x08;
+ }
DEBUGP(DMM, "-> MM INFO\n");