* [PATCH BlueZ 01/10] android/gatt: Make application API public
@ 2014-06-12 12:33 Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 02/10] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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.
---
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] 10+ messages in thread
* [PATCH BlueZ 02/10] android/bluetooth: Add bt_is_device_le function
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 03/10] android/hidhost: Add support for HoG Luiz Augusto von Dentz
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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] 10+ messages in thread
* [PATCH BlueZ 03/10] android/hidhost: Add support for HoG
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 02/10] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 04/10] android/gatt: Fix not detecting device found by Bluetooth HAL Luiz Augusto von Dentz
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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 | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 109 insertions(+), 1 deletion(-)
diff --git a/android/hidhost.c b/android/hidhost.c
index 4a158c6..49f7b77 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,67 @@ 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;
+ }
+
+ 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;
@@ -748,6 +819,14 @@ static void bt_hid_connect(const void *buf, uint16_t len)
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 +836,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 +849,20 @@ failed:
status);
}
+static bool hog_disconnect(struct hid_device *dev)
+{
+ DBG("");
+
+ 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 +882,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 +899,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 +1447,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] 10+ messages in thread
* [PATCH BlueZ 04/10] android/gatt: Fix not detecting device found by Bluetooth HAL
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 02/10] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 03/10] android/hidhost: Add support for HoG Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 05/10] android/gatt: Create device and connect bonded devices Luiz Augusto von Dentz
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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] 10+ messages in thread
* [PATCH BlueZ 05/10] android/gatt: Create device and connect bonded devices
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
` (2 preceding siblings ...)
2014-06-12 12:33 ` [PATCH BlueZ 04/10] android/gatt: Fix not detecting device found by Bluetooth HAL Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 06/10] android/bluetooth: Add bt_device_set_uuids Luiz Augusto von Dentz
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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] 10+ messages in thread
* [PATCH BlueZ 06/10] android/bluetooth: Add bt_device_set_uuids
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
` (3 preceding siblings ...)
2014-06-12 12:33 ` [PATCH BlueZ 05/10] android/gatt: Create device and connect bonded devices Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 07/10] android/gatt: Automatically discover primary services for bonded devices Luiz Augusto von Dentz
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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] 10+ messages in thread
* [PATCH BlueZ 07/10] android/gatt: Automatically discover primary services for bonded devices
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
` (4 preceding siblings ...)
2014-06-12 12:33 ` [PATCH BlueZ 06/10] android/bluetooth: Add bt_device_set_uuids Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 08/10] android/gatt: Do not disconnect immediately after discovering primaries Luiz Augusto von Dentz
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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] 10+ messages in thread
* [PATCH BlueZ 08/10] android/gatt: Do not disconnect immediately after discovering primaries
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
` (5 preceding siblings ...)
2014-06-12 12:33 ` [PATCH BlueZ 07/10] android/gatt: Automatically discover primary services for bonded devices Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 09/10] android/hidhost: Add support for re-connecting HoG Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 10/10] android/bluetooth: Fix not setting expected discovery type Luiz Augusto von Dentz
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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] 10+ messages in thread
* [PATCH BlueZ 09/10] android/hidhost: Add support for re-connecting HoG
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
` (6 preceding siblings ...)
2014-06-12 12:33 ` [PATCH BlueZ 08/10] android/gatt: Do not disconnect immediately after discovering primaries Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 10/10] android/bluetooth: Fix not setting expected discovery type Luiz Augusto von Dentz
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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 49f7b77..ce533f7 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] 10+ messages in thread
* [PATCH BlueZ 10/10] android/bluetooth: Fix not setting expected discovery type
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
` (7 preceding siblings ...)
2014-06-12 12:33 ` [PATCH BlueZ 09/10] android/hidhost: Add support for re-connecting HoG Luiz Augusto von Dentz
@ 2014-06-12 12:33 ` Luiz Augusto von Dentz
8 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2014-06-12 12: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] 10+ messages in thread
end of thread, other threads:[~2014-06-12 12:33 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-12 12:33 [PATCH BlueZ 01/10] android/gatt: Make application API public Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 02/10] android/bluetooth: Add bt_is_device_le function Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 03/10] android/hidhost: Add support for HoG Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 04/10] android/gatt: Fix not detecting device found by Bluetooth HAL Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 05/10] android/gatt: Create device and connect bonded devices Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 06/10] android/bluetooth: Add bt_device_set_uuids Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 07/10] android/gatt: Automatically discover primary services for bonded devices Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 08/10] android/gatt: Do not disconnect immediately after discovering primaries Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 09/10] android/hidhost: Add support for re-connecting HoG Luiz Augusto von Dentz
2014-06-12 12:33 ` [PATCH BlueZ 10/10] android/bluetooth: Fix not setting expected discovery type 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).