• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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