ofono.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor
@ 2023-10-17  7:33 MaxLyubimov
  2023-10-17  7:33 ` [PATCH 02/18] drivers: adding support for the SIMCom A7605E-H MaxLyubimov
                   ` (16 more replies)
  0 siblings, 17 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: Sergei Golubtsov

From: Sergei Golubtsov <sg@aqsi.ru>

This workarounds bug in EC200A firmware which leads to modem
reset in case of usage of some SIM cards when sending the next
command
---
 drivers/atmodem/sim.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index 67fe21e3..3cb8c7bd 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -1640,7 +1640,14 @@ static void at_discover_apps(struct ofono_sim *sim,
 				void *data)
 {
 	struct sim_data *sd = ofono_sim_get_data(sim);
-	struct cb_data *cbd = cb_data_new(cb, data);
+	struct cb_data *cbd;
+
+	/* QUECTEL EC2X reboots when executing the AT+CUAD command with SIM cards
+	of some operators */
+	if (sd->vendor == OFONO_VENDOR_QUECTEL_EC2X)
+		goto error;
+
+	cbd = cb_data_new(cb, data);
 
 	if (g_at_chat_send(sd->chat, "AT+CUAD", cuad_prefix,
 			at_discover_apps_cb, cbd, g_free) > 0)
@@ -1648,6 +1655,7 @@ static void at_discover_apps(struct ofono_sim *sim,
 
 	g_free(cbd);
 
+error:
 	CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
 }
 
-- 
2.25.1


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

* [PATCH 02/18] drivers: adding support for the SIMCom A7605E-H
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 03/18] plugins: " MaxLyubimov
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

The features of the SIMCom A7605E-H modem are taken into account in the atmodem driver
---
 drivers/atmodem/gprs.c | 60 +++++++++++++++++++++++++++++++++++++++++-
 drivers/atmodem/sim.c  |  7 ++---
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index 8c352ba6..a52bf2f1 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -41,6 +41,8 @@
 #include "gatchat.h"
 #include "gatresult.h"
 
+#include "atmodem.h"
+#include "common.h"
 #include "vendor.h"
 
 #define MAX_CONTEXTS 255
@@ -544,6 +546,54 @@ static void telit_mode_notify(GAtResult *result, gpointer user_data)
 	ofono_gprs_bearer_notify(gprs, bearer);
 }
 
+static void simcom_mode_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_gprs *gprs = user_data;
+	GAtResultIter iter;
+	gint stat, bearer;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CNSMOD:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter,&stat))
+		return;
+
+	switch (stat) {
+	case 0:
+		bearer = PACKET_BEARER_NONE;
+		break;
+	case 1:
+	case 2:
+		bearer = PACKET_BEARER_GPRS;
+		break;
+	case 3:
+		bearer = PACKET_BEARER_EGPRS;
+		break;
+	case 4:
+		bearer = PACKET_BEARER_UMTS;
+		break;
+	case 5:
+		bearer = PACKET_BEARER_HSDPA;
+		break;
+	case 6:
+		bearer = PACKET_BEARER_HSUPA;
+		break;
+	case 7:
+		bearer = PACKET_BEARER_HSUPA_HSDPA;
+		break;
+	case 8:
+		bearer = PACKET_BEARER_EPS;
+		break;
+	default:
+		bearer = PACKET_BEARER_NONE;
+		break;
+	}
+
+	ofono_gprs_bearer_notify(gprs, bearer);
+}
+
 static void ublox_ureg_notify(GAtResult *result, gpointer user_data)
 {
 	struct ofono_gprs *gprs = user_data;
@@ -626,6 +676,12 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
 		g_at_chat_send(gd->chat, "AT#PSNT=1", none_prefix,
 						NULL, NULL, NULL);
 		break;
+	case OFONO_VENDOR_SIMCOM:
+		g_at_chat_register(gd->chat, "+CNSMOD:", simcom_mode_notify,
+						FALSE, gprs, NULL);
+		g_at_chat_send(gd->chat, "AT+CNSMOD=1", none_prefix,
+						NULL, NULL, NULL);
+		break;
 	case OFONO_VENDOR_QUECTEL_EC2X:
 	case OFONO_VENDOR_QUECTEL_SERIAL:
 		break;
@@ -749,7 +805,9 @@ retry:
 		goto error;
 
 	g_at_chat_send(gd->chat, cmd, none_prefix, NULL, NULL, NULL);
-	g_at_chat_send(gd->chat, "AT+CGAUTO=0", none_prefix, NULL, NULL, NULL);
+	if (gd->vendor != OFONO_VENDOR_SIMCOM) {
+		g_at_chat_send(gd->chat, "AT+CGAUTO=0", none_prefix, NULL, NULL, NULL);
+	}
 
 	switch (gd->vendor) {
 	case OFONO_VENDOR_MBM:
diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index 3cb8c7bd..8849a129 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -1642,9 +1642,10 @@ static void at_discover_apps(struct ofono_sim *sim,
 	struct sim_data *sd = ofono_sim_get_data(sim);
 	struct cb_data *cbd;
 
-	/* QUECTEL EC2X reboots when executing the AT+CUAD command with SIM cards
-	of some operators */
-	if (sd->vendor == OFONO_VENDOR_QUECTEL_EC2X)
+	/* QUECTEL EC2X and SIMCom A7605E-H reboots when executing the AT+CUAD
+	command with SIM cards of some operators */
+	if (sd->vendor == OFONO_VENDOR_QUECTEL_EC2X
+			|| sd->vendor == OFONO_VENDOR_SIMCOM)
 		goto error;
 
 	cbd = cb_data_new(cb, data);
-- 
2.25.1


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

* [PATCH 03/18] plugins: adding support for the SIMCom A7605E-H
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
  2023-10-17  7:33 ` [PATCH 02/18] drivers: adding support for the SIMCom A7605E-H MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 04/18] build: " MaxLyubimov
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

The udevng plugin has been modified to detect the SIMCom A7605E-H modem and the simcom_a76xx plugin has been added to work with it
---
 plugins/simcom_a76xx.c | 321 +++++++++++++++++++++++++++++++++++++++++
 plugins/udevng.c       |  53 +++++++
 2 files changed, 374 insertions(+)
 create mode 100644 plugins/simcom_a76xx.c

diff --git a/plugins/simcom_a76xx.c b/plugins/simcom_a76xx.c
new file mode 100644
index 00000000..d66ca1b2
--- /dev/null
+++ b/plugins/simcom_a76xx.c
@@ -0,0 +1,321 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2009  Collabora Ltd. All rights reserved.
+ *  Copyright 2018 Purism SPC
+ *
+ *  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
+ *
+ */
+
+/*
+ * This file was originally copied from g1.c and
+ * modified by Bob Ham <bob.ham@puri.sm>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gattty.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-meter.h>
+#include <ofono/call-settings.h>
+#include <ofono/devinfo.h>
+#include <ofono/message-waiting.h>
+#include <ofono/netreg.h>
+#include <ofono/phonebook.h>
+#include <ofono/sim.h>
+#include <ofono/sms.h>
+#include <ofono/ussd.h>
+#include <ofono/voicecall.h>
+#include <ofono/gprs.h>
+#include <ofono/gprs-context.h>
+#include <ofono/lte.h>
+
+#include <drivers/atmodem/vendor.h>
+#include <drivers/atmodem/atutil.h>
+
+struct simcom_a76xx_data {
+	GAtChat *at;
+	GAtChat *ppp;
+};
+
+static const char *cfun_prefix[] = { "+CFUN:", NULL };
+
+static void simcom_a76xx_debug(const char *str, void *user_data)
+{
+	ofono_info("%s%s", (const char *)user_data, str);
+}
+
+/* Detect hardware, and initialize if found */
+static int simcom_a76xx_probe(struct ofono_modem *modem)
+{
+	struct simcom_a76xx_data *data;
+
+	DBG("");
+
+	data = g_try_new0(struct simcom_a76xx_data, 1);
+	if (data == NULL)
+		return -ENOMEM;
+
+	ofono_modem_set_data(modem, data);
+
+	return 0;
+}
+
+static void simcom_a76xx_remove(struct ofono_modem *modem)
+{
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	if (!data)
+		return;
+
+	if (data->at)
+		g_at_chat_unref(data->at);
+
+	if (data->ppp)
+		g_at_chat_unref(data->ppp);
+
+	ofono_modem_set_data(modem, NULL);
+	g_free (data);
+}
+
+static void cfun_set_on_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	if (ok)
+		ofono_modem_set_powered(modem, TRUE);
+}
+
+static int open_device(struct ofono_modem *modem, const char *devkey,
+			GAtChat **chatp)
+{
+	GIOChannel *channel;
+	GAtSyntax *syntax;
+	GAtChat *chat;
+	const char *device;
+
+	DBG("devkey=%s", devkey);
+
+	device = ofono_modem_get_string(modem, devkey);
+	if (device == NULL)
+		return -EINVAL;
+
+	channel = g_at_tty_open(device, NULL);
+	if (channel == NULL)
+		return -EIO;
+
+	syntax = g_at_syntax_new_gsm_permissive();
+	chat = g_at_chat_new(channel, syntax);
+	g_at_syntax_unref(syntax);
+	g_io_channel_unref(channel);
+
+	if (chat == NULL)
+		return -EIO;
+
+	if (getenv("OFONO_AT_DEBUG"))
+		g_at_chat_set_debug(chat, simcom_a76xx_debug, (void*) devkey);
+
+	*chatp = chat;
+	return 0;
+}
+
+static int simcom_a76xx_enable(struct ofono_modem *modem)
+{
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+	int err;
+
+	DBG("");
+
+	err = open_device(modem, "AT", &data->at);
+	if (err < 0)
+		return err;
+
+	err = open_device(modem, "PPP", &data->ppp);
+	if (err < 0)
+		return err;
+
+	g_at_chat_set_slave(data->ppp, data->at);
+
+	/* ensure modem is in a known state; verbose on, echo/quiet off */
+	g_at_chat_send(data->at, "ATE0Q0V1", NULL, NULL, NULL, NULL);
+
+	g_at_chat_send(data->at, "AT+CATR=3", NULL, NULL, NULL, NULL);
+
+	/* power up modem */
+	g_at_chat_send(data->at, "AT+CFUN=4", NULL, cfun_set_on_cb,
+								modem, NULL);
+
+	return 0;
+}
+
+static void cfun_set_off_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	g_at_chat_unref(data->ppp);
+	g_at_chat_unref(data->at);
+	data->at = data->ppp = NULL;
+
+	if (ok)
+		ofono_modem_set_powered(modem, FALSE);
+}
+
+static int simcom_a76xx_disable(struct ofono_modem *modem)
+{
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	/* power down modem */
+	g_at_chat_cancel_all(data->ppp);
+	g_at_chat_cancel_all(data->at);
+	g_at_chat_unregister_all(data->ppp);
+	g_at_chat_unregister_all(data->at);
+	g_at_chat_send(data->at, "AT+CFUN=0", NULL, cfun_set_off_cb,
+								modem, NULL);
+
+	return -EINPROGRESS;
+}
+
+static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_modem_online_cb_t cb = cbd->cb;
+	struct ofono_error error;
+
+	DBG("%p", user_data);
+
+	decode_at_error(&error, g_at_result_final_response(result));
+	cb(&error, cbd->data);
+}
+
+static void simcom_a76xx_set_online(struct ofono_modem *modem, ofono_bool_t online,
+				ofono_modem_online_cb_t cb, void *user_data)
+{
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+	struct cb_data *cbd = cb_data_new(cb, user_data);
+	char const *command = online ? "AT+CFUN=1" : "AT+CFUN=4";
+
+	DBG("modem %p %s", modem, online ? "online" : "offline");
+
+	if (g_at_chat_send(data->at, command, cfun_prefix, set_online_cb, cbd,
+				g_free) > 0)
+		return;
+
+	CALLBACK_WITH_FAILURE(cb, cbd->data);
+
+	g_free(cbd);
+}
+
+static void simcom_a76xx_pre_sim(struct ofono_modem *modem)
+{
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+	struct ofono_sim *sim;
+
+	DBG("");
+
+	ofono_devinfo_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
+	sim = ofono_sim_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
+	ofono_voicecall_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
+
+	if (sim) {
+		ofono_sim_inserted_notify(sim, TRUE);
+	}
+}
+
+static void simcom_a76xx_post_sim(struct ofono_modem *modem)
+{
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+	struct ofono_message_waiting *mw;
+	struct ofono_gprs *gprs = NULL;
+	struct ofono_gprs_context *gc = NULL;
+
+	DBG("");
+
+	ofono_ussd_create(modem, 0, "atmodem", data->at);
+	ofono_call_forwarding_create(modem, 0, "atmodem", data->at);
+	ofono_call_settings_create(modem, 0, "atmodem", data->at);
+	ofono_call_meter_create(modem, 0, "atmodem", data->at);
+	ofono_call_barring_create(modem, 0, "atmodem", data->at);
+	ofono_sms_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
+	ofono_phonebook_create(modem, 0, "atmodem", data->at);
+
+	gprs = ofono_gprs_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
+	gc = ofono_gprs_context_create(modem, 0, "atmodem", data->ppp);
+
+	if (gprs && gc)
+		ofono_gprs_add_context(gprs, gc);
+
+	mw = ofono_message_waiting_create(modem);
+	if (mw)
+		ofono_message_waiting_register(mw);
+}
+
+static void simcom_a76xx_post_online(struct ofono_modem *modem)
+{
+	struct simcom_a76xx_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_netreg_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
+}
+
+static struct ofono_modem_driver simcom_a76xx_driver = {
+	.name			= "simcom_a76xx",
+	.probe			= simcom_a76xx_probe,
+	.remove			= simcom_a76xx_remove,
+	.enable			= simcom_a76xx_enable,
+	.disable		= simcom_a76xx_disable,
+	.set_online		= simcom_a76xx_set_online,
+	.pre_sim		= simcom_a76xx_pre_sim,
+	.post_sim		= simcom_a76xx_post_sim,
+	.post_online	= simcom_a76xx_post_online,
+};
+
+static int simcom_a76xx_init(void)
+{
+	return ofono_modem_driver_register(&simcom_a76xx_driver);
+}
+
+static void simcom_a76xx_exit(void)
+{
+	ofono_modem_driver_unregister(&simcom_a76xx_driver);
+}
+
+OFONO_PLUGIN_DEFINE(simcom_a76xx, "SIMCom A76xx modem driver", VERSION,
+		OFONO_PLUGIN_PRIORITY_DEFAULT, simcom_a76xx_init, simcom_a76xx_exit)
diff --git a/plugins/udevng.c b/plugins/udevng.c
index f6580aba..41494906 100644
--- a/plugins/udevng.c
+++ b/plugins/udevng.c
@@ -1554,6 +1554,57 @@ static gboolean setup_sim7x00(struct modem_info *modem)
 	return TRUE;
 }
 
+static gboolean setup_simcom_a76xx(struct modem_info *modem)
+{
+	const char *diag = NULL, *gps = NULL;
+	const char *mdm = NULL, *ppp = NULL;
+	GSList *list;
+
+	DBG("%s", modem->syspath);
+
+	for (list = modem->devices; list; list = list->next) {
+		struct device_info *info = list->data;
+
+		DBG("%s %s %s %s %s %s", info->devnode, info->interface,
+						info->number, info->label,
+						info->sysattr, info->subsystem);
+
+		/*
+		 * SIMCom a76xx serial port layout:
+		 * 2: DIAG
+		 * 3: NMEA
+		 * 4: AT
+		 * 5: AT/PPP
+		 */
+		if (g_strcmp0(info->subsystem, "tty") == 0) {
+			if (g_strcmp0(info->interface, "255/0/0") == 0) {
+				if (g_strcmp0(info->number, "02") == 0)
+					diag = info->devnode;
+				else if (g_strcmp0(info->number, "03") == 0)
+					gps = info->devnode;
+				else if (g_strcmp0(info->number, "04") == 0)
+					mdm = info->devnode;
+				else if (g_strcmp0(info->number, "05") == 0)
+					ppp = info->devnode;
+			}
+		}
+	}
+
+	if (mdm == NULL)
+		return FALSE;
+
+	DBG("at=%s ppp=%s gps=%s diag=%s",
+						mdm, ppp, gps, diag);
+
+	ofono_modem_set_driver(modem->modem, "simcom_a76xx");
+
+	ofono_modem_set_string(modem->modem, "Diag", diag);
+	ofono_modem_set_string(modem->modem, "GPS", gps);
+	ofono_modem_set_string(modem->modem, "AT", mdm);
+	ofono_modem_set_string(modem->modem, "PPP", ppp);
+	return TRUE;
+}
+
 static struct {
 	const char *name;
 	gboolean (*setup)(struct modem_info *modem);
@@ -1574,6 +1625,7 @@ static struct {
 	{ "telitqmi",	setup_telitqmi	},
 	{ "simcom",	setup_simcom	},
 	{ "sim7x00",	setup_sim7x00	},
+	{ "simcom_a76xx",	setup_simcom_a76xx	},
 	{ "zte",	setup_zte	},
 	{ "icera",	setup_icera	},
 	{ "samsung",	setup_samsung	},
@@ -1951,6 +2003,7 @@ static struct {
 	{ "simcom",	"option",	"05c6", "9000"	},
 	{ "sim7x00",	"option",	"1e0e", "9001"	},
 	{ "sim7x00",	"qmi_wwan",	"1e0e",	"9001"	},
+	{ "simcom_a76xx",	"option",	"1e0e", "9011"	},
 	{ "telit",	"usbserial",	"1bc7"		},
 	{ "telit",	"option",	"1bc7"		},
 	{ "telit",	"cdc_acm",	"1bc7", "0021"	},
-- 
2.25.1


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

* [PATCH 04/18] build: adding support for the SIMCom A7605E-H
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
  2023-10-17  7:33 ` [PATCH 02/18] drivers: adding support for the SIMCom A7605E-H MaxLyubimov
  2023-10-17  7:33 ` [PATCH 03/18] plugins: " MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 05/18] drivers: simcom: Add radio settings MaxLyubimov
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

Modified the Makefile.am file to build the simcom_a76xx plugin
---
 Makefile.am | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index aac88f54..a649f085 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -586,6 +586,9 @@ builtin_sources += plugins/sim900.c
 builtin_modules += sim7100
 builtin_sources += plugins/sim7100.c
 
+builtin_modules += simcom_a76xx
+builtin_sources += plugins/simcom_a76xx.c
+
 builtin_modules += connman
 builtin_sources += plugins/connman.c
 
-- 
2.25.1


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

* [PATCH 05/18] drivers: simcom: Add radio settings
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (2 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 04/18] build: " MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 06/18] build: Add simcom radio settings rules MaxLyubimov
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 drivers/simcommodem/radio-settings.c | 245 +++++++++++++++++++++++++++
 drivers/simcommodem/simcommodem.c    |  49 ++++++
 drivers/simcommodem/simcommodem.h    |  25 +++
 3 files changed, 319 insertions(+)
 create mode 100644 drivers/simcommodem/radio-settings.c
 create mode 100644 drivers/simcommodem/simcommodem.c
 create mode 100644 drivers/simcommodem/simcommodem.h

diff --git a/drivers/simcommodem/radio-settings.c b/drivers/simcommodem/radio-settings.c
new file mode 100644
index 00000000..7addc12d
--- /dev/null
+++ b/drivers/simcommodem/radio-settings.c
@@ -0,0 +1,245 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *  Copyright (C) 2021 Sergey Matyukevich. All rights reserved.
+ *
+ *  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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/radio-settings.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "simcommodem.h"
+
+static const char *none_prefix[] = { NULL };
+static const char *cnmp_prefix[] = { "+CNMP:", NULL };
+
+struct radio_settings_data {
+	GAtChat *chat;
+};
+
+static void cnmp_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
+	unsigned int mode;
+	struct ofono_error error;
+	int r_mode;
+	GAtResultIter iter;
+
+	DBG("ok %d", ok);
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CNMP:"))
+		goto error;
+
+	if (!g_at_result_iter_next_number(&iter, &r_mode))
+		goto error;
+
+	DBG("r_mode %d", r_mode);
+
+	switch (r_mode) {
+	case 2:
+		mode = OFONO_RADIO_ACCESS_MODE_ANY;
+		break;
+	case 13:
+		mode = OFONO_RADIO_ACCESS_MODE_GSM;
+		break;
+	case 14:
+		mode = OFONO_RADIO_ACCESS_MODE_UMTS;
+		break;
+	case 38:
+		mode = OFONO_RADIO_ACCESS_MODE_LTE;
+		break;
+	default:
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	cb(&error, mode, cbd->data);
+
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+}
+
+static void simcom_query_rat_mode(struct ofono_radio_settings *rs,
+				ofono_radio_settings_rat_mode_query_cb_t cb,
+				void *data)
+{
+	struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("");
+
+	if (g_at_chat_send(rsd->chat, "AT+CNMP?", cnmp_prefix,
+				cnmp_query_cb, cbd, g_free) == 0) {
+		CALLBACK_WITH_FAILURE(cb, -1, data);
+		g_free(cbd);
+	}
+}
+
+static void cnmp_modify_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
+	struct ofono_error error;
+
+	DBG("ok %d", ok);
+
+	decode_at_error(&error, g_at_result_final_response(result));
+	cb(&error, cbd->data);
+}
+
+static void simcom_set_rat_mode(struct ofono_radio_settings *rs,
+				unsigned int m,
+				ofono_radio_settings_rat_mode_set_cb_t cb,
+				void *data)
+{
+	struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	int w_mode = 2;
+	char buf[20];
+
+	DBG("mode %d", m);
+
+	switch (m) {
+	case OFONO_RADIO_ACCESS_MODE_ANY:
+		w_mode = 2;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_GSM:
+		w_mode = 13;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_UMTS:
+	case OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM:
+		w_mode = 14;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_LTE:
+	case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM:
+	case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS:
+		w_mode = 38;
+		break;
+	}
+
+	snprintf(buf, sizeof(buf), "AT+CNMP=%u", w_mode);
+
+	if (g_at_chat_send(rsd->chat, buf, none_prefix,
+				cnmp_modify_cb, cbd, g_free) > 0)
+		return;
+
+	CALLBACK_WITH_FAILURE(cb, data);
+	g_free(cbd);
+}
+
+static void simcom_query_available_rats(struct ofono_radio_settings *rs,
+			ofono_radio_settings_available_rats_query_cb_t cb,
+			void *data)
+{
+	unsigned int available_rats = OFONO_RADIO_ACCESS_MODE_GSM
+				| OFONO_RADIO_ACCESS_MODE_UMTS
+				| OFONO_RADIO_ACCESS_MODE_LTE;
+
+	CALLBACK_WITH_SUCCESS(cb, available_rats, data);
+}
+
+static void cnmp_support_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_radio_settings *rs = user_data;
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		ofono_radio_settings_remove(rs);
+		return;
+	}
+
+	ofono_radio_settings_register(rs);
+}
+
+static int simcom_radio_settings_probe(struct ofono_radio_settings *rs,
+					unsigned int vendor, void *data)
+{
+	GAtChat *chat = data;
+	struct radio_settings_data *rsd;
+
+	DBG("");
+
+	rsd = g_new0(struct radio_settings_data, 1);
+
+	rsd->chat = g_at_chat_clone(chat);
+
+	ofono_radio_settings_set_data(rs, rsd);
+
+	g_at_chat_send(rsd->chat, "AT+CNMP=?", cnmp_prefix,
+			cnmp_support_cb, rs, NULL);
+
+	return 0;
+}
+
+static void simcom_radio_settings_remove(struct ofono_radio_settings *rs)
+{
+	struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+
+	DBG("");
+
+	ofono_radio_settings_set_data(rs, NULL);
+	g_at_chat_unref(rsd->chat);
+	g_free(rsd);
+}
+
+static const struct ofono_radio_settings_driver driver = {
+	.name			= "simcommodem",
+	.probe			= simcom_radio_settings_probe,
+	.remove			= simcom_radio_settings_remove,
+	.query_rat_mode		= simcom_query_rat_mode,
+	.set_rat_mode		= simcom_set_rat_mode,
+	.query_available_rats	= simcom_query_available_rats
+};
+
+void simcom_radio_settings_init(void)
+{
+	ofono_radio_settings_driver_register(&driver);
+}
+
+void simcom_radio_settings_exit(void)
+{
+	ofono_radio_settings_driver_unregister(&driver);
+}
diff --git a/drivers/simcommodem/simcommodem.c b/drivers/simcommodem/simcommodem.c
new file mode 100644
index 00000000..d39b05de
--- /dev/null
+++ b/drivers/simcommodem/simcommodem.c
@@ -0,0 +1,49 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017 Vincent Cesson. All rights reserved.
+ *
+ *  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 <glib.h>
+#include <gatchat.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/types.h>
+
+#include "simcommodem.h"
+
+static int simcommodem_init(void)
+{
+	simcom_radio_settings_init();
+
+	return 0;
+}
+
+static void simcommodem_exit(void)
+{
+	simcom_radio_settings_exit();
+}
+
+OFONO_PLUGIN_DEFINE(simcommodem, "Simcom modem driver", VERSION,
+			OFONO_PLUGIN_PRIORITY_DEFAULT,
+			simcommodem_init, simcommodem_exit)
diff --git a/drivers/simcommodem/simcommodem.h b/drivers/simcommodem/simcommodem.h
new file mode 100644
index 00000000..4156de76
--- /dev/null
+++ b/drivers/simcommodem/simcommodem.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017 Vincent Cesson. All rights reserved.
+ *
+ *  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
+ *
+ */
+
+#include <drivers/atmodem/atutil.h>
+
+extern void simcom_radio_settings_init(void);
+extern void simcom_radio_settings_exit(void);
-- 
2.25.1


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

* [PATCH 06/18] build: Add simcom radio settings rules
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (3 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 05/18] drivers: simcom: Add radio settings MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 07/18] plugins: simcom: Add radio settings MaxLyubimov
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 Makefile.am | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index a649f085..8c3ea657 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -505,6 +505,12 @@ builtin_sources += drivers/atmodem/atutil.h \
 			drivers/xmm7modem/ims.c \
 			drivers/xmm7modem/netmon.c
 
+builtin_modules += simcommodem
+builtin_sources += drivers/atmodem/atutil.h \
+			drivers/simcommodem/simcommodem.h \
+			drivers/simcommodem/simcommodem.c \
+			drivers/simcommodem/radio-settings.c
+
 if PHONESIM
 builtin_modules += phonesim
 builtin_sources += plugins/phonesim.c
-- 
2.25.1


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

* [PATCH 07/18] plugins: simcom: Add radio settings
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (4 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 06/18] build: Add simcom radio settings rules MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 08/18] drivers: quectel: " MaxLyubimov
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 plugins/simcom_a76xx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/plugins/simcom_a76xx.c b/plugins/simcom_a76xx.c
index d66ca1b2..059773b5 100644
--- a/plugins/simcom_a76xx.c
+++ b/plugins/simcom_a76xx.c
@@ -56,6 +56,7 @@
 #include <ofono/gprs.h>
 #include <ofono/gprs-context.h>
 #include <ofono/lte.h>
+#include <ofono/radio-settings.h>
 
 #include <drivers/atmodem/vendor.h>
 #include <drivers/atmodem/atutil.h>
@@ -274,6 +275,7 @@ static void simcom_a76xx_post_sim(struct ofono_modem *modem)
 	ofono_call_barring_create(modem, 0, "atmodem", data->at);
 	ofono_sms_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
 	ofono_phonebook_create(modem, 0, "atmodem", data->at);
+	ofono_radio_settings_create(modem, 0, "simcommodem", data->at);
 
 	gprs = ofono_gprs_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->at);
 	gc = ofono_gprs_context_create(modem, 0, "atmodem", data->ppp);
-- 
2.25.1


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

* [PATCH 08/18] drivers: quectel: Add radio settings
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (5 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 07/18] plugins: simcom: Add radio settings MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 09/18] build: Add quectel radio settings rules MaxLyubimov
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 drivers/quectelmodem/quectelmodem.c   |  49 +++++
 drivers/quectelmodem/quectelmodem.h   |  25 +++
 drivers/quectelmodem/radio-settings.c | 269 ++++++++++++++++++++++++++
 3 files changed, 343 insertions(+)
 create mode 100644 drivers/quectelmodem/quectelmodem.c
 create mode 100644 drivers/quectelmodem/quectelmodem.h
 create mode 100644 drivers/quectelmodem/radio-settings.c

diff --git a/drivers/quectelmodem/quectelmodem.c b/drivers/quectelmodem/quectelmodem.c
new file mode 100644
index 00000000..868ee0c1
--- /dev/null
+++ b/drivers/quectelmodem/quectelmodem.c
@@ -0,0 +1,49 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017 Vincent Cesson. All rights reserved.
+ *
+ *  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 <glib.h>
+#include <gatchat.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/types.h>
+
+#include "quectelmodem.h"
+
+static int quectelmodem_init(void)
+{
+	quectel_radio_settings_init();
+
+	return 0;
+}
+
+static void quectelmodem_exit(void)
+{
+	quectel_radio_settings_exit();
+}
+
+OFONO_PLUGIN_DEFINE(quectelmodem, "Quectel modem driver", VERSION,
+			OFONO_PLUGIN_PRIORITY_DEFAULT,
+			quectelmodem_init, quectelmodem_exit)
diff --git a/drivers/quectelmodem/quectelmodem.h b/drivers/quectelmodem/quectelmodem.h
new file mode 100644
index 00000000..53ea1df8
--- /dev/null
+++ b/drivers/quectelmodem/quectelmodem.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017 Vincent Cesson. All rights reserved.
+ *
+ *  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
+ *
+ */
+
+#include <drivers/atmodem/atutil.h>
+
+extern void quectel_radio_settings_init(void);
+extern void quectel_radio_settings_exit(void);
diff --git a/drivers/quectelmodem/radio-settings.c b/drivers/quectelmodem/radio-settings.c
new file mode 100644
index 00000000..dbc46ee1
--- /dev/null
+++ b/drivers/quectelmodem/radio-settings.c
@@ -0,0 +1,269 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *  Copyright (C) 2021 Sergey Matyukevich. All rights reserved.
+ *
+ *  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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/radio-settings.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "quectelmodem.h"
+
+static const char *none_prefix[] = { NULL };
+static const char *qcfg_prefix[] = { "+QCFG:", NULL };
+
+struct radio_settings_data {
+	GAtChat *chat;
+};
+
+static void qcfg_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
+	unsigned int mode;
+	struct ofono_error error;
+	int nwscanseq;
+	GAtResultIter iter;
+
+	DBG("ok %d", ok);
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+QCFG: \"nwscanseq\","))
+		goto error;
+
+	if (!g_at_result_iter_next_number(&iter, &nwscanseq))
+		goto error;
+
+	DBG("nwscanseq %d", nwscanseq);
+
+	switch (nwscanseq) {
+	case 0:
+	case 4:
+	case 5:
+	case 12:
+		mode = OFONO_RADIO_ACCESS_MODE_ANY;
+		break;
+	case 1:
+		mode = OFONO_RADIO_ACCESS_MODE_GSM;
+		break;
+	case 2:
+		mode = OFONO_RADIO_ACCESS_MODE_UMTS;
+		break;
+	case 3:
+		mode = OFONO_RADIO_ACCESS_MODE_LTE;
+		break;
+	case 6:
+	case 8:
+		mode = OFONO_RADIO_ACCESS_MODE_UMTS |
+			OFONO_RADIO_ACCESS_MODE_LTE;
+		break;
+	case 7:
+	case 10:
+		mode = OFONO_RADIO_ACCESS_MODE_GSM |
+			OFONO_RADIO_ACCESS_MODE_LTE;
+		break;
+	case 9:
+	case 11:
+		mode = OFONO_RADIO_ACCESS_MODE_GSM |
+			OFONO_RADIO_ACCESS_MODE_UMTS;
+		break;
+	default:
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	cb(&error, mode, cbd->data);
+
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+}
+
+static void quectel_query_rat_mode(struct ofono_radio_settings *rs,
+				ofono_radio_settings_rat_mode_query_cb_t cb,
+				void *data)
+{
+	struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("");
+
+	if (g_at_chat_send(rsd->chat, "AT+QCFG=\"nwscanseq\"", qcfg_prefix,
+				qcfg_query_cb, cbd, g_free) == 0) {
+		CALLBACK_WITH_FAILURE(cb, -1, data);
+		g_free(cbd);
+	}
+}
+
+static void qcfg_modify_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
+	struct ofono_error error;
+
+	DBG("ok %d", ok);
+
+	decode_at_error(&error, g_at_result_final_response(result));
+	cb(&error, cbd->data);
+}
+
+static void quectel_set_rat_mode(struct ofono_radio_settings *rs,
+				unsigned int m,
+				ofono_radio_settings_rat_mode_set_cb_t cb,
+				void *data)
+{
+	struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	int nwscanseq;
+	char buf[30];
+
+	DBG("mode %d", m);
+
+	switch (m) {
+	case OFONO_RADIO_ACCESS_MODE_ANY:
+		nwscanseq = 0;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_GSM:
+		nwscanseq = 1;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_UMTS:
+		nwscanseq = 2;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_LTE:
+		nwscanseq = 3;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM:
+		nwscanseq = 9;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS:
+		nwscanseq = 6;
+		break;
+	case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM:
+		nwscanseq = 7;
+		break;
+	}
+
+	snprintf(buf, sizeof(buf), "AT+QCFG=\"nwscanseq\",%u", nwscanseq);
+
+	if (g_at_chat_send(rsd->chat, buf, none_prefix,
+				qcfg_modify_cb, cbd, g_free) > 0)
+		return;
+
+	CALLBACK_WITH_FAILURE(cb, data);
+	g_free(cbd);
+}
+
+static void quectel_query_available_rats(struct ofono_radio_settings *rs,
+			ofono_radio_settings_available_rats_query_cb_t cb,
+			void *data)
+{
+	unsigned int available_rats = OFONO_RADIO_ACCESS_MODE_GSM
+				| OFONO_RADIO_ACCESS_MODE_UMTS
+				| OFONO_RADIO_ACCESS_MODE_LTE;
+
+	CALLBACK_WITH_SUCCESS(cb, available_rats, data);
+}
+
+static void qcfg_support_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_radio_settings *rs = user_data;
+
+	DBG("ok %d", ok);
+
+	if (!ok) {
+		ofono_radio_settings_remove(rs);
+		return;
+	}
+
+	ofono_radio_settings_register(rs);
+}
+
+static int quectel_radio_settings_probe(struct ofono_radio_settings *rs,
+					unsigned int vendor, void *data)
+{
+	GAtChat *chat = data;
+	struct radio_settings_data *rsd;
+
+	DBG("");
+
+	rsd = g_new0(struct radio_settings_data, 1);
+
+	rsd->chat = g_at_chat_clone(chat);
+
+	ofono_radio_settings_set_data(rs, rsd);
+
+	g_at_chat_send(rsd->chat, "AT+QCFG=\"nwscanseq\"", qcfg_prefix,
+			qcfg_support_cb, rs, NULL);
+
+	return 0;
+}
+
+static void quectel_radio_settings_remove(struct ofono_radio_settings *rs)
+{
+	struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+
+	DBG("");
+
+	ofono_radio_settings_set_data(rs, NULL);
+	g_at_chat_unref(rsd->chat);
+	g_free(rsd);
+}
+
+static const struct ofono_radio_settings_driver driver = {
+	.name			= "quectelmodem",
+	.probe			= quectel_radio_settings_probe,
+	.remove			= quectel_radio_settings_remove,
+	.query_rat_mode		= quectel_query_rat_mode,
+	.set_rat_mode		= quectel_set_rat_mode,
+	.query_available_rats	= quectel_query_available_rats
+};
+
+void quectel_radio_settings_init(void)
+{
+	ofono_radio_settings_driver_register(&driver);
+}
+
+void quectel_radio_settings_exit(void)
+{
+	ofono_radio_settings_driver_unregister(&driver);
+}
-- 
2.25.1


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

* [PATCH 09/18] build: Add quectel radio settings rules
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (6 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 08/18] drivers: quectel: " MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 10/18] plugins: quectel: Add radio settings MaxLyubimov
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 Makefile.am | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index 8c3ea657..6c112bf0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -511,6 +511,12 @@ builtin_sources += drivers/atmodem/atutil.h \
 			drivers/simcommodem/simcommodem.c \
 			drivers/simcommodem/radio-settings.c
 
+builtin_modules += quectelmodem
+builtin_sources += drivers/atmodem/atutil.h \
+			drivers/quectelmodem/quectelmodem.h \
+			drivers/quectelmodem/quectelmodem.c \
+			drivers/quectelmodem/radio-settings.c
+
 if PHONESIM
 builtin_modules += phonesim
 builtin_sources += plugins/phonesim.c
-- 
2.25.1


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

* [PATCH 10/18] plugins: quectel: Add radio settings
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (7 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 09/18] build: Add quectel radio settings rules MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 11/18] drivers: gemalto: Add models list MaxLyubimov
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 plugins/quectel.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/plugins/quectel.c b/plugins/quectel.c
index 464845ff..1dd67e80 100644
--- a/plugins/quectel.c
+++ b/plugins/quectel.c
@@ -53,6 +53,7 @@
 #include <ofono/gprs-context.h>
 #include <ofono/log.h>
 #include <ofono/dbus.h>
+#include <ofono/radio-settings.h>
 
 #include <gdbus/gdbus.h>
 
@@ -1366,6 +1367,7 @@ static void quectel_post_sim(struct ofono_modem *modem)
 	ofono_sms_create(modem, data->vendor, "atmodem", data->aux);
 	ofono_phonebook_create(modem, data->vendor, "atmodem", data->aux);
 	ofono_call_volume_create(modem, data->vendor, "atmodem", data->aux);
+	ofono_radio_settings_create(modem, 0, "quectelmodem", data->aux);
 
 	if (data->model == QUECTEL_EC21 || data->model == QUECTEL_EC200)
 		ofono_ussd_create(modem, data->vendor, "atmodem", data->aux);
-- 
2.25.1


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

* [PATCH 11/18] drivers: gemalto: Add models list
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (8 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 10/18] plugins: quectel: Add radio settings MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 12/18] plugins: gemalto: Include " MaxLyubimov
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 drivers/gemaltomodem/models.h | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 drivers/gemaltomodem/models.h

diff --git a/drivers/gemaltomodem/models.h b/drivers/gemaltomodem/models.h
new file mode 100644
index 00000000..6d0d6490
--- /dev/null
+++ b/drivers/gemaltomodem/models.h
@@ -0,0 +1,32 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2017 Vincent Cesson. All rights reserved.
+ *  Copyright (C) 2018 Gemalto M2M
+ *
+ *  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
+ *
+ */
+
+/* Supported gemalto's modem */
+/* PHS8-P modem */
+#define GEMALTO_MODEL_PHS8P	"0053"
+/* ALS3, PLS8-E, and PLS8-X family */
+#define GEMALTO_MODEL_ALS3_PLS8x	"0061"
+/* ELS81 modem */
+#define GEMALTO_MODEL_ELS81x	"005b"
+/* EHS5-E modem */
+#define GEMALTO_MODEL_EHS5_E	"0058"
+
-- 
2.25.1


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

* [PATCH 12/18] plugins: gemalto: Include models list
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (9 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 11/18] drivers: gemalto: Add models list MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 13/18] plugins: udevng: Add support gemalto EHS5-E MaxLyubimov
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

Include models list from drivers/gemaltomodem/models.h
---
 plugins/gemalto.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/plugins/gemalto.c b/plugins/gemalto.c
index d1962ab8..fb6b79e7 100644
--- a/plugins/gemalto.c
+++ b/plugins/gemalto.c
@@ -53,16 +53,10 @@
 
 #include <drivers/atmodem/atutil.h>
 #include <drivers/atmodem/vendor.h>
+#include <drivers/gemaltomodem/models.h>
 
 #define HARDWARE_MONITOR_INTERFACE OFONO_SERVICE ".cinterion.HardwareMonitor"
 
-/* Supported gemalto's modem */
-#define GEMALTO_MODEL_PHS8P	"0053"
-/* ALS3, PLS8-E, and PLS8-X family */
-#define GEMALTO_MODEL_ALS3_PLS8x	"0061"
-/* ELS81 modem */
-#define GEMALTO_MODEL_ELS81x   "005b"
-
 static const char *none_prefix[] = { NULL };
 static const char *sctm_prefix[] = { "^SCTM:", NULL };
 static const char *sbv_prefix[] = { "^SBV:", NULL };
-- 
2.25.1


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

* [PATCH 13/18] plugins: udevng: Add support gemalto EHS5-E
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (10 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 12/18] plugins: gemalto: Include " MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 14/18] gemalto: radio-settings: Add support EHS5-E MaxLyubimov
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 plugins/udevng.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/plugins/udevng.c b/plugins/udevng.c
index 41494906..62efb210 100644
--- a/plugins/udevng.c
+++ b/plugins/udevng.c
@@ -1356,7 +1356,7 @@ static gboolean setup_gemalto(struct modem_info *modem)
 				qmi = info->devnode;
 		}
 
-		/* Cinterion ALS3, PLS8-E, PLS8-X */
+		/* Cinterion ALS3, PLS8-E, PLS8-X, EHS5-E */
 		if (g_strcmp0(info->interface, "2/2/1") == 0) {
 			if (g_strcmp0(info->number, "00") == 0)
 				mdm = info->devnode;
@@ -2033,6 +2033,7 @@ static struct {
 	{ "gemalto",	"option",	"1e2d",	"0053"	},
 	{ "gemalto",	"cdc_wdm",	"1e2d",	"0053"	},
 	{ "gemalto",	"qmi_wwan",	"1e2d",	"0053"	},
+	{ "gemalto",	"cdc_acm",	"1e2d",	"0058"	},
 	{ "gemalto",	"cdc_acm",	"1e2d",	"0061"	},
 	{ "gemalto",	"cdc_ether",	"1e2d",	"0061"	},
 	{ "gemalto",	"cdc_acm",	"1e2d",	"005b"	},
-- 
2.25.1


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

* [PATCH 14/18] gemalto: radio-settings: Add support EHS5-E
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (11 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 13/18] plugins: udevng: Add support gemalto EHS5-E MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 15/18] Fix PPP LCP Configure-Reject MaxLyubimov
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 drivers/gemaltomodem/radio-settings.c | 233 ++++++++++++++++++--------
 1 file changed, 162 insertions(+), 71 deletions(-)

diff --git a/drivers/gemaltomodem/radio-settings.c b/drivers/gemaltomodem/radio-settings.c
index d711658d..ff7218a1 100644
--- a/drivers/gemaltomodem/radio-settings.c
+++ b/drivers/gemaltomodem/radio-settings.c
@@ -40,6 +40,9 @@
 #include "gatchat.h"
 #include "gatresult.h"
 
+#include "gemaltomodem.h"
+#include "models.h"
+
 static const char *none_prefix[] = { NULL };
 static const char *sxrat_prefix[] = { "^SXRAT:", NULL };
 
@@ -47,13 +50,32 @@ struct radio_settings_data {
 	GAtChat *chat;
 };
 
+static void gemalto_query_available_rats(struct ofono_radio_settings *rs,
+			ofono_radio_settings_available_rats_query_cb_t cb,
+			void *data) {
+	unsigned int available_rats;
+	struct ofono_modem *modem = ofono_radio_settings_get_modem(rs);
+	const char *model = ofono_modem_get_string(modem, "Model");
+
+	available_rats = OFONO_RADIO_ACCESS_MODE_GSM
+				| OFONO_RADIO_ACCESS_MODE_UMTS;
+
+	if (!g_strcmp0(model, GEMALTO_MODEL_ALS3_PLS8x) ||
+		!g_strcmp0(model, GEMALTO_MODEL_ELS81x))
+		available_rats |= OFONO_RADIO_ACCESS_MODE_LTE;
+
+	CALLBACK_WITH_SUCCESS(cb, available_rats, data);
+}
+
 static void sxrat_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
 	ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
+	struct ofono_radio_settings *rs = cbd->data;
+	struct ofono_modem *modem = ofono_radio_settings_get_modem(rs);
+	const char *model = ofono_modem_get_string(modem, "Model");
 	unsigned int mode;
 	struct ofono_error error;
-	int value, pref1, pref2;
 	GAtResultIter iter;
 
 	DBG("ok %d", ok);
@@ -70,42 +92,76 @@ static void sxrat_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	if (!g_at_result_iter_next(&iter, "^SXRAT:"))
 		goto error;
 
-	if (!g_at_result_iter_next_number(&iter, &value))
+	if (!g_strcmp0(model, GEMALTO_MODEL_ALS3_PLS8x) ||
+		!g_strcmp0(model, GEMALTO_MODEL_ELS81x)) {
+		int value, pref1, pref2;
+		
+		if (!g_at_result_iter_next_number(&iter, &value))
+			goto error;
+		
+		g_at_result_iter_next_number_default(&iter, -1, &pref1);
+		g_at_result_iter_next_number_default(&iter, -1, &pref2);
+
+		DBG("mode %d pref1 %d pref2 %d", value, pref1, pref2);
+
+		switch (value) {
+		case 0:
+			mode = OFONO_RADIO_ACCESS_MODE_GSM;
+			break;
+		case 1:
+			mode = OFONO_RADIO_ACCESS_MODE_GSM |
+				OFONO_RADIO_ACCESS_MODE_UMTS;
+			break;
+		case 2:
+			mode = OFONO_RADIO_ACCESS_MODE_UMTS;
+			break;
+		case 3:
+			mode = OFONO_RADIO_ACCESS_MODE_LTE;
+			break;
+		case 4:
+			mode = OFONO_RADIO_ACCESS_MODE_UMTS |
+				OFONO_RADIO_ACCESS_MODE_LTE;
+			break;
+		case 5:
+			mode = OFONO_RADIO_ACCESS_MODE_GSM |
+				OFONO_RADIO_ACCESS_MODE_LTE;
+			break;
+		case 6:
+			mode = OFONO_RADIO_ACCESS_MODE_ANY;
+			break;
+		default:
+			CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+			return;
+		}
+	}
+	else if (!g_strcmp0(model, GEMALTO_MODEL_EHS5_E)) {
+		int act, act_pref;
+		
+		if (!g_at_result_iter_next_number(&iter, &act))
+			goto error;
+		
+		g_at_result_iter_next_number_default(&iter, -1, &act_pref);
+		
+		DBG("act %d act_pref %d", act, act_pref);
+		
+		switch (act) {
+		case 0:
+			mode = OFONO_RADIO_ACCESS_MODE_GSM;
+			break;
+		case 1:
+			mode = OFONO_RADIO_ACCESS_MODE_GSM |
+				OFONO_RADIO_ACCESS_MODE_UMTS;
+			break;
+		case 2:
+			mode = OFONO_RADIO_ACCESS_MODE_UMTS;
+			break;
+		default:
+			CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+			return;
+		}
+	}
+	else {
 		goto error;
-
-	g_at_result_iter_next_number_default(&iter, -1, &pref1);
-	g_at_result_iter_next_number_default(&iter, -1, &pref2);
-
-	DBG("mode %d pref1 %d pref2 %d", value, pref1, pref2);
-
-	switch (value) {
-	case 0:
-		mode = OFONO_RADIO_ACCESS_MODE_GSM;
-		break;
-	case 1:
-		mode = OFONO_RADIO_ACCESS_MODE_GSM |
-			OFONO_RADIO_ACCESS_MODE_UMTS;
-		break;
-	case 2:
-		mode = OFONO_RADIO_ACCESS_MODE_UMTS;
-		break;
-	case 3:
-		mode = OFONO_RADIO_ACCESS_MODE_LTE;
-		break;
-	case 4:
-		mode = OFONO_RADIO_ACCESS_MODE_UMTS |
-			OFONO_RADIO_ACCESS_MODE_LTE;
-		break;
-	case 5:
-		mode = OFONO_RADIO_ACCESS_MODE_GSM |
-			OFONO_RADIO_ACCESS_MODE_LTE;
-		break;
-	case 6:
-		mode = OFONO_RADIO_ACCESS_MODE_ANY;
-		break;
-	default:
-		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
-		return;
 	}
 
 	cb(&error, mode, cbd->data);
@@ -151,51 +207,85 @@ static void gemalto_set_rat_mode(struct ofono_radio_settings *rs,
 {
 	struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
 	struct cb_data *cbd = cb_data_new(cb, data);
-	int val= 6, p1 = 3, p2 = 2;
+	struct ofono_modem *modem = ofono_radio_settings_get_modem(rs);
+	const char *model = ofono_modem_get_string(modem, "Model");
 	char buf[20];
 
 	DBG("mode %d", m);
 
-	switch (m) {
-	case OFONO_RADIO_ACCESS_MODE_ANY:
-		val = 6;
-		p1 = 3;
-		p2 = 2;
-		break;
-	case OFONO_RADIO_ACCESS_MODE_GSM:
-		val = 0;
-		break;
-	case OFONO_RADIO_ACCESS_MODE_UMTS:
-		val = 2;
-		break;
-	case OFONO_RADIO_ACCESS_MODE_LTE:
-		val = 3;
-		break;
-	case OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM:
-		val = 1;
-		p1 = 2;
-		break;
-	case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS:
-		val = 4;
-		p1 = 3;
-		break;
-	case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM:
-		val = 5;
-		p1 = 3;
-		break;
+	if (!g_strcmp0(model, GEMALTO_MODEL_ALS3_PLS8x) ||
+		!g_strcmp0(model, GEMALTO_MODEL_ELS81x)) {
+		int val= 6, p1 = 3, p2 = 2;
+		switch (m) {
+		case OFONO_RADIO_ACCESS_MODE_ANY:
+			val = 6;
+			p1 = 3;
+			p2 = 2;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_GSM:
+			val = 0;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_UMTS:
+			val = 2;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_LTE:
+			val = 3;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM:
+			val = 1;
+			p1 = 2;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS:
+			val = 4;
+			p1 = 3;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM:
+			val = 5;
+			p1 = 3;
+			break;
+		}
+
+		if (val == 6)
+			snprintf(buf, sizeof(buf), "AT^SXRAT=%u,%u,%u", val, p1, p2);
+		else if (val == 1 || val == 4 || val == 5)
+			snprintf(buf, sizeof(buf), "AT^SXRAT=%u,%u", val, p1);
+		else
+			snprintf(buf, sizeof(buf), "AT^SXRAT=%u", val);
+	}
+	else if (!g_strcmp0(model, GEMALTO_MODEL_EHS5_E)) {
+		int act = 1, act_pref = 2;
+		switch (m) {
+		case OFONO_RADIO_ACCESS_MODE_ANY:
+		case OFONO_RADIO_ACCESS_MODE_UMTS|OFONO_RADIO_ACCESS_MODE_GSM:
+			act = 1;
+			act_pref = 2;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_GSM:
+			act = 0;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_UMTS:
+			act = 2;
+			break;
+		case OFONO_RADIO_ACCESS_MODE_LTE:
+		case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_UMTS:
+		case OFONO_RADIO_ACCESS_MODE_LTE|OFONO_RADIO_ACCESS_MODE_GSM:
+			goto error;
+		}
+
+		if (act == 1)
+			snprintf(buf, sizeof(buf), "AT^SXRAT=%u,%u", act, act_pref);
+		else
+			snprintf(buf, sizeof(buf), "AT^SXRAT=%u", act);
+	}
+	else {
+		goto error;
 	}
-
-	if (val == 6)
-		snprintf(buf, sizeof(buf), "AT^SXRAT=%u,%u,%u", val, p1, p2);
-	else if (val == 1 || val == 4 || val == 5)
-		snprintf(buf, sizeof(buf), "AT^SXRAT=%u,%u", val, p1);
-	else
-		snprintf(buf, sizeof(buf), "AT^SXRAT=%u", val);
 
 	if (g_at_chat_send(rsd->chat, buf, none_prefix,
 				sxrat_modify_cb, cbd, g_free) > 0)
 		return;
 
+error:
 	CALLBACK_WITH_FAILURE(cb, data);
 	g_free(cbd);
 }
@@ -248,6 +338,7 @@ static void gemalto_radio_settings_remove(struct ofono_radio_settings *rs)
 static const struct ofono_radio_settings_driver driver = {
 	.probe			= gemalto_radio_settings_probe,
 	.remove			= gemalto_radio_settings_remove,
+	.query_available_rats = gemalto_query_available_rats,
 	.query_rat_mode		= gemalto_query_rat_mode,
 	.set_rat_mode		= gemalto_set_rat_mode
 };
-- 
2.25.1


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

* [PATCH 15/18] Fix PPP LCP Configure-Reject
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (12 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 14/18] gemalto: radio-settings: Add support EHS5-E MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 16/18] atmodem: added context deactivation event handling MaxLyubimov
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

According to RFC 1661 5.4

If some Configuration Options received in a Configure-Request are
not recognizable or are not acceptable for negotiation (as
configured by a network administrator), then the implementation
MUST transmit a Configure-Reject.  The Options field is filled
with only the unacceptable Configuration Options from the
Configure-Request.  All recognizable and negotiable Configuration
Options are filtered out of the Configure-Reject, but otherwise
the Configuration Options MUST NOT be reordered or modified in any
way.

Therefore, if the authorization type is NONE, then the authorization
type must be added to the list of not acceptable options.
---
 gatchat/ppp_lcp.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/gatchat/ppp_lcp.c b/gatchat/ppp_lcp.c
index 7c45a27f..26ee7456 100644
--- a/gatchat/ppp_lcp.c
+++ b/gatchat/ppp_lcp.c
@@ -236,6 +236,7 @@ static enum rcr_result lcp_rcr(struct pppcp_data *pppcp,
 		{
 			const guint8 *option_data =
 				ppp_option_iter_get_data(&iter);
+			guint8 option_length = ppp_option_iter_get_length(&iter);
 			guint16 proto = get_host_short(option_data);
 			guint8 method = option_data[2];
 			guint8 *option;
@@ -283,6 +284,15 @@ static enum rcr_result lcp_rcr(struct pppcp_data *pppcp,
 				return RCR_NAK;
 
 			case G_AT_PPP_AUTH_METHOD_NONE:
+				option = g_try_malloc0(option_length + 2);
+				if (option == NULL)
+					return RCR_REJECT;
+
+				option[0] = AUTH_PROTO;
+				option[1] = option_length + 2;
+				memcpy(option + 2, option_data, option_length);
+				*new_options = option;
+				*new_len = option_length + 2;
 				return RCR_REJECT;
 			}
 			break;
-- 
2.25.1


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

* [PATCH 16/18] atmodem: added context deactivation event handling
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (13 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 15/18] Fix PPP LCP Configure-Reject MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 17/18] gatchat: added command completion by timeout MaxLyubimov
  2023-10-17  7:33 ` [PATCH 18/18] ppp: message tracing MaxLyubimov
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 drivers/atmodem/gprs-context.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/atmodem/gprs-context.c b/drivers/atmodem/gprs-context.c
index 1954c6c6..d92b6392 100644
--- a/drivers/atmodem/gprs-context.c
+++ b/drivers/atmodem/gprs-context.c
@@ -359,9 +359,12 @@ static void cgev_notify(GAtResult *result, gpointer user_data)
 	struct ofono_gprs_context *gc = user_data;
 	struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
 	const char *event;
-	int cid;
+	unsigned int cid;
+	int r;
 	GAtResultIter iter;
 
+	DBG("");
+
 	g_at_result_iter_init(&iter, result);
 
 	if (!g_at_result_iter_next(&iter, "+CGEV:"))
@@ -370,18 +373,23 @@ static void cgev_notify(GAtResult *result, gpointer user_data)
 	if (!g_at_result_iter_next_unquoted_string(&iter, &event))
 		return;
 
-	if (g_str_has_prefix(event, "NW DEACT") == FALSE)
-		return;
-
-	if (!g_at_result_iter_skip_next(&iter))
+	if (g_str_has_prefix(event, "NW PDN DEACT"))
+		r = sscanf(event, "%*s %*s %*s %u", &cid);
+	else if (g_str_has_prefix(event, "ME PDN DEACT"))
+		r = sscanf(event, "%*s %*s %*s %u", &cid);
+	else if (g_str_has_prefix(event, "NW DEACT"))
+		r = sscanf(event, "%*s %*s %u", &cid);
+	else if (g_str_has_prefix(event, "ME DEACT"))
+		r = sscanf(event, "%*s %*s %u", &cid);
+	else
 		return;
 
-	if (!g_at_result_iter_next_number(&iter, &cid))
+	if (r != 1)
 		return;
 
-	DBG("cid %d", cid);
+	DBG("cid %u", cid);
 
-	if ((unsigned int) cid != gcd->active_context)
+	if (cid != gcd->active_context)
 		return;
 
 	if (gcd->state != STATE_IDLE && gcd->ppp)
-- 
2.25.1


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

* [PATCH 17/18] gatchat: added command completion by timeout
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (14 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 16/18] atmodem: added context deactivation event handling MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  7:33 ` [PATCH 18/18] ppp: message tracing MaxLyubimov
  16 siblings, 0 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

---
 gatchat/gatchat.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/gatchat/gatchat.c b/gatchat/gatchat.c
index 9e777107..f4249406 100644
--- a/gatchat/gatchat.c
+++ b/gatchat/gatchat.c
@@ -38,11 +38,16 @@
 
 /* #define WRITE_SCHEDULER_DEBUG 1 */
 
+#define COMMAND_RESPONSE_TIMEOUT_SEC 20
+
 #define COMMAND_FLAG_EXPECT_PDU			0x1
 #define COMMAND_FLAG_EXPECT_SHORT_PROMPT	0x2
 
 struct at_chat;
 static void chat_wakeup_writer(struct at_chat *chat);
+static void set_response_timeout(struct at_chat *chat);
+static void delete_response_timeout(struct at_chat *chat);
+static void refresh_response_timeout(struct at_chat *chat);
 
 static const char *none_prefix[] = { NULL };
 
@@ -92,6 +97,8 @@ struct at_chat {
 	gpointer debug_data;			/* Data to pass to debug func */
 	char *pdu_notify;			/* Unsolicited Resp w/ PDU */
 	GSList *response_lines;			/* char * lines of the response */
+	guint response_timeout_source;
+	guint response_timeout_counter;
 	char *wakeup;				/* command sent to wakeup modem */
 	gint timeout_source;
 	gdouble inactivity_time;		/* Period of inactivity */
@@ -360,6 +367,9 @@ static void chat_cleanup(struct at_chat *chat)
 		g_slist_free_full(chat->terminator_list, free_terminator);
 		chat->terminator_list = NULL;
 	}
+
+	delete_response_timeout(chat);
+	chat->response_timeout_counter = 0;
 }
 
 static void io_disconnect(gpointer user_data)
@@ -431,11 +441,14 @@ static gboolean at_chat_match_notify(struct at_chat *chat, char *line)
 	return ret;
 }
 
+
 static void at_chat_finish_command(struct at_chat *p, gboolean ok, char *final)
 {
 	struct at_command *cmd = g_queue_pop_head(p->command_queue);
 	GSList *response_lines;
 
+	refresh_response_timeout(p);
+
 	/* Cannot happen, but lets be paranoid */
 	if (cmd == NULL)
 		return;
@@ -938,6 +951,8 @@ static void at_chat_suspend(struct at_chat *chat)
 	g_at_io_set_write_handler(chat->io, NULL, NULL);
 	g_at_io_set_read_handler(chat->io, NULL, NULL);
 	g_at_io_set_debug(chat->io, NULL, NULL);
+
+	delete_response_timeout(chat);
 }
 
 static void at_chat_resume(struct at_chat *chat)
@@ -956,6 +971,8 @@ static void at_chat_resume(struct at_chat *chat)
 
 	if (g_queue_get_length(chat->command_queue) > 0)
 		chat_wakeup_writer(chat);
+
+	refresh_response_timeout(chat);
 }
 
 static void at_chat_unref(struct at_chat *chat)
@@ -1044,6 +1061,8 @@ static guint at_chat_send_common(struct at_chat *chat, guint gid,
 	if (g_queue_get_length(chat->command_queue) == 1)
 		chat_wakeup_writer(chat);
 
+	set_response_timeout(chat);
+
 	return c->id;
 }
 
@@ -1125,6 +1144,8 @@ static gboolean at_chat_cancel(struct at_chat *chat, guint group, guint id)
 		g_queue_remove(chat->command_queue, c);
 	}
 
+	refresh_response_timeout(chat);
+
 	return TRUE;
 }
 
@@ -1152,6 +1173,8 @@ static gboolean at_chat_cancel_group(struct at_chat *chat, guint group)
 		g_queue_remove(chat->command_queue, c);
 	}
 
+	refresh_response_timeout(chat);
+
 	return TRUE;
 }
 
@@ -1314,6 +1337,8 @@ static struct at_chat *create_chat(GIOChannel *channel, GIOFlags flags,
 	g_at_io_set_read_handler(chat->io, new_bytes, chat);
 
 	chat->syntax = g_at_syntax_ref(syntax);
+	chat->response_timeout_source = 0;
+	chat->response_timeout_counter = 0;
 
 	return chat;
 
@@ -1351,6 +1376,63 @@ static GAtChat *g_at_chat_new_common(GIOChannel *channel, GIOFlags flags,
 	return chat;
 }
 
+static gboolean response_timeout_cb(gpointer user_data)
+{
+	struct at_chat *chat = user_data;
+	char* error_str;
+	char* line;
+
+	if (chat->suspended) {
+		chat->response_timeout_source = 0;
+		return FALSE;
+	}
+
+	if (chat->response_timeout_counter < COMMAND_RESPONSE_TIMEOUT_SEC) {
+		chat->response_timeout_counter++;
+		return TRUE;
+	}
+	chat->response_timeout_counter = 0;
+
+	if (g_queue_peek_head(chat->command_queue)) {
+		if (chat->debugf)
+			chat->debugf(": Command response timeout\n", chat->debug_data);
+		error_str = "+CME ERROR: 100";
+		line = g_try_new(char, strlen(error_str) + 1);
+		if (line) {
+			strcpy(line, error_str);
+		}
+		at_chat_finish_command(chat, FALSE, line);
+	}
+	else {
+		chat->response_timeout_source = 0;
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void set_response_timeout(struct at_chat *chat) {
+	if (!chat->suspended && !chat->response_timeout_source) {
+		chat->response_timeout_source = g_timeout_add(1000, response_timeout_cb, chat);
+		chat->response_timeout_counter = 0;
+	}
+}
+
+static void delete_response_timeout(struct at_chat *chat) {
+	if (chat->response_timeout_source) {
+		g_source_remove(chat->response_timeout_source);
+		chat->response_timeout_source = 0;
+		chat->response_timeout_counter = 0;
+	}
+}
+
+static void refresh_response_timeout(struct at_chat *chat) {
+	chat->response_timeout_counter = 0;
+	if (g_queue_peek_head(chat->command_queue) && !chat->suspended && !chat->response_timeout_source) {
+		chat->response_timeout_source = g_timeout_add(1000, response_timeout_cb, chat);
+	}
+}
+
 GAtChat *g_at_chat_new(GIOChannel *channel, GAtSyntax *syntax)
 {
 	return g_at_chat_new_common(channel, G_IO_FLAG_NONBLOCK, syntax);
-- 
2.25.1


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

* [PATCH 18/18] ppp: message tracing
  2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
                   ` (15 preceding siblings ...)
  2023-10-17  7:33 ` [PATCH 17/18] gatchat: added command completion by timeout MaxLyubimov
@ 2023-10-17  7:33 ` MaxLyubimov
  2023-10-17  9:37   ` Любимов Максим
  2023-10-17 10:56   ` Lyubimov Maxim
  16 siblings, 2 replies; 20+ messages in thread
From: MaxLyubimov @ 2023-10-17  7:33 UTC (permalink / raw)
  To: ofono; +Cc: MaxLyubimov

Added OFONO_PPP_RECORDING_PATH environment variable handling to enable PPP message tracing
---
 gatchat/gatppp.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
index 259e6d5c..a655b35c 100644
--- a/gatchat/gatppp.c
+++ b/gatchat/gatppp.c
@@ -561,10 +561,16 @@ gboolean g_at_ppp_listen(GAtPPP *ppp, GAtIO *io)
 /* Administrative Open */
 gboolean g_at_ppp_open(GAtPPP *ppp, GAtIO *io)
 {
+	char* recording_path;
+
 	ppp->hdlc = g_at_hdlc_new_from_io(io);
 	if (ppp->hdlc == NULL)
 		return FALSE;
 
+	recording_path = getenv("OFONO_PPP_RECORDING_PATH");
+	if (recording_path)
+		g_at_ppp_set_recording(ppp, recording_path);
+
 	ppp->suspended = FALSE;
 	g_at_hdlc_set_receive(ppp->hdlc, ppp_receive, ppp);
 	g_at_hdlc_set_suspend_function(ppp->hdlc,
-- 
2.25.1


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

* Re: [PATCH 18/18] ppp: message tracing
  2023-10-17  7:33 ` [PATCH 18/18] ppp: message tracing MaxLyubimov
@ 2023-10-17  9:37   ` Любимов Максим
  2023-10-17 10:56   ` Lyubimov Maxim
  1 sibling, 0 replies; 20+ messages in thread
From: Любимов Максим @ 2023-10-17  9:37 UTC (permalink / raw)
  To: ofono

Good afternoon, I apologize, the previous 18 patches need to be
recalled, they were sent by mistake and do not take into account some
fixes, I will resend the corrected patches

Best regards,
Lyubimov Maxim

В Вт, 17/10/2023 в 12:33 +0500, MaxLyubimov пишет:
> Added OFONO_PPP_RECORDING_PATH environment variable handling to
> enable PPP message tracing
> ---
>  gatchat/gatppp.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
> index 259e6d5c..a655b35c 100644
> --- a/gatchat/gatppp.c
> +++ b/gatchat/gatppp.c
> @@ -561,10 +561,16 @@ gboolean g_at_ppp_listen(GAtPPP *ppp, GAtIO
> *io)
>  /* Administrative Open */
>  gboolean g_at_ppp_open(GAtPPP *ppp, GAtIO *io)
>  {
> +	char* recording_path;
> +
>  	ppp->hdlc = g_at_hdlc_new_from_io(io);
>  	if (ppp->hdlc == NULL)
>  		return FALSE;
>  
> +	recording_path = getenv("OFONO_PPP_RECORDING_PATH");
> +	if (recording_path)
> +		g_at_ppp_set_recording(ppp, recording_path);
> +
>  	ppp->suspended = FALSE;
>  	g_at_hdlc_set_receive(ppp->hdlc, ppp_receive, ppp);
>  	g_at_hdlc_set_suspend_function(ppp->hdlc,


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

* Re: [PATCH 18/18] ppp: message tracing
  2023-10-17  7:33 ` [PATCH 18/18] ppp: message tracing MaxLyubimov
  2023-10-17  9:37   ` Любимов Максим
@ 2023-10-17 10:56   ` Lyubimov Maxim
  1 sibling, 0 replies; 20+ messages in thread
From: Lyubimov Maxim @ 2023-10-17 10:56 UTC (permalink / raw)
  To: ofono

Good afternoon, I apologize, the previous 18 patches need to be
recalled, they were sent by mistake and do not take into account some
fixes, I will resend the corrected patches

Best regards,
Lyubimov Maxim

В Вт, 17/10/2023 в 12:33 +0500, MaxLyubimov пишет:
> Added OFONO_PPP_RECORDING_PATH environment variable handling to
> enable PPP message tracing
> ---
>  gatchat/gatppp.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
> index 259e6d5c..a655b35c 100644
> --- a/gatchat/gatppp.c
> +++ b/gatchat/gatppp.c
> @@ -561,10 +561,16 @@ gboolean g_at_ppp_listen(GAtPPP *ppp, GAtIO
> *io)
>  /* Administrative Open */
>  gboolean g_at_ppp_open(GAtPPP *ppp, GAtIO *io)
>  {
> +	char* recording_path;
> +
>  	ppp->hdlc = g_at_hdlc_new_from_io(io);
>  	if (ppp->hdlc == NULL)
>  		return FALSE;
>  
> +	recording_path = getenv("OFONO_PPP_RECORDING_PATH");
> +	if (recording_path)
> +		g_at_ppp_set_recording(ppp, recording_path);
> +
>  	ppp->suspended = FALSE;
>  	g_at_hdlc_set_receive(ppp->hdlc, ppp_receive, ppp);
>  	g_at_hdlc_set_suspend_function(ppp->hdlc,


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

end of thread, other threads:[~2023-10-17 11:46 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-17  7:33 [PATCH 01/18] Skipping AT+CUAD sending for QUECTEL_EC2X vendor MaxLyubimov
2023-10-17  7:33 ` [PATCH 02/18] drivers: adding support for the SIMCom A7605E-H MaxLyubimov
2023-10-17  7:33 ` [PATCH 03/18] plugins: " MaxLyubimov
2023-10-17  7:33 ` [PATCH 04/18] build: " MaxLyubimov
2023-10-17  7:33 ` [PATCH 05/18] drivers: simcom: Add radio settings MaxLyubimov
2023-10-17  7:33 ` [PATCH 06/18] build: Add simcom radio settings rules MaxLyubimov
2023-10-17  7:33 ` [PATCH 07/18] plugins: simcom: Add radio settings MaxLyubimov
2023-10-17  7:33 ` [PATCH 08/18] drivers: quectel: " MaxLyubimov
2023-10-17  7:33 ` [PATCH 09/18] build: Add quectel radio settings rules MaxLyubimov
2023-10-17  7:33 ` [PATCH 10/18] plugins: quectel: Add radio settings MaxLyubimov
2023-10-17  7:33 ` [PATCH 11/18] drivers: gemalto: Add models list MaxLyubimov
2023-10-17  7:33 ` [PATCH 12/18] plugins: gemalto: Include " MaxLyubimov
2023-10-17  7:33 ` [PATCH 13/18] plugins: udevng: Add support gemalto EHS5-E MaxLyubimov
2023-10-17  7:33 ` [PATCH 14/18] gemalto: radio-settings: Add support EHS5-E MaxLyubimov
2023-10-17  7:33 ` [PATCH 15/18] Fix PPP LCP Configure-Reject MaxLyubimov
2023-10-17  7:33 ` [PATCH 16/18] atmodem: added context deactivation event handling MaxLyubimov
2023-10-17  7:33 ` [PATCH 17/18] gatchat: added command completion by timeout MaxLyubimov
2023-10-17  7:33 ` [PATCH 18/18] ppp: message tracing MaxLyubimov
2023-10-17  9:37   ` Любимов Максим
2023-10-17 10:56   ` Lyubimov Maxim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).