Hi Denis,

Den mån 30 sep. 2019 kl 23:10 skrev Denis Kenzior <[email protected]>:

> Hi Richard,
>
> On 9/30/19 2:04 PM, [email protected] wrote:
> > From: Richard Röjfors <[email protected]>
> >
> > It turns out that both L2xx and L4xx modems are a bit
> > buggy when it comes to send CREG URC's when the tech changes.
> > Try to overcome this by subscribing to both UREG and CREG,
> > and poll the other when any of the URC's are received.
> > Protect from doing simultaneous polls though.
> > ---
> >   drivers/ubloxmodem/network-registration.c | 205 ++++++++++++++++------
> >   1 file changed, 154 insertions(+), 51 deletions(-)
> >
>
> Still no go:
>
> denkenz@localhost ~/ofono-master $ git am --3way ~/merge/\[PATCH\ v2\]\
> ublox\:\ netreg\:\ Also\ subscribe\ to\ UREG\ URC\'s.eml
> Applying: ublox: netreg: Also subscribe to UREG URC's
> Using index info to reconstruct a base tree...
> error: patch failed: drivers/ubloxmodem/network-registration.c:28
> error: drivers/ubloxmodem/network-registration.c: patch does not apply
> error: Did you hand edit your patch?
> It does not apply to blobs recorded in its index.
> Patch failed at 0001 ublox: netreg: Also subscribe to UREG URC's
> hint: Use 'git am --show-current-patch' to see the failed patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
>


This is strange.
I use gmail smtps, but to check if they tamper with the emails,
I cloned a fresh ofono and ran git am and  pasted my email,
it did work(?).

Line 28 is the first part which looks correct to me.

Not really sure why this does not work, I attached it, hope its okay.

--Richard
From 4668aaf3272750ea38e87b227bff64470c4a1d06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Richard=20R=C3=B6jfors?= <[email protected]>
Date: Fri, 27 Sep 2019 07:22:47 +0200
Subject: [PATCH] ublox: netreg: Also subscribe to UREG URC's

It turns out that both L2xx and L4xx modems are a bit
buggy when it comes to send CREG URC's when the tech changes.
Try to overcome this by subscribing to both UREG and CREG,
and poll the other when any of the URC's are received.
Protect from doing simultaneous polls though.
---
 drivers/ubloxmodem/network-registration.c | 205 ++++++++++++++++------
 1 file changed, 154 insertions(+), 51 deletions(-)

diff --git a/drivers/ubloxmodem/network-registration.c b/drivers/ubloxmodem/network-registration.c
index 69af4644..25f239a6 100644
--- a/drivers/ubloxmodem/network-registration.c
+++ b/drivers/ubloxmodem/network-registration.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
 
 #include <glib.h>
 
@@ -47,11 +48,13 @@
 static const char *none_prefix[] = { NULL };
 static const char *cmer_prefix[] = { "+CMER:", NULL };
 static const char *ureg_prefix[] = { "+UREG:", NULL };
+static const char *creg_prefix[] = { "+CREG:", NULL };
 
 struct netreg_data {
 	struct at_netreg_data at_data;
 
 	const struct ublox_model *model;
+	bool updating_status : 1;
 };
 
 struct tech_query {
@@ -213,13 +216,75 @@ static void ctze_notify(GAtResult *result, gpointer user_data)
 	ofono_netreg_time_notify(netreg, &nd->time);
 }
 
-static void ublox_query_tech_cb(gboolean ok, GAtResult *result,
+static int ublox_ureg_state_to_tech(int state)
+{
+	switch (state) {
+	case 1:
+		return ACCESS_TECHNOLOGY_GSM;
+	case 2:
+		return ACCESS_TECHNOLOGY_GSM_EGPRS;
+	case 3:
+		return ACCESS_TECHNOLOGY_UTRAN;
+	case 4:
+		return ACCESS_TECHNOLOGY_UTRAN_HSDPA;
+	case 5:
+		return ACCESS_TECHNOLOGY_UTRAN_HSUPA;
+	case 6:
+		return ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
+	case 7:
+		return ACCESS_TECHNOLOGY_EUTRAN;
+	case 8:
+		return ACCESS_TECHNOLOGY_GSM;
+	case 9:
+		return ACCESS_TECHNOLOGY_GSM_EGPRS;
+	default:
+		/* Not registered for PS (0) or something unknown (>9)... */
+		return -1;
+	}
+}
+
+static gboolean is_registered(int status)
+{
+	return status == NETWORK_REGISTRATION_STATUS_REGISTERED ||
+		status == NETWORK_REGISTRATION_STATUS_ROAMING;
+}
+
+static void ublox_creg_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct tech_query *tq = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(tq->netreg);
+	int status;
+	int lac;
+	int ci;
+	int tech;
+
+	nd->updating_status = false;
+
+	if (!ok)
+		return;
+
+	if (at_util_parse_reg(result, "+CREG:", NULL, &status,
+				&lac, &ci, &tech, OFONO_VENDOR_GENERIC) == FALSE)
+		return;
+
+	/* The query provided a tech, use that */
+	if (is_registered(status) && tq->tech != -1)
+		tech = tq->tech;
+
+	ofono_netreg_status_notify(tq->netreg, status, lac, ci, tech);
+}
+
+static void ublox_ureg_cb(gboolean ok, GAtResult *result,
 							gpointer user_data)
 {
 	struct tech_query *tq = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(tq->netreg);
 	GAtResultIter iter;
 	gint enabled, state;
-	int tech = -1;
+	int tech = tq->tech;
+
+	nd->updating_status = false;
 
 	if (!ok)
 		goto error;
@@ -235,60 +300,67 @@ static void ublox_query_tech_cb(gboolean ok, GAtResult *result,
 	if (!g_at_result_iter_next_number(&iter, &state))
 		return;
 
-	switch (state) {
-	case 0:
-		/* Not registered for PS, then we have to trust CREG... */
+	tech = ublox_ureg_state_to_tech(state);
+	if (tech < 0)
+		/* No valid UREG status, we have to trust CREG... */
 		tech = tq->tech;
-		break;
-	case 1:
-		tech = ACCESS_TECHNOLOGY_GSM;
-		break;
-	case 2:
-		tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
-		break;
-	case 3:
-		tech = ACCESS_TECHNOLOGY_UTRAN;
-		break;
-	case 4:
-		tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA;
-		break;
-	case 5:
-		tech = ACCESS_TECHNOLOGY_UTRAN_HSUPA;
-		break;
-	case 6:
-		tech = ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA;
-		break;
-	case 7:
-		tech = ACCESS_TECHNOLOGY_EUTRAN;
-		break;
-	case 8:
-		tech = ACCESS_TECHNOLOGY_GSM;
-		break;
-	case 9:
-		tech = ACCESS_TECHNOLOGY_GSM_EGPRS;
-		break;
-	default:
-		/* Not registered for PS or something unknown, trust CREG... */
-		tech = tq->tech;
-	}
 
 error:
 	ofono_netreg_status_notify(tq->netreg,
 			tq->status, tq->lac, tq->ci, tech);
 }
 
+static void ureg_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct tech_query *tq;
+	GAtResultIter iter;
+	int state;
+
+	if (nd->updating_status)
+		return;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+UREG:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &state))
+		return;
+
+	tq = g_new0(struct tech_query, 1);
+
+	tq->tech = ublox_ureg_state_to_tech(state);
+	tq->netreg = netreg;
+
+	if (g_at_chat_send(nd->at_data.chat, "AT+CREG?", creg_prefix,
+			ublox_creg_cb, tq, g_free) > 0) {
+		nd->updating_status = true;
+		return;
+	}
+
+	g_free(tq);
+}
+
 static void creg_notify(GAtResult *result, gpointer user_data)
 {
 	struct ofono_netreg *netreg = user_data;
-	int status, lac, ci, tech;
 	struct netreg_data *nd = ofono_netreg_get_data(netreg);
 	struct tech_query *tq;
+	int status;
+	int lac;
+	int ci;
+	int tech;
+
+	if (nd->updating_status)
+		return;
 
 	if (at_util_parse_reg_unsolicited(result, "+CREG:", &status,
 			&lac, &ci, &tech, OFONO_VENDOR_GENERIC) == FALSE)
 		return;
 
-	if (status != 1 && status != 5)
+	if (!is_registered(status))
 		goto notify;
 
 	if (ublox_is_toby_l4(nd->model) || ublox_is_toby_l2(nd->model)) {
@@ -301,13 +373,15 @@ static void creg_notify(GAtResult *result, gpointer user_data)
 		tq->netreg = netreg;
 
 		if (g_at_chat_send(nd->at_data.chat, "AT+UREG?", ureg_prefix,
-				ublox_query_tech_cb, tq, g_free) > 0)
+				ublox_ureg_cb, tq, g_free) > 0) {
+			nd->updating_status = true;
 			return;
+		}
 
 		g_free(tq);
 	}
 
-	if ((status == 1 || status == 5) && tech == -1)
+	if (tech == -1)
 		tech = nd->at_data.tech;
 
 notify:
@@ -322,24 +396,56 @@ static void at_cmer_not_supported(struct ofono_netreg *netreg)
 	ofono_netreg_remove(netreg);
 }
 
+static void ublox_finish_registration(struct ofono_netreg *netreg)
+{
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
+
+	if (ublox_is_toby_l4(nd->model) || ublox_is_toby_l2(nd->model))
+		g_at_chat_register(nd->at_data.chat, "+UREG:",
+					ureg_notify, FALSE, netreg, NULL);
+
+	g_at_chat_register(nd->at_data.chat, "+CIEV:",
+			ciev_notify, FALSE, netreg, NULL);
+
+	g_at_chat_register(nd->at_data.chat, "+CREG:",
+				creg_notify, FALSE, netreg, NULL);
+
+	ofono_netreg_register(netreg);
+}
+
+static void ublox_ureg_set_cb(gboolean ok,
+				GAtResult *result, gpointer user_data)
+{
+	struct ofono_netreg *netreg = user_data;
+
+	if (!ok) {
+		ofono_error("Unable to initialize Network Registration");
+		ofono_netreg_remove(netreg);
+		return;
+	}
+
+	ublox_finish_registration(netreg);
+}
+
 static void ublox_cmer_set_cb(gboolean ok,
 				GAtResult *result, gpointer user_data)
 {
 	struct ofono_netreg *netreg = user_data;
-	struct at_netreg_data *nd = ofono_netreg_get_data(netreg);
+	struct netreg_data *nd = ofono_netreg_get_data(netreg);
 
 	if (!ok) {
 		at_cmer_not_supported(netreg);
 		return;
 	}
 
-	g_at_chat_register(nd->chat, "+CIEV:",
-			ciev_notify, FALSE, netreg, NULL);
+	if (ublox_is_toby_l4(nd->model) || ublox_is_toby_l2(nd->model)) {
+		g_at_chat_send(nd->at_data.chat, "AT+UREG=1", none_prefix,
+			ublox_ureg_set_cb, netreg, NULL);
 
-	g_at_chat_register(nd->chat, "+CREG:",
-				creg_notify, FALSE, netreg, NULL);
+		return;
+	}
 
-	ofono_netreg_register(netreg);
+	ublox_finish_registration(netreg);
 }
 
 static void ublox_creg_set_cb(gboolean ok,
@@ -354,12 +460,9 @@ static void ublox_creg_set_cb(gboolean ok,
 		return;
 	}
 
-	if (ublox_is_toby_l4(nd->model)) {
+	if (ublox_is_toby_l4(nd->model))
 		/* FIXME */
 		ofono_error("TOBY L4 requires polling of ECSQ");
-		ofono_error("TOBY L4 wants UREG notifications for"
-				" tech updates");
-	}
 
 	/* Register for network time update reports */
 	if (ublox_is_toby_l2(nd->model)) {
-- 
2.20.1

_______________________________________________
ofono mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to