All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: [PATCH] atmodem: CEREG support for LTE network status reporting in AT modem
@ 2011-02-22 13:46 Vijay.Nayani
  2011-02-22 14:09 ` Tomasz Gregorek
  0 siblings, 1 reply; 15+ messages in thread
From: Vijay.Nayani @ 2011-02-22 13:46 UTC (permalink / raw)
  To: ofono

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

 

> Subject: [PATCH] atmodem: CEREG support for LTE network 
> status reporting in AT modem
> 
> [PATCH] atmodem: CEREG support for LTE network status 
> reporting in AT modem Tomasz Gregorek tomasz.gregorek at 
> gmail.com Thu Feb 17 19:52:45 PST 2011
> 
>     * Previous message: [PATCH 2/5] bluetooth: add a 
> bluetoothd connect watch
>     * Next message: Problem with SIM lock states not showing 
> correctly in Ofono API.
>     * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
> 
> From: Tomasz Gregorek <tomasz.gregorek@stericsson.com>
> 
> This is a proposal for CEREG support based on the AT modem.
> Support in driver should work, though I have an issue with the core.
> 
> The core has one gprs status currently. In case of having 
> second status for LTE, there is need of having two satuses, 
> one for each, 3G and LTE, or to combine those two into one.
> 
> I took second approach as it leaves current oFono API, though 
> it is not perfect.

I have been working on solution that comprises of separate eps atom and
corresponding driver. Code has been tested against modified phonesim for
eps.Will provide an RFC patch soon once I bring it to certain logical
end.

Regards,
Vijay

^ permalink raw reply	[flat|nested] 15+ messages in thread
* [PATCH] atmodem: CEREG support for LTE network status reporting in AT modem
@ 2011-02-18  3:52 Tomasz Gregorek
  0 siblings, 0 replies; 15+ messages in thread
From: Tomasz Gregorek @ 2011-02-18  3:52 UTC (permalink / raw)
  To: ofono

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

From: Tomasz Gregorek <tomasz.gregorek@stericsson.com>

This is a proposal for CEREG support based on the AT modem.
Support in driver should work, though I have an issue with
the core.

The core has one gprs status currently. In case of having
second status for LTE, there is need of having two satuses,
one for each, 3G and LTE, or to combine those two into one.

I took second approach as it leaves current oFono API, though
it is not perfect.
---
 drivers/atmodem/gprs.c  |  151 +++++++++++++++++++++++++++++++++++++++++++----
 drivers/isimodem/gprs.c |    6 +-
 include/gprs.h          |   11 +++-
 src/gprs.c              |   43 ++++++++++++-
 4 files changed, 189 insertions(+), 22 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index 6e01994..f6585de 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -43,12 +43,15 @@
 #include "vendor.h"
 
 static const char *cgreg_prefix[] = { "+CGREG:", NULL };
+static const char *cereg_prefix[] = { "+CEREG:", NULL };
 static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
 static const char *none_prefix[] = { NULL };
 
 struct gprs_data {
 	GAtChat *chat;
 	unsigned int vendor;
+	ofono_bool_t have_cgreg;
+	ofono_bool_t have_cereg;
 };
 
 static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -80,6 +83,31 @@ static void at_gprs_set_attached(struct ofono_gprs *gprs, int attached,
 	CALLBACK_WITH_FAILURE(cb, data);
 }
 
+static void at_cereg_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_gprs_status_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	int status;
+	struct gprs_data *gd = cbd->user;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, GPRS_PS_STATUS_SOURCE_LTE, cbd->data);
+		return;
+	}
+
+	if (at_util_parse_reg(result, "+CEREG:", NULL, &status,
+				NULL, NULL, NULL, gd->vendor) == FALSE) {
+		CALLBACK_WITH_FAILURE(cb, -1,
+				GPRS_PS_STATUS_SOURCE_LTE, cbd->data);
+		return;
+	}
+
+	cb(&error, status, GPRS_PS_STATUS_SOURCE_LTE, cbd->data);
+}
+
 static void at_cgreg_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
@@ -91,17 +119,28 @@ static void at_cgreg_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	decode_at_error(&error, g_at_result_final_response(result));
 
 	if (!ok) {
-		cb(&error, -1, cbd->data);
+		cb(&error, -1, GPRS_PS_STATUS_SOURCE_LTE, cbd->data);
 		return;
 	}
 
 	if (at_util_parse_reg(result, "+CGREG:", NULL, &status,
 				NULL, NULL, NULL, gd->vendor) == FALSE) {
-		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		CALLBACK_WITH_FAILURE(cb, -1,
+				GPRS_PS_STATUS_SOURCE_3G, cbd->data);
+		g_free(cbd);
 		return;
 	}
 
-	cb(&error, status, cbd->data);
+	cb(&error, status, GPRS_PS_STATUS_SOURCE_3G, cbd->data);
+
+	if (gd->have_cereg) {
+		if (g_at_chat_send(gd->chat, "AT+CEREG?", cereg_prefix,
+				at_cereg_cb, cbd, g_free) == FALSE) {
+			CALLBACK_WITH_FAILURE(cb, -1,
+					GPRS_PS_STATUS_SOURCE_LTE, cbd->data);
+			g_free(cbd);
+		}
+	}
 }
 
 static void at_gprs_registration_status(struct ofono_gprs *gprs,
@@ -132,9 +171,17 @@ static void at_gprs_registration_status(struct ofono_gprs *gprs,
 		break;
 	}
 
-	if (g_at_chat_send(gd->chat, "AT+CGREG?", cgreg_prefix,
-				at_cgreg_cb, cbd, g_free) > 0)
+	if (gd->have_cgreg) {
+		if (g_at_chat_send(gd->chat, "AT+CGREG?", cgreg_prefix,
+			at_cgreg_cb, cbd, NULL) > 0)
 		return;
+	}
+	else {
+		if (g_at_chat_send(gd->chat, "AT+CEREG?", cereg_prefix,
+			at_cereg_cb, cbd, g_free) > 0)
+		return;
+	}
+
 
 	g_free(cbd);
 
@@ -151,7 +198,20 @@ static void cgreg_notify(GAtResult *result, gpointer user_data)
 				NULL, NULL, NULL, gd->vendor) == FALSE)
 		return;
 
-	ofono_gprs_status_notify(gprs, status);
+	ofono_gprs_status_notify(gprs, status, GPRS_PS_STATUS_SOURCE_3G);
+}
+
+static void cereg_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_gprs *gprs = user_data;
+	int status;
+	struct gprs_data *gd = ofono_gprs_get_data(gprs);
+
+	if (at_util_parse_reg_unsolicited(result, "+CEREG:", &status,
+				NULL, NULL, NULL, gd->vendor) == FALSE)
+		return;
+
+	ofono_gprs_status_notify(gprs, status, GPRS_PS_STATUS_SOURCE_LTE);
 }
 
 static void cgev_notify(GAtResult *result, gpointer user_data)
@@ -226,8 +286,15 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
 	struct gprs_data *gd = ofono_gprs_get_data(gprs);
 
 	g_at_chat_register(gd->chat, "+CGEV:", cgev_notify, FALSE, gprs, NULL);
-	g_at_chat_register(gd->chat, "+CGREG:", cgreg_notify,
+
+	if (gd->have_cgreg)
+		g_at_chat_register(gd->chat, "+CGREG:", cgreg_notify,
 						FALSE, gprs, NULL);
+
+	if (gd->have_cereg)
+		g_at_chat_register(gd->chat, "+CEREG:", cereg_notify,
+						FALSE, gprs, NULL);
+
 	g_at_chat_register(gd->chat, "+CPSB:", cpsb_notify, FALSE, gprs, NULL);
 
 	g_at_chat_send(gd->chat, "AT+CPSB=1", none_prefix, NULL, NULL, NULL);
@@ -257,15 +324,15 @@ static void at_cgreg_test_cb(gboolean ok, GAtResult *result,
 	const char *cmd;
 
 	if (!ok)
-		goto error;
+		goto cgreg_notsupported;
 
 	g_at_result_iter_init(&iter, result);
 
 	if (!g_at_result_iter_next(&iter, "+CGREG:"))
-		goto error;
+		goto cgreg_notsupported;
 
 	if (!g_at_result_iter_open_list(&iter))
-		goto error;
+		goto cgreg_notsupported;
 
 	while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) {
 		if (1 >= range[0] && 1 <= range[1])
@@ -281,9 +348,16 @@ static void at_cgreg_test_cb(gboolean ok, GAtResult *result,
 	else if (cgreg1)
 		cmd = "AT+CGREG=1";
 	else
-		goto error;
+		goto cgreg_notsupported;
+
+	gd->have_cgreg = TRUE;
 
 	g_at_chat_send(gd->chat, cmd, none_prefix, NULL, NULL, NULL);
+
+cgreg_notsupported:
+	if (gd->have_cgreg == FALSE && gd->have_cereg == FALSE)
+		goto error;
+
 	g_at_chat_send(gd->chat, "AT+CGAUTO=0", none_prefix, NULL, NULL, NULL);
 
 	switch (gd->vendor) {
@@ -354,6 +428,10 @@ static void at_cgdcont_test_cb(gboolean ok, GAtResult *result,
 	if (found == FALSE)
 		goto error;
 
+	/* In case of LTE modem reserve lowest cid for Initial PDN */
+	if (gd->have_cereg)
+		min++;
+
 	ofono_gprs_set_cid_range(gprs, min, max);
 
 	g_at_chat_send(gd->chat, "AT+CGREG=?", cgreg_prefix,
@@ -366,6 +444,53 @@ error:
 	ofono_gprs_remove(gprs);
 }
 
+static void at_cereg_test_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ofono_gprs *gprs = user_data;
+	struct gprs_data *gd = ofono_gprs_get_data(gprs);
+	gint range[2];
+	GAtResultIter iter;
+	int cereg1 = 0;
+	int cereg2 = 0;
+	const char *cmd;
+
+	if (!ok)
+		goto test_cgdcont;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CEREG:"))
+		goto test_cgdcont;
+
+	if (!g_at_result_iter_open_list(&iter))
+		goto test_cgdcont;
+
+	while (g_at_result_iter_next_range(&iter, &range[0], &range[1])) {
+		if (1 >= range[0] && 1 <= range[1])
+			cereg1 = 1;
+		if (2 >= range[0] && 2 <= range[1])
+			cereg2 = 1;
+	}
+
+	g_at_result_iter_close_list(&iter);
+
+	if (cereg2)
+		cmd = "AT+CEREG=2";
+	else if (cereg1)
+		cmd = "AT+CEREG=1";
+	else
+		goto test_cgdcont;
+
+	gd->have_cereg = TRUE;
+
+	g_at_chat_send(gd->chat, cmd, none_prefix, NULL, NULL, NULL);
+
+test_cgdcont:
+	g_at_chat_send(gd->chat, "AT+CGDCONT=?", cgdcont_prefix,
+			at_cgdcont_test_cb, gprs, NULL);
+}
+
 static int at_gprs_probe(struct ofono_gprs *gprs,
 					unsigned int vendor, void *data)
 {
@@ -381,8 +506,8 @@ static int at_gprs_probe(struct ofono_gprs *gprs,
 
 	ofono_gprs_set_data(gprs, gd);
 
-	g_at_chat_send(gd->chat, "AT+CGDCONT=?", cgdcont_prefix,
-			at_cgdcont_test_cb, gprs, NULL);
+	g_at_chat_send(gd->chat, "AT+CEREG=?", cgdcont_prefix,
+			at_cereg_test_cb, gprs, NULL);
 
 	return 0;
 }
diff --git a/drivers/isimodem/gprs.c b/drivers/isimodem/gprs.c
index ea90704..7d54df3 100644
--- a/drivers/isimodem/gprs.c
+++ b/drivers/isimodem/gprs.c
@@ -459,11 +459,11 @@ static void status_resp_cb(const GIsiMessage *msg, void *opaque)
 
 	suspend_notify(gprs, data[10], data[11]);
 
-	CALLBACK_WITH_SUCCESS(cb, status, cbd->data);
+	CALLBACK_WITH_SUCCESS(cb, status, GPRS_PS_STATUS_SOURCE_3G, cbd->data);
 	return;
 
 error:
-	CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+	CALLBACK_WITH_FAILURE(cb, -1, GPRS_PS_STATUS_SOURCE_3G, cbd->data);
 }
 
 static void isi_gprs_attached_status(struct ofono_gprs *gprs,
@@ -485,7 +485,7 @@ static void isi_gprs_attached_status(struct ofono_gprs *gprs,
 		return;
 
 error:
-	CALLBACK_WITH_FAILURE(cb, -1, data);
+	CALLBACK_WITH_FAILURE(cb, -1, GPRS_PS_STATUS_SOURCE_3G, data);
 	g_free(cbd);
 }
 
diff --git a/include/gprs.h b/include/gprs.h
index 157a6f9..305e12f 100644
--- a/include/gprs.h
+++ b/include/gprs.h
@@ -31,8 +31,14 @@ extern "C" {
 struct ofono_gprs;
 struct ofono_gprs_context;
 
+enum gprs_ps_status_source {
+	GPRS_PS_STATUS_SOURCE_3G,
+	GPRS_PS_STATUS_SOURCE_LTE,
+};
+
 typedef void (*ofono_gprs_status_cb_t)(const struct ofono_error *error,
-						int status, void *data);
+			int status, enum gprs_ps_status_source status_src,
+			void *data);
 
 typedef void (*ofono_gprs_cb_t)(const struct ofono_error *error, void *data);
 
@@ -55,7 +61,8 @@ enum gprs_suspend_cause {
 	GPRS_SUSPENDED_UNKNOWN_CAUSE,
 };
 
-void ofono_gprs_status_notify(struct ofono_gprs *gprs, int status);
+void ofono_gprs_status_notify(struct ofono_gprs *gprs,
+		int status, enum gprs_ps_status_source status_src);
 void ofono_gprs_detached_notify(struct ofono_gprs *gprs);
 void ofono_gprs_suspend_notify(struct ofono_gprs *gprs, int cause);
 void ofono_gprs_resume_notify(struct ofono_gprs *gprs);
diff --git a/src/gprs.c b/src/gprs.c
index 33711dc..faccb91 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -80,6 +80,8 @@ struct ofono_gprs {
 	ofono_bool_t powered;
 	ofono_bool_t suspended;
 	int status;
+	int status3G;
+	int statusLTE;
 	int flags;
 	int bearer;
 	guint suspend_timeout;
@@ -138,6 +140,17 @@ struct pri_context {
 	struct ofono_gprs *gprs;
 };
 
+static const char status_priority[]={
+               0, /* NETWORK_REGISTRATION_STATUS_NOT_REGISTERED */
+               4, /* NETWORK_REGISTRATION_STATUS_REGISTERED */
+               3, /* NETWORK_REGISTRATION_STATUS_SEARCHING */
+               2, /* NETWORK_REGISTRATION_STATUS_DENIED */
+               1, /* NETWORK_REGISTRATION_STATUS_UNKNOWN */
+               5  /* NETWORK_REGISTRATION_STATUS_ROAMING */
+               /*0,  AT+CxREG? error */
+};
+
+
 static void gprs_netreg_update(struct ofono_gprs *gprs);
 static void gprs_deactivate_next(struct ofono_gprs *gprs);
 
@@ -1370,7 +1383,8 @@ static void gprs_attached_update(struct ofono_gprs *gprs)
 }
 
 static void registration_status_cb(const struct ofono_error *error,
-					int status, void *data)
+			int status, enum gprs_ps_status_source status_src,
+			void *data)
 {
 	struct ofono_gprs *gprs = data;
 
@@ -1378,7 +1392,7 @@ static void registration_status_cb(const struct ofono_error *error,
 		error->type, status);
 
 	if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
-		ofono_gprs_status_notify(gprs, status);
+		ofono_gprs_status_notify(gprs, status, status_src);
 
 	if (gprs->flags & GPRS_FLAG_RECHECK) {
 		gprs->flags &= ~GPRS_FLAG_RECHECK;
@@ -1985,11 +1999,32 @@ void ofono_gprs_detached_notify(struct ofono_gprs *gprs)
 	 */
 }
 
-void ofono_gprs_status_notify(struct ofono_gprs *gprs, int status)
+void ofono_gprs_status_notify(struct ofono_gprs *gprs, int status,
+		enum gprs_ps_status_source status_src)
 {
 	DBG("%s status %d", __ofono_atom_get_path(gprs->atom), status);
 
-	gprs->status = status;
+	/*
+	 * Combine statuses from 3G and LTE network into one.
+	 * Use prioryty table as a base.
+	 */
+	if (status != -1) {
+		switch(status_src)
+		{
+			case GPRS_PS_STATUS_SOURCE_3G:
+				gprs->status3G = status;
+				break;
+			case GPRS_PS_STATUS_SOURCE_LTE:
+				gprs->statusLTE = status;
+				break;
+		}
+
+		gprs->status = ((status_priority[gprs->status3G] >=
+				status_priority[gprs->statusLTE]) ?
+					gprs->status3G : gprs->statusLTE);
+	}
+	else
+		gprs->status = -1;
 
 	if (status != NETWORK_REGISTRATION_STATUS_REGISTERED &&
 			status != NETWORK_REGISTRATION_STATUS_ROAMING) {
-- 
1.7.4


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

end of thread, other threads:[~2011-02-24 16:12 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-22 13:46 [PATCH] atmodem: CEREG support for LTE network status reporting in AT modem Vijay.Nayani
2011-02-22 14:09 ` Tomasz Gregorek
2011-02-22 14:59   ` Vijay.Nayani
2011-02-22 15:20     ` Tomasz Gregorek
2011-02-22 16:08     ` Soum, RedouaneX
2011-02-22 16:35       ` Denis Kenzior
2011-02-23 10:13         ` Tomasz Gregorek
2011-02-23 15:58           ` Denis Kenzior
2011-02-23 16:36             ` Soum, RedouaneX
2011-02-23 16:49               ` Denis Kenzior
2011-02-23 18:24                 ` Joly, Frederic
2011-02-23 18:52                   ` Denis Kenzior
2011-02-24 10:34                     ` Arun Ravindran
2011-02-24 16:12                       ` Denis Kenzior
  -- strict thread matches above, loose matches on Subject: below --
2011-02-18  3:52 Tomasz Gregorek

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.