Add basic support for a location detection framework
authorMarcel Holtmann <marcel@holtmann.org>
Fri, 29 Jan 2010 22:11:26 +0000 (14:11 -0800)
committerMarcel Holtmann <marcel@holtmann.org>
Fri, 29 Jan 2010 22:11:26 +0000 (14:11 -0800)
Makefile.am
include/location.h [new file with mode: 0644]
src/connman.h
src/element.c
src/location.c [new file with mode: 0644]
src/service.c

index 15b41a6..37d5ef8 100644 (file)
@@ -15,7 +15,8 @@ noinst_HEADERS = include/driver.h include/element.h include/property.h \
                        include/rtnl.h include/wifi.h include/task.h \
                        include/dbus.h include/rfkill.h include/option.h \
                        include/profile.h include/provider.h include/dhcp.h \
-                       include/utsname.h include/timeserver.h
+                       include/utsname.h include/timeserver.h \
+                       include/location.h
 
 local_headers = $(foreach file,$(include_HEADERS) $(nodist_include_HEADERS) \
                        $(noinst_HEADERS), include/connman/$(notdir $(file)))
@@ -52,7 +53,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(builtin_sources) \
                        src/ipv4.c src/dhcp.c src/rtnl.c src/inet.c \
                        src/utsname.c src/timeserver.c src/rfkill.c \
                        src/wifi.c src/storage.c src/dbus.c src/config.c \
-                       src/technology.c src/counter.c
+                       src/technology.c src/counter.c src/location.c
 
 if UDEV
 src_connmand_SOURCES += src/udev.c
diff --git a/include/location.h b/include/location.h
new file mode 100644 (file)
index 0000000..a0b01d6
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
+ *
+ *  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
+ *
+ */
+
+#ifndef __CONNMAN_LOCATION_H
+#define __CONNMAN_LOCATION_H
+
+#include <connman/service.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * SECTION:location
+ * @title: Location premitives
+ * @short_description: Functions for detecting locations
+ */
+
+enum connman_location_result {
+       CONNMAN_LOCATION_RESULT_UNKNOWN = 0,
+       CONNMAN_LOCATION_RESULT_PORTAL  = 1,
+       CONNMAN_LOCATION_RESULT_ONLINE  = 2,
+};
+
+struct connman_location;
+
+struct connman_location *connman_location_ref(struct connman_location *location);
+void connman_location_unref(struct connman_location *location);
+
+enum connman_service_type connman_location_get_type(struct connman_location *location);
+char *connman_location_get_interface(struct connman_location *location);
+void connman_location_report_result(struct connman_location *location,
+                                       enum connman_location_result result);
+
+void *connman_location_get_data(struct connman_location *location);
+void connman_location_set_data(struct connman_location *location, void *data);
+
+struct connman_location_driver {
+       const char *name;
+       enum connman_service_type type;
+       int priority;
+       int (*detect) (struct connman_location *location);
+       int (*finish) (struct connman_location *location);
+};
+
+int connman_location_driver_register(struct connman_location_driver *driver);
+void connman_location_driver_unregister(struct connman_location_driver *driver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMAN_LOCATION_H */
index 4d869bb..593a517 100644 (file)
@@ -409,6 +409,17 @@ void __connman_service_auto_connect(void);
 
 const char *__connman_service_type2string(enum connman_service_type type);
 
+#include <connman/location.h>
+
+int __connman_location_init(void);
+void __connman_location_cleanup(void);
+
+struct connman_location *__connman_location_create(struct connman_service *service);
+struct connman_location *__connman_service_get_location(struct connman_service *service);
+
+int __connman_location_detect(struct connman_service *service);
+int __connman_location_finish(struct connman_service *service);
+
 #include <connman/provider.h>
 
 void __connman_provider_list(DBusMessageIter *iter, void *user_data);
index 1d2afaa..94d13b3 100644 (file)
@@ -1250,6 +1250,7 @@ int __connman_element_init(const char *device, const char *nodevice)
 
        __connman_technology_init();
        __connman_notifier_init();
+       __connman_location_init();
        __connman_service_init();
        __connman_provider_init();
        __connman_network_init();
@@ -1344,6 +1345,7 @@ void __connman_element_cleanup(void)
        __connman_device_cleanup();
        __connman_network_cleanup();
        __connman_service_cleanup();
+       __connman_location_cleanup();
        __connman_notifier_cleanup();
        __connman_technology_cleanup();
 
diff --git a/src/location.c b/src/location.c
new file mode 100644 (file)
index 0000000..a0a8c41
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
+ *
+ *  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 <config.h>
+#endif
+
+#include "connman.h"
+
+struct connman_location {
+       gint refcount;
+       struct connman_service *service;
+       enum connman_location_result result;
+
+       struct connman_location_driver *driver;
+       void *driver_data;
+};
+
+/**
+ * connman_location_ref:
+ * @location: Location structure
+ *
+ * Increase reference counter of location
+ */
+struct connman_location *connman_location_ref(struct connman_location *location)
+{
+       g_atomic_int_inc(&location->refcount);
+
+       return location;
+}
+
+/**
+ * connman_location_unref:
+ * @location: Location structure
+ *
+ * Decrease reference counter of location
+ */
+void connman_location_unref(struct connman_location *location)
+{
+       if (g_atomic_int_dec_and_test(&location->refcount) == FALSE)
+               return;
+
+       if (location->driver) {
+               location->driver->finish(location);
+               location->driver = NULL;
+       }
+
+       g_free(location);
+}
+
+/**
+ * connman_location_get_type:
+ * @location: Location structure
+ *
+ * Get the service type of location
+ */
+enum connman_service_type connman_location_get_type(struct connman_location *location)
+{
+       if (location == NULL)
+               return CONNMAN_SERVICE_TYPE_UNKNOWN;
+
+       return connman_service_get_type(location->service);
+}
+
+/**
+ * connman_location_get_interface:
+ * @location: location structure
+ *
+ * Get network interface of location
+ */
+char *connman_location_get_interface(struct connman_location *location)
+{
+       if (location == NULL)
+               return NULL;
+
+       return connman_service_get_interface(location->service);
+}
+
+/**
+ * connman_location_get_data:
+ * @location: Location structure
+ *
+ * Get private location data pointer
+ */
+void *connman_location_get_data(struct connman_location *location)
+{
+       return location->driver_data;
+}
+
+/**
+ * connman_location_set_data:
+ * @location: Location structure
+ * @data: data pointer
+ *
+ * Set private location data pointer
+ */
+void connman_location_set_data(struct connman_location *location, void *data)
+{
+       location->driver_data = data;
+}
+
+static GSList *driver_list = NULL;
+
+static gint compare_priority(gconstpointer a, gconstpointer b)
+{
+       const struct connman_location_driver *driver1 = a;
+       const struct connman_location_driver *driver2 = b;
+
+       return driver2->priority - driver1->priority;
+}
+
+/**
+ * connman_location_driver_register:
+ * @driver: Location driver definition
+ *
+ * Register a new Location driver
+ *
+ * Returns: %0 on success
+ */
+int connman_location_driver_register(struct connman_location_driver *driver)
+{
+       DBG("driver %p name %s", driver, driver->name);
+
+       driver_list = g_slist_insert_sorted(driver_list, driver,
+                                                       compare_priority);
+
+       return 0;
+}
+
+/**
+ * connman_location_driver_unregister:
+ * @driver: Location driver definition
+ *
+ * Remove a previously registered Location driver
+ */
+void connman_location_driver_unregister(struct connman_location_driver *driver)
+{
+       DBG("driver %p name %s", driver, driver->name);
+
+       driver_list = g_slist_remove(driver_list, driver);
+}
+
+/**
+ * connman_location_report_result:
+ * @location: location structure
+ * @result: result information
+ *
+ * Report result of a location detection
+ */
+void connman_location_report_result(struct connman_location *location,
+                                       enum connman_location_result result)
+{
+       DBG("location %p result %d", location, result);
+
+       if (location == NULL)
+               return;
+
+       if (location->result == result)
+               return;
+
+       location->result = result;
+
+       switch (location->result) {
+       case CONNMAN_LOCATION_RESULT_UNKNOWN:
+               return;
+       case CONNMAN_LOCATION_RESULT_PORTAL:
+               //__connman_service_indicate_state(location->service,
+               //                              CONNMAN_SERVICE_STATE_LOGIN);
+               break;
+       case CONNMAN_LOCATION_RESULT_ONLINE:
+               //__connman_service_indicate_state(location->service,
+               //                              CONNMAN_SERVICE_STATE_ONLINE);
+               break;
+       }
+}
+
+struct connman_location *__connman_location_create(struct connman_service *service)
+{
+       struct connman_location *location;
+
+       DBG("service %p", service);
+
+       if (service == NULL)
+               return NULL;
+
+       location = g_try_new0(struct connman_location, 1);
+       if (location == NULL)
+               return NULL;
+
+       DBG("location %p", location);
+
+       location->refcount = 1;
+
+       location->service = service;
+       location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
+
+       return location;
+}
+
+int __connman_location_detect(struct connman_service *service)
+{
+       struct connman_location *location;
+       GSList *list;
+
+       DBG("service %p", service);
+
+       location = __connman_service_get_location(service);
+       if (location == NULL)
+               return -EINVAL;
+
+       if (location->driver)
+               return -EBUSY;
+
+       for (list = driver_list; list; list = list->next) {
+               struct connman_location_driver *driver = list->data;
+
+               DBG("driver %p name %s", driver, driver->name);
+
+               if (driver->detect(location) == 0) {
+                       location->driver = driver;
+                       break;
+               }
+       }
+
+       if (location->driver == NULL)
+               connman_location_report_result(location,
+                                       CONNMAN_LOCATION_RESULT_ONLINE);
+
+       return 0;
+}
+
+int __connman_location_finish(struct connman_service *service)
+{
+       struct connman_location *location;
+
+       DBG("service %p", service);
+
+       location = __connman_service_get_location(service);
+       if (location == NULL)
+               return -EINVAL;
+
+       if (location->driver) {
+               location->driver->finish(location);
+               location->driver = NULL;
+       }
+
+       return 0;
+}
+
+int __connman_location_init(void)
+{
+       return 0;
+}
+
+void __connman_location_cleanup(void)
+{
+}
index 1eccbac..116a596 100644 (file)
@@ -75,6 +75,7 @@ struct connman_service {
        char *phase2;
        DBusMessage *pending;
        guint timeout;
+       struct connman_location *location;
 };
 
 static void append_path(gpointer value, gpointer user_data)
@@ -1251,6 +1252,9 @@ static void service_free(gpointer user_data)
                service->ipconfig = NULL;
        }
 
+       if (service->location != NULL)
+               connman_location_unref(service->location);
+
        g_free(service->mcc);
        g_free(service->mnc);
        g_free(service->apn);
@@ -1336,9 +1340,16 @@ struct connman_service *connman_service_create(void)
 
        __connman_service_initialize(service);
 
+       service->location = __connman_location_create(service);
+
        return service;
 }
 
+struct connman_location *__connman_service_get_location(struct connman_service *service)
+{
+       return service->location;
+}
+
 /**
  * connman_service_ref:
  * @service: service structure
@@ -1588,7 +1599,11 @@ int __connman_service_indicate_state(struct connman_service *service,
                __connman_notifier_connect(service->type);
 
                default_changed();
+
+               __connman_location_detect(service);
        } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
+               __connman_location_finish(service);
+
                default_changed();
 
                __connman_notifier_disconnect(service->type);