summaryrefslogtreecommitdiff
path: root/src/pdu_decode.c
diff options
context:
space:
mode:
authorBrandon Bayer <bbayer@multitech.com>2015-10-26 14:58:43 -0500
committerBrandon Bayer <bbayer@multitech.com>2015-11-06 13:49:06 -0600
commitbe01eb8a87f1582b1c15ec4e09a9a66770da87c5 (patch)
treed2044a650d334dca4aa2efb2521e3ecf887ac86b /src/pdu_decode.c
parentab80a82e2e0f5ea7cdef0394f80e69b377fab779 (diff)
downloadsms-utils-be01eb8a87f1582b1c15ec4e09a9a66770da87c5.tar.gz
sms-utils-be01eb8a87f1582b1c15ec4e09a9a66770da87c5.tar.bz2
sms-utils-be01eb8a87f1582b1c15ec4e09a9a66770da87c5.zip
feat: sms support for CE910-DUAL, DE910-DUAL, LE910-SVG0.0.8
- PDU is used for everything except LE910-SVG sending - a bug in radio requires radio reboot to send more than 1 PDU sms
Diffstat (limited to 'src/pdu_decode.c')
-rw-r--r--src/pdu_decode.c156
1 files changed, 148 insertions, 8 deletions
diff --git a/src/pdu_decode.c b/src/pdu_decode.c
index cbc2009..2b9e44c 100644
--- a/src/pdu_decode.c
+++ b/src/pdu_decode.c
@@ -30,6 +30,7 @@
#include <ctype.h>
#include "config.h"
+#include "global.h"
#include "log.h"
#include "utils.h"
#include "pdu_decode.h"
@@ -82,6 +83,31 @@ int pdu_decode_timestamp(const char *pdu_str, struct tm *tm)
return PDU_TIMESTAMP_LEN;
}
+
+int pdu_decode_cdma_timestamp(const char *pdu_str, struct tm *tm)
+{
+ char buf[PDU_CDMA_TIMESTAMP_LEN + 1];
+ char *cp;
+ int off_upper;
+ int off_lower;
+ int off;
+
+ STRLEN_CHECK(pdu_str, PDU_CDMA_TIMESTAMP_LEN, -1);
+
+ memset(tm, 0, sizeof(*tm));
+ memset(buf, 0, sizeof(buf));
+
+ strncpy(buf, pdu_str, PDU_CDMA_TIMESTAMP_LEN);
+
+ cp = (char *) strptime(buf, "%y%m%d%H%M%S", tm);
+ if (!cp || *cp) {
+ log_error("timestamp could not be converted to tm");
+ return -1;
+ }
+
+ return PDU_CDMA_TIMESTAMP_LEN;
+}
+
int pdu_decode_addr(const char *pdu_str, struct pdu_addr *addr, int smsc)
{
const char *begin = pdu_str;
@@ -141,17 +167,21 @@ done:
}
#define octet_idx(n) octet_align(n)
+#define octet_cdma_idx(n) ((n+1) * 7 / 8)
#define decode_septet(buf, n) \
shiftl(bit_maskr(cycledown(n, 8)) & buf[octet_idx(n)], cycleup(n, 8)) | \
shiftr(bit_maskl(cycleup(n, 8), 8) & buf[octet_idx(n - 1)], cycledown(n - 1, 8))
-int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu)
+#define decode_septet_cdma(buf, n) \
+shiftr(buf[octet_cdma_idx(n)], cycleup(n, 8) + 1) | \
+shiftl(buf[octet_cdma_idx(n) - 1], cycledown(n, 8)) & 0x7F
+
+int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octets)
{
const char *begin = pdu_str;
int tmp;
uint8_t octets[PDU_OCTETS_MAX + 1];
- int nr_octets;
int i;
STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1);
@@ -176,7 +206,30 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu)
pdu->user_data_len = PDU_UD_7BIT_MAX;
}
- nr_octets = octet_align(pdu->user_data_len);
+ *nr_octets = octet_align(pdu->user_data_len);
+ } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) {
+ log_debug("data coding alphabet is cdma default");
+
+ if (!strcmp(Global.core.model, "LE910-SVG")) {
+ if (pdu->user_data_len > PDU_UD_7BIT_MAX) {
+ log_warning("pdu contains invalid user-data-len: 0x%02X", pdu->user_data_len);
+ pdu->user_data_len = PDU_UD_7BIT_MAX;
+ }
+ }
+ else {
+ if (pdu->user_data_len > PDU_UD_8BIT_MAX) {
+ log_warning("pdu contains invalid user-data-len: 0x%02X", pdu->user_data_len);
+ pdu->user_data_len = PDU_UD_8BIT_MAX;
+ }
+ }
+
+ if (!strcmp(Global.core.model, "LE910-SVG")) {
+ *nr_octets = octet_align(pdu->user_data_len);
+ }
+ else {
+ *nr_octets = pdu->user_data_len;
+ pdu->user_data_len = octet_align_cdma(pdu->user_data_len);
+ }
} else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_EIGHT) {
log_debug("data coding alphabet is eight");
@@ -186,19 +239,19 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu)
pdu->user_data_len = PDU_UD_8BIT_MAX;
}
- nr_octets = pdu->user_data_len;
+ *nr_octets = pdu->user_data_len;
} else {
log_debug("data coding alphabet 0x%02X not implemented",
pdu->data_coding.general.alphabet);
return -1;
}
- STRLEN_CHECK(pdu_str, nr_octets * 2, -1);
+ STRLEN_CHECK(pdu_str, *nr_octets * 2, -1);
log_debug("user-data-len: 0x%02X", pdu->user_data_len);
- log_debug("nr_octets: 0x%02X", nr_octets);
+ log_debug("nr_octets: 0x%02X", *nr_octets);
- for (i = 0; i < nr_octets; i++) {
+ for (i = 0; i < *nr_octets; i++) {
octets[i] = hex_byte_decode(pdu_str);
pdu_str += HEX_BYTE_LEN;
}
@@ -222,6 +275,32 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu)
pdu->user_data[i] = decode_septet(octets, i);
}
pdu->user_data[i] = '\0';
+ } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) {
+ // Keep UDH for concatenated SMS.
+ // Otherwise it is impossible to process correctly concatenated SMS.
+ i = 0;
+ if (pdu->type.user_data_header) {
+ for (i = 0; i <= octets[0]; ++i) {
+ pdu->user_data[i] = octets[i];
+ }
+ i = octets[0] + 1; // Set message text start after UDH.
+ // Process octets padding for 7-bit encoding.
+ if (0 != (i * 8) % 7) {
+ pdu->user_data[i] = 0; // set padding data to 0;
+ i++;
+ }
+ }
+ for (; i < pdu->user_data_len; i++) {
+ pdu->user_data[i] = decode_septet_cdma(octets, i);
+ log_debug("DECODE: i: %d octet: 0x%02X --> data: 0x%02X", i, octets[i], pdu->user_data[i]);
+ }
+ //Remove padded byte for data length of 7 characters if not LE910-SVG
+ if (strcmp(Global.core.model, "LE910-SVG") && pdu->user_data[i-1] == 0) {
+ log_debug("Removing padded char");
+ i--;
+ pdu->user_data_len--;
+ }
+ pdu->user_data[i] = '\0';
} else {
for (i = 0; i < pdu->user_data_len; i++) {
pdu->user_data[i] = octets[i];
@@ -237,6 +316,7 @@ int pdu_decode(const char *pdu_str, struct pdu_info *pdu)
const char *begin = pdu_str;
const char *msg_begin;
int tmp;
+ int nr_octets;
memset(pdu, 0, sizeof(*pdu));
@@ -341,7 +421,7 @@ int pdu_decode(const char *pdu_str, struct pdu_info *pdu)
pdu_str += tmp;
}
- tmp = pdu_decode_user_data(pdu_str, pdu);
+ tmp = pdu_decode_user_data(pdu_str, pdu, &nr_octets);
DECODE_FAIL(tmp < 0, "user-data", -1);
pdu_str += tmp;
}
@@ -352,3 +432,63 @@ int pdu_decode(const char *pdu_str, struct pdu_info *pdu)
return pdu_str - begin;
}
+
+
+int pdu_decode_cdma(const char *pdu_str, struct pdu_info *pdu)
+{
+ const char *begin = pdu_str;
+ const char *msg_begin;
+ int tmp;
+ int nr_octets;
+
+ memset(pdu, 0, sizeof(*pdu));
+
+ //Destination address
+ tmp = pdu_decode_addr(pdu_str, &pdu->addr, 1);
+ DECODE_FAIL(tmp < 0, "addr", -1);
+ pdu_str += tmp;
+
+ msg_begin = pdu_str;
+
+ STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1);
+
+ //Timestamp
+ tmp = pdu_decode_cdma_timestamp(pdu_str, &pdu->timestamp);
+ DECODE_FAIL(tmp < 0, "timestamp", -1);
+ pdu_str += tmp;
+
+ //Teleservice ID
+ tmp = hex_byte_decode(pdu_str);
+ DECODE_FAIL(tmp < 0, "tele-id-1", -1);
+ pdu_str += HEX_BYTE_LEN;
+ log_debug("tele-id-1: 0x%02X", tmp);
+
+ tmp = hex_byte_decode(pdu_str);
+ DECODE_FAIL(tmp < 0, "tele-id-2", -1);
+ pdu_str += HEX_BYTE_LEN;
+ log_debug("tele-id-2: 0x%02X", tmp);
+
+ //Priority
+ tmp = hex_byte_decode(pdu_str);
+ DECODE_FAIL(tmp < 0, "priority", -1);
+ pdu_str += HEX_BYTE_LEN;
+ log_debug("priority: 0x%02X", tmp);
+
+ //Data coding scheme
+ tmp = hex_byte_decode(pdu_str);
+ DECODE_FAIL(tmp < 0, "data-coding-scheme", -1);
+ pdu_str += HEX_BYTE_LEN;
+ pdu->data_coding.data_coding = tmp;
+ log_debug("data-coding-scheme: 0x%02X", pdu->data_coding.data_coding);
+
+ //User Data
+ tmp = pdu_decode_user_data(pdu_str, pdu, &nr_octets);
+ DECODE_FAIL(tmp < 0, "user-data", -1);
+ pdu_str += tmp;
+
+ pdu->msg_len = 6 + nr_octets;
+
+ log_debug("msg_len: %d", pdu->msg_len);
+
+ return pdu_str - begin;
+}