Loading system/stack/btm/btm_iso.cc +14 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "btm_iso_impl.h" #include "btu.h" using bluetooth::hci::iso_manager::BigCallbacks; using bluetooth::hci::iso_manager::CigCallbacks; using bluetooth::hci::iso_manager::iso_impl; Loading Loading @@ -52,6 +53,10 @@ void IsoManager::RegisterCigCallbacks(CigCallbacks* callbacks) const { pimpl_->iso_impl_->handle_register_cis_callbacks(callbacks); } void IsoManager::RegisterBigCallbacks(BigCallbacks* callbacks) const { pimpl_->iso_impl_->handle_register_big_callbacks(callbacks); } void IsoManager::CreateCig(uint8_t cig_id, struct iso_manager::cig_create_params cig_params) { pimpl_->iso_impl_->create_cig(cig_id, std::move(cig_params)); Loading Loading @@ -89,6 +94,15 @@ void IsoManager::SendIsoData(uint16_t iso_handle, const uint8_t* data, pimpl_->iso_impl_->send_iso_data(iso_handle, data, data_len); } void IsoManager::CreateBig(uint8_t big_id, struct iso_manager::big_create_params big_params) { pimpl_->iso_impl_->create_big(big_id, std::move(big_params)); } void IsoManager::TerminateBig(uint8_t big_id, uint8_t reason) { pimpl_->iso_impl_->terminate_big(big_id, reason); } void IsoManager::HandleIsoData(void* p_msg) { if (pimpl_->IsRunning()) pimpl_->iso_impl_->handle_iso_data(static_cast<BT_HDR*>(p_msg)); Loading system/stack/btm/btm_iso_impl.h +142 −14 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ static constexpr uint8_t kIsoHeaderWithoutTsLen = 8; static constexpr uint8_t kStateFlagsNone = 0x00; static constexpr uint8_t kStateFlagIsConnected = 0x01; static constexpr uint8_t kStateFlagHasDataPathSet = 0x02; static constexpr uint8_t kStateFlagIsBroadcast = 0x04; struct iso_sync_info { uint32_t first_sync_ts; Loading @@ -48,7 +49,10 @@ struct iso_sync_info { }; struct iso_base { union { uint8_t cig_id; uint8_t big_handle; }; struct iso_sync_info sync_info; uint8_t state_flags; Loading @@ -56,6 +60,7 @@ struct iso_base { }; typedef iso_base iso_cis; typedef iso_base iso_bis; struct iso_impl { iso_impl() { Loading @@ -70,6 +75,11 @@ struct iso_impl { cig_callbacks_ = callbacks; } void handle_register_big_callbacks(BigCallbacks* callbacks) { LOG_ASSERT(callbacks != nullptr) << "Invalid BIG callbacks"; big_callbacks_ = callbacks; } void on_set_cig_params(uint8_t cig_id, uint32_t sdu_itv_mtos, uint8_t* stream, uint16_t len) { uint8_t cis_cnt; Loading Loading @@ -226,10 +236,14 @@ struct iso_impl { LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle; if (status == HCI_SUCCESS) iso->state_flags |= kStateFlagHasDataPathSet; if (iso->state_flags & kStateFlagIsBroadcast) { LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; big_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->big_handle); } else { LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; cig_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->cig_id); } } void setup_iso_data_path( uint16_t conn_handle, Loading @@ -237,8 +251,10 @@ struct iso_impl { iso_base* iso = GetIsoIfKnown(conn_handle); LOG_ASSERT(iso != nullptr) << "No such iso connection: " << +conn_handle; if (!(iso->state_flags & kStateFlagIsBroadcast)) { LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) << "CIS not established"; } btsnd_hcic_setup_iso_data_path( conn_handle, path_params.data_path_dir, path_params.data_path_id, Loading @@ -261,9 +277,14 @@ struct iso_impl { if (status == HCI_SUCCESS) iso->state_flags &= ~kStateFlagHasDataPathSet; if (iso->state_flags & kStateFlagIsBroadcast) { LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; big_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->big_handle); } else { LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; cig_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->cig_id); } } void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) { iso_base* iso = GetIsoIfKnown(iso_handle); Loading Loading @@ -314,8 +335,10 @@ struct iso_impl { LOG_ASSERT(iso != nullptr) << "No such iso connection handle: " << +iso_handle; if (!(iso->state_flags & kStateFlagIsBroadcast)) { LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) << "CIS not established"; } LOG_ASSERT(iso->state_flags & kStateFlagHasDataPathSet) << "Data path not set for handle: " << +iso_handle; Loading Loading @@ -411,23 +434,109 @@ struct iso_impl { STREAM_TO_UINT16(handle, p); STREAM_TO_UINT16(num_sent, p); if (conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) && (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end())) continue; iso_credits_ += num_sent; } } void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_create_cmpl_evt evt; LOG_ASSERT(len >= 18) << "Invalid packet length"; LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; STREAM_TO_UINT8(evt.status, data); STREAM_TO_UINT8(evt.big_id, data); STREAM_TO_UINT24(evt.big_sync_delay, data); STREAM_TO_UINT24(evt.transport_latency_big, data); STREAM_TO_UINT8(evt.phy, data); STREAM_TO_UINT8(evt.nse, data); STREAM_TO_UINT8(evt.bn, data); STREAM_TO_UINT8(evt.pto, data); STREAM_TO_UINT8(evt.irc, data); STREAM_TO_UINT16(evt.max_pdu, data); STREAM_TO_UINT16(evt.iso_interval, data); uint8_t num_bis; STREAM_TO_UINT8(num_bis, data); LOG_ASSERT(num_bis != 0) << "Invalid bis count"; LOG_ASSERT(len == (18 + num_bis * sizeof(uint16_t))) << "Invalid packet length"; uint32_t ts = bluetooth::common::time_get_os_boottime_us(); for (auto i = 0; i < num_bis; ++i) { uint16_t conn_handle; STREAM_TO_UINT16(conn_handle, data); evt.conn_handles.push_back(conn_handle); LOG_INFO(" received BIS conn_hdl %d", +conn_handle); if (evt.status == HCI_SUCCESS) { conn_hdl_to_bis_map_[conn_handle] = std::unique_ptr<iso_bis>( new iso_bis({.sync_info = {.first_sync_ts = ts, .seq_nb = 0}, .big_handle = evt.big_id, .state_flags = kStateFlagIsBroadcast, .sdu_itv = last_big_create_req_sdu_itv_})); } } big_callbacks_->OnBigEvent(kIsoEventBigOnCreateCmpl, &evt); } void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_terminate_cmpl_evt evt; LOG_ASSERT(len == 2) << "Invalid packet length"; LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; STREAM_TO_UINT8(evt.big_id, data); STREAM_TO_UINT8(evt.reason, data); bool is_known_handle = false; auto bis_it = conn_hdl_to_bis_map_.cbegin(); while (bis_it != conn_hdl_to_bis_map_.cend()) { if (bis_it->second->big_handle == evt.big_id) { bis_it = conn_hdl_to_bis_map_.erase(bis_it); is_known_handle = true; } else { ++bis_it; } } LOG_ASSERT(is_known_handle) << "No such big"; big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt); } void create_big(uint8_t big_id, struct big_create_params big_params) { LOG_ASSERT(!IsBigKnown(big_id)) << "Invalid big - already exists"; last_big_create_req_sdu_itv_ = big_params.sdu_itv; btsnd_hcic_create_big( big_id, big_params.adv_handle, big_params.num_bis, big_params.sdu_itv, big_params.max_sdu_size, big_params.max_transport_latency, big_params.rtn, big_params.phy, big_params.packing, big_params.framing, big_params.enc, big_params.enc_code); } void terminate_big(uint8_t big_id, uint8_t reason) { LOG_ASSERT(IsBigKnown(big_id)) << "No such big"; btsnd_hcic_term_big(big_id, reason); } void on_iso_event(uint8_t code, uint8_t* packet, uint16_t packet_len) { switch (code) { case HCI_BLE_CIS_EST_EVT: process_cis_est_pkt(packet_len, packet); break; case HCI_BLE_CREATE_BIG_CPL_EVT: /* TODO: Implement */ process_create_big_cmpl_pkt(packet_len, packet); break; case HCI_BLE_TERM_BIG_CPL_EVT: /* TODO: Implement */ process_terminate_big_cmpl_pkt(packet_len, packet); break; case HCI_BLE_CIS_REQ_EVT: /* Not supported */ Loading Loading @@ -503,8 +612,15 @@ struct iso_impl { : nullptr; } iso_bis* GetBisIfKnown(uint16_t bis_conn_handle) { auto bis_it = conn_hdl_to_bis_map_.find(bis_conn_handle); return (bis_it != conn_hdl_to_bis_map_.end()) ? bis_it->second.get() : nullptr; } iso_base* GetIsoIfKnown(uint16_t iso_handle) { return GetCisIfKnown(iso_handle); struct iso_base* iso = GetCisIfKnown(iso_handle); return (iso != nullptr) ? iso : GetBisIfKnown(iso_handle); } bool IsCigKnown(uint8_t cig_id) const { Loading @@ -516,12 +632,24 @@ struct iso_impl { return (cis_it != conn_hdl_to_cis_map_.cend()); } bool IsBigKnown(uint8_t big_id) const { auto bis_it = std::find_if(conn_hdl_to_bis_map_.cbegin(), conn_hdl_to_bis_map_.cend(), [&big_id](auto& kv_pair) { return (kv_pair.second->big_handle == big_id); }); return (bis_it != conn_hdl_to_bis_map_.cend()); } std::map<uint16_t, std::unique_ptr<iso_cis>> conn_hdl_to_cis_map_; std::map<uint16_t, std::unique_ptr<iso_bis>> conn_hdl_to_bis_map_; uint16_t iso_credits_; uint16_t iso_buffer_size_; uint32_t last_big_create_req_sdu_itv_; CigCallbacks* cig_callbacks_ = nullptr; BigCallbacks* big_callbacks_ = nullptr; }; } // namespace iso_manager Loading system/stack/include/btm_iso_api.h +40 −4 Original line number Diff line number Diff line Loading @@ -36,6 +36,16 @@ struct CigCallbacks { virtual void OnCisEvent(uint8_t event, void* data) = 0; virtual void OnCigEvent(uint8_t event, void* data) = 0; }; struct BigCallbacks { virtual ~BigCallbacks() = default; virtual void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t big_id) = 0; virtual void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t big_id) = 0; virtual void OnBigEvent(uint8_t event, void* data) = 0; }; } // namespace iso_manager class IsoManager { Loading @@ -57,6 +67,15 @@ class IsoManager { */ virtual void RegisterCigCallbacks(iso_manager::CigCallbacks* callbacks) const; /** * Set BIG related callbacks * * <p> Shall be set by the Le Audio Broadcaster implementation * * @param callbacks BigCallbacks implementation */ virtual void RegisterBigCallbacks(iso_manager::BigCallbacks* callbacks) const; /** * Creates connected isochronous group (CIG) according to given params. * Loading Loading @@ -102,7 +121,7 @@ class IsoManager { * Initiates creation of isochronous data path for connected isochronous * stream. * * @param conn_handle handle of CIS connection * @param conn_handle handle of BIS or CIS connection * @param path_params iso data path parameters */ virtual void SetupIsoDataPath( Loading @@ -113,7 +132,7 @@ class IsoManager { * Initiates removement of isochronous data path for connected isochronous * stream. * * @param conn_handle handle of CIS connection * @param conn_handle handle of BIS or CIS connection * @param data_path_dir iso data path direction */ virtual void RemoveIsoDataPath(uint16_t conn_handle, uint8_t data_path_dir); Loading @@ -121,13 +140,30 @@ class IsoManager { /** * Sends iso data to the controller * * @param conn_handle handle of CIS connection * @param conn_handle handle of BIS or CIS connection * @param data data buffer. The ownership of data is not being transferred. * @param data_len data buffer length */ virtual void SendIsoData(uint16_t conn_handle, const uint8_t* data, uint16_t data_len); /** * Creates the Broadcast Isochronous Group * * @param big_id host assigned BIG identifier * @param big_params BIG parameters */ virtual void CreateBig(uint8_t big_id, struct iso_manager::big_create_params big_params); /** * Terminates the Broadcast Isochronous Group * * @param big_id host assigned BIG identifier * @param reason termination reason data */ virtual void TerminateBig(uint8_t big_id, uint8_t reason); /* Below are defined handlers called by the legacy code in btu_hcif.cc */ /** Loading Loading @@ -159,7 +195,7 @@ class IsoManager { virtual void HandleNumComplDataPkts(uint8_t* p, uint8_t evt_len); /** * Handle CIS related HCI events * Handle CIS and BIG related HCI events * * @param sub_code ble subcode for the HCI event * @param params raw packet buffer for the event. The ownership of params is Loading system/stack/include/btm_iso_api_types.h +37 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,9 @@ constexpr uint8_t kIsoEventCigOnCreateCmpl = 0x00; constexpr uint8_t kIsoEventCigOnReconfigureCmpl = 0x01; constexpr uint8_t kIsoEventCigOnRemoveCmpl = 0x02; constexpr uint8_t kIsoEventBigOnCreateCmpl = 0x00; constexpr uint8_t kIsoEventBigOnTerminateCmpl = 0x01; struct cig_create_params { uint32_t sdu_itv_mtos; uint32_t sdu_itv_stom; Loading Loading @@ -107,6 +110,40 @@ struct cis_disconnected_evt { uint16_t cis_conn_hdl; }; struct big_create_params { uint8_t adv_handle; uint8_t num_bis; uint32_t sdu_itv; uint16_t max_sdu_size; uint16_t max_transport_latency; uint8_t rtn; uint8_t phy; uint8_t packing; uint8_t framing; uint8_t enc; std::array<uint8_t, 16> enc_code; }; struct big_create_cmpl_evt { uint8_t status; uint8_t big_id; uint32_t big_sync_delay; uint32_t transport_latency_big; uint8_t phy; uint8_t nse; uint8_t bn; uint8_t pto; uint8_t irc; uint16_t max_pdu; uint16_t iso_interval; std::vector<uint16_t> conn_handles; }; struct big_terminate_cmpl_evt { uint8_t big_id; uint8_t reason; }; struct iso_data_path_params { uint8_t data_path_dir; uint8_t data_path_id; Loading system/stack/test/btm_iso_test.cc +631 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
system/stack/btm/btm_iso.cc +14 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "btm_iso_impl.h" #include "btu.h" using bluetooth::hci::iso_manager::BigCallbacks; using bluetooth::hci::iso_manager::CigCallbacks; using bluetooth::hci::iso_manager::iso_impl; Loading Loading @@ -52,6 +53,10 @@ void IsoManager::RegisterCigCallbacks(CigCallbacks* callbacks) const { pimpl_->iso_impl_->handle_register_cis_callbacks(callbacks); } void IsoManager::RegisterBigCallbacks(BigCallbacks* callbacks) const { pimpl_->iso_impl_->handle_register_big_callbacks(callbacks); } void IsoManager::CreateCig(uint8_t cig_id, struct iso_manager::cig_create_params cig_params) { pimpl_->iso_impl_->create_cig(cig_id, std::move(cig_params)); Loading Loading @@ -89,6 +94,15 @@ void IsoManager::SendIsoData(uint16_t iso_handle, const uint8_t* data, pimpl_->iso_impl_->send_iso_data(iso_handle, data, data_len); } void IsoManager::CreateBig(uint8_t big_id, struct iso_manager::big_create_params big_params) { pimpl_->iso_impl_->create_big(big_id, std::move(big_params)); } void IsoManager::TerminateBig(uint8_t big_id, uint8_t reason) { pimpl_->iso_impl_->terminate_big(big_id, reason); } void IsoManager::HandleIsoData(void* p_msg) { if (pimpl_->IsRunning()) pimpl_->iso_impl_->handle_iso_data(static_cast<BT_HDR*>(p_msg)); Loading
system/stack/btm/btm_iso_impl.h +142 −14 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ static constexpr uint8_t kIsoHeaderWithoutTsLen = 8; static constexpr uint8_t kStateFlagsNone = 0x00; static constexpr uint8_t kStateFlagIsConnected = 0x01; static constexpr uint8_t kStateFlagHasDataPathSet = 0x02; static constexpr uint8_t kStateFlagIsBroadcast = 0x04; struct iso_sync_info { uint32_t first_sync_ts; Loading @@ -48,7 +49,10 @@ struct iso_sync_info { }; struct iso_base { union { uint8_t cig_id; uint8_t big_handle; }; struct iso_sync_info sync_info; uint8_t state_flags; Loading @@ -56,6 +60,7 @@ struct iso_base { }; typedef iso_base iso_cis; typedef iso_base iso_bis; struct iso_impl { iso_impl() { Loading @@ -70,6 +75,11 @@ struct iso_impl { cig_callbacks_ = callbacks; } void handle_register_big_callbacks(BigCallbacks* callbacks) { LOG_ASSERT(callbacks != nullptr) << "Invalid BIG callbacks"; big_callbacks_ = callbacks; } void on_set_cig_params(uint8_t cig_id, uint32_t sdu_itv_mtos, uint8_t* stream, uint16_t len) { uint8_t cis_cnt; Loading Loading @@ -226,10 +236,14 @@ struct iso_impl { LOG_ASSERT(iso != nullptr) << "Invalid connection handle: " << +conn_handle; if (status == HCI_SUCCESS) iso->state_flags |= kStateFlagHasDataPathSet; if (iso->state_flags & kStateFlagIsBroadcast) { LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; big_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->big_handle); } else { LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; cig_callbacks_->OnSetupIsoDataPath(status, conn_handle, iso->cig_id); } } void setup_iso_data_path( uint16_t conn_handle, Loading @@ -237,8 +251,10 @@ struct iso_impl { iso_base* iso = GetIsoIfKnown(conn_handle); LOG_ASSERT(iso != nullptr) << "No such iso connection: " << +conn_handle; if (!(iso->state_flags & kStateFlagIsBroadcast)) { LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) << "CIS not established"; } btsnd_hcic_setup_iso_data_path( conn_handle, path_params.data_path_dir, path_params.data_path_id, Loading @@ -261,9 +277,14 @@ struct iso_impl { if (status == HCI_SUCCESS) iso->state_flags &= ~kStateFlagHasDataPathSet; if (iso->state_flags & kStateFlagIsBroadcast) { LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; big_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->big_handle); } else { LOG_ASSERT(cig_callbacks_ != nullptr) << "Invalid CIG callbacks"; cig_callbacks_->OnRemoveIsoDataPath(status, conn_handle, iso->cig_id); } } void remove_iso_data_path(uint16_t iso_handle, uint8_t data_path_dir) { iso_base* iso = GetIsoIfKnown(iso_handle); Loading Loading @@ -314,8 +335,10 @@ struct iso_impl { LOG_ASSERT(iso != nullptr) << "No such iso connection handle: " << +iso_handle; if (!(iso->state_flags & kStateFlagIsBroadcast)) { LOG_ASSERT(iso->state_flags & kStateFlagIsConnected) << "CIS not established"; } LOG_ASSERT(iso->state_flags & kStateFlagHasDataPathSet) << "Data path not set for handle: " << +iso_handle; Loading Loading @@ -411,23 +434,109 @@ struct iso_impl { STREAM_TO_UINT16(handle, p); STREAM_TO_UINT16(num_sent, p); if (conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) if ((conn_hdl_to_cis_map_.find(handle) == conn_hdl_to_cis_map_.end()) && (conn_hdl_to_bis_map_.find(handle) == conn_hdl_to_bis_map_.end())) continue; iso_credits_ += num_sent; } } void process_create_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_create_cmpl_evt evt; LOG_ASSERT(len >= 18) << "Invalid packet length"; LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; STREAM_TO_UINT8(evt.status, data); STREAM_TO_UINT8(evt.big_id, data); STREAM_TO_UINT24(evt.big_sync_delay, data); STREAM_TO_UINT24(evt.transport_latency_big, data); STREAM_TO_UINT8(evt.phy, data); STREAM_TO_UINT8(evt.nse, data); STREAM_TO_UINT8(evt.bn, data); STREAM_TO_UINT8(evt.pto, data); STREAM_TO_UINT8(evt.irc, data); STREAM_TO_UINT16(evt.max_pdu, data); STREAM_TO_UINT16(evt.iso_interval, data); uint8_t num_bis; STREAM_TO_UINT8(num_bis, data); LOG_ASSERT(num_bis != 0) << "Invalid bis count"; LOG_ASSERT(len == (18 + num_bis * sizeof(uint16_t))) << "Invalid packet length"; uint32_t ts = bluetooth::common::time_get_os_boottime_us(); for (auto i = 0; i < num_bis; ++i) { uint16_t conn_handle; STREAM_TO_UINT16(conn_handle, data); evt.conn_handles.push_back(conn_handle); LOG_INFO(" received BIS conn_hdl %d", +conn_handle); if (evt.status == HCI_SUCCESS) { conn_hdl_to_bis_map_[conn_handle] = std::unique_ptr<iso_bis>( new iso_bis({.sync_info = {.first_sync_ts = ts, .seq_nb = 0}, .big_handle = evt.big_id, .state_flags = kStateFlagIsBroadcast, .sdu_itv = last_big_create_req_sdu_itv_})); } } big_callbacks_->OnBigEvent(kIsoEventBigOnCreateCmpl, &evt); } void process_terminate_big_cmpl_pkt(uint8_t len, uint8_t* data) { struct big_terminate_cmpl_evt evt; LOG_ASSERT(len == 2) << "Invalid packet length"; LOG_ASSERT(big_callbacks_ != nullptr) << "Invalid BIG callbacks"; STREAM_TO_UINT8(evt.big_id, data); STREAM_TO_UINT8(evt.reason, data); bool is_known_handle = false; auto bis_it = conn_hdl_to_bis_map_.cbegin(); while (bis_it != conn_hdl_to_bis_map_.cend()) { if (bis_it->second->big_handle == evt.big_id) { bis_it = conn_hdl_to_bis_map_.erase(bis_it); is_known_handle = true; } else { ++bis_it; } } LOG_ASSERT(is_known_handle) << "No such big"; big_callbacks_->OnBigEvent(kIsoEventBigOnTerminateCmpl, &evt); } void create_big(uint8_t big_id, struct big_create_params big_params) { LOG_ASSERT(!IsBigKnown(big_id)) << "Invalid big - already exists"; last_big_create_req_sdu_itv_ = big_params.sdu_itv; btsnd_hcic_create_big( big_id, big_params.adv_handle, big_params.num_bis, big_params.sdu_itv, big_params.max_sdu_size, big_params.max_transport_latency, big_params.rtn, big_params.phy, big_params.packing, big_params.framing, big_params.enc, big_params.enc_code); } void terminate_big(uint8_t big_id, uint8_t reason) { LOG_ASSERT(IsBigKnown(big_id)) << "No such big"; btsnd_hcic_term_big(big_id, reason); } void on_iso_event(uint8_t code, uint8_t* packet, uint16_t packet_len) { switch (code) { case HCI_BLE_CIS_EST_EVT: process_cis_est_pkt(packet_len, packet); break; case HCI_BLE_CREATE_BIG_CPL_EVT: /* TODO: Implement */ process_create_big_cmpl_pkt(packet_len, packet); break; case HCI_BLE_TERM_BIG_CPL_EVT: /* TODO: Implement */ process_terminate_big_cmpl_pkt(packet_len, packet); break; case HCI_BLE_CIS_REQ_EVT: /* Not supported */ Loading Loading @@ -503,8 +612,15 @@ struct iso_impl { : nullptr; } iso_bis* GetBisIfKnown(uint16_t bis_conn_handle) { auto bis_it = conn_hdl_to_bis_map_.find(bis_conn_handle); return (bis_it != conn_hdl_to_bis_map_.end()) ? bis_it->second.get() : nullptr; } iso_base* GetIsoIfKnown(uint16_t iso_handle) { return GetCisIfKnown(iso_handle); struct iso_base* iso = GetCisIfKnown(iso_handle); return (iso != nullptr) ? iso : GetBisIfKnown(iso_handle); } bool IsCigKnown(uint8_t cig_id) const { Loading @@ -516,12 +632,24 @@ struct iso_impl { return (cis_it != conn_hdl_to_cis_map_.cend()); } bool IsBigKnown(uint8_t big_id) const { auto bis_it = std::find_if(conn_hdl_to_bis_map_.cbegin(), conn_hdl_to_bis_map_.cend(), [&big_id](auto& kv_pair) { return (kv_pair.second->big_handle == big_id); }); return (bis_it != conn_hdl_to_bis_map_.cend()); } std::map<uint16_t, std::unique_ptr<iso_cis>> conn_hdl_to_cis_map_; std::map<uint16_t, std::unique_ptr<iso_bis>> conn_hdl_to_bis_map_; uint16_t iso_credits_; uint16_t iso_buffer_size_; uint32_t last_big_create_req_sdu_itv_; CigCallbacks* cig_callbacks_ = nullptr; BigCallbacks* big_callbacks_ = nullptr; }; } // namespace iso_manager Loading
system/stack/include/btm_iso_api.h +40 −4 Original line number Diff line number Diff line Loading @@ -36,6 +36,16 @@ struct CigCallbacks { virtual void OnCisEvent(uint8_t event, void* data) = 0; virtual void OnCigEvent(uint8_t event, void* data) = 0; }; struct BigCallbacks { virtual ~BigCallbacks() = default; virtual void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t big_id) = 0; virtual void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t big_id) = 0; virtual void OnBigEvent(uint8_t event, void* data) = 0; }; } // namespace iso_manager class IsoManager { Loading @@ -57,6 +67,15 @@ class IsoManager { */ virtual void RegisterCigCallbacks(iso_manager::CigCallbacks* callbacks) const; /** * Set BIG related callbacks * * <p> Shall be set by the Le Audio Broadcaster implementation * * @param callbacks BigCallbacks implementation */ virtual void RegisterBigCallbacks(iso_manager::BigCallbacks* callbacks) const; /** * Creates connected isochronous group (CIG) according to given params. * Loading Loading @@ -102,7 +121,7 @@ class IsoManager { * Initiates creation of isochronous data path for connected isochronous * stream. * * @param conn_handle handle of CIS connection * @param conn_handle handle of BIS or CIS connection * @param path_params iso data path parameters */ virtual void SetupIsoDataPath( Loading @@ -113,7 +132,7 @@ class IsoManager { * Initiates removement of isochronous data path for connected isochronous * stream. * * @param conn_handle handle of CIS connection * @param conn_handle handle of BIS or CIS connection * @param data_path_dir iso data path direction */ virtual void RemoveIsoDataPath(uint16_t conn_handle, uint8_t data_path_dir); Loading @@ -121,13 +140,30 @@ class IsoManager { /** * Sends iso data to the controller * * @param conn_handle handle of CIS connection * @param conn_handle handle of BIS or CIS connection * @param data data buffer. The ownership of data is not being transferred. * @param data_len data buffer length */ virtual void SendIsoData(uint16_t conn_handle, const uint8_t* data, uint16_t data_len); /** * Creates the Broadcast Isochronous Group * * @param big_id host assigned BIG identifier * @param big_params BIG parameters */ virtual void CreateBig(uint8_t big_id, struct iso_manager::big_create_params big_params); /** * Terminates the Broadcast Isochronous Group * * @param big_id host assigned BIG identifier * @param reason termination reason data */ virtual void TerminateBig(uint8_t big_id, uint8_t reason); /* Below are defined handlers called by the legacy code in btu_hcif.cc */ /** Loading Loading @@ -159,7 +195,7 @@ class IsoManager { virtual void HandleNumComplDataPkts(uint8_t* p, uint8_t evt_len); /** * Handle CIS related HCI events * Handle CIS and BIG related HCI events * * @param sub_code ble subcode for the HCI event * @param params raw packet buffer for the event. The ownership of params is Loading
system/stack/include/btm_iso_api_types.h +37 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,9 @@ constexpr uint8_t kIsoEventCigOnCreateCmpl = 0x00; constexpr uint8_t kIsoEventCigOnReconfigureCmpl = 0x01; constexpr uint8_t kIsoEventCigOnRemoveCmpl = 0x02; constexpr uint8_t kIsoEventBigOnCreateCmpl = 0x00; constexpr uint8_t kIsoEventBigOnTerminateCmpl = 0x01; struct cig_create_params { uint32_t sdu_itv_mtos; uint32_t sdu_itv_stom; Loading Loading @@ -107,6 +110,40 @@ struct cis_disconnected_evt { uint16_t cis_conn_hdl; }; struct big_create_params { uint8_t adv_handle; uint8_t num_bis; uint32_t sdu_itv; uint16_t max_sdu_size; uint16_t max_transport_latency; uint8_t rtn; uint8_t phy; uint8_t packing; uint8_t framing; uint8_t enc; std::array<uint8_t, 16> enc_code; }; struct big_create_cmpl_evt { uint8_t status; uint8_t big_id; uint32_t big_sync_delay; uint32_t transport_latency_big; uint8_t phy; uint8_t nse; uint8_t bn; uint8_t pto; uint8_t irc; uint16_t max_pdu; uint16_t iso_interval; std::vector<uint16_t> conn_handles; }; struct big_terminate_cmpl_evt { uint8_t big_id; uint8_t reason; }; struct iso_data_path_params { uint8_t data_path_dir; uint8_t data_path_id; Loading
system/stack/test/btm_iso_test.cc +631 −4 File changed.Preview size limit exceeded, changes collapsed. Show changes