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