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