1 /*
2  *
3  *  Copyright 2020 The Android Open Source Project
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 "iso_manager_impl.h"
19 
20 #include "common/bind.h"
21 #include "hci/hci_packets.h"
22 #include "iso/iso_manager.h"
23 #include "os/handler.h"
24 #include "os/log.h"
25 #include "packet/raw_builder.h"
26 
27 namespace bluetooth {
28 namespace iso {
29 namespace internal {
30 
31 using bluetooth::hci::IsoBuilder;
32 
IsoManagerImpl(os::Handler * iso_handler,hci::HciLayer * hci_layer,hci::Controller * controller)33 IsoManagerImpl::IsoManagerImpl(os::Handler* iso_handler, hci::HciLayer* hci_layer, hci::Controller* controller)
34     : iso_handler_(iso_handler),
35       hci_layer_(hci_layer),
36       hci_le_iso_interface_(hci_layer->GetLeIsoInterface(iso_handler_->BindOn(this, &IsoManagerImpl::OnHciLeEvent))),
37       controller_(controller) {
38   hci_layer_->GetIsoQueueEnd()->RegisterDequeue(
39       iso_handler_, common::Bind(&IsoManagerImpl::OnIncomingPacket, common::Unretained(this)));
40   iso_enqueue_buffer_ = std::make_unique<os::EnqueueBuffer<IsoBuilder>>(hci_layer_->GetIsoQueueEnd());
41 }
42 
~IsoManagerImpl()43 IsoManagerImpl::~IsoManagerImpl() {
44   hci_layer_->GetIsoQueueEnd()->UnregisterDequeue();
45   iso_enqueue_buffer_ = nullptr;
46 }
47 
OnHciLeEvent(hci::LeMetaEventView event)48 void IsoManagerImpl::OnHciLeEvent(hci::LeMetaEventView event) {
49   hci::SubeventCode code = event.GetSubeventCode();
50 
51   if (code == hci::SubeventCode::CIS_ESTABLISHED) {
52     hci::LeCisEstablishedView le_cis_established_view = hci::LeCisEstablishedView::Create(event);
53     if (!le_cis_established_view.IsValid()) {
54       LOG_ERROR("Invalid LeCisEstablishedView packet received");
55       return;
56     }
57 
58     cis_established_callback.Invoke(le_cis_established_view.GetConnectionHandle());
59     return;
60   } else if (code == hci::SubeventCode::CIS_REQUEST) {
61     hci::LeCisRequestView le_cis_request_view = hci::LeCisRequestView::Create(event);
62     if (!le_cis_request_view.IsValid()) {
63       LOG_ERROR("Invalid LeCisRequestView packet received");
64       return;
65     }
66 
67     hci_le_iso_interface_->EnqueueCommand(
68         hci::LeAcceptCisRequestBuilder::Create(le_cis_request_view.GetCisConnectionHandle()),
69         iso_handler_->BindOnce([](hci::CommandStatusView command_status) {
70           LOG_INFO("command_status=%hhu ", command_status.GetStatus());
71         }));
72 
73     return;
74   }
75 
76   LOG_ERROR("Unhandled HCI LE ISO event, code %s", hci::SubeventCodeText(code).c_str());
77   ASSERT_LOG(false, "Unhandled HCI LE ISO event");
78 }
79 
SetCigParameters(uint8_t cig_id,uint32_t sdu_interval_m_to_s,uint32_t sdu_interval_s_to_m,hci::ClockAccuracy peripherals_clock_accuracy,hci::Packing packing,hci::Enable framing,uint16_t max_transport_latency_m_to_s,uint16_t max_transport_latency_s_to_m,const std::vector<hci::CisParametersConfig> & cis_configs,SetCigParametersCallback command_complete_callback)80 void IsoManagerImpl::SetCigParameters(
81     uint8_t cig_id,
82     uint32_t sdu_interval_m_to_s,
83     uint32_t sdu_interval_s_to_m,
84     hci::ClockAccuracy peripherals_clock_accuracy,
85     hci::Packing packing,
86     hci::Enable framing,
87     uint16_t max_transport_latency_m_to_s,
88     uint16_t max_transport_latency_s_to_m,
89     const std::vector<hci::CisParametersConfig>& cis_configs,
90     SetCigParametersCallback command_complete_callback) {
91   hci_le_iso_interface_->EnqueueCommand(
92       hci::LeSetCigParametersBuilder::Create(
93           cig_id,
94           sdu_interval_m_to_s,
95           sdu_interval_s_to_m,
96           peripherals_clock_accuracy,
97           packing,
98           framing,
99           max_transport_latency_m_to_s,
100           max_transport_latency_s_to_m,
101           cis_configs),
102       iso_handler_->BindOnce(
103           &IsoManagerImpl::SetCigParametersComplete,
104           common::Unretained(this),
105           cig_id,
106           cis_configs,
107           std::move(command_complete_callback)));
108 }
109 
SetCigParametersComplete(uint8_t cig_id,const std::vector<hci::CisParametersConfig> & cis_configs,SetCigParametersCallback command_complete_callback,hci::CommandCompleteView command_complete)110 void IsoManagerImpl::SetCigParametersComplete(
111     uint8_t cig_id,
112     const std::vector<hci::CisParametersConfig>& cis_configs,
113     SetCigParametersCallback command_complete_callback,
114     hci::CommandCompleteView command_complete) {
115   ASSERT(command_complete.IsValid());
116 
117   hci::LeSetCigParametersCompleteView setCigParamsComplete =
118       hci::LeSetCigParametersCompleteView::Create(command_complete);
119   ASSERT(setCigParamsComplete.IsValid());
120 
121   if (setCigParamsComplete.GetStatus() == hci::ErrorCode::SUCCESS) {
122     uint8_t cig_id_back_from_ctrl = setCigParamsComplete.GetCigId();
123     auto conn_handles = setCigParamsComplete.GetConnectionHandle();
124 
125     ASSERT(cig_id_back_from_ctrl == cig_id);
126     ASSERT(conn_handles.size() == cis_configs.size());
127 
128     auto cis_it = cis_configs.begin();
129     auto handle_it = conn_handles.begin();
130 
131     std::vector<uint16_t> handles;
132     while (cis_it != cis_configs.end()) {
133       iso_connections_.push_back({
134           .cig_id = cig_id,
135           .cis_id = cis_it->cis_id_,
136           .connection_handle = *handle_it,
137       });
138 
139       handles.push_back(*handle_it);
140 
141       cis_it++;
142       handle_it++;
143     }
144 
145     command_complete_callback.Invoke(handles);
146   }
147 }
148 
SetCigParametersTest(uint8_t cig_id,uint32_t sdu_interval_m_to_s,uint32_t sdu_interval_s_to_m,uint8_t ft_m_to_s,uint8_t ft_s_to_m,uint16_t iso_interval,hci::ClockAccuracy peripherals_clock_accuracy,hci::Packing packing,hci::Enable framing,uint16_t max_transport_latency_m_to_s,uint16_t max_transport_latency_s_to_m,const std::vector<hci::LeCisParametersTestConfig> & cis_test_configs,SetCigParametersCallback command_complete_callback)149 void IsoManagerImpl::SetCigParametersTest(
150     uint8_t cig_id,
151     uint32_t sdu_interval_m_to_s,
152     uint32_t sdu_interval_s_to_m,
153     uint8_t ft_m_to_s,
154     uint8_t ft_s_to_m,
155     uint16_t iso_interval,
156     hci::ClockAccuracy peripherals_clock_accuracy,
157     hci::Packing packing,
158     hci::Enable framing,
159     uint16_t max_transport_latency_m_to_s,
160     uint16_t max_transport_latency_s_to_m,
161     const std::vector<hci::LeCisParametersTestConfig>& cis_test_configs,
162     SetCigParametersCallback command_complete_callback) {
163   hci_le_iso_interface_->EnqueueCommand(
164       hci::LeSetCigParametersTestBuilder::Create(
165           cig_id,
166           sdu_interval_m_to_s,
167           sdu_interval_s_to_m,
168           ft_m_to_s,
169           ft_s_to_m,
170           iso_interval,
171           peripherals_clock_accuracy,
172           packing,
173           framing,
174           cis_test_configs),
175       iso_handler_->BindOnce(
176           &IsoManagerImpl::SetCigParametersTestComplete,
177           common::Unretained(this),
178           cig_id,
179           cis_test_configs,
180           std::move(command_complete_callback)));
181 }
182 
SetCigParametersTestComplete(uint8_t cig_id,const std::vector<hci::LeCisParametersTestConfig> & cis_configs,SetCigParametersCallback command_complete_callback,hci::CommandCompleteView command_complete)183 void IsoManagerImpl::SetCigParametersTestComplete(
184     uint8_t cig_id,
185     const std::vector<hci::LeCisParametersTestConfig>& cis_configs,
186     SetCigParametersCallback command_complete_callback,
187     hci::CommandCompleteView command_complete) {
188   ASSERT(command_complete.IsValid());
189 
190   hci::LeSetCigParametersTestCompleteView setCigParamsComplete =
191       hci::LeSetCigParametersTestCompleteView::Create(command_complete);
192   ASSERT(setCigParamsComplete.IsValid());
193 
194   if (setCigParamsComplete.GetStatus() == hci::ErrorCode::SUCCESS) {
195     uint8_t cig_id_back_from_ctrl = setCigParamsComplete.GetCigId();
196     auto conn_handles = setCigParamsComplete.GetConnectionHandle();
197 
198     ASSERT(cig_id_back_from_ctrl == cig_id);
199     ASSERT(conn_handles.size() == cis_configs.size());
200 
201     auto cis_it = cis_configs.begin();
202     auto handle_it = conn_handles.begin();
203 
204     std::vector<uint16_t> handles;
205     while (cis_it != cis_configs.end()) {
206       iso_connections_.push_back({
207           .cig_id = cig_id,
208           .cis_id = cis_it->cis_id_,
209           .connection_handle = *handle_it,
210       });
211 
212       handles.push_back(*handle_it);
213 
214       cis_it++;
215       handle_it++;
216     }
217 
218     command_complete_callback.Invoke(handles);
219   }
220 }
221 
LeCreateCis(std::vector<std::pair<uint16_t,uint16_t>> cis_and_acl_handles)222 void IsoManagerImpl::LeCreateCis(std::vector<std::pair<uint16_t, uint16_t>> cis_and_acl_handles) {
223   std::vector<hci::CreateCisConfig> cis_configs;
224 
225   for (const auto& handle_pair : cis_and_acl_handles) {
226     hci::CreateCisConfig config;
227     config.cis_connection_handle_ = handle_pair.first;
228     config.acl_connection_handle_ = handle_pair.second;
229     cis_configs.push_back(config);
230   }
231 
232   hci_le_iso_interface_->EnqueueCommand(
233       hci::LeCreateCisBuilder::Create(cis_configs), iso_handler_->BindOnce([](hci::CommandStatusView command_status) {
234         LOG_INFO("command_status=%hhu ", command_status.GetStatus());
235       }));
236 }
237 
RemoveCig(uint8_t cig_id)238 void IsoManagerImpl::RemoveCig(uint8_t cig_id) {
239   ASSERT(IsKnownCig(cig_id));
240 
241   hci_le_iso_interface_->EnqueueCommand(
242       hci::LeRemoveCigBuilder::Create(cig_id),
243       iso_handler_->BindOnce(&IsoManagerImpl::RemoveCigComplete, common::Unretained(this)));
244 }
245 
RemoveCigComplete(hci::CommandCompleteView command_complete)246 void IsoManagerImpl::RemoveCigComplete(hci::CommandCompleteView command_complete) {
247   ASSERT(command_complete.IsValid());
248 
249   hci::LeRemoveCigCompleteView removeCigComplete = hci::LeRemoveCigCompleteView::Create(command_complete);
250   ASSERT(removeCigComplete.IsValid());
251 }
252 
SendIsoPacket(uint16_t cis_handle,std::vector<uint8_t> packet)253 void IsoManagerImpl::SendIsoPacket(uint16_t cis_handle, std::vector<uint8_t> packet) {
254   auto builder = hci::IsoWithoutTimestampBuilder::Create(
255       cis_handle,
256       hci::IsoPacketBoundaryFlag::COMPLETE_SDU,
257       0 /* sequence_number*/,
258       hci::IsoPacketStatusFlag::VALID,
259       std::make_unique<bluetooth::packet::RawBuilder>(packet));
260   LOG_INFO("%c%c", packet[0], packet[1]);
261   iso_enqueue_buffer_->Enqueue(std::move(builder), iso_handler_);
262 }
263 
OnIncomingPacket()264 void IsoManagerImpl::OnIncomingPacket() {
265   std::unique_ptr<hci::IsoView> packet = hci_layer_->GetIsoQueueEnd()->TryDequeue();
266   iso_data_callback.Invoke(std::move(packet));
267 }
268 
269 }  // namespace internal
270 }  // namespace iso
271 }  // namespace bluetooth
272