OSDN Git Service

core: Add skeleton for connecting external profiles
authorJohan Hedberg <johan.hedberg@intel.com>
Mon, 1 Oct 2012 12:17:46 +0000 (15:17 +0300)
committerJohan Hedberg <johan.hedberg@intel.com>
Mon, 1 Oct 2012 12:17:46 +0000 (15:17 +0300)
src/profile.c

index 05ef9f0..6033f35 100644 (file)
 #include "device.h"
 #include "profile.h"
 
+struct pending_connect {
+       struct btd_device *dev;
+       btd_profile_cb cb;
+};
+
 struct ext_profile {
        struct btd_profile p;
 
@@ -54,6 +59,8 @@ struct ext_profile {
        char *path;
        char *role;
 
+       char **remote_uuids;
+
        guint id;
 
        BtIOSecLevel sec_level;
@@ -64,6 +71,8 @@ struct ext_profile {
 
        GSList *servers;
        GSList *conns;
+
+       GSList *connects;
 };
 
 struct ext_io {
@@ -490,17 +499,25 @@ static int ext_start_servers(struct ext_profile *ext,
        return 0;
 }
 
-static int ext_adapter_probe(struct btd_profile *p,
-                                               struct btd_adapter *adapter)
+static struct ext_profile *find_ext(struct btd_profile *p)
 {
-       struct ext_profile *ext;
        GSList *l;
 
        l = g_slist_find(ext_profiles, p);
        if (!l)
-               return -ENOENT;
+               return NULL;
+
+       return l->data;
+}
 
-       ext = l->data;
+static int ext_adapter_probe(struct btd_profile *p,
+                                               struct btd_adapter *adapter)
+{
+       struct ext_profile *ext;
+
+       ext = find_ext(p);
+       if (!ext)
+               return -ENOENT;
 
        DBG("\"%s\" probed", ext->name);
 
@@ -513,12 +530,10 @@ static void ext_adapter_remove(struct btd_profile *p,
        struct ext_profile *ext;
        GSList *l, *next;
 
-       l = g_slist_find(ext_profiles, p);
-       if (!l)
+       ext = find_ext(p);
+       if (!ext)
                return;
 
-       ext = l->data;
-
        DBG("\"%s\" removed", ext->name);
 
        for (l = ext->servers; l != NULL; l = next) {
@@ -534,6 +549,102 @@ static void ext_adapter_remove(struct btd_profile *p,
        }
 }
 
+static int ext_device_probe(struct btd_profile *p, struct btd_device *dev,
+                                                               GSList *uuids)
+{
+       struct ext_profile *ext;
+
+       ext = find_ext(p);
+       if (!ext)
+               return -ENOENT;
+
+       DBG("%s probed with %u UUIDs", ext->name, g_slist_length(uuids));
+
+       return 0;
+}
+
+static void pending_conn_free(gpointer data)
+{
+       struct pending_connect *conn = data;
+
+       btd_device_unref(conn->dev);
+       g_free(conn);
+}
+
+static void remove_connect(struct ext_profile *ext, struct btd_device *dev)
+{
+       GSList *l, *next;
+
+       for (l = ext->connects; l != NULL; l = next) {
+               struct pending_connect *conn = l->data;
+
+               next = g_slist_next(l);
+
+               if (conn->dev != dev)
+                       continue;
+
+               ext->connects = g_slist_remove(ext->connects, conn);
+               pending_conn_free(conn);
+       }
+}
+
+static void ext_device_remove(struct btd_profile *p, struct btd_device *dev)
+{
+       struct ext_profile *ext;
+
+       ext = find_ext(p);
+       if (!ext)
+               return;
+
+       DBG("%s", ext->name);
+
+       remove_connect(ext, dev);
+}
+
+static int connect_ext(struct ext_profile *ext, struct btd_device *dev)
+{
+       return -ENOSYS;
+}
+
+static int ext_connect_dev(struct btd_device *dev, struct btd_profile *profile,
+                                                       btd_profile_cb cb)
+{
+       struct ext_profile *ext;
+       struct pending_connect *conn;
+       int err;
+
+       ext = find_ext(profile);
+       if (!ext)
+               return -ENOENT;
+
+       err = connect_ext(ext, dev);
+       if (err < 0)
+               return err;
+
+       conn = g_new0(struct pending_connect, 1);
+       conn->dev = btd_device_ref(dev);
+       conn->cb = cb;
+
+       ext->connects = g_slist_append(ext->connects, conn);
+
+       return 0;
+}
+
+static int ext_disconnect_dev(struct btd_device *dev,
+                                               struct btd_profile *profile,
+                                               btd_profile_cb cb)
+{
+       struct ext_profile *ext;
+
+       ext = find_ext(profile);
+       if (!ext)
+               return -ENOENT;
+
+       remove_connect(ext, dev);
+
+       return 0;
+}
+
 static void ext_get_defaults(struct ext_profile *ext)
 {
        if (ext->psm || ext->chan)
@@ -613,6 +724,7 @@ static struct ext_profile *create_ext(const char *owner, const char *path,
        ext->owner = g_strdup(owner);
        ext->path = g_strdup(path);
        ext->uuid = g_strdup(uuid);
+       ext->remote_uuids = g_new0(char *, 1);
 
        ext->sec_level = BT_IO_SEC_LOW;
 
@@ -643,6 +755,15 @@ static struct ext_profile *create_ext(const char *owner, const char *path,
        p->adapter_probe = ext_adapter_probe;
        p->adapter_remove = ext_adapter_remove;
 
+       /* Typecast can't really be avoided here:
+        * http://c-faq.com/ansi/constmismatch.html */
+       p->remote_uuids = (const char **) ext->remote_uuids;
+
+       p->device_probe = ext_device_probe;
+       p->device_remove = ext_device_remove;
+       p->connect = ext_connect_dev;
+       p->disconnect = ext_disconnect_dev;
+
        DBG("Created \"%s\"", ext->name);
 
        ext_profiles = g_slist_append(ext_profiles, ext);
@@ -662,6 +783,9 @@ static void remove_ext(struct ext_profile *ext)
 
        g_slist_free_full(ext->servers, ext_io_destroy);
        g_slist_free_full(ext->conns, ext_io_destroy);
+       g_slist_free_full(ext->connects, pending_conn_free);
+
+       g_strfreev(ext->remote_uuids);
 
        g_free(ext->name);
        g_free(ext->owner);