core: Add Device.ConnectProfile method
diff --git a/src/device.c b/src/device.c
index da42a7d..4b0625c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1285,14 +1285,33 @@
return device_browse_primary(dev, msg, FALSE);
}
-static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
- void *user_data)
+static struct btd_profile *find_connectable_profile(struct btd_device *dev,
+ const char *uuid)
{
- struct btd_device *dev = user_data;
+ GSList *l;
+
+ for (l = dev->profiles; l != NULL; l = g_slist_next(l)) {
+ struct btd_profile *p = l->data;
+
+ if (!p->connect)
+ continue;
+
+ if (strcasecmp(uuid, p->local_uuid) == 0)
+ return p;
+ }
+
+ return NULL;
+}
+
+static DBusMessage *connect_profiles(struct btd_device *dev, DBusMessage *msg,
+ const char *uuid)
+{
struct btd_profile *p;
GSList *l;
int err;
+ DBG("%s %s", dev->path, uuid ? uuid : "(all)");
+
if (dev->profiles_connected)
return btd_error_already_connected(msg);
@@ -1308,6 +1327,16 @@
return NULL;
}
+ if (uuid) {
+ p = find_connectable_profile(dev, uuid);
+ if (!p)
+ return btd_error_invalid_args(msg);
+
+ dev->pending = g_slist_prepend(dev->pending, p);
+
+ goto start_connect;
+ }
+
for (l = dev->profiles; l != NULL; l = g_slist_next(l)) {
p = l->data;
@@ -1318,6 +1347,7 @@
if (!dev->pending)
return btd_error_not_available(msg);
+start_connect:
err = connect_next(dev, dev_profile_connected);
if (err < 0)
return btd_error_failed(msg, strerror(-err));
@@ -1327,6 +1357,33 @@
return NULL;
}
+static DBusMessage *dev_connect(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+{
+ struct btd_device *dev = user_data;
+
+ return connect_profiles(dev, msg, NULL);
+}
+
+static DBusMessage *connect_profile(DBusConnection *conn, DBusMessage *msg,
+ void *user_data)
+{
+ struct btd_device *dev = user_data;
+ const char *pattern;
+ char *uuid;
+ DBusMessage *reply;
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern,
+ DBUS_TYPE_INVALID))
+ return btd_error_invalid_args(msg);
+
+ uuid = bt_name2string(pattern);
+ reply = connect_profiles(dev, msg, uuid);
+ g_free(uuid);
+
+ return reply;
+}
+
static void device_svc_resolved(struct btd_device *dev, int err)
{
DBusMessage *reply;
@@ -1345,24 +1402,34 @@
if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
"DiscoverServices")) {
discover_services_reply(req, err, dev->tmp_records);
- } else if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
+ return;
+ }
+
+ if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
"Pair")) {
reply = dbus_message_new_method_return(req->msg);
g_dbus_send_message(conn, reply);
- } else if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
- "Connect")) {
- if (err) {
- reply = btd_error_failed(req->msg, strerror(-err));
- g_dbus_send_message(conn, reply);
- return;
- }
-
- reply = dev_connect(conn, req->msg, dev);
- if (reply)
- g_dbus_send_message(conn, reply);
- else
- req->msg = NULL;
+ return;
}
+
+ if (err) {
+ reply = btd_error_failed(req->msg, strerror(-err));
+ g_dbus_send_message(conn, reply);
+ return;
+ }
+
+ if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE, "Connect"))
+ reply = dev_connect(conn, req->msg, dev);
+ else if (dbus_message_is_method_call(req->msg, DEVICE_INTERFACE,
+ "ConnectProfile"))
+ reply = connect_profile(conn, req->msg, dev);
+ else
+ return;
+
+ if (reply)
+ g_dbus_send_message(conn, reply);
+ else
+ req->msg = NULL;
}
static uint8_t parse_io_capability(const char *capability)
@@ -1428,6 +1495,8 @@
{ GDBUS_METHOD("CancelDiscovery", NULL, NULL, cancel_discover) },
{ GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, disconnect) },
{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, dev_connect) },
+ { GDBUS_ASYNC_METHOD("ConnectProfile", GDBUS_ARGS({ "UUID", "s" }),
+ NULL, connect_profile) },
{ GDBUS_ASYNC_METHOD("Pair",
GDBUS_ARGS({ "agent", "o" }, { "capability", "s" }),
NULL, pair_device) },