Bluetooth: Audio: ASCS: Make ASE Allocation Dynamic
Decoupled the ASEs from the ASCS Session and made them dynamically allocated instead. A Kconfig option was added to set the maximum number of active ASEs at a single time. The intent here is to allow the developer greater control over memory usage; this fix addresses one of the largest ram usages in le audio. Signed-off-by: Fredrik Danebjer <fredrik@danebjer.com>
This commit is contained in:
parent
15644da0a4
commit
18a889fb8b
3 changed files with 160 additions and 84 deletions
|
@ -35,4 +35,13 @@ config BT_ASCS_ASE_SNK
|
||||||
config BT_ASCS_ASE_SRC
|
config BT_ASCS_ASE_SRC
|
||||||
def_bool BT_ASCS_ASE_SRC_COUNT > 0
|
def_bool BT_ASCS_ASE_SRC_COUNT > 0
|
||||||
select BT_PAC_SRC
|
select BT_PAC_SRC
|
||||||
|
|
||||||
|
config BT_ASCS_MAX_ACTIVE_ASES
|
||||||
|
int "Number of simultaneously supported ASE sessions"
|
||||||
|
default BT_ISO_MAX_CHAN
|
||||||
|
range 1 65535
|
||||||
|
help
|
||||||
|
The number of simultanesouly supported active ASEs, in particular
|
||||||
|
meaning the number of ASEs that are allowed to be in a non-idle state at
|
||||||
|
a single time.
|
||||||
endif # BT_ASCS
|
endif # BT_ASCS
|
||||||
|
|
|
@ -39,6 +39,14 @@ LOG_MODULE_REGISTER(bt_ascs, CONFIG_BT_ASCS_LOG_LEVEL);
|
||||||
#include "pacs_internal.h"
|
#include "pacs_internal.h"
|
||||||
#include "cap_internal.h"
|
#include "cap_internal.h"
|
||||||
|
|
||||||
|
#define MAX_ASES_SESSIONS CONFIG_BT_MAX_CONN * \
|
||||||
|
(CONFIG_BT_ASCS_ASE_SNK_COUNT + \
|
||||||
|
CONFIG_BT_ASCS_ASE_SRC_COUNT)
|
||||||
|
|
||||||
|
BUILD_ASSERT(CONFIG_BT_ASCS_MAX_ACTIVE_ASES <= MAX(MAX_ASES_SESSIONS,
|
||||||
|
CONFIG_BT_ISO_MAX_CHAN),
|
||||||
|
"Max active ASEs are set to more than actual number of ASEs or ISOs");
|
||||||
|
|
||||||
#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER)
|
#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER)
|
||||||
|
|
||||||
#define ASE_ID(_ase) ase->ep.status.id
|
#define ASE_ID(_ase) ase->ep.status.id
|
||||||
|
@ -52,17 +60,43 @@ struct bt_ascs_ase {
|
||||||
struct bt_ascs *ascs;
|
struct bt_ascs *ascs;
|
||||||
struct bt_audio_ep ep;
|
struct bt_audio_ep ep;
|
||||||
const struct bt_gatt_attr *attr;
|
const struct bt_gatt_attr *attr;
|
||||||
|
sys_snode_t node;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bt_ascs {
|
struct bt_ascs {
|
||||||
struct bt_conn *conn;
|
struct bt_conn *conn;
|
||||||
struct bt_ascs_ase ases[ASE_COUNT];
|
sys_slist_t ases;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
K_MEM_SLAB_DEFINE(ase_slab, sizeof(struct bt_ascs_ase),
|
||||||
|
CONFIG_BT_ASCS_MAX_ACTIVE_ASES,
|
||||||
|
__alignof__(struct bt_ascs_ase));
|
||||||
|
|
||||||
static struct bt_ascs sessions[CONFIG_BT_MAX_CONN];
|
static struct bt_ascs sessions[CONFIG_BT_MAX_CONN];
|
||||||
|
|
||||||
static int control_point_notify(struct bt_conn *conn, const void *data, uint16_t len);
|
static int control_point_notify(struct bt_conn *conn, const void *data, uint16_t len);
|
||||||
|
|
||||||
|
static void bt_ascs_ase_return_to_slab(struct bt_ascs_ase *ase)
|
||||||
|
{
|
||||||
|
__ASSERT(ase && ase->ascs, "Non-existing ASE or ASCS");
|
||||||
|
|
||||||
|
LOG_DBG("Returning ase %p to slab", ase);
|
||||||
|
|
||||||
|
sys_slist_find_and_remove(&ase->ascs->ases, &ase->node);
|
||||||
|
k_mem_slab_free(&ase_slab, (void **)&ase);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_ascs_ase *bt_ascs_ase_get_from_slab(void)
|
||||||
|
{
|
||||||
|
struct bt_ascs_ase *ase = NULL;
|
||||||
|
|
||||||
|
if (k_mem_slab_alloc(&ase_slab, (void **)&ase, K_NO_WAIT) < 0) {
|
||||||
|
LOG_DBG("Could not get ASE from slab, out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ase;
|
||||||
|
}
|
||||||
|
|
||||||
static void ase_status_changed(struct bt_audio_ep *ep, uint8_t old_state,
|
static void ase_status_changed(struct bt_audio_ep *ep, uint8_t old_state,
|
||||||
uint8_t state)
|
uint8_t state)
|
||||||
{
|
{
|
||||||
|
@ -105,6 +139,10 @@ void ascs_ep_set_state(struct bt_audio_ep *ep, uint8_t state)
|
||||||
if (ops->released != NULL) {
|
if (ops->released != NULL) {
|
||||||
ops->released(stream);
|
ops->released(stream);
|
||||||
}
|
}
|
||||||
|
struct bt_ascs_ase *ase = CONTAINER_OF(ep, struct bt_ascs_ase, ep);
|
||||||
|
|
||||||
|
/* Return the ase to slab */
|
||||||
|
bt_ascs_ase_return_to_slab(ase);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case BT_AUDIO_EP_STATE_CODEC_CONFIGURED:
|
case BT_AUDIO_EP_STATE_CODEC_CONFIGURED:
|
||||||
|
@ -353,6 +391,26 @@ static void ascs_ep_get_status_enable(struct bt_audio_ep *ep,
|
||||||
LOG_DBG("dir 0x%02x cig 0x%02x cis 0x%02x", ep->dir, ep->cig_id, ep->cis_id);
|
LOG_DBG("dir 0x%02x cig 0x%02x cis 0x%02x", ep->dir, ep->cig_id, ep->cis_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ascs_ep_get_status_idle(uint8_t ase_id, struct net_buf_simple *buf)
|
||||||
|
{
|
||||||
|
struct bt_ascs_ase_status *status;
|
||||||
|
|
||||||
|
if (!buf || ase_id > ASE_COUNT) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_buf_simple_reset(buf);
|
||||||
|
|
||||||
|
status = net_buf_simple_add(buf, sizeof(*status));
|
||||||
|
status->id = ase_id;
|
||||||
|
status->state = BT_AUDIO_EP_STATE_IDLE;
|
||||||
|
|
||||||
|
LOG_DBG("id 0x%02x state %s", ase_id,
|
||||||
|
bt_audio_ep_state_str(status->state));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ascs_ep_get_status(struct bt_audio_ep *ep,
|
static int ascs_ep_get_status(struct bt_audio_ep *ep,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
|
@ -823,12 +881,19 @@ static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(session->ases); i++) {
|
sys_snode_t *ase_node, *s;
|
||||||
struct bt_ascs_ase *ase = &session->ases[i];
|
|
||||||
struct bt_audio_stream *stream = ase->ep.stream;
|
SYS_SLIST_FOR_EACH_NODE_SAFE(&session->ases, ase_node, s) {
|
||||||
|
struct bt_audio_stream *stream;
|
||||||
|
struct bt_ascs_ase *ase;
|
||||||
|
|
||||||
|
ase = CONTAINER_OF(ase_node, struct bt_ascs_ase, node);
|
||||||
|
stream = ase->ep.stream;
|
||||||
|
|
||||||
if (ase->ep.status.state != BT_AUDIO_EP_STATE_IDLE) {
|
if (ase->ep.status.state != BT_AUDIO_EP_STATE_IDLE) {
|
||||||
/* ase_process will handle the final state transition into idle state */
|
/* ase_process will handle the final state transition into idle
|
||||||
|
* state, where the ase finally will be deallocated
|
||||||
|
*/
|
||||||
ase_release(ase);
|
ase_release(ase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,7 +1062,6 @@ void ascs_ep_init(struct bt_audio_ep *ep, uint8_t id)
|
||||||
|
|
||||||
static void ase_init(struct bt_ascs_ase *ase, uint8_t id)
|
static void ase_init(struct bt_ascs_ase *ase, uint8_t id)
|
||||||
{
|
{
|
||||||
memset(ase, 0, sizeof(*ase));
|
|
||||||
ascs_ep_init(&ase->ep, id);
|
ascs_ep_init(&ase->ep, id);
|
||||||
|
|
||||||
/* Lookup ASE characteristic */
|
/* Lookup ASE characteristic */
|
||||||
|
@ -1009,30 +1073,19 @@ static void ase_init(struct bt_ascs_ase *ase, uint8_t id)
|
||||||
static struct bt_ascs_ase *ase_new(struct bt_ascs *ascs, uint8_t id)
|
static struct bt_ascs_ase *ase_new(struct bt_ascs *ascs, uint8_t id)
|
||||||
{
|
{
|
||||||
struct bt_ascs_ase *ase;
|
struct bt_ascs_ase *ase;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (id) {
|
if (!id || id > ASE_COUNT) {
|
||||||
if (id > ASE_COUNT) {
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
i = id;
|
|
||||||
ase = &ascs->ases[i - 1];
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ASE_COUNT; i++) {
|
ase = bt_ascs_ase_get_from_slab();
|
||||||
ase = &ascs->ases[i];
|
if (!ase) {
|
||||||
|
return NULL;
|
||||||
if (!ase->ep.status.id) {
|
|
||||||
i++;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
sys_slist_append(&ascs->ases, &ase->node);
|
||||||
|
|
||||||
done:
|
ase_init(ase, id);
|
||||||
ase_init(ase, i);
|
|
||||||
ase->ascs = ascs;
|
ase->ascs = ascs;
|
||||||
|
|
||||||
return ase;
|
return ase;
|
||||||
|
@ -1040,15 +1093,14 @@ done:
|
||||||
|
|
||||||
static struct bt_ascs_ase *ase_find(struct bt_ascs *ascs, uint8_t id)
|
static struct bt_ascs_ase *ase_find(struct bt_ascs *ascs, uint8_t id)
|
||||||
{
|
{
|
||||||
struct bt_ascs_ase *ase;
|
sys_snode_t *ase_node;
|
||||||
|
|
||||||
if (!id || id > ASE_COUNT) {
|
SYS_SLIST_FOR_EACH_NODE(&ascs->ases, ase_node) {
|
||||||
return NULL;
|
struct bt_ascs_ase *ase = CONTAINER_OF(ase_node, struct bt_ascs_ase, node);
|
||||||
}
|
|
||||||
|
|
||||||
ase = &ascs->ases[id - 1];
|
if (ase->ep.status.id == id) {
|
||||||
if (ase->ep.status.id == id) {
|
return ase;
|
||||||
return ase;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1072,16 +1124,25 @@ static ssize_t ascs_ase_read(struct bt_conn *conn,
|
||||||
{
|
{
|
||||||
struct bt_ascs *ascs = ascs_get(conn);
|
struct bt_ascs *ascs = ascs_get(conn);
|
||||||
struct bt_ascs_ase *ase;
|
struct bt_ascs_ase *ase;
|
||||||
|
uint8_t ase_id;
|
||||||
|
|
||||||
LOG_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len, offset);
|
LOG_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len, offset);
|
||||||
|
|
||||||
ase = ase_get(ascs, POINTER_TO_UINT(BT_AUDIO_CHRC_USER_DATA(attr)));
|
ase_id = POINTER_TO_UINT(BT_AUDIO_CHRC_USER_DATA(attr));
|
||||||
if (!ase) {
|
|
||||||
LOG_ERR("Unable to get ASE");
|
if (ase_id > ASE_COUNT) {
|
||||||
|
LOG_ERR("Unable to get ASE, id out of range");
|
||||||
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
|
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
|
||||||
}
|
}
|
||||||
|
|
||||||
ascs_ep_get_status(&ase->ep, &ase_buf);
|
ase = ase_find(ascs, ase_id);
|
||||||
|
|
||||||
|
/* If NULL, we haven't assigned an ASE, this also means that we are currently in IDLE */
|
||||||
|
if (!ase) {
|
||||||
|
ascs_ep_get_status_idle(ase_id, &ase_buf);
|
||||||
|
} else {
|
||||||
|
ascs_ep_get_status(&ase->ep, &ase_buf);
|
||||||
|
}
|
||||||
|
|
||||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, ase_buf.data,
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, ase_buf.data,
|
||||||
ase_buf.len);
|
ase_buf.len);
|
||||||
|
@ -1367,16 +1428,19 @@ static ssize_t ascs_config(struct bt_ascs *ascs, struct net_buf_simple *buf)
|
||||||
|
|
||||||
LOG_DBG("ase 0x%02x cc_len %u", cfg->ase, cfg->cc_len);
|
LOG_DBG("ase 0x%02x cc_len %u", cfg->ase, cfg->cc_len);
|
||||||
|
|
||||||
if (cfg->ase) {
|
if (!cfg->ase || cfg->ase > ASE_COUNT) {
|
||||||
ase = ase_get(ascs, cfg->ase);
|
LOG_WRN("Invalid ASE ID: %u", cfg->ase);
|
||||||
|
ascs_cp_rsp_add(cfg->ase, BT_ASCS_CONFIG_OP,
|
||||||
|
BT_ASCS_RSP_INVALID_ASE, 0x00);
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
ase = ase_new(ascs, 0);
|
ase = ase_get(ascs, cfg->ase);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ase) {
|
if (!ase) {
|
||||||
ascs_cp_rsp_add(cfg->ase, BT_ASCS_CONFIG_OP,
|
ascs_cp_rsp_add(cfg->ase, BT_ASCS_CONFIG_OP,
|
||||||
BT_ASCS_RSP_INVALID_ASE, 0x00);
|
BT_ASCS_RSP_NO_MEM, 0x00);
|
||||||
LOG_WRN("Unknown ase 0x%02x", cfg->ase);
|
LOG_WRN("No free ASE found for config ASE ID 0x%02x", cfg->ase);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,11 @@ static const struct bt_uuid *ase_snk_uuid = BT_UUID_ASCS_ASE_SNK;
|
||||||
static const struct bt_uuid *ase_src_uuid = BT_UUID_ASCS_ASE_SRC;
|
static const struct bt_uuid *ase_src_uuid = BT_UUID_ASCS_ASE_SRC;
|
||||||
static const struct bt_uuid *cp_uuid = BT_UUID_ASCS_ASE_CP;
|
static const struct bt_uuid *cp_uuid = BT_UUID_ASCS_ASE_CP;
|
||||||
|
|
||||||
static struct bt_unicast_client_ep snks[CONFIG_BT_MAX_CONN][CONFIG_BT_AUDIO_UNICAST_CLIENT_ASE_SNK_COUNT];
|
|
||||||
static struct bt_unicast_client_ep srcs[CONFIG_BT_MAX_CONN][CONFIG_BT_AUDIO_UNICAST_CLIENT_ASE_SRC_COUNT];
|
static struct bt_unicast_client_ep snks[CONFIG_BT_MAX_CONN]
|
||||||
|
[CONFIG_BT_AUDIO_UNICAST_CLIENT_ASE_SNK_COUNT];
|
||||||
|
static struct bt_unicast_client_ep srcs[CONFIG_BT_MAX_CONN]
|
||||||
|
[CONFIG_BT_AUDIO_UNICAST_CLIENT_ASE_SRC_COUNT];
|
||||||
|
|
||||||
static struct bt_gatt_subscribe_params cp_subscribe[CONFIG_BT_MAX_CONN];
|
static struct bt_gatt_subscribe_params cp_subscribe[CONFIG_BT_MAX_CONN];
|
||||||
static struct bt_gatt_subscribe_params snk_loc_subscribe[CONFIG_BT_MAX_CONN];
|
static struct bt_gatt_subscribe_params snk_loc_subscribe[CONFIG_BT_MAX_CONN];
|
||||||
|
@ -235,14 +238,14 @@ static struct bt_iso_chan_ops unicast_client_iso_ops = {
|
||||||
static void unicast_client_ep_init(struct bt_audio_ep *ep, uint16_t handle,
|
static void unicast_client_ep_init(struct bt_audio_ep *ep, uint16_t handle,
|
||||||
uint8_t dir)
|
uint8_t dir)
|
||||||
{
|
{
|
||||||
struct bt_unicast_client_ep *client;
|
struct bt_unicast_client_ep *client_ep;
|
||||||
|
|
||||||
LOG_DBG("ep %p dir 0x%02x handle 0x%04x", ep, dir, handle);
|
LOG_DBG("ep %p dir 0x%02x handle 0x%04x", ep, dir, handle);
|
||||||
|
|
||||||
client = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
client_ep = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
||||||
|
|
||||||
(void)memset(ep, 0, sizeof(*ep));
|
(void)memset(ep, 0, sizeof(*ep));
|
||||||
client->handle = handle;
|
client_ep->handle = handle;
|
||||||
ep->status.id = 0U;
|
ep->status.id = 0U;
|
||||||
ep->dir = dir;
|
ep->dir = dir;
|
||||||
}
|
}
|
||||||
|
@ -256,20 +259,20 @@ static struct bt_audio_ep *unicast_client_ep_find(struct bt_conn *conn,
|
||||||
index = bt_conn_index(conn);
|
index = bt_conn_index(conn);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(snks[index]); i++) {
|
for (i = 0; i < ARRAY_SIZE(snks[index]); i++) {
|
||||||
struct bt_unicast_client_ep *client = &snks[index][i];
|
struct bt_unicast_client_ep *client_ep = &snks[index][i];
|
||||||
|
|
||||||
if ((handle && client->handle == handle) ||
|
if ((handle && client_ep->handle == handle) ||
|
||||||
(!handle && client->handle)) {
|
(!handle && client_ep->handle)) {
|
||||||
return &client->ep;
|
return &client_ep->ep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(srcs[index]); i++) {
|
for (i = 0; i < ARRAY_SIZE(srcs[index]); i++) {
|
||||||
struct bt_unicast_client_ep *client = &srcs[index][i];
|
struct bt_unicast_client_ep *client_ep = &srcs[index][i];
|
||||||
|
|
||||||
if ((handle && client->handle == handle) ||
|
if ((handle && client_ep->handle == handle) ||
|
||||||
(!handle && client->handle)) {
|
(!handle && client_ep->handle)) {
|
||||||
return &client->ep;
|
return &client_ep->ep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,11 +319,11 @@ static struct bt_audio_ep *unicast_client_ep_new(struct bt_conn *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
struct bt_unicast_client_ep *client = &cache[i];
|
struct bt_unicast_client_ep *client_ep = &cache[i];
|
||||||
|
|
||||||
if (!client->handle) {
|
if (!client_ep->handle) {
|
||||||
unicast_client_ep_init(&client->ep, handle, dir);
|
unicast_client_ep_init(&client_ep->ep, handle, dir);
|
||||||
return &client->ep;
|
return &client_ep->ep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,7 +681,7 @@ static void unicast_client_ep_set_status(struct bt_audio_ep *ep,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
struct bt_ascs_ase_status *status;
|
struct bt_ascs_ase_status *status;
|
||||||
struct bt_unicast_client_ep *client;
|
struct bt_unicast_client_ep *client_ep;
|
||||||
bool state_changed;
|
bool state_changed;
|
||||||
uint8_t old_state;
|
uint8_t old_state;
|
||||||
|
|
||||||
|
@ -686,7 +689,7 @@ static void unicast_client_ep_set_status(struct bt_audio_ep *ep,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
client_ep = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
||||||
|
|
||||||
status = net_buf_simple_pull_mem(buf, sizeof(*status));
|
status = net_buf_simple_pull_mem(buf, sizeof(*status));
|
||||||
|
|
||||||
|
@ -694,7 +697,7 @@ static void unicast_client_ep_set_status(struct bt_audio_ep *ep,
|
||||||
ep->status = *status;
|
ep->status = *status;
|
||||||
state_changed = old_state != ep->status.state;
|
state_changed = old_state != ep->status.state;
|
||||||
|
|
||||||
LOG_DBG("ep %p handle 0x%04x id 0x%02x dir %u state %s -> %s", ep, client->handle,
|
LOG_DBG("ep %p handle 0x%04x id 0x%02x dir %u state %s -> %s", ep, client_ep->handle,
|
||||||
status->id, ep->dir, bt_audio_ep_state_str(old_state),
|
status->id, ep->dir, bt_audio_ep_state_str(old_state),
|
||||||
bt_audio_ep_state_str(status->state));
|
bt_audio_ep_state_str(status->state));
|
||||||
|
|
||||||
|
@ -1083,11 +1086,11 @@ static uint8_t unicast_client_ep_notify(struct bt_conn *conn,
|
||||||
const void *data, uint16_t length)
|
const void *data, uint16_t length)
|
||||||
{
|
{
|
||||||
struct net_buf_simple buf;
|
struct net_buf_simple buf;
|
||||||
struct bt_unicast_client_ep *client;
|
struct bt_unicast_client_ep *client_ep;
|
||||||
|
|
||||||
client = CONTAINER_OF(params, struct bt_unicast_client_ep, subscribe);
|
client_ep = CONTAINER_OF(params, struct bt_unicast_client_ep, subscribe);
|
||||||
|
|
||||||
LOG_DBG("conn %p ep %p len %u", conn, &client->ep, length);
|
LOG_DBG("conn %p ep %p len %u", conn, &client_ep->ep, length);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
LOG_DBG("Unsubscribed");
|
LOG_DBG("Unsubscribed");
|
||||||
|
@ -1102,7 +1105,7 @@ static uint8_t unicast_client_ep_notify(struct bt_conn *conn,
|
||||||
return BT_GATT_ITER_STOP;
|
return BT_GATT_ITER_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
unicast_client_ep_set_status(&client->ep, &buf);
|
unicast_client_ep_set_status(&client_ep->ep, &buf);
|
||||||
|
|
||||||
return BT_GATT_ITER_CONTINUE;
|
return BT_GATT_ITER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -1110,25 +1113,25 @@ static uint8_t unicast_client_ep_notify(struct bt_conn *conn,
|
||||||
static int unicast_client_ep_subscribe(struct bt_conn *conn,
|
static int unicast_client_ep_subscribe(struct bt_conn *conn,
|
||||||
struct bt_audio_ep *ep)
|
struct bt_audio_ep *ep)
|
||||||
{
|
{
|
||||||
struct bt_unicast_client_ep *client;
|
struct bt_unicast_client_ep *client_ep;
|
||||||
|
|
||||||
client = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
client_ep = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
||||||
|
|
||||||
LOG_DBG("ep %p handle 0x%02x", ep, client->handle);
|
LOG_DBG("ep %p handle 0x%02x", ep, client_ep->handle);
|
||||||
|
|
||||||
if (client->subscribe.value_handle) {
|
if (client_ep->subscribe.value_handle) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->subscribe.value_handle = client->handle;
|
client_ep->subscribe.value_handle = client_ep->handle;
|
||||||
client->subscribe.ccc_handle = 0x0000;
|
client_ep->subscribe.ccc_handle = 0x0000;
|
||||||
client->subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
|
client_ep->subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
|
||||||
client->subscribe.disc_params = &client->discover;
|
client_ep->subscribe.disc_params = &client_ep->discover;
|
||||||
client->subscribe.notify = unicast_client_ep_notify;
|
client_ep->subscribe.notify = unicast_client_ep_notify;
|
||||||
client->subscribe.value = BT_GATT_CCC_NOTIFY;
|
client_ep->subscribe.value = BT_GATT_CCC_NOTIFY;
|
||||||
atomic_set_bit(client->subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
atomic_set_bit(client_ep->subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||||
|
|
||||||
return bt_gatt_subscribe(conn, &client->subscribe);
|
return bt_gatt_subscribe(conn, &client_ep->subscribe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
|
static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
|
||||||
|
@ -1154,18 +1157,18 @@ static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(snks[index]); i++) {
|
for (i = 0; i < ARRAY_SIZE(snks[index]); i++) {
|
||||||
struct bt_unicast_client_ep *client = &snks[index][i];
|
struct bt_unicast_client_ep *client_ep = &snks[index][i];
|
||||||
|
|
||||||
if (client->handle) {
|
if (client_ep->handle) {
|
||||||
client->cp_handle = handle;
|
client_ep->cp_handle = handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(srcs[index]); i++) {
|
for (i = 0; i < ARRAY_SIZE(srcs[index]); i++) {
|
||||||
struct bt_unicast_client_ep *client = &srcs[index][i];
|
struct bt_unicast_client_ep *client_ep = &srcs[index][i];
|
||||||
|
|
||||||
if (client->handle) {
|
if (client_ep->handle) {
|
||||||
client->cp_handle = handle;
|
client_ep->cp_handle = handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1449,11 +1452,11 @@ static int unicast_client_ep_release(struct bt_audio_ep *ep,
|
||||||
int bt_unicast_client_ep_send(struct bt_conn *conn, struct bt_audio_ep *ep,
|
int bt_unicast_client_ep_send(struct bt_conn *conn, struct bt_audio_ep *ep,
|
||||||
struct net_buf_simple *buf)
|
struct net_buf_simple *buf)
|
||||||
{
|
{
|
||||||
struct bt_unicast_client_ep *client = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
struct bt_unicast_client_ep *client_ep = CONTAINER_OF(ep, struct bt_unicast_client_ep, ep);
|
||||||
|
|
||||||
LOG_DBG("conn %p ep %p buf %p len %u", conn, ep, buf, buf->len);
|
LOG_DBG("conn %p ep %p buf %p len %u", conn, ep, buf, buf->len);
|
||||||
|
|
||||||
return bt_gatt_write_without_response(conn, client->cp_handle,
|
return bt_gatt_write_without_response(conn, client_ep->cp_handle,
|
||||||
buf->data, buf->len, false);
|
buf->data, buf->len, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue