--- Makefile.am | 2 +- src/gprs-provision.c | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 1 deletions(-) create mode 100644 src/gprs-provision.c diff --git a/Makefile.am b/Makefile.am index 22ec95d..e792851 100644 --- a/Makefile.am +++ b/Makefile.am @@ -354,7 +354,7 @@ src_ofonod_SOURCES = $(gdbus_sources) $(builtin_sources) src/ofono.ver \ src/nettime.c src/stkagent.c src/stkagent.h \ src/simfs.c src/simfs.h src/audio-settings.c \ src/smsagent.c src/smsagent.h src/ctm.c \ - src/cdma-voicecall.c + src/cdma-voicecall.c src/gprs-provision.c src_ofonod_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS@ -ldl diff --git a/src/gprs-provision.c b/src/gprs-provision.c new file mode 100644 index 0000000..1690bc7 --- /dev/null +++ b/src/gprs-provision.c @@ -0,0 +1,236 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "ofono.h" +#include "gprs-provision.h" + +static GSList *g_drivers = NULL; +static GSList *provision_requests = NULL; + +struct gprs_provision_request { + GSList *drivers; /* Provisioning drivers to be called */ + struct ofono_modem *modem; + ofono_gprs_provision_cb_t cb; + void *user_data; +}; + +static void settings_cb(GSList *settings, void *user_data); + +static struct ofono_gprs_provision_context *gprs_provision_context_create( + struct ofono_modem *modem, + struct ofono_gprs_provision_driver *driver) +{ + struct ofono_gprs_provision_context *context; + + if (driver->probe == NULL) + return NULL; + + context = g_try_new0(struct ofono_gprs_provision_context, 1); + + if (context == NULL) + return NULL; + + context->driver = driver; + context->modem = modem; + + if (driver->probe(context) < 0) { + g_free(context); + return NULL; + } + + return context; +} + +static void clean_active_requests(gpointer data, gpointer user_data) +{ + struct gprs_provision_request *req = data; + struct ofono_gprs_provision_context *context = user_data; + + req->drivers = g_slist_remove(req->drivers, context); +} + +static void context_remove(struct ofono_atom *atom) +{ + struct ofono_gprs_provision_context *context = + __ofono_atom_get_data(atom); + + g_slist_foreach(provision_requests, clean_active_requests, context); + + if (context->driver->remove) + context->driver->remove(context); + + g_free(context); +} + +void __ofono_gprs_provision_probe_drivers(struct ofono_modem *modem) +{ + struct ofono_gprs_provision_driver *driver; + struct ofono_gprs_provision_context *context; + GSList *l; + + for (l = g_drivers; l; l = l->next) { + driver = l->data; + + context = gprs_provision_context_create(modem, driver); + if (context == NULL) + continue; + + __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_GPRS_PROVISION, + context_remove, context); + } +} + +void ofono_gprs_provision_data_free(struct ofono_gprs_provision_data *data) +{ + if (data == NULL) + return; + + free(data->name); + free(data->apn); + free(data->username); + free(data->password); + free(data->message_proxy); + free(data->message_center); + g_free(data); +} + +/* + * Calls next driver that has callable get_settings() + * Returns TRUE if a driver was called. + */ +static gboolean call_driver_get_settings(struct gprs_provision_request *req, + ofono_gprs_provision_cb_t cb) +{ + struct ofono_gprs_provision_context *context; + + if (req->drivers == NULL) + return FALSE; + + do { + context = req->drivers->data; + req->drivers = g_slist_delete_link(req->drivers, req->drivers); + + if (context->driver->get_settings != NULL) { + DBG("Calling provisioning plugin '%s'", + context->driver->name); + + provision_requests = g_slist_append(provision_requests, + req); + context->driver->get_settings(context, cb, req); + return TRUE; + } + + } while (req->drivers != NULL); + + return FALSE; +} + +static void settings_cb(GSList *settings, void *user_data) +{ + struct gprs_provision_request *req = user_data; + + provision_requests = g_slist_remove(provision_requests, req); + if (settings == NULL) { + DBG("Provisioning plugin returned no settings"); + + /* No success from this driver, try next */ + if (call_driver_get_settings(req, settings_cb) == TRUE) + return; + } else + DBG("Provisioning plugin returned settings for %d contexts", + g_slist_length(settings)); + + req->cb(settings, req->user_data); + g_slist_free(req->drivers); + g_free(req); +} + +static void prepend_provision_driver(struct ofono_atom *atom, void *data) +{ + struct ofono_gprs_provision_context *context = + __ofono_atom_get_data(atom); + GSList **drivers = data; + + *drivers = g_slist_prepend(*drivers, context); +} + +void __ofono_gprs_provision_get_settings(struct ofono_modem *modem, + ofono_gprs_provision_cb_t cb, + void *user_data) +{ + struct gprs_provision_request *req; + + req = g_try_new0(struct gprs_provision_request, 1); + if (req == NULL) + goto error; + + req->modem = modem; + req->cb = cb; + req->user_data = user_data; + + __ofono_modem_foreach_atom(modem, OFONO_ATOM_TYPE_GPRS_PROVISION, + prepend_provision_driver, + &req->drivers); + + if (call_driver_get_settings(req, settings_cb) == TRUE) + return; + + DBG("No callable GPRS provision drivers"); + + g_slist_free(req->drivers); + +error: + g_free(req); + cb(NULL, user_data); +} + +static gint compare_priority(gconstpointer a, gconstpointer b) +{ + const struct ofono_gprs_provision_driver *plugin1 = a; + const struct ofono_gprs_provision_driver *plugin2 = b; + + return plugin2->priority - plugin1->priority; +} + +int ofono_gprs_provision_driver_register( + const struct ofono_gprs_provision_driver *driver) +{ + DBG("driver: %p name: %s", driver, driver->name); + + g_drivers = g_slist_insert_sorted(g_drivers, (void *) driver, + compare_priority); + return 0; +} + +void ofono_gprs_provision_driver_unregister( + const struct ofono_gprs_provision_driver *driver) +{ + DBG("driver: %p name: %s", driver, driver->name); + + g_drivers = g_slist_remove(g_drivers, driver); +} -- 1.7.1