To find out which the current technology is on
we have to issue OCTI and OWCTI. OCTI returns
2G information and OWCTI returns 3G information.
OWCTI overrules OCTI.
The OSSYSI unsolicited command tells which
of information should be considered. Unfortunately,
AT_OSSYSI? only returns error.
OSSYSI 0 -> TECH_GPRS (use OCTI for details)
OSSYSI 2 -> TECH_UMTS (use OUWCTI for details)
OCTI 1 -> GSM
OCTI 2 -> GPRS
OCTI 3 -> EDGE
OUWCTI 1 -> UMTS
OUWCTI 2 -> HSDPA
OUWCTI 3 -> HSUPA
OUWCTI 4 -> HSPA
The order of apperance is OCTI OSSYSI [OUWCTI].
This sequence seem to happen before a CREG.
Roaming from 3g to 2g and from 3g to 3g it's okay,
though when roaming from 2g to 3g it comes late
(after CREG).
---
This version just relys on CREG appearing _after_ the OCTI OSSYSI
[OUWCTI] sequence. I've uploaded a log of the current version with
timestamps added.
http://pastebin.com/qUMsh6sk
An intereseting sequence in the log file is from line 376 to 401.
This is roaming from 2g to 3g, but OUWCTI is comming late
so that CREG doesn't pick up the late OUWCTI. On line 396 then
OUWCTI appears (2 seconds after CREG) but the next CREG is 28 seconds
away.
v3: - do not use connman_netreg_status_notify in octi/ossysi/ouwcti
notify functions.
- reset cached octi/ouwcti values when ossysi == 3
v2: - back to original version. rely only on notifications
v1: - fire OCTI, OWCTI in cregs callback.
v0: - initial version
drivers/atmodem/network-registration.c | 111 +++++++++++++++++++++++++++++---
1 files changed, 101 insertions(+), 10 deletions(-)
diff --git a/drivers/atmodem/network-registration.c
b/drivers/atmodem/network-registration.c
index f5ccbb1..b406116 100644
--- a/drivers/atmodem/network-registration.c
+++ b/drivers/atmodem/network-registration.c
@@ -55,9 +55,84 @@ struct netreg_data {
int signal_min; /* min strength reported via CIND */
int signal_max; /* max strength reported via CIND */
int tech;
+ int ossysi; /* option hso 2G/3G info */
+ int octi; /* option hso 2G info details */
+ int ouwcti; /* otpion hso 3G info details */
unsigned int vendor;
};
+static int option_octi_to_tech(struct netreg_data *nd)
+{
+ int tech = -1;
+ switch (nd->octi) {
+ case 1: /* GSM */
+ tech = 0;
+ break;
+ case 2: /* GPRS */
+ tech = 1;
+ break;
+ case 3: /* EDGE */
+ tech = 3;
+ }
+
+ return tech;
+}
+
+static int option_ouwcti_to_tech(struct netreg_data *nd)
+{
+ int tech = -1;
+
+ switch (nd->ouwcti) {
+ case 1: /* UMTS */
+ tech = 2;
+ break;
+ case 2: /* HSDPA */
+ tech = 4;
+ break;
+ case 3: /* HSUPA */
+ tech = 5;
+ break;
+ case 4: /* HSPA */
+ tech = 6;
+ }
+
+ return tech;
+}
+
+static void option_octi_ouwcti_to_tech(struct netreg_data *nd)
+{
+ int tech = -1;
+ int tech_2g, tech_3g;
+
+ switch (nd->ossysi) {
+ case -1:
+ tech_2g = option_octi_to_tech(nd);
+ tech_3g = option_ouwcti_to_tech(nd);
+
+ /* 3G tech takes precedence over 2G tech */
+ if (tech_3g == -1)
+ tech = tech_2g;
+ else
+ tech = tech_3g;
+ break;
+ case 0: /* 2G */
+ tech = option_octi_to_tech(nd);
+ break;
+ case 2: /* 3G */
+ tech = option_ouwcti_to_tech(nd);
+ break;
+ case 3: /* Unknown, reset octi and ouwcti */
+ nd->octi = -1;
+ nd->ouwcti = -1;
+ break;
+ }
+
+ DBG("ossysi %d octi %d ouwcti %d tech %d",
+ nd->ossysi, nd->octi, nd->ouwcti, tech);
+
+ nd->tech = tech;
+}
+
static void extract_mcc_mnc(const char *str, char *mcc, char *mnc)
{
/* Three digit country code */
@@ -535,34 +610,46 @@ static void option_osigq_notify(GAtResult *result, gpointer
user_data)
static void option_ouwcti_notify(GAtResult *result, gpointer user_data)
{
- int mode;
+ struct ofono_netreg *netreg = user_data;
+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
GAtResultIter iter;
+ int mode;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "_OUWCTI:"))
return;
- if (!g_at_result_iter_next_number(&iter, &mode))
+ if (!g_at_result_iter_next_number(&iter, &nd->ouwcti))
return;
- ofono_info("OWCTI mode: %d", mode);
+ /* Handle query responses too */
+ if (!g_at_result_iter_next_number(&iter, &mode) == FALSE)
+ nd->ouwcti = mode;
+
+ option_octi_ouwcti_to_tech(nd);
}
static void option_octi_notify(GAtResult *result, gpointer user_data)
{
- int mode;
+ struct ofono_netreg *netreg = user_data;
+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
GAtResultIter iter;
+ int mode;
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "_OCTI:"))
return;
- if (!g_at_result_iter_next_number(&iter, &mode))
+ if (!g_at_result_iter_next_number(&iter, &nd->octi))
return;
- ofono_info("OCTI mode: %d", mode);
+ /* Handle query responses too */
+ if (!g_at_result_iter_next_number(&iter, &mode) == FALSE)
+ nd->octi = mode;
+
+ option_octi_ouwcti_to_tech(nd);
}
static void ciev_notify(GAtResult *result, gpointer user_data)
@@ -626,7 +713,8 @@ static void cind_cb(gboolean ok, GAtResult *result, gpointer
user_data)
static void option_ossysi_notify(GAtResult *result, gpointer user_data)
{
- int mode;
+ struct ofono_netreg *netreg = user_data;
+ struct netreg_data *nd = ofono_netreg_get_data(netreg);
GAtResultIter iter;
g_at_result_iter_init(&iter, result);
@@ -634,10 +722,10 @@ static void option_ossysi_notify(GAtResult *result, gpointer
user_data)
if (!g_at_result_iter_next(&iter, "_OSSYSI:"))
return;
- if (!g_at_result_iter_next_number(&iter, &mode))
+ if (!g_at_result_iter_next_number(&iter, &nd->ossysi))
return;
- ofono_info("OSSYSI mode: %d", mode);
+ option_octi_ouwcti_to_tech(nd);
}
static void huawei_rssi_notify(GAtResult *result, gpointer user_data)
@@ -926,7 +1014,7 @@ static void at_creg_set_cb(gboolean ok, GAtResult *result, gpointer
user_data)
g_at_chat_send(nd->chat, "AT_OSSYS?", none_prefix,
NULL, NULL, NULL);
- g_at_chat_send(nd->chat, "AT_OWCTI?", none_prefix,
+ g_at_chat_send(nd->chat, "AT_OUWCTI?", none_prefix,
NULL, NULL, NULL);
g_at_chat_send(nd->chat, "AT_OCTI?", none_prefix,
NULL, NULL, NULL);
@@ -1022,6 +1110,9 @@ static int at_netreg_probe(struct ofono_netreg *netreg, unsigned int
vendor,
nd->chat = chat;
nd->vendor = vendor;
nd->tech = -1;
+ nd->ossysi = -1;
+ nd->octi = -1;
+ nd->ouwcti = -1;
ofono_netreg_set_data(netreg, nd);
g_at_chat_send(chat, "AT+CREG=?", creg_prefix,
--
1.6.6.1