linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ v2 01/11] android/gatt: Make application API public
@ 2014-06-13 11:33 Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 02/11] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This in future gonna be used by HoG to receive connection notifications.
---
v2: Fix hidhost states not being propagated and add patch to set medium
security for devices paired.

 android/gatt.c | 142 +++++++++++++++++++++++++++++++++++++++++++++------------
 android/gatt.h |  15 ++++++
 2 files changed, 129 insertions(+), 28 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 741dc38..a2314e0 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -87,11 +87,6 @@ static const char const *device_state_str[] = {
 	"CONNECTED",
 };
 
-typedef enum {
-	APP_CLIENT,
-	APP_SERVER,
-} gatt_app_type_t;
-
 struct pending_trans_data {
 	unsigned int id;
 	uint8_t opcode;
@@ -101,10 +96,12 @@ struct gatt_app {
 	int32_t id;
 	uint8_t uuid[16];
 
-	gatt_app_type_t type;
+	gatt_type_t type;
 
 	/* Valid for client applications */
 	struct queue *notifications;
+
+	gatt_conn_cb_t func;
 };
 
 struct element_id {
@@ -617,7 +614,7 @@ static void destroy_gatt_app(void *data)
 	 * too. So remove all elements and then destroy queue.
 	 */
 
-	if (app->type == APP_CLIENT)
+	if (app->type == GATT_CLIENT)
 		while (queue_peek_head(app->notifications)) {
 			struct notification_data *notification;
 
@@ -630,14 +627,14 @@ static void destroy_gatt_app(void *data)
 	free(app);
 }
 
-static int register_app(const uint8_t *uuid, gatt_app_type_t app_type)
+static struct gatt_app *register_app(const uint8_t *uuid, gatt_type_t type)
 {
 	static int32_t application_id = 1;
 	struct gatt_app *app;
 
 	if (queue_find(gatt_apps, match_app_by_uuid, uuid)) {
 		error("gatt: app uuid is already on list");
-		return 0;
+		return NULL;
 	}
 
 	app = new0(struct gatt_app, 1);
@@ -646,14 +643,14 @@ static int register_app(const uint8_t *uuid, gatt_app_type_t app_type)
 		return 0;
 	}
 
-	app->type = app_type;
+	app->type = type;
 
-	if (app->type == APP_CLIENT) {
+	if (app->type == GATT_CLIENT) {
 		app->notifications = queue_new();
 		if (!app->notifications) {
 			error("gatt: couldn't allocate notifications queue");
 			destroy_gatt_app(app);
-			return 0;
+			return NULL;
 		}
 	}
 
@@ -664,33 +661,35 @@ static int register_app(const uint8_t *uuid, gatt_app_type_t app_type)
 	if (!queue_push_head(gatt_apps, app)) {
 		error("gatt: Cannot push app on the list");
 		destroy_gatt_app(app);
-		return 0;
+		return NULL;
 	}
 
-	if ((app->type == APP_SERVER) &&
+	if ((app->type == GATT_SERVER) &&
 			!queue_push_tail(listen_apps, INT_TO_PTR(app->id))) {
 		error("gatt: Cannot push server on the list");
 		destroy_gatt_app(app);
-		return 0;
+		return NULL;
 	}
 
-	return app->id;
+	return app;
 }
 
 static void handle_client_register(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_client_register *cmd = buf;
 	struct hal_ev_gatt_client_register_client ev;
+	struct gatt_app *app;
 
 	DBG("");
 
 	memset(&ev, 0, sizeof(ev));
 
-	ev.client_if = register_app(cmd->uuid, APP_CLIENT);
+	app = register_app(cmd->uuid, GATT_CLIENT);
 
-	if (ev.client_if)
+	if (app) {
+		ev.client_if = app->id;
 		ev.status = GATT_SUCCESS;
-	else
+	} else
 		ev.status = GATT_FAILURE;
 
 	/* We should send notification with given in cmd UUID */
@@ -708,6 +707,12 @@ static void send_client_disconnection_notify(struct app_connection *connection,
 {
 	struct hal_ev_gatt_client_disconnect ev;
 
+	if (connection->app->func) {
+		connection->app->func(&connection->device->bdaddr, -ENOTCONN,
+						connection->device->attrib);
+		return;
+	}
+
 	ev.client_if = connection->app->id;
 	ev.conn_id = connection->id;
 	ev.status = status;
@@ -723,6 +728,13 @@ static void send_client_connection_notify(struct app_connection *connection,
 {
 	struct hal_ev_gatt_client_connect ev;
 
+	if (connection->app->func) {
+		connection->app->func(&connection->device->bdaddr,
+					status == GATT_SUCCESS ? 0 : -ENOTCONN,
+					connection->device->attrib);
+		return;
+	}
+
 	ev.client_if = connection->app->id;
 	ev.conn_id = connection->id;
 	ev.status = status;
@@ -738,6 +750,13 @@ static void send_server_connection_notify(struct app_connection *connection,
 {
 	struct hal_ev_gatt_server_connection ev;
 
+	if (connection->app->func) {
+		connection->app->func(&connection->device->bdaddr,
+					connected ? 0 : -ENOTCONN,
+					connection->device->attrib);
+		return;
+	}
+
 	ev.server_if = connection->app->id;
 	ev.conn_id = connection->id;
 	ev.connected = connected;
@@ -751,7 +770,7 @@ static void send_server_connection_notify(struct app_connection *connection,
 static void send_app_disconnect_notify(struct app_connection *connection,
 								int32_t status)
 {
-	if (connection->app->type == APP_CLIENT)
+	if (connection->app->type == GATT_CLIENT)
 		send_client_disconnection_notify(connection, status);
 	else
 		send_server_connection_notify(connection, !!status);
@@ -760,9 +779,9 @@ static void send_app_disconnect_notify(struct app_connection *connection,
 static void send_app_connect_notify(struct app_connection *connection,
 								int32_t status)
 {
-	if (connection->app->type == APP_CLIENT)
+	if (connection->app->type == GATT_CLIENT)
 		send_client_connection_notify(connection, status);
-	else
+	else if (connection->app->type == GATT_SERVER)
 		send_server_connection_notify(connection, !status);
 }
 
@@ -3566,9 +3585,11 @@ static void handle_client_test_command(const void *buf, uint16_t len)
 	switch (cmd->command) {
 	case GATT_CLIENT_TEST_CMD_ENABLE:
 		if (cmd->u1) {
-			if (!test_client_if)
-				test_client_if = register_app(TEST_UUID,
-								APP_CLIENT);
+			if (!test_client_if) {
+				app = register_app(TEST_UUID, GATT_CLIENT);
+				if (app)
+					test_client_if = app->id;
+			}
 
 			if (test_client_if)
 				status = HAL_STATUS_SUCCESS;
@@ -3613,16 +3634,18 @@ static void handle_server_register(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_server_register *cmd = buf;
 	struct hal_ev_gatt_server_register ev;
+	struct gatt_app *app;
 
 	DBG("");
 
 	memset(&ev, 0, sizeof(ev));
 
-	ev.server_if = register_app(cmd->uuid, APP_SERVER);
+	app = register_app(cmd->uuid, GATT_SERVER);
 
-	if (ev.server_if)
+	if (app) {
+		ev.server_if = app->id;
 		ev.status = GATT_SUCCESS;
-	else
+	} else
 		ev.status = GATT_FAILURE;
 
 	memcpy(ev.uuid, cmd->uuid, sizeof(ev.uuid));
@@ -5963,3 +5986,66 @@ void bt_gatt_unregister(void)
 	bt_crypto_unref(crypto);
 	crypto = NULL;
 }
+
+
+unsigned int bt_gatt_register_app(const char *uuid, gatt_type_t type,
+							gatt_conn_cb_t func)
+{
+	struct gatt_app *app;
+	bt_uuid_t uuid128;
+
+	bt_string_to_uuid(&uuid128, uuid);
+	app = register_app((void *) &uuid128.value.u128, type);
+	if (!app)
+		return 0;
+
+	app->func = func;
+
+	return app->id;
+}
+
+bool bt_gatt_unregister_app(unsigned int id)
+{
+	uint8_t status;
+
+	status = unregister_app(id);
+
+	return status != HAL_STATUS_FAILED;
+}
+
+bool bt_gatt_connect_app(unsigned int id, const bdaddr_t *addr)
+{
+	uint8_t status;
+
+	status = handle_connect(id, addr);
+
+	return status != HAL_STATUS_FAILED;
+}
+
+bool bt_gatt_disconnect_app(unsigned int id, const bdaddr_t *addr)
+{
+	struct app_connection match;
+	struct app_connection *conn;
+	struct gatt_device *device;
+	struct gatt_app *app;
+
+	app = find_app_by_id(id);
+	if (!app)
+		return false;
+
+	device = find_device_by_addr(addr);
+	if (!device)
+		return false;
+
+	match.device = device;
+	match.app = app;
+
+	conn = queue_find(app_connections, match_connection_by_device_and_app,
+									&match);
+	if (!conn)
+		return false;
+
+	trigger_disconnection(conn);
+
+	return true;
+}
diff --git a/android/gatt.h b/android/gatt.h
index d4392d9..5ba9161 100644
--- a/android/gatt.h
+++ b/android/gatt.h
@@ -23,3 +23,18 @@
 
 bool bt_gatt_register(struct ipc *ipc, const bdaddr_t *addr);
 void bt_gatt_unregister(void);
+
+
+typedef enum {
+	GATT_CLIENT,
+	GATT_SERVER,
+} gatt_type_t;
+
+typedef void (*gatt_conn_cb_t)(const bdaddr_t *addr, int err, void *attrib);
+
+unsigned int bt_gatt_register_app(const char *uuid, gatt_type_t type,
+							gatt_conn_cb_t func);
+bool bt_gatt_unregister_app(unsigned int id);
+
+bool bt_gatt_connect_app(unsigned int id, const bdaddr_t *addr);
+bool bt_gatt_disconnect_app(unsigned int id, const bdaddr_t *addr);
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 02/11] android/bluetooth: Add bt_is_device_le function
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 03/11] android/hidhost: Add support for HoG Luiz Augusto von Dentz
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/bluetooth.c | 11 +++++++++++
 android/bluetooth.h |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index a864326..fac2637 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1386,6 +1386,17 @@ uint8_t bt_get_device_android_type(const bdaddr_t *addr)
 	return get_device_android_type(dev);
 }
 
+bool bt_is_device_le(const bdaddr_t *addr)
+{
+	struct device *dev;
+
+	dev = find_device(addr);
+	if (!dev)
+		return false;
+
+	return dev->le;
+}
+
 const char *bt_get_adapter_name(void)
 {
 	return adapter.name;
diff --git a/android/bluetooth.h b/android/bluetooth.h
index b4a5f32..2409d46 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -54,6 +54,8 @@ bool bt_le_set_advertising(bool advertising, bt_le_set_advertising_done cb,
 							void *user_data);
 
 uint8_t bt_get_device_android_type(const bdaddr_t *addr);
+bool bt_is_device_le(const bdaddr_t *addr);
+
 const char *bt_get_adapter_name(void);
 bool bt_device_is_bonded(const bdaddr_t *bdaddr);
 
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 03/11] android/hidhost: Add support for HoG
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 02/11] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 04/11] android/gatt: Fix not detecting device found by Bluetooth HAL Luiz Augusto von Dentz
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This enables using hidhost HAL for LE devices since this is how HoG is
implemented in Android.
---
 android/hidhost.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 115 insertions(+), 1 deletion(-)

diff --git a/android/hidhost.c b/android/hidhost.c
index 4a158c6..b8b36a9 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -48,6 +48,9 @@
 #include "hal-msg.h"
 #include "ipc-common.h"
 #include "ipc.h"
+#include "bluetooth.h"
+#include "gatt.h"
+#include "hog.h"
 #include "hidhost.h"
 #include "utils.h"
 
@@ -77,11 +80,14 @@
 /* HID Virtual Cable Unplug */
 #define HID_VIRTUAL_CABLE_UNPLUG	0x05
 
+#define HOG_UUID		"00001812-0000-1000-8000-00805f9b34fb"
+
 static bdaddr_t adapter_addr;
 
 static GIOChannel *ctrl_io = NULL;
 static GIOChannel *intr_io = NULL;
 static GSList *devices = NULL;
+static unsigned int hog_app = 0;
 
 static struct ipc *hal_ipc = NULL;
 
@@ -102,6 +108,7 @@ struct hid_device {
 	guint		intr_watch;
 	struct bt_uhid	*uhid;
 	uint8_t		last_hid_msg;
+	struct bt_hog	*hog;
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -131,6 +138,9 @@ static void hid_device_free(void *data)
 	if (dev->uhid)
 		bt_uhid_unref(dev->uhid);
 
+	if (dev->hog)
+		bt_hog_unref(dev->hog);
+
 	g_free(dev->rd_data);
 	g_free(dev);
 }
@@ -722,6 +732,69 @@ fail:
 	hid_device_remove(dev);
 }
 
+static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
+{
+	GSList *l;
+	struct hid_device *dev;
+
+	l = g_slist_find_custom(devices, addr, device_cmp);
+	dev = l ? l->data : NULL;
+
+	if (err < 0) {
+		if (!dev)
+			return;
+		goto fail;
+	}
+
+	if (!dev) {
+		dev = g_new0(struct hid_device, 1);
+		bacpy(&dev->dst, addr);
+		devices = g_slist_append(devices, dev);
+		bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTING);
+	}
+
+	if (!dev->hog) {
+		/* TODO: Get device details and primary */
+		dev->hog = bt_hog_new("bluez-input-device", dev->vendor,
+					dev->product, dev->version, NULL);
+		if (!dev->hog) {
+			error("HoG: unable to create session");
+			goto fail;
+		}
+	}
+
+	if (!bt_hog_attach(dev->hog, attrib)) {
+		error("HoG: unable to attach");
+		goto fail;
+	}
+
+	DBG("");
+
+	bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTED);
+
+	return;
+
+fail:
+	bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
+	hid_device_remove(dev);
+}
+
+static bool hog_connect(struct hid_device *dev)
+{
+	DBG("");
+
+	if (hog_app)
+		return bt_gatt_connect_app(hog_app, &dev->dst);
+
+	hog_app = bt_gatt_register_app(HOG_UUID, GATT_CLIENT, hog_conn_cb);
+	if (!hog_app) {
+		error("hidhost: bt_gatt_register_app failed");
+		return false;
+	}
+
+	return bt_gatt_connect_app(hog_app, &dev->dst);
+}
+
 static void bt_hid_connect(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_hidhost_connect *cmd = buf;
@@ -744,10 +817,19 @@ static void bt_hid_connect(const void *buf, uint16_t len)
 
 	dev = g_new0(struct hid_device, 1);
 	bacpy(&dev->dst, &dst);
+	dev->state = HAL_HIDHOST_STATE_DISCONNECTED;
 
 	ba2str(&dev->dst, addr);
 	DBG("connecting to %s", addr);
 
+	if (bt_is_device_le(&dst)) {
+		if (!hog_connect(dev)) {
+			status = HAL_STATUS_FAILED;
+			goto failed;
+		}
+		goto done;
+	}
+
 	sdp_uuid16_create(&uuid, PNP_INFO_SVCLASS_ID);
 	if (bt_search_service(&adapter_addr, &dev->dst, &uuid,
 				hid_sdp_did_search_cb, dev, NULL, 0) < 0) {
@@ -757,8 +839,11 @@ static void bt_hid_connect(const void *buf, uint16_t len)
 		goto failed;
 	}
 
+done:
 	devices = g_slist_append(devices, dev);
-	bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTING);
+
+	if (dev->state == HAL_HIDHOST_STATE_DISCONNECTED)
+		bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTING);
 
 	status = HAL_STATUS_SUCCESS;
 
@@ -767,6 +852,23 @@ failed:
 									status);
 }
 
+static bool hog_disconnect(struct hid_device *dev)
+{
+	DBG("");
+
+	if (dev->state == HAL_HIDHOST_STATE_DISCONNECTED)
+		return false;
+
+	bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTING);
+
+	if (!bt_gatt_disconnect_app(hog_app, &dev->dst)) {
+		bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED);
+		hid_device_remove(dev);
+	}
+
+	return true;
+}
+
 static void bt_hid_disconnect(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_hidhost_disconnect *cmd = buf;
@@ -786,6 +888,13 @@ static void bt_hid_disconnect(const void *buf, uint16_t len)
 	}
 
 	dev = l->data;
+	if (bt_is_device_le(&dst)) {
+		if (!hog_disconnect(dev)) {
+			status = HAL_STATUS_FAILED;
+			goto failed;
+		}
+		goto done;
+	}
 
 	/* Wait either channels to HUP */
 	if (dev->intr_io)
@@ -796,6 +905,8 @@ static void bt_hid_disconnect(const void *buf, uint16_t len)
 
 	bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTING);
 
+
+done:
 	status = HAL_STATUS_SUCCESS;
 
 failed:
@@ -1342,6 +1453,9 @@ void bt_hid_unregister(void)
 {
 	DBG("");
 
+	if (hog_app > 0)
+		bt_gatt_unregister_app(hog_app);
+
 	g_slist_free_full(devices, hid_device_free);
 	devices = NULL;
 
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 04/11] android/gatt: Fix not detecting device found by Bluetooth HAL
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 02/11] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 03/11] android/hidhost: Add support for HoG Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 05/11] android/gatt: Create device and connect bonded devices Luiz Augusto von Dentz
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This is necessary so that devices found during regular discovery can be
handled by gatt HAL.
---
 android/bluetooth.c |  42 ++++++++++++++--------
 android/bluetooth.h |   5 ++-
 android/gatt.c      | 101 +++++++++++++++++++++++++++++-----------------------
 3 files changed, 88 insertions(+), 60 deletions(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index fac2637..4ec7c7a 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -179,6 +179,7 @@ static struct {
 	uint32_t current_settings;
 	uint32_t supported_settings;
 
+	bool le_scanning;
 	uint8_t cur_discovery_type;
 	uint8_t exp_discovery_type;
 	uint32_t discoverable_timeout;
@@ -1301,10 +1302,8 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
 	}
 
 	type = adapter.exp_discovery_type;
-	adapter.exp_discovery_type = SCAN_TYPE_NONE;
-
-	if (type == SCAN_TYPE_NONE && gatt_device_found_cb)
-		type = SCAN_TYPE_LE;
+	adapter.exp_discovery_type = adapter.le_scanning ? SCAN_TYPE_LE :
+								SCAN_TYPE_NONE;
 
 	if (type != SCAN_TYPE_NONE)
 		start_discovery(type);
@@ -3512,42 +3511,57 @@ bool bt_le_set_advertising(bool advertising, bt_le_set_advertising_done cb,
 	return false;
 }
 
+bool bt_le_register(bt_le_device_found cb)
+{
+	if (gatt_device_found_cb)
+		return false;
+
+	gatt_device_found_cb = cb;
+
+	return true;
+}
+
+void bt_le_unregister(void)
+{
+	gatt_device_found_cb = NULL;
+}
+
 bool bt_le_discovery_stop(bt_le_discovery_stopped cb)
 {
+	if (!(adapter.current_settings & MGMT_SETTING_POWERED))
+		return false;
+
+	adapter.le_scanning = false;
+
 	if (adapter.cur_discovery_type != SCAN_TYPE_LE) {
 		if (cb)
 			cb();
 
-		gatt_device_found_cb = NULL;
-
 		return true;
 	}
 
 	if (!stop_discovery(SCAN_TYPE_LE))
 		return false;
 
-	gatt_device_found_cb = NULL;
 	gatt_discovery_stopped_cb = cb;
 	adapter.exp_discovery_type = SCAN_TYPE_NONE;
 
 	return true;
 }
 
-bool bt_le_discovery_start(bt_le_device_found cb)
+bool bt_le_discovery_start(void)
 {
 	if (!(adapter.current_settings & MGMT_SETTING_POWERED))
 		return false;
 
+	adapter.le_scanning = true;
+
 	/* If core is discovering, don't bother */
-	if (adapter.cur_discovery_type != SCAN_TYPE_NONE) {
-		gatt_device_found_cb = cb;
+	if (adapter.cur_discovery_type != SCAN_TYPE_NONE)
 		return true;
-	}
 
-	if (start_discovery(SCAN_TYPE_LE)) {
-		gatt_device_found_cb = cb;
+	if (start_discovery(SCAN_TYPE_LE))
 		return true;
-	}
 
 	return false;
 }
diff --git a/android/bluetooth.h b/android/bluetooth.h
index 2409d46..7c64bab 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -44,7 +44,10 @@ typedef void (*bt_le_device_found)(const bdaddr_t *addr, uint8_t addr_type,
 					int rssi, uint16_t eir_len,
 					const void *eir, bool discoverable,
 					bool bonded);
-bool bt_le_discovery_start(bt_le_device_found cb);
+bool bt_le_register(bt_le_device_found cb);
+void bt_le_unregister(void);
+
+bool bt_le_discovery_start(void);
 
 typedef void (*bt_le_discovery_stopped)(void);
 bool bt_le_discovery_stop(bt_le_discovery_stopped cb);
diff --git a/android/gatt.c b/android/gatt.c
index a2314e0..13d03e8 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -627,6 +627,47 @@ static void destroy_gatt_app(void *data)
 	free(app);
 }
 
+static void le_device_found_handler(const bdaddr_t *addr, uint8_t addr_type,
+						int rssi, uint16_t eir_len,
+						const void *eir,
+						bool discoverable, bool bonded)
+{
+	uint8_t buf[IPC_MTU];
+	struct hal_ev_gatt_client_scan_result *ev = (void *) buf;
+	struct gatt_device *dev;
+	char bda[18];
+
+	if (!scanning || (!discoverable && !bonded))
+		goto connect;
+
+	ba2str(addr, bda);
+	DBG("LE Device found: %s, rssi: %d, adv_data: %d", bda, rssi, !!eir);
+
+	bdaddr2android(addr, ev->bda);
+	ev->rssi = rssi;
+	ev->len = eir_len;
+
+	memcpy(ev->adv_data, eir, ev->len);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+						HAL_EV_GATT_CLIENT_SCAN_RESULT,
+						sizeof(*ev) + ev->len, ev);
+
+connect:
+	dev = find_device_by_addr(addr);
+	if (!dev || (dev->state != DEVICE_CONNECT_INIT))
+		return;
+
+	device_set_state(dev, DEVICE_CONNECT_READY);
+	dev->bdaddr_type = addr_type;
+
+	/*
+	 * We are ok to perform connect now. Stop discovery
+	 * and once it is stopped continue with creating ACL
+	 */
+	bt_le_discovery_stop(bt_le_discovery_stop_cb);
+}
+
 static struct gatt_app *register_app(const uint8_t *uuid, gatt_type_t type)
 {
 	static int32_t application_id = 1;
@@ -955,47 +996,6 @@ static struct service *create_service(uint8_t id, bool primary, char *uuid,
 	return s;
 }
 
-static void le_device_found_handler(const bdaddr_t *addr, uint8_t addr_type,
-						int rssi, uint16_t eir_len,
-						const void *eir,
-						bool discoverable, bool bonded)
-{
-	uint8_t buf[IPC_MTU];
-	struct hal_ev_gatt_client_scan_result *ev = (void *) buf;
-	struct gatt_device *dev;
-	char bda[18];
-
-	if (!scanning || (!discoverable && !bonded))
-		goto connect;
-
-	ba2str(addr, bda);
-	DBG("LE Device found: %s, rssi: %d, adv_data: %d", bda, rssi, !!eir);
-
-	bdaddr2android(addr, ev->bda);
-	ev->rssi = rssi;
-	ev->len = eir_len;
-
-	memcpy(ev->adv_data, eir, ev->len);
-
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-						HAL_EV_GATT_CLIENT_SCAN_RESULT,
-						sizeof(*ev) + ev->len, ev);
-
-connect:
-	dev = find_device_by_addr(addr);
-	if (!dev || (dev->state != DEVICE_CONNECT_INIT))
-		return;
-
-	device_set_state(dev, DEVICE_CONNECT_READY);
-	dev->bdaddr_type = addr_type;
-
-	/*
-	 * We are ok to perform connect now. Stop discovery
-	 * and once it is stopped continue with creating ACL
-	 */
-	bt_le_discovery_stop(bt_le_discovery_stop_cb);
-}
-
 static gboolean disconnected_cb(GIOChannel *io, GIOCondition cond,
 							gpointer user_data)
 {
@@ -1206,7 +1206,7 @@ reply:
 
 	/* Check if we should restart scan */
 	if (scanning)
-		bt_le_discovery_start(le_device_found_handler);
+		bt_le_discovery_start();
 
 	/* FIXME: What to do if discovery won't start here. */
 }
@@ -1292,7 +1292,7 @@ static void handle_client_scan(const void *buf, uint16_t len)
 	}
 
 	/* Turn on scan */
-	if (!bt_le_discovery_start(le_device_found_handler)) {
+	if (!bt_le_discovery_start()) {
 		error("gatt: LE scan switch failed");
 		status = HAL_STATUS_FAILED;
 		goto reply;
@@ -1324,7 +1324,7 @@ static void bt_le_discovery_stop_cb(void)
 
 	/* Check now if there is any device ready to connect */
 	if (connect_next_dev() < 0)
-		bt_le_discovery_start(le_device_found_handler);
+		bt_le_discovery_start();
 }
 
 static struct gatt_device *create_device(const bdaddr_t *addr)
@@ -1433,7 +1433,7 @@ static bool trigger_connection(struct app_connection *connection)
 
 	/* after state change trigger discovering */
 	if (!scanning && (connection->device->state == DEVICE_CONNECT_INIT))
-		if (!bt_le_discovery_start(le_device_found_handler)) {
+		if (!bt_le_discovery_start()) {
 			error("gatt: Could not start scan");
 
 			return false;
@@ -5901,6 +5901,15 @@ bool bt_gatt_register(struct ipc *ipc, const bdaddr_t *addr)
 	if (!start_listening_io())
 		return false;
 
+	if (!bt_le_register(le_device_found_handler)) {
+		error("gatt: bt_le_register failed");
+
+		g_io_channel_unref(listening_io);
+		listening_io = NULL;
+
+		return false;
+	}
+
 	crypto = bt_crypto_new();
 	if (!crypto) {
 		error("gatt: Failed to setup crypto");
@@ -5985,6 +5994,8 @@ void bt_gatt_unregister(void)
 
 	bt_crypto_unref(crypto);
 	crypto = NULL;
+
+	bt_le_unregister();
 }
 
 
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 05/11] android/gatt: Create device and connect bonded devices
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (2 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 04/11] android/gatt: Fix not detecting device found by Bluetooth HAL Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 06/11] android/bluetooth: Add bt_device_set_uuids Luiz Augusto von Dentz
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Devices bonded should be connected so later their services can be
discovered.
---
 android/gatt.c | 615 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 312 insertions(+), 303 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 13d03e8..ac204c0 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -627,141 +627,100 @@ static void destroy_gatt_app(void *data)
 	free(app);
 }
 
-static void le_device_found_handler(const bdaddr_t *addr, uint8_t addr_type,
-						int rssi, uint16_t eir_len,
-						const void *eir,
-						bool discoverable, bool bonded)
-{
-	uint8_t buf[IPC_MTU];
-	struct hal_ev_gatt_client_scan_result *ev = (void *) buf;
-	struct gatt_device *dev;
-	char bda[18];
-
-	if (!scanning || (!discoverable && !bonded))
-		goto connect;
-
-	ba2str(addr, bda);
-	DBG("LE Device found: %s, rssi: %d, adv_data: %d", bda, rssi, !!eir);
-
-	bdaddr2android(addr, ev->bda);
-	ev->rssi = rssi;
-	ev->len = eir_len;
+enum pend_req_state {
+	REQUEST_INIT,
+	REQUEST_PENDING,
+	REQUEST_DONE,
+};
 
-	memcpy(ev->adv_data, eir, ev->len);
+struct pending_request {
+	uint16_t handle;
+	int length;
+	uint8_t *value;
+	uint16_t offset;
 
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-						HAL_EV_GATT_CLIENT_SCAN_RESULT,
-						sizeof(*ev) + ev->len, ev);
+	uint8_t *filter_value;
+	uint16_t filter_vlen;
 
-connect:
-	dev = find_device_by_addr(addr);
-	if (!dev || (dev->state != DEVICE_CONNECT_INIT))
-		return;
+	enum pend_req_state state;
+	uint8_t error;
+};
 
-	device_set_state(dev, DEVICE_CONNECT_READY);
-	dev->bdaddr_type = addr_type;
+static void destroy_pending_request(void *data)
+{
+	struct pending_request *entry = data;
 
-	/*
-	 * We are ok to perform connect now. Stop discovery
-	 * and once it is stopped continue with creating ACL
-	 */
-	bt_le_discovery_stop(bt_le_discovery_stop_cb);
+	free(entry->value);
+	free(entry->filter_value);
+	free(entry);
 }
 
-static struct gatt_app *register_app(const uint8_t *uuid, gatt_type_t type)
+static void destroy_device(void *data)
 {
-	static int32_t application_id = 1;
-	struct gatt_app *app;
-
-	if (queue_find(gatt_apps, match_app_by_uuid, uuid)) {
-		error("gatt: app uuid is already on list");
-		return NULL;
-	}
-
-	app = new0(struct gatt_app, 1);
-	if (!app) {
-		error("gatt: Cannot allocate memory for registering app");
-		return 0;
-	}
-
-	app->type = type;
+	struct gatt_device *dev = data;
 
-	if (app->type == GATT_CLIENT) {
-		app->notifications = queue_new();
-		if (!app->notifications) {
-			error("gatt: couldn't allocate notifications queue");
-			destroy_gatt_app(app);
-			return NULL;
-		}
-	}
+	if (!dev)
+		return;
 
-	memcpy(app->uuid, uuid, sizeof(app->uuid));
+	queue_destroy(dev->services, destroy_service);
+	queue_destroy(dev->pending_requests, destroy_pending_request);
 
-	app->id = application_id++;
+	free(dev);
+}
 
-	if (!queue_push_head(gatt_apps, app)) {
-		error("gatt: Cannot push app on the list");
-		destroy_gatt_app(app);
+static struct gatt_device *device_ref(struct gatt_device *device)
+{
+	if (!device)
 		return NULL;
-	}
 
-	if ((app->type == GATT_SERVER) &&
-			!queue_push_tail(listen_apps, INT_TO_PTR(app->id))) {
-		error("gatt: Cannot push server on the list");
-		destroy_gatt_app(app);
-		return NULL;
-	}
+	device->ref++;
 
-	return app;
+	return device;
 }
 
-static void handle_client_register(const void *buf, uint16_t len)
+static void device_unref(struct gatt_device *device)
 {
-	const struct hal_cmd_gatt_client_register *cmd = buf;
-	struct hal_ev_gatt_client_register_client ev;
-	struct gatt_app *app;
-
-	DBG("");
+	if (!device)
+		return;
 
-	memset(&ev, 0, sizeof(ev));
+	if (--device->ref)
+		return;
 
-	app = register_app(cmd->uuid, GATT_CLIENT);
+	destroy_device(device);
+}
 
-	if (app) {
-		ev.client_if = app->id;
-		ev.status = GATT_SUCCESS;
-	} else
-		ev.status = GATT_FAILURE;
+static struct gatt_device *create_device(const bdaddr_t *addr)
+{
+	struct gatt_device *dev;
 
-	/* We should send notification with given in cmd UUID */
-	memcpy(ev.app_uuid, cmd->uuid, sizeof(ev.app_uuid));
+	dev = new0(struct gatt_device, 1);
+	if (!dev)
+		return NULL;
 
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-			HAL_EV_GATT_CLIENT_REGISTER_CLIENT, sizeof(ev), &ev);
+	bacpy(&dev->bdaddr, addr);
 
-	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT, HAL_OP_GATT_CLIENT_REGISTER,
-							HAL_STATUS_SUCCESS);
-}
+	dev->services = queue_new();
+	if (!dev->services) {
+		error("gatt: Failed to allocate memory for client");
+		destroy_device(dev);
+		return NULL;
+	}
 
-static void send_client_disconnection_notify(struct app_connection *connection,
-								int32_t status)
-{
-	struct hal_ev_gatt_client_disconnect ev;
 
-	if (connection->app->func) {
-		connection->app->func(&connection->device->bdaddr, -ENOTCONN,
-						connection->device->attrib);
-		return;
+	dev->pending_requests = queue_new();
+	if (!dev->pending_requests) {
+		error("gatt: Failed to allocate memory for client");
+		destroy_device(dev);
+		return NULL;
 	}
 
-	ev.client_if = connection->app->id;
-	ev.conn_id = connection->id;
-	ev.status = status;
-
-	bdaddr2android(&connection->device->bdaddr, &ev.bda);
+	if (!queue_push_head(gatt_devices, dev)) {
+		error("gatt: Cannot push device to queue");
+		destroy_device(dev);
+		return NULL;
+	}
 
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-				HAL_EV_GATT_CLIENT_DISCONNECT, sizeof(ev), &ev);
+	return device_ref(dev);
 }
 
 static void send_client_connection_notify(struct app_connection *connection,
@@ -808,6 +767,28 @@ static void send_server_connection_notify(struct app_connection *connection,
 				HAL_EV_GATT_SERVER_CONNECTION, sizeof(ev), &ev);
 }
 
+static void send_client_disconnection_notify(struct app_connection *connection,
+								int32_t status)
+{
+	struct hal_ev_gatt_client_disconnect ev;
+
+	if (connection->app->func) {
+		connection->app->func(&connection->device->bdaddr, -ENOTCONN,
+						connection->device->attrib);
+		return;
+	}
+
+	ev.client_if = connection->app->id;
+	ev.conn_id = connection->id;
+	ev.status = status;
+
+	bdaddr2android(&connection->device->bdaddr, &ev.bda);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+				HAL_EV_GATT_CLIENT_DISCONNECT, sizeof(ev), &ev);
+
+}
+
 static void send_app_disconnect_notify(struct app_connection *connection,
 								int32_t status)
 {
@@ -841,69 +822,7 @@ static void disconnect_notify_by_device(void *data, void *user_data)
 		send_app_connect_notify(conn, GATT_FAILURE);
 }
 
-enum pend_req_state {
-	REQUEST_INIT,
-	REQUEST_PENDING,
-	REQUEST_DONE,
-};
-
-struct pending_request {
-	uint16_t handle;
-	int length;
-	uint8_t *value;
-	uint16_t offset;
-
-	uint8_t *filter_value;
-	uint16_t filter_vlen;
-
-	enum pend_req_state state;
-	uint8_t error;
-};
-
-static void destroy_pending_request(void *data)
-{
-	struct pending_request *entry = data;
-
-	free(entry->value);
-	free(entry->filter_value);
-	free(entry);
-}
-
-static void destroy_device(void *data)
-{
-	struct gatt_device *dev = data;
-
-	if (!dev)
-		return;
-
-	queue_destroy(dev->services, destroy_service);
-	queue_destroy(dev->pending_requests, destroy_pending_request);
-
-	free(dev);
-}
-
-static struct gatt_device *device_ref(struct gatt_device *device)
-{
-	if (!device)
-		return NULL;
-
-	device->ref++;
-
-	return device;
-}
-
-static void device_unref(struct gatt_device *device)
-{
-	if (!device)
-		return;
-
-	if (--device->ref)
-		return;
-
-	destroy_device(device);
-}
-
-static void destroy_app_connection(void *data)
+static void destroy_connection(void *data)
 {
 	struct app_connection *conn = data;
 
@@ -927,73 +846,7 @@ static void device_disconnect_clients(struct gatt_device *dev)
 
 	/* Remove all clients by given device's */
 	queue_remove_all(app_connections, match_connection_by_device, dev,
-							destroy_app_connection);
-}
-
-static void send_client_primary_notify(void *data, void *user_data)
-{
-	struct hal_ev_gatt_client_search_result ev;
-	struct service *p = data;
-	int32_t conn_id = PTR_TO_INT(user_data);
-
-	/* In service queue we will have also included services */
-	if (!p->primary)
-		return;
-
-	ev.conn_id  = conn_id;
-	element_id_to_hal_srvc_id(&p->id, 1, &ev.srvc_id);
-
-	uuid2android(&p->id.uuid, ev.srvc_id.uuid);
-
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-			HAL_EV_GATT_CLIENT_SEARCH_RESULT, sizeof(ev), &ev);
-}
-
-static struct service *create_service(uint8_t id, bool primary, char *uuid,
-								void *data)
-{
-	struct service *s;
-
-	s = new0(struct service, 1);
-	if (!s) {
-		error("gatt: Cannot allocate memory for gatt_primary");
-		return NULL;
-	}
-
-	s->chars = queue_new();
-	if (!s->chars) {
-		error("gatt: Cannot allocate memory for char cache");
-		free(s);
-		return NULL;
-	}
-
-	if (bt_string_to_uuid(&s->id.uuid, uuid) < 0) {
-		error("gatt: Cannot convert string to uuid");
-		queue_destroy(s->chars, NULL);
-		free(s);
-		return NULL;
-	}
-
-	s->id.instance = id;
-
-	/* Put primary service to our local list */
-	s->primary = primary;
-	if (s->primary) {
-		memcpy(&s->prim, data, sizeof(s->prim));
-	} else {
-		memcpy(&s->incl, data, sizeof(s->incl));
-		return s;
-	}
-
-	/* For primary service allocate queue for included services */
-	s->included = queue_new();
-	if (!s->included) {
-		queue_destroy(s->chars, NULL);
-		free(s);
-		return NULL;
-	}
-
-	return s;
+							destroy_connection);
 }
 
 static gboolean disconnected_cb(GIOChannel *io, GIOCondition cond,
@@ -1013,20 +866,6 @@ static gboolean disconnected_cb(GIOChannel *io, GIOCondition cond,
 	return FALSE;
 }
 
-struct connect_data {
-	struct gatt_device *dev;
-	int32_t status;
-};
-
-static void send_app_connect_notifications(void *data, void *user_data)
-{
-	struct app_connection *conn = data;
-	struct connect_data *con_data = user_data;
-
-	if (conn->device == con_data->dev)
-		send_app_connect_notify(conn, con_data->status);
-}
-
 static void att_handler(const uint8_t *ipdu, uint16_t len, gpointer user_data);
 
 static void exchange_mtu_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -1126,8 +965,22 @@ static void notify_att_range_change(struct gatt_device *dev,
 		break;
 	}
 
-	if (length)
-		g_attrib_send(dev->attrib, 0, pdu, length, NULL, NULL, NULL);
+	if (length)
+		g_attrib_send(dev->attrib, 0, pdu, length, NULL, NULL, NULL);
+}
+
+struct connect_data {
+	struct gatt_device *dev;
+	int32_t status;
+};
+
+static void send_app_connect_notifications(void *data, void *user_data)
+{
+	struct app_connection *conn = data;
+	struct connect_data *con_data = user_data;
+
+	if (conn->device == con_data->dev)
+		send_app_connect_notify(conn, con_data->status);
 }
 
 static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
@@ -1257,6 +1110,208 @@ static int connect_le(struct gatt_device *dev)
 	return 0;
 }
 
+static int connect_next_dev(void)
+{
+	struct gatt_device *dev;
+
+	DBG("");
+
+	dev = find_device_by_state(DEVICE_CONNECT_READY);
+	if (!dev)
+		return -ENODEV;
+
+	return connect_le(dev);
+}
+
+static void le_device_found_handler(const bdaddr_t *addr, uint8_t addr_type,
+						int rssi, uint16_t eir_len,
+						const void *eir,
+						bool discoverable, bool bonded)
+{
+	uint8_t buf[IPC_MTU];
+	struct hal_ev_gatt_client_scan_result *ev = (void *) buf;
+	struct gatt_device *dev;
+	char bda[18];
+
+	if (!scanning || (!discoverable && !bonded))
+		goto connect;
+
+	ba2str(addr, bda);
+	DBG("LE Device found: %s, rssi: %d, adv_data: %d", bda, rssi, !!eir);
+
+	bdaddr2android(addr, ev->bda);
+	ev->rssi = rssi;
+	ev->len = eir_len;
+
+	memcpy(ev->adv_data, eir, ev->len);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+						HAL_EV_GATT_CLIENT_SCAN_RESULT,
+						sizeof(*ev) + ev->len, ev);
+
+connect:
+	dev = find_device_by_addr(addr);
+	if (!dev) {
+		if (!bonded)
+			return;
+
+		dev = create_device(addr);
+	}
+
+	if (!dev || dev->state != DEVICE_CONNECT_INIT)
+		return;
+
+	device_set_state(dev, DEVICE_CONNECT_READY);
+	dev->bdaddr_type = addr_type;
+
+	/*
+	 * We are ok to perform connect now. Stop discovery
+	 * and once it is stopped continue with creating ACL
+	 */
+	bt_le_discovery_stop(bt_le_discovery_stop_cb);
+}
+
+static struct gatt_app *register_app(const uint8_t *uuid, gatt_type_t type)
+{
+	static int32_t application_id = 1;
+	struct gatt_app *app;
+
+	if (queue_find(gatt_apps, match_app_by_uuid, uuid)) {
+		error("gatt: app uuid is already on list");
+		return NULL;
+	}
+
+	app = new0(struct gatt_app, 1);
+	if (!app) {
+		error("gatt: Cannot allocate memory for registering app");
+		return 0;
+	}
+
+	app->type = type;
+
+	if (app->type == GATT_CLIENT) {
+		app->notifications = queue_new();
+		if (!app->notifications) {
+			error("gatt: couldn't allocate notifications queue");
+			destroy_gatt_app(app);
+			return NULL;
+		}
+	}
+
+	memcpy(app->uuid, uuid, sizeof(app->uuid));
+
+	app->id = application_id++;
+
+	if (!queue_push_head(gatt_apps, app)) {
+		error("gatt: Cannot push app on the list");
+		destroy_gatt_app(app);
+		return NULL;
+	}
+
+	if ((app->type == GATT_SERVER) &&
+			!queue_push_tail(listen_apps, INT_TO_PTR(app->id))) {
+		error("gatt: Cannot push server on the list");
+		destroy_gatt_app(app);
+		return NULL;
+	}
+
+	return app;
+}
+
+static void handle_client_register(const void *buf, uint16_t len)
+{
+	const struct hal_cmd_gatt_client_register *cmd = buf;
+	struct hal_ev_gatt_client_register_client ev;
+	struct gatt_app *app;
+
+	DBG("");
+
+	memset(&ev, 0, sizeof(ev));
+
+	app = register_app(cmd->uuid, GATT_CLIENT);
+
+	if (app) {
+		ev.client_if = app->id;
+		ev.status = GATT_SUCCESS;
+	} else
+		ev.status = GATT_FAILURE;
+
+	/* We should send notification with given in cmd UUID */
+	memcpy(ev.app_uuid, cmd->uuid, sizeof(ev.app_uuid));
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+			HAL_EV_GATT_CLIENT_REGISTER_CLIENT, sizeof(ev), &ev);
+
+	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT, HAL_OP_GATT_CLIENT_REGISTER,
+							HAL_STATUS_SUCCESS);
+}
+
+static void send_client_primary_notify(void *data, void *user_data)
+{
+	struct hal_ev_gatt_client_search_result ev;
+	struct service *p = data;
+	int32_t conn_id = PTR_TO_INT(user_data);
+
+	/* In service queue we will have also included services */
+	if (!p->primary)
+		return;
+
+	ev.conn_id  = conn_id;
+	element_id_to_hal_srvc_id(&p->id, 1, &ev.srvc_id);
+
+	uuid2android(&p->id.uuid, ev.srvc_id.uuid);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+			HAL_EV_GATT_CLIENT_SEARCH_RESULT, sizeof(ev), &ev);
+}
+
+static struct service *create_service(uint8_t id, bool primary, char *uuid,
+								void *data)
+{
+	struct service *s;
+
+	s = new0(struct service, 1);
+	if (!s) {
+		error("gatt: Cannot allocate memory for gatt_primary");
+		return NULL;
+	}
+
+	s->chars = queue_new();
+	if (!s->chars) {
+		error("gatt: Cannot allocate memory for char cache");
+		free(s);
+		return NULL;
+	}
+
+	if (bt_string_to_uuid(&s->id.uuid, uuid) < 0) {
+		error("gatt: Cannot convert string to uuid");
+		queue_destroy(s->chars, NULL);
+		free(s);
+		return NULL;
+	}
+
+	s->id.instance = id;
+
+	/* Put primary service to our local list */
+	s->primary = primary;
+	if (s->primary) {
+		memcpy(&s->prim, data, sizeof(s->prim));
+	} else {
+		memcpy(&s->incl, data, sizeof(s->incl));
+		return s;
+	}
+
+	/* For primary service allocate queue for included services */
+	s->included = queue_new();
+	if (!s->included) {
+		queue_destroy(s->chars, NULL);
+		free(s);
+		return NULL;
+	}
+
+	return s;
+}
+
 static void handle_client_scan(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_client_scan *cmd = buf;
@@ -1305,19 +1360,6 @@ reply:
 									status);
 }
 
-static int connect_next_dev(void)
-{
-	struct gatt_device *dev;
-
-	DBG("");
-
-	dev = find_device_by_state(DEVICE_CONNECT_READY);
-	if (!dev)
-		return -ENODEV;
-
-	return connect_le(dev);
-}
-
 static void bt_le_discovery_stop_cb(void)
 {
 	DBG("");
@@ -1327,40 +1369,7 @@ static void bt_le_discovery_stop_cb(void)
 		bt_le_discovery_start();
 }
 
-static struct gatt_device *create_device(const bdaddr_t *addr)
-{
-	struct gatt_device *dev;
-
-	dev = new0(struct gatt_device, 1);
-	if (!dev)
-		return NULL;
-
-	bacpy(&dev->bdaddr, addr);
-
-	dev->services = queue_new();
-	if (!dev->services) {
-		error("gatt: Failed to allocate memory for client");
-		destroy_device(dev);
-		return NULL;
-	}
-
-	dev->pending_requests = queue_new();
-	if (!dev->pending_requests) {
-		error("gatt: Failed to allocate memory for client");
-		destroy_device(dev);
-		return NULL;
-	}
-
-	if (!queue_push_head(gatt_devices, dev)) {
-		error("gatt: Cannot push device to queue");
-		destroy_device(dev);
-		return NULL;
-	}
-
-	return device_ref(dev);
-}
-
-static struct app_connection *create_app_connection(struct gatt_device *device,
+static struct app_connection *create_connection(struct gatt_device *device,
 						struct gatt_app *app)
 {
 	struct app_connection *new_conn;
@@ -1400,7 +1409,7 @@ static void trigger_disconnection(struct app_connection *connection)
 	if (queue_remove(app_connections, connection))
 			send_app_disconnect_notify(connection, GATT_SUCCESS);
 
-	destroy_app_connection(connection);
+	destroy_connection(connection);
 }
 
 static void app_disconnect_devices(struct gatt_app *client)
@@ -1526,7 +1535,7 @@ static uint8_t handle_connect(int32_t app_id, const bdaddr_t *addr)
 	conn = queue_find(app_connections, match_connection_by_device_and_app,
 								&conn_match);
 	if (!conn) {
-		conn = create_app_connection(device, app);
+		conn = create_connection(device, app);
 		if (!conn)
 			return HAL_STATUS_NOMEM;
 	}
@@ -5508,7 +5517,7 @@ static void create_listen_connections(void *data, void *user_data)
 
 	app = find_app_by_id(id);
 	if (app)
-		create_app_connection(dev, app);
+		create_connection(dev, app);
 }
 
 static void connect_confirm(GIOChannel *io, void *user_data)
@@ -5977,7 +5986,7 @@ void bt_gatt_unregister(void)
 	queue_destroy(gatt_apps, destroy_gatt_app);
 	gatt_apps = NULL;
 
-	queue_destroy(app_connections, destroy_app_connection);
+	queue_destroy(app_connections, destroy_connection);
 	app_connections = NULL;
 
 	queue_destroy(gatt_devices, destroy_device);
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 06/11] android/bluetooth: Add bt_device_set_uuids
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (3 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 05/11] android/gatt: Create device and connect bonded devices Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 07/11] android/gatt: Automatically discover primary services for bonded devices Luiz Augusto von Dentz
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/bluetooth.c | 13 +++++++++++++
 android/bluetooth.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 4ec7c7a..9d17faa 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1409,6 +1409,19 @@ bool bt_device_is_bonded(const bdaddr_t *bdaddr)
 	return false;
 }
 
+bool bt_device_set_uuids(const bdaddr_t *addr, GSList *uuids)
+{
+	struct device *dev;
+
+	dev = find_device(addr);
+	if (!dev)
+		return false;
+
+	set_device_uuids(dev, uuids);
+
+	return true;
+}
+
 static bool rssi_above_threshold(int old, int new)
 {
 	/* only 8 dBm or more */
diff --git a/android/bluetooth.h b/android/bluetooth.h
index 7c64bab..eb50fe1 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -61,6 +61,7 @@ bool bt_is_device_le(const bdaddr_t *addr);
 
 const char *bt_get_adapter_name(void);
 bool bt_device_is_bonded(const bdaddr_t *bdaddr);
+bool bt_device_set_uuids(const bdaddr_t *bdaddr, GSList *uuids);
 
 typedef void (*bt_read_device_rssi_done)(uint8_t status, const bdaddr_t *addr,
 						int8_t rssi, void *user_data);
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 07/11] android/gatt: Automatically discover primary services for bonded devices
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (4 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 06/11] android/bluetooth: Add bt_device_set_uuids Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 08/11] android/gatt: Do not disconnect immediately after discovering primaries Luiz Augusto von Dentz
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

---
 android/gatt.c | 637 ++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 353 insertions(+), 284 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index ac204c0..0a8684e 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -792,6 +792,9 @@ static void send_client_disconnection_notify(struct app_connection *connection,
 static void send_app_disconnect_notify(struct app_connection *connection,
 								int32_t status)
 {
+	if (!connection->app)
+		return;
+
 	if (connection->app->type == GATT_CLIENT)
 		send_client_disconnection_notify(connection, status);
 	else
@@ -801,6 +804,9 @@ static void send_app_disconnect_notify(struct app_connection *connection,
 static void send_app_connect_notify(struct app_connection *connection,
 								int32_t status)
 {
+	if (!connection->app)
+		return;
+
 	if (connection->app->type == GATT_CLIENT)
 		send_client_connection_notify(connection, status);
 	else if (connection->app->type == GATT_SERVER)
@@ -812,7 +818,7 @@ static void disconnect_notify_by_device(void *data, void *user_data)
 	struct app_connection *conn = data;
 	struct gatt_device *dev = user_data;
 
-	if (dev != conn->device)
+	if (dev != conn->device || !conn->app)
 		return;
 
 	if (dev->state == DEVICE_CONNECTED)
@@ -969,6 +975,317 @@ static void notify_att_range_change(struct gatt_device *dev,
 		g_attrib_send(dev->attrib, 0, pdu, length, NULL, NULL, NULL);
 }
 
+static struct app_connection *create_connection(struct gatt_device *device,
+						struct gatt_app *app)
+{
+	struct app_connection *new_conn;
+	static int32_t last_conn_id = 1;
+
+	/* Check if already connected */
+	new_conn = new0(struct app_connection, 1);
+	if (!new_conn)
+		return NULL;
+
+	/* Make connection id unique to connection record (app, device) pair */
+	new_conn->app = app;
+	new_conn->id = last_conn_id++;
+
+	new_conn->transactions = queue_new();
+	if (!new_conn->transactions) {
+		free(new_conn);
+		return NULL;
+	}
+
+	if (!queue_push_head(app_connections, new_conn)) {
+		error("gatt: Cannot push client on the client queue!?");
+		queue_destroy(new_conn->transactions, free);
+		free(new_conn);
+		return NULL;
+	}
+
+	new_conn->device = device_ref(device);
+	new_conn->device->conn_cnt++;
+
+	return new_conn;
+}
+
+static struct service *create_service(uint8_t id, bool primary, char *uuid,
+								void *data)
+{
+	struct service *s;
+
+	s = new0(struct service, 1);
+	if (!s) {
+		error("gatt: Cannot allocate memory for gatt_primary");
+		return NULL;
+	}
+
+	s->chars = queue_new();
+	if (!s->chars) {
+		error("gatt: Cannot allocate memory for char cache");
+		free(s);
+		return NULL;
+	}
+
+	if (bt_string_to_uuid(&s->id.uuid, uuid) < 0) {
+		error("gatt: Cannot convert string to uuid");
+		queue_destroy(s->chars, NULL);
+		free(s);
+		return NULL;
+	}
+
+	s->id.instance = id;
+
+	/* Put primary service to our local list */
+	s->primary = primary;
+	if (s->primary) {
+		memcpy(&s->prim, data, sizeof(s->prim));
+	} else {
+		memcpy(&s->incl, data, sizeof(s->incl));
+		return s;
+	}
+
+	/* For primary service allocate queue for included services */
+	s->included = queue_new();
+	if (!s->included) {
+		queue_destroy(s->chars, NULL);
+		free(s);
+		return NULL;
+	}
+
+	return s;
+}
+
+static void send_client_primary_notify(void *data, void *user_data)
+{
+	struct hal_ev_gatt_client_search_result ev;
+	struct service *p = data;
+	int32_t conn_id = PTR_TO_INT(user_data);
+
+	/* In service queue we will have also included services */
+	if (!p->primary)
+		return;
+
+	ev.conn_id  = conn_id;
+	element_id_to_hal_srvc_id(&p->id, 1, &ev.srvc_id);
+
+	uuid2android(&p->id.uuid, ev.srvc_id.uuid);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+			HAL_EV_GATT_CLIENT_SEARCH_RESULT, sizeof(ev), &ev);
+}
+
+static void send_client_search_complete_notify(int32_t status, int32_t conn_id)
+{
+	struct hal_ev_gatt_client_search_complete ev;
+
+	ev.status = status;
+	ev.conn_id = conn_id;
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+			HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, sizeof(ev), &ev);
+}
+
+struct discover_srvc_data {
+	bt_uuid_t uuid;
+	struct app_connection *conn;
+};
+
+static void discover_srvc_by_uuid_cb(uint8_t status, GSList *ranges,
+								void *user_data)
+{
+	struct discover_srvc_data *cb_data = user_data;
+	struct gatt_primary prim;
+	struct service *s;
+	int32_t gatt_status;
+	struct gatt_device *dev = cb_data->conn->device;
+	uint8_t instance_id = queue_length(dev->services);
+
+	DBG("Status %d", status);
+
+	if (status) {
+		error("gatt: Discover pri srvc filtered by uuid failed: %s",
+							att_ecode2str(status));
+		gatt_status = GATT_FAILURE;
+		goto reply;
+	}
+
+	if (!ranges) {
+		info("gatt: No primary services searched by uuid found");
+		gatt_status = GATT_SUCCESS;
+		goto reply;
+	}
+
+	bt_uuid_to_string(&cb_data->uuid, prim.uuid, sizeof(prim.uuid));
+	/*
+	 * If multiple instances of the same service (as identified by UUID)
+	 * exist, the first instance of the service is returned.
+	 */
+	memcpy(&prim.range, ranges->data, sizeof(prim.range));
+
+	s = create_service(instance_id++, true, prim.uuid, &prim);
+	if (!s) {
+		gatt_status = GATT_FAILURE;
+		goto reply;
+	}
+
+	if (!queue_push_tail(dev->services, s)) {
+		error("gatt: Cannot push primary service to the list");
+		gatt_status = GATT_FAILURE;
+		goto reply;
+	}
+
+	send_client_primary_notify(s, INT_TO_PTR(cb_data->conn->id));
+
+	DBG("attr handle = 0x%04x, end grp handle = 0x%04x uuid: %s",
+		prim.range.start, prim.range.end, prim.uuid);
+
+	/* Partial search service scanning was performed */
+	dev->partial_srvc_search = true;
+	gatt_status = GATT_SUCCESS;
+
+reply:
+	send_client_search_complete_notify(gatt_status, cb_data->conn->id);
+	free(cb_data);
+}
+
+static void discover_srvc_all_cb(uint8_t status, GSList *services,
+								void *user_data)
+{
+	struct discover_srvc_data *cb_data = user_data;
+	struct gatt_device *dev = cb_data->conn->device;
+	int32_t gatt_status;
+	GSList *l;
+	/*
+	 * There might be multiply services with same uuid. Therefore make sure
+	 * each primary service one has unique instance_id
+	 */
+	uint8_t instance_id = queue_length(dev->services);
+
+	DBG("Status %d", status);
+
+	if (status) {
+		error("gatt: Discover all primary services failed: %s",
+							att_ecode2str(status));
+		gatt_status = GATT_FAILURE;
+		goto reply;
+	}
+
+	if (!services) {
+		info("gatt: No primary services found");
+		gatt_status = GATT_SUCCESS;
+		goto reply;
+	}
+
+	for (l = services; l; l = l->next) {
+		struct gatt_primary *prim = l->data;
+		struct service *p;
+
+		if (queue_find(dev->services, match_srvc_by_range,
+								&prim->range))
+			continue;
+
+		p = create_service(instance_id++, true, prim->uuid, prim);
+		if (!p)
+			continue;
+
+		if (!queue_push_tail(dev->services, p)) {
+			error("gatt: Cannot push primary service to the list");
+			free(p);
+			continue;
+		}
+
+		DBG("attr handle = 0x%04x, end grp handle = 0x%04x uuid: %s",
+			prim->range.start, prim->range.end, prim->uuid);
+	}
+
+	/*
+	 * Send all found services notifications - first cache,
+	 * then send notifies
+	 */
+	queue_foreach(dev->services, send_client_primary_notify,
+						INT_TO_PTR(cb_data->conn->id));
+
+	/* Full search service scanning was performed */
+	dev->partial_srvc_search = false;
+	gatt_status = GATT_SUCCESS;
+
+reply:
+	send_client_search_complete_notify(gatt_status, cb_data->conn->id);
+	free(cb_data);
+}
+
+static void discover_primary_cb(uint8_t status, GSList *services,
+								void *user_data)
+{
+	struct discover_srvc_data *cb_data = user_data;
+	struct app_connection *conn = cb_data->conn;
+	struct gatt_device *dev = conn->device;
+	GSList *l, *uuids = NULL;
+
+	DBG("Status %d", status);
+
+	if (status) {
+		error("gatt: Discover all primary services failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	if (!services) {
+		info("gatt: No primary services found");
+		return;
+	}
+
+	for (l = services; l; l = l->next) {
+		struct gatt_primary *prim = l->data;
+		uint8_t *new_uuid;
+		bt_uuid_t uuid;
+
+		DBG("uuid: %s", prim->uuid);
+
+		if (bt_string_to_uuid(&uuid, prim->uuid) < 0) {
+			error("gatt: Cannot convert string to uuid");
+			continue;
+		}
+
+		new_uuid = g_memdup(&uuid.value.u128, sizeof(uuid.value.u128));
+
+		uuids = g_slist_prepend(uuids, new_uuid);
+	}
+
+	bt_device_set_uuids(&dev->bdaddr, uuids);
+
+	free(cb_data);
+	queue_remove(app_connections, conn);
+	destroy_connection(conn);
+}
+
+static guint search_dev_for_srvc(struct app_connection *conn, bt_uuid_t *uuid)
+{
+	struct discover_srvc_data *cb_data =
+					new0(struct discover_srvc_data, 1);
+
+	if (!cb_data) {
+		error("gatt: Cannot allocate cb data");
+		return 0;
+	}
+
+	cb_data->conn = conn;
+
+	if (uuid) {
+		memcpy(&cb_data->uuid, uuid, sizeof(cb_data->uuid));
+		return gatt_discover_primary(conn->device->attrib, uuid,
+					discover_srvc_by_uuid_cb, cb_data);
+	}
+
+
+	if (conn->app)
+		return gatt_discover_primary(conn->device->attrib, NULL,
+						discover_srvc_all_cb, cb_data);
+
+	return gatt_discover_primary(conn->device->attrib, NULL,
+						discover_primary_cb, cb_data);
+}
+
 struct connect_data {
 	struct gatt_device *dev;
 	int32_t status;
@@ -1052,6 +1369,19 @@ static void connect_cb(GIOChannel *io, GError *gerr, gpointer user_data)
 	status = GATT_SUCCESS;
 
 reply:
+	if (!dev->conn_cnt) {
+		struct app_connection *conn;
+
+		if (!dev->attrib)
+			return;
+
+		conn = create_connection(dev, NULL);
+		if (!conn)
+			return;
+
+		search_dev_for_srvc(conn, NULL);
+	}
+
 	data.dev = dev;
 	data.status = status;
 	queue_foreach(app_connections, send_app_connect_notifications, &data);
@@ -1211,105 +1541,39 @@ static struct gatt_app *register_app(const uint8_t *uuid, gatt_type_t type)
 	if ((app->type == GATT_SERVER) &&
 			!queue_push_tail(listen_apps, INT_TO_PTR(app->id))) {
 		error("gatt: Cannot push server on the list");
-		destroy_gatt_app(app);
-		return NULL;
-	}
-
-	return app;
-}
-
-static void handle_client_register(const void *buf, uint16_t len)
-{
-	const struct hal_cmd_gatt_client_register *cmd = buf;
-	struct hal_ev_gatt_client_register_client ev;
-	struct gatt_app *app;
-
-	DBG("");
-
-	memset(&ev, 0, sizeof(ev));
-
-	app = register_app(cmd->uuid, GATT_CLIENT);
-
-	if (app) {
-		ev.client_if = app->id;
-		ev.status = GATT_SUCCESS;
-	} else
-		ev.status = GATT_FAILURE;
-
-	/* We should send notification with given in cmd UUID */
-	memcpy(ev.app_uuid, cmd->uuid, sizeof(ev.app_uuid));
-
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-			HAL_EV_GATT_CLIENT_REGISTER_CLIENT, sizeof(ev), &ev);
-
-	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT, HAL_OP_GATT_CLIENT_REGISTER,
-							HAL_STATUS_SUCCESS);
-}
-
-static void send_client_primary_notify(void *data, void *user_data)
-{
-	struct hal_ev_gatt_client_search_result ev;
-	struct service *p = data;
-	int32_t conn_id = PTR_TO_INT(user_data);
-
-	/* In service queue we will have also included services */
-	if (!p->primary)
-		return;
-
-	ev.conn_id  = conn_id;
-	element_id_to_hal_srvc_id(&p->id, 1, &ev.srvc_id);
-
-	uuid2android(&p->id.uuid, ev.srvc_id.uuid);
+		destroy_gatt_app(app);
+		return NULL;
+	}
 
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-			HAL_EV_GATT_CLIENT_SEARCH_RESULT, sizeof(ev), &ev);
+	return app;
 }
 
-static struct service *create_service(uint8_t id, bool primary, char *uuid,
-								void *data)
+static void handle_client_register(const void *buf, uint16_t len)
 {
-	struct service *s;
+	const struct hal_cmd_gatt_client_register *cmd = buf;
+	struct hal_ev_gatt_client_register_client ev;
+	struct gatt_app *app;
 
-	s = new0(struct service, 1);
-	if (!s) {
-		error("gatt: Cannot allocate memory for gatt_primary");
-		return NULL;
-	}
+	DBG("");
 
-	s->chars = queue_new();
-	if (!s->chars) {
-		error("gatt: Cannot allocate memory for char cache");
-		free(s);
-		return NULL;
-	}
+	memset(&ev, 0, sizeof(ev));
 
-	if (bt_string_to_uuid(&s->id.uuid, uuid) < 0) {
-		error("gatt: Cannot convert string to uuid");
-		queue_destroy(s->chars, NULL);
-		free(s);
-		return NULL;
-	}
+	app = register_app(cmd->uuid, GATT_CLIENT);
 
-	s->id.instance = id;
+	if (app) {
+		ev.client_if = app->id;
+		ev.status = GATT_SUCCESS;
+	} else
+		ev.status = GATT_FAILURE;
 
-	/* Put primary service to our local list */
-	s->primary = primary;
-	if (s->primary) {
-		memcpy(&s->prim, data, sizeof(s->prim));
-	} else {
-		memcpy(&s->incl, data, sizeof(s->incl));
-		return s;
-	}
+	/* We should send notification with given in cmd UUID */
+	memcpy(ev.app_uuid, cmd->uuid, sizeof(ev.app_uuid));
 
-	/* For primary service allocate queue for included services */
-	s->included = queue_new();
-	if (!s->included) {
-		queue_destroy(s->chars, NULL);
-		free(s);
-		return NULL;
-	}
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+			HAL_EV_GATT_CLIENT_REGISTER_CLIENT, sizeof(ev), &ev);
 
-	return s;
+	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT, HAL_OP_GATT_CLIENT_REGISTER,
+							HAL_STATUS_SUCCESS);
 }
 
 static void handle_client_scan(const void *buf, uint16_t len)
@@ -1369,40 +1633,6 @@ static void bt_le_discovery_stop_cb(void)
 		bt_le_discovery_start();
 }
 
-static struct app_connection *create_connection(struct gatt_device *device,
-						struct gatt_app *app)
-{
-	struct app_connection *new_conn;
-	static int32_t last_conn_id = 1;
-
-	/* Check if already connected */
-	new_conn = new0(struct app_connection, 1);
-	if (!new_conn)
-		return NULL;
-
-	/* Make connection id unique to connection record (app, device) pair */
-	new_conn->app = app;
-	new_conn->id = last_conn_id++;
-
-	new_conn->transactions = queue_new();
-	if (!new_conn->transactions) {
-		free(new_conn);
-		return NULL;
-	}
-
-	if (!queue_push_head(app_connections, new_conn)) {
-		error("gatt: Cannot push client on the client queue!?");
-		queue_destroy(new_conn->transactions, free);
-		free(new_conn);
-		return NULL;
-	}
-
-	new_conn->device = device_ref(device);
-	new_conn->device->conn_cnt++;
-
-	return new_conn;
-}
-
 static void trigger_disconnection(struct app_connection *connection)
 {
 	/* Notify client */
@@ -1750,167 +1980,6 @@ done:
 									status);
 }
 
-struct discover_srvc_data {
-	bt_uuid_t uuid;
-	struct app_connection *conn;
-};
-
-static void send_client_search_complete_notify(int32_t status, int32_t conn_id)
-{
-	struct hal_ev_gatt_client_search_complete ev;
-
-	ev.status = status;
-	ev.conn_id = conn_id;
-	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
-			HAL_EV_GATT_CLIENT_SEARCH_COMPLETE, sizeof(ev), &ev);
-}
-
-static void discover_srvc_all_cb(uint8_t status, GSList *services,
-								void *user_data)
-{
-	struct discover_srvc_data *cb_data = user_data;
-	struct gatt_device *dev = cb_data->conn->device;
-	int32_t gatt_status;
-	GSList *l;
-	/*
-	 * There might be multiply services with same uuid. Therefore make sure
-	 * each primary service one has unique instance_id
-	 */
-	uint8_t instance_id = queue_length(dev->services);
-
-	DBG("Status %d", status);
-
-	if (status) {
-		error("gatt: Discover all primary services failed: %s",
-							att_ecode2str(status));
-		gatt_status = GATT_FAILURE;
-		goto reply;
-	}
-
-	if (!services) {
-		info("gatt: No primary services found");
-		gatt_status = GATT_SUCCESS;
-		goto reply;
-	}
-
-	for (l = services; l; l = l->next) {
-		struct gatt_primary *prim = l->data;
-		struct service *p;
-
-		if (queue_find(dev->services, match_srvc_by_range,
-								&prim->range))
-			continue;
-
-		p = create_service(instance_id++, true, prim->uuid, prim);
-		if (!p)
-			continue;
-
-		if (!queue_push_tail(dev->services, p)) {
-			error("gatt: Cannot push primary service to the list");
-			free(p);
-			continue;
-		}
-
-		DBG("attr handle = 0x%04x, end grp handle = 0x%04x uuid: %s",
-			prim->range.start, prim->range.end, prim->uuid);
-	}
-
-	/*
-	 * Send all found services notifications - first cache,
-	 * then send notifies
-	 */
-	queue_foreach(dev->services, send_client_primary_notify,
-						INT_TO_PTR(cb_data->conn->id));
-
-	/* Full search service scanning was performed */
-	dev->partial_srvc_search = false;
-	gatt_status = GATT_SUCCESS;
-
-reply:
-	send_client_search_complete_notify(gatt_status, cb_data->conn->id);
-	free(cb_data);
-}
-
-static void discover_srvc_by_uuid_cb(uint8_t status, GSList *ranges,
-								void *user_data)
-{
-	struct discover_srvc_data *cb_data = user_data;
-	struct gatt_primary prim;
-	struct service *s;
-	int32_t gatt_status;
-	struct gatt_device *dev = cb_data->conn->device;
-	uint8_t instance_id = queue_length(dev->services);
-
-	DBG("Status %d", status);
-
-	if (status) {
-		error("gatt: Discover pri srvc filtered by uuid failed: %s",
-							att_ecode2str(status));
-		gatt_status = GATT_FAILURE;
-		goto reply;
-	}
-
-	if (!ranges) {
-		info("gatt: No primary services searched by uuid found");
-		gatt_status = GATT_SUCCESS;
-		goto reply;
-	}
-
-	bt_uuid_to_string(&cb_data->uuid, prim.uuid, sizeof(prim.uuid));
-	/*
-	 * If multiple instances of the same service (as identified by UUID)
-	 * exist, the first instance of the service is returned.
-	 */
-	memcpy(&prim.range, ranges->data, sizeof(prim.range));
-
-	s = create_service(instance_id++, true, prim.uuid, &prim);
-	if (!s) {
-		gatt_status = GATT_FAILURE;
-		goto reply;
-	}
-
-	if (!queue_push_tail(dev->services, s)) {
-		error("gatt: Cannot push primary service to the list");
-		gatt_status = GATT_FAILURE;
-		goto reply;
-	}
-
-	send_client_primary_notify(s, INT_TO_PTR(cb_data->conn->id));
-
-	DBG("attr handle = 0x%04x, end grp handle = 0x%04x uuid: %s",
-		prim.range.start, prim.range.end, prim.uuid);
-
-	/* Partial search service scanning was performed */
-	dev->partial_srvc_search = true;
-	gatt_status = GATT_SUCCESS;
-
-reply:
-	send_client_search_complete_notify(gatt_status, cb_data->conn->id);
-	free(cb_data);
-}
-
-static guint search_dev_for_srvc(struct app_connection *conn, bt_uuid_t *uuid)
-{
-	struct discover_srvc_data *cb_data =
-					new0(struct discover_srvc_data, 1);
-
-	if (!cb_data) {
-		error("gatt: Cannot allocate cb data");
-		return 0;
-	}
-
-	cb_data->conn = conn;
-
-	if (uuid) {
-		memcpy(&cb_data->uuid, uuid, sizeof(cb_data->uuid));
-		return gatt_discover_primary(conn->device->attrib, uuid,
-					discover_srvc_by_uuid_cb, cb_data);
-	}
-
-	return gatt_discover_primary(conn->device->attrib, NULL,
-						discover_srvc_all_cb, cb_data);
-}
-
 static void handle_client_search_service(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_client_search_service *cmd = buf;
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 08/11] android/gatt: Do not disconnect immediately after discovering primaries
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (5 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 07/11] android/gatt: Automatically discover primary services for bonded devices Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 09/11] android/hidhost: Add support for re-connecting HoG Luiz Augusto von Dentz
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This is needed in Android in order react to services found.
---
 android/gatt.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index 0a8684e..d63efc9 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -68,6 +68,8 @@
 #define GATT_PERM_WRITE_SIGNED		0x00010000
 #define GATT_PERM_WRITE_SIGNED_MITM	0x00020000
 
+#define GATT_CONN_TIMEOUT 2
+
 static const uint8_t BLUETOOTH_UUID[] = {
 	0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
 	0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
@@ -169,6 +171,8 @@ struct app_connection {
 	struct queue *transactions;
 	int32_t id;
 
+	guint timeout_id;
+
 	bool wait_execute_write;
 };
 
@@ -832,6 +836,9 @@ static void destroy_connection(void *data)
 {
 	struct app_connection *conn = data;
 
+	if (conn->timeout_id > 0)
+		g_source_remove(conn->timeout_id);
+
 	if (!queue_find(gatt_devices, match_by_value, conn->device))
 		goto cleanup;
 
@@ -1213,6 +1220,17 @@ reply:
 	send_client_search_complete_notify(gatt_status, cb_data->conn->id);
 	free(cb_data);
 }
+static gboolean connection_timeout(void *user_data)
+{
+	struct app_connection *conn = user_data;
+
+	conn->timeout_id = 0;
+
+	queue_remove(app_connections, conn);
+	destroy_connection(conn);
+
+	return FALSE;
+}
 
 static void discover_primary_cb(uint8_t status, GSList *services,
 								void *user_data)
@@ -1255,8 +1273,9 @@ static void discover_primary_cb(uint8_t status, GSList *services,
 	bt_device_set_uuids(&dev->bdaddr, uuids);
 
 	free(cb_data);
-	queue_remove(app_connections, conn);
-	destroy_connection(conn);
+
+	conn->timeout_id = g_timeout_add_seconds(GATT_CONN_TIMEOUT,
+						connection_timeout, conn);
 }
 
 static guint search_dev_for_srvc(struct app_connection *conn, bt_uuid_t *uuid)
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 09/11] android/hidhost: Add support for re-connecting HoG
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (6 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 08/11] android/gatt: Do not disconnect immediately after discovering primaries Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 10/11] android/bluetooth: Fix not setting expected discovery type Luiz Augusto von Dentz
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Once HoG disconnects scanning should be turned on so that once the
device starts advertising again it should connected automatically.
---
 android/hidhost.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/android/hidhost.c b/android/hidhost.c
index b8b36a9..846dd57 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -109,6 +109,7 @@ struct hid_device {
 	struct bt_uhid	*uhid;
 	uint8_t		last_hid_msg;
 	struct bt_hog	*hog;
+	guint		reconnect_id;
 };
 
 static int device_cmp(gconstpointer s, gconstpointer user_data)
@@ -123,6 +124,9 @@ static void hid_device_free(void *data)
 {
 	struct hid_device *dev = data;
 
+	if (dev->reconnect_id > 0)
+		g_source_remove(dev->reconnect_id);
+
 	if (dev->ctrl_watch > 0)
 		g_source_remove(dev->ctrl_watch);
 
@@ -732,6 +736,19 @@ fail:
 	hid_device_remove(dev);
 }
 
+static gboolean hog_reconnect(void *user_data)
+{
+	struct hid_device *dev = user_data;
+
+	DBG("");
+
+	dev->reconnect_id = 0;
+
+	bt_gatt_connect_app(hog_app, &dev->dst);
+
+	return FALSE;
+}
+
 static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
 {
 	GSList *l;
@@ -743,6 +760,13 @@ static void hog_conn_cb(const bdaddr_t *addr, int err, void *attrib)
 	if (err < 0) {
 		if (!dev)
 			return;
+		if (dev->hog && !dev->reconnect_id) {
+			bt_hid_notify_state(dev,
+						HAL_HIDHOST_STATE_DISCONNECTED);
+			bt_hog_detach(dev->hog);
+			dev->reconnect_id = g_idle_add(hog_reconnect, dev);
+			return;
+		}
 		goto fail;
 	}
 
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 10/11] android/bluetooth: Fix not setting expected discovery type
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (7 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 09/11] android/hidhost: Add support for re-connecting HoG Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 11:33 ` [PATCH BlueZ v2 11/11] android/gatt: Fix not setting medium security for paired devices Luiz Augusto von Dentz
  2014-06-13 12:52 ` [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

The code was not setting the expected discovery type for the next round
when discovering is active.
---
 android/bluetooth.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 9d17faa..bc10b38 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -1292,8 +1292,11 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
 
 	adapter.cur_discovery_type = type;
 
-	if (ev->discovering)
+	if (ev->discovering) {
+		adapter.exp_discovery_type = adapter.le_scanning ?
+						SCAN_TYPE_LE : SCAN_TYPE_NONE;
 		return;
+	}
 
 	/* One shot notification about discovery stopped */
 	if (gatt_discovery_stopped_cb) {
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH BlueZ v2 11/11] android/gatt: Fix not setting medium security for paired devices
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (8 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 10/11] android/bluetooth: Fix not setting expected discovery type Luiz Augusto von Dentz
@ 2014-06-13 11:33 ` Luiz Augusto von Dentz
  2014-06-13 12:52 ` [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 11:33 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Always use medium security when connecting devices already paired since
some profiles like HoG do require encryption.
---
 android/gatt.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/android/gatt.c b/android/gatt.c
index d63efc9..5505cd0 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -1430,8 +1430,8 @@ static int connect_le(struct gatt_device *dev)
 
 	DBG("Connection attempt to: %s", addr);
 
-	/* TODO: If we are bonded then we should use higier sec level */
-	sec_level = BT_IO_SEC_LOW;
+	sec_level = bt_device_is_bonded(&dev->bdaddr) ? BT_IO_SEC_MEDIUM :
+								BT_IO_SEC_LOW;
 
 	/*
 	 * This connection will help us catch any PDUs that comes before
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH BlueZ v2 01/11] android/gatt: Make application API public
  2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
                   ` (9 preceding siblings ...)
  2014-06-13 11:33 ` [PATCH BlueZ v2 11/11] android/gatt: Fix not setting medium security for paired devices Luiz Augusto von Dentz
@ 2014-06-13 12:52 ` Luiz Augusto von Dentz
  10 siblings, 0 replies; 12+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-13 12:52 UTC (permalink / raw)
  To: linux-bluetooth@vger.kernel.org

Hi,

On Fri, Jun 13, 2014 at 2:33 PM, Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> This in future gonna be used by HoG to receive connection notifications.
> ---
> v2: Fix hidhost states not being propagated and add patch to set medium
> security for devices paired.
>
>  android/gatt.c | 142 +++++++++++++++++++++++++++++++++++++++++++++------------
>  android/gatt.h |  15 ++++++
>  2 files changed, 129 insertions(+), 28 deletions(-)
>
> diff --git a/android/gatt.c b/android/gatt.c
> index 741dc38..a2314e0 100644
> --- a/android/gatt.c
> +++ b/android/gatt.c
> @@ -87,11 +87,6 @@ static const char const *device_state_str[] = {
>         "CONNECTED",
>  };
>
> -typedef enum {
> -       APP_CLIENT,
> -       APP_SERVER,
> -} gatt_app_type_t;
> -
>  struct pending_trans_data {
>         unsigned int id;
>         uint8_t opcode;
> @@ -101,10 +96,12 @@ struct gatt_app {
>         int32_t id;
>         uint8_t uuid[16];
>
> -       gatt_app_type_t type;
> +       gatt_type_t type;
>
>         /* Valid for client applications */
>         struct queue *notifications;
> +
> +       gatt_conn_cb_t func;
>  };
>
>  struct element_id {
> @@ -617,7 +614,7 @@ static void destroy_gatt_app(void *data)
>          * too. So remove all elements and then destroy queue.
>          */
>
> -       if (app->type == APP_CLIENT)
> +       if (app->type == GATT_CLIENT)
>                 while (queue_peek_head(app->notifications)) {
>                         struct notification_data *notification;
>
> @@ -630,14 +627,14 @@ static void destroy_gatt_app(void *data)
>         free(app);
>  }
>
> -static int register_app(const uint8_t *uuid, gatt_app_type_t app_type)
> +static struct gatt_app *register_app(const uint8_t *uuid, gatt_type_t type)
>  {
>         static int32_t application_id = 1;
>         struct gatt_app *app;
>
>         if (queue_find(gatt_apps, match_app_by_uuid, uuid)) {
>                 error("gatt: app uuid is already on list");
> -               return 0;
> +               return NULL;
>         }
>
>         app = new0(struct gatt_app, 1);
> @@ -646,14 +643,14 @@ static int register_app(const uint8_t *uuid, gatt_app_type_t app_type)
>                 return 0;
>         }
>
> -       app->type = app_type;
> +       app->type = type;
>
> -       if (app->type == APP_CLIENT) {
> +       if (app->type == GATT_CLIENT) {
>                 app->notifications = queue_new();
>                 if (!app->notifications) {
>                         error("gatt: couldn't allocate notifications queue");
>                         destroy_gatt_app(app);
> -                       return 0;
> +                       return NULL;
>                 }
>         }
>
> @@ -664,33 +661,35 @@ static int register_app(const uint8_t *uuid, gatt_app_type_t app_type)
>         if (!queue_push_head(gatt_apps, app)) {
>                 error("gatt: Cannot push app on the list");
>                 destroy_gatt_app(app);
> -               return 0;
> +               return NULL;
>         }
>
> -       if ((app->type == APP_SERVER) &&
> +       if ((app->type == GATT_SERVER) &&
>                         !queue_push_tail(listen_apps, INT_TO_PTR(app->id))) {
>                 error("gatt: Cannot push server on the list");
>                 destroy_gatt_app(app);
> -               return 0;
> +               return NULL;
>         }
>
> -       return app->id;
> +       return app;
>  }
>
>  static void handle_client_register(const void *buf, uint16_t len)
>  {
>         const struct hal_cmd_gatt_client_register *cmd = buf;
>         struct hal_ev_gatt_client_register_client ev;
> +       struct gatt_app *app;
>
>         DBG("");
>
>         memset(&ev, 0, sizeof(ev));
>
> -       ev.client_if = register_app(cmd->uuid, APP_CLIENT);
> +       app = register_app(cmd->uuid, GATT_CLIENT);
>
> -       if (ev.client_if)
> +       if (app) {
> +               ev.client_if = app->id;
>                 ev.status = GATT_SUCCESS;
> -       else
> +       } else
>                 ev.status = GATT_FAILURE;
>
>         /* We should send notification with given in cmd UUID */
> @@ -708,6 +707,12 @@ static void send_client_disconnection_notify(struct app_connection *connection,
>  {
>         struct hal_ev_gatt_client_disconnect ev;
>
> +       if (connection->app->func) {
> +               connection->app->func(&connection->device->bdaddr, -ENOTCONN,
> +                                               connection->device->attrib);
> +               return;
> +       }
> +
>         ev.client_if = connection->app->id;
>         ev.conn_id = connection->id;
>         ev.status = status;
> @@ -723,6 +728,13 @@ static void send_client_connection_notify(struct app_connection *connection,
>  {
>         struct hal_ev_gatt_client_connect ev;
>
> +       if (connection->app->func) {
> +               connection->app->func(&connection->device->bdaddr,
> +                                       status == GATT_SUCCESS ? 0 : -ENOTCONN,
> +                                       connection->device->attrib);
> +               return;
> +       }
> +
>         ev.client_if = connection->app->id;
>         ev.conn_id = connection->id;
>         ev.status = status;
> @@ -738,6 +750,13 @@ static void send_server_connection_notify(struct app_connection *connection,
>  {
>         struct hal_ev_gatt_server_connection ev;
>
> +       if (connection->app->func) {
> +               connection->app->func(&connection->device->bdaddr,
> +                                       connected ? 0 : -ENOTCONN,
> +                                       connection->device->attrib);
> +               return;
> +       }
> +
>         ev.server_if = connection->app->id;
>         ev.conn_id = connection->id;
>         ev.connected = connected;
> @@ -751,7 +770,7 @@ static void send_server_connection_notify(struct app_connection *connection,
>  static void send_app_disconnect_notify(struct app_connection *connection,
>                                                                 int32_t status)
>  {
> -       if (connection->app->type == APP_CLIENT)
> +       if (connection->app->type == GATT_CLIENT)
>                 send_client_disconnection_notify(connection, status);
>         else
>                 send_server_connection_notify(connection, !!status);
> @@ -760,9 +779,9 @@ static void send_app_disconnect_notify(struct app_connection *connection,
>  static void send_app_connect_notify(struct app_connection *connection,
>                                                                 int32_t status)
>  {
> -       if (connection->app->type == APP_CLIENT)
> +       if (connection->app->type == GATT_CLIENT)
>                 send_client_connection_notify(connection, status);
> -       else
> +       else if (connection->app->type == GATT_SERVER)
>                 send_server_connection_notify(connection, !status);
>  }
>
> @@ -3566,9 +3585,11 @@ static void handle_client_test_command(const void *buf, uint16_t len)
>         switch (cmd->command) {
>         case GATT_CLIENT_TEST_CMD_ENABLE:
>                 if (cmd->u1) {
> -                       if (!test_client_if)
> -                               test_client_if = register_app(TEST_UUID,
> -                                                               APP_CLIENT);
> +                       if (!test_client_if) {
> +                               app = register_app(TEST_UUID, GATT_CLIENT);
> +                               if (app)
> +                                       test_client_if = app->id;
> +                       }
>
>                         if (test_client_if)
>                                 status = HAL_STATUS_SUCCESS;
> @@ -3613,16 +3634,18 @@ static void handle_server_register(const void *buf, uint16_t len)
>  {
>         const struct hal_cmd_gatt_server_register *cmd = buf;
>         struct hal_ev_gatt_server_register ev;
> +       struct gatt_app *app;
>
>         DBG("");
>
>         memset(&ev, 0, sizeof(ev));
>
> -       ev.server_if = register_app(cmd->uuid, APP_SERVER);
> +       app = register_app(cmd->uuid, GATT_SERVER);
>
> -       if (ev.server_if)
> +       if (app) {
> +               ev.server_if = app->id;
>                 ev.status = GATT_SUCCESS;
> -       else
> +       } else
>                 ev.status = GATT_FAILURE;
>
>         memcpy(ev.uuid, cmd->uuid, sizeof(ev.uuid));
> @@ -5963,3 +5986,66 @@ void bt_gatt_unregister(void)
>         bt_crypto_unref(crypto);
>         crypto = NULL;
>  }
> +
> +
> +unsigned int bt_gatt_register_app(const char *uuid, gatt_type_t type,
> +                                                       gatt_conn_cb_t func)
> +{
> +       struct gatt_app *app;
> +       bt_uuid_t uuid128;
> +
> +       bt_string_to_uuid(&uuid128, uuid);
> +       app = register_app((void *) &uuid128.value.u128, type);
> +       if (!app)
> +               return 0;
> +
> +       app->func = func;
> +
> +       return app->id;
> +}
> +
> +bool bt_gatt_unregister_app(unsigned int id)
> +{
> +       uint8_t status;
> +
> +       status = unregister_app(id);
> +
> +       return status != HAL_STATUS_FAILED;
> +}
> +
> +bool bt_gatt_connect_app(unsigned int id, const bdaddr_t *addr)
> +{
> +       uint8_t status;
> +
> +       status = handle_connect(id, addr);
> +
> +       return status != HAL_STATUS_FAILED;
> +}
> +
> +bool bt_gatt_disconnect_app(unsigned int id, const bdaddr_t *addr)
> +{
> +       struct app_connection match;
> +       struct app_connection *conn;
> +       struct gatt_device *device;
> +       struct gatt_app *app;
> +
> +       app = find_app_by_id(id);
> +       if (!app)
> +               return false;
> +
> +       device = find_device_by_addr(addr);
> +       if (!device)
> +               return false;
> +
> +       match.device = device;
> +       match.app = app;
> +
> +       conn = queue_find(app_connections, match_connection_by_device_and_app,
> +                                                                       &match);
> +       if (!conn)
> +               return false;
> +
> +       trigger_disconnection(conn);
> +
> +       return true;
> +}
> diff --git a/android/gatt.h b/android/gatt.h
> index d4392d9..5ba9161 100644
> --- a/android/gatt.h
> +++ b/android/gatt.h
> @@ -23,3 +23,18 @@
>
>  bool bt_gatt_register(struct ipc *ipc, const bdaddr_t *addr);
>  void bt_gatt_unregister(void);
> +
> +
> +typedef enum {
> +       GATT_CLIENT,
> +       GATT_SERVER,
> +} gatt_type_t;
> +
> +typedef void (*gatt_conn_cb_t)(const bdaddr_t *addr, int err, void *attrib);
> +
> +unsigned int bt_gatt_register_app(const char *uuid, gatt_type_t type,
> +                                                       gatt_conn_cb_t func);
> +bool bt_gatt_unregister_app(unsigned int id);
> +
> +bool bt_gatt_connect_app(unsigned int id, const bdaddr_t *addr);
> +bool bt_gatt_disconnect_app(unsigned int id, const bdaddr_t *addr);
> --
> 1.9.3

This set is now pushed.


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2014-06-13 12:52 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-13 11:33 [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 02/11] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 03/11] android/hidhost: Add support for HoG Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 04/11] android/gatt: Fix not detecting device found by Bluetooth HAL Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 05/11] android/gatt: Create device and connect bonded devices Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 06/11] android/bluetooth: Add bt_device_set_uuids Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 07/11] android/gatt: Automatically discover primary services for bonded devices Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 08/11] android/gatt: Do not disconnect immediately after discovering primaries Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 09/11] android/hidhost: Add support for re-connecting HoG Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 10/11] android/bluetooth: Fix not setting expected discovery type Luiz Augusto von Dentz
2014-06-13 11:33 ` [PATCH BlueZ v2 11/11] android/gatt: Fix not setting medium security for paired devices Luiz Augusto von Dentz
2014-06-13 12:52 ` [PATCH BlueZ v2 01/11] android/gatt: Make application API public Luiz Augusto von Dentz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).