Lines Matching +full:source +full:- +full:dir

7  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
9 * SPDX-License-Identifier: Apache-2.0
56 "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT shall be non-zero");
68 #define PAC_DIR_UNUSED(dir) ((dir) != BT_AUDIO_DIR_SINK && (dir) != BT_AUDIO_DIR_SOURCE) argument
124 enum bt_audio_dir dir; member
161 if (ep->receiver_ready != true || ep->dir != BT_AUDIO_DIR_SOURCE) { in unicast_client_send_start()
163 ep, ep->receiver_ready, bt_audio_dir_str(ep->dir)); in unicast_client_send_start()
165 return -EINVAL; in unicast_client_send_start()
172 buf = bt_bap_unicast_client_ep_create_pdu(ep->stream->conn, BT_ASCS_START_OP); in unicast_client_send_start()
175 return -EBUSY; in unicast_client_send_start()
179 req->num_ases = 1U; in unicast_client_send_start()
189 err = bt_bap_unicast_client_ep_send(ep->stream->conn, ep, buf); in unicast_client_send_start()
215 if (client_ep->ep.status.id == id) { in audio_stream_by_ep_id()
216 return client_ep->ep.stream; in audio_stream_by_ep_id()
226 if (client_ep->ep.status.id == id) { in audio_stream_by_ep_id()
227 return client_ep->ep.stream; in audio_stream_by_ep_id()
237 net_buf_simple_init_with_data(&client->net_buf, &client->att_buf, sizeof(client->att_buf)); in reset_att_buf()
238 net_buf_simple_reset(&client->net_buf); in reset_att_buf()
248 struct bt_bap_ep *ep = iso->rx.ep; in unicast_client_ep_iso_recv()
259 if ((info->flags & BT_ISO_FLAGS_VALID) != 0) { in unicast_client_ep_iso_recv()
267 if (ep->status.state != BT_BAP_EP_STATE_STREAMING) { in unicast_client_ep_iso_recv()
270 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_iso_recv()
276 stream = ep->stream; in unicast_client_ep_iso_recv()
282 ops = stream->ops; in unicast_client_ep_iso_recv()
288 if (ops != NULL && ops->recv != NULL) { in unicast_client_ep_iso_recv()
289 ops->recv(stream, info, buf); in unicast_client_ep_iso_recv()
301 struct bt_bap_ep *ep = iso->tx.ep; in unicast_client_ep_iso_sent()
308 stream = ep->stream; in unicast_client_ep_iso_sent()
318 if (stream->ops != NULL && stream->ops->sent != NULL) { in unicast_client_ep_iso_sent()
319 stream->ops->sent(stream); in unicast_client_ep_iso_sent()
329 if (ep->unicast_group != NULL) { in unicast_client_ep_iso_connected()
330 ep->unicast_group->has_been_connected = true; in unicast_client_ep_iso_connected()
333 if (ep->status.state != BT_BAP_EP_STATE_ENABLING) { in unicast_client_ep_iso_connected()
335 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_iso_connected()
339 stream = ep->stream; in unicast_client_ep_iso_connected()
345 LOG_DBG("stream %p ep %p dir %s receiver_ready %u", in unicast_client_ep_iso_connected()
346 stream, ep, bt_audio_dir_str(ep->dir), ep->receiver_ready); in unicast_client_ep_iso_connected()
350 stream->_prev_seq_num = 0U; in unicast_client_ep_iso_connected()
353 stream_ops = stream->ops; in unicast_client_ep_iso_connected()
354 if (stream_ops != NULL && stream_ops->connected != NULL) { in unicast_client_ep_iso_connected()
355 stream_ops->connected(stream); in unicast_client_ep_iso_connected()
363 if (iso->rx.ep == NULL && iso->tx.ep == NULL) { in unicast_client_iso_connected()
368 if (iso->rx.ep != NULL) { in unicast_client_iso_connected()
369 unicast_client_ep_iso_connected(iso->rx.ep); in unicast_client_iso_connected()
372 if (iso->tx.ep != NULL) { in unicast_client_iso_connected()
373 unicast_client_ep_iso_connected(iso->tx.ep); in unicast_client_iso_connected()
382 stream = ep->stream; in unicast_client_ep_iso_disconnected()
389 ep->reason = reason; in unicast_client_ep_iso_disconnected()
391 stream_ops = stream->ops; in unicast_client_ep_iso_disconnected()
392 if (stream_ops != NULL && stream_ops->disconnected != NULL) { in unicast_client_ep_iso_disconnected()
393 stream_ops->disconnected(stream, reason); in unicast_client_ep_iso_disconnected()
400 if (ep->status.state == BT_BAP_EP_STATE_IDLE) { in unicast_client_ep_iso_disconnected()
404 if (stream->conn != NULL) { in unicast_client_ep_iso_disconnected()
408 err = bt_conn_get_info(stream->conn, &conn_info); in unicast_client_ep_iso_disconnected()
423 if (iso->rx.ep == NULL && iso->tx.ep == NULL) { in unicast_client_iso_disconnected()
428 if (iso->rx.ep != NULL) { in unicast_client_iso_disconnected()
429 unicast_client_ep_iso_disconnected(iso->rx.ep, reason); in unicast_client_iso_disconnected()
432 if (iso->tx.ep != NULL) { in unicast_client_iso_disconnected()
433 unicast_client_ep_iso_disconnected(iso->tx.ep, reason); in unicast_client_iso_disconnected()
467 static void unicast_client_ep_init(struct bt_bap_ep *ep, uint16_t handle, uint8_t dir) in unicast_client_ep_init() argument
471 LOG_DBG("ep %p dir %s handle 0x%04x", ep, bt_audio_dir_str(dir), handle); in unicast_client_ep_init()
476 client_ep->handle = handle; in unicast_client_ep_init()
477 ep->status.id = 0U; in unicast_client_ep_init()
478 ep->dir = dir; in unicast_client_ep_init()
479 ep->reason = BT_HCI_ERR_SUCCESS; in unicast_client_ep_init()
480 k_work_init_delayable(&client_ep->ase_read_work, delayed_ase_read_handler); in unicast_client_ep_init()
493 if ((handle && client_ep->handle == handle) || (!handle && client_ep->handle)) { in unicast_client_ep_find()
494 return &client_ep->ep; in unicast_client_ep_find()
503 if ((handle && client_ep->handle == handle) || (!handle && client_ep->handle)) { in unicast_client_ep_find()
504 return &client_ep->ep; in unicast_client_ep_find()
528 static struct bt_bap_ep *unicast_client_ep_new(struct bt_conn *conn, enum bt_audio_dir dir, in unicast_client_ep_new() argument
537 switch (dir) { in unicast_client_ep_new()
557 if (!client_ep->handle) { in unicast_client_ep_new()
558 unicast_client_ep_init(&client_ep->ep, handle, dir); in unicast_client_ep_new()
559 return &client_ep->ep; in unicast_client_ep_new()
566 static struct bt_bap_ep *unicast_client_ep_get(struct bt_conn *conn, enum bt_audio_dir dir, in unicast_client_ep_get() argument
576 return unicast_client_ep_new(conn, dir, handle); in unicast_client_ep_get()
582 .id = ep->status.id, in unicast_client_ep_set_local_idle_state()
592 static void unicast_client_notify_location(struct bt_conn *conn, enum bt_audio_dir dir, in unicast_client_notify_location() argument
598 if (listener->location != NULL) { in unicast_client_notify_location()
599 listener->location(conn, dir, loc); in unicast_client_notify_location()
611 if (listener->available_contexts != NULL) { in unicast_client_notify_available_contexts()
612 listener->available_contexts(conn, snk_ctx, src_ctx); in unicast_client_notify_available_contexts()
622 const enum bt_audio_dir dir = client->dir; in unicast_client_notify_pac_record() local
630 if (listener->pac_record != NULL) { in unicast_client_notify_pac_record()
631 listener->pac_record(conn, dir, codec_cap); in unicast_client_notify_pac_record()
640 const enum bt_audio_dir dir = client->dir; in unicast_client_notify_endpoint() local
643 if (listener->endpoint != NULL) { in unicast_client_notify_endpoint()
644 listener->endpoint(conn, dir, ep); in unicast_client_notify_endpoint()
653 const enum bt_audio_dir dir = client->dir; in unicast_client_discover_complete() local
655 /* Discover complete - Reset discovery values */ in unicast_client_discover_complete()
656 client->dir = 0U; in unicast_client_discover_complete()
658 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in unicast_client_discover_complete()
661 if (listener->discover != NULL) { in unicast_client_discover_complete()
662 listener->discover(conn, err, dir); in unicast_client_discover_complete()
674 if (listener->config != NULL) { in unicast_client_notify_ep_config()
675 listener->config(stream, rsp_code, reason); in unicast_client_notify_ep_config()
687 if (listener->qos != NULL) { in unicast_client_notify_ep_qos()
688 listener->qos(stream, rsp_code, reason); in unicast_client_notify_ep_qos()
700 if (listener->enable != NULL) { in unicast_client_notify_ep_enable()
701 listener->enable(stream, rsp_code, reason); in unicast_client_notify_ep_enable()
713 if (listener->start != NULL) { in unicast_client_notify_ep_start()
714 listener->start(stream, rsp_code, reason); in unicast_client_notify_ep_start()
726 if (listener->stop != NULL) { in unicast_client_notify_ep_stop()
727 listener->stop(stream, rsp_code, reason); in unicast_client_notify_ep_stop()
739 if (listener->disable != NULL) { in unicast_client_notify_ep_disable()
740 listener->disable(stream, rsp_code, reason); in unicast_client_notify_ep_disable()
752 if (listener->metadata != NULL) { in unicast_client_notify_ep_metadata()
753 listener->metadata(stream, rsp_code, reason); in unicast_client_notify_ep_metadata()
765 if (listener->release != NULL) { in unicast_client_notify_ep_released()
766 listener->release(stream, rsp_code, reason); in unicast_client_notify_ep_released()
775 struct bt_bap_stream *stream = ep->stream; in unicast_client_ep_idle_state()
778 ep->receiver_ready = false; in unicast_client_ep_idle_state()
796 } else if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) { in unicast_client_ep_idle_state()
804 if (client_ep->release_requested) { in unicast_client_ep_idle_state()
805 client_ep->release_requested = false; in unicast_client_ep_idle_state()
807 if (client_ep->cp_ntf_pending) { in unicast_client_ep_idle_state()
812 client_ep->cp_ntf_pending = false; in unicast_client_ep_idle_state()
819 ops = stream->ops; in unicast_client_ep_idle_state()
820 if (ops != NULL && ops->released != NULL) { in unicast_client_ep_idle_state()
821 ops->released(stream); in unicast_client_ep_idle_state()
832 LOG_DBG("ep %p dir %s bap_iso %p", ep, bt_audio_dir_str(ep->dir), ep->iso); in unicast_client_ep_qos_update()
834 if (ep->dir == BT_AUDIO_DIR_SOURCE) { in unicast_client_ep_qos_update()
835 /* If the endpoint is a source, then we need to in unicast_client_ep_qos_update()
838 iso_io_qos = &ep->iso->rx.qos; in unicast_client_ep_qos_update()
839 } else if (ep->dir == BT_AUDIO_DIR_SINK) { in unicast_client_ep_qos_update()
843 iso_io_qos = &ep->iso->tx.qos; in unicast_client_ep_qos_update()
845 __ASSERT(false, "Invalid ep->dir: %u", ep->dir); in unicast_client_ep_qos_update()
849 iso_io_qos->phy = qos->phy; in unicast_client_ep_qos_update()
850 iso_io_qos->sdu = sys_le16_to_cpu(qos->sdu); in unicast_client_ep_qos_update()
851 iso_io_qos->rtn = qos->rtn; in unicast_client_ep_qos_update()
863 ep->receiver_ready = false; in unicast_client_ep_config_state()
865 if (client_ep->release_requested) { in unicast_client_ep_config_state()
867 ep->reason = BT_HCI_ERR_LOCALHOST_TERM_CONN; in unicast_client_ep_config_state()
872 if (buf->len < sizeof(*cfg)) { in unicast_client_ep_config_state()
877 stream = ep->stream; in unicast_client_ep_config_state()
885 if (stream->codec_cfg == NULL) { in unicast_client_ep_config_state()
888 } else if (stream->codec_cfg->id != cfg->codec.id) { in unicast_client_ep_config_state()
889 LOG_ERR("Codec configuration mismatched: %u, %u", stream->codec_cfg->id, in unicast_client_ep_config_state()
890 cfg->codec.id); in unicast_client_ep_config_state()
895 if (buf->len < cfg->cc_len) { in unicast_client_ep_config_state()
896 LOG_ERR("Malformed ASE Config status: buf->len %u < %u cc_len", buf->len, in unicast_client_ep_config_state()
897 cfg->cc_len); in unicast_client_ep_config_state()
901 cc = net_buf_simple_pull_mem(buf, cfg->cc_len); in unicast_client_ep_config_state()
903 pref = &stream->ep->qos_pref; in unicast_client_ep_config_state()
906 pref->unframed_supported = cfg->framing == BT_ASCS_QOS_FRAMING_UNFRAMED; in unicast_client_ep_config_state()
907 pref->phy = cfg->phy; in unicast_client_ep_config_state()
908 pref->rtn = cfg->rtn; in unicast_client_ep_config_state()
909 pref->latency = sys_le16_to_cpu(cfg->latency); in unicast_client_ep_config_state()
910 pref->pd_min = sys_get_le24(cfg->pd_min); in unicast_client_ep_config_state()
911 pref->pd_max = sys_get_le24(cfg->pd_max); in unicast_client_ep_config_state()
912 pref->pref_pd_min = sys_get_le24(cfg->prefer_pd_min); in unicast_client_ep_config_state()
913 pref->pref_pd_max = sys_get_le24(cfg->prefer_pd_max); in unicast_client_ep_config_state()
915 LOG_DBG("dir %s unframed_supported 0x%02x phy 0x%02x rtn %u " in unicast_client_ep_config_state()
917 bt_audio_dir_str(ep->dir), pref->unframed_supported, pref->phy, pref->rtn, in unicast_client_ep_config_state()
918 pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max, in unicast_client_ep_config_state()
919 stream->codec_cfg->id); in unicast_client_ep_config_state()
931 unicast_client_ep_set_codec_cfg(ep, cfg->codec.id, sys_le16_to_cpu(cfg->codec.cid), in unicast_client_ep_config_state()
932 sys_le16_to_cpu(cfg->codec.vid), cc, cfg->cc_len, NULL); in unicast_client_ep_config_state()
935 if (stream->ops != NULL && stream->ops->configured != NULL) { in unicast_client_ep_config_state()
936 stream->ops->configured(stream, pref); in unicast_client_ep_config_state()
949 ep->receiver_ready = false; in unicast_client_ep_qos_state()
951 if (buf->len < sizeof(*qos)) { in unicast_client_ep_qos_state()
956 stream = ep->stream; in unicast_client_ep_qos_state()
961 ops = stream->ops; in unicast_client_ep_qos_state()
964 if (ep->dir == BT_AUDIO_DIR_SINK && ops->disabled != NULL) { in unicast_client_ep_qos_state()
973 ops->disabled(stream); in unicast_client_ep_qos_state()
975 } else if (ep->dir == BT_AUDIO_DIR_SOURCE && in unicast_client_ep_qos_state()
976 old_state == BT_BAP_EP_STATE_DISABLING && ops->stopped != NULL) { in unicast_client_ep_qos_state()
980 uint8_t reason = ep->reason; in unicast_client_ep_qos_state()
987 ep->reason = BT_HCI_ERR_SUCCESS; in unicast_client_ep_qos_state()
990 ops->stopped(stream, reason); in unicast_client_ep_qos_state()
999 ep->cig_id = qos->cig_id; in unicast_client_ep_qos_state()
1000 ep->cis_id = qos->cis_id; in unicast_client_ep_qos_state()
1001 (void)memcpy(&stream->qos->interval, sys_le24_to_cpu(qos->interval), sizeof(qos->interval)); in unicast_client_ep_qos_state()
1002 stream->qos->framing = qos->framing; in unicast_client_ep_qos_state()
1003 stream->qos->phy = qos->phy; in unicast_client_ep_qos_state()
1004 stream->qos->sdu = sys_le16_to_cpu(qos->sdu); in unicast_client_ep_qos_state()
1005 stream->qos->rtn = qos->rtn; in unicast_client_ep_qos_state()
1006 stream->qos->latency = sys_le16_to_cpu(qos->latency); in unicast_client_ep_qos_state()
1007 (void)memcpy(&stream->qos->pd, sys_le24_to_cpu(qos->pd), sizeof(qos->pd)); in unicast_client_ep_qos_state()
1009 LOG_DBG("dir %s cig 0x%02x cis 0x%02x codec 0x%02x interval %u " in unicast_client_ep_qos_state()
1011 bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id, stream->codec_cfg->id, in unicast_client_ep_qos_state()
1012 stream->qos->interval, stream->qos->framing, stream->qos->phy, stream->qos->rtn, in unicast_client_ep_qos_state()
1013 stream->qos->latency, stream->qos->pd); in unicast_client_ep_qos_state()
1024 * we have the ISO <-> EP coupling completed (due to setting in unicast_client_ep_qos_state()
1028 bt_bap_iso_configure_data_path(ep, stream->codec_cfg); in unicast_client_ep_qos_state()
1032 if (stream->ops != NULL && stream->ops->qos_set != NULL) { in unicast_client_ep_qos_state()
1033 stream->ops->qos_set(stream); in unicast_client_ep_qos_state()
1046 if (buf->len < sizeof(*enable)) { in unicast_client_ep_enabling_state()
1051 stream = ep->stream; in unicast_client_ep_enabling_state()
1059 if (buf->len < enable->metadata_len) { in unicast_client_ep_enabling_state()
1060 LOG_ERR("Malformed PDU: remaining len %u expected %u", buf->len, in unicast_client_ep_enabling_state()
1061 enable->metadata_len); in unicast_client_ep_enabling_state()
1065 metadata = net_buf_simple_pull_mem(buf, enable->metadata_len); in unicast_client_ep_enabling_state()
1067 LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id); in unicast_client_ep_enabling_state()
1069 unicast_client_ep_set_metadata(ep, metadata, enable->metadata_len, NULL); in unicast_client_ep_enabling_state()
1076 if (stream->ops != NULL && stream->ops->enabled != NULL) { in unicast_client_ep_enabling_state()
1077 stream->ops->enabled(stream); in unicast_client_ep_enabling_state()
1082 if (stream->ops != NULL && stream->ops->metadata_updated != NULL) { in unicast_client_ep_enabling_state()
1083 stream->ops->metadata_updated(stream); in unicast_client_ep_enabling_state()
1096 if (buf->len < sizeof(*stream_status)) { in unicast_client_ep_streaming_state()
1101 stream = ep->stream; in unicast_client_ep_streaming_state()
1109 LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id); in unicast_client_ep_streaming_state()
1116 if (stream->ops != NULL && stream->ops->started != NULL) { in unicast_client_ep_streaming_state()
1117 stream->ops->started(stream); in unicast_client_ep_streaming_state()
1122 if (stream->ops != NULL && stream->ops->metadata_updated != NULL) { in unicast_client_ep_streaming_state()
1123 stream->ops->metadata_updated(stream); in unicast_client_ep_streaming_state()
1135 ep->receiver_ready = false; in unicast_client_ep_disabling_state()
1137 if (buf->len < sizeof(*disable)) { in unicast_client_ep_disabling_state()
1142 stream = ep->stream; in unicast_client_ep_disabling_state()
1150 LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id); in unicast_client_ep_disabling_state()
1153 if (stream->ops != NULL && stream->ops->disabled != NULL) { in unicast_client_ep_disabling_state()
1154 stream->ops->disabled(stream); in unicast_client_ep_disabling_state()
1164 ep->receiver_ready = false; in unicast_client_ep_releasing_state()
1166 stream = ep->stream; in unicast_client_ep_releasing_state()
1172 LOG_DBG("dir %s", bt_audio_dir_str(ep->dir)); in unicast_client_ep_releasing_state()
1204 old_state = ep->status.state; in unicast_client_ep_set_status()
1205 ep->status = *status; in unicast_client_ep_set_status()
1206 state_changed = old_state != ep->status.state; in unicast_client_ep_set_status()
1211 struct bt_bap_stream *stream = ep->stream; in unicast_client_ep_set_status()
1214 struct bt_bap_stream_ops *ops = stream->ops; in unicast_client_ep_set_status()
1215 uint8_t reason = ep->reason; in unicast_client_ep_set_status()
1222 ep->reason = BT_HCI_ERR_SUCCESS; in unicast_client_ep_set_status()
1225 if (ops != NULL && ops->stopped != NULL) { in unicast_client_ep_set_status()
1226 ops->stopped(stream, reason); in unicast_client_ep_set_status()
1233 LOG_DBG("ep %p handle 0x%04x id 0x%02x dir %s state %s -> %s", ep, client_ep->handle, in unicast_client_ep_set_status()
1234 status->id, bt_audio_dir_str(ep->dir), bt_bap_ep_state_str(old_state), in unicast_client_ep_set_status()
1235 bt_bap_ep_state_str(status->state)); in unicast_client_ep_set_status()
1237 switch (status->state) { in unicast_client_ep_set_status()
1253 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1255 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1263 if (ep->dir == BT_AUDIO_DIR_SOURCE) { in unicast_client_ep_set_status()
1275 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1277 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1292 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1294 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1309 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1311 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1325 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1327 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1334 if (ep->dir == BT_AUDIO_DIR_SOURCE) { in unicast_client_ep_set_status()
1342 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1344 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1349 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1351 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1370 if (ep->dir == BT_AUDIO_DIR_SOURCE) { in unicast_client_ep_set_status()
1376 LOG_WRN("Invalid state transition: %s -> %s", in unicast_client_ep_set_status()
1378 bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_set_status()
1398 return -EINVAL; in unicast_client_ep_set_codec_cfg()
1404 codec_cfg = &ep->codec_cfg; in unicast_client_ep_set_codec_cfg()
1407 if (len > sizeof(codec_cfg->data)) { in unicast_client_ep_set_codec_cfg()
1410 return -ENOMEM; in unicast_client_ep_set_codec_cfg()
1413 codec_cfg->id = id; in unicast_client_ep_set_codec_cfg()
1414 codec_cfg->cid = cid; in unicast_client_ep_set_codec_cfg()
1415 codec_cfg->vid = vid; in unicast_client_ep_set_codec_cfg()
1417 codec_cfg->data_len = len; in unicast_client_ep_set_codec_cfg()
1418 memcpy(codec_cfg->data, data, len); in unicast_client_ep_set_codec_cfg()
1430 return -EINVAL; in unicast_client_set_codec_cap()
1439 codec_cap->id = id; in unicast_client_set_codec_cap()
1440 codec_cap->cid = cid; in unicast_client_set_codec_cap()
1441 codec_cap->vid = vid; in unicast_client_set_codec_cap()
1444 if (data_len > sizeof(codec_cap->data)) { in unicast_client_set_codec_cap()
1445 return -ENOMEM; in unicast_client_set_codec_cap()
1450 /* If codec is LC3, then it shall be LTV encoded - We verify this before storing the in unicast_client_set_codec_cap()
1451 * data For any non-LC3 codecs, we cannot verify anything in unicast_client_set_codec_cap()
1459 return -EINVAL; in unicast_client_set_codec_cap()
1462 memcpy(codec_cap->data, data, data_len); in unicast_client_set_codec_cap()
1463 codec_cap->data_len = data_len; in unicast_client_set_codec_cap()
1467 if (meta_len > sizeof(codec_cap->meta)) { in unicast_client_set_codec_cap()
1468 return -ENOMEM; in unicast_client_set_codec_cap()
1478 return -EINVAL; in unicast_client_set_codec_cap()
1481 memcpy(codec_cap->meta, meta, meta_len); in unicast_client_set_codec_cap()
1482 codec_cap->meta_len = meta_len; in unicast_client_set_codec_cap()
1492 return -EINVAL; in unicast_client_ep_set_metadata()
1498 codec_cfg = &ep->codec_cfg; in unicast_client_ep_set_metadata()
1501 if (len > sizeof(codec_cfg->meta)) { in unicast_client_ep_set_metadata()
1504 return -ENOMEM; in unicast_client_ep_set_metadata()
1508 codec_cfg->meta_len = len; in unicast_client_ep_set_metadata()
1509 (void)memcpy(codec_cfg->meta, data, len); in unicast_client_ep_set_metadata()
1525 params->value_handle = BAP_HANDLE_UNUSED; in unicast_client_cp_notify()
1538 if (rsp->num_ase == BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE) { in unicast_client_cp_notify()
1542 rsp->num_ase = 1U; in unicast_client_cp_notify()
1545 for (uint8_t i = 0U; i < rsp->num_ase; i++) { in unicast_client_cp_notify()
1558 "reason %s (0x%02x)", bt_ascs_op_str(rsp->op), rsp->op, in unicast_client_cp_notify()
1559 ase_rsp->id, bt_ascs_rsp_str(ase_rsp->code), in unicast_client_cp_notify()
1560 ase_rsp->code, bt_ascs_reason_str(ase_rsp->reason), in unicast_client_cp_notify()
1561 ase_rsp->reason); in unicast_client_cp_notify()
1563 stream = audio_stream_by_ep_id(conn, ase_rsp->id); in unicast_client_cp_notify()
1565 LOG_DBG("Could not find stream by id %u", ase_rsp->id); in unicast_client_cp_notify()
1567 client_ep = CONTAINER_OF(stream->ep, struct bt_bap_unicast_client_ep, ep); in unicast_client_cp_notify()
1568 client_ep->cp_ntf_pending = false; in unicast_client_cp_notify()
1571 switch (rsp->op) { in unicast_client_cp_notify()
1573 unicast_client_notify_ep_config(stream, ase_rsp->code, ase_rsp->reason); in unicast_client_cp_notify()
1576 unicast_client_notify_ep_qos(stream, ase_rsp->code, ase_rsp->reason); in unicast_client_cp_notify()
1579 unicast_client_notify_ep_enable(stream, ase_rsp->code, ase_rsp->reason); in unicast_client_cp_notify()
1582 unicast_client_notify_ep_start(stream, ase_rsp->code, ase_rsp->reason); in unicast_client_cp_notify()
1585 unicast_client_notify_ep_disable(stream, ase_rsp->code, ase_rsp->reason); in unicast_client_cp_notify()
1588 unicast_client_notify_ep_stop(stream, ase_rsp->code, ase_rsp->reason); in unicast_client_cp_notify()
1591 unicast_client_notify_ep_metadata(stream, ase_rsp->code, ase_rsp->reason); in unicast_client_cp_notify()
1594 /* client_ep->release_requested is set to false if handled by the in unicast_client_cp_notify()
1597 if (client_ep != NULL && client_ep->release_requested) { in unicast_client_cp_notify()
1599 if (ase_rsp->code != BT_BAP_ASCS_RSP_CODE_SUCCESS) { in unicast_client_cp_notify()
1600 client_ep->cp_ntf_pending = false; in unicast_client_cp_notify()
1601 client_ep->release_requested = false; in unicast_client_cp_notify()
1604 unicast_client_notify_ep_released(stream, ase_rsp->code, in unicast_client_cp_notify()
1605 ase_rsp->reason); in unicast_client_cp_notify()
1620 uint16_t handle = read->single.handle; in unicast_client_ase_ntf_read_func()
1637 buf = &client->net_buf; in unicast_client_ase_ntf_read_func()
1642 length + client->net_buf.len); in unicast_client_ase_ntf_read_func()
1644 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in unicast_client_ase_ntf_read_func()
1657 if (buf->len < sizeof(struct bt_ascs_ase_status)) { in unicast_client_ase_ntf_read_func()
1658 LOG_DBG("Read response too small (%u)", buf->len); in unicast_client_ase_ntf_read_func()
1660 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in unicast_client_ase_ntf_read_func()
1670 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in unicast_client_ase_ntf_read_func()
1672 ep = unicast_client_ep_get(conn, client->dir, handle); in unicast_client_ase_ntf_read_func()
1674 LOG_DBG("Unknown %s ep for handle 0x%04X", bt_audio_dir_str(client->dir), handle); in unicast_client_ase_ntf_read_func()
1677 if (ep->reason == BT_HCI_ERR_SUCCESS) { in unicast_client_ase_ntf_read_func()
1678 ep->reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN; in unicast_client_ase_ntf_read_func()
1690 struct bt_conn *conn = client_ep->ep.stream->conn; in long_ase_read()
1692 struct net_buf_simple *long_read_buf = &client->net_buf; in long_ase_read()
1695 LOG_DBG("conn %p ep %p 0x%04X", conn, &client_ep->ep, client_ep->handle); in long_ase_read()
1697 if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) { in long_ase_read()
1711 err = k_work_reschedule(&client_ep->ase_read_work, in long_ase_read()
1720 client->read_params.func = unicast_client_ase_ntf_read_func; in long_ase_read()
1721 client->read_params.handle_count = 1U; in long_ase_read()
1722 client->read_params.single.handle = client_ep->handle; in long_ase_read()
1723 client->read_params.single.offset = long_read_buf->len; in long_ase_read()
1725 err = bt_gatt_read(conn, &client->read_params); in long_ase_read()
1728 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in long_ase_read()
1738 LOG_DBG("ep %p 0x%04X", &client_ep->ep, client_ep->handle); in delayed_ase_read_handler()
1755 ep = &client_ep->ep; in unicast_client_ep_notify()
1760 (void)k_work_cancel_delayable(&client_ep->ase_read_work); in unicast_client_ep_notify()
1764 params->value_handle = BAP_HANDLE_UNUSED; in unicast_client_ep_notify()
1768 max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size; in unicast_client_ep_notify()
1773 if (!atomic_test_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) { in unicast_client_ep_notify()
1774 struct net_buf_simple *long_read_buf = &client->net_buf; in unicast_client_ep_notify()
1793 if (ep->reason == BT_HCI_ERR_SUCCESS) { in unicast_client_ep_notify()
1794 ep->reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN; in unicast_client_ep_notify()
1809 LOG_DBG("ep %p handle 0x%02x", ep, client_ep->handle); in unicast_client_ep_subscribe()
1811 if (client_ep->subscribe.value_handle) { in unicast_client_ep_subscribe()
1815 client_ep->subscribe.value_handle = client_ep->handle; in unicast_client_ep_subscribe()
1816 client_ep->subscribe.ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE; in unicast_client_ep_subscribe()
1817 client_ep->subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_ep_subscribe()
1818 client_ep->subscribe.disc_params = &client_ep->discover; in unicast_client_ep_subscribe()
1819 client_ep->subscribe.notify = unicast_client_ep_notify; in unicast_client_ep_subscribe()
1820 client_ep->subscribe.value = BT_GATT_CCC_NOTIFY; in unicast_client_ep_subscribe()
1821 atomic_set_bit(client_ep->subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE); in unicast_client_ep_subscribe()
1823 err = bt_gatt_subscribe(conn, &client_ep->subscribe); in unicast_client_ep_subscribe()
1824 if (err != 0 && err != -EALREADY) { in unicast_client_ep_subscribe()
1847 for (size_t i = 0U; i < ARRAY_SIZE(client->snks); i++) { in unicast_client_ep_set_cp()
1848 struct bt_bap_unicast_client_ep *client_ep = &client->snks[i]; in unicast_client_ep_set_cp()
1850 if (client_ep->handle) { in unicast_client_ep_set_cp()
1851 client_ep->cp_handle = handle; in unicast_client_ep_set_cp()
1857 for (size_t i = 0U; i < ARRAY_SIZE(client->srcs); i++) { in unicast_client_ep_set_cp()
1858 struct bt_bap_unicast_client_ep *client_ep = &client->srcs[i]; in unicast_client_ep_set_cp()
1860 if (client_ep->handle) { in unicast_client_ep_set_cp()
1861 client_ep->cp_handle = handle; in unicast_client_ep_set_cp()
1866 if (!client->cp_subscribe.value_handle) { in unicast_client_ep_set_cp()
1869 client->cp_subscribe.value_handle = handle; in unicast_client_ep_set_cp()
1870 client->cp_subscribe.ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE; in unicast_client_ep_set_cp()
1871 client->cp_subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_ep_set_cp()
1872 client->cp_subscribe.disc_params = &client->disc_params; in unicast_client_ep_set_cp()
1873 client->cp_subscribe.notify = unicast_client_cp_notify; in unicast_client_ep_set_cp()
1874 client->cp_subscribe.value = BT_GATT_CCC_NOTIFY; in unicast_client_ep_set_cp()
1875 client->cp_subscribe.subscribe = unicast_client_cp_sub_cb; in unicast_client_ep_set_cp()
1876 atomic_set_bit(client->cp_subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE); in unicast_client_ep_set_cp()
1878 err = bt_gatt_subscribe(conn, &client->cp_subscribe); in unicast_client_ep_set_cp()
1879 if (err != 0 && err != -EALREADY) { in unicast_client_ep_set_cp()
1896 if (atomic_test_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) { in bt_bap_unicast_client_ep_create_pdu()
1900 hdr = net_buf_simple_add(&client->net_buf, sizeof(*hdr)); in bt_bap_unicast_client_ep_create_pdu()
1901 hdr->op = op; in bt_bap_unicast_client_ep_create_pdu()
1903 return &client->net_buf; in bt_bap_unicast_client_ep_create_pdu()
1914 return -EINVAL; in unicast_client_ep_config()
1917 switch (ep->status.state) { in unicast_client_ep_config()
1926 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_config()
1927 return -EINVAL; in unicast_client_ep_config()
1930 LOG_DBG("id 0x%02x dir %s codec 0x%02x", ep->status.id, bt_audio_dir_str(ep->dir), in unicast_client_ep_config()
1931 codec_cfg->id); in unicast_client_ep_config()
1934 req->ase = ep->status.id; in unicast_client_ep_config()
1935 req->latency = 0x02; /* TODO: Select target latency based on additional input? */ in unicast_client_ep_config()
1936 req->phy = 0x02; /* TODO: Select target PHY based on additional input? */ in unicast_client_ep_config()
1937 req->codec.id = codec_cfg->id; in unicast_client_ep_config()
1938 req->codec.cid = codec_cfg->cid; in unicast_client_ep_config()
1939 req->codec.vid = codec_cfg->vid; in unicast_client_ep_config()
1941 req->cc_len = codec_cfg->data_len; in unicast_client_ep_config()
1942 net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len); in unicast_client_ep_config()
1956 return -EINVAL; in bt_bap_unicast_client_ep_qos()
1959 switch (ep->status.state) { in bt_bap_unicast_client_ep_qos()
1966 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in bt_bap_unicast_client_ep_qos()
1967 return -EINVAL; in bt_bap_unicast_client_ep_qos()
1970 conn_iso = &ep->iso->chan.iso->iso; in bt_bap_unicast_client_ep_qos()
1974 ep->status.id, conn_iso->cig_id, conn_iso->cis_id, qos->interval, qos->framing, in bt_bap_unicast_client_ep_qos()
1975 qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd); in bt_bap_unicast_client_ep_qos()
1978 req->ase = ep->status.id; in bt_bap_unicast_client_ep_qos()
1980 req->cig = conn_iso->cig_id; in bt_bap_unicast_client_ep_qos()
1981 req->cis = conn_iso->cis_id; in bt_bap_unicast_client_ep_qos()
1982 sys_put_le24(qos->interval, req->interval); in bt_bap_unicast_client_ep_qos()
1983 req->framing = qos->framing; in bt_bap_unicast_client_ep_qos()
1984 req->phy = qos->phy; in bt_bap_unicast_client_ep_qos()
1985 req->sdu = qos->sdu; in bt_bap_unicast_client_ep_qos()
1986 req->rtn = qos->rtn; in bt_bap_unicast_client_ep_qos()
1987 req->latency = sys_cpu_to_le16(qos->latency); in bt_bap_unicast_client_ep_qos()
1988 sys_put_le24(qos->pd, req->pd); in bt_bap_unicast_client_ep_qos()
2001 return -EINVAL; in unicast_client_ep_enable()
2004 if (ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) { in unicast_client_ep_enable()
2005 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_enable()
2006 return -EINVAL; in unicast_client_ep_enable()
2009 LOG_DBG("id 0x%02x", ep->status.id); in unicast_client_ep_enable()
2012 req->ase = ep->status.id; in unicast_client_ep_enable()
2014 req->len = meta_len; in unicast_client_ep_enable()
2028 return -EINVAL; in unicast_client_ep_metadata()
2031 switch (ep->status.state) { in unicast_client_ep_metadata()
2038 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_metadata()
2039 return -EINVAL; in unicast_client_ep_metadata()
2042 LOG_DBG("id 0x%02x", ep->status.id); in unicast_client_ep_metadata()
2045 req->ase = ep->status.id; in unicast_client_ep_metadata()
2047 req->len = meta_len; in unicast_client_ep_metadata()
2058 return -EINVAL; in unicast_client_ep_start()
2061 if (ep->status.state != BT_BAP_EP_STATE_ENABLING && in unicast_client_ep_start()
2062 ep->status.state != BT_BAP_EP_STATE_DISABLING) { in unicast_client_ep_start()
2063 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_start()
2064 return -EINVAL; in unicast_client_ep_start()
2067 LOG_DBG("id 0x%02x", ep->status.id); in unicast_client_ep_start()
2069 net_buf_simple_add_u8(buf, ep->status.id); in unicast_client_ep_start()
2079 return -EINVAL; in unicast_client_ep_disable()
2082 switch (ep->status.state) { in unicast_client_ep_disable()
2089 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_disable()
2090 return -EINVAL; in unicast_client_ep_disable()
2093 LOG_DBG("id 0x%02x", ep->status.id); in unicast_client_ep_disable()
2095 net_buf_simple_add_u8(buf, ep->status.id); in unicast_client_ep_disable()
2105 return -EINVAL; in unicast_client_ep_stop()
2109 if (ep->status.state != BT_BAP_EP_STATE_DISABLING) { in unicast_client_ep_stop()
2110 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_stop()
2111 return -EINVAL; in unicast_client_ep_stop()
2114 LOG_DBG("id 0x%02x", ep->status.id); in unicast_client_ep_stop()
2116 net_buf_simple_add_u8(buf, ep->status.id); in unicast_client_ep_stop()
2126 return -EINVAL; in unicast_client_ep_release()
2129 switch (ep->status.state) { in unicast_client_ep_release()
2142 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state)); in unicast_client_ep_release()
2143 return -EINVAL; in unicast_client_ep_release()
2146 LOG_DBG("id 0x%02x", ep->status.id); in unicast_client_ep_release()
2148 net_buf_simple_add_u8(buf, ep->status.id); in unicast_client_ep_release()
2161 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in gatt_write_cb()
2170 const uint16_t max_write_size = bt_gatt_get_mtu(conn) - att_write_header_size; in bt_bap_unicast_client_ep_send()
2176 LOG_DBG("conn %p ep %p buf %p len %u", conn, ep, buf, buf->len); in bt_bap_unicast_client_ep_send()
2178 if (buf->len > max_write_size) { in bt_bap_unicast_client_ep_send()
2179 if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) { in bt_bap_unicast_client_ep_send()
2181 return -EBUSY; in bt_bap_unicast_client_ep_send()
2184 client->write_params.func = gatt_write_cb; in bt_bap_unicast_client_ep_send()
2185 client->write_params.handle = client_ep->cp_handle; in bt_bap_unicast_client_ep_send()
2186 client->write_params.offset = 0U; in bt_bap_unicast_client_ep_send()
2187 client->write_params.data = buf->data; in bt_bap_unicast_client_ep_send()
2188 client->write_params.length = buf->len; in bt_bap_unicast_client_ep_send()
2190 client->write_params.chan_opt = BT_ATT_CHAN_OPT_NONE; in bt_bap_unicast_client_ep_send()
2193 err = bt_gatt_write(conn, &client->write_params); in bt_bap_unicast_client_ep_send()
2196 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in bt_bap_unicast_client_ep_send()
2199 err = bt_gatt_write_without_response(conn, client_ep->cp_handle, buf->data, in bt_bap_unicast_client_ep_send()
2200 buf->len, false); in bt_bap_unicast_client_ep_send()
2210 client_ep->cp_ntf_pending = true; in bt_bap_unicast_client_ep_send()
2222 ep->reason = reason; in unicast_client_reset()
2227 if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) { in unicast_client_reset()
2232 (void)k_work_cancel_delayable(&client_ep->ase_read_work); in unicast_client_reset()
2235 client_ep->cp_handle = BAP_HANDLE_UNUSED; in unicast_client_reset()
2236 client_ep->handle = BAP_HANDLE_UNUSED; in unicast_client_reset()
2237 (void)memset(&client_ep->discover, 0, sizeof(client_ep->discover)); in unicast_client_reset()
2238 client_ep->release_requested = false; in unicast_client_reset()
2239 client_ep->cp_ntf_pending = false; in unicast_client_reset()
2269 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in unicast_client_ep_reset()
2270 client->dir = 0U; in unicast_client_ep_reset()
2277 cig_param->framing = group->cig_param.framing; in bt_bap_qos_cfg_to_cig_param()
2278 cig_param->c_to_p_interval = group->cig_param.c_to_p_interval; in bt_bap_qos_cfg_to_cig_param()
2279 cig_param->p_to_c_interval = group->cig_param.p_to_c_interval; in bt_bap_qos_cfg_to_cig_param()
2280 cig_param->c_to_p_latency = group->cig_param.c_to_p_latency; in bt_bap_qos_cfg_to_cig_param()
2281 cig_param->p_to_c_latency = group->cig_param.p_to_c_latency; in bt_bap_qos_cfg_to_cig_param()
2282 cig_param->packing = group->cig_param.packing; in bt_bap_qos_cfg_to_cig_param()
2283 cig_param->sca = BT_GAP_SCA_UNKNOWN; in bt_bap_qos_cfg_to_cig_param()
2286 cig_param->c_to_p_ft = group->cig_param.c_to_p_ft; in bt_bap_qos_cfg_to_cig_param()
2287 cig_param->p_to_c_ft = group->cig_param.p_to_c_ft; in bt_bap_qos_cfg_to_cig_param()
2288 cig_param->iso_interval = group->cig_param.iso_interval; in bt_bap_qos_cfg_to_cig_param()
2297 if (cig_param->c_to_p_interval == 0U) { in bt_bap_qos_cfg_to_cig_param()
2298 cig_param->c_to_p_interval = cig_param->p_to_c_interval; in bt_bap_qos_cfg_to_cig_param()
2299 } else if (cig_param->p_to_c_interval == 0U) { in bt_bap_qos_cfg_to_cig_param()
2300 cig_param->p_to_c_interval = cig_param->c_to_p_interval; in bt_bap_qos_cfg_to_cig_param()
2303 if (cig_param->c_to_p_latency == 0U) { in bt_bap_qos_cfg_to_cig_param()
2304 cig_param->c_to_p_latency = cig_param->p_to_c_latency; in bt_bap_qos_cfg_to_cig_param()
2305 } else if (cig_param->p_to_c_latency == 0U) { in bt_bap_qos_cfg_to_cig_param()
2306 cig_param->p_to_c_latency = cig_param->c_to_p_latency; in bt_bap_qos_cfg_to_cig_param()
2314 for (size_t i = 0U; i < ARRAY_SIZE(unicast_group->cis); i++) { in unicast_group_get_cis_count()
2315 if (unicast_group->cis[i] == NULL) { in unicast_group_get_cis_count()
2334 param.cis_channels = group->cis; in bt_audio_cig_create()
2337 err = bt_iso_cig_create(&param, &group->cig); in bt_audio_cig_create()
2355 for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) { in bt_audio_cig_reconfigure()
2356 if (group->cis[i] == NULL) { in bt_audio_cig_reconfigure()
2365 param.cis_channels = group->cis; in bt_audio_cig_reconfigure()
2368 err = bt_iso_cig_reconfigure(group->cig, &param); in bt_audio_cig_reconfigure()
2382 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) { in audio_stream_qos_cleanup()
2383 if (stream->conn != conn) { in audio_stream_qos_cleanup()
2388 if (stream->ep == NULL) { in audio_stream_qos_cleanup()
2393 bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep); in audio_stream_qos_cleanup()
2401 return bt_iso_cig_terminate(group->cig); in unicast_client_cig_terminate()
2411 /* Append iso channel to the group->cis array */ in unicast_group_add_iso()
2412 for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) { in unicast_group_add_iso()
2414 if (group->cis[i] == &iso->chan) { in unicast_group_add_iso()
2418 if (chan_slot == NULL && group->cis[i] == NULL) { in unicast_group_add_iso()
2419 chan_slot = &group->cis[i]; in unicast_group_add_iso()
2424 return -ENOMEM; in unicast_group_add_iso()
2427 *chan_slot = &iso->chan; in unicast_group_add_iso()
2439 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) { in unicast_group_del_iso()
2440 if (stream->ep->iso == iso) { in unicast_group_del_iso()
2446 for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) { in unicast_group_del_iso()
2447 if (group->cis[i] == &iso->chan) { in unicast_group_del_iso()
2448 group->cis[i] = NULL; in unicast_group_del_iso()
2456 enum bt_audio_dir dir) in unicast_client_qos_cfg_to_iso_qos() argument
2461 if (dir == BT_AUDIO_DIR_SINK) { in unicast_client_qos_cfg_to_iso_qos()
2465 io_qos = iso->chan.qos->tx; in unicast_client_qos_cfg_to_iso_qos()
2467 other_io_qos = iso->chan.qos->rx; in unicast_client_qos_cfg_to_iso_qos()
2472 /* If the endpoint is a source, then we need to in unicast_client_qos_cfg_to_iso_qos()
2475 io_qos = iso->chan.qos->rx; in unicast_client_qos_cfg_to_iso_qos()
2477 other_io_qos = iso->chan.qos->tx; in unicast_client_qos_cfg_to_iso_qos()
2485 iso->chan.qos->num_subevents = qos->num_subevents; in unicast_client_qos_cfg_to_iso_qos()
2492 other_io_qos->phy = io_qos->phy; in unicast_client_qos_cfg_to_iso_qos()
2499 enum bt_audio_dir dir) in unicast_group_set_iso_stream_param() argument
2502 unicast_client_qos_cfg_to_iso_qos(iso, qos, dir); in unicast_group_set_iso_stream_param()
2504 /* Store the group Codec QoS in the group - This assume thats the parameters have been in unicast_group_set_iso_stream_param()
2507 group->cig_param.framing = qos->framing; in unicast_group_set_iso_stream_param()
2508 if (dir == BT_AUDIO_DIR_SOURCE) { in unicast_group_set_iso_stream_param()
2509 group->cig_param.p_to_c_interval = qos->interval; in unicast_group_set_iso_stream_param()
2510 group->cig_param.p_to_c_latency = qos->latency; in unicast_group_set_iso_stream_param()
2512 group->cig_param.c_to_p_interval = qos->interval; in unicast_group_set_iso_stream_param()
2513 group->cig_param.c_to_p_latency = qos->latency; in unicast_group_set_iso_stream_param()
2519 struct bt_bap_iso *iso, enum bt_audio_dir dir) in unicast_group_add_stream() argument
2521 struct bt_bap_stream *stream = param->stream; in unicast_group_add_stream()
2522 struct bt_bap_qos_cfg *qos = param->qos; in unicast_group_add_stream()
2524 LOG_DBG("group %p stream %p qos %p iso %p dir %u", group, stream, qos, iso, dir); in unicast_group_add_stream()
2526 __ASSERT_NO_MSG(stream->ep == NULL || (stream->ep != NULL && stream->ep->iso == NULL)); in unicast_group_add_stream()
2528 stream->qos = qos; in unicast_group_add_stream()
2529 stream->group = group; in unicast_group_add_stream()
2532 bt_bap_iso_bind_stream(iso, stream, dir); in unicast_group_add_stream()
2533 if (stream->ep != NULL) { in unicast_group_add_stream()
2534 bt_bap_iso_bind_ep(iso, stream->ep); in unicast_group_add_stream()
2537 unicast_group_set_iso_stream_param(group, iso, qos, dir); in unicast_group_add_stream()
2539 sys_slist_append(&group->streams, &stream->_node); in unicast_group_add_stream()
2550 __ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL); in unicast_group_add_stream_pair()
2554 return -ENOMEM; in unicast_group_add_stream_pair()
2563 if (param->rx_param != NULL) { in unicast_group_add_stream_pair()
2564 unicast_group_add_stream(group, param->rx_param, iso, BT_AUDIO_DIR_SOURCE); in unicast_group_add_stream_pair()
2567 if (param->tx_param != NULL) { in unicast_group_add_stream_pair()
2568 unicast_group_add_stream(group, param->tx_param, iso, BT_AUDIO_DIR_SINK); in unicast_group_add_stream_pair()
2577 struct bt_bap_stream *stream, enum bt_audio_dir dir) in unicast_group_del_stream() argument
2582 if (sys_slist_find_and_remove(&group->streams, &stream->_node)) { in unicast_group_del_stream()
2583 struct bt_bap_ep *ep = stream->ep; in unicast_group_del_stream()
2585 if (stream->bap_iso != NULL) { in unicast_group_del_stream()
2586 bt_bap_iso_unbind_stream(stream->bap_iso, stream, dir); in unicast_group_del_stream()
2589 if (ep != NULL && ep->iso != NULL) { in unicast_group_del_stream()
2590 unicast_group_del_iso(group, ep->iso); in unicast_group_del_stream()
2592 bt_bap_iso_unbind_ep(ep->iso, ep); in unicast_group_del_stream()
2595 stream->group = NULL; in unicast_group_del_stream()
2604 __ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL); in unicast_group_del_stream_pair()
2606 if (param->rx_param != NULL) { in unicast_group_del_stream_pair()
2607 __ASSERT_NO_MSG(param->rx_param->stream); in unicast_group_del_stream_pair()
2608 unicast_group_del_stream(group, param->rx_param->stream, BT_AUDIO_DIR_SOURCE); in unicast_group_del_stream_pair()
2611 if (param->tx_param != NULL) { in unicast_group_del_stream_pair()
2612 __ASSERT_NO_MSG(param->tx_param->stream); in unicast_group_del_stream_pair()
2613 unicast_group_del_stream(group, param->tx_param->stream, BT_AUDIO_DIR_SINK); in unicast_group_del_stream_pair()
2627 group->allocated = true; in unicast_group_alloc()
2628 group->index = i; in unicast_group_alloc()
2643 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&group->streams, stream, next, _node) { in unicast_group_free()
2644 struct bt_bap_iso *bap_iso = stream->bap_iso; in unicast_group_free()
2645 struct bt_bap_ep *ep = stream->ep; in unicast_group_free()
2647 stream->group = NULL; in unicast_group_free()
2649 if (bap_iso->rx.stream == stream) { in unicast_group_free()
2650 bt_bap_iso_unbind_stream(stream->bap_iso, stream, in unicast_group_free()
2652 } else if (bap_iso->tx.stream == stream) { in unicast_group_free()
2653 bt_bap_iso_unbind_stream(stream->bap_iso, stream, in unicast_group_free()
2660 if (ep != NULL && ep->iso != NULL) { in unicast_group_free()
2661 bt_bap_iso_unbind_ep(ep->iso, ep); in unicast_group_free()
2664 sys_slist_remove(&group->streams, NULL, &stream->_node); in unicast_group_free()
2667 group->allocated = false; in unicast_group_free()
2672 CHECKIF(param->stream == NULL) in stream_param_check()
2674 LOG_DBG("param->stream is NULL"); in stream_param_check()
2675 return -EINVAL; in stream_param_check()
2678 CHECKIF(param->qos == NULL) in stream_param_check()
2680 LOG_DBG("param->qos is NULL"); in stream_param_check()
2681 return -EINVAL; in stream_param_check()
2684 if (param->stream != NULL && param->stream->group != NULL) { in stream_param_check()
2685 LOG_DBG("stream %p already part of group %p", param->stream, param->stream->group); in stream_param_check()
2686 return -EALREADY; in stream_param_check()
2689 CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE) in stream_param_check()
2692 return -EINVAL; in stream_param_check()
2702 CHECKIF(param->rx_param == NULL && param->tx_param == NULL) in stream_pair_param_check()
2705 return -EINVAL; in stream_pair_param_check()
2708 if (param->rx_param != NULL) { in stream_pair_param_check()
2709 err = stream_param_check(param->rx_param); in stream_pair_param_check()
2715 if (param->tx_param != NULL) { in stream_pair_param_check()
2716 err = stream_param_check(param->tx_param); in stream_pair_param_check()
2729 enum bt_audio_dir dir) in valid_unicast_group_stream_param() argument
2733 CHECKIF(param->stream == NULL) { in valid_unicast_group_stream_param()
2734 LOG_DBG("param->stream is NULL"); in valid_unicast_group_stream_param()
2735 return -EINVAL; in valid_unicast_group_stream_param()
2738 CHECKIF(param->qos == NULL) { in valid_unicast_group_stream_param()
2739 LOG_DBG("param->qos is NULL"); in valid_unicast_group_stream_param()
2740 return -EINVAL; in valid_unicast_group_stream_param()
2743 if (param->stream != NULL && param->stream->group != NULL) { in valid_unicast_group_stream_param()
2744 if (unicast_group != NULL && param->stream->group != unicast_group) { in valid_unicast_group_stream_param()
2745 LOG_DBG("stream %p not part of group %p (%p)", param->stream, unicast_group, in valid_unicast_group_stream_param()
2746 param->stream->group); in valid_unicast_group_stream_param()
2748 LOG_DBG("stream %p already part of group %p", param->stream, in valid_unicast_group_stream_param()
2749 param->stream->group); in valid_unicast_group_stream_param()
2751 return -EALREADY; in valid_unicast_group_stream_param()
2754 CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE) { in valid_unicast_group_stream_param()
2756 return -EINVAL; in valid_unicast_group_stream_param()
2759 qos = param->qos; in valid_unicast_group_stream_param()
2764 if (dir == BT_AUDIO_DIR_SINK) { in valid_unicast_group_stream_param()
2765 if (cig_param->c_to_p_interval == 0) { in valid_unicast_group_stream_param()
2766 cig_param->c_to_p_interval = qos->interval; in valid_unicast_group_stream_param()
2767 } else if (cig_param->c_to_p_interval != qos->interval) { in valid_unicast_group_stream_param()
2771 if (cig_param->c_to_p_latency == 0) { in valid_unicast_group_stream_param()
2772 cig_param->c_to_p_latency = qos->latency; in valid_unicast_group_stream_param()
2773 } else if (cig_param->c_to_p_latency != qos->latency) { in valid_unicast_group_stream_param()
2777 if (cig_param->p_to_c_interval == 0) { in valid_unicast_group_stream_param()
2778 cig_param->p_to_c_interval = qos->interval; in valid_unicast_group_stream_param()
2779 } else if (cig_param->p_to_c_interval != qos->interval) { in valid_unicast_group_stream_param()
2783 if (cig_param->p_to_c_latency == 0) { in valid_unicast_group_stream_param()
2784 cig_param->p_to_c_latency = qos->latency; in valid_unicast_group_stream_param()
2785 } else if (cig_param->p_to_c_latency != qos->latency) { in valid_unicast_group_stream_param()
2790 if (cig_param->framing == 0) { in valid_unicast_group_stream_param()
2791 if (qos->framing == BT_BAP_QOS_CFG_FRAMING_UNFRAMED) { in valid_unicast_group_stream_param()
2792 cig_param->framing = BT_ISO_FRAMING_UNFRAMED; in valid_unicast_group_stream_param()
2793 } else if (qos->framing == BT_BAP_QOS_CFG_FRAMING_FRAMED) { in valid_unicast_group_stream_param()
2794 cig_param->framing = BT_ISO_FRAMING_FRAMED; in valid_unicast_group_stream_param()
2796 } else if ((qos->framing == BT_BAP_QOS_CFG_FRAMING_UNFRAMED && in valid_unicast_group_stream_param()
2797 cig_param->framing != BT_ISO_FRAMING_UNFRAMED) || in valid_unicast_group_stream_param()
2798 (qos->framing == BT_BAP_QOS_CFG_FRAMING_FRAMED && in valid_unicast_group_stream_param()
2799 cig_param->framing != BT_ISO_FRAMING_FRAMED)) { in valid_unicast_group_stream_param()
2817 if (pair_param->rx_param != NULL) { in valid_group_stream_pair_param()
2818 if (!valid_unicast_group_stream_param(unicast_group, pair_param->rx_param, in valid_group_stream_pair_param()
2824 if (pair_param->tx_param != NULL) { in valid_group_stream_pair_param()
2825 if (!valid_unicast_group_stream_param(unicast_group, pair_param->tx_param, in valid_group_stream_pair_param()
2842 CHECKIF(param->params_count > UNICAST_GROUP_STREAM_CNT) { in valid_unicast_group_param()
2843 LOG_DBG("Too many streams provided: %u/%u", param->params_count, in valid_unicast_group_param()
2851 if (param->params_count != group_cis_cnt) { in valid_unicast_group_param()
2853 group_cis_cnt, param->params_count); in valid_unicast_group_param()
2859 for (size_t i = 0U; i < param->params_count; i++) { in valid_unicast_group_param()
2860 if (!valid_group_stream_pair_param(unicast_group, &param->params[i])) { in valid_unicast_group_param()
2877 return -EINVAL; in bt_bap_unicast_group_create()
2879 /* Set out_unicast_group to NULL until the source has actually been created */ in bt_bap_unicast_group_create()
2885 return -ENOMEM; in bt_bap_unicast_group_create()
2891 return -EINVAL; in bt_bap_unicast_group_create()
2894 for (size_t i = 0U; i < param->params_count; i++) { in bt_bap_unicast_group_create()
2897 stream_param = &param->params[i]; in bt_bap_unicast_group_create()
2899 unicast_group->cig_param.packing = param->packing; in bt_bap_unicast_group_create()
2901 unicast_group->cig_param.c_to_p_ft = param->c_to_p_ft; in bt_bap_unicast_group_create()
2902 unicast_group->cig_param.p_to_c_ft = param->p_to_c_ft; in bt_bap_unicast_group_create()
2903 unicast_group->cig_param.iso_interval = param->iso_interval; in bt_bap_unicast_group_create()
2943 return -EINVAL; in bt_bap_unicast_group_reconfig()
2946 if (unicast_group->has_been_connected) { in bt_bap_unicast_group_reconfig()
2948 return -EINVAL; in bt_bap_unicast_group_reconfig()
2952 return -EINVAL; in bt_bap_unicast_group_reconfig()
2959 SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) { in bt_bap_unicast_group_reconfig()
2960 memcpy(&rx_io_qos_backup[idx], tmp_stream->bap_iso->chan.qos->rx, in bt_bap_unicast_group_reconfig()
2962 memcpy(&tx_io_qos_backup[idx], tmp_stream->bap_iso->chan.qos->tx, in bt_bap_unicast_group_reconfig()
2966 (num_subevents_backup[idx] = tmp_stream->bap_iso->chan.qos->num_subevents)); in bt_bap_unicast_group_reconfig()
2969 memcpy(&cig_param_backup, &unicast_group->cig_param, sizeof(cig_param_backup)); in bt_bap_unicast_group_reconfig()
2972 for (size_t i = 0U; i < param->params_count; i++) { in bt_bap_unicast_group_reconfig()
2973 struct bt_bap_unicast_group_stream_pair_param *stream_param = &param->params[i]; in bt_bap_unicast_group_reconfig()
2974 struct bt_bap_unicast_group_stream_param *rx_param = stream_param->rx_param; in bt_bap_unicast_group_reconfig()
2975 struct bt_bap_unicast_group_stream_param *tx_param = stream_param->tx_param; in bt_bap_unicast_group_reconfig()
2978 unicast_group_set_iso_stream_param(unicast_group, rx_param->stream->bap_iso, in bt_bap_unicast_group_reconfig()
2979 rx_param->qos, BT_AUDIO_DIR_SOURCE); in bt_bap_unicast_group_reconfig()
2983 unicast_group_set_iso_stream_param(unicast_group, tx_param->stream->bap_iso, in bt_bap_unicast_group_reconfig()
2984 tx_param->qos, BT_AUDIO_DIR_SOURCE); in bt_bap_unicast_group_reconfig()
2994 memcpy(&unicast_group->cig_param, &cig_param_backup, sizeof(cig_param_backup)); in bt_bap_unicast_group_reconfig()
2996 SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) { in bt_bap_unicast_group_reconfig()
2997 memcpy(tmp_stream->bap_iso->chan.qos->rx, &rx_io_qos_backup[idx], in bt_bap_unicast_group_reconfig()
2999 memcpy(tmp_stream->bap_iso->chan.qos->tx, &tx_io_qos_backup[idx], in bt_bap_unicast_group_reconfig()
3002 (tmp_stream->bap_iso->chan.qos->num_subevents = in bt_bap_unicast_group_reconfig()
3026 return -EINVAL; in bt_bap_unicast_group_add_streams()
3029 if (unicast_group->has_been_connected) { in bt_bap_unicast_group_add_streams()
3031 return -EINVAL; in bt_bap_unicast_group_add_streams()
3037 return -EINVAL; in bt_bap_unicast_group_add_streams()
3043 return -EINVAL; in bt_bap_unicast_group_add_streams()
3047 SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) { in bt_bap_unicast_group_add_streams()
3054 return -EINVAL; in bt_bap_unicast_group_add_streams()
3059 return -EINVAL; in bt_bap_unicast_group_add_streams()
3066 cig = unicast_group->cig; in bt_bap_unicast_group_add_streams()
3067 if (cig != NULL && cig->state != BT_ISO_CIG_STATE_CONFIGURED) { in bt_bap_unicast_group_add_streams()
3069 return -EBADMSG; in bt_bap_unicast_group_add_streams()
3099 while (num_added--) { in bt_bap_unicast_group_add_streams()
3113 return -EINVAL; in bt_bap_unicast_group_delete()
3116 SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, stream, _node) { in bt_bap_unicast_group_delete()
3120 if (stream->ep != NULL) { in bt_bap_unicast_group_delete()
3122 return -EINVAL; in bt_bap_unicast_group_delete()
3126 if (unicast_group->cig != NULL) { in bt_bap_unicast_group_delete()
3144 struct bt_bap_ep *ep = stream->ep; in bt_bap_unicast_client_config()
3151 if (stream->conn == NULL) { in bt_bap_unicast_client_config()
3154 return -ENOTCONN; in bt_bap_unicast_client_config()
3157 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_CONFIG_OP); in bt_bap_unicast_client_config()
3160 return -EBUSY; in bt_bap_unicast_client_config()
3164 op->num_ases = 0x01; in bt_bap_unicast_client_config()
3171 err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf); in bt_bap_unicast_client_config()
3191 return -ENOTCONN; in bt_bap_unicast_client_qos()
3200 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) { in bt_bap_unicast_client_qos()
3201 if (stream->conn != conn) { in bt_bap_unicast_client_qos()
3207 ep = stream->ep; in bt_bap_unicast_client_qos()
3209 LOG_DBG("stream->ep is NULL"); in bt_bap_unicast_client_qos()
3210 return -EINVAL; in bt_bap_unicast_client_qos()
3216 switch (ep->status.state) { in bt_bap_unicast_client_qos()
3221 LOG_DBG("Invalid state: %s", bt_bap_ep_state_str(stream->ep->status.state)); in bt_bap_unicast_client_qos()
3222 return -EINVAL; in bt_bap_unicast_client_qos()
3225 if (bt_bap_stream_verify_qos(stream, stream->qos) != BT_BAP_ASCS_REASON_NONE) { in bt_bap_unicast_client_qos()
3226 return -EINVAL; in bt_bap_unicast_client_qos()
3229 /* Verify ep->dir */ in bt_bap_unicast_client_qos()
3230 switch (ep->dir) { in bt_bap_unicast_client_qos()
3235 __ASSERT(false, "invalid endpoint dir: %u", ep->dir); in bt_bap_unicast_client_qos()
3236 return -EINVAL; in bt_bap_unicast_client_qos()
3239 if (stream->bap_iso == NULL) { in bt_bap_unicast_client_qos()
3244 return -EINVAL; in bt_bap_unicast_client_qos()
3250 return -EINVAL; in bt_bap_unicast_client_qos()
3257 return -EBUSY; in bt_bap_unicast_client_qos()
3264 SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) { in bt_bap_unicast_client_qos()
3265 if (stream->conn != conn) { in bt_bap_unicast_client_qos()
3270 op->num_ases++; in bt_bap_unicast_client_qos()
3272 if (stream->ep->iso == NULL) { in bt_bap_unicast_client_qos()
3274 bt_bap_iso_bind_ep(stream->bap_iso, stream->ep); in bt_bap_unicast_client_qos()
3277 err = bt_bap_unicast_client_ep_qos(stream->ep, buf, stream->qos); in bt_bap_unicast_client_qos()
3285 ep = stream->ep; in bt_bap_unicast_client_qos()
3303 struct bt_bap_ep *ep = stream->ep; in bt_bap_unicast_client_enable()
3310 if (stream->conn == NULL) { in bt_bap_unicast_client_enable()
3313 return -ENOTCONN; in bt_bap_unicast_client_enable()
3316 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_ENABLE_OP); in bt_bap_unicast_client_enable()
3319 return -EBUSY; in bt_bap_unicast_client_enable()
3323 req->num_ases = 0x01; in bt_bap_unicast_client_enable()
3330 return bt_bap_unicast_client_ep_send(stream->conn, ep, buf); in bt_bap_unicast_client_enable()
3336 struct bt_bap_ep *ep = stream->ep; in bt_bap_unicast_client_metadata()
3343 if (stream->conn == NULL) { in bt_bap_unicast_client_metadata()
3346 return -ENOTCONN; in bt_bap_unicast_client_metadata()
3349 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_METADATA_OP); in bt_bap_unicast_client_metadata()
3352 return -EBUSY; in bt_bap_unicast_client_metadata()
3356 req->num_ases = 0x01; in bt_bap_unicast_client_metadata()
3363 return bt_bap_unicast_client_ep_send(stream->conn, ep, buf); in bt_bap_unicast_client_metadata()
3377 return -EINVAL; in bt_bap_unicast_client_connect()
3384 return -EINVAL; in bt_bap_unicast_client_connect()
3389 param.acl = stream->conn; in bt_bap_unicast_client_connect()
3392 iso_state = iso_chan->state; in bt_bap_unicast_client_connect()
3396 if (err == 0 || err == -EBUSY) { /* Expected / known return values */ in bt_bap_unicast_client_connect()
3403 return -ENOEXEC; in bt_bap_unicast_client_connect()
3407 return -EALREADY; in bt_bap_unicast_client_connect()
3412 return -EBADMSG; in bt_bap_unicast_client_connect()
3417 struct bt_bap_ep *ep = stream->ep; in bt_bap_unicast_client_start()
3422 if (stream->conn == NULL) { in bt_bap_unicast_client_start()
3425 return -ENOTCONN; in bt_bap_unicast_client_start()
3428 /* As per the ASCS spec, only source streams can be started by the client */ in bt_bap_unicast_client_start()
3429 if (ep->dir == BT_AUDIO_DIR_SINK) { in bt_bap_unicast_client_start()
3430 LOG_DBG("Stream %p is not a source stream", stream); in bt_bap_unicast_client_start()
3432 return -EINVAL; in bt_bap_unicast_client_start()
3435 ep->receiver_ready = true; in bt_bap_unicast_client_start()
3442 ep->receiver_ready = false; in bt_bap_unicast_client_start()
3452 struct bt_bap_ep *ep = stream->ep; in bt_bap_unicast_client_disable()
3459 if (stream->conn == NULL) { in bt_bap_unicast_client_disable()
3462 return -ENOTCONN; in bt_bap_unicast_client_disable()
3465 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_DISABLE_OP); in bt_bap_unicast_client_disable()
3468 return -EBUSY; in bt_bap_unicast_client_disable()
3472 req->num_ases = 0x01; in bt_bap_unicast_client_disable()
3479 return bt_bap_unicast_client_ep_send(stream->conn, ep, buf); in bt_bap_unicast_client_disable()
3484 struct bt_bap_ep *ep = stream->ep; in bt_bap_unicast_client_stop()
3492 if (stream->conn == NULL) { in bt_bap_unicast_client_stop()
3495 return -ENOTCONN; in bt_bap_unicast_client_stop()
3508 if (ep->iso == NULL) { in bt_bap_unicast_client_stop()
3510 return -EALREADY; in bt_bap_unicast_client_stop()
3513 iso_state = ep->iso->chan.state; in bt_bap_unicast_client_stop()
3516 return -EALREADY; in bt_bap_unicast_client_stop()
3519 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_STOP_OP); in bt_bap_unicast_client_stop()
3522 return -EBUSY; in bt_bap_unicast_client_stop()
3526 req->num_ases = 0x00; in bt_bap_unicast_client_stop()
3529 * parameter value = 0x02 (Server is Audio Source) in bt_bap_unicast_client_stop()
3531 if (ep->dir == BT_AUDIO_DIR_SOURCE) { in bt_bap_unicast_client_stop()
3536 req->num_ases++; in bt_bap_unicast_client_stop()
3538 err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf); in bt_bap_unicast_client_stop()
3541 if (err == -ENOTCONN || err == -ENOMEM) { in bt_bap_unicast_client_stop()
3548 return -ENOEXEC; in bt_bap_unicast_client_stop()
3558 struct bt_bap_ep *ep = stream->ep; in bt_bap_unicast_client_release()
3565 if (stream->conn == NULL) { in bt_bap_unicast_client_release()
3568 return -ENOTCONN; in bt_bap_unicast_client_release()
3571 buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_RELEASE_OP); in bt_bap_unicast_client_release()
3574 return -EBUSY; in bt_bap_unicast_client_release()
3578 req->num_ases = 0x01; in bt_bap_unicast_client_release()
3579 len = buf->len; in bt_bap_unicast_client_release()
3582 if (stream->ep->status.state == BT_BAP_EP_STATE_IDLE) { in bt_bap_unicast_client_release()
3592 if (len == buf->len) { in bt_bap_unicast_client_release()
3596 err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf); in bt_bap_unicast_client_release()
3602 client_ep->release_requested = true; in bt_bap_unicast_client_release()
3621 chrc = attr->user_data; in unicast_client_cp_discover_func()
3622 value_handle = chrc->value_handle; in unicast_client_cp_discover_func()
3638 client->disc_params.uuid = cp_uuid; in unicast_client_ase_cp_discover()
3639 client->disc_params.func = unicast_client_cp_discover_func; in unicast_client_ase_cp_discover()
3640 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; in unicast_client_ase_cp_discover()
3641 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_ase_cp_discover()
3642 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; in unicast_client_ase_cp_discover()
3644 return bt_gatt_discover(conn, &client->disc_params); in unicast_client_ase_cp_discover()
3651 uint16_t handle = read->single.handle; in unicast_client_ase_read_func()
3667 buf = &client->net_buf; in unicast_client_ase_read_func()
3672 length + client->net_buf.len); in unicast_client_ase_read_func()
3687 if (buf->len < sizeof(struct bt_ascs_ase_status)) { in unicast_client_ase_read_func()
3688 LOG_DBG("Read response too small (%u)", buf->len); in unicast_client_ase_read_func()
3695 ep = unicast_client_ep_get(conn, client->dir, handle); in unicast_client_ase_read_func()
3702 cb_err = -ENOMEM; in unicast_client_ase_read_func()
3733 /* We always allocate ases from 0 to X, so to verify if any sink or source ASEs have been in any_ases_found()
3737 if (client->dir == BT_AUDIO_DIR_SINK && client->snks[0].handle == BAP_HANDLE_UNUSED) { in any_ases_found()
3743 if (client->dir == BT_AUDIO_DIR_SOURCE && client->srcs[0].handle == BAP_HANDLE_UNUSED) { in any_ases_found()
3744 LOG_DBG("No source ASEs found"); in any_ases_found()
3778 chrc = attr->user_data; in unicast_client_ase_discover_cb()
3779 value_handle = chrc->value_handle; in unicast_client_ase_discover_cb()
3782 LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle, in unicast_client_ase_discover_cb()
3783 bt_audio_dir_str(client->dir)); in unicast_client_ase_discover_cb()
3785 client->read_params.func = unicast_client_ase_read_func; in unicast_client_ase_discover_cb()
3786 client->read_params.handle_count = 1U; in unicast_client_ase_discover_cb()
3787 client->read_params.single.handle = value_handle; in unicast_client_ase_discover_cb()
3788 client->read_params.single.offset = 0U; in unicast_client_ase_discover_cb()
3790 err = bt_gatt_read(conn, &client->read_params); in unicast_client_ase_discover_cb()
3806 if (client->dir == BT_AUDIO_DIR_SINK) { in unicast_client_ase_discover()
3807 client->disc_params.uuid = ase_snk_uuid; in unicast_client_ase_discover()
3808 } else if (client->dir == BT_AUDIO_DIR_SOURCE) { in unicast_client_ase_discover()
3809 client->disc_params.uuid = ase_src_uuid; in unicast_client_ase_discover()
3811 return -EINVAL; in unicast_client_ase_discover()
3814 client->disc_params.func = unicast_client_ase_discover_cb; in unicast_client_ase_discover()
3815 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; in unicast_client_ase_discover()
3816 client->disc_params.start_handle = start_handle; in unicast_client_ase_discover()
3817 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_ase_discover()
3819 return bt_gatt_discover(conn, &client->disc_params); in unicast_client_ase_discover()
3850 LOG_DBG("sink context %u, source context %u", context.snk, context.src); in unicast_client_pacs_avail_ctx_read_func()
3876 params->value_handle = BAP_HANDLE_UNUSED; in unicast_client_pacs_avail_ctx_notify_cb()
3891 LOG_DBG("sink context %u, source context %u", context.snk, context.src); in unicast_client_pacs_avail_ctx_notify_cb()
3904 client->read_params.func = unicast_client_pacs_avail_ctx_read_func; in unicast_client_pacs_avail_ctx_read()
3905 client->read_params.handle_count = 1U; in unicast_client_pacs_avail_ctx_read()
3906 client->read_params.single.handle = handle; in unicast_client_pacs_avail_ctx_read()
3907 client->read_params.single.offset = 0U; in unicast_client_pacs_avail_ctx_read()
3909 return bt_gatt_read(conn, &client->read_params); in unicast_client_pacs_avail_ctx_read()
3932 chrc = attr->user_data; in unicast_client_pacs_avail_ctx_discover_cb()
3933 chrc_properties = chrc->properties; in unicast_client_pacs_avail_ctx_discover_cb()
3934 value_handle = chrc->value_handle; in unicast_client_pacs_avail_ctx_discover_cb()
3944 if (sub_params->value_handle == 0) { in unicast_client_pacs_avail_ctx_discover_cb()
3946 sub_params->value_handle = value_handle; in unicast_client_pacs_avail_ctx_discover_cb()
3947 sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE; in unicast_client_pacs_avail_ctx_discover_cb()
3948 sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_pacs_avail_ctx_discover_cb()
3949 sub_params->disc_params = &uni_cli_insts[index].avail_ctx_cc_disc; in unicast_client_pacs_avail_ctx_discover_cb()
3950 sub_params->notify = unicast_client_pacs_avail_ctx_notify_cb; in unicast_client_pacs_avail_ctx_discover_cb()
3951 sub_params->value = BT_GATT_CCC_NOTIFY; in unicast_client_pacs_avail_ctx_discover_cb()
3952 atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE); in unicast_client_pacs_avail_ctx_discover_cb()
3955 if (err != 0 && err != -EALREADY) { in unicast_client_pacs_avail_ctx_discover_cb()
3960 LOG_DBG("Invalid chrc->properties: %u", chrc_properties); in unicast_client_pacs_avail_ctx_discover_cb()
3985 client->disc_params.uuid = pacs_avail_ctx_uuid; in unicast_client_pacs_avail_ctx_discover()
3986 client->disc_params.func = unicast_client_pacs_avail_ctx_discover_cb; in unicast_client_pacs_avail_ctx_discover()
3987 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; in unicast_client_pacs_avail_ctx_discover()
3988 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_pacs_avail_ctx_discover()
3989 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; in unicast_client_pacs_avail_ctx_discover()
3991 return bt_gatt_discover(conn, &client->disc_params); in unicast_client_pacs_avail_ctx_discover()
4010 LOG_DBG("Unable to read PACS location for dir %s: %u, %p, %u", in unicast_client_pacs_location_read_func()
4011 bt_audio_dir_str(client->dir), err, data, length); in unicast_client_pacs_location_read_func()
4025 LOG_DBG("dir %s loc %X", bt_audio_dir_str(client->dir), location); in unicast_client_pacs_location_read_func()
4027 unicast_client_notify_location(conn, client->dir, (enum bt_audio_location)location); in unicast_client_pacs_location_read_func()
4045 enum bt_audio_dir dir; in unicast_client_pacs_location_notify_cb() local
4052 params->value_handle = BAP_HANDLE_UNUSED; in unicast_client_pacs_location_notify_cb()
4064 dir = BT_AUDIO_DIR_SINK; in unicast_client_pacs_location_notify_cb()
4066 dir = BT_AUDIO_DIR_SOURCE; in unicast_client_pacs_location_notify_cb()
4076 LOG_DBG("dir %s loc %X", bt_audio_dir_str(dir), location); in unicast_client_pacs_location_notify_cb()
4078 unicast_client_notify_location(conn, dir, (enum bt_audio_location)location); in unicast_client_pacs_location_notify_cb()
4089 client->read_params.func = unicast_client_pacs_location_read_func; in unicast_client_pacs_location_read()
4090 client->read_params.handle_count = 1U; in unicast_client_pacs_location_read()
4091 client->read_params.single.handle = handle; in unicast_client_pacs_location_read()
4092 client->read_params.single.offset = 0U; in unicast_client_pacs_location_read()
4094 return bt_gatt_read(conn, &client->read_params); in unicast_client_pacs_location_read()
4120 chrc = attr->user_data; in unicast_client_pacs_location_discover_cb()
4121 value_handle = chrc->value_handle; in unicast_client_pacs_location_discover_cb()
4126 if (chrc->properties & BT_GATT_CHRC_NOTIFY) { in unicast_client_pacs_location_discover_cb()
4130 if (client->dir == BT_AUDIO_DIR_SINK) { in unicast_client_pacs_location_discover_cb()
4136 sub_params->value_handle = value_handle; in unicast_client_pacs_location_discover_cb()
4137 sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE; in unicast_client_pacs_location_discover_cb()
4138 sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_pacs_location_discover_cb()
4139 sub_params->disc_params = &uni_cli_insts[index].loc_cc_disc; in unicast_client_pacs_location_discover_cb()
4140 sub_params->notify = unicast_client_pacs_location_notify_cb; in unicast_client_pacs_location_discover_cb()
4141 sub_params->value = BT_GATT_CCC_NOTIFY; in unicast_client_pacs_location_discover_cb()
4142 atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE); in unicast_client_pacs_location_discover_cb()
4145 if (err != 0 && err != -EALREADY) { in unicast_client_pacs_location_discover_cb()
4164 LOG_DBG("conn %p dir %s", conn, bt_audio_dir_str(client->dir)); in unicast_client_pacs_location_discover()
4166 if (client->dir == BT_AUDIO_DIR_SINK) { in unicast_client_pacs_location_discover()
4167 client->disc_params.uuid = pacs_snk_loc_uuid; in unicast_client_pacs_location_discover()
4168 } else if (client->dir == BT_AUDIO_DIR_SOURCE) { in unicast_client_pacs_location_discover()
4169 client->disc_params.uuid = pacs_src_loc_uuid; in unicast_client_pacs_location_discover()
4171 return -EINVAL; in unicast_client_pacs_location_discover()
4174 client->disc_params.func = unicast_client_pacs_location_discover_cb; in unicast_client_pacs_location_discover()
4175 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; in unicast_client_pacs_location_discover()
4176 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_pacs_location_discover()
4177 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; in unicast_client_pacs_location_discover()
4179 return bt_gatt_discover(conn, &client->disc_params); in unicast_client_pacs_location_discover()
4223 LOG_ERR("Unable to find %s PAC context", bt_audio_dir_str(client->dir)); in unicast_client_pacs_context_discover_cb()
4230 chrc = attr->user_data; in unicast_client_pacs_context_discover_cb()
4231 value_handle = chrc->value_handle; in unicast_client_pacs_context_discover_cb()
4234 LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle, in unicast_client_pacs_context_discover_cb()
4235 bt_audio_dir_str(client->dir)); in unicast_client_pacs_context_discover_cb()
4239 client->read_params.func = unicast_client_pacs_context_read_func; in unicast_client_pacs_context_discover_cb()
4240 client->read_params.handle_count = 1U; in unicast_client_pacs_context_discover_cb()
4241 client->read_params.single.handle = value_handle; in unicast_client_pacs_context_discover_cb()
4242 client->read_params.single.offset = 0U; in unicast_client_pacs_context_discover_cb()
4244 err = bt_gatt_read(conn, &client->read_params); in unicast_client_pacs_context_discover_cb()
4260 client->disc_params.uuid = pacs_context_uuid; in unicast_client_pacs_context_discover()
4261 client->disc_params.func = unicast_client_pacs_context_discover_cb; in unicast_client_pacs_context_discover()
4262 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; in unicast_client_pacs_context_discover()
4263 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; in unicast_client_pacs_context_discover()
4264 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in unicast_client_pacs_context_discover()
4266 return bt_gatt_discover(conn, &client->disc_params); in unicast_client_pacs_context_discover()
4273 uint16_t handle = read->single.handle; in unicast_client_read_func()
4289 buf = &client->net_buf; in unicast_client_read_func()
4294 length + client->net_buf.len); in unicast_client_read_func()
4309 if (buf->len < sizeof(*rsp)) { in unicast_client_read_func()
4310 LOG_DBG("Read response too small (%u)", buf->len); in unicast_client_read_func()
4320 if (!rsp->num_pac) { in unicast_client_read_func()
4324 for (i = 0U; i < rsp->num_pac; i++) { in unicast_client_read_func()
4330 LOG_DBG("pac #%u/%u", i + 1, rsp->num_pac); in unicast_client_read_func()
4332 if (buf->len < sizeof(*pac_codec)) { in unicast_client_read_func()
4334 buf->len, sizeof(*pac_codec)); in unicast_client_read_func()
4340 if (buf->len < sizeof(*cc)) { in unicast_client_read_func()
4342 buf->len, sizeof(*cc)); in unicast_client_read_func()
4347 if (buf->len < cc->len) { in unicast_client_read_func()
4349 buf->len, cc->len); in unicast_client_read_func()
4353 cc_ltv = net_buf_simple_pull_mem(buf, cc->len); in unicast_client_read_func()
4355 if (buf->len < sizeof(*meta)) { in unicast_client_read_func()
4357 buf->len, sizeof(*meta)); in unicast_client_read_func()
4362 if (buf->len < meta->len) { in unicast_client_read_func()
4364 buf->len, meta->len); in unicast_client_read_func()
4368 meta_ltv = net_buf_simple_pull_mem(buf, meta->len); in unicast_client_read_func()
4370 if (unicast_client_set_codec_cap(pac_codec->id, sys_le16_to_cpu(pac_codec->cid), in unicast_client_read_func()
4371 sys_le16_to_cpu(pac_codec->vid), cc_ltv, cc->len, in unicast_client_read_func()
4372 meta_ltv, meta->len, &codec_cap)) { in unicast_client_read_func()
4385 if (i != rsp->num_pac) { in unicast_client_read_func()
4386 LOG_DBG("Failed to process all PAC records (%u/%u)", i, rsp->num_pac); in unicast_client_read_func()
4415 LOG_DBG("Unable to find %s PAC", bt_audio_dir_str(client->dir)); in unicast_client_pac_discover_cb()
4422 chrc = attr->user_data; in unicast_client_pac_discover_cb()
4423 value_handle = chrc->value_handle; in unicast_client_pac_discover_cb()
4426 LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle, in unicast_client_pac_discover_cb()
4427 bt_audio_dir_str(client->dir)); in unicast_client_pac_discover_cb()
4434 client->read_params.func = unicast_client_read_func; in unicast_client_pac_discover_cb()
4435 client->read_params.handle_count = 1U; in unicast_client_pac_discover_cb()
4436 client->read_params.single.handle = value_handle; in unicast_client_pac_discover_cb()
4437 client->read_params.single.offset = 0U; in unicast_client_pac_discover_cb()
4439 err = bt_gatt_read(conn, &client->read_params); in unicast_client_pac_discover_cb()
4460 int bt_bap_unicast_client_discover(struct bt_conn *conn, enum bt_audio_dir dir) in bt_bap_unicast_client_discover() argument
4467 if (!conn || conn->state != BT_CONN_CONNECTED) { in bt_bap_unicast_client_discover()
4468 return -ENOTCONN; in bt_bap_unicast_client_discover()
4471 role = conn->role; in bt_bap_unicast_client_discover()
4474 return -EINVAL; in bt_bap_unicast_client_discover()
4478 if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) { in bt_bap_unicast_client_discover()
4480 return -EBUSY; in bt_bap_unicast_client_discover()
4483 if (dir == BT_AUDIO_DIR_SINK) { in bt_bap_unicast_client_discover()
4484 client->disc_params.uuid = snk_uuid; in bt_bap_unicast_client_discover()
4485 } else if (dir == BT_AUDIO_DIR_SOURCE) { in bt_bap_unicast_client_discover()
4486 client->disc_params.uuid = src_uuid; in bt_bap_unicast_client_discover()
4488 return -EINVAL; in bt_bap_unicast_client_discover()
4491 client->disc_params.func = unicast_client_pac_discover_cb; in bt_bap_unicast_client_discover()
4492 client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC; in bt_bap_unicast_client_discover()
4493 client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE; in bt_bap_unicast_client_discover()
4494 client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE; in bt_bap_unicast_client_discover()
4501 err = bt_gatt_discover(conn, &client->disc_params); in bt_bap_unicast_client_discover()
4503 atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY); in bt_bap_unicast_client_discover()
4507 client->dir = dir; in bt_bap_unicast_client_discover()
4516 return -EINVAL; in bt_bap_unicast_client_register_cb()
4519 if (sys_slist_find(&unicast_client_cbs, &cb->_node, NULL)) { in bt_bap_unicast_client_register_cb()
4520 return -EEXIST; in bt_bap_unicast_client_register_cb()
4523 sys_slist_append(&unicast_client_cbs, &cb->_node); in bt_bap_unicast_client_register_cb()