From 7ab85649e5d9522a1784eeba22f77ed3deecc723 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 1 Oct 2012 15:17:46 +0300 Subject: [PATCH] core: Add skeleton for connecting external profiles --- src/profile.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 133 insertions(+), 9 deletions(-) diff --git a/src/profile.c b/src/profile.c index 05ef9f0f6..6033f3563 100644 --- a/src/profile.c +++ b/src/profile.c @@ -45,6 +45,11 @@ #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); -- 2.47.3