Bluetooth: Audio: Use BT_GATT_SUBSCRIBE_FLAG_VOLATILE
The LE Audio implementations do not really support bonding yet, and removing subs on disconnect is the most effective (and correct) way of ensuring that we do not subscribe more than once when we re-discover after reconnection. The broadcast assistant and the media control client does not support multiple connections as of this commit, so they needed special treatment. In the case that we do discovery on multiple ACL connections, it is important that the existing subscriptions are removed correctly by calling bt_gatt_unsubscribe. In order to implement this change properly on some of the clients, thet had no proper connection references or support for clearing the data on disconnects, they had to be updated as well. The csip_notify.sh test has been disabled, as that expected a notification in the client, but since this commit removes that (until bonding is properly supported in the clients), then the test will fail. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
922ac3c7c1
commit
ec41dd9ba6
14 changed files with 325 additions and 122 deletions
|
@ -618,6 +618,8 @@ static uint8_t aics_discover_func(struct bt_conn *conn, const struct bt_gatt_att
|
|||
*/
|
||||
sub_params->ccc_handle = attr->handle + 2;
|
||||
sub_params->notify = aics_client_notify_handler;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
LOG_ERR("Failed to subscribe: %d", err);
|
||||
|
@ -651,16 +653,6 @@ static void aics_client_reset(struct bt_aics *inst)
|
|||
if (inst->cli.conn != NULL) {
|
||||
struct bt_conn *conn = inst->cli.conn;
|
||||
|
||||
/* It's okay if these fail. In case of disconnect, we can't
|
||||
* unsubscribe and they will just fail.
|
||||
* In case that we reset due to another call of the discover
|
||||
* function, we will unsubscribe (regardless of bonding state)
|
||||
* to accommodate the new discovery values.
|
||||
*/
|
||||
(void)bt_gatt_unsubscribe(conn, &inst->cli.state_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &inst->cli.status_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &inst->cli.desc_sub_params);
|
||||
|
||||
bt_conn_unref(conn);
|
||||
inst->cli.conn = NULL;
|
||||
}
|
||||
|
@ -711,7 +703,6 @@ int bt_aics_discover(struct bt_conn *conn, struct bt_aics *inst,
|
|||
|
||||
(void)memset(&inst->cli.discover_params, 0, sizeof(inst->cli.discover_params));
|
||||
|
||||
inst->cli.conn = bt_conn_ref(conn);
|
||||
inst->cli.discover_params.start_handle = param->start_handle;
|
||||
inst->cli.discover_params.end_handle = param->end_handle;
|
||||
inst->cli.discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
@ -722,6 +713,7 @@ int bt_aics_discover(struct bt_conn *conn, struct bt_aics *inst,
|
|||
LOG_DBG("Discover failed (err %d)", err);
|
||||
} else {
|
||||
inst->cli.busy = true;
|
||||
inst->cli.conn = bt_conn_ref(conn);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
@ -35,7 +35,7 @@ LOG_MODULE_REGISTER(bt_bap_broadcast_assistant, CONFIG_BT_BAP_BROADCAST_ASSISTAN
|
|||
#define MINIMUM_RECV_STATE_LEN 15
|
||||
|
||||
struct bap_broadcast_assistant_instance {
|
||||
bool discovering;
|
||||
struct bt_conn *conn;
|
||||
bool scanning;
|
||||
uint8_t pa_sync;
|
||||
uint8_t recv_state_cnt;
|
||||
|
@ -61,7 +61,6 @@ struct bap_broadcast_assistant_instance {
|
|||
struct bt_gatt_discover_params disc_params;
|
||||
|
||||
struct k_work_delayable bap_read_work;
|
||||
struct bt_conn *conn;
|
||||
uint16_t long_read_handle;
|
||||
};
|
||||
|
||||
|
@ -431,8 +430,8 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
if (cb_err != 0) {
|
||||
LOG_DBG("err: %d", cb_err);
|
||||
if (broadcast_assistant.discovering) {
|
||||
broadcast_assistant.discovering = false;
|
||||
if (broadcast_assistant.busy) {
|
||||
broadcast_assistant.busy = false;
|
||||
if (broadcast_assistant_cbs != NULL &&
|
||||
broadcast_assistant_cbs->discover != NULL) {
|
||||
broadcast_assistant_cbs->discover(conn,
|
||||
|
@ -447,8 +446,8 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err,
|
|||
}
|
||||
}
|
||||
} else if (handle == last_handle) {
|
||||
if (broadcast_assistant.discovering) {
|
||||
broadcast_assistant.discovering = false;
|
||||
if (broadcast_assistant.busy) {
|
||||
broadcast_assistant.busy = false;
|
||||
if (broadcast_assistant_cbs != NULL &&
|
||||
broadcast_assistant_cbs->discover != NULL) {
|
||||
broadcast_assistant_cbs->discover(
|
||||
|
@ -486,8 +485,6 @@ static uint8_t read_recv_state_cb(struct bt_conn *conn, uint8_t err,
|
|||
|
||||
static void discover_init(void)
|
||||
{
|
||||
(void)memset(&broadcast_assistant, 0, sizeof(broadcast_assistant));
|
||||
|
||||
k_work_init_delayable(&broadcast_assistant.bap_read_work, delayed_bap_read_handler);
|
||||
|
||||
net_buf_simple_reset(&att_buf);
|
||||
|
@ -512,7 +509,7 @@ static uint8_t char_discover_func(struct bt_conn *conn,
|
|||
|
||||
err = bt_bap_broadcast_assistant_read_recv_state(conn, 0);
|
||||
if (err != 0) {
|
||||
broadcast_assistant.discovering = false;
|
||||
broadcast_assistant.busy = false;
|
||||
if (broadcast_assistant_cbs != NULL &&
|
||||
broadcast_assistant_cbs->discover != NULL) {
|
||||
broadcast_assistant_cbs->discover(conn, err, 0);
|
||||
|
@ -552,13 +549,14 @@ static uint8_t char_discover_func(struct bt_conn *conn,
|
|||
sub_params->value = BT_GATT_CCC_NOTIFY;
|
||||
sub_params->value_handle = attr->handle + 1;
|
||||
sub_params->notify = notify_handler;
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err != 0) {
|
||||
LOG_DBG("Could not subscribe to handle 0x%04x: %d",
|
||||
sub_params->value_handle, err);
|
||||
|
||||
broadcast_assistant.discovering = false;
|
||||
broadcast_assistant.busy = false;
|
||||
if (broadcast_assistant_cbs != NULL &&
|
||||
broadcast_assistant_cbs->discover != NULL) {
|
||||
broadcast_assistant_cbs->discover(conn,
|
||||
|
@ -585,7 +583,7 @@ static uint8_t service_discover_func(struct bt_conn *conn,
|
|||
LOG_DBG("Could not discover BASS");
|
||||
(void)memset(params, 0, sizeof(*params));
|
||||
|
||||
broadcast_assistant.discovering = false;
|
||||
broadcast_assistant.busy = false;
|
||||
|
||||
if (broadcast_assistant_cbs != NULL &&
|
||||
broadcast_assistant_cbs->discover != NULL) {
|
||||
|
@ -612,7 +610,7 @@ static uint8_t service_discover_func(struct bt_conn *conn,
|
|||
err = bt_gatt_discover(conn, &broadcast_assistant.disc_params);
|
||||
if (err != 0) {
|
||||
LOG_DBG("Discover failed (err %d)", err);
|
||||
broadcast_assistant.discovering = false;
|
||||
broadcast_assistant.busy = false;
|
||||
|
||||
if (broadcast_assistant_cbs != NULL &&
|
||||
broadcast_assistant_cbs->discover != NULL) {
|
||||
|
@ -759,16 +757,56 @@ static struct bt_le_scan_cb scan_cb = {
|
|||
|
||||
static int broadcast_assistant_reset(struct bap_broadcast_assistant_instance *inst)
|
||||
{
|
||||
broadcast_assistant.long_read_handle = 0;
|
||||
(void)k_work_cancel_delayable(&broadcast_assistant.bap_read_work);
|
||||
inst->busy = false;
|
||||
inst->scanning = false;
|
||||
inst->pa_sync = 0U;
|
||||
inst->recv_state_cnt = 0U;
|
||||
inst->start_handle = 0U;
|
||||
inst->end_handle = 0U;
|
||||
inst->cp_handle = 0U;
|
||||
inst->long_read_handle = 0;
|
||||
(void)k_work_cancel_delayable(&inst->bap_read_work);
|
||||
|
||||
for (int i = 0U; i < CONFIG_BT_BAP_BROADCAST_ASSISTANT_RECV_STATE_COUNT; i++) {
|
||||
inst->src_ids[i] = 0U;
|
||||
inst->past_avail[i] = false;
|
||||
inst->recv_state_handles[i] = 0U;
|
||||
}
|
||||
|
||||
if (inst->conn != NULL) {
|
||||
struct bt_conn *conn = inst->conn;
|
||||
struct bt_conn_info info;
|
||||
int err;
|
||||
|
||||
err = bt_conn_get_info(conn, &info);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (info.state == BT_CONN_STATE_CONNECTED) {
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(inst->recv_state_sub_params); i++) {
|
||||
/* It's okay if this fail with -EINVAL as that means that they are
|
||||
* not currently subscribed
|
||||
*/
|
||||
err = bt_gatt_unsubscribe(conn, &inst->recv_state_sub_params[i]);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to state: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
inst->conn = NULL;
|
||||
}
|
||||
|
||||
/* The subscribe parameters must remain instact so they can get cleaned up by GATT */
|
||||
memset(&inst->disc_params, 0, sizeof(inst->disc_params));
|
||||
memset(&inst->recv_state_disc_params, 0, sizeof(inst->recv_state_disc_params));
|
||||
memset(&inst->read_params, 0, sizeof(inst->read_params));
|
||||
memset(&inst->write_params, 0, sizeof(inst->write_params));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -817,7 +855,7 @@ int bt_bap_broadcast_assistant_discover(struct bt_conn *conn)
|
|||
return err;
|
||||
}
|
||||
|
||||
broadcast_assistant.discovering = true;
|
||||
broadcast_assistant.busy = true;
|
||||
broadcast_assistant.conn = bt_conn_ref(conn);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1611,6 +1611,7 @@ static uint8_t unicast_client_ep_notify(struct bt_conn *conn,
|
|||
static int unicast_client_ep_subscribe(struct bt_conn *conn, struct bt_bap_ep *ep)
|
||||
{
|
||||
struct bt_bap_unicast_client_ep *client_ep;
|
||||
int err;
|
||||
|
||||
client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
|
||||
|
||||
|
@ -1628,7 +1629,12 @@ static int unicast_client_ep_subscribe(struct bt_conn *conn, struct bt_bap_ep *e
|
|||
client_ep->subscribe.value = BT_GATT_CCC_NOTIFY;
|
||||
atomic_set_bit(client_ep->subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
return bt_gatt_subscribe(conn, &client_ep->subscribe);
|
||||
err = bt_gatt_subscribe(conn, &client_ep->subscribe);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pac_record_cb(struct bt_conn *conn, const struct bt_audio_codec_cap *codec_cap)
|
||||
|
@ -1718,7 +1724,7 @@ static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
|
|||
atomic_set_bit(client->cp_subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, &client->cp_subscribe);
|
||||
if (err != 0) {
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
LOG_DBG("Failed to subscribe: %d", err);
|
||||
|
||||
discover_cb(conn, err);
|
||||
|
@ -3510,6 +3516,7 @@ static uint8_t unicast_client_pacs_avail_ctx_discover_cb(struct bt_conn *conn,
|
|||
sub_params->disc_params = &uni_cli_insts[index].avail_ctx_cc_disc;
|
||||
sub_params->notify = unicast_client_pacs_avail_ctx_notify_cb;
|
||||
sub_params->value = BT_GATT_CCC_NOTIFY;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
|
@ -3708,6 +3715,7 @@ static uint8_t unicast_client_pacs_location_discover_cb(struct bt_conn *conn,
|
|||
sub_params->disc_params = &uni_cli_insts[index].loc_cc_disc;
|
||||
sub_params->notify = unicast_client_pacs_location_notify_cb;
|
||||
sub_params->value = BT_GATT_CCC_NOTIFY;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
|
|
|
@ -747,6 +747,7 @@ static uint8_t discover_func(struct bt_conn *conn,
|
|||
sub_params->end_handle = cur_inst->end_handle;
|
||||
sub_params->value_handle = chrc->value_handle;
|
||||
sub_params->notify = notify_handler;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
|
@ -1342,20 +1343,6 @@ static void csip_set_coordinator_reset(struct bt_csip_set_coordinator_inst *inst
|
|||
if (svc_inst->conn != NULL) {
|
||||
struct bt_conn *conn = svc_inst->conn;
|
||||
|
||||
/* It's okay if these fail. In case of disconnect,
|
||||
* we can't unsubscribe and they will just fail.
|
||||
* In case that we reset due to another call of the
|
||||
* discover function, we will unsubscribe (regardless of
|
||||
* bonding state) to accommodate the new discovery
|
||||
* values.
|
||||
*/
|
||||
(void)bt_gatt_unsubscribe(conn,
|
||||
&svc_inst->sirk_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn,
|
||||
&svc_inst->size_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn,
|
||||
&svc_inst->lock_sub_params);
|
||||
|
||||
bt_conn_unref(conn);
|
||||
svc_inst->conn = NULL;
|
||||
}
|
||||
|
|
|
@ -425,6 +425,8 @@ static void active_index_subscribe_cb(struct bt_conn *conn, uint8_t att_err,
|
|||
|
||||
static int active_index_subscribe(struct bt_has_client *inst, uint16_t value_handle)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_DBG("conn %p handle 0x%04x", (void *)inst->conn, value_handle);
|
||||
|
||||
inst->active_index_subscription.notify = active_preset_notify_cb;
|
||||
|
@ -436,7 +438,12 @@ static int active_index_subscribe(struct bt_has_client *inst, uint16_t value_han
|
|||
inst->active_index_subscription.value = BT_GATT_CCC_NOTIFY;
|
||||
atomic_set_bit(inst->active_index_subscription.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
return bt_gatt_subscribe(inst->conn, &inst->active_index_subscription);
|
||||
err = bt_gatt_subscribe(inst->conn, &inst->active_index_subscription);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t active_index_read_cb(struct bt_conn *conn, uint8_t att_err,
|
||||
|
@ -520,6 +527,8 @@ fail:
|
|||
static int control_point_subscribe(struct bt_has_client *inst, uint16_t value_handle,
|
||||
uint8_t properties)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_DBG("conn %p handle 0x%04x", (void *)inst->conn, value_handle);
|
||||
|
||||
inst->control_point_subscription.notify = control_point_notify_cb;
|
||||
|
@ -536,7 +545,12 @@ static int control_point_subscribe(struct bt_has_client *inst, uint16_t value_ha
|
|||
inst->control_point_subscription.value = BT_GATT_CCC_INDICATE;
|
||||
}
|
||||
|
||||
return bt_gatt_subscribe(inst->conn, &inst->control_point_subscription);
|
||||
err = bt_gatt_subscribe(inst->conn, &inst->control_point_subscription);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t control_point_discover_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
|
@ -709,6 +723,8 @@ static uint8_t features_notify_cb(struct bt_conn *conn, struct bt_gatt_subscribe
|
|||
|
||||
static int features_subscribe(struct bt_has_client *inst, uint16_t value_handle)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_DBG("conn %p handle 0x%04x", (void *)inst->conn, value_handle);
|
||||
|
||||
inst->features_subscription.notify = features_notify_cb;
|
||||
|
@ -720,7 +736,12 @@ static int features_subscribe(struct bt_has_client *inst, uint16_t value_handle)
|
|||
inst->features_subscription.value = BT_GATT_CCC_NOTIFY;
|
||||
atomic_set_bit(inst->features_subscription.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
return bt_gatt_subscribe(inst->conn, &inst->features_subscription);
|
||||
err = bt_gatt_subscribe(inst->conn, &inst->features_subscription);
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t features_discover_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
|
|
|
@ -1156,77 +1156,215 @@ static uint8_t mcs_notify_handler(struct bt_conn *conn,
|
|||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static void reset_mcs_inst(struct mcs_instance_t *mcs_inst, struct bt_conn *conn)
|
||||
static int reset_mcs_inst(struct mcs_instance_t *mcs_inst)
|
||||
{
|
||||
(void)memset(mcs_inst, 0, offsetof(struct mcs_instance_t, busy));
|
||||
if (mcs_inst->conn != NULL) {
|
||||
struct bt_conn *conn = mcs_inst->conn;
|
||||
struct bt_conn_info info;
|
||||
int err;
|
||||
|
||||
err = bt_conn_get_info(conn, &info);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (info.state == BT_CONN_STATE_CONNECTED) {
|
||||
/* It's okay if these fail with -EINVAL as that means that they are
|
||||
* not currently subscribed
|
||||
*/
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->player_name_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to name: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->track_changed_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to track change: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* It's okay if these fail. In case of disconnect, we can't
|
||||
* unsubscribe and they will just fail.
|
||||
* In case that we reset due to another call of the discover
|
||||
* function, we will unsubscribe (regardless of bonding state)
|
||||
* to accommodate the new discovery values.
|
||||
*/
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->player_name_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->track_changed_sub_params);
|
||||
#if defined(CONFIG_BT_MCC_READ_TRACK_TITLE_ENABLE_SUBSCRIPTION)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->track_title_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->track_title_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to track title: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE_ENABLE_SUBSCRIPTION) */
|
||||
|
||||
#if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->track_duration_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->track_duration_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to track duration: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
|
||||
|
||||
#if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->track_position_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->track_position_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to track position: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
|
||||
|
||||
#if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->playback_speed_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->playback_speed_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to playback speed: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
|
||||
|
||||
#if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->seeking_speed_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->seeking_speed_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to seeking speed: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
|
||||
|
||||
#ifdef CONFIG_BT_MCC_OTS
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->current_track_obj_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->next_track_obj_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->parent_group_obj_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->current_group_obj_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->current_track_obj_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to current track object: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->next_track_obj_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to next track object: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->parent_group_obj_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to parent group object: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->current_group_obj_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to current group object: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BT_MCC_OTS */
|
||||
#if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->playing_order_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->playing_order_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to playing order: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
|
||||
|
||||
#if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->media_state_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->media_state_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to media state: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->cp_sub_params);
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->cp_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to control point: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->opcodes_supported_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->opcodes_supported_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to supported opcodes: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
|
||||
|
||||
#ifdef CONFIG_BT_MCC_OTS
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->scp_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->search_results_obj_sub_params);
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->scp_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to search control point: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->search_results_obj_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to search results: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->otc.oacp_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to oacp: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = bt_gatt_unsubscribe(conn, &mcs_inst->otc.olcp_sub_params);
|
||||
if (err != 0 && err != -EINVAL) {
|
||||
LOG_DBG("Failed to unsubscribe to olcp: %d", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_BT_MCC_OTS */
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
mcs_inst->conn = NULL;
|
||||
}
|
||||
|
||||
(void)memset(mcs_inst, 0, offsetof(struct mcs_instance_t, busy));
|
||||
#ifdef CONFIG_BT_MCC_OTS
|
||||
/* Reset OTC instance as well if supported */
|
||||
(void)memset(&mcs_inst->otc, 0, offsetof(struct bt_ots_client, oacp_sub_params));
|
||||
#endif /* CONFIG_BT_MCC_OTS */
|
||||
|
||||
/* Reset OTC instance as well if supported */
|
||||
#ifdef CONFIG_BT_MCC_OTS
|
||||
(void)memset(&mcs_inst->otc, 0,
|
||||
offsetof(struct bt_ots_client, oacp_sub_params));
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->otc.oacp_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &mcs_inst->otc.olcp_sub_params);
|
||||
#endif /* CONFIG_BT_MCC_OTS */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void disconnected_cb(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
struct mcs_instance_t *mcs_inst;
|
||||
|
||||
mcs_inst = lookup_inst_by_conn(conn);
|
||||
if (mcs_inst != NULL) {
|
||||
(void)reset_mcs_inst(mcs_inst);
|
||||
}
|
||||
}
|
||||
|
||||
BT_CONN_CB_DEFINE(conn_callbacks) = {
|
||||
.disconnected = disconnected_cb,
|
||||
};
|
||||
|
||||
/* Called when discovery is completed - successfully or with error */
|
||||
static void discovery_complete(struct bt_conn *conn, int err)
|
||||
{
|
||||
struct mcs_instance_t *mcs_inst;
|
||||
|
||||
LOG_DBG("Discovery completed, err: %d", err);
|
||||
|
||||
/* TODO: Handle resets of instance, and re-discovery.
|
||||
* For now, reset instance on error.
|
||||
*/
|
||||
if (err) {
|
||||
struct mcs_instance_t *mcs_inst;
|
||||
|
||||
mcs_inst = lookup_inst_by_conn(conn);
|
||||
if (mcs_inst != NULL) {
|
||||
reset_mcs_inst(mcs_inst, conn);
|
||||
mcs_inst = lookup_inst_by_conn(conn);
|
||||
if (mcs_inst != NULL) {
|
||||
mcs_inst->busy = false;
|
||||
if (err != 0) {
|
||||
(void)reset_mcs_inst(mcs_inst);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1296,6 +1434,7 @@ static uint8_t discover_otc_char_func(struct bt_conn *conn,
|
|||
sub_params->value = BT_GATT_CCC_INDICATE;
|
||||
sub_params->value_handle = chrc->value_handle;
|
||||
sub_params->notify = bt_ots_client_indicate_handler;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err != 0) {
|
||||
|
@ -1463,7 +1602,7 @@ static int do_subscribe(struct mcs_instance_t *mcs_inst, struct bt_conn *conn,
|
|||
sub_params->subscribe = subscribe_mcs_char_func;
|
||||
/* disc_params pointer is also used as subscription flag */
|
||||
sub_params->disc_params = &mcs_inst->discover_params;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_NO_RESUB);
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
LOG_DBG("Subscring to handle %d", handle);
|
||||
return bt_gatt_subscribe(conn, sub_params);
|
||||
|
@ -1945,6 +2084,7 @@ int bt_mcc_init(struct bt_mcc_cb *cb)
|
|||
int bt_mcc_discover_mcs(struct bt_conn *conn, bool subscribe)
|
||||
{
|
||||
struct mcs_instance_t *mcs_inst;
|
||||
int err;
|
||||
|
||||
CHECKIF(!conn) {
|
||||
return -EINVAL;
|
||||
|
@ -1961,7 +2101,12 @@ int bt_mcc_discover_mcs(struct bt_conn *conn, bool subscribe)
|
|||
}
|
||||
|
||||
subscribe_all = subscribe;
|
||||
reset_mcs_inst(mcs_inst, conn);
|
||||
err = reset_mcs_inst(mcs_inst);
|
||||
if (err != 0) {
|
||||
LOG_DBG("Failed to reset MCS instance %p: %d", mcs_inst, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
(void)memcpy(&uuid, BT_UUID_GMCS, sizeof(uuid));
|
||||
|
||||
mcs_inst->discover_params.func = discover_primary_func;
|
||||
|
@ -1971,7 +2116,15 @@ int bt_mcc_discover_mcs(struct bt_conn *conn, bool subscribe)
|
|||
mcs_inst->discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
|
||||
|
||||
LOG_DBG("start discovery of GMCS primary service");
|
||||
return bt_gatt_discover(conn, &mcs_inst->discover_params);
|
||||
err = bt_gatt_discover(conn, &mcs_inst->discover_params);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
mcs_inst->conn = bt_conn_ref(conn);
|
||||
mcs_inst->busy = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mcc_read_player_name(struct bt_conn *conn)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
struct mcs_instance_t *lookup_inst_by_conn(struct bt_conn *conn);
|
||||
|
||||
struct mcs_instance_t {
|
||||
struct bt_conn *conn;
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
uint16_t player_name_handle;
|
||||
|
|
|
@ -409,9 +409,10 @@ static uint8_t micp_discover_func(struct bt_conn *conn,
|
|||
sub_params->value = BT_GATT_CCC_NOTIFY;
|
||||
sub_params->value_handle = chrc->value_handle;
|
||||
sub_params->notify = mute_notify_handler;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err == 0) {
|
||||
if (err == 0 || err == -EALREADY) {
|
||||
LOG_DBG("Subscribed to handle 0x%04X", attr->handle);
|
||||
} else {
|
||||
LOG_DBG("Could not subscribe to handle 0x%04X: %d", attr->handle,
|
||||
|
@ -480,14 +481,6 @@ static void micp_mic_ctlr_reset(struct bt_micp_mic_ctlr *mic_ctlr)
|
|||
if (mic_ctlr->conn != NULL) {
|
||||
struct bt_conn *conn = mic_ctlr->conn;
|
||||
|
||||
/* It's okay if this fails. In case of disconnect, we can't
|
||||
* unsubscribe and it will just fail.
|
||||
* In case that we reset due to another call of the discover
|
||||
* function, we will unsubscribe (regardless of bonding state)
|
||||
* to accommodate the new discovery values.
|
||||
*/
|
||||
(void)bt_gatt_unsubscribe(conn, &mic_ctlr->mute_sub_params);
|
||||
|
||||
bt_conn_unref(conn);
|
||||
mic_ctlr->conn = NULL;
|
||||
}
|
||||
|
|
|
@ -1539,8 +1539,9 @@ static uint8_t discover_func(struct bt_conn *conn,
|
|||
sub_params->end_handle = current_inst->end_handle;
|
||||
sub_params->notify = notify_handler;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err != 0) {
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
LOG_DBG("Could not subscribe to "
|
||||
"characterstic at handle 0x%04X"
|
||||
"(%d)",
|
||||
|
|
|
@ -449,8 +449,10 @@ static uint8_t vcs_discover_func(struct bt_conn *conn,
|
|||
sub_params->ccc_handle = 0;
|
||||
sub_params->end_handle = vol_ctlr->end_handle;
|
||||
sub_params->notify = vcp_vol_ctlr_notify_handler;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err == 0) {
|
||||
if (err == 0 || err == -EALREADY) {
|
||||
LOG_DBG("Subscribed to handle 0x%04X",
|
||||
attr->handle);
|
||||
} else {
|
||||
|
@ -817,15 +819,6 @@ static void vcp_vol_ctlr_reset(struct bt_vcp_vol_ctlr *vol_ctlr)
|
|||
if (vol_ctlr->conn != NULL) {
|
||||
struct bt_conn *conn = vol_ctlr->conn;
|
||||
|
||||
/* It's okay if these fail. In case of disconnect, we can't
|
||||
* unsubscribe and they will just fail.
|
||||
* In case that we reset due to another call of the discover
|
||||
* function, we will unsubscribe (regardless of bonding state)
|
||||
* to accommodate the new discovery values.
|
||||
*/
|
||||
(void)bt_gatt_unsubscribe(conn, &vol_ctlr->state_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &vol_ctlr->flag_sub_params);
|
||||
|
||||
bt_conn_unref(conn);
|
||||
vol_ctlr->conn = NULL;
|
||||
}
|
||||
|
|
|
@ -411,9 +411,15 @@ static uint8_t vocs_discover_func(struct bt_conn *conn, const struct bt_gatt_att
|
|||
*/
|
||||
sub_params->ccc_handle = attr->handle + 2;
|
||||
sub_params->notify = vocs_client_notify_handler;
|
||||
atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
|
||||
|
||||
err = bt_gatt_subscribe(conn, sub_params);
|
||||
if (err) {
|
||||
if (err != 0 && err != -EALREADY) {
|
||||
LOG_WRN("Could not subscribe to handle %u", sub_params->ccc_handle);
|
||||
|
||||
inst->cb->discover(&inst->vocs, err);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -687,16 +693,6 @@ static void vocs_client_reset(struct bt_vocs_client *inst)
|
|||
if (inst->conn != NULL) {
|
||||
struct bt_conn *conn = inst->conn;
|
||||
|
||||
/* It's okay if these fail. In case of disconnect, we can't
|
||||
* unsubscribe and they will just fail.
|
||||
* In case that we reset due to another call of the discover
|
||||
* function, we will unsubscribe (regardless of bonding state)
|
||||
* to accommodate the new discovery values.
|
||||
*/
|
||||
(void)bt_gatt_unsubscribe(conn, &inst->state_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &inst->location_sub_params);
|
||||
(void)bt_gatt_unsubscribe(conn, &inst->desc_sub_params);
|
||||
|
||||
bt_conn_unref(conn);
|
||||
inst->conn = NULL;
|
||||
}
|
||||
|
|
|
@ -307,6 +307,16 @@ static void test_bass_discover(void)
|
|||
return;
|
||||
}
|
||||
|
||||
WAIT_FOR_FLAG(flag_discovery_complete);
|
||||
|
||||
/* Verify that we can discover again */
|
||||
flag_discovery_complete = false;
|
||||
err = bt_bap_broadcast_assistant_discover(default_conn);
|
||||
if (err != 0) {
|
||||
FAIL("Failed to discover BASS for the second time: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
WAIT_FOR_FLAG(flag_discovery_complete);
|
||||
printk("Discovery complete\n");
|
||||
}
|
||||
|
|
|
@ -832,6 +832,16 @@ static void test_discover(void)
|
|||
}
|
||||
|
||||
WAIT_FOR_COND(g_discovery_complete);
|
||||
|
||||
/* Verify that we can discover again */
|
||||
g_discovery_complete = false;
|
||||
err = bt_vcp_vol_ctlr_discover(default_conn, &vol_ctlr);
|
||||
if (err != 0) {
|
||||
FAIL("Failed to discover VCP for the second time: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
WAIT_FOR_COND(g_discovery_complete);
|
||||
}
|
||||
|
||||
static void test_included_get(void)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue