summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon Bayer <bbayer@multitech.com>2016-02-05 11:15:14 -0600
committerBrandon Bayer <bbayer@multitech.com>2016-02-08 16:42:35 -0600
commitfea5d250ef5dd8d2b13aa0748b38e621e5eec6f4 (patch)
tree788ec4b32241c99c88ff0fc0370d5781a3279780
parentbbf6ae9b1790c7129bf249641350b302def3ee27 (diff)
downloadsms-utils-fea5d250ef5dd8d2b13aa0748b38e621e5eec6f4.tar.gz
sms-utils-fea5d250ef5dd8d2b13aa0748b38e621e5eec6f4.tar.bz2
sms-utils-fea5d250ef5dd8d2b13aa0748b38e621e5eec6f4.zip
fix: cdma send length | also some refactoring & added comments
-rw-r--r--src/pdu.h21
-rw-r--r--src/pdu_decode.c96
-rw-r--r--src/pdu_encode.c41
3 files changed, 100 insertions, 58 deletions
diff --git a/src/pdu.h b/src/pdu.h
index 0143f1f..35c43a6 100644
--- a/src/pdu.h
+++ b/src/pdu.h
@@ -49,12 +49,13 @@ enum {
PDU_VPF_ABSOUTE = 3,
};
+//PDU data formats (how the data was represented before encoding)
enum {
- PDU_ALPHABET_DEFAULT = 0, //7-bit
- PDU_ALPHABET_CDMA_DEFAULT = 2, //7-bit
- PDU_ALPHABET_EIGHT = 4,
- PDU_ALPHABET_CDMA_EIGHT = 8,
- PDU_ALPHABET_DEFAULT_MULTI = 9,
+ PDU_ALPHABET_DEFAULT = 0, //GSM 7-bit, (supposedly CDMA 8-bit but haven't seen it)
+ PDU_ALPHABET_CDMA_DEFAULT = 2, //no GSM, CDMA 7-bit
+ PDU_ALPHABET_EIGHT = 4, //GSM 8-bit, CDMA 16-bit unicode
+ PDU_ALPHABET_CDMA_EIGHT = 8, //GSM 16-bit, CDMA 8-bit (what CDMA radios are actually using)
+ PDU_ALPHABET_DEFAULT_MULTI = 9,//no GSM, LVW2 7-bit, multi-part
};
struct pdu_info {
@@ -117,10 +118,14 @@ int pdu_user_data_read(int fd, struct pdu_info *pdu);
#define cycleup(n, mod) ((n) % (mod))
#define cycledown(n, mod) ((mod - 1) - ((n) % (mod)))
-#define octet_align(n) ((((n) * 7) + ((-(n) * 7) & 7)) / 8)
+//Returns the number of octets the given septets (normal ascii) can be encoded to
+#define octets_from_septets(n) ((((n) * 7) + ((-(n) * 7) & 7)) / 8)
-#define septet_idx(n) ((n) * 8 / 7)
-#define octet_align_cdma(n) septet_idx(n)
+//Returns the number of septets the given octets will decode to
+#define septets_from_octets(n) ((n) * 8 / 7)
+
+#define octet_idx(n) octets_from_septets(n)
+#define septet_idx(n) septets_from_octets(n)
#define STRLEN_CHECK(str, len, ret) \
diff --git a/src/pdu_decode.c b/src/pdu_decode.c
index 459916c..27822f3 100644
--- a/src/pdu_decode.c
+++ b/src/pdu_decode.c
@@ -163,16 +163,14 @@ done:
return pdu_str - begin;
}
-#define octet_idx(n) octet_align(n)
-#define octet_cdma_idx(n) ((n+1) * 7 / 8)
-#define decode_septet(buf, n) \
+#define decode_septet_from_octet(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))
-#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
+#define decode_cdma_septet_from_octet(buf, n) \
+shiftr(buf[octet_idx(n)], cycleup(n, 8) + 1) | \
+shiftl(buf[octet_idx(n) - 1], cycledown(n, 8)) & 0x7F
int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octets)
{
@@ -195,19 +193,19 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
return -1;
}
- if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) {
- log_debug("data coding alphabet is default");
- 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;
- }
-
- *nr_octets = octet_align(pdu->user_data_len);
- } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI) {
- //GSM style 8 bit conversion but with UDH multi-part header (LE910-SVG)
- log_debug("data coding alphabet is nine");
+ // -----------------------------------------------------------------------------
+ // VERIFY DATA LENGTH AND GET NUMBER OF OCTETS (ACTUAL DATA BYTES IN PDU STRING)
+ // -----------------------------------------------------------------------------
+ if ((pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) ||
+ (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)) {
+ if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI) {
+ //GSM style 7-bit encoding but with UDH multi-part header (LE910-SVG)
+ log_debug("data coding alphabet is nine");
+ } else {
+ //GSM 7-bit encoding
+ log_debug("data coding alphabet is default");
+ }
if (pdu->user_data_len > PDU_UD_7BIT_MAX) {
log_warning("pdu contains invalid user-data-len: 0x%02X",
@@ -215,31 +213,30 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
pdu->user_data_len = PDU_UD_7BIT_MAX;
}
- *nr_octets = octet_align(pdu->user_data_len);
+ //GSM 7-bit data (septets) length is encoded in PDU as number of septets
+ // (which is same as user_data_len), but octets is needed for decoding loop
+ *nr_octets = octets_from_septets(pdu->user_data_len);
+
+ // CDMA 7-BIT ENCODING
} else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) {
log_debug("data coding alphabet is cdma default");
- // Encoding 02 is 7 bit for LE910-SVG but 8 bit for other CDMA radios
+ // LE910-SVG stores data length as # of septets
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;
- }
+ *nr_octets = octets_from_septets(pdu->user_data_len);
}
+ // Other CDMA radios store data length as # of octets
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;
- }
+ *nr_octets = pdu->user_data_len;
+ pdu->user_data_len = septets_from_octets(pdu->user_data_len);
}
- 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);
+ 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;
}
+
+ // GSM & CDMA 8-BIT ENCODING
} else if ((pdu->data_coding.general.alphabet == PDU_ALPHABET_EIGHT) ||
(pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_EIGHT)) {
log_debug("data coding alphabet is eight");
@@ -250,7 +247,11 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
pdu->user_data_len = PDU_UD_8BIT_MAX;
}
+ //Original data is octets (all 8 bits could contain data)
+ //Therefore, octets = user_data_len
*nr_octets = pdu->user_data_len;
+
+ // UNSUPPORTED
} else {
log_debug("data coding alphabet 0x%02X not implemented",
pdu->data_coding.general.alphabet);
@@ -259,14 +260,20 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
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 (encoded data length)", *nr_octets);
+ log_debug("user-data-len: 0x%02X (decoded data length)", pdu->user_data_len);
+ //Copy user data from pdu string into octets
for (i = 0; i < *nr_octets; i++) {
octets[i] = hex_byte_decode(pdu_str);
pdu_str += HEX_BYTE_LEN;
}
+
+ // ---------------------------------------------------------
+ // DECODE USER DATA (IF NEEDED) AND COPY INTO pdu->user_data
+ // ---------------------------------------------------------
+ // GSM 7-BIT & LVW2 7-BIT MULTI-PART
if ((pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) ||
(pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)) {
// Keep UDH for concatenated SMS.
@@ -284,12 +291,15 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
i++;
}
}
+
user_data_start_index = i;
for (; i < pdu->user_data_len; i++) {
- pdu->user_data[i] = decode_septet(octets, i);
+ pdu->user_data[i] = decode_septet_from_octet(octets, i);
log_debug("DECODE: i: %d octet: 0x%02X --> data: 0x%02X", i, octets[i], pdu->user_data[i]);
}
pdu->user_data[i] = '\0';
+
+ // CDMA 7-BIT
} 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.
@@ -305,10 +315,12 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
i++;
}
}
+
for (; i < pdu->user_data_len; i++) {
- pdu->user_data[i] = decode_septet_cdma(octets, i);
+ pdu->user_data[i] = decode_cdma_septet_from_octet(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");
@@ -316,6 +328,8 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
pdu->user_data_len--;
}
pdu->user_data[i] = '\0';
+
+ // ALL 8-BIT ENCODING
} else {
for (i = 0; i < pdu->user_data_len; i++) {
pdu->user_data[i] = octets[i];
@@ -323,7 +337,11 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe
pdu->user_data[i] = '\0';
}
- //Only for GSM 7-bit character set
+
+ // ---------------------------------------------------------------------
+ // FOR GSM 7-BIT ENCODING ONLY, DECODE FROM GSM ALPHABET TO IRA ALPHABET
+ // (includes LVW2 multi-part)
+ // ---------------------------------------------------------------------
if ((pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) ||
(pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)) {
int read = user_data_start_index;
diff --git a/src/pdu_encode.c b/src/pdu_encode.c
index ce62ee8..4d43eac 100644
--- a/src/pdu_encode.c
+++ b/src/pdu_encode.c
@@ -183,7 +183,9 @@ int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu, int *n
}
- //Convert to GSM character set, Only for 7-bit character set
+ // ---------------------------------------------------------------------
+ // FOR GSM 7-BIT ENCODING ONLY, ENCODE FROM IRA ALPHABET TO GSM ALPHABET
+ // ---------------------------------------------------------------------
if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) {
int read = 0;
int store = 0;
@@ -226,28 +228,36 @@ int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu, int *n
}
+ // ------------------------------
+ // ENCODE USER DATA INTO PDU DATA
+ // ------------------------------
+ // GSM 7-BIT ENCODING
if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) {
if (pdu->user_data_len > PDU_UD_7BIT_MAX) {
log_error("string exceeds 7-bit data max length");
return -1;
}
- *nr_octets = octet_align(pdu->user_data_len);
+ *nr_octets = octets_from_septets(pdu->user_data_len);
for (i = 0; i < *nr_octets; i++) {
octets[i] = encode_octet(pdu->user_data, i);
+ log_debug("ENCODE: i: %d data: 0x%02X --> octet: 0x%02X", i, pdu->user_data[i], octets[i]);
}
+
+ // CDMA 7-BIT ENCODING
} else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) {
if (pdu->user_data_len > PDU_UD_7BIT_MAX) {
log_error("string exceeds 7-bit data max length");
return -1;
}
- //CDMA ENCODING
- *nr_octets = octet_align(pdu->user_data_len);
- pdu->user_data_len = *nr_octets;
+ *nr_octets = octets_from_septets(pdu->user_data_len);
for (i = 0; i < *nr_octets; i++) {
octets[i] = encode_cdma_octet(pdu->user_data, i);
+ log_debug("ENCODE: i: %d data: 0x%02X --> octet: 0x%02X", i, pdu->user_data[i], octets[i]);
}
+
+ // ALL 8-BIT ENCODING
} else {
if (pdu->user_data_len > PDU_UD_8BIT_MAX) {
log_error("string exceeds 8-bit data max length");
@@ -265,10 +275,19 @@ int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu, int *n
return -1;
}
- tmp = hex_byte_encode(pdu_str, len, pdu->user_data_len);
- ENCODE_FAIL(tmp != HEX_BYTE_LEN, "user-data-len", -1);
- pdu_str += tmp;
- len -= tmp;
+ if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) {
+ // user_data_len is stored as number of encoded octets
+ // (but GSM is stored as originial # of septets)
+ log_debug("putting nr_octets into PDU as data length (CDMA)");
+ tmp = hex_byte_encode(pdu_str, len, *nr_octets);
+ }
+ else {
+ log_debug("putting user_data_len into PDU as data length");
+ tmp = hex_byte_encode(pdu_str, len, pdu->user_data_len);
+ }
+ ENCODE_FAIL(tmp != HEX_BYTE_LEN, "user-data-len", -1);
+ pdu_str += tmp;
+ len -= tmp;
for (i = 0; i < *nr_octets; i++) {
hex_byte_encode(pdu_str, len, octets[i]);
@@ -277,8 +296,8 @@ int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu, int *n
len -= *nr_octets * 2;
pdu_str[i] = '\0';
- log_debug("user-data-len: 0x%02X", pdu->user_data_len);
- log_debug("nr_octets: 0x%02X", *nr_octets);
+ log_debug("user-data-len: 0x%02X (before encoding)", pdu->user_data_len);
+ log_debug("nr_octets: 0x%02X (after encoding)", *nr_octets);
return pdu_str - begin;
}