1 /*
2 * Copyright (c) 2025 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <errno.h>
7 #include <stdint.h>
8 #include <string.h>
9
10 #include <zephyr/autoconf.h>
11 #include <zephyr/bluetooth/audio/audio.h>
12 #include <zephyr/bluetooth/audio/bap.h>
13 #include <zephyr/bluetooth/hci_types.h>
14 #include <zephyr/bluetooth/iso.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/logging/log.h>
17 #include <zephyr/logging/log_core.h>
18 #include <zephyr/net_buf.h>
19 #include <zephyr/sys/util.h>
20 #include <zephyr/sys/util_macro.h>
21
22 #if defined(CONFIG_LIBLC3)
23 #include <lc3.h>
24 #endif /* defined(CONFIG_LIBLC3) */
25
26 #include "stream_rx.h"
27 #include "lc3.h"
28
29 struct stream_rx rx_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
30 uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */
31
32 LOG_MODULE_REGISTER(stream_rx, CONFIG_LOG_DEFAULT_LEVEL);
33
34 #if CONFIG_INFO_REPORTING_INTERVAL > 0
log_stream_rx(const struct stream_rx * stream,const struct bt_iso_recv_info * info,const struct net_buf * buf)35 static void log_stream_rx(const struct stream_rx *stream, const struct bt_iso_recv_info *info,
36 const struct net_buf *buf)
37 {
38 LOG_INF("[%zu]: Incoming audio on stream %p len %u, flags 0x%02X, seq_num %u and ts %u: "
39 "Valid %zu | Error %zu | Loss %zu | Dup TS %zu | Dup PSN %zu",
40 stream->reporting_info.recv_cnt, &stream->stream, buf->len, info->flags,
41 info->seq_num, info->ts, stream->reporting_info.valid_cnt,
42 stream->reporting_info.error_cnt, stream->reporting_info.loss_cnt,
43 stream->reporting_info.dup_ts_cnt, stream->reporting_info.dup_psn_cnt);
44 }
45 #endif /* CONFIG_INFO_REPORTING_INTERVAL > 0 */
46
stream_rx_recv(struct bt_bap_stream * bap_stream,const struct bt_iso_recv_info * info,struct net_buf * buf)47 void stream_rx_recv(struct bt_bap_stream *bap_stream, const struct bt_iso_recv_info *info,
48 struct net_buf *buf)
49 {
50 struct stream_rx *stream = CONTAINER_OF(bap_stream, struct stream_rx, stream);
51
52 #if CONFIG_INFO_REPORTING_INTERVAL > 0
53 if ((stream->reporting_info.recv_cnt % CONFIG_INFO_REPORTING_INTERVAL) == 0U) {
54 log_stream_rx(stream, info, buf);
55 }
56
57 if (stream->reporting_info.recv_cnt > 0U && info->ts == stream->reporting_info.last_ts) {
58 log_stream_rx(stream, info, buf);
59 LOG_WRN("Duplicated timestamp received: %u\n", stream->reporting_info.last_ts);
60 stream->reporting_info.dup_ts_cnt++;
61 }
62
63 if (stream->reporting_info.recv_cnt > 0U &&
64 info->seq_num == stream->reporting_info.last_seq_num) {
65 log_stream_rx(stream, info, buf);
66 LOG_WRN("Duplicated PSN received: %u\n", stream->reporting_info.last_seq_num);
67 stream->reporting_info.dup_psn_cnt++;
68 }
69
70 if (info->flags & BT_ISO_FLAGS_ERROR) {
71 log_stream_rx(stream, info, buf);
72 LOG_DBG("ISO receive error\n");
73 stream->reporting_info.error_cnt++;
74 }
75
76 if (info->flags & BT_ISO_FLAGS_LOST) {
77 log_stream_rx(stream, info, buf);
78 LOG_DBG("ISO receive lost\n");
79 stream->reporting_info.loss_cnt++;
80 }
81
82 if (info->flags & BT_ISO_FLAGS_VALID) {
83 if (buf->len == 0U) {
84 stream->reporting_info.empty_sdu_cnt++;
85 } else {
86 stream->reporting_info.valid_cnt++;
87 }
88 }
89
90 stream->reporting_info.last_seq_num = info->seq_num;
91 stream->reporting_info.last_ts = info->ts;
92 stream->reporting_info.recv_cnt++;
93 #endif /* CONFIG_INFO_REPORTING_INTERVAL > 0 */
94
95 total_rx_iso_packet_count++;
96
97 if (IS_ENABLED(CONFIG_LIBLC3)) {
98 /* Invalid SDUs will trigger PLC */
99 lc3_enqueue_for_decoding(stream, info, buf);
100 }
101 }
102
stream_rx_started(struct bt_bap_stream * bap_stream)103 int stream_rx_started(struct bt_bap_stream *bap_stream)
104 {
105 struct stream_rx *stream = CONTAINER_OF(bap_stream, struct stream_rx, stream);
106
107 if (stream == NULL) {
108 return -EINVAL;
109 }
110
111 #if CONFIG_INFO_REPORTING_INTERVAL > 0
112 memset(&stream->reporting_info, 0, sizeof((stream->reporting_info)));
113 #endif /* CONFIG_INFO_REPORTING_INTERVAL > 0 */
114
115 if (IS_ENABLED(CONFIG_LIBLC3) && bap_stream->codec_cfg != NULL &&
116 bap_stream->codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
117 int err;
118
119 err = lc3_enable(stream);
120 if (err < 0) {
121 LOG_ERR("Error: cannot enable LC3 codec: %d", err);
122 return err;
123 }
124 }
125
126 return 0;
127 }
128
stream_rx_stopped(struct bt_bap_stream * bap_stream)129 int stream_rx_stopped(struct bt_bap_stream *bap_stream)
130 {
131 struct stream_rx *stream = CONTAINER_OF(bap_stream, struct stream_rx, stream);
132
133 if (bap_stream == NULL) {
134 return -EINVAL;
135 }
136
137 if (IS_ENABLED(CONFIG_LIBLC3) && bap_stream->codec_cfg != NULL &&
138 bap_stream->codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
139 int err;
140
141 err = lc3_disable(stream);
142 if (err < 0) {
143 LOG_ERR("Error: cannot disable LC3 codec: %d", err);
144 return err;
145 }
146 }
147
148 return 0;
149 }
150
stream_rx_get_streams(struct bt_bap_stream * bap_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT])151 void stream_rx_get_streams(
152 struct bt_bap_stream *bap_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT])
153 {
154 for (size_t i = 0U; i < ARRAY_SIZE(rx_streams); i++) {
155 bap_streams[i] = &rx_streams[i].stream;
156 }
157 }
158