diff options
Diffstat (limited to 'src/pdu_encode.c')
-rw-r--r-- | src/pdu_encode.c | 125 |
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; +} |