Add interface infrastructure
authorMarcel Holtmann <marcel@holtmann.org>
Sat, 22 Dec 2007 21:10:15 +0000 (22:10 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Sat, 22 Dec 2007 21:10:15 +0000 (22:10 +0100)
configure.in
include/Makefile.am
include/iface.h [new file with mode: 0644]
src/Makefile.am
src/connman.h
src/iface.c [new file with mode: 0644]
src/main.c

index ecf67c4..930691a 100644 (file)
@@ -34,4 +34,9 @@ PKG_CHECK_MODULES(GDBUS, gdbus, dummy=yes,
 AC_SUBST(GDBUS_CFLAGS)
 AC_SUBST(GDBUS_LIBS)
 
+PKG_CHECK_MODULES(HAL, hal >= 0.5.8, dummy=yes,
+                               AC_MSG_ERROR(libhal is required))
+AC_SUBST(HAL_CFLAGS)
+AC_SUBST(HAL_LIBS)
+
 AC_OUTPUT(Makefile include/Makefile src/Makefile plugins/Makefile)
index 55bf6b5..ece5af1 100644 (file)
@@ -1,7 +1,7 @@
 
 includedir = @includedir@/connman
 
-noinst_HEADERS = plugin.h
+noinst_HEADERS = plugin.h iface.h
 
 MAINTAINERCLEANFILES = Makefile.in
 
diff --git a/include/iface.h b/include/iface.h
new file mode 100644 (file)
index 0000000..cc3ab0c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007  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_IFACE_H
+#define __CONNMAN_IFACE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum connman_iface_type {
+       CONNMAN_IFACE_TYPE_UNKNOWN   = 0,
+       CONNMAN_IFACE_TYPE_80203     = 1,
+       CONNMAN_IFACE_TYPE_80211     = 2,
+       CONNMAN_IFACE_TYPE_WIMAX     = 3,
+       CONNMAN_IFACE_TYPE_BLUETOOTH = 4,
+};
+
+enum connman_iface_flags {
+       CONNMAN_IFACE_FLAGS_CARRIER_DETECT      = (1 << 0),
+       CONNMAN_IFACE_FLAGS_IPV4                = (1 << 1),
+       CONNMAN_IFACE_FLAGS_IPV6                = (1 << 2),
+};
+
+struct connman_iface {
+       struct connman_iface_driver *driver;
+       char *path;
+       char *udi;
+       char *sysfs;
+       enum connman_iface_type type;
+       enum connman_iface_flags flags;
+};
+
+struct connman_iface_driver {
+       const char *name;
+       const char *capability;
+       int (*probe) (struct connman_iface *iface);
+       void (*remove) (struct connman_iface *iface);
+};
+
+extern int connman_iface_register(struct connman_iface_driver *driver);
+extern void connman_iface_unregister(struct connman_iface_driver *driver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMAN_IFACE_H */
index 9f15cf3..5233c0b 100644 (file)
@@ -5,17 +5,17 @@ dbus_DATA = connman.conf
 
 sbin_PROGRAMS = connmand
 
-connmand_SOURCES = main.c connman.h plugin.c
+connmand_SOURCES = main.c connman.h plugin.c iface.c
 
-connmand_LDADD = @GDBUS_LIBS@ @GMODULE_LIBS@
+connmand_LDADD = @HAL_LIBS@ @GDBUS_LIBS@ @GMODULE_LIBS@
  
 if MAINTAINER_MODE
 plugindir = $(abs_top_srcdir)/plugins
 else
-plugindir = $(libdir)/connman
+plugindir = $(libdir)/connman/plugins
 endif
 
-AM_CFLAGS = @GMODULE_CFLAGS@ @GDBUS_CFLAGS@ \
+AM_CFLAGS = @GMODULE_CFLAGS@ @GDBUS_CFLAGS@ @HAL_CFLAGS@ \
                        -DPLUGINDIR=\""$(plugindir)"\"
 
 INCLUDES = -I$(top_builddir)/include
index f81ecd0..641b0a2 100644 (file)
 #define CONNMAN_MANAGER_PATH "/"
 #define CONNMAN_MANAGER_INTERFACE  CONNMAN_SERVICE ".Manager"
 
+#define CONNMAN_IFACE_BASEPATH  "/interface"
+#define CONNMAN_IFACE_INTERFACE  CONNMAN_SERVICE ".Interface"
+
 #include <connman/plugin.h>
 
 int __connman_plugin_init(void);
 void __connman_plugin_cleanup(void);
+
+#include <connman/iface.h>
+
+int __connman_iface_init(DBusConnection *conn);
+void __connman_iface_cleanup(void);
diff --git a/src/iface.c b/src/iface.c
new file mode 100644 (file)
index 0000000..ce6ab38
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007  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 <string.h>
+
+#include <glib.h>
+#include <gdbus.h>
+
+#include <hal/libhal.h>
+
+#include "connman.h"
+
+static GSList *drivers = NULL;
+
+int connman_iface_register(struct connman_iface_driver *driver)
+{
+       DBG("driver %p", driver);
+
+       drivers = g_slist_append(drivers, driver);
+
+       return 0;
+}
+
+void connman_iface_unregister(struct connman_iface_driver *driver)
+{
+       DBG("driver %p", driver);
+
+       drivers = g_slist_remove(drivers, driver);
+}
+
+static GSList *interfaces = NULL;
+
+static void device_free(void *data)
+{
+       struct connman_iface *iface = data;
+
+       DBG("iface %p", iface);
+
+       if (iface->driver && iface->driver->remove)
+               iface->driver->remove(iface);
+
+       g_free(iface->path);
+       g_free(iface->udi);
+       g_free(iface->sysfs);
+       g_free(iface);
+}
+
+static int probe_device(LibHalContext *ctx,
+                       struct connman_iface_driver *driver, const char *udi)
+{
+       DBusConnection *conn;
+       struct connman_iface *iface;
+       char *temp, *sysfs;
+       int err;
+
+       DBG("ctx %p driver %p udi %s", ctx, driver, udi);
+
+       if (!driver->probe)
+               return -1;
+
+       iface = g_try_new0(struct connman_iface, 1);
+       if (iface == NULL)
+               return -1;
+
+       temp = g_path_get_basename(udi);
+       iface->path = g_strdup_printf("%s/%s", CONNMAN_IFACE_BASEPATH, temp);
+       g_free(temp);
+
+       iface->udi = g_strdup(udi);
+
+       DBG("path %s", iface->path);
+
+       sysfs = libhal_device_get_property_string(ctx, udi,
+                                               "linux.sysfs_path", NULL);
+       if (sysfs != NULL)
+               iface->sysfs = g_strdup(sysfs);
+
+       iface->type = CONNMAN_IFACE_TYPE_UNKNOWN;
+       iface->flags = 0;
+
+       DBG("iface %p", iface);
+
+       err = driver->probe(iface);
+       if (err < 0) {
+               device_free(iface);
+               return -1;
+       }
+
+       iface->driver = driver;
+
+       conn = libhal_ctx_get_dbus_connection(ctx);
+
+       g_dbus_register_object(conn, iface->path, iface, device_free);
+
+       interfaces = g_slist_append(interfaces, iface);
+
+       return 0;
+}
+
+static void device_added(LibHalContext *ctx, const char *udi)
+{
+       GSList *list;
+
+       DBG("ctx %p udi %s", ctx, udi);
+
+       for (list = drivers; list; list = list->next) {
+               struct connman_iface_driver *driver = list->data;
+
+               if (driver->capability == NULL)
+                       continue;
+
+               if (libhal_device_query_capability(ctx, udi,
+                                       driver->capability, NULL) == TRUE) {
+                       if (probe_device(ctx, driver, udi) == 0)
+                               break;
+               }
+       }
+}
+
+static void device_removed(LibHalContext *ctx, const char *udi)
+{
+       DBusConnection *conn;
+       GSList *list;
+
+       DBG("ctx %p udi %s", ctx, udi);
+
+       conn = libhal_ctx_get_dbus_connection(ctx);
+
+       for (list = interfaces; list; list = list->next) {
+               struct connman_iface *iface = list->data;
+
+               if (strcmp(udi, iface->udi) == 0) {
+                       interfaces = g_slist_remove(interfaces, iface);
+                       g_dbus_unregister_object(conn, iface->path);
+                       break;
+               }
+       }
+}
+
+static void probe_driver(LibHalContext *ctx,
+                               struct connman_iface_driver *driver)
+{
+       char **list;
+       int num;
+
+       DBG("ctx %p driver %p", ctx, driver);
+
+       list = libhal_find_device_by_capability(ctx,
+                                       driver->capability, &num, NULL);
+       if (list) {
+               char **tmp = list;
+
+               while (*tmp) {
+                       probe_device(ctx, driver, *tmp);
+                       tmp++;
+               }
+
+               libhal_free_string_array(list);
+       }
+}
+
+static void find_devices(LibHalContext *ctx)
+{
+       GSList *list;
+
+       DBG("ctx %p", ctx);
+
+       for (list = drivers; list; list = list->next) {
+               struct connman_iface_driver *driver = list->data;
+
+               DBG("driver %p", driver);
+
+               if (driver->capability == NULL)
+                       continue;
+
+               probe_driver(ctx, driver);
+       }
+}
+
+static LibHalContext *hal_ctx = NULL;
+
+static void hal_init(void *data)
+{
+       DBusConnection *conn = data;
+
+       DBG("conn %p", conn);
+
+       if (hal_ctx != NULL)
+               return;
+
+       hal_ctx = libhal_ctx_new();
+       if (hal_ctx == NULL)
+               return;
+
+       if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
+               libhal_ctx_free(hal_ctx);
+               return;
+       }
+
+       if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
+               libhal_ctx_free(hal_ctx);
+               return ;
+       }
+
+       libhal_ctx_set_device_added(hal_ctx, device_added);
+       libhal_ctx_set_device_removed(hal_ctx, device_removed);
+
+       //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
+       //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
+
+       find_devices(hal_ctx);
+}
+
+static void hal_cleanup(void *data)
+{
+       DBusConnection *conn = data;
+       GSList *list;
+
+       DBG("conn %p", conn);
+
+       if (hal_ctx == NULL)
+               return;
+
+       for (list = interfaces; list; list = list->next) {
+               struct connman_iface *iface = list->data;
+
+               DBG("path %s", iface->path);
+
+               g_dbus_unregister_object(conn, iface->path);
+       }
+
+       g_slist_free(interfaces);
+
+       interfaces = NULL;
+
+       libhal_ctx_shutdown(hal_ctx, NULL);
+
+       libhal_ctx_free(hal_ctx);
+
+       hal_ctx = NULL;
+}
+
+static DBusConnection *connection = NULL;
+static guint hal_watch = 0;
+
+int __connman_iface_init(DBusConnection *conn)
+{
+       DBG("conn %p", conn);
+
+       connection = dbus_connection_ref(conn);
+       if (connection == NULL)
+               return -1;
+
+       hal_init(connection);
+
+       hal_watch = g_dbus_add_watch(connection, "org.freedesktop.Hal",
+                               hal_init, hal_cleanup, connection, NULL);
+
+       return 0;
+}
+
+void __connman_iface_cleanup(void)
+{
+       DBG("conn %p", connection);
+
+       g_dbus_remove_watch(connection, hal_watch);
+
+       hal_cleanup(connection);
+
+       dbus_connection_unref(connection);
+}
index 7437802..89c49fd 100644 (file)
@@ -56,6 +56,8 @@ int main(int argc, char *argv[])
 
        __connman_plugin_init();
 
+       __connman_iface_init(conn);
+
        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = sig_term;
        sigaction(SIGINT, &sa, NULL);
@@ -63,6 +65,8 @@ int main(int argc, char *argv[])
 
        g_main_loop_run(main_loop);
 
+       __connman_iface_cleanup();
+
        __connman_plugin_cleanup();
 
        g_dbus_unregister_object(conn, CONNMAN_MANAGER_PATH);