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