All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] gemalto: netmon driver
@ 2021-01-10 19:44 Sergey Matyukevich
  2021-01-10 19:44 ` [RFC PATCH 1/2] gemalto: add " Sergey Matyukevich
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Sergey Matyukevich @ 2021-01-10 19:44 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 993 bytes --]

Hello Denis and all,

This patch series implements netmon driver for gemalto modems that are
able to provide basic measurements using AT+CQS and AT^SMONI commands.

This patch series is intendedly marked as RFC. In addition to general
feedback for this v1 I would like to clarify the right way to handle
negative values that can be returned by modem. For instance, this
is the case for the values measured in dBm including EC/n0 and RSCP.
Currently such values are discarded by CELL_INFO_DICT_APPEND macro.

Regards,
Sergey


Sergey Matyukevich (2):
  gemalto: add netmon driver
  plugin: gemalto: enable netmon

 Makefile.am                         |   3 +-
 drivers/gemaltomodem/gemaltomodem.c |   2 +
 drivers/gemaltomodem/gemaltomodem.h |   3 +
 drivers/gemaltomodem/netmon.c       | 609 ++++++++++++++++++++++++++++
 plugins/gemalto.c                   |   6 +
 5 files changed, 622 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gemaltomodem/netmon.c

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC PATCH 1/2] gemalto: add netmon driver
  2021-01-10 19:44 [RFC PATCH 0/2] gemalto: netmon driver Sergey Matyukevich
@ 2021-01-10 19:44 ` Sergey Matyukevich
  2021-01-11 19:28   ` Denis Kenzior
  2021-01-10 19:44 ` [RFC PATCH 2/2] plugin: gemalto: enable netmon Sergey Matyukevich
  2021-01-11 19:56 ` [RFC PATCH 0/2] gemalto: netmon driver Denis Kenzior
  2 siblings, 1 reply; 6+ messages in thread
From: Sergey Matyukevich @ 2021-01-10 19:44 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 19998 bytes --]

Implement network monitoring driver for gemalto modems that
are able to provide serving cell information and basic
measurements using AT+CQS and AT^SMONI commands.
---
 Makefile.am                         |   3 +-
 drivers/gemaltomodem/gemaltomodem.c |   2 +
 drivers/gemaltomodem/gemaltomodem.h |   3 +
 drivers/gemaltomodem/netmon.c       | 609 ++++++++++++++++++++++++++++
 4 files changed, 616 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gemaltomodem/netmon.c

diff --git a/Makefile.am b/Makefile.am
index c0631081..5e7614c1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -483,7 +483,8 @@ builtin_sources += drivers/atmodem/atutil.h \
 			drivers/gemaltomodem/gemaltomodem.c \
 			drivers/gemaltomodem/location-reporting.c \
 			drivers/gemaltomodem/voicecall.c \
-			drivers/gemaltomodem/gprs-context.c
+			drivers/gemaltomodem/gprs-context.c \
+			drivers/gemaltomodem/netmon.c
 
 builtin_modules += xmm7modem
 builtin_sources += drivers/atmodem/atutil.h \
diff --git a/drivers/gemaltomodem/gemaltomodem.c b/drivers/gemaltomodem/gemaltomodem.c
index 4b20dd1b..f7e4ff3e 100644
--- a/drivers/gemaltomodem/gemaltomodem.c
+++ b/drivers/gemaltomodem/gemaltomodem.c
@@ -38,6 +38,7 @@ static int gemaltomodem_init(void)
 	gemalto_location_reporting_init();
 	gemalto_gprs_context_init();
 	gemalto_voicecall_init();
+	gemalto_netmon_init();
 
 	return 0;
 }
@@ -47,6 +48,7 @@ static void gemaltomodem_exit(void)
 	gemalto_location_reporting_exit();
 	gemalto_gprs_context_exit();
 	gemalto_voicecall_exit();
+	gemalto_netmon_exit();
 }
 
 OFONO_PLUGIN_DEFINE(gemaltomodem, "Gemalto modem driver", VERSION,
diff --git a/drivers/gemaltomodem/gemaltomodem.h b/drivers/gemaltomodem/gemaltomodem.h
index dc0d346b..ae8f2141 100644
--- a/drivers/gemaltomodem/gemaltomodem.h
+++ b/drivers/gemaltomodem/gemaltomodem.h
@@ -30,3 +30,6 @@ extern void gemalto_voicecall_exit();
 
 extern void gemalto_gprs_context_init();
 extern void gemalto_gprs_context_exit();
+
+extern void gemalto_netmon_init(void);
+extern void gemalto_netmon_exit(void);
diff --git a/drivers/gemaltomodem/netmon.c b/drivers/gemaltomodem/netmon.c
new file mode 100644
index 00000000..93e6d02f
--- /dev/null
+++ b/drivers/gemaltomodem/netmon.c
@@ -0,0 +1,609 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/netreg.h>
+#include <ofono/netmon.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "common.h"
+#include "gemaltomodem.h"
+#include "drivers/atmodem/vendor.h"
+
+static const char *smoni_prefix[] = { "^SMONI:", NULL };
+static const char *csq_prefix[] = { "+CSQ:", NULL };
+
+struct netmon_driver_data {
+	GAtChat *chat;
+};
+
+struct req_cb_data {
+	gint ref_count; /* Ref count */
+
+	struct ofono_netmon *netmon;
+	ofono_netmon_cb_t cb;
+	void *data;
+
+	struct ofono_network_operator op;
+
+	int rssi;	/* CSQ: received signal strength indicator (RSSI) */
+
+	union {
+		struct {
+			int arfcn;	/* SMONI: Absolute Radio Frequency Channel Number */
+			int bcch;	/* SMONI: Receiving level of the BCCH carrier in dBm */
+			int lac;	/* SMONI: Location Area Code */
+			int ci;		/* SMONI: Cell ID */
+		} gsm;
+		struct {
+			int uarfcn;	/* SMONI: UTRAN Absolute Radio Frequency Channel Number */
+			int psc;	/* SMONI: Primary Scrambling Code */
+			int ecn0;	/* SMONI: Carrier to noise ratio in dB */
+			int rscp;	/* SMONI: Received Signal Code Power in dBm */
+			int lac;	/* SMONI: Location Area Code */
+			int ci;		/* SMONI: Cell ID */
+		} umts;
+		struct {
+			int euarfcn;	/* SMONI: E-UTRA Absolute Radio Frequency Channel Number */
+			int rsrp;	/* SMONI: Reference Signal Received Power */
+			int rsrq;	/* SMONI: Reference Signal Received Quality */
+		} lte;
+	} t;
+};
+
+static inline struct req_cb_data *req_cb_data_new0(void *cb, void *data,
+							void *user)
+{
+	struct req_cb_data *ret = g_new0(struct req_cb_data, 1);
+
+	ret->ref_count = 1;
+	ret->netmon = user;
+	ret->data = data;
+	ret->cb = cb;
+
+	return ret;
+}
+
+static inline struct req_cb_data *req_cb_data_ref(struct req_cb_data *cbd)
+{
+	if (cbd == NULL)
+		return NULL;
+
+	g_atomic_int_inc(&cbd->ref_count);
+
+	return cbd;
+}
+
+static void req_cb_data_unref(gpointer user_data)
+{
+	struct req_cb_data *cbd = user_data;
+	gboolean is_zero;
+
+	if (cbd == NULL)
+		return;
+
+	is_zero = g_atomic_int_dec_and_test(&cbd->ref_count);
+
+	if (is_zero == TRUE)
+		g_free(cbd);
+}
+
+static gboolean gemalto_delayed_register(gpointer user_data)
+{
+	struct ofono_netmon *netmon = user_data;
+
+	ofono_netmon_register(netmon);
+
+	return FALSE;
+}
+
+static int gemalto_parse_smoni_gsm(GAtResultIter *iter,
+					struct req_cb_data *cbd)
+{
+	/*
+	 * ME is camping on a GSM (2G) cell:
+	 * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,Conn_state
+	 * ^SMONI: 2G,71,-61,262,02,0143,83BA,33,33,3,6,G,NOCONN
+	 *
+	 * ME is searching and could not (yet) find a suitable GSM (2G) cell:
+	 * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,ARFCN,TS,timAdv,dBm,Q,ChMod
+	 * ^SMONI: 2G,SEARCH,SEARCH
+	 *
+	 * ME is camping on a GSM cell but not registered to the network (only emergency call allowed):
+	 * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,PWR,RXLev,ARFCN,TS,timAdv,dBm,Q,ChMod
+	 * ^SMONI: 2G,673,-89,262,07,4EED,A500,16,16,7,4,G,5,-107,LIMSRV
+	 *
+	 * ME has a dedicated channel (for example call in progress):
+	 * ^SMONI: ACT,ARFCN,BCCH,MCC,MNC,LAC,cell,C1,C2,NCC,BCC,GPRS,ARFCN,TS,timAdv,dBm,Q,ChMod
+	 * ^SMONI: 2G,673,-80,262,07,4EED,A500,35,35,7,4,G,643,4,0,-80,0,S_FR
+	 */
+
+	enum smoni_gsm_field {
+		SMONI_GSM_ARFCN,
+		SMONI_GSM_BCCH,
+		SMONI_GSM_MCC,
+		SMONI_GSM_MNC,
+		SMONI_GSM_LAC,
+		SMONI_GSM_CI,
+		SMONI_GSM_MAX,
+	};
+
+	const char *str;
+	int number;
+	int idx;
+
+	cbd->t.gsm.arfcn = -1;
+	cbd->t.gsm.bcch = -1;
+	cbd->t.gsm.lac = -1;
+	cbd->t.gsm.ci = -1;
+
+	for (idx = 0; idx < SMONI_GSM_MAX; idx++) {
+		switch (idx) {
+		case SMONI_GSM_ARFCN:
+			if (g_at_result_iter_next_number(iter, &number))
+				cbd->t.gsm.arfcn = number;
+			break;
+		case SMONI_GSM_BCCH:
+			if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+				if (sscanf(str, "%d", &number) == 1)
+					cbd->t.gsm.bcch = number;
+			}
+			break;
+		case SMONI_GSM_MCC:
+			if (g_at_result_iter_next_number(iter, &number))
+				snprintf(cbd->op.mcc, 4, "%d", number);
+			break;
+		case SMONI_GSM_MNC:
+			if (g_at_result_iter_next_number(iter, &number))
+				snprintf(cbd->op.mnc, 4, "%d", number);
+			break;
+		case SMONI_GSM_LAC:
+			if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+				if (sscanf(str, "%x", &number) == 1)
+					cbd->t.gsm.lac = number;
+			}
+			break;
+		case SMONI_GSM_CI:
+			if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+				if (sscanf(str, "%x", &number) == 1)
+					cbd->t.gsm.ci = number;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	DBG(" %-15s %s", "GSM.MCC", cbd->op.mcc);
+	DBG(" %-15s %s", "GSM.MNC", cbd->op.mnc);
+	DBG(" %-15s %d", "GSM.ARFCN", cbd->t.gsm.arfcn);
+	DBG(" %-15s %d", "GSM.BCCH", cbd->t.gsm.bcch);
+	DBG(" %-15s %d", "GSM.LAC", cbd->t.gsm.lac);
+	DBG(" %-15s %d", "GSM.CELL", cbd->t.gsm.ci);
+
+	return 0;
+}
+
+static int gemalto_parse_smoni_umts(GAtResultIter *iter,
+					struct req_cb_data *cbd)
+{
+	/*
+	 * ME is camping on a UMTS (3G) cell:
+	 * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,,Conn_state
+	 * ^SMONI: 3G,10564,296,-7.5,-79,262,02,0143,00228FF,-92,-78,NOCONN
+	 *
+	 * ME is searching and could not (yet) find a suitable UMTS (3G) cell:
+	 * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA
+	 * ^SMONI: 3G,SEARCH,SEARCH
+	 *
+	 * ME is camping on a UMTS cell but not registered to the network (only emergency call allowed):
+	 * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA
+	 * ^SMONI: 3G,10564,96,-7.5,-79,262,02,0143,00228FF,-92,-78,LIMSRV
+	 *
+	 * ME has a dedicated channel (for example call in progress):
+	 * ^SMONI: ACT,UARFCN,PSC,EC/n0,RSCP,MCC,MNC,LAC,cell,SQual,SRxLev,PhysCh, SF,Slot,EC/n0,RSCP,ComMod,HSUPA,HSDPA
+	 * ^SMONI: 3G,10737,131,-5,-93,260,01,7D3D,C80BC9A,--,--,----,---,-,-5,-93,0,01,06
+	 */
+
+	enum smoni_umts_field {
+		SMONI_UMTS_UARFCN,
+		SMONI_UMTS_PSC,
+		SMONI_UMTS_ECN0,
+		SMONI_UMTS_RSCP,
+		SMONI_UMTS_MCC,
+		SMONI_UMTS_MNC,
+		SMONI_UMTS_LAC,
+		SMONI_UMTS_CI,
+		SMONI_UMTS_MAX,
+	};
+
+	const char *str;
+	float fnumber;
+	int number;
+	int idx;
+
+	cbd->t.umts.uarfcn = -1;
+	cbd->t.umts.psc = -1;
+	cbd->t.umts.ecn0 = -1;
+	cbd->t.umts.rscp = -1;
+	cbd->t.umts.lac = -1;
+	cbd->t.umts.ci = -1;
+
+	for (idx = 0; idx < SMONI_UMTS_MAX; idx++) {
+		switch (idx) {
+		case SMONI_UMTS_UARFCN:
+			if (g_at_result_iter_next_number(iter, &number))
+				cbd->t.umts.uarfcn = number;
+			break;
+		case SMONI_UMTS_PSC:
+			if (g_at_result_iter_next_number(iter, &number))
+				cbd->t.umts.psc = number;
+			break;
+		case SMONI_UMTS_ECN0:
+			if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+				if (sscanf(str, "%f", &fnumber) == 1)
+					cbd->t.umts.ecn0 = (int)fnumber;
+			}
+			break;
+		case SMONI_UMTS_RSCP:
+			if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+				if (sscanf(str, "%d", &number) == 1)
+					cbd->t.umts.rscp = number;
+			}
+			break;
+		case SMONI_UMTS_MCC:
+			if (g_at_result_iter_next_number(iter, &number))
+				snprintf(cbd->op.mcc, 4, "%d", number);
+			break;
+		case SMONI_UMTS_MNC:
+			if (g_at_result_iter_next_number(iter, &number))
+				snprintf(cbd->op.mnc, 4, "%d", number);
+			break;
+		case SMONI_UMTS_LAC:
+			if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+				if (sscanf(str, "%x", &number) == 1)
+					cbd->t.umts.lac = number;
+			}
+			break;
+		case SMONI_UMTS_CI:
+			if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+				if (sscanf(str, "%x", &number) == 1)
+					cbd->t.umts.ci = number;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+	DBG(" %-15s %s", "UMTS.MCC", cbd->op.mcc);
+	DBG(" %-15s %s", "UMTS.MNC", cbd->op.mnc);
+	DBG(" %-15s %d", "UMTS.UARFCN", cbd->t.umts.uarfcn);
+	DBG(" %-15s %d", "UMTS.PSC", cbd->t.umts.psc);
+	DBG(" %-15s %d", "UMTS.ECN0", cbd->t.umts.ecn0);
+	DBG(" %-15s %d", "UMTS.RSCP", cbd->t.umts.rscp);
+	DBG(" %-15s %d", "UMTS.LAC", cbd->t.umts.lac);
+	DBG(" %-15s %d", "UMTS.CELL", cbd->t.umts.ci);
+
+	return 0;
+}
+
+static int gemalto_parse_smoni_lte(GAtResultIter *iter,
+					struct req_cb_data *cbd)
+{
+	/*
+	 * ME is camping on a LTE (4G) cell:
+	 * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,Srxlev,RSRP,RSRQ,Conn_state
+	 * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-94,-7,NOCONN
+	 *
+	 * ME is searching and could not (yet) find a suitable LTE (4G) cell:
+	 * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,Srxlev,RSRP,RSRQ,Conn_state
+	 * ^SMONI: 4G,SEARCH
+	 *
+	 * ME is camping on a LTE (4G) cell but not registered to the network (only emergency call allowed):
+	 * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,Srxlev,RSRP,RSRQ,Conn_state
+	 * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,33,-94,-7,LIMSRV
+	 *
+	 * ME has a dedicated channel (for example call in progress):
+	 * ^SMONI: ACT,EARFCN,Band,DL bandwidth,UL bandwidth,Mode,MCC,MNC,TAC,Global Cell ID,Phys-ical Cell ID,TX_power,RSRP,RSRQ,Conn_state
+	 * ^SMONI: 4G,6300,20,10,10,FDD,262,02,BF75,0345103,350,90,-94,-7,CONN
+	 */
+
+	const char *str;
+	int number;
+
+	cbd->t.lte.euarfcn = -1;
+	cbd->t.lte.rsrp = -1;
+	cbd->t.lte.rsrq = -1;
+
+	if (g_at_result_iter_next_number(iter, &number))
+		cbd->t.lte.euarfcn = number;
+
+	g_at_result_iter_skip_next(iter);
+	g_at_result_iter_skip_next(iter);
+	g_at_result_iter_skip_next(iter);
+	g_at_result_iter_skip_next(iter);
+
+	if (g_at_result_iter_next_number(iter, &number))
+		snprintf(cbd->op.mcc, 4, "%d", number);
+
+	if (g_at_result_iter_next_number(iter, &number))
+		snprintf(cbd->op.mnc, 4, "%d", number);
+
+	g_at_result_iter_skip_next(iter);
+	g_at_result_iter_skip_next(iter);
+	g_at_result_iter_skip_next(iter);
+	g_at_result_iter_skip_next(iter);
+
+	if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+		if (sscanf(str, "%d", &number) == 1)
+			cbd->t.lte.rsrp = number;
+	}
+
+	if (g_at_result_iter_next_unquoted_string(iter, &str)) {
+		if (sscanf(str, "%d", &number) == 1)
+			cbd->t.lte.rsrq = number;
+	}
+
+	DBG(" %-15s %s", "LTE.MCC", cbd->op.mcc);
+	DBG(" %-15s %s", "LTE.MNC", cbd->op.mnc);
+	DBG(" %-15s %d", "LTE.EUARFCN", cbd->t.lte.euarfcn);
+	DBG(" %-15s %d", "LTE.RSRP", cbd->t.lte.rsrp);
+	DBG(" %-15s %d", "LTE.RSRQ", cbd->t.lte.rsrq);
+
+	return 0;
+}
+
+static void gemalto_netmon_finish_success(struct req_cb_data *cbd)
+{
+	struct ofono_netmon *nm = cbd->netmon;
+
+	switch (cbd->op.tech) {
+	case OFONO_NETMON_CELL_TYPE_LTE:
+		ofono_netmon_serving_cell_notify(nm, cbd->op.tech,
+					OFONO_NETMON_INFO_MCC, cbd->op.mcc,
+					OFONO_NETMON_INFO_MNC, cbd->op.mnc,
+					OFONO_NETMON_INFO_RSSI, cbd->rssi,
+					OFONO_NETMON_INFO_EARFCN, cbd->t.lte.euarfcn,
+					OFONO_NETMON_INFO_RSRP, cbd->t.lte.rsrp,
+					OFONO_NETMON_INFO_RSRQ, cbd->t.lte.rsrq,
+					OFONO_NETMON_INFO_INVALID);
+		break;
+	case OFONO_NETMON_CELL_TYPE_UMTS:
+		ofono_netmon_serving_cell_notify(nm, cbd->op.tech,
+					OFONO_NETMON_INFO_MCC, cbd->op.mcc,
+					OFONO_NETMON_INFO_MNC, cbd->op.mnc,
+					OFONO_NETMON_INFO_RSSI, cbd->rssi,
+					OFONO_NETMON_INFO_ARFCN, cbd->t.umts.uarfcn,
+					OFONO_NETMON_INFO_PSC, cbd->t.umts.psc,
+					OFONO_NETMON_INFO_ECN0, cbd->t.umts.ecn0,
+					OFONO_NETMON_INFO_RSCP, cbd->t.umts.rscp,
+					OFONO_NETMON_INFO_LAC, cbd->t.umts.lac,
+					OFONO_NETMON_INFO_CI, cbd->t.umts.ci,
+					OFONO_NETMON_INFO_INVALID);
+		break;
+	case OFONO_NETMON_CELL_TYPE_GSM:
+		ofono_netmon_serving_cell_notify(nm, cbd->op.tech,
+					OFONO_NETMON_INFO_MCC, cbd->op.mcc,
+					OFONO_NETMON_INFO_MNC, cbd->op.mnc,
+					OFONO_NETMON_INFO_RSSI, cbd->rssi,
+					OFONO_NETMON_INFO_ARFCN, cbd->t.gsm.arfcn,
+					OFONO_NETMON_INFO_LAC, cbd->t.gsm.lac,
+					OFONO_NETMON_INFO_CI, cbd->t.gsm.ci,
+					OFONO_NETMON_INFO_INVALID);
+		break;
+	default:
+		break;
+	}
+
+	CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data);
+}
+
+static void csq_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct req_cb_data *cbd = user_data;
+	struct ofono_error error;
+	GAtResultIter iter;
+	int rssi;
+
+	DBG("ok %d", ok);
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		CALLBACK_WITH_FAILURE(cbd->cb, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CSQ: ")) {
+		cbd->rssi = -1;
+		goto out;
+	}
+
+	if (!g_at_result_iter_next_number(&iter, &rssi) || rssi == 99)
+		cbd->rssi = -1;
+	else
+		cbd->rssi = (rssi * 100) / 31;
+
+	DBG(" RSSI %d ", cbd->rssi);
+
+out:
+	gemalto_netmon_finish_success(cbd);
+}
+
+static void smoni_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct req_cb_data *cbd = user_data;
+	struct ofono_netmon *nm = cbd->netmon;
+	struct netmon_driver_data *nmd = ofono_netmon_get_data(nm);
+	struct ofono_error error;
+	const char *technology;
+	GAtResultIter iter;
+	int ret;
+
+	DBG("ok %d", ok);
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		CALLBACK_WITH_FAILURE(cbd->cb, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	/* do not fail */
+
+	if (!g_at_result_iter_next(&iter, "^SMONI: ")) {
+		CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data);
+		return;
+	}
+
+	if (!g_at_result_iter_next_unquoted_string(&iter, &technology)) {
+		DBG("^SMONI: failed to parse technology");
+		CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data);
+		return;
+	}
+
+	if (strcmp(technology, "2G") == 0) {
+		cbd->op.tech = OFONO_NETMON_CELL_TYPE_GSM;
+	} else if (strcmp(technology, "3G") == 0) {
+		cbd->op.tech = OFONO_NETMON_CELL_TYPE_UMTS;
+	} else if (strcmp(technology, "4G") == 0) {
+		cbd->op.tech = OFONO_NETMON_CELL_TYPE_LTE;
+	} else {
+		/* fall-back to GSM by default */
+		DBG("^SMONI: unexpected technology: %s", technology);
+		cbd->op.tech = OFONO_NETMON_CELL_TYPE_GSM;
+	}
+
+	switch (cbd->op.tech) {
+	case OFONO_NETMON_CELL_TYPE_LTE:
+		ret = gemalto_parse_smoni_lte(&iter, cbd);
+		break;
+	case OFONO_NETMON_CELL_TYPE_UMTS:
+		ret = gemalto_parse_smoni_umts(&iter, cbd);
+		break;
+	case OFONO_NETMON_CELL_TYPE_GSM:
+		ret = gemalto_parse_smoni_gsm(&iter, cbd);
+		break;
+	default:
+		break;
+	}
+
+	if (ret) {
+		CALLBACK_WITH_SUCCESS(cbd->cb, cbd->data);
+		return;
+	}
+
+	cbd = req_cb_data_ref(cbd);
+	if (g_at_chat_send(nmd->chat, "AT+CSQ", csq_prefix,
+				csq_cb, cbd, req_cb_data_unref))
+		return;
+
+	req_cb_data_unref(cbd);
+	CALLBACK_WITH_FAILURE(cbd->cb, cbd->data);
+}
+
+static void gemalto_netmon_request_update(struct ofono_netmon *netmon,
+						ofono_netmon_cb_t cb,
+						void *data)
+{
+	struct netmon_driver_data *nmd = ofono_netmon_get_data(netmon);
+	struct req_cb_data *cbd;
+
+	DBG("gemalto netmon request update");
+
+	cbd = req_cb_data_new0(cb, data, netmon);
+
+	if (g_at_chat_send(nmd->chat, "AT^SMONI", smoni_prefix,
+				smoni_cb, cbd, req_cb_data_unref))
+		return;
+
+	req_cb_data_unref(cbd);
+	CALLBACK_WITH_FAILURE(cbd->cb, cbd->data);
+}
+
+static int gemalto_netmon_probe(struct ofono_netmon *netmon,
+					unsigned int vendor, void *user)
+{
+	GAtChat *chat = user;
+	struct netmon_driver_data *nmd;
+
+	DBG("gemalto netmon probe");
+
+	nmd = g_try_new0(struct netmon_driver_data, 1);
+	if (nmd == NULL)
+		return -ENOMEM;
+
+	nmd->chat = g_at_chat_clone(chat);
+
+	ofono_netmon_set_data(netmon, nmd);
+
+	g_idle_add(gemalto_delayed_register, netmon);
+
+	return 0;
+}
+
+static void gemalto_netmon_remove(struct ofono_netmon *netmon)
+{
+	struct netmon_driver_data *nmd = ofono_netmon_get_data(netmon);
+
+	DBG("gemalto netmon remove");
+
+	g_at_chat_unref(nmd->chat);
+
+	ofono_netmon_set_data(netmon, NULL);
+
+	g_free(nmd);
+}
+
+static const struct ofono_netmon_driver driver = {
+	.name			= "gemaltomodem",
+	.probe			= gemalto_netmon_probe,
+	.remove			= gemalto_netmon_remove,
+	.request_update		= gemalto_netmon_request_update,
+};
+
+void gemalto_netmon_init(void)
+{
+	ofono_netmon_driver_register(&driver);
+}
+
+void gemalto_netmon_exit(void)
+{
+	ofono_netmon_driver_unregister(&driver);
+}

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC PATCH 2/2] plugin: gemalto: enable netmon
  2021-01-10 19:44 [RFC PATCH 0/2] gemalto: netmon driver Sergey Matyukevich
  2021-01-10 19:44 ` [RFC PATCH 1/2] gemalto: add " Sergey Matyukevich
@ 2021-01-10 19:44 ` Sergey Matyukevich
  2021-01-11 19:56 ` [RFC PATCH 0/2] gemalto: netmon driver Denis Kenzior
  2 siblings, 0 replies; 6+ messages in thread
From: Sergey Matyukevich @ 2021-01-10 19:44 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1245 bytes --]

Enable netmon functionality for Gemalto ELS81x modems.
---
 plugins/gemalto.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/plugins/gemalto.c b/plugins/gemalto.c
index 28ee3aff..135e2d26 100644
--- a/plugins/gemalto.c
+++ b/plugins/gemalto.c
@@ -48,6 +48,7 @@
 #include <ofono/gprs.h>
 #include <ofono/gprs-context.h>
 #include <ofono/location-reporting.h>
+#include <ofono/netmon.h>
 
 #include <drivers/atmodem/atutil.h>
 #include <drivers/atmodem/vendor.h>
@@ -622,6 +623,7 @@ static void gemalto_post_sim(struct ofono_modem *modem)
 static void gemalto_post_online(struct ofono_modem *modem)
 {
 	struct gemalto_data *data = ofono_modem_get_data(modem);
+	const char *model = ofono_modem_get_string(modem, "Model");
 
 	DBG("%p", modem);
 
@@ -634,6 +636,10 @@ static void gemalto_post_online(struct ofono_modem *modem)
 	ofono_call_settings_create(modem, 0, "atmodem", data->app);
 	ofono_call_meter_create(modem, 0, "atmodem", data->app);
 	ofono_call_barring_create(modem, 0, "atmodem", data->app);
+
+	if (!g_strcmp0(model, GEMALTO_MODEL_ELS81x))
+		ofono_netmon_create(modem, OFONO_VENDOR_GEMALTO,
+					"gemaltomodem", data->app);
 }
 
 static struct ofono_modem_driver gemalto_driver = {

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 1/2] gemalto: add netmon driver
  2021-01-10 19:44 ` [RFC PATCH 1/2] gemalto: add " Sergey Matyukevich
@ 2021-01-11 19:28   ` Denis Kenzior
  0 siblings, 0 replies; 6+ messages in thread
From: Denis Kenzior @ 2021-01-11 19:28 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1240 bytes --]

Hi Sergey,

On 1/10/21 1:44 PM, Sergey Matyukevich wrote:
> Implement network monitoring driver for gemalto modems that
> are able to provide serving cell information and basic
> measurements using AT+CQS and AT^SMONI commands.
> ---
>   Makefile.am                         |   3 +-
>   drivers/gemaltomodem/gemaltomodem.c |   2 +
>   drivers/gemaltomodem/gemaltomodem.h |   3 +
>   drivers/gemaltomodem/netmon.c       | 609 ++++++++++++++++++++++++++++
>   4 files changed, 616 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/gemaltomodem/netmon.c
> 

<snip>

> +static int gemalto_netmon_probe(struct ofono_netmon *netmon,
> +					unsigned int vendor, void *user)
> +{
> +	GAtChat *chat = user;
> +	struct netmon_driver_data *nmd;
> +
> +	DBG("gemalto netmon probe");
> +
> +	nmd = g_try_new0(struct netmon_driver_data, 1);
> +	if (nmd == NULL)
> +		return -ENOMEM;

Feel free to use g_new0.  We have given up using g_try_new0 since these errors 
don't really occur on Linux.

> +
> +	nmd->chat = g_at_chat_clone(chat);
> +
> +	ofono_netmon_set_data(netmon, nmd);
> +
> +	g_idle_add(gemalto_delayed_register, netmon);
> +
> +	return 0;
> +}

Other than this, LGTM.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 0/2] gemalto: netmon driver
  2021-01-10 19:44 [RFC PATCH 0/2] gemalto: netmon driver Sergey Matyukevich
  2021-01-10 19:44 ` [RFC PATCH 1/2] gemalto: add " Sergey Matyukevich
  2021-01-10 19:44 ` [RFC PATCH 2/2] plugin: gemalto: enable netmon Sergey Matyukevich
@ 2021-01-11 19:56 ` Denis Kenzior
  2021-01-11 21:08   ` Sergey Matyukevich
  2 siblings, 1 reply; 6+ messages in thread
From: Denis Kenzior @ 2021-01-11 19:56 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1366 bytes --]

Hi Sergey,

On 1/10/21 1:44 PM, Sergey Matyukevich wrote:
> Hello Denis and all,
> 
> This patch series implements netmon driver for gemalto modems that are
> able to provide basic measurements using AT+CQS and AT^SMONI commands.
> 
> This patch series is intendedly marked as RFC. In addition to general

I guess you mean intentionally here...

> feedback for this v1 I would like to clarify the right way to handle
> negative values that can be returned by modem. For instance, this

So the short answer is: You're not supposed to even have negative numbers in AT 
commands.  And since oFono follows 27.007, which is itself based on AT commands, 
negative numbers do not really exist at the API level.

Refer to ITU v.250 Section 5.4.2.1 "Numeric constants".  Strings are also 
supposed to be formatted in a certain way, which the firmware isn't doing 
properly either...  The fact that you have to resort to using 
next_unquoted_string is kind of telling.

> is the case for the values measured in dBm including EC/n0 and RSCP.
> Currently such values are discarded by CELL_INFO_DICT_APPEND macro.

I would guess your best bet would be to re-scale from what Gemalto firmware 
reports into something that 27.007 recommends.  You may have to refer to 27.007, 
Section 8.69 to see what the scale is according to 3GPP.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC PATCH 0/2] gemalto: netmon driver
  2021-01-11 19:56 ` [RFC PATCH 0/2] gemalto: netmon driver Denis Kenzior
@ 2021-01-11 21:08   ` Sergey Matyukevich
  0 siblings, 0 replies; 6+ messages in thread
From: Sergey Matyukevich @ 2021-01-11 21:08 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1457 bytes --]

Hello Denis,

> > This patch series implements netmon driver for gemalto modems that are
> > able to provide basic measurements using AT+CQS and AT^SMONI commands.
> > 
> > This patch series is intendedly marked as RFC. In addition to general
> 
> I guess you mean intentionally here...
> 
> > feedback for this v1 I would like to clarify the right way to handle
> > negative values that can be returned by modem. For instance, this
> 
> So the short answer is: You're not supposed to even have negative numbers in
> AT commands.  And since oFono follows 27.007, which is itself based on AT
> commands, negative numbers do not really exist at the API level.
> 
> Refer to ITU v.250 Section 5.4.2.1 "Numeric constants".  Strings are also
> supposed to be formatted in a certain way, which the firmware isn't doing
> properly either...  The fact that you have to resort to using
> next_unquoted_string is kind of telling.
> 
> > is the case for the values measured in dBm including EC/n0 and RSCP.
> > Currently such values are discarded by CELL_INFO_DICT_APPEND macro.
> 
> I would guess your best bet would be to re-scale from what Gemalto firmware
> reports into something that 27.007 recommends.  You may have to refer to
> 27.007, Section 8.69 to see what the scale is according to 3GPP.

Thanks a lot for pointing me in the right direction. I will get back
with v2 once I introduce the suggested changes.

Regards,
Sergey

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-01-11 21:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-10 19:44 [RFC PATCH 0/2] gemalto: netmon driver Sergey Matyukevich
2021-01-10 19:44 ` [RFC PATCH 1/2] gemalto: add " Sergey Matyukevich
2021-01-11 19:28   ` Denis Kenzior
2021-01-10 19:44 ` [RFC PATCH 2/2] plugin: gemalto: enable netmon Sergey Matyukevich
2021-01-11 19:56 ` [RFC PATCH 0/2] gemalto: netmon driver Denis Kenzior
2021-01-11 21:08   ` Sergey Matyukevich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.