summaryrefslogtreecommitdiff
path: root/src/atcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/atcmd.c')
-rw-r--r--src/atcmd.c227
1 files changed, 159 insertions, 68 deletions
diff --git a/src/atcmd.c b/src/atcmd.c
index b988a57..d17c03f 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 (is_telit_3gpp2_format()) {
+ 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 (is_telit_3gpp2_format()) {
+ 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;
@@ -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];
@@ -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;
}
@@ -1342,12 +1342,12 @@ 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);
}
- tmp_buf = strrchr(token,' ');
+ tmp_buf = strrchr(token,' ');
if (tmp_buf) {
token = ++tmp_buf;
log_debug("Found blank, incrementing tmp");
@@ -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;
@@ -1421,19 +1480,25 @@ 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);
+ if (tmp < 0) {
+ log_error("failed to read SIM ICCID");
return -1;
}
- tmp = atcmd_plus_iccid_read(fd);
+ tmp = atcmd_plus_imsi_read(fd);
if (tmp < 0) {
- log_error("failed to read SIM ICCID");
+ log_error("failed to read SIM IMSI");
return -1;
}
@@ -1446,22 +1511,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,8 +1539,8 @@ static int sms_atcmd_init(int fd)
return -1;
}
- //Doesn't apply to CDMA type radios
- if (!isCdmaTypeModel() && !msg_store_choice(&new_store, Global.core.msg_store_new)) {
+ //Doesn't apply to CDMA type radios
+ 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,45 +1608,71 @@ 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");
- /* 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 */
-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))
{
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;
}
-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())
- return 1;
+ /* Test for possible dual firmware model */
+ if (is_telit_lte_vzw_3gpp2_format())
+ 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()