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 */
__anon1ad8bfbd0202() 251 [this](const void*) {
252 SetState(State::CONFIGURING);
253 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
254 EnableAnnouncement();
255 },
256 /* in CONFIGURING state */
__anon1ad8bfbd0302() 257 [](const void*) { /* Do nothing */ },
258 /* in CONFIGURED state */
__anon1ad8bfbd0402() 259 [this](const void*) {
260 SetState(State::ENABLING);
261 CreateBig();
262 },
263 /* in ENABLING state */
__anon1ad8bfbd0502() 264 [](const void*) { /* Do nothing */ },
265 /* in DISABLING state */
__anon1ad8bfbd0602() 266 [this](const void*) { SetState(State::ENABLING); },
267 /* in STOPPING state */
__anon1ad8bfbd0702() 268 [](const void*) { /* Do nothing */ },
269 /* in STREAMING state */
__anon1ad8bfbd0802() 270 [](const void*) { /* Do nothing */ }};
271
272 const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT> stop_msg_handlers{
273 /* in STOPPED state */
__anon1ad8bfbd0902() 274 [](const void*) { /* Already stopped */ },
275 /* in CONFIGURING state */
__anon1ad8bfbd0a02() 276 [](const void*) { /* Do nothing */ },
277 /* in CONFIGURED state */
__anon1ad8bfbd0b02() 278 [this](const void*) {
279 SetState(State::STOPPING);
280 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
281 DisableAnnouncement();
282 },
283 /* in ENABLING state */
__anon1ad8bfbd0c02() 284 [](const void*) { /* Do nothing */ },
285 /* in DISABLING state */
__anon1ad8bfbd0d02() 286 [](const void*) { /* Do nothing */ },
287 /* in STOPPING state */
__anon1ad8bfbd0e02() 288 [](const void*) { /* Do nothing */ },
289 /* in STREAMING state */
__anon1ad8bfbd0f02() 290 [this](const void*) {
291 SetState(State::STOPPING);
292 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState());
293 TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
294 }};
295
296 const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT> suspend_msg_handlers{
297 /* in STOPPED state */
__anon1ad8bfbd1002() 298 [](const void*) { /* Do nothing */ },
299 /* in CONFIGURING state */
__anon1ad8bfbd1102() 300 [](const void*) { /* Do nothing */ },
301 /* in CONFIGURED state */
__anon1ad8bfbd1202() 302 [](const void*) { /* Already suspended */ },
303 /* in ENABLING state */
__anon1ad8bfbd1302() 304 [this](const void*) {
305 SetState(State::DISABLING);
306
307 if (active_config_ != std::nullopt) {
308 TerminateBig();
309 }
310 },
311 /* in DISABLING state */
__anon1ad8bfbd1402() 312 [](const void*) { /* Do nothing */ },
313 /* in STOPPING state */
__anon1ad8bfbd1502() 314 [](const void*) { /* Do nothing */ },
315 /* in STREAMING state */
__anon1ad8bfbd1602() 316 [this](const void*) {
317 SetState(State::DISABLING);
318 TriggerIsoDatapathTeardown(active_config_->connection_handles[0]);
319 }};
320
321 const std::array<msg_handler_t, BroadcastStateMachine::STATE_COUNT> resume_msg_handlers{
322 /* in STOPPED state */
__anon1ad8bfbd1702() 323 [](const void*) { /* Do nothing */ },
324 /* in CONFIGURING state */
__anon1ad8bfbd1802() 325 [](const void*) { /* Do nothing */ },
326 /* in CONFIGURED state */
__anon1ad8bfbd1902() 327 [this](const void*) {
328 SetState(State::ENABLING);
329 CreateBig();
330 },
331 /* in ENABLING state */
__anon1ad8bfbd1a02() 332 [](const void*) { /* Do nothing */ },
333 /* in DISABLING state */
__anon1ad8bfbd1b02() 334 [](const void*) { /* Do nothing */ },
335 /* in STOPPING state */
__anon1ad8bfbd1c02() 336 [](const void*) { /* Do nothing */ },
337 /* in STREAMING state */
__anon1ad8bfbd1d02() 338 [](const void*) { /* Already streaming */ }};
339
OnAddressResponse(uint8_t addr_type,RawAddress addr)340 void OnAddressResponse(uint8_t addr_type, RawAddress addr) {
341 log::info("own address={}, type={}", addr, addr_type);
342 addr_ = addr;
343 addr_type_ = addr_type;
344
345 /* Ext. advertisings are already on */
346 SetState(State::CONFIGURED);
347
348 callbacks_->OnStateMachineCreateStatus(GetBroadcastId(), true);
349 callbacks_->OnStateMachineEvent(GetBroadcastId(), State::CONFIGURED);
350 }
351
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)352 void CreateBroadcastAnnouncement(
353 bool is_public, const std::string& broadcast_name,
354 bluetooth::le_audio::BroadcastId& broadcast_id,
355 const bluetooth::le_audio::PublicBroadcastAnnouncementData& public_announcement,
356 const bluetooth::le_audio::BasicAudioAnnouncementData& announcement,
357 uint8_t streaming_phy) {
358 log::info("is_public={}, broadcast_name={}, public_features={}",
359 is_public ? "public" : "non-public", broadcast_name, public_announcement.features);
360 if (advertiser_if_ != nullptr) {
361 ::AdvertiseParameters adv_params;
362 ::PeriodicAdvertisingParameters periodic_params;
363 std::vector<uint8_t> adv_data;
364 std::vector<uint8_t> periodic_data;
365
366 PrepareAdvertisingData(is_public, broadcast_name, broadcast_id, public_announcement,
367 adv_data);
368 PreparePeriodicData(announcement, periodic_data);
369
370 adv_params.min_interval = 0x00A0; /* 160 * 0,625 = 100ms */
371 adv_params.max_interval = 0x0140; /* 320 * 0,625 = 200ms */
372 adv_params.advertising_event_properties = 0;
373 adv_params.channel_map = kAdvertisingChannelAll;
374 adv_params.tx_power = 8;
375 adv_params.primary_advertising_phy = PHY_LE_1M;
376 adv_params.secondary_advertising_phy = streaming_phy;
377 adv_params.scan_request_notification_enable = 0;
378 adv_params.own_address_type = kBroadcastAdvertisingType;
379
380 periodic_params.max_interval = BroadcastStateMachine::kPaIntervalMax;
381 periodic_params.min_interval = BroadcastStateMachine::kPaIntervalMin;
382 periodic_params.periodic_advertising_properties = 0;
383 periodic_params.enable = true;
384
385 /* Status and timeout callbacks are handled by OnAdvertisingSetStarted()
386 * which returns the status and handle to be used later in CreateBIG
387 * command.
388 */
389 advertiser_if_->StartAdvertisingSet(
390 kAdvertiserClientIdLeAudio, kLeAudioBroadcastRegId, base::DoNothing(), adv_params,
391 adv_data, std::vector<uint8_t>(), periodic_params, periodic_data, 0 /* duration */,
392 0 /* maxExtAdvEvents */, base::DoNothing());
393 }
394 }
395
DestroyBroadcastAnnouncement()396 void DestroyBroadcastAnnouncement() { advertiser_if_->Unregister(GetAdvertisingSid()); }
397
EnableAnnouncement()398 void EnableAnnouncement() {
399 log::info("broadcast_id={}", GetBroadcastId());
400 // Callback is handled by OnAdvertisingEnabled() which returns the status
401 advertiser_if_->Enable(GetAdvertisingSid(), true, base::DoNothing(), 0,
402 0, /* Enable until stopped */
403 base::DoNothing());
404 }
405
CreateBig(void)406 void CreateBig(void) {
407 log::info("broadcast_id={}", GetBroadcastId());
408 /* TODO: Figure out how to decide on the currently hard-codded params. */
409 struct bluetooth::hci::iso_manager::big_create_params big_params = {
410 .adv_handle = GetAdvertisingSid(),
411 .num_bis = sm_config_.config.GetNumBisTotal(),
412 .sdu_itv = sm_config_.config.GetSduIntervalUs(),
413 .max_sdu_size = sm_config_.config.GetMaxSduOctets(),
414 .max_transport_latency = sm_config_.config.qos.getMaxTransportLatency(),
415 .rtn = sm_config_.config.qos.getRetransmissionNumber(),
416 .phy = sm_config_.streaming_phy,
417 .packing = 0x00, /* Sequencial */
418 .framing = 0x00, /* Unframed */
419 .enc = static_cast<uint8_t>(sm_config_.broadcast_code ? 1 : 0),
420 .enc_code = sm_config_.broadcast_code ? *sm_config_.broadcast_code
421 : std::array<uint8_t, 16>({0}),
422 };
423
424 IsoManager::GetInstance()->CreateBig(GetAdvertisingSid(), std::move(big_params));
425 }
426
DisableAnnouncement(void)427 void DisableAnnouncement(void) {
428 log::info("broadcast_id={}", GetBroadcastId());
429 // Callback is handled by OnAdvertisingEnabled() which returns the status
430 advertiser_if_->Enable(GetAdvertisingSid(), false, base::DoNothing(), 0, 0, base::DoNothing());
431 }
432
TerminateBig()433 void TerminateBig() {
434 log::info("disabling={}", GetState() == BroadcastStateMachine::State::DISABLING);
435 /* Terminate with reason: Remote User Terminated Connection */
436 IsoManager::GetInstance()->TerminateBig(GetAdvertisingSid(), 0x13);
437 }
438
OnSetupIsoDataPath(uint8_t status,uint16_t conn_hdl)439 void OnSetupIsoDataPath(uint8_t status, uint16_t conn_hdl) override {
440 log::assert_that(active_config_ != std::nullopt,
441 "assert failed: active_config_ != std::nullopt");
442
443 if (status != 0) {
444 log::error("Failure creating data path. Tearing down the BIG now.");
445 SetState(State::DISABLING);
446 TerminateBig();
447 return;
448 }
449
450 /* Look for the next BIS handle */
451 auto handle_it = std::find_if(active_config_->connection_handles.begin(),
452 active_config_->connection_handles.end(),
453 [conn_hdl](const auto& handle) { return conn_hdl == handle; });
454 log::assert_that(handle_it != active_config_->connection_handles.end(),
455 "assert failed: handle_it != active_config_->connection_handles.end()");
456 handle_it = std::next(handle_it);
457
458 if (handle_it == active_config_->connection_handles.end()) {
459 /* It was the last BIS to set up - change state to streaming */
460 SetState(State::STREAMING);
461 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState(), nullptr);
462 } else {
463 /* Note: We would feed a watchdog here if we had one */
464 /* There are more BISes to set up data path for */
465 log::info("There is more data paths to set up.");
466 TriggerIsoDatapathSetup(*handle_it);
467 }
468 }
469
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle)470 void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle) override {
471 log::assert_that(active_config_ != std::nullopt,
472 "assert failed: active_config_ != std::nullopt");
473
474 if (status != 0) {
475 log::error("Failure removing data path. Tearing down the BIG now.");
476 TerminateBig();
477 return;
478 }
479
480 /* Look for the next BIS handle */
481 auto handle_it = std::find_if(
482 active_config_->connection_handles.begin(), active_config_->connection_handles.end(),
483 [conn_handle](const auto& handle) { return conn_handle == handle; });
484 log::assert_that(handle_it != active_config_->connection_handles.end(),
485 "assert failed: handle_it != active_config_->connection_handles.end()");
486 handle_it = std::next(handle_it);
487
488 if (handle_it == active_config_->connection_handles.end()) {
489 /* It was the last one to set up - start tearing down the BIG */
490 TerminateBig();
491 } else {
492 /* Note: We would feed a watchdog here if we had one */
493 /* There are more BISes to tear down data path for */
494 log::info("There is more data paths to tear down.");
495 TriggerIsoDatapathTeardown(*handle_it);
496 }
497 }
498
TriggerIsoDatapathSetup(uint16_t conn_handle)499 void TriggerIsoDatapathSetup(uint16_t conn_handle) {
500 log::info("conn_hdl={}", conn_handle);
501 log::assert_that(active_config_ != std::nullopt,
502 "assert failed: active_config_ != std::nullopt");
503
504 /* Note: If coding format is transparent, 'codec_id_company' and
505 * 'codec_id_vendor' shall be ignored.
506 */
507 auto& iso_datapath_config = sm_config_.config.data_path.isoDataPathConfig;
508 bluetooth::hci::iso_manager::iso_data_path_params param = {
509 .data_path_dir = bluetooth::hci::iso_manager::kIsoDataPathDirectionIn,
510 .data_path_id = static_cast<uint8_t>(sm_config_.config.data_path.dataPathId),
511 .codec_id_format = static_cast<uint8_t>(
512 iso_datapath_config.isTransparent ? bluetooth::hci::kIsoCodingFormatTransparent
513 : iso_datapath_config.codecId.coding_format),
514 .codec_id_company =
515 static_cast<uint16_t>(iso_datapath_config.isTransparent
516 ? 0x0000
517 : iso_datapath_config.codecId.vendor_company_id),
518 .codec_id_vendor =
519 static_cast<uint16_t>(iso_datapath_config.isTransparent
520 ? 0x0000
521 : iso_datapath_config.codecId.vendor_codec_id),
522 .controller_delay = iso_datapath_config.controllerDelayUs,
523 .codec_conf = iso_datapath_config.configuration,
524 };
525 IsoManager::GetInstance()->SetupIsoDataPath(conn_handle, std::move(param));
526 }
527
TriggerIsoDatapathTeardown(uint16_t conn_handle)528 void TriggerIsoDatapathTeardown(uint16_t conn_handle) {
529 log::info("conn_hdl={}", conn_handle);
530 log::assert_that(active_config_ != std::nullopt,
531 "assert failed: active_config_ != std::nullopt");
532
533 SetMuted(true);
534 IsoManager::GetInstance()->RemoveIsoDataPath(
535 conn_handle, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput);
536 }
537
HandleHciEvent(uint16_t event,void * data)538 void HandleHciEvent(uint16_t event, void* data) override {
539 switch (event) {
540 case HCI_BLE_CREATE_BIG_CPL_EVT: {
541 auto* evt = static_cast<big_create_cmpl_evt*>(data);
542
543 if (evt->big_id != GetAdvertisingSid()) {
544 log::error("State={}, Event={}, Unknown big, big_id={}", ToString(GetState()), event,
545 evt->big_id);
546 break;
547 }
548
549 if (evt->status == 0x00) {
550 log::info("BIG create BIG complete, big_id={}", evt->big_id);
551 active_config_ = {
552 .status = evt->status,
553 .big_id = evt->big_id,
554 .big_sync_delay = evt->big_sync_delay,
555 .transport_latency_big = evt->transport_latency_big,
556 .phy = evt->phy,
557 .nse = evt->nse,
558 .bn = evt->bn,
559 .pto = evt->pto,
560 .irc = evt->irc,
561 .max_pdu = evt->max_pdu,
562 .iso_interval = evt->iso_interval,
563 .connection_handles = evt->conn_handles,
564 };
565
566 if (GetState() == BroadcastStateMachine::State::DISABLING) {
567 log::info("Terminating BIG due to stream suspending, big_id={}", evt->big_id);
568 TerminateBig();
569 } else {
570 callbacks_->OnBigCreated(evt->conn_handles);
571 TriggerIsoDatapathSetup(evt->conn_handles[0]);
572 }
573 } else {
574 log::error("State={} Event={}. Unable to create big, big_id={}, status={}",
575 ToString(GetState()), event, evt->big_id, evt->status);
576 }
577 } break;
578 case HCI_BLE_TERM_BIG_CPL_EVT: {
579 auto* evt = static_cast<big_terminate_cmpl_evt*>(data);
580
581 log::info("BIG terminate BIG cmpl, reason={} big_id={}", evt->reason, evt->big_id);
582
583 if (evt->big_id != GetAdvertisingSid()) {
584 log::error("State={} Event={}, unknown adv.sid={}", ToString(GetState()), event,
585 evt->big_id);
586 break;
587 }
588
589 active_config_ = std::nullopt;
590 bool disabling = GetState() == BroadcastStateMachine::State::DISABLING;
591
592 /* Go back to configured if BIG is inactive (we are still announcing) */
593 SetState(State::CONFIGURED);
594
595 /* Check if we got this HCI event due to STOP or SUSPEND message. */
596 if (disabling) {
597 callbacks_->OnStateMachineEvent(GetBroadcastId(), GetState(), evt);
598 } else {
599 DisableAnnouncement();
600 }
601 } break;
602 default:
603 log::error("State={} Unknown event={}", ToString(GetState()), event);
604 break;
605 }
606 }
607 };
608
609 IBroadcastStateMachineCallbacks* BroadcastStateMachineImpl::callbacks_ = nullptr;
610 ::BleAdvertiserInterface* BroadcastStateMachineImpl::advertiser_if_ = nullptr;
611 } /* namespace */
612
CreateInstance(BroadcastStateMachineConfig msg)613 std::unique_ptr<BroadcastStateMachine> BroadcastStateMachine::CreateInstance(
614 BroadcastStateMachineConfig msg) {
615 return std::make_unique<BroadcastStateMachineImpl>(std::move(msg));
616 }
617
Initialize(IBroadcastStateMachineCallbacks * callbacks,AdvertisingCallbacks * adv_callbacks)618 void BroadcastStateMachine::Initialize(IBroadcastStateMachineCallbacks* callbacks,
619 AdvertisingCallbacks* adv_callbacks) {
620 BroadcastStateMachineImpl::callbacks_ = callbacks;
621 /* Get gd le advertiser interface */
622 BroadcastStateMachineImpl::advertiser_if_ = bluetooth::shim::get_ble_advertiser_instance();
623 if (BroadcastStateMachineImpl::advertiser_if_ != nullptr) {
624 log::info("Advertiser_instance acquired");
625 BroadcastStateMachineImpl::advertiser_if_->RegisterCallbacksNative(adv_callbacks,
626 kAdvertiserClientIdLeAudio);
627 } else {
628 log::error("Could not acquire advertiser_instance!");
629 BroadcastStateMachineImpl::advertiser_if_ = nullptr;
630 }
631 }
632
633 namespace bluetooth::le_audio {
634 namespace broadcaster {
635
operator <<(std::ostream & os,const BroadcastStateMachine::Message & msg)636 std::ostream& operator<<(std::ostream& os, const BroadcastStateMachine::Message& msg) {
637 static const char* char_value_[BroadcastStateMachine::MESSAGE_COUNT] = {"START", "SUSPEND",
638 "STOP"};
639 os << char_value_[static_cast<uint8_t>(msg)];
640 return os;
641 }
642
operator <<(std::ostream & os,const BroadcastStateMachine::State & state)643 std::ostream& operator<<(std::ostream& os, const BroadcastStateMachine::State& state) {
644 static const char* char_value_[BroadcastStateMachine::STATE_COUNT] = {
645 "STOPPED", "CONFIGURING", "CONFIGURED", "ENABLING", "DISABLING", "STOPPING", "STREAMING"};
646 os << char_value_[static_cast<uint8_t>(state)];
647 return os;
648 }
649
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BigConfig & config)650 std::ostream& operator<<(std::ostream& os,
651 const bluetooth::le_audio::broadcaster::BigConfig& config) {
652 os << "\n";
653 os << " Status: 0x" << std::hex << +config.status << std::dec << "\n";
654 os << " BIG ID: " << +config.big_id << "\n";
655 os << " Sync delay: " << config.big_sync_delay << "\n";
656 os << " Transport Latency: " << config.transport_latency_big << "\n";
657 os << " Phy: " << +config.phy << "\n";
658 os << " Nse: " << +config.nse << "\n";
659 os << " Bn: " << +config.bn << "\n";
660 os << " Pto: " << +config.pto << "\n";
661 os << " Irc: " << +config.irc << "\n";
662 os << " Max pdu: " << config.max_pdu << "\n";
663 os << " Iso interval: " << config.iso_interval << "\n";
664 os << " Connection handles (BISes): [";
665 for (auto& el : config.connection_handles) {
666 os << std::hex << +el << std::dec << ":";
667 }
668 os << "]";
669 return os;
670 }
671
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig & config)672 std::ostream& operator<<(
673 std::ostream& os,
674 const bluetooth::le_audio::broadcaster::BroadcastStateMachineConfig& config) {
675 const char* const PHYS[] = {"NONE", "1M", "2M", "CODED"};
676
677 os << "\n";
678 os << " Broadcast ID: " << config.broadcast_id << "\n";
679 os << " Streaming PHY: "
680 << ((config.streaming_phy > 3) ? std::to_string(config.streaming_phy)
681 : PHYS[config.streaming_phy])
682 << "\n";
683 os << " Subgroups: {\n";
684 for (auto const& subgroup : config.config.subgroups) {
685 os << " " << subgroup << "\n";
686 }
687 os << " }\n";
688 os << " Qos Config: " << config.config.qos << "\n";
689 if (config.broadcast_code) {
690 os << " Broadcast Code: [";
691 for (auto& el : *config.broadcast_code) {
692 os << std::hex << +el << ":";
693 }
694 os << "]\n";
695 } else {
696 os << " Broadcast Code: NONE\n";
697 }
698
699 std::vector<uint8_t> an_raw;
700 ToRawPacket(config.announcement, an_raw);
701 os << " Announcement RAW: [";
702 for (auto& el : an_raw) {
703 os << std::hex << +el << ":";
704 }
705 os << "]";
706
707 return os;
708 }
709
operator <<(std::ostream & os,const bluetooth::le_audio::broadcaster::BroadcastStateMachine & machine)710 std::ostream& operator<<(std::ostream& os,
711 const bluetooth::le_audio::broadcaster::BroadcastStateMachine& machine) {
712 os << " Broadcast state machine: {"
713 << " Advertising SID: " << +machine.GetAdvertisingSid() << "\n"
714 << " State: " << machine.GetState() << "\n";
715 os << " State Machine Config: " << machine.GetStateMachineConfig() << "\n";
716
717 if (machine.GetBigConfig()) {
718 os << " BigConfig: " << *machine.GetBigConfig() << "\n";
719 } else {
720 os << " BigConfig: NONE\n";
721 }
722 os << " }\n";
723 return os;
724 }
725
726 } // namespace broadcaster
727 } // namespace bluetooth::le_audio
728