1 /*
2 * Copyright 2021 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "bta/le_audio/broadcaster/state_machine.h"
19
20 #include <bind_helpers.h>
21 #include <bluetooth/log.h>
22
23 #include <algorithm>
24 #include <array>
25 #include <cstdint>
26 #include <functional>
27 #include <iostream>
28 #include <iterator>
29 #include <memory>
30 #include <optional>
31 #include <string>
32 #include <utility>
33 #include <vector>
34
35 #include "base/functional/bind.h"
36 #include "base/functional/callback.h"
37 #include "bta/le_audio/broadcaster/broadcaster_types.h"
38 #include "bta/le_audio/le_audio_types.h"
39 #include "btm_api_types.h"
40 #include "btm_iso_api_types.h"
41 #include "common/strings.h"
42 #include "hardware/ble_advertiser.h"
43 #include "hardware/bt_le_audio.h"
44 #include "hci/le_advertising_manager.h"
45 #include "hcidefs.h"
46 #include "main/shim/le_advertising_manager.h"
47 #include "stack/include/btm_iso_api.h"
48 #include "types/raw_address.h"
49
50 using bluetooth::common::ToString;
51 using bluetooth::hci::IsoManager;
52 using bluetooth::hci::iso_manager::big_create_cmpl_evt;
53 using bluetooth::hci::iso_manager::big_terminate_cmpl_evt;
54
55 using namespace bluetooth::le_audio::broadcaster;
56 using namespace bluetooth;
57
58 namespace {
59
60 // Advertising channels. These should be kept the same as those defined in the
61 // stack.
62 const int kAdvertisingChannel37 = (1 << 0);
63 const int kAdvertisingChannel38 = (1 << 1);
64 const int kAdvertisingChannel39 = (1 << 2);
65 const int kAdvertisingChannelAll =
66 (kAdvertisingChannel37 | kAdvertisingChannel38 | kAdvertisingChannel39);
67
68 class BroadcastStateMachineImpl : public BroadcastStateMachine {
69 public:
BroadcastStateMachineImpl(BroadcastStateMachineConfig msg)70 BroadcastStateMachineImpl(BroadcastStateMachineConfig msg)
71 : active_config_(std::nullopt), sm_config_(std::move(msg)) {}
72
~BroadcastStateMachineImpl()73 ~BroadcastStateMachineImpl() {
74 if (GetState() == State::STREAMING) {
75 TerminateBig();
76 }
77 DestroyBroadcastAnnouncement();
78 if (callbacks_) {
79 callbacks_->OnStateMachineDestroyed(GetBroadcastId());
80 }
81 }
82
Initialize()83 bool Initialize() override {
84 static constexpr uint8_t sNumBisMax = 31;
85
86 if (sm_config_.config.GetNumBisTotal() > sNumBisMax) {
87 log::error(
88 "Channel count of {} exceeds the maximum number of possible BISes, "
89 "which is {}",
90 sm_config_.config.GetNumBisTotal(), sNumBisMax);
91 return false;
92 }
93
94 CreateBroadcastAnnouncement(sm_config_.is_public, sm_config_.broadcast_name,
95 sm_config_.broadcast_id, sm_config_.public_announcement,
96 sm_config_.announcement, sm_config_.streaming_phy);
97 return true;
98 }
99
GetCodecConfig() const100 const std::vector<BroadcastSubgroupCodecConfig>& GetCodecConfig() const override {
101 return sm_config_.config.subgroups;
102 }
103
GetBroadcastConfig() const104 const BroadcastConfiguration& GetBroadcastConfig() const override { return sm_config_.config; }
105
GetBigConfig() const106 std::optional<BigConfig> const& GetBigConfig() const override { return active_config_; }
107
GetStateMachineConfig() const108 BroadcastStateMachineConfig const& GetStateMachineConfig() const override { return sm_config_; }
109
RequestOwnAddress(base::Callback<void (uint8_t,RawAddress)> cb)110 void RequestOwnAddress(
111 base::Callback<void(uint8_t /* address_type*/, RawAddress /*address*/)> cb) override {
112 uint8_t advertising_sid = GetAdvertisingSid();
113 advertiser_if_->GetOwnAddress(advertising_sid, cb);
114 }
115
RequestOwnAddress(void)116 void RequestOwnAddress(void) override {
117 auto broadcast_id = GetBroadcastId();
118 RequestOwnAddress(base::Bind(&IBroadcastStateMachineCallbacks::OnOwnAddressResponse,
119 base::Unretained(this->callbacks_), broadcast_id));
120 }
121
GetOwnAddress()122 RawAddress GetOwnAddress() override { return addr_; }
123
GetOwnAddressType()124 uint8_t GetOwnAddressType() override { return addr_type_; }
125
GetBroadcastId() const126 bluetooth::le_audio::BroadcastId GetBroadcastId() const override {
127 return sm_config_.broadcast_id;
128 }
129
GetBroadcastCode() const130 std::optional<bluetooth::le_audio::BroadcastCode> GetBroadcastCode() const override {
131 return sm_config_.broadcast_code;
132 }
133
GetBroadcastAnnouncement() const134 const bluetooth::le_audio::BasicAudioAnnouncementData& GetBroadcastAnnouncement() const override {
135 return sm_config_.announcement;
136 }
137
IsPublicBroadcast()138 bool IsPublicBroadcast() override { return sm_config_.is_public; }
139
GetBroadcastName()140 std::string GetBroadcastName() override { return sm_config_.broadcast_name; }
141
GetPublicBroadcastAnnouncement() const142 const bluetooth::le_audio::PublicBroadcastAnnouncementData& GetPublicBroadcastAnnouncement()
143 const override {
144 return sm_config_.public_announcement;
145 }
146
OnCreateAnnouncement(uint8_t advertising_sid,int8_t tx_power,uint8_t status)147 void OnCreateAnnouncement(uint8_t advertising_sid, int8_t tx_power, uint8_t status) {
148 log::info("advertising_sid={} tx_power={} status={}", advertising_sid, tx_power, status);
149
150 /* If this callback gets called the advertising_sid is valid even though the
151 * status can be other than SUCCESS.
152 */
153 advertising_sid_ = advertising_sid;
154
155 if (status != bluetooth::hci::AdvertisingCallback::AdvertisingStatus::SUCCESS) {
156 log::error("Creating Announcement failed");
157 callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), false);
158 return;
159 }
160
161 advertiser_if_->GetOwnAddress(
162 advertising_sid,
163 base::Bind(&BroadcastStateMachineImpl::OnAddressResponse, base::Unretained(this)));
164 }
165
OnEnableAnnouncement(bool enable,uint8_t status)166 void OnEnableAnnouncement(bool enable, uint8_t status) {
167 log::info("operation={}, broadcast_id={}, status={}", enable ? "enable" : "disable",
168 GetBroadcastId(), status);
169
170 if (status == bluetooth::hci::AdvertisingCallback::AdvertisingStatus::SUCCESS) {
171 /* Periodic is enabled but without BIGInfo. Stream is suspended. */
172 if (enable) {
173 SetState(State::CONFIGURED);
174 /* Target state is always STREAMING state - start it now. */
175 ProcessMessage(Message::START);
176 } else {
177 /* User wanted to stop the announcement - report target state reached */
178 SetState(State::STOPPED);
179 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
180 }
181 } else {
182 // Handle error case
183 if (enable) {
184 /* Error on enabling */
185 SetState(State::STOPPED);
186 } else {
187 /* Error on disabling */
188 SetState(State::CONFIGURED);
189 }
190 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
191 }
192 }
193
OnUpdateAnnouncement(uint8_t status)194 void OnUpdateAnnouncement(uint8_t status) {
195 log::info("broadcast_id={}, status={}", GetBroadcastId(), status);
196
197 if (status == bluetooth::hci::AdvertisingCallback::AdvertisingStatus::SUCCESS) {
198 callbacks_->OnAnnouncementUpdated(GetBroadcastId());
199 } else {
200 log::error("Updating Announcement failed");
201 }
202 }
203
UpdatePublicBroadcastAnnouncement(uint32_t broadcast_id,const std::string & broadcast_name,const bluetooth::le_audio::PublicBroadcastAnnouncementData & announcement)204 void UpdatePublicBroadcastAnnouncement(
205 uint32_t broadcast_id, const std::string& broadcast_name,
206 const bluetooth::le_audio::PublicBroadcastAnnouncementData& announcement) override {
207 std::vector<uint8_t> adv_data;
208 PrepareAdvertisingData(true, broadcast_name, broadcast_id, announcement, adv_data);
209
210 sm_config_.broadcast_name = broadcast_name;
211 sm_config_.public_announcement = announcement;
212 advertiser_if_->SetData(advertising_sid_, false, adv_data, base::DoNothing());
213 }
214
UpdateBroadcastAnnouncement(bluetooth::le_audio::BasicAudioAnnouncementData announcement)215 void UpdateBroadcastAnnouncement(
216 bluetooth::le_audio::BasicAudioAnnouncementData announcement) override {
217 std::vector<uint8_t> periodic_data;
218 PreparePeriodicData(announcement, periodic_data);
219
220 sm_config_.announcement = std::move(announcement);
221 advertiser_if_->SetPeriodicAdvertisingData(advertising_sid_, periodic_data, base::DoNothing());
222 }
223
ProcessMessage(Message msg,const void * data=nullptr)224 void ProcessMessage(Message msg, const void* data = nullptr) override {
225 log::info("broadcast_id={}, state={}, message={}", GetBroadcastId(), ToString(GetState()),
226 ToString(msg));
227 switch (msg) {
228 case Message::START:
229 start_msg_handlers[StateMachine::GetState()](data);
230 break;
231 case Message::STOP:
232 stop_msg_handlers[StateMachine::GetState()](data);
233 break;
234 case Message::SUSPEND:
235 suspend_msg_handlers[StateMachine::GetState()](data);
236 break;
237 };
238 }
239
240 static IBroadcastStateMachineCallbacks* callbacks_;
241 static ::BleAdvertiserInterface* advertiser_if_;
242
243 private:
244 std::optional<BigConfig> active_config_;
245 BroadcastStateMachineConfig sm_config_;
246
247 /* Message handlers for each possible state */
248 typedef std::function<void(const void*)> msg_handler_t;
249 const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT> start_msg_handlers{
250 /* in STOPPED state */
__anon1bc24a3d0202() 251 [this](const void*) {
252 SetState(State::CONFIGURING);
253 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
254 EnableAnnouncement();
255 },
256 /* in CONFIGURING state */
__anon1bc24a3d0302() 257 [](const void*) { /* Do nothing */ },
258 /* in CONFIGURED state */
__anon1bc24a3d0402() 259 [this](const void*) {
260 SetState(State::ENABLING);
261 CreateBig();
262 },
263 /* in ENABLING state */
__anon1bc24a3d0502() 264 [](const void*) { /* Do nothing */ },
265 /* in DISABLING state */
__anon1bc24a3d0602() 266 [this](const void*) { SetState(State::ENABLING); },
267 /* in STOPPING state */
__anon1bc24a3d0702() 268 [](const void*) { /* Do nothing */ },
269 /* in STREAMING state */
__anon1bc24a3d0802() 270 [](const void*) { /* Do nothing */ }};
271
272 const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT> stop_msg_handlers{
273 /* in STOPPED state */
__anon1bc24a3d0902() 274 [](const void*) { /* Already stopped */ },
275 /* in CONFIGURING state */
__anon1bc24a3d0a02() 276 [](const void*) { /* Do nothing */ },
277 /* in CONFIGURED state */
__anon1bc24a3d0b02() 278 [this](const void*) {
279 SetState(State::STOPPING);
280 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
281 DisableAnnouncement();
282 },
283 /* in ENABLING state */
__anon1bc24a3d0c02() 284 [this](const void*) {
285 SetState(State::STOPPING);
286 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
287 },
288 /* in DISABLING state */
__anon1bc24a3d0d02() 289 [](const void*) { /* Do nothing */ },
290 /* in STOPPING state */
__anon1bc24a3d0e02() 291 [](const void*) { /* Do nothing */ },
292 /* in STREAMING state */
__anon1bc24a3d0f02() 293 [this](const void*) {
294 SetState(State::STOPPING);
295 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
296 TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
297 }};
298
299 const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT> suspend_msg_handlers{
300 /* in STOPPED state */
__anon1bc24a3d1002() 301 [](const void*) { /* Do nothing */ },
302 /* in CONFIGURING state */
__anon1bc24a3d1102() 303 [](const void*) { /* Do nothing */ },
304 /* in CONFIGURED state */
__anon1bc24a3d1202() 305 [](const void*) { /* Already suspended */ },
306 /* in ENABLING state */
__anon1bc24a3d1302() 307 [this](const void*) {
308 SetState(State::DISABLING);
309
310 if (active_config_ != std::nullopt) {
311 TerminateBig();
312 }
313 },
314 /* in DISABLING state */
__anon1bc24a3d1402() 315 [](const void*) { /* Do nothing */ },
316 /* in STOPPING state */
__anon1bc24a3d1502() 317 [](const void*) { /* Do nothing */ },
318 /* in STREAMING state */
__anon1bc24a3d1602() 319 [this](const void*) {
320 SetState(State::DISABLING);
321 TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
322 }};
323
324 const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT> resume_msg_handlers{
325 /* in STOPPED state */
__anon1bc24a3d1702() 326 [](const void*) { /* Do nothing */ },
327 /* in CONFIGURING state */
__anon1bc24a3d1802() 328 [](const void*) { /* Do nothing */ },
329 /* in CONFIGURED state */
__anon1bc24a3d1902() 330 [this](const void*) {
331 SetState(State::ENABLING);
332 CreateBig();
333 },
334 /* in ENABLING state */
__anon1bc24a3d1a02() 335 [](const void*) { /* Do nothing */ },
336 /* in DISABLING state */
__anon1bc24a3d1b02() 337 [](const void*) { /* Do nothing */ },
338 /* in STOPPING state */
__anon1bc24a3d1c02() 339 [](const void*) { /* Do nothing */ },
340 /* in STREAMING state */
__anon1bc24a3d1d02() 341 [](const void*) { /* Already streaming */ }};
342
OnAddressResponse(uint8_t addr_type,RawAddress addr)343 void OnAddressResponse(uint8_t addr_type, RawAddress addr) {
344 log::info("own address={}, type={}", addr, addr_type);
345 addr_ = addr;
346 addr_type_ = addr_type;
347
348 /* Ext. advertisings are already on */
349 SetState(State::CONFIGURED);
350
351 callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), true);
352 callbacks_->OnStateMachineEvent(GetBroadcastId(), State::CONFIGURED);
353 }
354
CreateBroadcastAnnouncement(bool is_public,const std::string & broadcast_name,bluetooth::le_audio::BroadcastId & broadcast_id,const bluetooth::le_audio::PublicBroadcastAnnouncementData & public_announcement,const bluetooth::le_audio::BasicAudioAnnouncementData & announcement,uint8_t streaming_phy)355 void CreateBroadcastAnnouncement(
356 bool is_public, const std::string& broadcast_name,
357 bluetooth::le_audio::BroadcastId& broadcast_id,
358 const bluetooth::le_audio::PublicBroadcastAnnouncementData& public_announcement,
359 const bluetooth::le_audio::BasicAudioAnnouncementData& announcement,
360 uint8_t streaming_phy) {
361 log::info("is_public={}, broadcast_name={}, public_features={}",
362 is_public ? "public" : "non-public", broadcast_name, public_announcement.features);
363 if (advertiser_if_ != nullptr) {
364 ::AdvertiseParameters adv_params;
365 ::PeriodicAdvertisingParameters periodic_params;
366 std::vector<uint8_t> adv_data;
367 std::vector<uint8_t> periodic_data;
368
369 PrepareAdvertisingData(is_public, broadcast_name, broadcast_id, public_announcement,
370 adv_data);
371 PreparePeriodicData(announcement, periodic_data);
372
373 adv_params.min_interval = 0x00A0; /* 160 * 0,625 = 100ms */
374 adv_params.max_interval = 0x0140; /* 320 * 0,625 = 200ms */
375 adv_params.advertising_event_properties = 0;
376 adv_params.channel_map = kAdvertisingChannelAll;
377 adv_params.tx_power = 8;
378 adv_params.primary_advertising_phy = PHY_LE_1M;
379 adv_params.secondary_advertising_phy = streaming_phy;
380 adv_params.scan_request_notification_enable = 0;
381 adv_params.own_address_type = kBroadcastAdvertisingType;
382
383 periodic_params.max_interval = BroadcastStateMachine::kPaIntervalMax;
384 periodic_params.min_interval = BroadcastStateMachine::kPaIntervalMin;
385 periodic_params.periodic_advertising_properties = 0;
386 periodic_params.enable = true;
387
388 /* Status and timeout callbacks are handled by OnAdvertisingSetStarted()
389 * which returns the status and handle to be used later in CreateBIG
390 * command.
391 */
392 advertiser_if_->StartAdvertisingSet(
393 kAdvertiserClientIdLeAudio, kLeAudioBroadcastRegId, base::DoNothing(), adv_params,
394 adv_data, std::vector<uint8_t>(), periodic_params, periodic_data, 0 /* duration */,
395 0 /* maxExtAdvEvents */, base::DoNothing());
396 }
397 }
398
DestroyBroadcastAnnouncement()399 void DestroyBroadcastAnnouncement() { advertiser_if_->Unregister(GetAdvertisingSid()); }
400
EnableAnnouncement()401 void EnableAnnouncement() {
402 log::info("broadcast_id={}", GetBroadcastId());
403 // Callback is handled by OnAdvertisingEnabled() which returns the status
404 advertiser_if_->Enable(GetAdvertisingSid(), true, base::DoNothing(), 0,
405 0, /* Enable until stopped */
406 base::DoNothing());
407 }
408
CreateBig(void)409 void CreateBig(void) {
410 log::info("broadcast_id={}", GetBroadcastId());
411 /* TODO: Figure out how to decide on the currently hard-codded params. */
412 struct bluetooth::hci::iso_manager::big_create_params big_params = {
413 .adv_handle = GetAdvertisingSid(),
414 .num_bis = sm_config_.config.GetNumBisTotal(),
415 .sdu_itv = sm_config_.config.GetSduIntervalUs(),
416 .max_sdu_size = sm_config_.config.GetMaxSduOctets(),
417 .max_transport_latency = sm_config_.config.qos.getMaxTransportLatency(),
418 .rtn = sm_config_.config.qos.getRetransmissionNumber(),
419 .phy = sm_config_.streaming_phy,
420 .packing = 0x00, /* Sequencial */
421 .framing = 0x00, /* Unframed */
422 .enc = static_cast<uint8_t>(sm_config_.broadcast_code ? 1 : 0),
423 .enc_code = sm_config_.broadcast_code ? *sm_config_.broadcast_code
424 : std::array<uint8_t, 16>({0}),
425 };
426
427 IsoManager::GetInstance()->CreateBig(GetAdvertisingSid(), std::move(big_params));
428 }
429
DisableAnnouncement(void)430 void DisableAnnouncement(void) {
431 log::info("broadcast_id={}", GetBroadcastId());
432 // Callback is handled by OnAdvertisingEnabled() which returns the status
433 advertiser_if_->Enable(GetAdvertisingSid(), false, base::DoNothing(), 0, 0, base::DoNothing());
434 }
435
TerminateBig()436 void TerminateBig() {
437 log::info("disabling={}", GetState() == BroadcastStateMachine::State::DISABLING);
438 /* Terminate with reason: Remote User Terminated Connection */
439 IsoManager::GetInstance()->TerminateBig(GetAdvertisingSid(), 0x13);
440 }
441
OnSetupIsoDataPath(uint8_t status,uint16_t conn_hdl)442 void OnSetupIsoDataPath(uint8_t status, uint16_t conn_hdl) override {
443 log::assert_that(active_config_ != std::nullopt,
444 "assert failed: active_config_ != std::nullopt");
445
446 if (status != 0) {
447 log::error("Failure creating data path. Tearing down the BIG now.");
448 SetState(State::DISABLING);
449 TerminateBig();
450 return;
451 }
452
453 /* Look for the next BIS handle */
454 auto handle_it = std::find_if(active_config_->connection_handles.begin(),
455 active_config_->connection_handles.end(),
456 [conn_hdl](const auto& handle) { return conn_hdl == handle; });
457 log::assert_that(handle_it != active_config_->connection_handles.end(),
458 "assert failed: handle_it != active_config_->connection_handles.end()");
459 handle_it = std::next(handle_it);
460
461 if (handle_it == active_config_->connection_handles.end()) {
462 if (GetState() == BroadcastStateMachine::State::STOPPING) {
463 // All ISO setup completed, but we're in stopping state, we need to tear down all ISO
464 log::warn("ISO setup in stopping state. Tearing down ISO data path.");
465 // Remain in STOPPING, BIG will be terminated in OnRemoveIsoDataPath
466 TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
467 return;
468 }
469 /* It was the last BIS to set up - change state to streaming */
470 SetState(State::STREAMING);
471 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState(), nullptr);
472 } else {
473 /* Note: We would feed a watchdog here if we had one */
474 /* There are more BISes to set up data path for */
475 log::info("There is more data paths to set up.");
476 TriggerIsoDatapathSetup(*handle_it);
477 }
478 }
479
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle)480 void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle) override {
481 log::assert_that(active_config_ != std::nullopt,
482 "assert failed: active_config_ != std::nullopt");
483
484 if (status != 0) {
485 log::error("Failure removing data path. Tearing down the BIG now.");
486 TerminateBig();
487 return;
488 }
489
490 /* Look for the next BIS handle */
491 auto handle_it = std::find_if(
492 active_config_->connection_handles.begin(), active_config_->connection_handles.end(),
493 [conn_handle](const auto& handle) { return conn_handle == handle; });
494 log::assert_that(handle_it != active_config_->connection_handles.end(),
495 "assert failed: handle_it != active_config_->connection_handles.end()");
496 handle_it = std::next(handle_it);
497
498 if (handle_it == active_config_->connection_handles.end()) {
499 /* It was the last one to set up - start tearing down the BIG */
500 TerminateBig();
501 } else {
502 /* Note: We would feed a watchdog here if we had one */
503 /* There are more BISes to tear down data path for */
504 log::info("There is more data paths to tear down.");
505 TriggerIsoDatapathTeardown(*handle_it);
506 }
507 }
508
TriggerIsoDatapathSetup(uint16_t conn_handle)509 void TriggerIsoDatapathSetup(uint16_t conn_handle) {
510 log::info("conn_hdl={}", conn_handle);
511 log::assert_that(active_config_ != std::nullopt,
512 "assert failed: active_config_ != std::nullopt");
513
514 /* Note: If coding format is transparent, 'codec_id_company' and
515 * 'codec_id_vendor' shall be ignored.
516 */
517 auto& iso_datapath_config = sm_config_.config.data_path.isoDataPathConfig;
518 bluetooth::hci::iso_manager::iso_data_path_params param = {
519 .data_path_dir = bluetooth::hci::iso_manager::kIsoDataPathDirectionIn,
520 .data_path_id = static_cast<uint8_t>(sm_config_.config.data_path.dataPathId),
521 .codec_id_format = static_cast<uint8_t>(
522 iso_datapath_config.isTransparent ? bluetooth::hci::kIsoCodingFormatTransparent
523 : iso_datapath_config.codecId.coding_format),
524 .codec_id_company =
525 static_cast<uint16_t>(iso_datapath_config.isTransparent
526 ? 0x0000
527 : iso_datapath_config.codecId.vendor_company_id),
528 .codec_id_vendor =
529 static_cast<uint16_t>(iso_datapath_config.isTransparent
530 ? 0x0000
531 : iso_datapath_config.codecId.vendor_codec_id),
532 .controller_delay = iso_datapath_config.controllerDelayUs,
533 .codec_conf = iso_datapath_config.configuration,
534 };
535 IsoManager::GetInstance()->SetupIsoDataPath(conn_handle, std::move(param));
536 }
537
TriggerIsoDatapathTeardown(uint16_t conn_handle)538 void TriggerIsoDatapathTeardown(uint16_t conn_handle) {
539 log::info("conn_hdl={}", conn_handle);
540 log::assert_that(active_config_ != std::nullopt,
541 "assert failed: active_config_ != std::nullopt");
542
543 SetMuted(true);
544 IsoManager::GetInstance()->RemoveIsoDataPath(
545 conn_handle, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput);
546 }
547
HandleHciEvent(uint16_t event,void * data)548 void HandleHciEvent(uint16_t event, void* data) override {
549 switch (event) {
550 case HCI_BLE_CREATE_BIG_CPL_EVT: {
551 auto* evt = static_cast<big_create_cmpl_evt*>(data);
552
553 if (evt->big_id != GetAdvertisingSid()) {
554 log::error("State={}, Event={}, Unknown big, big_id={}", ToString(GetState()), event,
555 evt->big_id);
556 break;
557 }
558
559 if (evt->status == 0x00) {
560 log::info("BIG create BIG complete, big_id={}", evt->big_id);
561 active_config_ = {
562 .status = evt->status,
563 .big_id = evt->big_id,
564 .big_sync_delay = evt->big_sync_delay,
565 .transport_latency_big = evt->transport_latency_big,
566 .phy = evt->phy,
567 .nse = evt->nse,
568 .bn = evt->bn,
569 .pto = evt->pto,
570 .irc = evt->irc,
571 .max_pdu = evt->max_pdu,
572 .iso_interval = evt->iso_interval,
573 .connection_handles = evt->conn_handles,
574 };
575
576 if (GetState() == BroadcastStateMachine::State::DISABLING ||
577 GetState() == BroadcastStateMachine::State::STOPPING) {
578 log::info("Terminating BIG in state={}, big_id={}", ToString(GetState()), evt->big_id);
579 TerminateBig();
580 } else {
581 callbacks_->OnBigCreated(evt->conn_handles);
582 TriggerIsoDatapathSetup(evt->conn_handles[0]);
583 }
584 } else {
585 log::error("State={} Event={}. Unable to create big, big_id={}, status={}",
586 ToString(GetState()), event, evt->big_id, evt->status);
587 }
588 } break;
589 case HCI_BLE_TERM_BIG_CPL_EVT: {
590 auto* evt = static_cast<big_terminate_cmpl_evt*>(data);
591
592 log::info("BIG terminate BIG cmpl in state={}, reason={} big_id={}", ToString(GetState()),
593 evt->reason, evt->big_id);
594
595 if (evt->big_id != GetAdvertisingSid()) {
596 log::error("State={} Event={}, unknown adv.sid={}", ToString(GetState()), event,
597 evt->big_id);
598 break;
599 }
600
601 active_config_ = std::nullopt;
602 bool disabling = GetState() == BroadcastStateMachine::State::DISABLING;
603
604 /* Go back to configured if BIG is inactive (we are still announcing) and state is not
605 * stopping*/
606 if (GetState() != BroadcastStateMachine::State::STOPPING) {
607 SetState(State::CONFIGURED);
608 }
609
610 /* Check if we got this HCI event due to STOP or SUSPEND message. */
611 if (disabling) {
612 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState(), evt);
613 } else {
614 DisableAnnouncement();
615 }
616 } break;
617 default:
618 log::error("State={} Unknown event={}", ToString(GetState()), event);
619 break;
620 }
621 }
622 };
623
624 IBroadcastStateMachineCallbacks* BroadcastStateMachineImpl::callbacks_ = nullptr;
625 ::BleAdvertiserInterface* BroadcastStateMachineImpl::advertiser_if_ = nullptr;
626 } /* namespace */
627
CreateInstance(BroadcastStateMachineConfig msg)628 std::unique_ptr<BroadcastStateMachine> BroadcastStateMachine::CreateInstance(
629 BroadcastStateMachineConfig msg) {
630 return std::make_unique<BroadcastStateMachineImpl>(std::move(msg));
631 }
632
Initialize(IBroadcastStateMachineCallbacks * callbacks,AdvertisingCallbacks * adv_callbacks)633 void BroadcastStateMachine::Initialize(IBroadcastStateMachineCallbacks* callbacks,
634 AdvertisingCallbacks* adv_callbacks) {
635 BroadcastStateMachineImpl::callbacks_ = callbacks;
636 /* Get gd le advertiser interface */
637 BroadcastStateMachineImpl::advertiser_if_ = bluetooth::shim::get_ble_advertiser_instance();
638 if (BroadcastStateMachineImpl::advertiser_if_ != nullptr) {
639 log::info("Advertiser_instance acquired");
640 BroadcastStateMachineImpl::advertiser_if_->RegisterCallbacksNative(adv_callbacks,
641 kAdvertiserClientIdLeAudio);
642 } else {
643 log::error("Could not acquire advertiser_instance!");
644 BroadcastStateMachineImpl::advertiser_if_ = nullptr;
645 }
646 }
647
648 namespace bluetooth::le_audio {
649 namespace broadcaster {
650
operator <<(std::ostream & os,const BroadcastStateMachine::Message & msg)651 std::ostream& operator<<(std::ostream& os, const BroadcastStateMachine::Message& msg) {
652 static const char* char_value_[BroadcastStateMachine::MESSAGE_COUNT] = {"START", "SUSPEND",
653 "STOP"};
654 os << char_value_[static_cast<uint8_t>(msg)];
655 return os;
656 }
657
operator <<(std::ostream & os,const BroadcastStateMachine::State & state)658 std::ostream& operator<<(std::ostream& os, const BroadcastStateMachine::State& state) {
659 static const char* char_value_[BroadcastStateMachine::STATE_COUNT] = {
660 "STOPPED", "CONFIGURING", "CONFIGURED", "ENABLING", "DISABLING", "STOPPING", "STREAMING"};
661 os << char_value_[static_cast<uint8_t>(state)];
662 return os;
663 }
664
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BigConfig & config)665 std::ostream& operator<<(std::ostream& os,
666 const bluetooth::le_audio::broadcaster::BigConfig& config) {
667 os << "\n";
668 os << " Status: 0x" << std::hex << +config.status << std::dec << "\n";
669 os << " BIG ID: " << +config.big_id << "\n";
670 os << " Sync delay: " << config.big_sync_delay << "\n";
671 os << " Transport Latency: " << config.transport_latency_big << "\n";
672 os << " Phy: " << +config.phy << "\n";
673 os << " Nse: " << +config.nse << "\n";
674 os << " Bn: " << +config.bn << "\n";
675 os << " Pto: " << +config.pto << "\n";
676 os << " Irc: " << +config.irc << "\n";
677 os << " Max pdu: " << config.max_pdu << "\n";
678 os << " Iso interval: " << config.iso_interval << "\n";
679 os << " Connection handles (BISes): [";
680 for (auto& el : config.connection_handles) {
681 os << std::hex << +el << std::dec << ":";
682 }
683 os << "]";
684 return os;
685 }
686
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig & config)687 std::ostream& operator<<(
688 std::ostream& os,
689 const bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig& config) {
690 const char* const PHYS[] = {"NONE", "1M", "2M", "CODED"};
691
692 os << "\n";
693 os << " Broadcast ID: " << config.broadcast_id << "\n";
694 os << " Streaming PHY: "
695 << ((config.streaming_phy > 3) ? std::to_string(config.streaming_phy)
696 : PHYS[config.streaming_phy])
697 << "\n";
698 os << " Subgroups: {\n";
699 for (auto const& subgroup : config.config.subgroups) {
700 os << " " << subgroup << "\n";
701 }
702 os << " }\n";
703 os << " Qos Config: " << config.config.qos << "\n";
704 if (config.broadcast_code) {
705 os << " Broadcast Code: [";
706 for (auto& el : *config.broadcast_code) {
707 os << std::hex << +el << ":";
708 }
709 os << "]\n";
710 } else {
711 os << " Broadcast Code: NONE\n";
712 }
713
714 std::vector<uint8_t> an_raw;
715 ToRawPacket(config.announcement, an_raw);
716 os << " Announcement RAW: [";
717 for (auto& el : an_raw) {
718 os << std::hex << +el << ":";
719 }
720 os << "]";
721
722 return os;
723 }
724
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastStateMachine & machine)725 std::ostream& operator<<(std::ostream& os,
726 const bluetooth::le_audio::broadcaster::BroadcastStateMachine& machine) {
727 os << " Broadcast state machine: {"
728 << " Advertising SID: " << +machine.GetAdvertisingSid() << "\n"
729 << " State: " << machine.GetState() << "\n";
730 os << " State Machine Config: " << machine.GetStateMachineConfig() << "\n";
731
732 if (machine.GetBigConfig()) {
733 os << " BigConfig: " << *machine.GetBigConfig() << "\n";
734 } else {
735 os << " BigConfig: NONE\n";
736 }
737 os << " }\n";
738 return os;
739 }
740
741 } // namespace broadcaster
742 } // namespace bluetooth::le_audio
743