plugins/service: Add initial code
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Sun, 5 Jan 2014 17:08:29 +0000 (19:08 +0200)
committerMikko Ylinen <mikko.ylinen@intel.com>
Tue, 23 Sep 2014 18:29:46 +0000 (21:29 +0300)
Add initial code that creates service objects data.

plugins/service.c

index e63d8a8..0c22d79 100644 (file)
 #include <config.h>
 #endif
 
-#include "src/plugin.h"
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <gdbus/gdbus.h>
+
+#include "lib/uuid.h"
 #include "src/log.h"
+#include "src/plugin.h"
+#include "src/dbus-common.h"
+#include "src/error.h"
+#include "src/adapter.h"
+#include "src/device.h"
+#include "src/service.h"
+#include "src/profile.h"
+
+#define SERVICE_INTERFACE "org.bluez.Service1"
+
+static unsigned int service_id = 0;
+static GSList *services = NULL;
+
+struct service_data {
+       struct btd_service *service;
+       char *path;
+};
+
+static struct service_data *find_data(struct btd_service *service)
+{
+       GSList *l;
+
+       for (l = services; l; l = l->next) {
+               struct service_data *data = l->data;
+
+               if (data->service == service)
+                       return data;
+       }
+
+       return NULL;
+}
+
+static void data_free(void *user_data)
+{
+       struct service_data *data = user_data;
+
+       g_free(data->path);
+       g_free(data);
+}
+
+static void data_remove(struct service_data *data)
+{
+       services = g_slist_remove(services, data);
+       g_dbus_unregister_interface(btd_get_dbus_connection(), data->path,
+                                                       SERVICE_INTERFACE);
+}
+
+static DBusMessage *service_disconnect(DBusConnection *conn, DBusMessage *msg,
+                                                               void *user_data)
+{
+       return btd_error_not_available(msg);
+}
+
+static DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg,
+                                                               void *user_data)
+{
+       return btd_error_not_available(msg);
+}
+
+static const GDBusMethodTable service_methods[] = {
+       { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, service_disconnect) },
+       { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, service_connect) },
+       {}
+};
+
+static struct service_data *service_get_data(struct btd_service *service)
+{
+       struct btd_device *dev = btd_service_get_device(service);
+       struct btd_profile *p = btd_service_get_profile(service);
+       struct service_data *data;
+
+       data = find_data(service);
+       if (data != NULL)
+               return data;
+
+       data = g_new0(struct service_data, 1);
+       data->path = g_strdup_printf("%s/%s", btd_device_get_path(dev),
+                                                               p->remote_uuid);
+       data->path = g_strdelimit(data->path, "-", '_');
+       data->service = service;
+       if (g_dbus_register_interface(btd_get_dbus_connection(),
+                                       data->path, SERVICE_INTERFACE,
+                                       service_methods, NULL,
+                                       NULL, data,
+                                       data_free) == FALSE) {
+               error("Unable to register service interface for %s",
+                                                               data->path);
+               data_free(data);
+               return NULL;
+       }
+
+       services = g_slist_prepend(services, data);
+
+       DBG("%s", data->path);
+
+       return data;
+}
+
+static void service_cb(struct btd_service *service,
+                                               btd_service_state_t old_state,
+                                               btd_service_state_t new_state,
+                                               void *user_data)
+{
+       struct service_data *data;
+
+       data = service_get_data(service);
+       if (!data)
+               return;
+
+       switch (new_state) {
+       case BTD_SERVICE_STATE_UNAVAILABLE:
+               data_remove(data);
+               break;
+       default:
+               return;
+       }
+}
 
 static int service_init(void)
 {
        DBG("");
 
+       service_id = btd_service_add_state_cb(service_cb, NULL);
+
        return 0;
 }
 
 static void service_exit(void)
 {
        DBG("");
+
+       btd_service_remove_state_cb(service_id);
+
+       g_slist_free_full(services, data_free);
 }
 
 BLUETOOTH_PLUGIN_DEFINE(service, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,