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