1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "l2cap/le/internal/signalling_manager.h"
18
19 #include <chrono>
20
21 #include "common/bind.h"
22 #include "l2cap/internal/data_pipeline_manager.h"
23 #include "l2cap/internal/dynamic_channel_impl.h"
24 #include "l2cap/internal/le_credit_based_channel_data_controller.h"
25 #include "l2cap/l2cap_packets.h"
26 #include "l2cap/le/internal/link.h"
27 #include "os/log.h"
28 #include "packet/raw_builder.h"
29
30 namespace bluetooth {
31 namespace l2cap {
32 namespace le {
33 namespace internal {
34
35 static constexpr auto kTimeout = std::chrono::seconds(3);
36
LeSignallingManager(os::Handler * handler,Link * link,l2cap::internal::DataPipelineManager * data_pipeline_manager,DynamicChannelServiceManagerImpl * dynamic_service_manager,l2cap::internal::DynamicChannelAllocator * channel_allocator)37 LeSignallingManager::LeSignallingManager(os::Handler* handler, Link* link,
38 l2cap::internal::DataPipelineManager* data_pipeline_manager,
39 DynamicChannelServiceManagerImpl* dynamic_service_manager,
40 l2cap::internal::DynamicChannelAllocator* channel_allocator)
41 : handler_(handler), link_(link), data_pipeline_manager_(data_pipeline_manager),
42 dynamic_service_manager_(dynamic_service_manager), channel_allocator_(channel_allocator), alarm_(handler) {
43 ASSERT(handler_ != nullptr);
44 ASSERT(link_ != nullptr);
45 signalling_channel_ =
46 link_->AllocateFixedChannel(kLeSignallingCid, SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK);
47 signalling_channel_->GetQueueUpEnd()->RegisterDequeue(
48 handler_, common::Bind(&LeSignallingManager::on_incoming_packet, common::Unretained(this)));
49 enqueue_buffer_ =
50 std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>(signalling_channel_->GetQueueUpEnd());
51 }
52
~LeSignallingManager()53 LeSignallingManager::~LeSignallingManager() {
54 enqueue_buffer_.reset();
55 signalling_channel_->GetQueueUpEnd()->UnregisterDequeue();
56 signalling_channel_ = nullptr;
57 }
58
SendConnectionRequest(Psm psm,Cid local_cid,Mtu mtu)59 void LeSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid, Mtu mtu) {
60 dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
61 link_->GetDevice(),
62 dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
63 handler_->BindOnceOn(this, &LeSignallingManager::on_security_result_for_outgoing, psm, local_cid, mtu));
64 }
65
on_security_result_for_outgoing(Psm psm,Cid local_cid,Mtu mtu,bool result)66 void LeSignallingManager::on_security_result_for_outgoing(Psm psm, Cid local_cid, Mtu mtu, bool result) {
67 if (!result) {
68 LOG_WARN("Security requirement can't be satisfied. Dropping connection request");
69 return;
70 }
71
72 PendingCommand pending_command = PendingCommand::CreditBasedConnectionRequest(
73 next_signal_id_, psm, local_cid, mtu, link_->GetMps(), link_->GetInitialCredit());
74 next_signal_id_++;
75 pending_commands_.push(pending_command);
76 if (pending_commands_.size() == 1) {
77 handle_send_next_command();
78 }
79 }
80
SendDisconnectRequest(Cid scid,Cid dcid)81 void LeSignallingManager::SendDisconnectRequest(Cid scid, Cid dcid) {
82 PendingCommand pending_command = PendingCommand::DisconnectionRequest(next_signal_id_, scid, dcid);
83 next_signal_id_++;
84 pending_commands_.push(pending_command);
85 if (pending_commands_.size() == 1) {
86 handle_send_next_command();
87 }
88 }
89
SendConnectionParameterUpdateRequest(uint16_t interval_min,uint16_t interval_max,uint16_t peripheral_latency,uint16_t timeout_multiplier)90 void LeSignallingManager::SendConnectionParameterUpdateRequest(
91 uint16_t interval_min, uint16_t interval_max, uint16_t peripheral_latency, uint16_t timeout_multiplier) {
92 PendingCommand pending_command = PendingCommand::ConnectionParameterUpdate(
93 next_signal_id_, interval_min, interval_max, peripheral_latency, timeout_multiplier);
94 next_signal_id_++;
95 pending_commands_.push(pending_command);
96 if (pending_commands_.size() == 1) {
97 handle_send_next_command();
98 }
99 }
100
SendConnectionParameterUpdateResponse(SignalId signal_id,ConnectionParameterUpdateResponseResult result)101 void LeSignallingManager::SendConnectionParameterUpdateResponse(SignalId signal_id,
102 ConnectionParameterUpdateResponseResult result) {
103 auto builder = ConnectionParameterUpdateResponseBuilder::Create(signal_id.Value(), result);
104 enqueue_buffer_->Enqueue(std::move(builder), handler_);
105 }
106
SendCredit(Cid local_cid,uint16_t credits)107 void LeSignallingManager::SendCredit(Cid local_cid, uint16_t credits) {
108 auto builder = LeFlowControlCreditBuilder::Create(next_signal_id_.Value(), local_cid, credits);
109 next_signal_id_++;
110 enqueue_buffer_->Enqueue(std::move(builder), handler_);
111 }
112
SendEnhancedConnectionRequest(Psm psm,std::vector<Cid> local_cid,Mtu mtu)113 void LeSignallingManager::SendEnhancedConnectionRequest(Psm psm, std::vector<Cid> local_cid, Mtu mtu) {}
114
SendEnhancedReconfigureRequest(std::vector<Cid> local_cid,Mtu mtu)115 void LeSignallingManager::SendEnhancedReconfigureRequest(std::vector<Cid> local_cid, Mtu mtu) {}
116
CancelAlarm()117 void LeSignallingManager::CancelAlarm() {
118 alarm_.Cancel();
119 }
120
OnCommandReject(LeCommandRejectView command_reject_view)121 void LeSignallingManager::OnCommandReject(LeCommandRejectView command_reject_view) {
122 auto signal_id = command_reject_view.GetIdentifier();
123 if (signal_id != command_just_sent_.signal_id_) {
124 LOG_WARN("Unexpected response: no pending request");
125 return;
126 }
127 alarm_.Cancel();
128 if (command_just_sent_.command_code_ == LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST) {
129 link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_,
130 LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE);
131 }
132 handle_send_next_command();
133
134 LOG_WARN("Command rejected");
135 }
136
OnConnectionParameterUpdateRequest(SignalId signal_id,uint16_t interval_min,uint16_t interval_max,uint16_t peripheral_latency,uint16_t timeout_multiplier)137 void LeSignallingManager::OnConnectionParameterUpdateRequest(
138 SignalId signal_id,
139 uint16_t interval_min,
140 uint16_t interval_max,
141 uint16_t peripheral_latency,
142 uint16_t timeout_multiplier) {
143 if (link_->GetRole() == hci::Role::PERIPHERAL) {
144 LOG_WARN("Received request from LL central");
145 auto builder = LeCommandRejectNotUnderstoodBuilder::Create(signal_id.Value());
146 enqueue_buffer_->Enqueue(std::move(builder), handler_);
147 return;
148 }
149
150 if (!link_->CheckConnectionParameters(interval_min, interval_max, peripheral_latency, timeout_multiplier)) {
151 LOG_WARN("Received invalid connection parameter update request from LL central");
152 auto builder = ConnectionParameterUpdateResponseBuilder::Create(signal_id.Value(),
153 ConnectionParameterUpdateResponseResult::REJECTED);
154 enqueue_buffer_->Enqueue(std::move(builder), handler_);
155 return;
156 }
157 link_->UpdateConnectionParameterFromRemote(
158 signal_id, interval_min, interval_max, peripheral_latency, timeout_multiplier);
159 }
160
OnConnectionParameterUpdateResponse(SignalId signal_id,ConnectionParameterUpdateResponseResult result)161 void LeSignallingManager::OnConnectionParameterUpdateResponse(SignalId signal_id,
162 ConnectionParameterUpdateResponseResult result) {
163 if (signal_id != command_just_sent_.signal_id_) {
164 LOG_WARN("Unexpected response: no pending request");
165 return;
166 }
167 if (command_just_sent_.command_code_ != LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST) {
168 LOG_WARN("Unexpected response: no pending request");
169 return;
170 }
171 alarm_.Cancel();
172 command_just_sent_.signal_id_ = kInitialSignalId;
173 if (result != ConnectionParameterUpdateResponseResult::ACCEPTED) {
174 LOG_ERROR("Connection parameter update is not accepted");
175 }
176 }
177
OnConnectionRequest(SignalId signal_id,Psm psm,Cid remote_cid,Mtu mtu,uint16_t mps,uint16_t initial_credits)178 void LeSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm, Cid remote_cid, Mtu mtu, uint16_t mps,
179 uint16_t initial_credits) {
180 if (remote_cid == kInvalidCid) {
181 LOG_WARN("Invalid remote cid received from remote psm:%d remote_cid:%d", psm, remote_cid);
182 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
183 LeCreditBasedConnectionResponseResult::INVALID_SOURCE_CID);
184 return;
185 }
186
187 if (channel_allocator_->IsPsmUsed(psm)) {
188 LOG_WARN("Psm already exists");
189 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
190 LeCreditBasedConnectionResponseResult::LE_PSM_NOT_SUPPORTED);
191 return;
192 }
193
194 if (!dynamic_service_manager_->IsServiceRegistered(psm)) {
195 LOG_INFO("Service for this psm (%d) is not registered", psm);
196 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
197 LeCreditBasedConnectionResponseResult::LE_PSM_NOT_SUPPORTED);
198 return;
199 }
200
201 PendingConnection pending{
202 .remote_cid = remote_cid,
203 .incoming_signal_id = signal_id,
204 .initial_credits = initial_credits,
205 .max_pdu_size = mps,
206 .mtu = mtu,
207 };
208 dynamic_service_manager_->GetSecurityEnforcementInterface()->Enforce(
209 link_->GetDevice(),
210 dynamic_service_manager_->GetService(psm)->GetSecurityPolicy(),
211 handler_->BindOnceOn(this, &LeSignallingManager::on_security_result_for_incoming, psm, pending));
212 }
213
on_security_result_for_incoming(Psm psm,PendingConnection request,bool result)214 void LeSignallingManager::on_security_result_for_incoming(Psm psm, PendingConnection request, bool result) {
215 auto signal_id = request.incoming_signal_id;
216 auto* service = dynamic_service_manager_->GetService(psm);
217 if (!result) {
218 auto security_policy = service->GetSecurityPolicy();
219 switch (security_policy) {
220 case SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK:
221 LOG_ERROR("If no security requirement, we should never fail");
222 break;
223 case SecurityPolicy::ENCRYPTED_TRANSPORT:
224 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
225 LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHENTICATION);
226 return;
227 case SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT:
228 case SecurityPolicy::BEST:
229 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
230 LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHENTICATION);
231 return;
232 case SecurityPolicy::_NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY:
233 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
234 LeCreditBasedConnectionResponseResult::INSUFFICIENT_ENCRYPTION_KEY_SIZE);
235 return;
236 case SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION:
237 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
238 LeCreditBasedConnectionResponseResult::INSUFFICIENT_AUTHORIZATION);
239 return;
240 }
241 }
242 auto config = service->GetConfigOption();
243 auto local_mtu = config.mtu;
244 auto local_mps = link_->GetMps();
245
246 auto new_channel = link_->AllocateDynamicChannel(psm, request.remote_cid);
247 if (new_channel == nullptr) {
248 LOG_WARN("Can't allocate dynamic channel");
249 // TODO: We need to respond with the correct reason
250 send_connection_response(signal_id, kInvalidCid, 0, 0, 0,
251 LeCreditBasedConnectionResponseResult::SOURCE_CID_ALREADY_ALLOCATED);
252 return;
253 }
254
255 send_connection_response(signal_id, new_channel->GetCid(), local_mtu, local_mps, link_->GetInitialCredit(),
256 LeCreditBasedConnectionResponseResult::SUCCESS);
257 auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>(
258 data_pipeline_manager_->GetDataController(new_channel->GetCid()));
259 auto actual_mtu = std::min(request.mtu, local_mtu);
260 data_controller->SetMtu(actual_mtu);
261 data_controller->SetMps(std::min(request.max_pdu_size, local_mps));
262 data_controller->OnCredit(request.initial_credits);
263 auto user_channel = std::make_unique<DynamicChannel>(new_channel, handler_, link_, actual_mtu);
264 dynamic_service_manager_->GetService(psm)->NotifyChannelCreation(std::move(user_channel));
265 }
266
OnConnectionResponse(SignalId signal_id,Cid remote_cid,Mtu mtu,uint16_t mps,uint16_t initial_credits,LeCreditBasedConnectionResponseResult result)267 void LeSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Mtu mtu, uint16_t mps,
268 uint16_t initial_credits, LeCreditBasedConnectionResponseResult result) {
269 if (signal_id != command_just_sent_.signal_id_) {
270 LOG_WARN("Unexpected response: no pending request");
271 return;
272 }
273 if (command_just_sent_.command_code_ != LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST) {
274 LOG_WARN("Unexpected response: no pending request");
275 return;
276 }
277 alarm_.Cancel();
278 command_just_sent_.signal_id_ = kInitialSignalId;
279 if (result != LeCreditBasedConnectionResponseResult::SUCCESS) {
280 LOG_WARN("Connection failed: %s", LeCreditBasedConnectionResponseResultText(result).data());
281 link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_, result);
282 handle_send_next_command();
283 return;
284 }
285 auto new_channel =
286 link_->AllocateReservedDynamicChannel(command_just_sent_.source_cid_, command_just_sent_.psm_, remote_cid);
287 if (new_channel == nullptr) {
288 LOG_WARN("Can't allocate dynamic channel");
289 link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_,
290 LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE);
291 handle_send_next_command();
292 return;
293 }
294 auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>(
295 data_pipeline_manager_->GetDataController(new_channel->GetCid()));
296 auto actual_mtu = std::min(mtu, command_just_sent_.mtu_);
297 data_controller->SetMtu(actual_mtu);
298 data_controller->SetMps(std::min(mps, command_just_sent_.mps_));
299 data_controller->OnCredit(initial_credits);
300 std::unique_ptr<DynamicChannel> user_channel =
301 std::make_unique<DynamicChannel>(new_channel, handler_, link_, actual_mtu);
302 link_->NotifyChannelCreation(new_channel->GetCid(), std::move(user_channel));
303 }
304
OnDisconnectionRequest(SignalId signal_id,Cid cid,Cid remote_cid)305 void LeSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) {
306 auto channel = channel_allocator_->FindChannelByCid(cid);
307 if (channel == nullptr) {
308 LOG_WARN("Disconnect request for an unknown channel");
309 return;
310 }
311 if (channel->GetRemoteCid() != remote_cid) {
312 LOG_WARN("Disconnect request for an unmatching channel");
313 return;
314 }
315 auto builder = LeDisconnectionResponseBuilder::Create(signal_id.Value(), cid, remote_cid);
316 enqueue_buffer_->Enqueue(std::move(builder), handler_);
317 channel->OnClosed(hci::ErrorCode::SUCCESS);
318 link_->FreeDynamicChannel(cid);
319 }
320
OnDisconnectionResponse(SignalId signal_id,Cid remote_cid,Cid cid)321 void LeSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
322 if (signal_id != command_just_sent_.signal_id_ ||
323 command_just_sent_.command_code_ != LeCommandCode::DISCONNECTION_REQUEST) {
324 LOG_WARN("Unexpected response: no pending request");
325 return;
326 }
327 if (command_just_sent_.source_cid_ != cid || command_just_sent_.destination_cid_ != remote_cid) {
328 LOG_WARN("Unexpected response: cid doesn't match. Expected scid %d dcid %d, got scid %d dcid %d",
329 command_just_sent_.source_cid_, command_just_sent_.destination_cid_, cid, remote_cid);
330 handle_send_next_command();
331 return;
332 }
333 alarm_.Cancel();
334 command_just_sent_.signal_id_ = kInitialSignalId;
335 auto channel = channel_allocator_->FindChannelByCid(cid);
336 if (channel == nullptr) {
337 LOG_WARN("Disconnect response for an unknown channel");
338 handle_send_next_command();
339 return;
340 }
341
342 channel->OnClosed(hci::ErrorCode::SUCCESS);
343 link_->FreeDynamicChannel(cid);
344 handle_send_next_command();
345 }
346
OnCredit(Cid remote_cid,uint16_t credits)347 void LeSignallingManager::OnCredit(Cid remote_cid, uint16_t credits) {
348 auto channel = channel_allocator_->FindChannelByRemoteCid(remote_cid);
349 if (channel == nullptr) {
350 LOG_WARN("Received credit for invalid cid %d", channel->GetCid());
351 return;
352 }
353 auto* data_controller = reinterpret_cast<l2cap::internal::LeCreditBasedDataController*>(
354 data_pipeline_manager_->GetDataController(channel->GetCid()));
355 data_controller->OnCredit(credits);
356 }
357
on_incoming_packet()358 void LeSignallingManager::on_incoming_packet() {
359 auto packet = signalling_channel_->GetQueueUpEnd()->TryDequeue();
360 LeControlView control_packet_view = LeControlView::Create(*packet);
361 if (!control_packet_view.IsValid()) {
362 LOG_WARN("Invalid signalling packet received");
363 return;
364 }
365 auto code = control_packet_view.GetCode();
366 switch (code) {
367 case LeCommandCode::COMMAND_REJECT: {
368 LeCommandRejectView command_reject_view = LeCommandRejectView::Create(control_packet_view);
369 if (!command_reject_view.IsValid()) {
370 return;
371 }
372 OnCommandReject(command_reject_view);
373 return;
374 }
375
376 case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: {
377 ConnectionParameterUpdateRequestView parameter_update_req_view =
378 ConnectionParameterUpdateRequestView::Create(control_packet_view);
379 if (!parameter_update_req_view.IsValid()) {
380 return;
381 }
382 OnConnectionParameterUpdateRequest(
383 parameter_update_req_view.GetIdentifier(),
384 parameter_update_req_view.GetIntervalMin(),
385 parameter_update_req_view.GetIntervalMax(),
386 parameter_update_req_view.GetPeripheralLatency(),
387 parameter_update_req_view.GetTimeoutMultiplier());
388 return;
389 }
390 case LeCommandCode::CONNECTION_PARAMETER_UPDATE_RESPONSE: {
391 ConnectionParameterUpdateResponseView parameter_update_rsp_view =
392 ConnectionParameterUpdateResponseView::Create(control_packet_view);
393 if (!parameter_update_rsp_view.IsValid()) {
394 return;
395 }
396 OnConnectionParameterUpdateResponse(parameter_update_rsp_view.GetIdentifier(),
397 parameter_update_rsp_view.GetResult());
398 return;
399 }
400 case LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST: {
401 LeCreditBasedConnectionRequestView connection_request_view =
402 LeCreditBasedConnectionRequestView::Create(control_packet_view);
403 if (!connection_request_view.IsValid()) {
404 return;
405 }
406 OnConnectionRequest(connection_request_view.GetIdentifier(), connection_request_view.GetLePsm(),
407 connection_request_view.GetSourceCid(), connection_request_view.GetMtu(),
408 connection_request_view.GetMps(), connection_request_view.GetInitialCredits());
409 return;
410 }
411 case LeCommandCode::LE_CREDIT_BASED_CONNECTION_RESPONSE: {
412 LeCreditBasedConnectionResponseView connection_response_view =
413 LeCreditBasedConnectionResponseView::Create(control_packet_view);
414 if (!connection_response_view.IsValid()) {
415 return;
416 }
417 OnConnectionResponse(connection_response_view.GetIdentifier(), connection_response_view.GetDestinationCid(),
418 connection_response_view.GetMtu(), connection_response_view.GetMps(),
419 connection_response_view.GetInitialCredits(), connection_response_view.GetResult());
420 return;
421 }
422 case LeCommandCode::LE_FLOW_CONTROL_CREDIT: {
423 LeFlowControlCreditView credit_view = LeFlowControlCreditView::Create(control_packet_view);
424 if (!credit_view.IsValid()) {
425 return;
426 }
427 OnCredit(credit_view.GetCid(), credit_view.GetCredits());
428 return;
429 }
430 case LeCommandCode::DISCONNECTION_REQUEST: {
431 LeDisconnectionRequestView disconnection_request_view = LeDisconnectionRequestView::Create(control_packet_view);
432 if (!disconnection_request_view.IsValid()) {
433 return;
434 }
435 OnDisconnectionRequest(disconnection_request_view.GetIdentifier(), disconnection_request_view.GetDestinationCid(),
436 disconnection_request_view.GetSourceCid());
437 return;
438 }
439 case LeCommandCode::DISCONNECTION_RESPONSE: {
440 LeDisconnectionResponseView disconnection_response_view =
441 LeDisconnectionResponseView::Create(control_packet_view);
442 if (!disconnection_response_view.IsValid()) {
443 return;
444 }
445 OnDisconnectionResponse(disconnection_response_view.GetIdentifier(),
446 disconnection_response_view.GetDestinationCid(),
447 disconnection_response_view.GetSourceCid());
448 return;
449 }
450 case LeCommandCode::CREDIT_BASED_CONNECTION_REQUEST: {
451 LeEnhancedCreditBasedConnectionRequestView request_view =
452 LeEnhancedCreditBasedConnectionRequestView::Create(control_packet_view);
453 if (!request_view.IsValid()) {
454 return;
455 }
456 return;
457 }
458 case LeCommandCode::CREDIT_BASED_CONNECTION_RESPONSE: {
459 LeEnhancedCreditBasedConnectionResponseView response_view =
460 LeEnhancedCreditBasedConnectionResponseView::Create(control_packet_view);
461 if (!response_view.IsValid()) {
462 return;
463 }
464 return;
465 }
466 case LeCommandCode::CREDIT_BASED_RECONFIGURE_REQUEST: {
467 LeEnhancedCreditBasedReconfigureRequestView request_view =
468 LeEnhancedCreditBasedReconfigureRequestView::Create(control_packet_view);
469 if (!request_view.IsValid()) {
470 return;
471 }
472 return;
473 }
474 case LeCommandCode::CREDIT_BASED_RECONFIGURE_RESPONSE: {
475 LeEnhancedCreditBasedReconfigureResponseView response_view =
476 LeEnhancedCreditBasedReconfigureResponseView::Create(control_packet_view);
477 if (!response_view.IsValid()) {
478 return;
479 }
480 return;
481 }
482 default:
483 LOG_WARN("Unhandled event 0x%x", static_cast<int>(code));
484 auto builder = LeCommandRejectNotUnderstoodBuilder::Create(control_packet_view.GetIdentifier());
485 enqueue_buffer_->Enqueue(std::move(builder), handler_);
486 return;
487 }
488 }
489
send_connection_response(SignalId signal_id,Cid local_cid,Mtu mtu,uint16_t mps,uint16_t initial_credit,LeCreditBasedConnectionResponseResult result)490 void LeSignallingManager::send_connection_response(SignalId signal_id, Cid local_cid, Mtu mtu, uint16_t mps,
491 uint16_t initial_credit,
492 LeCreditBasedConnectionResponseResult result) {
493 auto builder =
494 LeCreditBasedConnectionResponseBuilder::Create(signal_id.Value(), local_cid, mtu, mps, initial_credit, result);
495 enqueue_buffer_->Enqueue(std::move(builder), handler_);
496 }
497
on_command_timeout()498 void LeSignallingManager::on_command_timeout() {
499 LOG_WARN("Response time out");
500 if (command_just_sent_.signal_id_ == kInvalidSignalId) {
501 LOG_ERROR("No pending command");
502 return;
503 }
504 switch (command_just_sent_.command_code_) {
505 case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: {
506 link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_,
507 LeCreditBasedConnectionResponseResult::NO_RESOURCES_AVAILABLE);
508 break;
509 }
510 default:
511 break;
512 }
513 handle_send_next_command();
514 }
515
handle_send_next_command()516 void LeSignallingManager::handle_send_next_command() {
517 command_just_sent_.signal_id_ = kInvalidSignalId;
518 if (pending_commands_.empty()) {
519 return;
520 }
521
522 command_just_sent_ = pending_commands_.front();
523 pending_commands_.pop();
524 switch (command_just_sent_.command_code_) {
525 case LeCommandCode::LE_CREDIT_BASED_CONNECTION_REQUEST: {
526 auto builder = LeCreditBasedConnectionRequestBuilder::Create(
527 command_just_sent_.signal_id_.Value(), command_just_sent_.psm_, command_just_sent_.source_cid_,
528 command_just_sent_.mtu_, command_just_sent_.mps_, command_just_sent_.credits_);
529 enqueue_buffer_->Enqueue(std::move(builder), handler_);
530 alarm_.Schedule(common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout);
531 break;
532 }
533 case LeCommandCode::DISCONNECTION_REQUEST: {
534 auto builder = LeDisconnectionRequestBuilder::Create(
535 command_just_sent_.signal_id_.Value(), command_just_sent_.destination_cid_, command_just_sent_.source_cid_);
536 enqueue_buffer_->Enqueue(std::move(builder), handler_);
537 alarm_.Schedule(common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout);
538 break;
539 }
540 case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: {
541 auto builder = ConnectionParameterUpdateRequestBuilder::Create(
542 command_just_sent_.signal_id_.Value(),
543 command_just_sent_.interval_min_,
544 command_just_sent_.interval_max_,
545 command_just_sent_.peripheral_latency_,
546 command_just_sent_.timeout_multiplier_);
547 enqueue_buffer_->Enqueue(std::move(builder), handler_);
548 alarm_.Schedule(common::BindOnce(&LeSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout);
549 break;
550 }
551 default: {
552 LOG_WARN("Unsupported command code 0x%x", static_cast<int>(command_just_sent_.command_code_));
553 }
554 }
555 }
556 } // namespace internal
557 } // namespace le
558 } // namespace l2cap
559 } // namespace bluetooth
560