All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support
@ 2017-10-13 14:02 Martin Fuzzey
  2017-10-13 14:02 ` [PATCH V2 BLueZ 1/3] android: Skip key loading for LE only devices Martin Fuzzey
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Martin Fuzzey @ 2017-10-13 14:02 UTC (permalink / raw)
  To: linux-bluetooth

This series adds a few missing pieces for Peripheral role support on Android 5.

This has been tested in the following configuration:
- Android 5.1.1
- Kernel 4.4
- nRF52 chip running Apache Newt firmware

Changes for V2:
- Only load keys if BRDE supported rather than always trying and ignoring error
- Use the bt_ad_* helper functions rather than open coding advertisement data
- free_adv_instance() accepts NULL like the other free family members
- Style fixes
- Remove SOBs


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

* [PATCH V2 BLueZ 1/3] android: Skip key loading for LE only devices.
  2017-10-13 14:02 [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Martin Fuzzey
@ 2017-10-13 14:02 ` Martin Fuzzey
  2017-10-13 14:02 ` [PATCH V2 BLueZ 2/3] android: Get max advertising instances from kernel Martin Fuzzey
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Martin Fuzzey @ 2017-10-13 14:02 UTC (permalink / raw)
  To: linux-bluetooth

Key loading is not supported for LE only devices.
---
 android/bluetooth.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index 51a31fe..c3ad5ce 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -3265,7 +3265,11 @@ static void load_devices_info(bt_bluetooth_ready cb)
 	load_irks(irks);
 	g_slist_free_full(irks, g_free);
 
-	load_link_keys(keys, cb);
+	if (adapter.supported_settings & MGMT_SETTING_BREDR)
+		load_link_keys(keys, cb);
+	else
+		cb(0, &adapter.bdaddr);
+
 	g_slist_free_full(keys, g_free);
 
 	g_strfreev(devs);


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

* [PATCH V2 BLueZ 2/3] android: Get max advertising instances from kernel
  2017-10-13 14:02 [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Martin Fuzzey
  2017-10-13 14:02 ` [PATCH V2 BLueZ 1/3] android: Skip key loading for LE only devices Martin Fuzzey
@ 2017-10-13 14:02 ` Martin Fuzzey
  2017-10-13 14:02 ` [PATCH V2 BLueZ 3/3] android: Enable multiadvertising Martin Fuzzey
  2017-11-06  9:25 ` [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Szymon Janc
  3 siblings, 0 replies; 5+ messages in thread
From: Martin Fuzzey @ 2017-10-13 14:02 UTC (permalink / raw)
  To: linux-bluetooth

Use the mgmnt "advinfo" operation to obtain the number of advertising
instances supported by the kernel.
---
 android/bluetooth.c |   44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/android/bluetooth.c b/android/bluetooth.c
index c3ad5ce..b5a2eab 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -3336,6 +3336,37 @@ static void clear_auto_connect_list(void)
 	error("Could not clear auto connect list");
 }
 
+static void read_adv_features_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_read_adv_features *rp = param;
+	bt_bluetooth_ready cb = user_data;
+	int err;
+
+	if (status) {
+		error("Failed to read advertising features for index %u: %s (0x%02x)",
+				adapter.index, mgmt_errstr(status), status);
+		err = -EIO;
+		goto failed;
+	}
+
+	if (length < sizeof(*rp)) {
+		error("Too small read advertising features response");
+		err = -EIO;
+		goto failed;
+	}
+
+	adapter.max_advert_instance = rp->max_instances;
+	info("Max LE advertising instances: %d", adapter.max_advert_instance);
+
+	load_devices_info(cb);
+
+	return;
+
+failed:
+	cb(err, NULL);
+}
+
 static void read_info_complete(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -3407,7 +3438,18 @@ static void read_info_complete(uint8_t status, uint16_t length,
 	if (missing_settings & MGMT_SETTING_BONDABLE)
 		set_mode(MGMT_OP_SET_BONDABLE, 0x01);
 
-	load_devices_info(cb);
+	if (adapter.supported_settings & MGMT_SETTING_LE) {
+		if (mgmt_send(mgmt_if, MGMT_OP_READ_ADV_FEATURES, adapter.index,
+			      0, NULL,
+			      read_adv_features_complete, cb, NULL) == 0) {
+			error("Cannot get LE adv features");
+			err = -EIO;
+			goto failed;
+		}
+	} else {
+		load_devices_info(cb);
+	}
+
 	load_devices_cache();
 
 	return;


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

* [PATCH V2 BLueZ 3/3] android: Enable multiadvertising
  2017-10-13 14:02 [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Martin Fuzzey
  2017-10-13 14:02 ` [PATCH V2 BLueZ 1/3] android: Skip key loading for LE only devices Martin Fuzzey
  2017-10-13 14:02 ` [PATCH V2 BLueZ 2/3] android: Get max advertising instances from kernel Martin Fuzzey
@ 2017-10-13 14:02 ` Martin Fuzzey
  2017-11-06  9:25 ` [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Szymon Janc
  3 siblings, 0 replies; 5+ messages in thread
From: Martin Fuzzey @ 2017-10-13 14:02 UTC (permalink / raw)
  To: linux-bluetooth

This is required for custom advertising data.

The HAL entry points related to multiadvertising are now implemented
and map to the mgmnt "add advertising" operation.
---
 android/Android.mk  |    1 
 android/bluetooth.c |  129 +++++++++++++++++++++
 android/bluetooth.h |   25 ++++
 android/gatt.c      |  309 +++++++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 454 insertions(+), 10 deletions(-)

diff --git a/android/Android.mk b/android/Android.mk
index 38ef4aa..76a826b 100644
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -72,6 +72,7 @@ LOCAL_SRC_FILES := \
 	bluez/src/shared/crypto.c \
 	bluez/src/shared/uhid.c \
 	bluez/src/shared/att.c \
+	bluez/src/shared/ad.c \
 	bluez/src/sdpd-database.c \
 	bluez/src/sdpd-service.c \
 	bluez/src/sdpd-request.c \
diff --git a/android/bluetooth.c b/android/bluetooth.c
index b5a2eab..c8468e1 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -42,6 +42,7 @@
 #include "src/shared/util.h"
 #include "src/shared/mgmt.h"
 #include "src/shared/queue.h"
+#include "src/shared/ad.h"
 #include "src/eir.h"
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
@@ -4019,6 +4020,134 @@ bool bt_le_set_advertising(bool advertising, bt_le_set_advertising_done cb,
 	return false;
 }
 
+struct addrm_adv_user_data {
+	bt_le_addrm_advertising_done cb;
+	void *user_data;
+};
+
+static void add_advertising_cb(uint8_t status, uint16_t length,
+			       const void *param, void *user_data)
+{
+	struct addrm_adv_user_data *data = user_data;
+
+	DBG("");
+
+	if (status)
+		error("Failed to add advertising %s (0x%02x))",
+				mgmt_errstr(status), status);
+
+	data->cb(status, data->user_data);
+}
+
+bool bt_le_add_advertising(struct adv_instance *adv,
+			   bt_le_addrm_advertising_done cb, void *user_data)
+{
+	struct mgmt_cp_add_advertising *cp;
+	struct addrm_adv_user_data *cb_data;
+	size_t len;
+	size_t adv_data_len = 0;
+	size_t sr_data_len = 0;
+	uint8_t *dst, *adv_data, *sr_data;
+	bool ok = false;
+
+	/* These accept NULL and return NULL */
+	adv_data = bt_ad_generate(adv->ad, &adv_data_len);
+	sr_data = bt_ad_generate(adv->sr, &sr_data_len);
+
+	len = sizeof(*cp) + adv_data_len + sr_data_len;
+	cp = malloc0(len);
+	if (!cp)
+		goto out;
+
+	cp->instance = adv->instance;
+	cp->timeout = adv->timeout;
+	/* XXX: how should we set duration? (kernel defaults to 2s) */
+
+	switch (adv->type) {
+	case ANDROID_ADVERTISING_EVENT_TYPE_CONNECTABLE:
+		cp->flags |= MGMT_ADV_FLAG_CONNECTABLE;
+		break;
+
+	case ANDROID_ADVERTISING_EVENT_TYPE_SCANNABLE:
+	case ANDROID_ADVERTISING_EVENT_TYPE_NON_CONNECTABLE:
+	default:
+		break;
+	}
+
+	if (adv->include_tx_power)
+		cp->flags |= MGMT_ADV_FLAG_TX_POWER;
+
+	dst = cp->data;
+	if (adv_data) {
+		cp->adv_data_len = adv_data_len;
+		memcpy(dst, adv_data, adv_data_len);
+		dst += adv_data_len;
+	}
+
+	if (sr_data) {
+		cp->scan_rsp_len = sr_data_len;
+		memcpy(dst, sr_data, sr_data_len);
+		dst += sr_data_len;
+	}
+
+	DBG("lens: adv=%d sr=%d total=%d",
+		cp->adv_data_len, cp->scan_rsp_len, len);
+
+	cb_data = new0(typeof(*cb_data), 1);
+	cb_data->cb = cb;
+	cb_data->user_data = user_data;
+
+	ok = (mgmt_send(mgmt_if, MGMT_OP_ADD_ADVERTISING, adapter.index,
+			len, cp, add_advertising_cb, cb_data, free) > 0);
+
+	if (!ok)
+		free(cb_data);
+
+out:
+	free(adv_data);
+	free(sr_data);
+	free(cp);
+
+	return ok;
+}
+
+static void remove_advertising_cb(uint8_t status, uint16_t length,
+				  const void *param, void *user_data)
+{
+	struct addrm_adv_user_data *data = user_data;
+
+	DBG("");
+
+	if (status)
+		error("Failed to remove advertising %s (0x%02x))",
+						mgmt_errstr(status), status);
+
+	data->cb(status, data->user_data);
+}
+
+bool bt_le_remove_advertising(struct adv_instance *adv,
+			      bt_le_addrm_advertising_done cb, void *user_data)
+{
+	struct mgmt_cp_remove_advertising cp = {
+		.instance = adv->instance,
+	};
+	struct addrm_adv_user_data *cb_data;
+	bool ok;
+
+	cb_data = new0(typeof(*cb_data), 1);
+	cb_data->cb = cb;
+	cb_data->user_data = user_data;
+
+	ok = (mgmt_send(mgmt_if, MGMT_OP_REMOVE_ADVERTISING, adapter.index,
+			sizeof(cp), &cp,
+			remove_advertising_cb, cb_data, free) > 0);
+
+	if (!ok)
+		free(cb_data);
+
+	return ok;
+}
+
 bool bt_le_register(bt_le_device_found cb)
 {
 	if (gatt_device_found_cb)
diff --git a/android/bluetooth.h b/android/bluetooth.h
index 4b17209..b139cb1 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -88,3 +88,28 @@ typedef void (*bt_paired_device_cb)(const bdaddr_t *addr);
 bool bt_paired_register(bt_paired_device_cb cb);
 void bt_paired_unregister(bt_paired_device_cb cb);
 bool bt_is_pairing(const bdaddr_t *addr);
+
+struct bt_ad;
+struct adv_instance {
+	uint8_t	instance;
+	int32_t timeout;
+	int32_t type;
+	struct bt_ad *ad;
+	struct bt_ad *sr;
+	unsigned include_tx_power:1;
+};
+
+/* Values below have no C API definition - only in Java (AdvertiseManager.java)
+ * and bluedroid
+ */
+enum android_adv_type {
+	ANDROID_ADVERTISING_EVENT_TYPE_CONNECTABLE = 0,
+	ANDROID_ADVERTISING_EVENT_TYPE_SCANNABLE = 2,
+	ANDROID_ADVERTISING_EVENT_TYPE_NON_CONNECTABLE = 3,
+};
+
+typedef void (*bt_le_addrm_advertising_done)(uint8_t status, void *user_data);
+bool bt_le_add_advertising(struct adv_instance *adv,
+		bt_le_addrm_advertising_done cb, void *user_data);
+bool bt_le_remove_advertising(struct adv_instance *adv,
+		bt_le_addrm_advertising_done cb, void *user_data);
diff --git a/android/gatt.c b/android/gatt.c
index 28635ed..6b36985 100644
--- a/android/gatt.c
+++ b/android/gatt.c
@@ -46,6 +46,7 @@
 #include "src/shared/queue.h"
 #include "src/shared/att.h"
 #include "src/shared/gatt-db.h"
+#include "src/shared/ad.h"
 #include "attrib/gattrib.h"
 #include "attrib/att.h"
 #include "attrib/gatt.h"
@@ -110,6 +111,8 @@ struct gatt_app {
 	struct queue *notifications;
 
 	gatt_conn_cb_t func;
+
+	struct adv_instance *adv;
 };
 
 struct element_id {
@@ -192,6 +195,7 @@ static struct ipc *hal_ipc = NULL;
 static bdaddr_t adapter_addr;
 static bool scanning = false;
 static unsigned int advertising_cnt = 0;
+static uint32_t adv_inst_bits = 0;
 
 static struct queue *gatt_apps = NULL;
 static struct queue *gatt_devices = NULL;
@@ -650,6 +654,19 @@ static void connection_cleanup(struct gatt_device *device)
 		bt_auto_connect_remove(&device->bdaddr);
 }
 
+static void free_adv_instance(struct adv_instance *adv)
+{
+	if (!adv)
+		return;
+
+	if (adv->instance)
+		adv_inst_bits &= ~(1 << (adv->instance - 1));
+
+	bt_ad_unref(adv->ad);
+	bt_ad_unref(adv->sr);
+	free(adv);
+}
+
 static void destroy_gatt_app(void *data)
 {
 	struct gatt_app *app = data;
@@ -674,6 +691,8 @@ static void destroy_gatt_app(void *data)
 
 	queue_destroy(app->notifications, free);
 
+	free_adv_instance(app->adv);
+
 	free(app);
 }
 
@@ -5586,19 +5605,162 @@ static void handle_client_set_scan_param(const void *buf, uint16_t len)
 					HAL_STATUS_UNSUPPORTED);
 }
 
+static struct adv_instance *find_adv_instance(uint32_t client_if)
+{
+	struct gatt_app *app;
+	struct adv_instance *adv;
+	uint8_t inst = 0;
+	unsigned int i;
+
+	app = find_app_by_id(client_if);
+	if (!app)
+		return NULL;
+
+	if (app->adv)
+		return app->adv;
+
+	/* Assume that kernel supports <= 32 advertising instances (5 today)
+	 * We have already indicated the number to the android framework layers
+	 * via the LE features so we don't check again here.
+	 * The kernel will detect the error if needed
+	 */
+	for (i = 0; i < sizeof(adv_inst_bits) * 8; i++) {
+		uint32_t mask = 1 << i;
+
+		if (!(adv_inst_bits & mask)) {
+			inst = i + 1;
+			adv_inst_bits |= mask;
+			break;
+		}
+	}
+	if (!inst)
+		return NULL;
+
+	adv = new0(typeof(*adv), 1);
+	adv->instance = inst;
+	app->adv = adv;
+
+	DBG("Assigned advertising instance %d for client %d", inst, client_if);
+
+	return adv;
+};
+
+/* Build advertising data object from a data buffer containing
+ * manufacturer_data, service_data, service uuids (in that order)
+ * The input data is raw with no TLV structure and the service uuids are 128 bit
+ */
+static struct bt_ad *build_adv_data(int32_t manufacturer_data_len,
+					int32_t service_data_len,
+					int32_t service_uuid_len,
+					const uint8_t *data_in)
+{
+	const int one_svc_uuid_len = 128 / 8;  /* Android uses 128bit UUIDs */
+	uint8_t *src = (uint8_t *)data_in;
+	struct bt_ad *ad;
+	unsigned num_svc_uuids, i;
+
+	ad = bt_ad_new();
+
+	if (manufacturer_data_len >= 2) { /* Includes manufacturer id */
+		uint16_t manufacturer_id;
+
+		manufacturer_id = bt_get_le16(src);
+		src += 2;
+
+		if (!bt_ad_add_manufacturer_data(ad,
+						 manufacturer_id,
+						 src,
+						 manufacturer_data_len - 2))
+			goto err;
+
+		src +=  manufacturer_data_len - 2;
+	}
+
+	if (service_data_len >= 2) { /* Includes service uuid (always 16 bit) */
+		bt_uuid_t bt_uuid;
+		uint16_t uuid16;
+
+		uuid16 = bt_get_le16(src);
+		src += 2;
+		bt_uuid16_create(&bt_uuid, uuid16);
+
+		if (!bt_ad_add_service_data(ad,
+					    &bt_uuid,
+					    src,
+					    service_data_len - 2))
+			goto err;
+
+		src += service_data_len - 2;
+	}
+
+	if (service_uuid_len % one_svc_uuid_len) {
+		error("Service UUIDs not multiple of %d bytes (%d)",
+			one_svc_uuid_len, service_uuid_len);
+		num_svc_uuids = 0;
+	} else {
+		num_svc_uuids = service_uuid_len / one_svc_uuid_len;
+	}
+
+	for (i = 0; i  < num_svc_uuids; i++) {
+		bt_uuid_t bt_uuid;
+
+		android2uuid(src, &bt_uuid);
+		src += one_svc_uuid_len;
+
+		if (!bt_ad_add_service_uuid(ad, &bt_uuid))
+			goto err;
+	}
+
+	return ad;
+
+err:
+	bt_ad_unref(ad);
+	return NULL;
+}
+
+
 static void handle_client_setup_multi_adv(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_client_setup_multi_adv *cmd = buf;
+	struct hal_ev_gatt_client_multi_adv_enable ev;
+	struct adv_instance *adv;
+	uint8_t status;
 
-	DBG("client_if %d", cmd->client_if);
+	DBG("client_if %d min_interval=%d max_interval=%d type=%d channel_map=0x%x tx_power=%d timeout=%d",
+		cmd->client_if,
+		cmd->min_interval,
+		cmd->max_interval,
+		cmd->type,
+		cmd->channel_map,
+		cmd->tx_power,
+		cmd->timeout);
+
+	adv = find_adv_instance(cmd->client_if);
+	if (!adv) {
+		status = HAL_STATUS_FAILED;
+		goto out;
+	}
 
-	/* TODO */
+	status = HAL_STATUS_SUCCESS;
+	adv->timeout = cmd->timeout;
+	adv->type = cmd->type;
+	if (adv->type != ANDROID_ADVERTISING_EVENT_TYPE_SCANNABLE) {
+		bt_ad_unref(adv->sr);
+		adv->sr = NULL;
+	}
 
+out:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
 					HAL_OP_GATT_CLIENT_SETUP_MULTI_ADV,
-					HAL_STATUS_UNSUPPORTED);
+					status);
+
+	ev.client_if = cmd->client_if;
+	ev.status = status;
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+			HAL_EV_GATT_CLIENT_MULTI_ADV_ENABLE, sizeof(ev), &ev);
 }
 
+/* This is not currently called by Android 5.1 */
 static void handle_client_update_multi_adv(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_client_update_multi_adv *cmd = buf;
@@ -5612,30 +5774,157 @@ static void handle_client_update_multi_adv(const void *buf, uint16_t len)
 					HAL_STATUS_UNSUPPORTED);
 }
 
+struct addrm_adv_cb_data {
+	int32_t client_if;
+	struct adv_instance *adv;
+};
+
+static void add_advertising_cb(uint8_t status, void *user_data)
+{
+	struct addrm_adv_cb_data *cb_data = user_data;
+	struct hal_ev_gatt_client_multi_adv_data ev = {
+		.status = status,
+		.client_if = cb_data->client_if,
+	};
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+				HAL_EV_GATT_CLIENT_MULTI_ADV_DATA,
+				sizeof(ev), &ev);
+
+	free(cb_data);
+}
+
 static void handle_client_setup_multi_adv_inst(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_client_setup_multi_adv_inst *cmd = buf;
+	struct adv_instance *adv;
+	struct bt_ad *adv_data;
+	struct addrm_adv_cb_data *cb_data = NULL;
+	uint8_t status = HAL_STATUS_FAILED;
+
+	DBG("client_if %d set_scan_rsp=%d include_name=%d include_tx_power=%d appearance=%d manuf_data_len=%d svc_data_len=%d svc_uuid_len=%d",
+		cmd->client_if,
+		cmd->set_scan_rsp,
+		cmd->include_name,
+		cmd->include_tx_power,
+		cmd->appearance,
+		cmd->manufacturer_data_len,
+		cmd->service_data_len,
+		cmd->service_uuid_len
+	);
+
+	adv = find_adv_instance(cmd->client_if);
+	if (!adv)
+		goto out;
+
+	adv->include_tx_power = cmd->include_tx_power ? 1 : 0;
+
+	adv_data = build_adv_data(cmd->manufacturer_data_len,
+				  cmd->service_data_len,
+				  cmd->service_uuid_len,
+				  cmd->data_service_uuid);
+	if (!adv_data)
+		goto out;
+
+	if (cmd->set_scan_rsp) {
+		bt_ad_unref(adv->sr);
+		adv->sr = adv_data;
+	} else {
+		bt_ad_unref(adv->ad);
+		adv->ad = adv_data;
+	}
 
-	DBG("client_if %d", cmd->client_if);
+	cb_data = new0(typeof(*cb_data), 1);
+	cb_data->client_if = cmd->client_if;
+	cb_data->adv = adv;
 
-	/* TODO */
+	if (!bt_le_add_advertising(adv, add_advertising_cb, cb_data)) {
+		error("gatt: Could not add advertising");
+		free(cb_data);
+		goto out;
+	}
 
+	status = HAL_STATUS_SUCCESS;
+
+out:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
-					HAL_OP_GATT_CLIENT_SETUP_MULTI_ADV_INST,
-					HAL_STATUS_UNSUPPORTED);
+				HAL_OP_GATT_CLIENT_SETUP_MULTI_ADV_INST,
+				status);
+
+	if (status != HAL_STATUS_SUCCESS) {
+		struct hal_ev_gatt_client_multi_adv_data ev = {
+			.status = status,
+			.client_if = cmd->client_if,
+		};
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+				HAL_EV_GATT_CLIENT_MULTI_ADV_DATA,
+				sizeof(ev), &ev);
+	}
+}
+
+static void remove_advertising_cb(uint8_t status, void *user_data)
+{
+	struct addrm_adv_cb_data *cb_data = user_data;
+	struct hal_ev_gatt_client_multi_adv_data ev = {
+		.status = status,
+		.client_if = cb_data->client_if,
+	};
+
+	free_adv_instance(cb_data->adv);
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+				HAL_EV_GATT_CLIENT_MULTI_ADV_DISABLE,
+				sizeof(ev), &ev);
+
+	free(cb_data);
 }
 
 static void handle_client_disable_multi_adv_inst(const void *buf, uint16_t len)
 {
 	const struct hal_cmd_gatt_client_disable_multi_adv_inst *cmd = buf;
+	struct adv_instance *adv;
+	struct gatt_app *app;
+	struct addrm_adv_cb_data *cb_data = NULL;
+	uint8_t status = HAL_STATUS_FAILED;
 
 	DBG("client_if %d", cmd->client_if);
 
-	/* TODO */
+	adv = find_adv_instance(cmd->client_if);
+	if (!adv)
+		goto out;
+
+	cb_data = new0(typeof(*cb_data), 1);
+	cb_data->client_if = cmd->client_if;
+	cb_data->adv = adv;
+
+	if (!bt_le_remove_advertising(adv, remove_advertising_cb, cb_data)) {
+		error("gatt: Could not remove advertising");
+		free(cb_data);
+		goto out;
+	}
+
+	app = find_app_by_id(cmd->client_if);
+	if (app)
+		app->adv = NULL;
 
+	status = HAL_STATUS_SUCCESS;
+
+out:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_GATT,
 				HAL_OP_GATT_CLIENT_DISABLE_MULTI_ADV_INST,
-				HAL_STATUS_UNSUPPORTED);
+				status);
+
+	if (status != HAL_STATUS_SUCCESS) {
+		struct hal_ev_gatt_client_multi_adv_data ev = {
+			.status = status,
+			.client_if = cmd->client_if,
+		};
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_GATT,
+				HAL_EV_GATT_CLIENT_MULTI_ADV_DISABLE,
+				sizeof(ev), &ev);
+	}
 }
 
 static void handle_client_configure_batchscan(const void *buf, uint16_t len)
@@ -5824,7 +6113,7 @@ static const struct ipc_handler cmd_handlers[] = {
 	{ handle_client_update_multi_adv, false,
 		sizeof(struct hal_cmd_gatt_client_update_multi_adv) },
 	/* HAL_OP_GATT_CLIENT_SETUP_MULTI_ADV_INST */
-	{ handle_client_setup_multi_adv_inst, false,
+	{ handle_client_setup_multi_adv_inst, true,
 		sizeof(struct hal_cmd_gatt_client_setup_multi_adv_inst) },
 	/* HAL_OP_GATT_CLIENT_DISABLE_MULTI_ADV_INST */
 	{ handle_client_disable_multi_adv_inst, false,


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

* Re: [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support
  2017-10-13 14:02 [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Martin Fuzzey
                   ` (2 preceding siblings ...)
  2017-10-13 14:02 ` [PATCH V2 BLueZ 3/3] android: Enable multiadvertising Martin Fuzzey
@ 2017-11-06  9:25 ` Szymon Janc
  3 siblings, 0 replies; 5+ messages in thread
From: Szymon Janc @ 2017-11-06  9:25 UTC (permalink / raw)
  To: Martin Fuzzey; +Cc: linux-bluetooth

Hi Martin,

On Friday, 13 October 2017 16:02:04 CET Martin Fuzzey wrote:
> This series adds a few missing pieces for Peripheral role support on Android
> 5.
> 
> This has been tested in the following configuration:
> - Android 5.1.1
> - Kernel 4.4
> - nRF52 chip running Apache Newt firmware
> 
> Changes for V2:
> - Only load keys if BRDE supported rather than always trying and ignoring
> error - Use the bt_ad_* helper functions rather than open coding
> advertisement data - free_adv_instance() accepts NULL like the other free
> family members - Style fixes
> - Remove SOBs
> 

All patches applied, thanks.
Note that I had to fix last patch to build on Fedora (print formatters).

-- 
pozdrawiam
Szymon Janc

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

end of thread, other threads:[~2017-11-06  9:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-13 14:02 [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Martin Fuzzey
2017-10-13 14:02 ` [PATCH V2 BLueZ 1/3] android: Skip key loading for LE only devices Martin Fuzzey
2017-10-13 14:02 ` [PATCH V2 BLueZ 2/3] android: Get max advertising instances from kernel Martin Fuzzey
2017-10-13 14:02 ` [PATCH V2 BLueZ 3/3] android: Enable multiadvertising Martin Fuzzey
2017-11-06  9:25 ` [PATCH V2 BlueZ 0/3] android: Add LE Peripheral role support Szymon Janc

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.