--- 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