aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gsm_04_11.c
diff options
context:
space:
mode:
authorSteffen Neubauer <stefreak@stefreak.de>2009-11-11 23:02:07 +0900
committerHarald Welte <laforge@gnumonks.org>2009-11-11 23:02:07 +0900
commit5727cf4ea78033b955fadd2525dbe12da486edf6 (patch)
tree2223039d9311f059145f832332900367825dfce1 /openbsc/src/gsm_04_11.c
parentd409be7faecb24640ee55b2be667340b9997775c (diff)
[SMS] implement GSM340_TP_VPF_ABSOLUTE
- Added function "gsm340_scts" to decode the service center time stamp into a UTC/GMT timestamp - in function gsm340_validity_period: can now decode validity period format absolute.
Diffstat (limited to 'openbsc/src/gsm_04_11.c')
-rw-r--r--openbsc/src/gsm_04_11.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 6e59eafe..f941d90a 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -216,10 +216,14 @@ static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
}
+static time_t gsm340_scts(u_int8_t *scts);
+
static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
{
u_int8_t vp;
unsigned long minutes;
+ time_t expires;
+ time_t now;
switch (sms_vpf) {
case GSM340_TP_VPF_RELATIVE:
@@ -236,8 +240,12 @@ static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
break;
case GSM340_TP_VPF_ABSOLUTE:
/* Chapter 9.2.3.12.2 */
- /* FIXME: like service center time stamp */
- DEBUGP(DSMS, "VPI absolute not implemented yet\n");
+ expires = gsm340_scts(sms_vp);
+ now = mktime(gmtime(NULL));
+ if (expires <= now)
+ minutes = 0;
+ else
+ minutes = (expires-now)/60;
break;
case GSM340_TP_VPF_ENHANCED:
/* Chapter 9.2.3.12.3 */
@@ -317,6 +325,7 @@ static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
return len_in_bytes;
}
+/* Turn int into semi-octet representation: 98 => 0x89 */
static u_int8_t bcdify(u_int8_t value)
{
u_int8_t ret;
@@ -327,6 +336,21 @@ static u_int8_t bcdify(u_int8_t value)
return ret;
}
+/* Turn semi-octet representation into int: 0x89 => 98 */
+static u_int8_t unbcdify(u_int8_t value)
+{
+ u_int8_t ret;
+
+ if ((value & 0x0F) > 9 || (value >> 4) > 9)
+ DEBUGP(DSMS, "unbcdify got too big nibble: 0x%02X\n", value);
+
+ ret = (value&0x0F)*10;
+ if (ret > 90)
+ ret += value>>4;
+
+ return ret;
+}
+
/* Generate 03.40 TP-SCTS */
static void gsm340_gen_scts(u_int8_t *scts, time_t time)
{
@@ -338,7 +362,30 @@ static void gsm340_gen_scts(u_int8_t *scts, time_t time)
*scts++ = bcdify(tm->tm_hour);
*scts++ = bcdify(tm->tm_min);
*scts++ = bcdify(tm->tm_sec);
- *scts++ = 0; /* FIXME: timezone */
+ *scts++ = bcdify(tm->tm_gmtoff/(60*15));
+}
+
+/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
+static time_t gsm340_scts(u_int8_t *scts)
+{
+ struct tm tm;
+
+ u_int8_t yr = unbcdify(*scts++);
+
+ if (yr <= 80)
+ tm.tm_year = 100 + yr;
+ else
+ tm.tm_year = yr;
+ tm.tm_mon = unbcdify(*scts++) - 1;
+ tm.tm_mday = unbcdify(*scts++);
+ tm.tm_hour = unbcdify(*scts++);
+ tm.tm_min = unbcdify(*scts++);
+ tm.tm_sec = unbcdify(*scts++);
+ /* according to gsm 03.40 time zone is
+ "expressed in quarters of an hour" */
+ tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
+
+ return mktime(&tm);
}
/* generate a msgb containing a TPDU derived from struct gsm_sms,