---
 src/gprs.c |  176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 162 insertions(+), 14 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index 58166f8..c9d4fb3 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -43,6 +43,9 @@
 #include "common.h"
 #include "storage.h"
 #include "idmap.h"
+#include "util.h"
+#include "simutil.h"
+#include "operator-settings.h"
 
 #define GPRS_FLAG_ATTACHING 0x1
 #define GPRS_FLAG_RECHECK 0x2
@@ -2261,6 +2264,84 @@ static void netreg_watch(struct ofono_atom *atom,
        gprs_netreg_update(gprs);
 }
 
+static gboolean provision_contexts(struct ofono_gprs *gprs,
+                                       const char *mcc,
+                                       const char *mnc,
+                                       const char *spn)
+{
+       gboolean ret = FALSE;
+       GSList *settings, *sp;
+
+       settings = get_operator_settings(mcc, mnc, spn);
+
+       for (sp = settings; sp != NULL; sp = sp->next) {
+               unsigned int id;
+               struct pri_context *context = NULL;
+               struct gprs_access_settings *ap = sp->data;
+
+               /* Sanity check */
+               if (ap == NULL || ap->name == NULL) {
+                       sp = sp->next;
+                       continue;
+               }
+
+               if (gprs->last_context_id)
+                       id = idmap_alloc_next(gprs->pid_map,
+                                               gprs->last_context_id);
+               else
+                       id = idmap_alloc(gprs->pid_map);
+
+               if (id > idmap_get_max(gprs->pid_map))
+                       break;
+
+               context = pri_context_create(gprs, ap->name, ap->type);
+               DBG("Provisioned context %d '%s' %s", id, ap->name,
+                       context ? "created" : "creation failed");
+
+               if (context == NULL)
+                       continue;
+
+               context->id = id;
+
+               if (ap->username != NULL)
+                       strncpy(context->context.username, ap->username,
+                               OFONO_GPRS_MAX_USERNAME_LENGTH);
+
+               if (ap->password != NULL)
+                       strncpy(context->context.password, ap->password,
+                               OFONO_GPRS_MAX_PASSWORD_LENGTH);
+
+               if (ap->apn != NULL)
+                       strncpy(context->context.apn, ap->apn,
+                               OFONO_GPRS_MAX_APN_LENGTH);
+
+               context->context.proto = ap->proto;
+
+               if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS &&
+                       ap->proxy != NULL)
+                       strncpy(context->message_proxy, ap->proxy,
+                               MAX_MESSAGE_PROXY_LENGTH);
+
+               if (ap->type == OFONO_GPRS_CONTEXT_TYPE_MMS &&
+                       ap->mms_server != NULL)
+                       strncpy(context->message_center, ap->mms_server,
+                               MAX_MESSAGE_CENTER_LENGTH);
+
+               if (context_dbus_register(context) == TRUE) {
+                       gprs->last_context_id = id;
+                       gprs->contexts = g_slist_append(gprs->contexts,
+                                                       context);
+                       write_context_settings(gprs, context);
+                       ret = TRUE;
+               }
+       }
+
+       g_slist_foreach(settings, (GFunc) gprs_access_settings_free, NULL);
+       g_slist_free(settings);
+
+       return ret;
+}
+
 static gboolean load_context(struct ofono_gprs *gprs, const char *group)
 {
        char *name = NULL;
@@ -2454,13 +2535,16 @@ remove:
                storage_sync(imsi, SETTINGS_STORE, gprs->settings);
 }
 
-void ofono_gprs_register(struct ofono_gprs *gprs)
+static void ofono_gprs_finish_register(struct ofono_gprs *gprs)
 {
+
        DBusConnection *conn = ofono_dbus_get_connection();
        struct ofono_modem *modem = __ofono_atom_get_modem(gprs->atom);
        const char *path = __ofono_atom_get_path(gprs->atom);
        struct ofono_atom *netreg_atom;
-       struct ofono_atom *sim_atom;
+
+       if (gprs->contexts == NULL) /* Automatic provisioning failed */
+               add_context(gprs, NULL, OFONO_GPRS_CONTEXT_TYPE_INTERNET);
 
        if (!g_dbus_register_interface(conn, path,
                                        OFONO_CONNECTION_MANAGER_INTERFACE,
@@ -2475,18 +2559,6 @@ void ofono_gprs_register(struct ofono_gprs *gprs)
        ofono_modem_add_interface(modem,
                                OFONO_CONNECTION_MANAGER_INTERFACE);
 
-       sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
-
-       if (sim_atom) {
-               struct ofono_sim *sim = __ofono_atom_get_data(sim_atom);
-               const char *imsi = ofono_sim_get_imsi(sim);
-
-               gprs_load_settings(gprs, imsi);
-       }
-
-       if (gprs->contexts == NULL)
-               add_context(gprs, NULL, OFONO_GPRS_CONTEXT_TYPE_INTERNET);
-
        gprs->netreg_watch = __ofono_modem_add_atom_watch(modem,
                                        OFONO_ATOM_TYPE_NETREG,
                                        netreg_watch, gprs, NULL);
@@ -2498,6 +2570,82 @@ void ofono_gprs_register(struct ofono_gprs *gprs)
                                OFONO_ATOM_WATCH_CONDITION_REGISTERED, gprs);
 
        __ofono_atom_register(gprs->atom, gprs_unregister);
+
+}
+
+static void sim_spn_read_cb(int ok, int length, int record,
+                               const unsigned char *data,
+                               int record_length, void *userdata)
+{
+       struct ofono_gprs *gprs = userdata;
+       char *spn = NULL;
+
+       struct ofono_atom *sim_atom;
+       struct ofono_sim *sim;
+       const char *imsi;
+
+       unsigned char mnc_length;
+       char mcc[OFONO_MAX_MCC_LENGTH + 1];
+       char mnc[OFONO_MAX_MNC_LENGTH + 1];
+
+       struct ofono_modem *modem = __ofono_atom_get_modem(gprs->atom);
+
+       sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+       if (sim_atom == NULL)
+               goto finish;
+
+       sim = __ofono_atom_get_data(sim_atom);
+       imsi = ofono_sim_get_imsi(sim);
+       if (imsi == NULL)
+               goto finish;
+
+       mnc_length = ofono_sim_get_mnc_length(sim);
+       if (mnc_length == 0)
+               goto finish;
+
+       strncpy(mcc, imsi, OFONO_MAX_MCC_LENGTH);
+       mcc[OFONO_MAX_MCC_LENGTH] = '\0';
+       strncpy(mnc, imsi + OFONO_MAX_MCC_LENGTH, mnc_length);
+       mnc[mnc_length] = '\0';
+
+       if (ok)
+               spn = sim_string_to_utf8(data + 1, length - 1);
+
+       /* TODO: if SPN is missing/empty, use operator name mapped from
+          mcc/mnc (when implemented in oFono) */
+
+       DBG("MCC %s, MNC %s, SPN %s", mcc, mnc, spn);
+       provision_contexts(gprs, mcc, mnc, spn);
+       g_free(spn);
+
+finish:
+       ofono_gprs_finish_register(gprs);
+
+}
+
+void ofono_gprs_register(struct ofono_gprs *gprs)
+{
+       struct ofono_modem *modem = __ofono_atom_get_modem(gprs->atom);
+       struct ofono_atom *sim_atom;
+       struct ofono_sim *sim = NULL;
+
+       sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+       if (sim_atom != NULL) {
+               const char *imsi = ofono_sim_get_imsi(sim);
+               sim = __ofono_atom_get_data(sim_atom);
+               gprs_load_settings(gprs, imsi);
+       }
+
+       if (gprs->contexts == NULL && sim != NULL) {
+               /* Try reading SPN for automatic context provisioning */
+               ofono_sim_read(sim, SIM_EFSPN_FILEID,
+                               OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+                               sim_spn_read_cb, gprs);
+               return;
+       }
+
+       ofono_gprs_finish_register(gprs);
 }
 
 void ofono_gprs_remove(struct ofono_gprs *gprs)
-- 
1.7.1

_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to