Commit 90a5d027 authored by Andries Kruithof's avatar Andries Kruithof Committed by Carles Cufi
Browse files

Bluetooth: audio: bap: add support for long read



Make sure that buffers are large enough and add
semaphores so that we can do long reads

Signed-off-by: default avatarAndries Kruithof <andries.kruithof@nordicsemi.no>
parent 9887ebf4
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -235,6 +235,15 @@ config BT_BAP_SCAN_DELEGATOR_MAX_SUBGROUPS
	help
	  The maximum number of BIS subgroups supported.

config BT_BAP_SCAN_DELEGATOR_BUF_TIMEOUT
	int "Milliseconds of timeout when handle concurrent access to the long read ASE buffer"
	range 0 1000
	default 50
	help
	  The number of milliseconds that the scan delegator implementation will maximum wait
	  before rejecting a ASE read or dropping a notification if the scan delegator state is
	  being accessed by another thread.

endif # BT_BAP_SCAN_DELEGATOR

config BT_BAP_BROADCAST_ASSISTANT
+63 −8
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/l2cap.h>
#include <zephyr/bluetooth/buf.h>

#include <zephyr/logging/log.h>
@@ -32,6 +33,8 @@ LOG_MODULE_REGISTER(bt_bap_scan_delegator, CONFIG_BT_BAP_SCAN_DELEGATOR_LOG_LEVE

#define PAST_TIMEOUT              K_SECONDS(10)

#define SCAN_DELEGATOR_BUF_SEM_TIMEOUT K_MSEC(CONFIG_BT_BAP_SCAN_DELEGATOR_BUF_TIMEOUT)
static K_SEM_DEFINE(read_buf_sem, 1, 1);
NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, BT_ATT_MAX_ATTRIBUTE_LEN);

enum bass_recv_state_internal_flag {
@@ -137,11 +140,29 @@ static void bt_debug_dump_recv_state(const struct bass_recv_state_internal *recv
	}
}

static void bass_notify_receive_state(const struct bass_recv_state_internal *internal_state)
static void bass_notify_receive_state(struct bt_conn *conn,
				      const struct bass_recv_state_internal *internal_state)
{
	int err = bt_gatt_notify_uuid(NULL, BT_UUID_BASS_RECV_STATE,
	const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */
	uint16_t max_ntf_size;
	uint16_t ntf_size;
	int err;

	if (conn != NULL) {
		max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size;
	} else {
		max_ntf_size = MIN(BT_L2CAP_RX_MTU, BT_L2CAP_TX_MTU) - att_ntf_header_size;
	}

	ntf_size = MIN(max_ntf_size, read_buf.len);
	if (ntf_size < read_buf.len) {
		LOG_DBG("Sending truncated notification (%u/%u)", ntf_size, read_buf.len);
	}

	LOG_DBG("Sending bytes %d", ntf_size);
	err = bt_gatt_notify_uuid(NULL, BT_UUID_BASS_RECV_STATE,
				      internal_state->attr, read_buf.data,
				      read_buf.len);
				      ntf_size);

	if (err != 0 && err != -ENOTCONN) {
		LOG_DBG("Could not notify receive state: %d", err);
@@ -158,6 +179,7 @@ static void net_buf_put_recv_state(const struct bass_recv_state_internal *recv_s

	if (!recv_state->active) {
		/* Notify empty */

		return;
	}

@@ -187,21 +209,31 @@ static void net_buf_put_recv_state(const struct bass_recv_state_internal *recv_s
static void receive_state_updated(struct bt_conn *conn,
				  const struct bass_recv_state_internal *internal_state)
{
	int err;

	/* If something is holding the NOTIFY_PEND flag we should not notify now */
	if (atomic_test_bit(internal_state->flags,
			    BASS_RECV_STATE_INTERNAL_FLAG_NOTIFY_PEND)) {
		return;
	}

	err = k_sem_take(&read_buf_sem, SCAN_DELEGATOR_BUF_SEM_TIMEOUT);
	if (err != 0) {
		LOG_DBG("Failed to take read_buf_sem: %d", err);

		return;
	}

	bt_debug_dump_recv_state(internal_state);
	net_buf_put_recv_state(internal_state);
	bass_notify_receive_state(internal_state);

	bass_notify_receive_state(conn, internal_state);
	if (scan_delegator_cbs != NULL &&
	    scan_delegator_cbs->recv_state_updated != NULL) {
		scan_delegator_cbs->recv_state_updated(conn,
						       &internal_state->state);
	}

	k_sem_give(&read_buf_sem);
}

static void bis_sync_request_updated(struct bt_conn *conn,
@@ -254,11 +286,21 @@ static void scan_delegator_security_changed(struct bt_conn *conn,
			continue;
		}

		err = k_sem_take(&read_buf_sem, SCAN_DELEGATOR_BUF_SEM_TIMEOUT);
		if (err != 0) {
			LOG_DBG("Failed to take read_buf_sem: %d", err);

			return;
		}

		net_buf_put_recv_state(internal_state);

		gatt_err = bt_gatt_notify_uuid(conn, BT_UUID_BASS_RECV_STATE,
					       internal_state->attr, read_buf.data,
					       read_buf.len);

		k_sem_give(&read_buf_sem);

		if (gatt_err != 0) {
			LOG_WRN("Could not notify receive state[%d] to reconnecting assistant: %d",
				i, gatt_err);
@@ -1025,14 +1067,27 @@ static ssize_t read_recv_state(struct bt_conn *conn,
	struct bt_bap_scan_delegator_recv_state *state = &recv_state->state;

	if (recv_state->active) {
		ssize_t ret_val;
		int err;

		LOG_DBG("Index %u: Source ID 0x%02x", idx, state->src_id);

		bt_debug_dump_recv_state(recv_state);
		err = k_sem_take(&read_buf_sem, SCAN_DELEGATOR_BUF_SEM_TIMEOUT);
		if (err != 0) {
			LOG_DBG("Failed to take read_buf_sem: %d", err);

			return err;
		}

		bt_debug_dump_recv_state(recv_state);
		net_buf_put_recv_state(recv_state);

		return bt_gatt_attr_read(conn, attr, buf, len, offset,
		ret_val = bt_gatt_attr_read(conn, attr, buf, len, offset,
					    read_buf.data, read_buf.len);

		k_sem_give(&read_buf_sem);

		return ret_val;
	} else {
		LOG_DBG("Index %u: Not active", idx);