[PATCH 4/5] atmodem: report cell technology capability for SIMCom A76XX
Sean Nyekjaer <[email protected]> Thu, 21 Aug 2025 13:24:12 +0200
| Newsgroups | dev.linux.lists.ofono |
|---|---|
| Message-ID | <[email protected]> |
---
drivers/atmodem/network-registration.c | 80 ++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/drivers/atmodem/network-registration.c b/drivers/atmodem/network-registration.c
index 8087543117b7abfce87240940e47264283f95234..7f03759b83b3cf8c45cc885a450cdf24ac9aed92 100644
--- a/drivers/atmodem/network-registration.c
+++ b/drivers/atmodem/network-registration.c
@@ -38,6 +38,7 @@ static const char *csq_prefix[] = { "+CSQ:", NULL };
static const char *cind_prefix[] = { "+CIND:", NULL };
static const char *cmer_prefix[] = { "+CMER:", NULL };
static const char *smoni_prefix[] = { "^SMONI:", NULL };
+static const char *simcom_tech_prefix[] = { "+CNSMOD:", NULL };
static const char *zpas_prefix[] = { "+ZPAS:", NULL };
static const char *option_tech_prefix[] = { "_OCTI:", "_OUWCTI:", NULL };
@@ -179,6 +180,45 @@ static int gemalto_parse_tech(GAtResult *result)
return tech;
}
+static int simcom_parse_tech(GAtResult *result)
+{
+ GAtResultIter iter;
+ int s, stat, tech;
+
+ g_at_result_iter_init(&iter, result);
+
+ if (!g_at_result_iter_next(&iter, "+CNSMOD:"))
+ return -1;
+
+ if (!g_at_result_iter_next_number(&iter, &s))
+ return -1;
+
+ if (!g_at_result_iter_next_number(&iter, &stat))
+ return -1;
+
+ switch (stat) {
+ case 1: /* GSM */
+ tech = ACCESS_TECHNOLOGY_GSM;
+ break;
+ case 2: /* GPRS */
+ tech = ACCESS_TECHNOLOGY_GSM;
+ break;
+ case 3: /* EDGE */
+ tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
+ break;
+ case 8: /* LTE */
+ tech = ACCESS_TECHNOLOGY_EUTRAN;
+ break;
+ default:
+ tech = -1;
+ break;
+ }
+
+ DBG("stat %d tech %d", stat, tech);
+
+ return tech;
+}
+
static void at_creg_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
@@ -246,6 +286,18 @@ static void option_tech_cb(gboolean ok, GAtResult *result, gpointer user_data)
nd->tech = -1;
}
+static void simcom_tech_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct cb_data *cbd = user_data;
+ struct ofono_netreg *netreg = cbd->data;
+ struct at_netreg_data *nd = ofono_netreg_get_data(netreg);
+
+ if (ok)
+ nd->tech = simcom_parse_tech(result);
+ else
+ nd->tech = -1;
+}
+
void at_registration_status(struct ofono_netreg *netreg,
ofono_netreg_status_cb_t cb,
void *data)
@@ -299,6 +351,13 @@ void at_registration_status(struct ofono_netreg *netreg,
option_tech_cb, cbd, NULL) == 0)
nd->tech = -1;
break;
+ case OFONO_VENDOR_SIMCOM_A76XX:
+ /* Send AT+CNSMOD? to find out the current tech */
+ if (g_at_chat_send(nd->chat, "AT+CNSMOD?",
+ simcom_tech_prefix,
+ simcom_tech_cb, cbd, NULL) == 0)
+ nd->tech = -1;
+ break;
}
if (g_at_chat_send(nd->chat, "AT+CREG?", creg_prefix,
@@ -1561,6 +1620,21 @@ static void option_query_tech_cb(gboolean ok, GAtResult *result,
tq->status, tq->lac, tq->ci, tech);
}
+static void simcom_query_tech_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
+{
+ struct tech_query *tq = user_data;
+ int tech;
+
+ if (ok)
+ tech = simcom_parse_tech(result);
+ else
+ tech = -1;
+
+ ofono_netreg_status_notify(tq->netreg,
+ tq->status, tq->lac, tq->ci, tech);
+}
+
static void creg_notify(GAtResult *result, gpointer user_data)
{
struct ofono_netreg *netreg = user_data;
@@ -1620,6 +1694,12 @@ static void creg_notify(GAtResult *result, gpointer user_data)
gemalto_query_tech_cb, tq, g_free) > 0)
return;
break;
+ case OFONO_VENDOR_SIMCOM_A76XX:
+ if (g_at_chat_send(nd->chat, "AT+CNSMOD?",
+ simcom_tech_prefix,
+ simcom_query_tech_cb, tq, g_free) > 0)
+ return;
+ break;
}
g_free(tq);
--
2.50.1