diff mbox series

[5/5] Add SDP records retrieval for a unpaired/unconnected device

Message ID 20200401221434.12185-5-sonnysasaka@chromium.org
State New
Headers show
Series [1/5] D-Bus API changes for managing SDP records | expand

Commit Message

Sonny Sasaka April 1, 2020, 10:14 p.m. UTC
From: Miao Chou <mcchou@chromium.org>

This add the support of SDP record inquiry to a device which is not paired or
connected previously.
---
 src/device.c | 130 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 109 insertions(+), 21 deletions(-)
diff mbox series

Patch

diff --git a/src/device.c b/src/device.c
index 1b5afc226..dd7c32625 100644
--- a/src/device.c
+++ b/src/device.c
@@ -270,9 +270,35 @@  static const uint16_t uuid_list[] = {
 	0
 };
 
+struct pending_sdp_query {
+	bdaddr_t dev_bdaddr;
+	DBusConnection *conn;
+	DBusMessage *msg;
+};
+
 static int device_browse_gatt(struct btd_device *device, DBusMessage *msg);
 static int device_browse_sdp(struct btd_device *device, DBusMessage *msg);
 
+static struct pending_sdp_query *pending_sdp_query_new(DBusConnection *conn,
+				DBusMessage *msg, const struct btd_device *dev)
+{
+	struct pending_sdp_query *query;
+
+	query = g_new0(struct pending_sdp_query, 1);
+	query->dev_bdaddr = dev->bdaddr;
+	query->conn = dbus_connection_ref(conn);
+	query->msg = dbus_message_ref(msg);
+
+	return query;
+}
+
+static void pending_sdp_query_free(struct pending_sdp_query *query)
+{
+	dbus_connection_unref(query->conn);
+	dbus_message_unref(query->msg);
+	g_free(query);
+}
+
 static struct bearer_state *get_state(struct btd_device *dev,
 							uint8_t bdaddr_type)
 {
@@ -3008,28 +3034,13 @@  static dbus_bool_t append_record(const sdp_record_t *rec,
 	return TRUE;
 }
 
-static DBusMessage *get_service_records(DBusConnection *conn,
-					DBusMessage *msg, void *data)
+static dbus_bool_t append_records(DBusMessage *reply, sdp_list_t *seq)
 {
-	struct btd_device *dev = data;
-	sdp_list_t *seq;
-	DBusMessage *reply;
 	DBusMessageIter rec_array;
 	DBusMessageIter attr_array;
 
-	if (!btd_adapter_get_powered(dev->adapter))
-		return btd_error_not_ready(msg);
-
-	if (!btd_device_is_connected(dev))
-		return btd_error_not_connected(msg);
-
-	reply = dbus_message_new_method_return(msg);
-	if (!reply)
-		return btd_error_failed(msg, "Failed to create method reply");
-
-	/* Load records from storage if there is nothing in cache */
-	if (!dev->tmp_records)
-		return btd_error_failed(msg, "SDP record not found");
+	if (!seq)
+		return FALSE;
 
 	dbus_message_iter_init_append(reply, &rec_array);
 
@@ -3037,18 +3048,95 @@  static DBusMessage *get_service_records(DBusConnection *conn,
 						"a{q(yuv)}", &attr_array))
 		return FALSE;
 
-	for (seq = dev->tmp_records; seq; seq = seq->next) {
+	for (; seq; seq = seq->next) {
 		sdp_record_t *rec = (sdp_record_t *) seq->data;
 		if (!rec)
 			continue;
 		if (!append_record(rec, &attr_array))
-			return btd_error_failed(msg,
-						"SDP record attachment failed");
+			return FALSE;
 	}
 
 	if (!dbus_message_iter_close_container(&rec_array, &attr_array))
 		return FALSE;
 
+	return TRUE;
+}
+
+static void get_service_records_cb(struct btd_device *dev, int err,
+						void *user_data)
+{
+	struct pending_sdp_query *query = user_data;
+	DBusMessage *reply;
+	sdp_list_t *seq = dev->tmp_records;
+
+	if (memcmp(&query->dev_bdaddr, &dev->bdaddr, sizeof(bdaddr_t))) {
+		reply = btd_error_failed(query->msg, "Device mismatched");
+		goto send_reply;
+	}
+
+	if (!dev->bredr_state.svc_resolved) {
+		reply = btd_error_not_ready(query->msg);
+		goto send_reply;
+	}
+
+	/* Load records from storage if there is nothing in cache */
+	if (!seq) {
+		reply = btd_error_failed(query->msg, "SDP record not found");
+		goto send_reply;
+	}
+
+	reply = dbus_message_new_method_return(query->msg);
+	if (!reply) {
+		reply = btd_error_failed(query->msg, "Failed to create method reply");
+		goto send_reply;
+	}
+
+	if (!append_records(reply, dev->tmp_records))
+		reply = btd_error_failed(query->msg, "SDP record attachment failed");
+
+send_reply:
+	g_dbus_send_message(query->conn, reply);
+	pending_sdp_query_free(query);
+}
+
+static DBusMessage *get_service_records(DBusConnection *conn,
+					DBusMessage *msg, void *data)
+{
+	struct btd_device *dev = data;
+	DBusMessage *reply;
+	struct pending_sdp_query *query = NULL;
+	sdp_list_t *seq = dev->tmp_records;
+
+	if (!btd_adapter_get_powered(dev->adapter))
+		return btd_error_not_ready(msg);
+
+	if (!btd_device_is_connected(dev)) {
+		/*
+		 * Do a SDP service discovery on the device if the device is not
+		 * previously connected. SDP records will be returned later in
+		 * get_service_records_cb.
+		 */
+		query = pending_sdp_query_new(conn, msg, dev);
+		device_wait_for_svc_complete(dev, get_service_records_cb,
+						query);
+		device_browse_sdp(dev, NULL);
+		return NULL;
+	}
+
+	if (!dev->bredr_state.svc_resolved)
+		return btd_error_not_ready(msg);
+
+	/* Load records from storage if there is nothing in cache */
+	if (!seq)
+		return btd_error_failed(msg, "SDP record not found");
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return btd_error_failed(msg, "Failed to create method reply");
+
+	if (!append_records(reply, seq))
+		return btd_error_failed(msg, "SDP record attachment failed");
+
 	return reply;
 }