In some cases the field MNC length in EFad is not present. MNC can
have either 2 or 3 digits depending on the MCC: we will try with
those 2 lengths when searching in the database for this corner case
(this situation can happen for SIMs (non-USIM), as MNC lenght field
is not mandatory for them - see 3gpp TS 51.011)
---
 include/sim.h |  1 +
 src/gprs.c    | 26 +++++++++++++++++++++----
 src/sim.c     | 61 ++++++++++++++++++++++++++++++++++++++++-------------------
 3 files changed, 65 insertions(+), 23 deletions(-)

diff --git a/include/sim.h b/include/sim.h
index ed850f9..f63324a 100644
--- a/include/sim.h
+++ b/include/sim.h
@@ -191,6 +191,7 @@ void *ofono_sim_get_data(struct ofono_sim *sim);
 const char *ofono_sim_get_imsi(struct ofono_sim *sim);
 const char *ofono_sim_get_mcc(struct ofono_sim *sim);
 const char *ofono_sim_get_mnc(struct ofono_sim *sim);
+unsigned ofono_sim_get_mnc_length(struct ofono_sim *sim);
 const char *ofono_sim_get_spn(struct ofono_sim *sim);
 enum ofono_sim_phase ofono_sim_get_phase(struct ofono_sim *sim);
 
diff --git a/src/gprs.c b/src/gprs.c
index e379f7b..0218696 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -2967,7 +2967,7 @@ static void provision_context(const struct 
ofono_gprs_provision_data *ap,
        gprs->contexts = g_slist_append(gprs->contexts, context);
 }
 
-static void provision_contexts(struct ofono_gprs *gprs, const char *mcc,
+static int provision_contexts(struct ofono_gprs *gprs, const char *mcc,
                                const char *mnc, const char *spn)
 {
        struct ofono_gprs_provision_data *settings;
@@ -2977,13 +2977,15 @@ static void provision_contexts(struct ofono_gprs *gprs, 
const char *mcc,
        if (__ofono_gprs_provision_get_settings(mcc, mnc, spn,
                                                &settings, &count) == FALSE) {
                ofono_warn("Provisioning failed");
-               return;
+               return -EINVAL;
        }
 
        for (i = 0; i < count; i++)
                provision_context(&settings[i], gprs);
 
        __ofono_gprs_provision_free_settings(settings, count);
+
+       return 0;
 }
 
 static void ofono_gprs_finish_register(struct ofono_gprs *gprs)
@@ -3021,9 +3023,25 @@ static void spn_read_cb(const char *spn, const char *dc, 
void *data)
        struct ofono_gprs *gprs = data;
        struct ofono_modem *modem = __ofono_atom_get_modem(gprs->atom);
        struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
+       const char *mnc = ofono_sim_get_mnc(sim);
+       const char *mcc = ofono_sim_get_mcc(sim);
+
+       if (ofono_sim_get_mnc_length(sim) == 0 && mnc != NULL) {
+               /* MNC length not found in EFad: we try with length 3 and 2 */
+               char aux_mnc[OFONO_MAX_MNC_LENGTH + 1];
 
-       provision_contexts(gprs, ofono_sim_get_mcc(sim),
-                                       ofono_sim_get_mnc(sim), spn);
+               strncpy(aux_mnc, mnc, OFONO_MAX_MNC_LENGTH);
+               aux_mnc[OFONO_MAX_MNC_LENGTH] = '\0';
+
+               if (provision_contexts(gprs, mcc, aux_mnc, spn) != 0) {
+                       ofono_info("MNC length is not 3: trying length 2");
+                       aux_mnc[OFONO_MAX_MNC_LENGTH - 1] = '\0';
+                       provision_contexts(gprs, mcc, aux_mnc, spn);
+               }
+
+       } else {
+               provision_contexts(gprs, mcc, mnc, spn);
+       }
 
        ofono_sim_remove_spn_watch(sim, &gprs->spn_watch);
 
diff --git a/src/sim.c b/src/sim.c
index edae5eb..3d31386 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -1427,6 +1427,8 @@ static void sim_imsi_obtained(struct ofono_sim *sim, 
const char *imsi)
 {
        DBusConnection *conn = ofono_dbus_get_connection();
        const char *path = __ofono_atom_get_path(sim->atom);
+       unsigned char aux_mnc_length;
+       const char *str;
 
        sim->imsi = g_strdup(imsi);
 
@@ -1435,27 +1437,36 @@ static void sim_imsi_obtained(struct ofono_sim *sim, 
const char *imsi)
                                                "SubscriberIdentity",
                                                DBUS_TYPE_STRING, &sim->imsi);
 
-       if (sim->mnc_length) {
-               const char *str;
+       /*
+        * sim->mnc_length = 0 means that EFad did not contain the MNC length
+        * field. So we will copy 3 digits from the IMSI in the MNC. MNC can
+        * have either 2 or 3 digits depending on the MCC: we will try with
+        * those 2 lengths when searching in the database for this corner case
+        * (this situation can happen for SIMs (non-USIM), as MNC lenght field
+        * is not mandatory for them - see TS 51.011)
+        */
+       if (sim->mnc_length)
+               aux_mnc_length = sim->mnc_length;
+       else
+               aux_mnc_length = OFONO_MAX_MNC_LENGTH;
 
-               strncpy(sim->mcc, sim->imsi, OFONO_MAX_MCC_LENGTH);
-               sim->mcc[OFONO_MAX_MCC_LENGTH] = '\0';
-               strncpy(sim->mnc, sim->imsi + OFONO_MAX_MCC_LENGTH,
-                       sim->mnc_length);
-               sim->mnc[sim->mnc_length] = '\0';
+       strncpy(sim->mcc, sim->imsi, OFONO_MAX_MCC_LENGTH);
+       sim->mcc[OFONO_MAX_MCC_LENGTH] = '\0';
+       strncpy(sim->mnc, sim->imsi + OFONO_MAX_MCC_LENGTH,
+               aux_mnc_length);
+       sim->mnc[aux_mnc_length] = '\0';
 
-               str = sim->mcc;
-               ofono_dbus_signal_property_changed(conn, path,
-                                               OFONO_SIM_MANAGER_INTERFACE,
-                                               "MobileCountryCode",
-                                               DBUS_TYPE_STRING, &str);
+       str = sim->mcc;
+       ofono_dbus_signal_property_changed(conn, path,
+                                       OFONO_SIM_MANAGER_INTERFACE,
+                                       "MobileCountryCode",
+                                       DBUS_TYPE_STRING, &str);
 
-               str = sim->mnc;
-               ofono_dbus_signal_property_changed(conn, path,
-                                               OFONO_SIM_MANAGER_INTERFACE,
-                                               "MobileNetworkCode",
-                                               DBUS_TYPE_STRING, &str);
-       }
+       str = sim->mnc;
+       ofono_dbus_signal_property_changed(conn, path,
+                                       OFONO_SIM_MANAGER_INTERFACE,
+                                       "MobileNetworkCode",
+                                       DBUS_TYPE_STRING, &str);
 
        sim_set_ready(sim);
 
@@ -1772,8 +1783,12 @@ static void sim_ad_read_cb(int ok, int length, int 
record,
        if (!ok)
                return;
 
+       if (length < 3) {
+               ofono_error("EFad should contain at least three bytes");
+               return;
+       }
        if (length < 4) {
-               ofono_error("EFad should contain at least four bytes");
+               ofono_info("EFad does not contain MNC length");
                return;
        }
 
@@ -2234,6 +2249,14 @@ const char *ofono_sim_get_mnc(struct ofono_sim *sim)
        return sim->mnc;
 }
 
+unsigned ofono_sim_get_mnc_length(struct ofono_sim *sim)
+{
+       if (sim == NULL)
+               return 0;
+
+       return sim->mnc_length;
+}
+
 const char *ofono_sim_get_spn(struct ofono_sim *sim)
 {
        if (sim == NULL)
-- 
1.8.1.2

_______________________________________________
ofono mailing list
[email protected]
https://lists.ofono.org/mailman/listinfo/ofono

Reply via email to