summaryrefslogtreecommitdiff
path: root/src/pdu_encode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdu_encode.c')
-rw-r--r--src/pdu_encode.c125
1 files changed, 111 insertions, 14 deletions
diff --git a/src/pdu_encode.c b/src/pdu_encode.c
index 30cb4a9..1bb7e4d 100644
--- a/src/pdu_encode.c
+++ b/src/pdu_encode.c
@@ -39,6 +39,8 @@ do { \
} \
} while (0)
+#define CEIL(X) ((X-(int)(X)) > 0 ? (int)(X+1) : (int)(X))
+
int pdu_encode_timestamp(char *pdu_str, size_t len, struct tm *tm)
{
int tmp;
@@ -75,7 +77,7 @@ int pdu_encode_timestamp(char *pdu_str, size_t len, struct tm *tm)
strpad(pdu_str, PDU_TIMESTAMP_LEN, 'F');
nibble_swap(pdu_str, PDU_TIMESTAMP_LEN);
- log_debug("%s", pdu_str);
+ log_debug("encode_timestamp: %s", pdu_str);
return PDU_TIMESTAMP_LEN;
}
@@ -86,7 +88,17 @@ int pdu_encode_addr(char *pdu_str, size_t len, struct pdu_addr *addr, int smsc)
int addr_len;
int tmp;
- addr_len = strlen(addr->addr);
+ if (isCdmaTypeModel()) {
+ //CDMA length is # of bytes including address type
+ //Ex: Type: 80 #: 9132074666 --> 80 19 23 70 64 66 => 6 bytes
+ addr_len = 1; //1 byte for address type
+ addr_len += CEIL(strlen(addr->addr) / 2); //Number of hex bytes
+ }
+ else {
+ //GSM length is # of digits in converted number
+ //Ex: Type: 81 #: 9132074666 --> 1923706466 => 10 digits
+ addr_len = strlen(addr->addr);
+ }
if (smsc) {
if (addr_len) {
@@ -136,18 +148,20 @@ done:
return pdu_str - begin;
}
-#define septet_idx(n) ((n) * 8 / 7)
+
#define encode_octet(buf, n) \
shiftr(bit_maskl(cycledown(n, 7) + 1, 7) & buf[septet_idx(n)], cycleup(n, 7)) | \
shiftl(bit_maskr(cycleup(n, 7) + 1) & buf[septet_idx(n) + 1], cycledown(n, 7) + 1)
-int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu)
+#define encode_cdma_octet(buf, n) \
+shiftl(buf[septet_idx(n)], cycleup(n, 7) + 1) | shiftr(buf[septet_idx(n) + 1], cycledown(n, 7))
+
+int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu, int *nr_octets)
{
char *begin = pdu_str;
int tmp;
uint8_t octets[PDU_OCTETS_MAX];
- int nr_octets;
int i;
if (pdu->data_coding.general.unused) {
@@ -157,9 +171,11 @@ int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu)
}
if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) {
- log_debug("data coding alphabet is default");
+ log_debug("data coding alphabet is default (7-bit)");
} else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_EIGHT) {
log_debug("data coding alphabet is eight");
+ } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) {
+ log_debug("data coding alphabet is CDMA default (7-bit)");
} else {
log_debug("data coding alphabet 0x%02X not implemented",
pdu->data_coding.general.alphabet);
@@ -172,23 +188,35 @@ int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu)
return -1;
}
- nr_octets = octet_align(pdu->user_data_len);
- for (i = 0; i < nr_octets; i++) {
+ *nr_octets = octet_align(pdu->user_data_len);
+ for (i = 0; i < *nr_octets; i++) {
octets[i] = encode_octet(pdu->user_data, i);
}
+ } 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;
+ for (i = 0; i < *nr_octets; i++) {
+ octets[i] = encode_cdma_octet(pdu->user_data, i);
+ }
} else {
if (pdu->user_data_len > PDU_UD_8BIT_MAX) {
log_error("string exceeds 8-bit data max length");
return -1;
}
- nr_octets = pdu->user_data_len;
+ *nr_octets = pdu->user_data_len;
for (i = 0; i < pdu->user_data_len; i++) {
octets[i] = pdu->user_data[i];
}
}
- if (len < nr_octets * 2 + HEX_BYTE_LEN + 1) {
+ if (len < *nr_octets * 2 + HEX_BYTE_LEN + 1) {
log_error("buffer is not large enough to hold user-data");
return -1;
}
@@ -198,15 +226,15 @@ int pdu_encode_user_data(char *pdu_str, size_t len, struct pdu_info *pdu)
pdu_str += tmp;
len -= tmp;
- for (i = 0; i < nr_octets; i++) {
+ for (i = 0; i < *nr_octets; i++) {
hex_byte_encode(pdu_str, len, octets[i]);
pdu_str += HEX_BYTE_LEN;
}
- len -= nr_octets * 2;
+ 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("nr_octets: 0x%02X", *nr_octets);
return pdu_str - begin;
}
@@ -216,6 +244,7 @@ int pdu_encode(char *pdu_str, size_t len, struct pdu_info *pdu)
char *begin = pdu_str;
char *msg_begin = pdu_str;
int tmp;
+ int nr_octets;
tmp = pdu_encode_addr(pdu_str, len, &pdu->smsc_addr, 1);
ENCODE_FAIL(tmp < 0, "smsc-addr", -1);
@@ -293,7 +322,7 @@ int pdu_encode(char *pdu_str, size_t len, struct pdu_info *pdu)
pdu_str += tmp;
}
- tmp = pdu_encode_user_data(pdu_str, len, pdu);
+ tmp = pdu_encode_user_data(pdu_str, len, pdu, &nr_octets);
ENCODE_FAIL(tmp < 0, "user-data", -1);
len -= tmp;
pdu_str += tmp;
@@ -305,3 +334,71 @@ int pdu_encode(char *pdu_str, size_t len, struct pdu_info *pdu)
return pdu_str - begin;
}
+
+int pdu_encode_cdma(char *pdu_str, size_t len, struct pdu_info *pdu)
+{
+ char *begin = pdu_str;
+ char *msg_begin = pdu_str;
+ int tmp;
+ int nr_octets;
+
+ //Set pdu encoding for CDMA
+ pdu->data_coding.general.alphabet = PDU_ALPHABET_CDMA_DEFAULT;
+
+ //Destination address
+ tmp = pdu_encode_addr(pdu_str, len, &pdu->addr, 0);
+ ENCODE_FAIL(tmp < 0, "addr", -1);
+ len -= tmp;
+ pdu_str += tmp;
+
+ //Callback address (Always 00 because it's empty)
+ tmp = hex_byte_encode(pdu_str, len, 0);
+ ENCODE_FAIL(tmp != HEX_BYTE_LEN, "callback-addr-len", -1);
+ pdu_str += tmp;
+ len -= tmp;
+
+ //Teleservice ID (always 1002)
+ tmp = hex_byte_encode(pdu_str, len, 16);
+ ENCODE_FAIL(tmp != HEX_BYTE_LEN, "tele-id-1", -1);
+ pdu_str += tmp;
+ len -= tmp;
+ tmp = hex_byte_encode(pdu_str, len, 2);
+ ENCODE_FAIL(tmp != HEX_BYTE_LEN, "tele-id-2", -1);
+ pdu_str += tmp;
+ len -= tmp;
+
+ //Priority (always 00 for normal)
+ tmp = hex_byte_encode(pdu_str, len, 0);
+ ENCODE_FAIL(tmp != HEX_BYTE_LEN, "priority", -1);
+ pdu_str += tmp;
+ len -= tmp;
+
+ switch (pdu->type.msg_type) {
+ case PDU_MTI_REPORT:
+ log_error("msg_type PDU_MTI_REPORT not supported!");
+ return 0;
+
+ case PDU_MTI_DELIVER:
+ log_debug("msg_type: PDU_MTI_DELIVER");
+ case PDU_MTI_SUBMIT:
+ log_debug("msg_type: PDU_MTI_SUBMIT");
+
+ //add data coding scheme
+ tmp = hex_byte_encode(pdu_str, len, pdu->data_coding.data_coding);
+ ENCODE_FAIL(tmp != HEX_BYTE_LEN, "data-coding-scheme", -1);
+ len -= tmp;
+ pdu_str += tmp;
+
+
+ tmp = pdu_encode_user_data(pdu_str, len, pdu, &nr_octets);
+ ENCODE_FAIL(tmp < 0, "user-data", -1);
+ len -= tmp;
+ pdu_str += tmp;
+ }
+
+ // pdu->msg_len = (pdu_str - msg_begin) / 2;
+ pdu->msg_len = 6 + nr_octets;
+ log_debug("msg-len: %d", pdu->msg_len);
+
+ return pdu_str - begin;
+}