1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
|
/*
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
* www.ehima.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <array>
#include <map>
#include <optional>
#include <vector>
#include "raw_address.h"
namespace bluetooth {
namespace le_audio {
enum class ConnectionState {
DISCONNECTED = 0,
CONNECTING,
CONNECTED,
DISCONNECTING
};
enum class GroupStatus {
INACTIVE = 0,
ACTIVE,
};
enum class GroupStreamStatus {
IDLE = 0,
STREAMING,
RELEASING,
SUSPENDING,
SUSPENDED,
CONFIGURED_AUTONOMOUS,
CONFIGURED_BY_USER,
DESTROYED,
};
enum class GroupNodeStatus {
ADDED = 1,
REMOVED,
};
typedef enum {
LE_AUDIO_CODEC_INDEX_SOURCE_LC3 = 0,
LE_AUDIO_CODEC_INDEX_SOURCE_MAX
} btle_audio_codec_index_t;
typedef struct {
btle_audio_codec_index_t codec_type;
std::string ToString() const {
std::string codec_name_str;
switch (codec_type) {
case LE_AUDIO_CODEC_INDEX_SOURCE_LC3:
codec_name_str = "LC3";
break;
default:
codec_name_str = "Unknown LE codec " + std::to_string(codec_type);
break;
}
return "codec: " + codec_name_str;
}
} btle_audio_codec_config_t;
class LeAudioClientCallbacks {
public:
virtual ~LeAudioClientCallbacks() = default;
/* Callback to notify Java that stack is ready */
virtual void OnInitialized(void) = 0;
/** Callback for profile connection state change */
virtual void OnConnectionState(ConnectionState state,
const RawAddress& address) = 0;
/* Callback with group status update */
virtual void OnGroupStatus(int group_id, GroupStatus group_status) = 0;
/* Callback with node status update */
virtual void OnGroupNodeStatus(const RawAddress& bd_addr, int group_id,
GroupNodeStatus node_status) = 0;
/* Callback for newly recognized or reconfigured existing le audio group */
virtual void OnAudioConf(uint8_t direction, int group_id,
uint32_t snk_audio_location,
uint32_t src_audio_location,
uint16_t avail_cont) = 0;
/* Callback for sink audio location recognized */
virtual void OnSinkAudioLocationAvailable(const RawAddress& address,
uint32_t snk_audio_locations) = 0;
/* Callback with local codec capabilities */
virtual void OnAudioLocalCodecCapabilities(
std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf) = 0;
/* Callback with group codec configurations */
virtual void OnAudioGroupCodecConf(
int group_id, btle_audio_codec_config_t input_codec_conf,
btle_audio_codec_config_t output_codec_conf,
std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
std::vector<btle_audio_codec_config_t> output_selectable_codec_conf) = 0;
};
class LeAudioClientInterface {
public:
virtual ~LeAudioClientInterface() = default;
/* Register the LeAudio callbacks */
virtual void Initialize(
LeAudioClientCallbacks* callbacks,
const std::vector<btle_audio_codec_config_t>& offloading_preference) = 0;
/** Connect to LEAudio */
virtual void Connect(const RawAddress& address) = 0;
/** Disconnect from LEAudio */
virtual void Disconnect(const RawAddress& address) = 0;
/* Cleanup the LeAudio */
virtual void Cleanup(void) = 0;
/* Called when LeAudio is unbonded. */
virtual void RemoveDevice(const RawAddress& address) = 0;
/* Attach le audio node to group */
virtual void GroupAddNode(int group_id, const RawAddress& addr) = 0;
/* Detach le audio node from a group */
virtual void GroupRemoveNode(int group_id, const RawAddress& addr) = 0;
/* Set active le audio group */
virtual void GroupSetActive(int group_id) = 0;
/* Set codec config preference */
virtual void SetCodecConfigPreference(
int group_id, btle_audio_codec_config_t input_codec_config,
btle_audio_codec_config_t output_codec_config) = 0;
/* Set Ccid for context type */
virtual void SetCcidInformation(int ccid, int context_type) = 0;
};
/* Represents the broadcast source state. */
enum class BroadcastState {
STOPPED = 0,
CONFIGURING,
CONFIGURED,
STOPPING,
STREAMING,
};
/* A general hint for the codec configuration process. */
enum class BroadcastAudioProfile {
SONIFICATION = 0,
MEDIA,
};
using BroadcastId = uint32_t;
static constexpr BroadcastId kBroadcastIdInvalid = 0x00000000;
using BroadcastCode = std::array<uint8_t, 16>;
/* Content Metadata LTV Types */
constexpr uint8_t kLeAudioMetadataTypePreferredAudioContext = 0x01;
constexpr uint8_t kLeAudioMetadataTypeStreamingAudioContext = 0x02;
constexpr uint8_t kLeAudioMetadataTypeProgramInfo = 0x03;
constexpr uint8_t kLeAudioMetadataTypeLanguage = 0x04;
constexpr uint8_t kLeAudioMetadataTypeCcidList = 0x05;
/* Codec specific LTV Types */
constexpr uint8_t kLeAudioCodecLC3TypeSamplingFreq = 0x01;
constexpr uint8_t kLeAudioCodecLC3TypeFrameDuration = 0x02;
constexpr uint8_t kLeAudioCodecLC3TypeAudioChannelAllocation = 0x03;
constexpr uint8_t kLeAudioCodecLC3TypeOctetPerFrame = 0x04;
constexpr uint8_t kLeAudioCodecLC3TypeCodecFrameBlocksPerSdu = 0x05;
struct BasicAudioAnnouncementCodecConfig {
/* 5 octets for the Codec ID */
uint8_t codec_id;
uint16_t vendor_company_id;
uint16_t vendor_codec_id;
/* Codec params - series of LTV formatted triplets */
std::map<uint8_t, std::vector<uint8_t>> codec_specific_params;
};
struct BasicAudioAnnouncementBisConfig {
std::map<uint8_t, std::vector<uint8_t>> codec_specific_params;
uint8_t bis_index;
};
struct BasicAudioAnnouncementSubgroup {
/* Subgroup specific codec configuration and metadata */
BasicAudioAnnouncementCodecConfig codec_config;
// Content metadata
std::map<uint8_t, std::vector<uint8_t>> metadata;
// Broadcast channel configuration
std::vector<BasicAudioAnnouncementBisConfig> bis_configs;
};
struct BasicAudioAnnouncementData {
/* Announcement Header fields */
uint32_t presentation_delay;
/* Subgroup specific configurations */
std::vector<BasicAudioAnnouncementSubgroup> subgroup_configs;
};
struct BroadcastMetadata {
uint16_t pa_interval;
RawAddress addr;
uint8_t addr_type;
uint8_t adv_sid;
BroadcastId broadcast_id;
std::optional<BroadcastCode> broadcast_code;
/* Presentation delay and subgroup configurations */
BasicAudioAnnouncementData basic_audio_announcement;
};
class LeAudioBroadcasterCallbacks {
public:
virtual ~LeAudioBroadcasterCallbacks() = default;
/* Callback for the newly created broadcast event. */
virtual void OnBroadcastCreated(uint32_t broadcast_id, bool success) = 0;
/* Callback for the destroyed broadcast event. */
virtual void OnBroadcastDestroyed(uint32_t broadcast_id) = 0;
/* Callback for the broadcast source state event. */
virtual void OnBroadcastStateChanged(uint32_t broadcast_id,
BroadcastState state) = 0;
/* Callback for the broadcast metadata change. */
virtual void OnBroadcastMetadataChanged(
uint32_t broadcast_id, const BroadcastMetadata& broadcast_metadata) = 0;
};
class LeAudioBroadcasterInterface {
public:
virtual ~LeAudioBroadcasterInterface() = default;
/* Register the LeAudio Broadcaster callbacks */
virtual void Initialize(LeAudioBroadcasterCallbacks* callbacks) = 0;
/* Stop the LeAudio Broadcaster and all active broadcasts */
virtual void Stop(void) = 0;
/* Cleanup the LeAudio Broadcaster */
virtual void Cleanup(void) = 0;
/* Create Broadcast instance */
virtual void CreateBroadcast(std::vector<uint8_t> metadata,
BroadcastAudioProfile profile,
std::optional<BroadcastCode> broadcast_code) = 0;
/* Update the ongoing Broadcast metadata */
virtual void UpdateMetadata(uint32_t broadcast_id,
std::vector<uint8_t> metadata) = 0;
/* Start the existing Broadcast stream */
virtual void StartBroadcast(uint32_t broadcast_id) = 0;
/* Pause the ongoing Broadcast stream */
virtual void PauseBroadcast(uint32_t broadcast_id) = 0;
/* Stop the Broadcast (no stream, no periodic advertisements */
virtual void StopBroadcast(uint32_t broadcast_id) = 0;
/* Destroy the existing Broadcast instance */
virtual void DestroyBroadcast(uint32_t broadcast_id) = 0;
/* Get Broadcast Metadata */
virtual void GetBroadcastMetadata(uint32_t broadcast_id) = 0;
};
} /* namespace le_audio */
} /* namespace bluetooth */
|