From cd38e2b12d6f13dfd03eed207aa7f262e00099f1 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 6 Jan 2023 16:57:35 +0200 Subject: [GP-1842] Refactoring - Fixed indentations This project uses tabs, not spaces. Make the indentation consistent. --- src/atcmd.c | 118 ++++---- src/pdu_decode.c | 878 +++++++++++++++++++++++++++---------------------------- src/pdu_encode.c | 780 ++++++++++++++++++++++++------------------------ src/phonebook.c | 2 +- src/sms_list.c | 16 +- src/sms_send.c | 72 ++--- src/utils.c | 16 +- 7 files changed, 941 insertions(+), 941 deletions(-) diff --git a/src/atcmd.c b/src/atcmd.c index b988a57..7c39313 100644 --- a/src/atcmd.c +++ b/src/atcmd.c @@ -873,17 +873,17 @@ int atcmd_plus_cpms_read(int fd, struct data_store *read_store, char *token; int tmp; int i; - int data_stores_size; + int data_stores_size; struct data_store *store; - struct data_store *data_stores[] = {read_store, send_store, new_store}; + struct data_store *data_stores[] = {read_store, send_store, new_store}; - if (isCdmaTypeModel()) { - data_stores_size = 2; - } - else { - data_stores_size = 3; - } + if (isCdmaTypeModel()) { + data_stores_size = 2; + } + else { + data_stores_size = 3; + } atcmd_writeline(fd, "AT+CPMS?"); tmp = atcmd_expect_line(fd, buf, sizeof(buf), "+CPMS: "); @@ -944,7 +944,7 @@ int atcmd_plus_cpms_test(int fd, struct store_locations *read_loc, int tmp; int i, j; - struct store_locations *locations[] = {read_loc, send_loc, new_loc}; + struct store_locations *locations[] = {read_loc, send_loc, new_loc}; struct store_locations *loc; atcmd_writeline(fd, "AT+CPMS=?"); @@ -1006,14 +1006,14 @@ int atcmd_plus_cpms_write(int fd, const char *read_name, char buf[ATCMD_LINE_SIZE]; int tmp; - if (isCdmaTypeModel()) { - atcmd_writeline(fd, "AT+CPMS=\"%s\",\"%s\"", read_name, send_name); - } - else - { - atcmd_writeline(fd, "AT+CPMS=\"%s\",\"%s\",\"%s\"", - read_name, send_name, new_name); - } + if (isCdmaTypeModel()) { + atcmd_writeline(fd, "AT+CPMS=\"%s\",\"%s\"", read_name, send_name); + } + else + { + atcmd_writeline(fd, "AT+CPMS=\"%s\",\"%s\",\"%s\"", + read_name, send_name, new_name); + } tmp = atcmd_expect_line(fd, buf, sizeof(buf), "OK"); if (tmp <= 0) { log_debug("expected OK but it was not received"); @@ -1224,15 +1224,15 @@ int atcmd_plus_gmm_read(int fd) int tmp; atcmd_writeline(fd, "AT+GMM"); - //Swallow extra "\r\n" - tmp = atcmd_readline(fd, buf, sizeof(buf)); + //Swallow extra "\r\n" + tmp = atcmd_readline(fd, buf, sizeof(buf)); if (tmp <= 0) { log_debug("expected \\r\\n but it was not received"); return -1; } - //Read model string - tmp = atcmd_readline(fd, buf, sizeof(buf)); + //Read model string + tmp = atcmd_readline(fd, buf, sizeof(buf)); if (tmp <= 0) { log_debug("expected model but it was not received"); return -1; @@ -1313,7 +1313,7 @@ int atcmd_plus_iccid_read(int fd) if (is_telit_model()) { command = "AT#CCID"; if (strstr(Global.core.model, "FN980")) { - command = "AT+ICCID"; + command = "AT+ICCID"; } } else if (is_quectel_model()) { command = "AT+QCCID"; @@ -1323,18 +1323,18 @@ int atcmd_plus_iccid_read(int fd) } atcmd_writeline(fd, command); - //Swallow extra "\r\n" - tmp = atcmd_readline(fd, buf, sizeof(buf)); + //Swallow extra "\r\n" + tmp = atcmd_readline(fd, buf, sizeof(buf)); if (tmp <= 0) { log_debug("expected \\r\\n but it was not received"); return -1; } - //Read iccid string - tmp = atcmd_readline(fd, buf, sizeof(buf)); + //Read iccid string + tmp = atcmd_readline(fd, buf, sizeof(buf)); if (tmp <= 0) { log_debug("expected ICCID but it was not received"); - /* Currently only LNA3 models will need the ICCID */ + /* Currently only LNA3 models will need the ICCID */ return -1; } @@ -1347,7 +1347,7 @@ int atcmd_plus_iccid_read(int fd) } else { log_debug("token is %s",token); } - tmp_buf = strrchr(token,' '); + tmp_buf = strrchr(token,' '); if (tmp_buf) { token = ++tmp_buf; log_debug("Found blank, incrementing tmp"); @@ -1421,19 +1421,19 @@ static int sms_atcmd_init(int fd) tmp = atcmd_plus_gmm_read(fd); if (tmp < 0) { - log_error("failed to read radio model"); + log_error("failed to read radio model"); return -1; } tmp = atcmd_plus_gmi_read(fd); if (tmp < 0) { - log_error("failed to read radio manufacturer"); + log_error("failed to read radio manufacturer"); return -1; } - tmp = atcmd_plus_iccid_read(fd); + tmp = atcmd_plus_iccid_read(fd); if (tmp < 0) { - log_error("failed to read SIM ICCID"); + log_error("failed to read SIM ICCID"); return -1; } @@ -1446,22 +1446,22 @@ static int sms_atcmd_init(int fd) memset(&send_store, 0, sizeof(send_store)); memset(&new_store, 0, sizeof(new_store)); - if (!strcmp(Global.core.model, "CE910-DUAL") || !strcmp(Global.core.model, "DE910-DUAL")) { - log_info("Changing message storage locations to ME for CE/DE910-DUAL"); - free(Global.core.msg_store_read); - free(Global.core.msg_store_send); - free(Global.core.pb_store); - Global.core.msg_store_read = strdup("ME"); - Global.core.msg_store_send = strdup("ME"); - Global.core.pb_store = strdup("ME"); - } + if (!strcmp(Global.core.model, "CE910-DUAL") || !strcmp(Global.core.model, "DE910-DUAL")) { + log_info("Changing message storage locations to ME for CE/DE910-DUAL"); + free(Global.core.msg_store_read); + free(Global.core.msg_store_send); + free(Global.core.pb_store); + Global.core.msg_store_read = strdup("ME"); + Global.core.msg_store_send = strdup("ME"); + Global.core.pb_store = strdup("ME"); + } atcmd_plus_cpms_test(fd, &read_store.choices, &send_store.choices, &new_store.choices); atcmd_plus_cpms_read(fd, &read_store.selected, &send_store.selected, &new_store.selected, Global.core.model); if (Global.core.msg_store_read && Global.core.msg_store_send && - Global.core.msg_store_new) { + Global.core.msg_store_new) { if (!msg_store_choice(&read_store, Global.core.msg_store_read)) { log_error("message storage location %s is not a choice", @@ -1474,7 +1474,7 @@ static int sms_atcmd_init(int fd) return -1; } - //Doesn't apply to CDMA type radios + //Doesn't apply to CDMA type radios if (!isCdmaTypeModel() && !msg_store_choice(&new_store, Global.core.msg_store_new)) { log_error("message storage location %s is not a choice", Global.core.msg_store_new); @@ -1545,17 +1545,17 @@ int sms_device_open(void) int is_vzw_lte(void) { - if (!strcmp(Global.core.model, "LE910-NA1")) { - log_debug("Found LE910-NA1"); - /* Verizon Wireless SIM */ - if (strncmp(Global.core.iccid,"891480",6) == 0) { - log_debug("Found VZW SIM"); - return 1; - } - } - - return (!strncmp(Global.core.model, "LE910-SVG", MODEL_LEN) || - !strncmp(Global.core.model, "LE910-SV1", MODEL_LEN)); + if (!strcmp(Global.core.model, "LE910-NA1")) { + log_debug("Found LE910-NA1"); + /* Verizon Wireless SIM */ + if (strncmp(Global.core.iccid,"891480",6) == 0) { + log_debug("Found VZW SIM"); + return 1; + } + } + + return (!strncmp(Global.core.model, "LE910-SVG", MODEL_LEN) || + !strncmp(Global.core.model, "LE910-SV1", MODEL_LEN)); } /* Detect LNA7/L4G1 radio with Verizon SIM */ @@ -1576,12 +1576,12 @@ int is_quectel_dual_sms_format(void) int isCdmaTypeModel() { - /* Test for possible dual firmware model */ - if (is_vzw_lte()) - return 1; + /* Test for possible dual firmware model */ + if (is_vzw_lte()) + return 1; - return (!strncmp(Global.core.model, "DE910-DUAL", MODEL_LEN) || - !strncmp(Global.core.model, "CE910-DUAL", MODEL_LEN)); + return (!strncmp(Global.core.model, "DE910-DUAL", MODEL_LEN) || + !strncmp(Global.core.model, "CE910-DUAL", MODEL_LEN)); } int is_telit_model() diff --git a/src/pdu_decode.c b/src/pdu_decode.c index 9c0ced5..7f76ff5 100644 --- a/src/pdu_decode.c +++ b/src/pdu_decode.c @@ -37,134 +37,134 @@ #define DECODE_FAIL(cond, name, ret) \ do { \ - if (cond) { \ - log_error("decode failed at %s", name); \ - return ret; \ - } \ + if (cond) { \ + log_error("decode failed at %s", name); \ + return ret; \ + } \ } while (0) int pdu_decode_timestamp(const char *pdu_str, struct tm *tm) { - char buf[PDU_TIMESTAMP_SIZE + 3]; - char *cp; - int off_upper; - int off_lower; - int off; + char buf[PDU_TIMESTAMP_SIZE + 3]; + char *cp; + int off_upper; + int off_lower; + int off; - STRLEN_CHECK(pdu_str, PDU_TIMESTAMP_LEN, -1); + STRLEN_CHECK(pdu_str, PDU_TIMESTAMP_LEN, -1); - memset(tm, 0, sizeof(*tm)); - memset(buf, 0, sizeof(buf)); + memset(tm, 0, sizeof(*tm)); + memset(buf, 0, sizeof(buf)); - strncpy(buf, pdu_str, PDU_TIMESTAMP_LEN); - nibble_swap(buf, PDU_TIMESTAMP_LEN); - strunpad(buf, 'F'); + strncpy(buf, pdu_str, PDU_TIMESTAMP_LEN); + nibble_swap(buf, PDU_TIMESTAMP_LEN); + strunpad(buf, 'F'); - off_upper = hex_nibble_scan(buf + GMT_OFFSET_IDX, 1); - off_lower = hex_nibble_scan(buf + GMT_OFFSET_IDX + 1, 1); + off_upper = hex_nibble_scan(buf + GMT_OFFSET_IDX, 1); + off_lower = hex_nibble_scan(buf + GMT_OFFSET_IDX + 1, 1); - if (off_upper & BIT(3)) { - off_upper &= ~BIT(3); - buf[GMT_OFFSET_IDX] = '-'; - } else { - buf[GMT_OFFSET_IDX] = '+'; - } + if (off_upper & BIT(3)) { + off_upper &= ~BIT(3); + buf[GMT_OFFSET_IDX] = '-'; + } else { + buf[GMT_OFFSET_IDX] = '+'; + } - off = (off_upper * 10 + off_lower) * 15; + off = (off_upper * 10 + off_lower) * 15; - snprintf(buf + GMT_OFFSET_IDX + 1, 5, "%02d%02d", off / 60, off % 60); + snprintf(buf + GMT_OFFSET_IDX + 1, 5, "%02d%02d", off / 60, off % 60); - cp = (char *) strptime(buf, "%y%m%d%H%M%S%z", tm); - if (!cp || *cp) { - log_error("timestamp could not be converted to tm"); - return -1; - } + cp = (char *) strptime(buf, "%y%m%d%H%M%S%z", tm); + if (!cp || *cp) { + log_error("timestamp could not be converted to tm"); + return -1; + } - return PDU_TIMESTAMP_LEN; + 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; + char buf[PDU_CDMA_TIMESTAMP_LEN + 1]; + char *cp; - STRLEN_CHECK(pdu_str, PDU_CDMA_TIMESTAMP_LEN, -1); + STRLEN_CHECK(pdu_str, PDU_CDMA_TIMESTAMP_LEN, -1); - memset(tm, 0, sizeof(*tm)); - memset(buf, 0, sizeof(buf)); + memset(tm, 0, sizeof(*tm)); + memset(buf, 0, sizeof(buf)); - strncpy(buf, pdu_str, PDU_CDMA_TIMESTAMP_LEN); + 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; - } + 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; + return PDU_CDMA_TIMESTAMP_LEN; } int pdu_decode_addr(const char *pdu_str, struct pdu_addr *addr, int smsc) { - const char *begin = pdu_str; - int addr_len; - int tmp; - - memset(addr, 0, sizeof(*addr)); - - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "addr-len", -1); - pdu_str += HEX_BYTE_LEN; - addr->len = tmp; - - addr_len = addr->len; - if (smsc) { - if (!addr_len) { - goto done; - } - addr_len = addr_len * HEX_BYTE_LEN - HEX_BYTE_LEN; - } else { - if (addr_len & 1) { - addr_len++; - } - } - - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "addr-type", -1); - pdu_str += HEX_BYTE_LEN; - addr->type = tmp; - - if (addr_len < 0 || addr_len >= sizeof(addr->addr)) { - log_error("invalid length: 0x%02X", addr_len); - return -1; - } - - log_debug("addr-len [transformed]: 0x%02X", addr_len); - log_debug("addr-type: 0x%02X", addr->type); - - STRLEN_CHECK(pdu_str, addr_len, -1); - - strncpy(addr->addr, pdu_str, addr_len); - - nibble_swap(addr->addr, addr_len); - strunpad(addr->addr, 'F'); - if(addr->type == 0x91) {//91 indicates international format of the phone number - memmove(&addr->addr[1],addr->addr,addr_len); - addr->addr[0]='+'; - }; - pdu_str += addr_len; + const char *begin = pdu_str; + int addr_len; + int tmp; + + memset(addr, 0, sizeof(*addr)); + + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + + tmp = hex_byte_decode(pdu_str); + DECODE_FAIL(tmp < 0, "addr-len", -1); + pdu_str += HEX_BYTE_LEN; + addr->len = tmp; + + addr_len = addr->len; + if (smsc) { + if (!addr_len) { + goto done; + } + addr_len = addr_len * HEX_BYTE_LEN - HEX_BYTE_LEN; + } else { + if (addr_len & 1) { + addr_len++; + } + } + + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + + tmp = hex_byte_decode(pdu_str); + DECODE_FAIL(tmp < 0, "addr-type", -1); + pdu_str += HEX_BYTE_LEN; + addr->type = tmp; + + if (addr_len < 0 || addr_len >= sizeof(addr->addr)) { + log_error("invalid length: 0x%02X", addr_len); + return -1; + } + + log_debug("addr-len [transformed]: 0x%02X", addr_len); + log_debug("addr-type: 0x%02X", addr->type); + + STRLEN_CHECK(pdu_str, addr_len, -1); + + strncpy(addr->addr, pdu_str, addr_len); + + nibble_swap(addr->addr, addr_len); + strunpad(addr->addr, 'F'); + if (addr->type == 0x91) {//91 indicates international format of the phone number + memmove(&addr->addr[1],addr->addr,addr_len); + addr->addr[0]='+'; + }; + pdu_str += addr_len; done: - log_debug("addr: %s", addr->addr); - log_debug("addr-len: 0x%02X", addr->len); + log_debug("addr: %s", addr->addr); + log_debug("addr-len: 0x%02X", addr->len); - return pdu_str - begin; + return pdu_str - begin; } @@ -178,400 +178,400 @@ 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) { - const char *begin = pdu_str; - int tmp; - uint8_t octets[PDU_OCTETS_MAX + 1]; - int user_data_start_index = 0; - int i; - - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "user-data-len", -1); - pdu_str += HEX_BYTE_LEN; - pdu->user_data_len = tmp; - - if (pdu->data_coding.general.unused) { - log_error("data coding group 0x%02X not implemented", - pdu->data_coding.data_coding & 0xF0); - return -1; - } - - - if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT || - pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT2 ) - { - log_debug("data coding alphabet is default (7-bit)"); - } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI) { - log_debug("data coding alphabet is default (7-bit) multi-part"); - } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) { - log_debug("data coding alphabet is CDMA 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_EIGHT) { - log_debug("data coding alphabet is CDMA eight"); - } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_TE) { - log_debug("data coding alphabet is TE specific 7-bit"); - } else { - log_debug("data coding alphabet 0x%02X not implemented", - pdu->data_coding.general.alphabet); - return -1; - } - - // ----------------------------------------------------------------------------- - // 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_DEFAULT2) || - (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)|| - (pdu->data_coding.general.alphabet == PDU_ALPHABET_TE)) { - 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 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) { - if (is_vzw_lte()) { - // LE910-SVG stores data length as # of septets - log_debug("counting PDU length byte as number of septets (LE910-SVG/LE910-SV1/LE910-NA1/VZW)"); - *nr_octets = octets_from_septets(pdu->user_data_len); - } - else { - // Other CDMA radios store data length as # of octets - // NOTE: CE910 send PDU needs # of septets but receive PDU is in # of octets - log_debug("counting PDU length byte as number of octets"); - *nr_octets = pdu->user_data_len; - pdu->user_data_len = septets_from_octets(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)) { - 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; - } - - //Original data is octets (all 8 bits could contain data) - //Therefore, octets = user_data_len - *nr_octets = pdu->user_data_len; - } - - STRLEN_CHECK(pdu_str, *nr_octets * 2, -1); - - 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_DEFAULT2) || - (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)|| - (pdu->data_coding.general.alphabet == PDU_ALPHABET_TE)) { - // Keep UDH for concatenated SMS ONLY. - // Otherwise it is impossible to process correctly concatenated SMS. - i = 0; - if (pdu->type.user_data_header || - // For LVW3, LNA3 and LVW2 - Save header ONLY when it's actually a multi-part message. - // Multi-part messages should use Teleservice ID 4101 (0x1005) in LVW2 7-BIT MULTI-PART format. - // See 3GPP2 X.S0004-550-E for details on Teleservice ID. - (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI - && pdu->teleservice_id == PDU_TELE_ID_CDMA_WEMT)) { - 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++; - } - } - - user_data_start_index = i; - for (; i < pdu->user_data_len; 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. - 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_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 (!is_vzw_lte() && (pdu->user_data[i-1] == 0)) { - log_debug("Removing padded char"); - i--; - 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]; - } - pdu->user_data[i] = '\0'; - } - - - // --------------------------------------------------------------------- - // 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_DEFAULT2) || - (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)) { - int read = user_data_start_index; - int store = user_data_start_index; - - log_debug("Converting from GSM character set to IRA"); - for (; read < pdu->user_data_len; read++) { - if (pdu->user_data[read] == 0x1B) { - //Character from the extended set using the escape char (27) - read++; - log_debug("GSM before: 0x1B%02X | IRA after: 0x%02X", pdu->user_data[read], strExtendedTable[pdu->user_data[read]]); - pdu->user_data[store] = strExtendedTable[pdu->user_data[read]]; - } - else { - log_debug("GSM before: 0x%02X | IRA after: 0x%02X", pdu->user_data[read], strGSMTable[pdu->user_data[read]]); - pdu->user_data[store] = strGSMTable[pdu->user_data[read]]; - } - store++; - } - //Update lengths - pdu->user_data_len -= read - store; - pdu_str -= (read - store) * HEX_BYTE_LEN; - } - - return pdu_str - begin; + const char *begin = pdu_str; + int tmp; + uint8_t octets[PDU_OCTETS_MAX + 1]; + int user_data_start_index = 0; + int i; + + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + + tmp = hex_byte_decode(pdu_str); + DECODE_FAIL(tmp < 0, "user-data-len", -1); + pdu_str += HEX_BYTE_LEN; + pdu->user_data_len = tmp; + + if (pdu->data_coding.general.unused) { + log_error("data coding group 0x%02X not implemented", + pdu->data_coding.data_coding & 0xF0); + return -1; + } + + + if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT || + pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT2 ) + { + log_debug("data coding alphabet is default (7-bit)"); + } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI) { + log_debug("data coding alphabet is default (7-bit) multi-part"); + } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) { + log_debug("data coding alphabet is CDMA 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_EIGHT) { + log_debug("data coding alphabet is CDMA eight"); + } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_TE) { + log_debug("data coding alphabet is TE specific 7-bit"); + } else { + log_debug("data coding alphabet 0x%02X not implemented", + pdu->data_coding.general.alphabet); + return -1; + } + + // ----------------------------------------------------------------------------- + // 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_DEFAULT2) || + (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)|| + (pdu->data_coding.general.alphabet == PDU_ALPHABET_TE)) { + 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 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) { + if (is_vzw_lte()) { + // LE910-SVG stores data length as # of septets + log_debug("counting PDU length byte as number of septets (LE910-SVG/LE910-SV1/LE910-NA1/VZW)"); + *nr_octets = octets_from_septets(pdu->user_data_len); + } + else { + // Other CDMA radios store data length as # of octets + // NOTE: CE910 send PDU needs # of septets but receive PDU is in # of octets + log_debug("counting PDU length byte as number of octets"); + *nr_octets = pdu->user_data_len; + pdu->user_data_len = septets_from_octets(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)) { + 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; + } + + //Original data is octets (all 8 bits could contain data) + //Therefore, octets = user_data_len + *nr_octets = pdu->user_data_len; + } + + STRLEN_CHECK(pdu_str, *nr_octets * 2, -1); + + 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_DEFAULT2) || + (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)|| + (pdu->data_coding.general.alphabet == PDU_ALPHABET_TE)) { + // Keep UDH for concatenated SMS ONLY. + // Otherwise it is impossible to process correctly concatenated SMS. + i = 0; + if (pdu->type.user_data_header || + // For LVW3, LNA3 and LVW2 - Save header ONLY when it's actually a multi-part message. + // Multi-part messages should use Teleservice ID 4101 (0x1005) in LVW2 7-BIT MULTI-PART format. + // See 3GPP2 X.S0004-550-E for details on Teleservice ID. + (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI + && pdu->teleservice_id == PDU_TELE_ID_CDMA_WEMT)) { + 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++; + } + } + + user_data_start_index = i; + for (; i < pdu->user_data_len; 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. + 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_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 (!is_vzw_lte() && (pdu->user_data[i-1] == 0)) { + log_debug("Removing padded char"); + i--; + 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]; + } + pdu->user_data[i] = '\0'; + } + + + // --------------------------------------------------------------------- + // 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_DEFAULT2) || + (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT_MULTI)) { + int read = user_data_start_index; + int store = user_data_start_index; + + log_debug("Converting from GSM character set to IRA"); + for (; read < pdu->user_data_len; read++) { + if (pdu->user_data[read] == 0x1B) { + //Character from the extended set using the escape char (27) + read++; + log_debug("GSM before: 0x1B%02X | IRA after: 0x%02X", pdu->user_data[read], strExtendedTable[pdu->user_data[read]]); + pdu->user_data[store] = strExtendedTable[pdu->user_data[read]]; + } + else { + log_debug("GSM before: 0x%02X | IRA after: 0x%02X", pdu->user_data[read], strGSMTable[pdu->user_data[read]]); + pdu->user_data[store] = strGSMTable[pdu->user_data[read]]; + } + store++; + } + //Update lengths + pdu->user_data_len -= read - store; + pdu_str -= (read - store) * HEX_BYTE_LEN; + } + + return pdu_str - begin; } 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; + const char *begin = pdu_str; + const char *msg_begin; + int tmp; + int nr_octets; - memset(pdu, 0, sizeof(*pdu)); + memset(pdu, 0, sizeof(*pdu)); - tmp = pdu_decode_addr(pdu_str, &pdu->smsc_addr, 1); - DECODE_FAIL(tmp < 0, "smsc-addr", -1); - pdu_str += tmp; + tmp = pdu_decode_addr(pdu_str, &pdu->smsc_addr, 1); + DECODE_FAIL(tmp < 0, "smsc-addr", -1); + pdu_str += tmp; - msg_begin = pdu_str; + msg_begin = pdu_str; - log_debug("smsc-addr: %s", pdu->smsc_addr.addr); - log_debug("smsc-addr-type: 0x%02X", pdu->smsc_addr.type); - log_debug("smsc-addr-len: 0x%02X", pdu->smsc_addr.len); + log_debug("smsc-addr: %s", pdu->smsc_addr.addr); + log_debug("smsc-addr-type: 0x%02X", pdu->smsc_addr.type); + log_debug("smsc-addr-len: 0x%02X", pdu->smsc_addr.len); - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "type", -1); - pdu_str += HEX_BYTE_LEN; - pdu->type.type = tmp; + tmp = hex_byte_decode(pdu_str); + DECODE_FAIL(tmp < 0, "type", -1); + pdu_str += HEX_BYTE_LEN; + pdu->type.type = tmp; - log_debug("type: 0x%02X", pdu->type.type); + log_debug("type: 0x%02X", pdu->type.type); - if (pdu->type.msg_type == PDU_MTI_SUBMIT || - pdu->type.msg_type == PDU_MTI_REPORT) { - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + if (pdu->type.msg_type == PDU_MTI_SUBMIT || + pdu->type.msg_type == PDU_MTI_REPORT) { + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "msg-reference", -1); - pdu_str += HEX_BYTE_LEN; - pdu->msg_reference = tmp; + tmp = hex_byte_decode(pdu_str); + DECODE_FAIL(tmp < 0, "msg-reference", -1); + pdu_str += HEX_BYTE_LEN; + pdu->msg_reference = tmp; - log_debug("msg-reference: 0x%02X", pdu->msg_reference); - } + log_debug("msg-reference: 0x%02X", pdu->msg_reference); + } - tmp = pdu_decode_addr(pdu_str, &pdu->addr, 0); - DECODE_FAIL(tmp < 0, "addr", -1); - pdu_str += tmp; + tmp = pdu_decode_addr(pdu_str, &pdu->addr, 0); + DECODE_FAIL(tmp < 0, "addr", -1); + pdu_str += tmp; - log_debug("addr: %s", pdu->addr.addr); - log_debug("addr-type: 0x%02X", pdu->addr.type); - log_debug("addr-len: 0x%02X", pdu->addr.len); + log_debug("addr: %s", pdu->addr.addr); + log_debug("addr-type: 0x%02X", pdu->addr.type); + log_debug("addr-len: 0x%02X", pdu->addr.len); - switch (pdu->type.msg_type) { - case PDU_MTI_REPORT: - tmp = pdu_decode_timestamp(pdu_str, &pdu->timestamp); - DECODE_FAIL(tmp < 0, "report-timestamp", -1); - pdu_str += tmp; + switch (pdu->type.msg_type) { + case PDU_MTI_REPORT: + tmp = pdu_decode_timestamp(pdu_str, &pdu->timestamp); + DECODE_FAIL(tmp < 0, "report-timestamp", -1); + pdu_str += tmp; - break; - case PDU_MTI_DELIVER: - case PDU_MTI_SUBMIT: - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + break; + case PDU_MTI_DELIVER: + case PDU_MTI_SUBMIT: + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "protocol-id", -1); - pdu_str += HEX_BYTE_LEN; - pdu->protocol_id = tmp; + tmp = hex_byte_decode(pdu_str); + DECODE_FAIL(tmp < 0, "protocol-id", -1); + pdu_str += HEX_BYTE_LEN; + pdu->protocol_id = tmp; - log_debug("protocol-id: 0x%02X", pdu->protocol_id); + log_debug("protocol-id: 0x%02X", pdu->protocol_id); - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - 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; + 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); + log_debug("data-coding-scheme: 0x%02X", pdu->data_coding.data_coding); - if (pdu->type.msg_type == PDU_MTI_SUBMIT) { - log_debug("validity-period-format: 0x%02X", - pdu->type.validity_period_format); - switch (pdu->type.validity_period_format) { - case PDU_VPF_RELATIVE: - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + if (pdu->type.msg_type == PDU_MTI_SUBMIT) { + log_debug("validity-period-format: 0x%02X", + pdu->type.validity_period_format); + switch (pdu->type.validity_period_format) { + case PDU_VPF_RELATIVE: + STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "validity-period", -1); - pdu_str += HEX_BYTE_LEN; - pdu->validity_period = tmp; + tmp = hex_byte_decode(pdu_str); + DECODE_FAIL(tmp < 0, "validity-period", -1); + pdu_str += HEX_BYTE_LEN; + pdu->validity_period = tmp; - log_debug("validity-period: 0x%02X", pdu->validity_period); + log_debug("validity-period: 0x%02X", pdu->validity_period); - break; + break; - case PDU_VPF_ENHANCED: - log_warning("PDU_VPF_ENHANCED? Falling through to absolute"); - case PDU_VPF_ABSOUTE: - tmp = pdu_decode_timestamp(pdu_str, &pdu->timestamp); - DECODE_FAIL(tmp < 0, "validity-period-timestamp", -1); - pdu_str += tmp; + case PDU_VPF_ENHANCED: + log_warning("PDU_VPF_ENHANCED? Falling through to absolute"); + case PDU_VPF_ABSOUTE: + tmp = pdu_decode_timestamp(pdu_str, &pdu->timestamp); + DECODE_FAIL(tmp < 0, "validity-period-timestamp", -1); + pdu_str += tmp; - return -1; + return -1; - case PDU_VPF_NOT_PRESENT: - default: - break; - } - } else if (pdu->type.msg_type == PDU_MTI_DELIVER) { - tmp = pdu_decode_timestamp(pdu_str, &pdu->timestamp); - DECODE_FAIL(tmp < 0, "delivery-timestamp", -1); - pdu_str += tmp; - } + case PDU_VPF_NOT_PRESENT: + default: + break; + } + } else if (pdu->type.msg_type == PDU_MTI_DELIVER) { + tmp = pdu_decode_timestamp(pdu_str, &pdu->timestamp); + DECODE_FAIL(tmp < 0, "delivery-timestamp", -1); + pdu_str += tmp; + } - tmp = pdu_decode_user_data(pdu_str, pdu, &nr_octets); - DECODE_FAIL(tmp < 0, "user-data", -1); - pdu_str += tmp; - } + tmp = pdu_decode_user_data(pdu_str, pdu, &nr_octets); + DECODE_FAIL(tmp < 0, "user-data", -1); + pdu_str += tmp; + } - pdu->msg_len = (pdu_str - msg_begin) / 2; + pdu->msg_len = (pdu_str - msg_begin) / 2; - log_debug("msg_len: %d", pdu->msg_len); + log_debug("msg_len: %d", pdu->msg_len); - return pdu_str - begin; + 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; + const char *begin = pdu_str; + const char *msg_begin; + int tmp; + int nr_octets; - memset(pdu, 0, sizeof(*pdu)); + 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; + //Destination address + tmp = pdu_decode_addr(pdu_str, &pdu->addr, 1); + DECODE_FAIL(tmp < 0, "addr", -1); + pdu_str += tmp; - msg_begin = pdu_str; + msg_begin = pdu_str; - STRLEN_CHECK(pdu_str, HEX_BYTE_LEN, -1); + 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; + //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); + //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); - pdu->teleservice_id = 0; - pdu->teleservice_id |= (tmp << 8); // save upper byte of the Teleservice ID + pdu->teleservice_id = 0; + pdu->teleservice_id |= (tmp << 8); // save upper byte of the Teleservice ID - 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); + 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); - pdu->teleservice_id |= (tmp); // save lower byte of the Teleservice ID - log_debug("tele-id: 0x%04X", pdu->teleservice_id); + pdu->teleservice_id |= (tmp); // save lower byte of the Teleservice ID + log_debug("tele-id: 0x%04X", pdu->teleservice_id); - //Priority - tmp = hex_byte_decode(pdu_str); - DECODE_FAIL(tmp < 0, "priority", -1); - pdu_str += HEX_BYTE_LEN; - log_debug("priority: 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); + //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; + //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; + pdu->msg_len = 6 + nr_octets; - log_debug("msg_len: %d", pdu->msg_len); + log_debug("msg_len: %d", pdu->msg_len); - return pdu_str - begin; + return pdu_str - begin; } diff --git a/src/pdu_encode.c b/src/pdu_encode.c index f8d6160..d859543 100644 --- a/src/pdu_encode.c +++ b/src/pdu_encode.c @@ -33,119 +33,119 @@ #define ENCODE_FAIL(cond, name, ret) \ do { \ - if (cond) { \ - log_error("encode failed at %s", name); \ - return ret; \ - } \ + if (cond) { \ + log_error("encode failed at %s", name); \ + return ret; \ + } \ } 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; - int off_upper; - int off_lower; - int off; - int negative; + int tmp; + int off_upper; + int off_lower; + int off; + int negative; - if (len < PDU_TIMESTAMP_SIZE) { - log_error("buffer is not large enough to hold a timestamp"); - return -1; - } + if (len < PDU_TIMESTAMP_SIZE) { + log_error("buffer is not large enough to hold a timestamp"); + return -1; + } - tmp = strftime(pdu_str, PDU_TIMESTAMP_SIZE, "%y%m%d%H%M%S", tm); - ENCODE_FAIL(tmp != GMT_OFFSET_IDX, "timestamp", -1); + tmp = strftime(pdu_str, PDU_TIMESTAMP_SIZE, "%y%m%d%H%M%S", tm); + ENCODE_FAIL(tmp != GMT_OFFSET_IDX, "timestamp", -1); - off = tm->tm_gmtoff; - if (off < 0) { - off = -off; - negative = 1; - } - off = off / 60 / 15; + off = tm->tm_gmtoff; + if (off < 0) { + off = -off; + negative = 1; + } + off = off / 60 / 15; - off_upper = off / 10; - off_lower = off % 10; + off_upper = off / 10; + off_lower = off % 10; - if (negative) { - off_upper |= BIT(3); - } + if (negative) { + off_upper |= BIT(3); + } - snprintf(pdu_str + GMT_OFFSET_IDX, 2, "%X", off_upper & 0xF); - snprintf(pdu_str + GMT_OFFSET_IDX + 1, 2, "%X", off_lower & 0xF); + snprintf(pdu_str + GMT_OFFSET_IDX, 2, "%X", off_upper & 0xF); + snprintf(pdu_str + GMT_OFFSET_IDX + 1, 2, "%X", off_lower & 0xF); - strpad(pdu_str, PDU_TIMESTAMP_LEN, 'F'); - nibble_swap(pdu_str, PDU_TIMESTAMP_LEN); + strpad(pdu_str, PDU_TIMESTAMP_LEN, 'F'); + nibble_swap(pdu_str, PDU_TIMESTAMP_LEN); - log_debug("encode_timestamp: %s", pdu_str); + log_debug("encode_timestamp: %s", pdu_str); - return PDU_TIMESTAMP_LEN; + return PDU_TIMESTAMP_LEN; } int pdu_encode_addr(char *pdu_str, size_t len, struct pdu_addr *addr, int smsc) { - char *begin = pdu_str; - int addr_len; - int tmp; - - 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) { - if (addr_len & 1) { - addr_len++; - } - addr_len = addr_len / HEX_BYTE_LEN + 1; - } - } - - log_debug("addr-len [transformed]: 0x%02X", addr_len); - addr->len = addr_len; - - tmp = hex_byte_encode(pdu_str, len, addr_len); - ENCODE_FAIL(tmp != HEX_BYTE_LEN, "addr-len", -1); - pdu_str += tmp; - len -= tmp; - - if (smsc && !addr_len) { - log_debug("smsc addr is empty"); - goto done; - } - - tmp = hex_byte_encode(pdu_str, len, addr->type); - ENCODE_FAIL(tmp != HEX_BYTE_LEN, "addr-type", -1); - pdu_str += tmp; - len -= tmp; - - addr_len = strlen(addr->addr); - if (addr_len & 1) { - addr_len++; - } - - if (len < addr_len + 1) { - log_error("buffer is not large enough to hold the addr"); - return -1; - } - - strcpy(pdu_str, addr->addr); - strpad(pdu_str, addr_len, 'F'); - nibble_swap(pdu_str, addr_len); - len -= addr_len; - pdu_str += addr_len; + char *begin = pdu_str; + int addr_len; + int tmp; + + 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) { + if (addr_len & 1) { + addr_len++; + } + addr_len = addr_len / HEX_BYTE_LEN + 1; + } + } + + log_debug("addr-len [transformed]: 0x%02X", addr_len); + addr->len = addr_len; + + tmp = hex_byte_encode(pdu_str, len, addr_len); + ENCODE_FAIL(tmp != HEX_BYTE_LEN, "addr-len", -1); + pdu_str += tmp; + len -= tmp; + + if (smsc && !addr_len) { + log_debug("smsc addr is empty"); + goto done; + } + + tmp = hex_byte_encode(pdu_str, len, addr->type); + ENCODE_FAIL(tmp != HEX_BYTE_LEN, "addr-type", -1); + pdu_str += tmp; + len -= tmp; + + addr_len = strlen(addr->addr); + if (addr_len & 1) { + addr_len++; + } + + if (len < addr_len + 1) { + log_error("buffer is not large enough to hold the addr"); + return -1; + } + + strcpy(pdu_str, addr->addr); + strpad(pdu_str, addr_len, 'F'); + nibble_swap(pdu_str, addr_len); + len -= addr_len; + pdu_str += addr_len; done: - return pdu_str - begin; + return pdu_str - begin; } @@ -159,312 +159,312 @@ shiftl(buf[septet_idx(n)], cycleup(n, 7) + 1) | shiftr(buf[septet_idx(n) + 1], c 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 i; - - if (pdu->data_coding.general.unused) { - log_error("data coding group 0x%02X not implemented", - pdu->data_coding.data_coding & 0xF0); - return -1; - } - - if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) { - log_debug("data coding alphabet is default (7-bit)"); - } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) { - log_debug("data coding alphabet is CDMA 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_EIGHT) { - log_debug("data coding alphabet is CDMA eight"); - } else { - log_debug("data coding alphabet 0x%02X not implemented", - pdu->data_coding.general.alphabet); - return -1; - } - - - // --------------------------------------------------------------------- - // 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; - char initial_user_data[PDU_UD_7BIT_MAX]; - - for (read = 0; read < pdu->user_data_len; read++) { - initial_user_data[read] = pdu->user_data[read]; - } - initial_user_data[read] = 0; - - log_debug("Converting from IRA character set to GSM"); - for (read = 0; read < pdu->user_data_len; read++) { - int GSMchar = indexOfChar(strGSMTable, GSM_TABLE_SIZE, initial_user_data[read]); - - if (GSMchar >= 0) { - log_debug("IRA before: 0x%02X | GSM after: 0x%02X", initial_user_data[read], GSMchar); - pdu->user_data[store] = GSMchar; - } - else { - //Check in extended table - GSMchar = indexOfChar(strExtendedTable, GSM_TABLE_SIZE, initial_user_data[read]); - - if (GSMchar >= 0) { - log_debug("IRA before: 0x%02X | GSM after: 0x1B%02X", initial_user_data[read], GSMchar); - pdu->user_data[store] = 0x1B; - store++; - pdu->user_data[store] = GSMchar; - } - else { - log_debug("IRA before: 0x%02X | Translation not found - no change", initial_user_data[read]); - pdu->user_data[store] = initial_user_data[read]; - } - } - - store++; - } - - //Update lengths - pdu->user_data_len += store - read; - } - - - // ------------------------------ - // 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 = 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; - } - - *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"); - return -1; - } - - *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) { - log_error("buffer is not large enough to hold user-data"); - return -1; - } - - if ((pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) && - !strcmp(Global.core.model, "DE910-DUAL")) { - // user_data_len is stored as number of encoded octets - log_debug("putting nr_octets into PDU as data length (DE910-DUAL)"); - tmp = hex_byte_encode(pdu_str, len, *nr_octets); - } - else { - // user_data_len is stored as number of septets - 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]); - pdu_str += HEX_BYTE_LEN; - } - len -= *nr_octets * 2; - pdu_str[i] = '\0'; - - 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; + char *begin = pdu_str; + int tmp; + uint8_t octets[PDU_OCTETS_MAX]; + int i; + + if (pdu->data_coding.general.unused) { + log_error("data coding group 0x%02X not implemented", + pdu->data_coding.data_coding & 0xF0); + return -1; + } + + if (pdu->data_coding.general.alphabet == PDU_ALPHABET_DEFAULT) { + log_debug("data coding alphabet is default (7-bit)"); + } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) { + log_debug("data coding alphabet is CDMA 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_EIGHT) { + log_debug("data coding alphabet is CDMA eight"); + } else { + log_debug("data coding alphabet 0x%02X not implemented", + pdu->data_coding.general.alphabet); + return -1; + } + + + // --------------------------------------------------------------------- + // 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; + char initial_user_data[PDU_UD_7BIT_MAX]; + + for (read = 0; read < pdu->user_data_len; read++) { + initial_user_data[read] = pdu->user_data[read]; + } + initial_user_data[read] = 0; + + log_debug("Converting from IRA character set to GSM"); + for (read = 0; read < pdu->user_data_len; read++) { + int GSMchar = indexOfChar(strGSMTable, GSM_TABLE_SIZE, initial_user_data[read]); + + if (GSMchar >= 0) { + log_debug("IRA before: 0x%02X | GSM after: 0x%02X", initial_user_data[read], GSMchar); + pdu->user_data[store] = GSMchar; + } + else { + //Check in extended table + GSMchar = indexOfChar(strExtendedTable, GSM_TABLE_SIZE, initial_user_data[read]); + + if (GSMchar >= 0) { + log_debug("IRA before: 0x%02X | GSM after: 0x1B%02X", initial_user_data[read], GSMchar); + pdu->user_data[store] = 0x1B; + store++; + pdu->user_data[store] = GSMchar; + } + else { + log_debug("IRA before: 0x%02X | Translation not found - no change", initial_user_data[read]); + pdu->user_data[store] = initial_user_data[read]; + } + } + + store++; + } + + //Update lengths + pdu->user_data_len += store - read; + } + + + // ------------------------------ + // 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 = 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; + } + + *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"); + return -1; + } + + *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) { + log_error("buffer is not large enough to hold user-data"); + return -1; + } + + if ((pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) && + !strcmp(Global.core.model, "DE910-DUAL")) { + // user_data_len is stored as number of encoded octets + log_debug("putting nr_octets into PDU as data length (DE910-DUAL)"); + tmp = hex_byte_encode(pdu_str, len, *nr_octets); + } + else { + // user_data_len is stored as number of septets + 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]); + pdu_str += HEX_BYTE_LEN; + } + len -= *nr_octets * 2; + pdu_str[i] = '\0'; + + 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; } 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); - len -= tmp; - pdu_str += tmp; - - msg_begin = pdu_str; - - tmp = hex_byte_encode(pdu_str, len, pdu->type.type); - ENCODE_FAIL(tmp != HEX_BYTE_LEN, "type", -1); - len -= tmp; - pdu_str += tmp; - - if (pdu->type.msg_type == PDU_MTI_SUBMIT || - pdu->type.msg_type == PDU_MTI_REPORT) { - tmp = hex_byte_encode(pdu_str, len, pdu->msg_reference); - ENCODE_FAIL(tmp != HEX_BYTE_LEN, "msg-reference", -1); - len -= tmp; - pdu_str += tmp; - } - - tmp = pdu_encode_addr(pdu_str, len, &pdu->addr, 0); - ENCODE_FAIL(tmp < 0, "addr", -1); - len -= tmp; - pdu_str += tmp; - - switch (pdu->type.msg_type) { - case PDU_MTI_REPORT: - tmp = pdu_encode_timestamp(pdu_str, len, &pdu->timestamp); - ENCODE_FAIL(tmp < 0, "report-timestamp", -1); - len -= tmp; - pdu_str += tmp; - - break; - case PDU_MTI_DELIVER: - case PDU_MTI_SUBMIT: - tmp = hex_byte_encode(pdu_str, len, pdu->protocol_id); - ENCODE_FAIL(tmp != HEX_BYTE_LEN, "protocol-id", -1); - len -= tmp; - pdu_str += tmp; - - 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; - - if (pdu->type.msg_type == PDU_MTI_SUBMIT) { - switch (pdu->type.validity_period_format) { - case PDU_VPF_RELATIVE: - tmp = hex_byte_encode(pdu_str, len, pdu->validity_period); - ENCODE_FAIL(tmp != HEX_BYTE_LEN, "validity-period", -1); - len -= tmp; - pdu_str += tmp; - - break; - - case PDU_VPF_ENHANCED: - log_warning("PDU_VPF_ENHANCED? Falling through to absolute"); - case PDU_VPF_ABSOUTE: - tmp = pdu_encode_timestamp(pdu_str, len, &pdu->timestamp); - ENCODE_FAIL(tmp < 0, "validity-period-timestamp", -1); - len -= tmp; - pdu_str += tmp; - - break; - - case PDU_VPF_NOT_PRESENT: - default: - break; - } - } else if (pdu->type.msg_type == PDU_MTI_DELIVER) { - tmp = pdu_encode_timestamp(pdu_str, len, &pdu->timestamp); - ENCODE_FAIL(tmp < 0, "delivery-timestamp", -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; - log_debug("msg-len: %d", pdu->msg_len); - - return pdu_str - begin; + 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); + len -= tmp; + pdu_str += tmp; + + msg_begin = pdu_str; + + tmp = hex_byte_encode(pdu_str, len, pdu->type.type); + ENCODE_FAIL(tmp != HEX_BYTE_LEN, "type", -1); + len -= tmp; + pdu_str += tmp; + + if (pdu->type.msg_type == PDU_MTI_SUBMIT || + pdu->type.msg_type == PDU_MTI_REPORT) { + tmp = hex_byte_encode(pdu_str, len, pdu->msg_reference); + ENCODE_FAIL(tmp != HEX_BYTE_LEN, "msg-reference", -1); + len -= tmp; + pdu_str += tmp; + } + + tmp = pdu_encode_addr(pdu_str, len, &pdu->addr, 0); + ENCODE_FAIL(tmp < 0, "addr", -1); + len -= tmp; + pdu_str += tmp; + + switch (pdu->type.msg_type) { + case PDU_MTI_REPORT: + tmp = pdu_encode_timestamp(pdu_str, len, &pdu->timestamp); + ENCODE_FAIL(tmp < 0, "report-timestamp", -1); + len -= tmp; + pdu_str += tmp; + + break; + case PDU_MTI_DELIVER: + case PDU_MTI_SUBMIT: + tmp = hex_byte_encode(pdu_str, len, pdu->protocol_id); + ENCODE_FAIL(tmp != HEX_BYTE_LEN, "protocol-id", -1); + len -= tmp; + pdu_str += tmp; + + 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; + + if (pdu->type.msg_type == PDU_MTI_SUBMIT) { + switch (pdu->type.validity_period_format) { + case PDU_VPF_RELATIVE: + tmp = hex_byte_encode(pdu_str, len, pdu->validity_period); + ENCODE_FAIL(tmp != HEX_BYTE_LEN, "validity-period", -1); + len -= tmp; + pdu_str += tmp; + + break; + + case PDU_VPF_ENHANCED: + log_warning("PDU_VPF_ENHANCED? Falling through to absolute"); + case PDU_VPF_ABSOUTE: + tmp = pdu_encode_timestamp(pdu_str, len, &pdu->timestamp); + ENCODE_FAIL(tmp < 0, "validity-period-timestamp", -1); + len -= tmp; + pdu_str += tmp; + + break; + + case PDU_VPF_NOT_PRESENT: + default: + break; + } + } else if (pdu->type.msg_type == PDU_MTI_DELIVER) { + tmp = pdu_encode_timestamp(pdu_str, len, &pdu->timestamp); + ENCODE_FAIL(tmp < 0, "delivery-timestamp", -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; + log_debug("msg-len: %d", pdu->msg_len); + + 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; + 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; } diff --git a/src/phonebook.c b/src/phonebook.c index fc29d61..3165235 100644 --- a/src/phonebook.c +++ b/src/phonebook.c @@ -290,7 +290,7 @@ int phonebook_list_get(int fd, struct phonebook_list_info *list_info) atcmd_writeline(fd, "AT+CPBR=%d,%d", list_info->store.index_min, list_info->store.index_max); tmp = atcmd_response_foreach_line(fd, list_info_callback, list_info); - //CE910 reports an error if empty. Don't report error in this case + //CE910 reports an error if empty. Don't report error in this case if ((tmp < 0) && strcmp(Global.core.model, "CE910-DUAL")) { log_error("listing failed"); phonebook_list_free(list_info); diff --git a/src/sms_list.c b/src/sms_list.c index 2c39aa8..3a3d395 100644 --- a/src/sms_list.c +++ b/src/sms_list.c @@ -283,14 +283,14 @@ static int list_info_callback(char *buf, size_t len, void *data) msg = list_entry(list_info->msg_list.prev, typeof(*msg), list); if (msg->len > 0) { - if (isCdmaTypeModel()) { - log_debug("using CDMA pdu decoding"); - err = pdu_decode_cdma(buf, &msg->pdu); - } - else { - log_debug("using GSM pdu decoding"); - err = pdu_decode(buf, &msg->pdu); - } + if (isCdmaTypeModel()) { + log_debug("using CDMA pdu decoding"); + err = pdu_decode_cdma(buf, &msg->pdu); + } + else { + log_debug("using GSM pdu decoding"); + err = pdu_decode(buf, &msg->pdu); + } if (err < 0) { log_warning("pdu decode failed: %d", err); } diff --git a/src/sms_send.c b/src/sms_send.c index bc98cb4..149ce1a 100644 --- a/src/sms_send.c +++ b/src/sms_send.c @@ -224,25 +224,25 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) printf("preparing for send...\n"); } - //LE910-SVG SMS SEND WORKAROUND - if (is_vzw_lte()) { - log_info("setting text mode for Verizon LTE"); - tmp = atcmd_plus_cmgf_write(fd, SMS_TEXT_MODE); - if (tmp < 0) { - log_error("failed to set text mode for sending with Verizon LTE."); - return false; - } - } + //LE910-SVG SMS SEND WORKAROUND + if (is_vzw_lte()) { + log_info("setting text mode for Verizon LTE"); + tmp = atcmd_plus_cmgf_write(fd, SMS_TEXT_MODE); + if (tmp < 0) { + log_error("failed to set text mode for sending with Verizon LTE."); + return false; + } + } if (options->cmgw_first) { - if (isCdmaTypeModel()) { + if (isCdmaTypeModel()) { log_debug("using CDMA pdu encoding for cmgw"); - tmp = pdu_encode_cdma(buf, sizeof(buf), &pdu); - } - else { + tmp = pdu_encode_cdma(buf, sizeof(buf), &pdu); + } + else { log_debug("using GSM pdu encoding for cmgw"); - tmp = pdu_encode(buf, sizeof(buf), &pdu); - } + tmp = pdu_encode(buf, sizeof(buf), &pdu); + } if (tmp < 0) { log_error("pdu encode failed"); return false; @@ -252,13 +252,13 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) printf("writing message to memory\n"); } - //LE910-SVG SMS SEND WORKAROUND + //LE910-SVG SMS SEND WORKAROUND if (is_vzw_lte()) { - mem_index = atcmd_plus_cmgw_write_text(fd, NULL, SMS_ADDR_UNSPEC, NULL, pdu.user_data, pdu.user_data_len); - } - else { - mem_index = atcmd_plus_cmgw_write(fd, buf, pdu.msg_len); - } + mem_index = atcmd_plus_cmgw_write_text(fd, NULL, SMS_ADDR_UNSPEC, NULL, pdu.user_data, pdu.user_data_len); + } + else { + mem_index = atcmd_plus_cmgw_write(fd, buf, pdu.msg_len); + } if (mem_index < 0) { log_error("write message to memory failed"); return false; @@ -298,27 +298,27 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) continue; } } else { - if (isCdmaTypeModel()) { - log_debug("using CDMA pdu encoding for cmgs"); - tmp = pdu_encode_cdma(buf, sizeof(buf), &pdu); - } - else { - log_debug("using GSM pdu encoding for cmgs"); - tmp = pdu_encode(buf, sizeof(buf), &pdu); - } + if (isCdmaTypeModel()) { + log_debug("using CDMA pdu encoding for cmgs"); + tmp = pdu_encode_cdma(buf, sizeof(buf), &pdu); + } + else { + log_debug("using GSM pdu encoding for cmgs"); + tmp = pdu_encode(buf, sizeof(buf), &pdu); + } if (tmp < 0) { printf("sending message to %s failed\n", argv[i]); failed++; continue; } - //LE910-SVG SMS SEND WORKAROUND - if (is_vzw_lte()) { - tmp = atcmd_plus_cmgs_write_text(fd, pdu.addr.addr, pdu.user_data, pdu.user_data_len); - } - else { - tmp = atcmd_plus_cmgs_write(fd, buf, pdu.msg_len); - } + //LE910-SVG SMS SEND WORKAROUND + if (is_vzw_lte()) { + tmp = atcmd_plus_cmgs_write_text(fd, pdu.addr.addr, pdu.user_data, pdu.user_data_len); + } + else { + tmp = atcmd_plus_cmgs_write(fd, buf, pdu.msg_len); + } if (tmp < 0) { printf("sending message to %s failed\n", argv[i]); failed++; diff --git a/src/utils.c b/src/utils.c index 3a18487..37d0ac3 100644 --- a/src/utils.c +++ b/src/utils.c @@ -288,12 +288,12 @@ int device_unlock(int lock) int indexOfChar(const char *array, int len, char character) { - int i; - - for (i = 0; i < len; i++) { - if (array[i] == character) { - return i; - } - } - return -1; + int i; + + for (i = 0; i < len; i++) { + if (array[i] == character) { + return i; + } + } + return -1; } -- cgit v1.2.3 From e8b95d56ac9e06c3dc55f2c6fc3b2e177f9b10b0 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 6 Jan 2023 17:52:09 +0200 Subject: [GP-1842] Refactoring - Renamed Verizon 3GPP2 detection functions Renamed the functions to better represent their behavior and purpose. --- src/atcmd.c | 18 ++++++++++-------- src/atcmd.h | 6 +++--- src/pdu_decode.c | 4 ++-- src/pdu_encode.c | 2 +- src/sms_delete.c | 4 ++-- src/sms_list.c | 6 +++--- src/sms_send.c | 10 +++++----- 7 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/atcmd.c b/src/atcmd.c index 7c39313..0c4860a 100644 --- a/src/atcmd.c +++ b/src/atcmd.c @@ -878,7 +878,7 @@ int atcmd_plus_cpms_read(int fd, struct data_store *read_store, struct data_store *store; struct data_store *data_stores[] = {read_store, send_store, new_store}; - if (isCdmaTypeModel()) { + if (is_telit_3gpp2_format()) { data_stores_size = 2; } else { @@ -1006,7 +1006,7 @@ int atcmd_plus_cpms_write(int fd, const char *read_name, char buf[ATCMD_LINE_SIZE]; int tmp; - if (isCdmaTypeModel()) { + if (is_telit_3gpp2_format()) { atcmd_writeline(fd, "AT+CPMS=\"%s\",\"%s\"", read_name, send_name); } else @@ -1475,7 +1475,7 @@ static int sms_atcmd_init(int fd) } //Doesn't apply to CDMA type radios - if (!isCdmaTypeModel() && !msg_store_choice(&new_store, Global.core.msg_store_new)) { + if (!is_telit_3gpp2_format() && !msg_store_choice(&new_store, Global.core.msg_store_new)) { log_error("message storage location %s is not a choice", Global.core.msg_store_new); return -1; @@ -1543,7 +1543,8 @@ int sms_device_open(void) return fd; } -int is_vzw_lte(void) +/* Detect Telit LTE radios that use the 3GPP2 SMS format for Verizon */ +int is_telit_lte_vzw_3gpp2_format(void) { if (!strcmp(Global.core.model, "LE910-NA1")) { log_debug("Found LE910-NA1"); @@ -1558,8 +1559,8 @@ int is_vzw_lte(void) !strncmp(Global.core.model, "LE910-SV1", MODEL_LEN)); } -/* Detect LNA7/L4G1 radio with Verizon SIM */ -int is_quectel_dual_sms_format(void) +/* Detect LNA7/LNA7D/L4G1 radios with Verizon SIM that support both 3GPP and 3GPP2 */ +int is_quectel_dual_format(void) { if (!strncmp(Global.core.model, "EG95", MODEL_LEN) || !strncmp(Global.core.model, "EG25", MODEL_LEN)) @@ -1574,10 +1575,11 @@ int is_quectel_dual_sms_format(void) return 0; } -int isCdmaTypeModel() +/* Detect Telit LTE and CDMA radios that use the 3GPP2 SMS format for Verizon */ +int is_telit_3gpp2_format() { /* Test for possible dual firmware model */ - if (is_vzw_lte()) + if (is_telit_lte_vzw_3gpp2_format()) return 1; return (!strncmp(Global.core.model, "DE910-DUAL", MODEL_LEN) || diff --git a/src/atcmd.h b/src/atcmd.h index 28bc384..1f15e62 100644 --- a/src/atcmd.h +++ b/src/atcmd.h @@ -72,7 +72,7 @@ int atcmd_plus_cmgd_write(int fd, int index); int atcmd_plus_qcfg_write(int fd, int sms_format); -int isCdmaTypeModel(); +int is_telit_3gpp2_format(); #define STORE_NAME_LEN 2 #define STORE_NAME_SIZE (STORE_NAME_LEN + 1) @@ -121,8 +121,8 @@ int atcmd_plus_gmi_read(int fd); int atcmd_init(int fd, int read_timeout); int sms_device_close(int fd); int sms_device_open(void); -int is_vzw_lte(void); -int is_quectel_dual_sms_format(void); +int is_telit_lte_vzw_3gpp2_format(void); +int is_quectel_dual_format(void); int is_telit_model(void); int is_quectel_model(void); diff --git a/src/pdu_decode.c b/src/pdu_decode.c index 7f76ff5..9014162 100644 --- a/src/pdu_decode.c +++ b/src/pdu_decode.c @@ -237,7 +237,7 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe // CDMA 7-BIT ENCODING } else if (pdu->data_coding.general.alphabet == PDU_ALPHABET_CDMA_DEFAULT) { - if (is_vzw_lte()) { + if (is_telit_lte_vzw_3gpp2_format()) { // LE910-SVG stores data length as # of septets log_debug("counting PDU length byte as number of septets (LE910-SVG/LE910-SV1/LE910-NA1/VZW)"); *nr_octets = octets_from_septets(pdu->user_data_len); @@ -340,7 +340,7 @@ int pdu_decode_user_data(const char *pdu_str, struct pdu_info *pdu, int *nr_octe } //Remove padded byte for data length of 7 characters if not LE910-SVG - if (!is_vzw_lte() && (pdu->user_data[i-1] == 0)) { + if (!is_telit_lte_vzw_3gpp2_format() && (pdu->user_data[i-1] == 0)) { log_debug("Removing padded char"); i--; pdu->user_data_len--; diff --git a/src/pdu_encode.c b/src/pdu_encode.c index d859543..34028a9 100644 --- a/src/pdu_encode.c +++ b/src/pdu_encode.c @@ -88,7 +88,7 @@ int pdu_encode_addr(char *pdu_str, size_t len, struct pdu_addr *addr, int smsc) int addr_len; int tmp; - if (isCdmaTypeModel()) { + if (is_telit_3gpp2_format()) { //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 diff --git a/src/sms_delete.c b/src/sms_delete.c index 7bd50d0..e70ddc3 100644 --- a/src/sms_delete.c +++ b/src/sms_delete.c @@ -167,8 +167,8 @@ int sms_delete(int argc, char **argv) return false; } - // LNA7/L4G1 with Verizon SIM SMS 3GPP, 3GPP2 WORKAROUND - if (is_quectel_dual_sms_format()) { + // LNA7/LNA7D/L4G1 with Verizon SIM SMS 3GPP, 3GPP2 WORKAROUND + if (is_quectel_dual_format()) { int tmp; tmp = atcmd_plus_qcfg_write(fd, SMS_FORMAT_3GPP); if (tmp == 0) { diff --git a/src/sms_list.c b/src/sms_list.c index 3a3d395..7f246be 100644 --- a/src/sms_list.c +++ b/src/sms_list.c @@ -283,7 +283,7 @@ static int list_info_callback(char *buf, size_t len, void *data) msg = list_entry(list_info->msg_list.prev, typeof(*msg), list); if (msg->len > 0) { - if (isCdmaTypeModel()) { + if (is_telit_3gpp2_format()) { log_debug("using CDMA pdu decoding"); err = pdu_decode_cdma(buf, &msg->pdu); } @@ -499,8 +499,8 @@ int sms_list(int argc, char **argv) return false; } - // LNA7 with Verizon SIM SMS 3GPP, 3GPP2 WORKAROUND - if (is_quectel_dual_sms_format()) { + // LNA7/LNA7D/L4G1 with Verizon SIM SMS 3GPP, 3GPP2 WORKAROUND + if (is_quectel_dual_format()) { int tmp; tmp = atcmd_plus_qcfg_write(fd, SMS_FORMAT_3GPP); if (tmp == 0) { diff --git a/src/sms_send.c b/src/sms_send.c index 149ce1a..a95a0ca 100644 --- a/src/sms_send.c +++ b/src/sms_send.c @@ -225,7 +225,7 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) } //LE910-SVG SMS SEND WORKAROUND - if (is_vzw_lte()) { + if (is_telit_lte_vzw_3gpp2_format()) { log_info("setting text mode for Verizon LTE"); tmp = atcmd_plus_cmgf_write(fd, SMS_TEXT_MODE); if (tmp < 0) { @@ -235,7 +235,7 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) } if (options->cmgw_first) { - if (isCdmaTypeModel()) { + if (is_telit_3gpp2_format()) { log_debug("using CDMA pdu encoding for cmgw"); tmp = pdu_encode_cdma(buf, sizeof(buf), &pdu); } @@ -253,7 +253,7 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) } //LE910-SVG SMS SEND WORKAROUND - if (is_vzw_lte()) { + if (is_telit_lte_vzw_3gpp2_format()) { mem_index = atcmd_plus_cmgw_write_text(fd, NULL, SMS_ADDR_UNSPEC, NULL, pdu.user_data, pdu.user_data_len); } else { @@ -298,7 +298,7 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) continue; } } else { - if (isCdmaTypeModel()) { + if (is_telit_3gpp2_format()) { log_debug("using CDMA pdu encoding for cmgs"); tmp = pdu_encode_cdma(buf, sizeof(buf), &pdu); } @@ -313,7 +313,7 @@ static int do_send(int fd, struct send_options *options, int argc, char **argv) } //LE910-SVG SMS SEND WORKAROUND - if (is_vzw_lte()) { + if (is_telit_lte_vzw_3gpp2_format()) { tmp = atcmd_plus_cmgs_write_text(fd, pdu.addr.addr, pdu.user_data, pdu.user_data_len); } else { -- cgit v1.2.3 From 78a27efb55e1c509604fe9d96f8c421d6b1bda36 Mon Sep 17 00:00:00 2001 From: Serhii Kostiuk Date: Fri, 6 Jan 2023 18:48:25 +0200 Subject: [GP-1842] Update the Cellular code to use SIM IMSI for Verizon detection The certifications lab uses special SIM cards with non-Verizon ICCID numbers and Verizon IMSI numbers (MCC/MNC prefixes or PLMN IDs). Update the code to detect Verizon properly for such "special" SIM cards. --- src/atcmd.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/atcmd.h | 2 ++ src/global.h | 7 ++++- 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/src/atcmd.c b/src/atcmd.c index 0c4860a..d17c03f 100644 --- a/src/atcmd.c +++ b/src/atcmd.c @@ -1300,7 +1300,7 @@ int atcmd_plus_gmi_read(int fd) return 0; } -/* ICCID needed for LNA3 to determine carrier */ +/* ICCID needed to detect Verizon on multi-carrier radios */ int atcmd_plus_iccid_read(int fd) { char buf[ATCMD_LINE_SIZE]; @@ -1342,7 +1342,7 @@ int atcmd_plus_iccid_read(int fd) log_debug("buf=%s for %d", buf,strlen(buf)); token = atcmd_value_tok(&save); if (!token) { - log_debug("atcmd_value_tok model"); + log_debug("atcmd_value_tok iccid"); return -1; } else { log_debug("token is %s",token); @@ -1371,6 +1371,65 @@ int atcmd_plus_iccid_read(int fd) return 0; } +/* IMSI needed to detect Verizon when the ICCID is unrecognized */ +int atcmd_plus_imsi_read(int fd) +{ + char buf[ATCMD_LINE_SIZE]; + char *save; + char *token; + int tmp; + char *tmp_buf; + char* command = "AT+CIMI"; + + atcmd_writeline(fd, command); + //Swallow extra "\r\n" + tmp = atcmd_readline(fd, buf, sizeof(buf)); + if (tmp <= 0) { + log_debug("expected \\r\\n but it was not received"); + return -1; + } + + //Read imsi string + tmp = atcmd_readline(fd, buf, sizeof(buf)); + if (tmp <= 0) { + log_debug("expected IMSI but it was not received"); + /* Currently only LNA7/LNA7D/L4G1 models will need the IMSI */ + return -1; + } + + save = buf; + log_debug("buf=%s for %d", buf,strlen(buf)); + token = atcmd_value_tok(&save); + if (!token) { + log_debug("atcmd_value_tok imsi"); + return -1; + } else { + log_debug("token is %s",token); + } + tmp_buf = strrchr(token,' '); + if (tmp_buf) { + token = ++tmp_buf; + log_debug("Found blank, incrementing tmp"); + } else { + tmp_buf = strrchr(token,'\t'); + log_debug("Found tab, incrementing tmp"); + if(tmp_buf) + token = ++tmp_buf; + } + log_debug("token[0]=%2.2x token[1]=%2.2x",token[0],token[1]); + strncpy(Global.core.imsi, token, IMSI_LEN); + + log_debug("imsi: %s", Global.core.imsi); + + tmp = atcmd_expect_line(fd, buf, sizeof(buf), "OK"); + if (tmp <= 0) { + log_debug("expected OK but it was not received"); + return -1; + } + + return 0; +} + int atcmd_init(int fd, int read_timeout) { int tmp; @@ -1437,6 +1496,12 @@ static int sms_atcmd_init(int fd) return -1; } + tmp = atcmd_plus_imsi_read(fd); + if (tmp < 0) { + log_error("failed to read SIM IMSI"); + return -1; + } + tmp = atcmd_plus_cmgf_write(fd, SMS_PDU_MODE); if (tmp < 0) { return -1; @@ -1566,11 +1631,35 @@ int is_quectel_dual_format(void) !strncmp(Global.core.model, "EG25", MODEL_LEN)) { log_debug("Found Quectel radio with dual SMS format support"); - /* Verizon Wireless SIM */ + + /* Verizon Wireless SIM ICCID */ if (strncmp(Global.core.iccid,"891480",6) == 0) { - log_debug("Found VZW SIM"); + log_debug("Found VZW SIM by ICCID"); return 1; } + + /* Extract PLMN ID - the first 5 or 6 digits of IMSI. + Assume 6 digits for Verizon. + NOTE: Other carriers may use shorter codes */ + char plmn_id_str[PLMN_ID_SIZE_VZW] = {0}; + strncpy(plmn_id_str, Global.core.imsi, PLMN_ID_LEN_VZW); + + /* Parse as integer for easier comparison */ + int plmn_id_num = atoi(plmn_id_str); + + /* Verizon Wireless SIM MCC/MNC */ + switch (plmn_id_num) { + case 310590: + case 310890: + case 311270: + case 311480: + case 312770: + log_debug("Found VZW SIM by IMSI"); + return 1; + default: + /* ignore, not Verizon */ + break; + }; } return 0; } diff --git a/src/atcmd.h b/src/atcmd.h index 1f15e62..bbab2d7 100644 --- a/src/atcmd.h +++ b/src/atcmd.h @@ -117,6 +117,8 @@ int atcmd_plus_cpbr_test(int fd, struct phonebook_store *store); int atcmd_plus_gmm_read(int fd); int atcmd_plus_gmi_read(int fd); +int atcmd_plus_iccid_read(int fd); +int atcmd_plus_imsi_read(int fd); int atcmd_init(int fd, int read_timeout); int sms_device_close(int fd); diff --git a/src/global.h b/src/global.h index a6073dd..4b83cb5 100644 --- a/src/global.h +++ b/src/global.h @@ -14,6 +14,10 @@ #define ICCID_LEN 23 #define ICCID_SIZE (ICCID_LEN + 1) +#define IMSI_LEN 15 +#define IMSI_SIZE (IMSI_LEN + 1) +#define PLMN_ID_LEN_VZW 6 +#define PLMN_ID_SIZE_VZW (PLMN_ID_LEN_VZW + 1) #define MODEL_LEN 1023 #define MODEL_SIZE (MODEL_LEN + 1) #define MANUFACTURER_LEN 1023 @@ -37,7 +41,8 @@ struct global_core { char *msg_store_new; char *pb_store; char model[MODEL_SIZE]; - char iccid[ICCID_SIZE]; /* Needed for LNA3/Verizon */ + char iccid[ICCID_SIZE]; /* Needed for Verizon 3GPP2 SMS format detection */ + char imsi[IMSI_SIZE]; /* Needed for Verizon 3GPP2 SMS format detection */ char manufacturer[MANUFACTURER_SIZE]; /* Needed to pick proper manufacturer-specific commands */ char *editor; -- cgit v1.2.3