1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
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
19 /******************************************************************************
20 *
21 * This file contains the L2CAP channel state machine
22 *
23 ******************************************************************************/
24 #define LOG_TAG "l2c_csm"
25
26 #include <base/functional/callback.h>
27 #include <bluetooth/log.h>
28 #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
29
30 #include <string>
31
32 #include "hal/snoop_logger.h"
33 #include "internal_include/bt_target.h"
34 #include "main/shim/entry.h"
35 #include "main/shim/metrics_api.h"
36 #include "os/log.h"
37 #include "osi/include/allocator.h"
38 #include "osi/include/stack_power_telemetry.h"
39 #include "stack/btm/btm_sec.h"
40 #include "stack/include/acl_api.h"
41 #include "stack/include/bt_hdr.h"
42 #include "stack/include/bt_types.h"
43 #include "stack/include/l2cdefs.h"
44 #include "stack/l2cap/l2c_int.h"
45
46 using namespace bluetooth;
47
48 /******************************************************************************/
49 /* L O C A L F U N C T I O N P R O T O T Y P E S */
50 /******************************************************************************/
51 static void l2c_csm_closed(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data);
52 static void l2c_csm_orig_w4_sec_comp(tL2C_CCB* p_ccb, tL2CEVT event,
53 void* p_data);
54 static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, tL2CEVT event,
55 void* p_data);
56 static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
57 void* p_data);
58 static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
59 void* p_data);
60 static void l2c_csm_config(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data);
61 static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data);
62 static void l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
63 void* p_data);
64 static void l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
65 void* p_data);
66
67 static const char* l2c_csm_get_event_name(tL2CEVT event);
68
69 // Send a connect response with result OK and adjust the state machine
l2c_csm_send_connect_rsp(tL2C_CCB * p_ccb)70 static void l2c_csm_send_connect_rsp(tL2C_CCB* p_ccb) {
71 l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP, NULL);
72 }
73
74 // Send a config request and adjust the state machine
l2c_csm_send_config_req(tL2C_CCB * p_ccb)75 static void l2c_csm_send_config_req(tL2C_CCB* p_ccb) {
76 tL2CAP_CFG_INFO config{};
77 config.mtu_present = true;
78 config.mtu = p_ccb->p_rcb->my_mtu;
79 p_ccb->max_rx_mtu = config.mtu;
80 if (p_ccb->p_rcb->ertm_info.preferred_mode != L2CAP_FCR_BASIC_MODE) {
81 config.fcr_present = true;
82 config.fcr = kDefaultErtmOptions;
83 }
84 p_ccb->our_cfg = config;
85 l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONFIG_REQ, &config);
86 }
87
88 // Send a config response with result OK and adjust the state machine
l2c_csm_send_config_rsp_ok(tL2C_CCB * p_ccb,bool cbit)89 static void l2c_csm_send_config_rsp_ok(tL2C_CCB* p_ccb, bool cbit) {
90 tL2CAP_CFG_INFO config{};
91 config.result = L2CAP_CFG_OK;
92 if (cbit) {
93 config.flags = L2CAP_CFG_FLAGS_MASK_CONT;
94 }
95 l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONFIG_RSP, &config);
96 }
97
l2c_csm_send_disconnect_rsp(tL2C_CCB * p_ccb)98 static void l2c_csm_send_disconnect_rsp(tL2C_CCB* p_ccb) {
99 l2c_csm_execute(p_ccb, L2CEVT_L2CA_DISCONNECT_RSP, NULL);
100 }
101
l2c_csm_indicate_connection_open(tL2C_CCB * p_ccb)102 static void l2c_csm_indicate_connection_open(tL2C_CCB* p_ccb) {
103 if (p_ccb->connection_initiator == L2CAP_INITIATOR_LOCAL) {
104 (*p_ccb->p_rcb->api.pL2CA_ConnectCfm_Cb)(p_ccb->local_cid, L2CAP_CONN_OK);
105 } else {
106 if (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb) {
107 (*p_ccb->p_rcb->api.pL2CA_ConnectInd_Cb)(
108 p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, p_ccb->p_rcb->psm,
109 p_ccb->remote_id);
110 } else {
111 log::warn("pL2CA_ConnectInd_Cb is null");
112 }
113 }
114 if (p_ccb->chnl_state == CST_OPEN && !p_ccb->p_lcb->is_transport_ble()) {
115 (*p_ccb->p_rcb->api.pL2CA_ConfigCfm_Cb)(
116 p_ccb->local_cid, p_ccb->connection_initiator, &p_ccb->peer_cfg);
117 }
118 power_telemetry::GetInstance().LogChannelConnected(
119 p_ccb->p_rcb->psm, p_ccb->local_cid, p_ccb->remote_id,
120 p_ccb->p_lcb->remote_bd_addr);
121 }
122
123 /*******************************************************************************
124 *
125 * Function l2c_csm_execute
126 *
127 * Description This function executes the state machine.
128 *
129 * Returns void
130 *
131 ******************************************************************************/
l2c_csm_execute(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)132 void l2c_csm_execute(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
133 if (p_ccb == nullptr) {
134 log::warn("CCB is null for event ({})", event);
135 return;
136 }
137
138 if (!l2cu_is_ccb_active(p_ccb)) {
139 log::warn("CCB not in use, event ({}) cannot be processed", event);
140 return;
141 }
142
143 // Log all but data events
144 if (event != L2CEVT_L2CAP_DATA && event != L2CEVT_L2CA_DATA_READ &&
145 event != L2CEVT_L2CA_DATA_WRITE) {
146 log::info("Enter CSM, chnl_state:{} [{}], event:{} [{}]",
147 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
148 l2c_csm_get_event_name(event), event);
149 }
150
151 switch (p_ccb->chnl_state) {
152 case CST_CLOSED:
153 l2c_csm_closed(p_ccb, event, p_data);
154 break;
155
156 case CST_ORIG_W4_SEC_COMP:
157 l2c_csm_orig_w4_sec_comp(p_ccb, event, p_data);
158 break;
159
160 case CST_TERM_W4_SEC_COMP:
161 l2c_csm_term_w4_sec_comp(p_ccb, event, p_data);
162 break;
163
164 case CST_W4_L2CAP_CONNECT_RSP:
165 l2c_csm_w4_l2cap_connect_rsp(p_ccb, event, p_data);
166 break;
167
168 case CST_W4_L2CA_CONNECT_RSP:
169 l2c_csm_w4_l2ca_connect_rsp(p_ccb, event, p_data);
170 break;
171
172 case CST_CONFIG:
173 l2c_csm_config(p_ccb, event, p_data);
174 break;
175
176 case CST_OPEN:
177 l2c_csm_open(p_ccb, event, p_data);
178 break;
179
180 case CST_W4_L2CAP_DISCONNECT_RSP:
181 l2c_csm_w4_l2cap_disconnect_rsp(p_ccb, event, p_data);
182 break;
183
184 case CST_W4_L2CA_DISCONNECT_RSP:
185 l2c_csm_w4_l2ca_disconnect_rsp(p_ccb, event, p_data);
186 break;
187
188 default:
189 log::error("Unhandled state {}, event {}", p_ccb->chnl_state, event);
190 break;
191 }
192 }
193
194 /*******************************************************************************
195 *
196 * Function l2c_csm_closed
197 *
198 * Description This function handles events when the channel is in
199 * CLOSED state. This state exists only when the link is
200 * being initially established.
201 *
202 * Returns void
203 *
204 ******************************************************************************/
l2c_csm_closed(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)205 static void l2c_csm_closed(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
206 tL2C_CONN_INFO* p_ci = (tL2C_CONN_INFO*)p_data;
207 uint16_t local_cid = p_ccb->local_cid;
208 tL2CA_DISCONNECT_IND_CB* disconnect_ind;
209
210 if (p_ccb->p_rcb == NULL) {
211 log::error("LCID: 0x{:04x} st: CLOSED evt: {} p_rcb == NULL",
212 p_ccb->local_cid, l2c_csm_get_event_name(event));
213 return;
214 }
215
216 disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
217
218 log::debug("LCID: 0x{:04x} st: CLOSED evt: {}", p_ccb->local_cid,
219 l2c_csm_get_event_name(event));
220
221 switch (event) {
222 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
223 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
224 p_ccb->local_cid);
225 l2cu_release_ccb(p_ccb);
226 (*disconnect_ind)(local_cid, false);
227 break;
228
229 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
230 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
231 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
232 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
233 true, &l2c_link_sec_comp, p_ccb);
234 } else {
235 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
236 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
237 p_ccb->p_rcb->psm, true, &l2c_link_sec_comp,
238 p_ccb);
239 }
240 break;
241
242 case L2CEVT_LP_CONNECT_CFM_NEG: /* Link failed */
243 if (p_ci->status == HCI_ERR_CONNECTION_EXISTS) {
244 btm_acl_notif_conn_collision(p_ccb->p_lcb->remote_bd_addr);
245 } else {
246 l2cu_release_ccb(p_ccb);
247 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid,
248 L2CAP_CONN_ACL_CONNECTION_FAILED);
249 bluetooth::shim::CountCounterMetrics(
250 android::bluetooth::CodePathCounterKeyEnum::
251 L2CAP_CONNECT_CONFIRM_NEG,
252 1);
253 }
254 break;
255
256 case L2CEVT_L2CA_CREDIT_BASED_CONNECT_REQ: /* API connect request */
257 case L2CEVT_L2CA_CONNECT_REQ:
258 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
259 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
260 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
261 true, &l2c_link_sec_comp, p_ccb);
262 } else {
263 if (!BTM_SetLinkPolicyActiveMode(p_ccb->p_lcb->remote_bd_addr)) {
264 log::warn("Unable to set link policy active");
265 }
266 /* If sec access does not result in started SEC_COM or COMP_NEG are
267 * already processed */
268 if (btm_sec_l2cap_access_req(
269 p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, true,
270 &l2c_link_sec_comp, p_ccb) == BTM_CMD_STARTED) {
271 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
272 }
273 }
274 break;
275
276 case L2CEVT_SEC_COMP:
277 p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
278
279 /* Wait for the info resp in this state before sending connect req (if
280 * needed) */
281 if (!p_ccb->p_lcb->w4_info_rsp) {
282 /* Need to have at least one compatible channel to continue */
283 if (!l2c_fcr_chk_chan_modes(p_ccb)) {
284 l2cu_release_ccb(p_ccb);
285 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid,
286 L2CAP_CONN_OTHER_ERROR);
287 bluetooth::shim::CountCounterMetrics(
288 android::bluetooth::CodePathCounterKeyEnum::
289 L2CAP_NO_COMPATIBLE_CHANNEL_AT_CSM_CLOSED,
290 1);
291 } else {
292 l2cu_send_peer_connect_req(p_ccb);
293 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
294 L2CAP_CHNL_CONNECT_TIMEOUT_MS,
295 l2c_ccb_timer_timeout, p_ccb);
296 }
297 }
298 break;
299
300 case L2CEVT_SEC_COMP_NEG: /* something is really bad with security */
301 l2cu_release_ccb(p_ccb);
302 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(
303 local_cid, L2CAP_CONN_CLIENT_SECURITY_CLEARANCE_FAILED);
304 bluetooth::shim::CountCounterMetrics(
305 android::bluetooth::CodePathCounterKeyEnum::
306 L2CAP_SECURITY_NEG_AT_CSM_CLOSED,
307 1);
308 break;
309
310 case L2CEVT_L2CAP_CREDIT_BASED_CONNECT_REQ: /* Peer connect request */
311 case L2CEVT_L2CAP_CONNECT_REQ:
312 /* stop link timer to avoid race condition between A2MP, Security, and
313 * L2CAP */
314 alarm_cancel(p_ccb->p_lcb->l2c_lcb_timer);
315
316 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
317 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
318 tL2CAP_LE_RESULT_CODE result = l2ble_sec_access_req(
319 p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, false,
320 &l2c_link_sec_comp, p_ccb);
321
322 switch (result) {
323 case L2CAP_LE_RESULT_INSUFFICIENT_AUTHORIZATION:
324 case L2CAP_LE_RESULT_UNACCEPTABLE_PARAMETERS:
325 case L2CAP_LE_RESULT_INVALID_PARAMETERS:
326 case L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION:
327 case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE:
328 case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP:
329 l2cu_reject_ble_connection(p_ccb, p_ccb->remote_id, result);
330 l2cu_release_ccb(p_ccb);
331 break;
332 case L2CAP_LE_RESULT_CONN_OK:
333 case L2CAP_LE_RESULT_NO_PSM:
334 case L2CAP_LE_RESULT_NO_RESOURCES:
335 case L2CAP_LE_RESULT_INVALID_SOURCE_CID:
336 case L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED:
337 break;
338 }
339 } else {
340 if (!BTM_SetLinkPolicyActiveMode(p_ccb->p_lcb->remote_bd_addr)) {
341 log::warn("Unable to set link policy active");
342 }
343 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
344 auto status = btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
345 p_ccb->p_rcb->psm, false,
346 &l2c_link_sec_comp, p_ccb);
347 if (status == BTM_CMD_STARTED) {
348 // started the security process, tell the peer to set a longer timer
349 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
350 } else {
351 log::info("Check security for psm 0x{:04x}, status {}",
352 p_ccb->p_rcb->psm, status);
353 }
354 }
355 break;
356
357 case L2CEVT_TIMEOUT:
358 l2cu_release_ccb(p_ccb);
359 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid, L2CAP_CONN_OTHER_ERROR);
360 bluetooth::shim::CountCounterMetrics(
361 android::bluetooth::CodePathCounterKeyEnum::
362 L2CAP_TIMEOUT_AT_CSM_CLOSED,
363 1);
364 break;
365
366 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
367 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
368 osi_free(p_data);
369 break;
370
371 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
372 l2cu_release_ccb(p_ccb);
373 break;
374
375 default:
376 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
377 }
378 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
379 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
380 l2c_csm_get_event_name(event), event);
381 }
382
383 /*******************************************************************************
384 *
385 * Function l2c_csm_orig_w4_sec_comp
386 *
387 * Description This function handles events when the channel is in
388 * CST_ORIG_W4_SEC_COMP state.
389 *
390 * Returns void
391 *
392 ******************************************************************************/
l2c_csm_orig_w4_sec_comp(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)393 static void l2c_csm_orig_w4_sec_comp(tL2C_CCB* p_ccb, tL2CEVT event,
394 void* p_data) {
395 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
396 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
397 uint16_t local_cid = p_ccb->local_cid;
398
399 log::debug("{} - LCID: 0x{:04x} st: ORIG_W4_SEC_COMP evt: {}",
400 ((p_ccb->p_lcb) && (p_ccb->p_lcb->transport == BT_TRANSPORT_LE))
401 ? "LE "
402 : "",
403 p_ccb->local_cid, l2c_csm_get_event_name(event));
404
405 switch (event) {
406 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
407 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
408 p_ccb->local_cid);
409 l2cu_release_ccb(p_ccb);
410 (*disconnect_ind)(local_cid, false);
411 break;
412
413 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
414 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
415 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
416 l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
417 false, &l2c_link_sec_comp, p_ccb);
418 } else {
419 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr,
420 p_ccb->p_rcb->psm, true, &l2c_link_sec_comp,
421 p_ccb);
422 }
423 break;
424
425 case L2CEVT_SEC_COMP: /* Security completed success */
426 /* Wait for the info resp in this state before sending connect req (if
427 * needed) */
428 p_ccb->chnl_state = CST_W4_L2CAP_CONNECT_RSP;
429 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
430 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
431 l2c_ccb_timer_timeout, p_ccb);
432 l2cble_credit_based_conn_req(p_ccb); /* Start Connection */
433 } else {
434 if (!p_ccb->p_lcb->w4_info_rsp) {
435 /* Need to have at least one compatible channel to continue */
436 if (!l2c_fcr_chk_chan_modes(p_ccb)) {
437 l2cu_release_ccb(p_ccb);
438 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid,
439 L2CAP_CONN_OTHER_ERROR);
440 bluetooth::shim::CountCounterMetrics(
441 android::bluetooth::CodePathCounterKeyEnum::
442 L2CAP_NO_COMPATIBLE_CHANNEL_AT_W4_SEC,
443 1);
444 } else {
445 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
446 L2CAP_CHNL_CONNECT_TIMEOUT_MS,
447 l2c_ccb_timer_timeout, p_ccb);
448 l2cu_send_peer_connect_req(p_ccb); /* Start Connection */
449 }
450 }
451 }
452 break;
453
454 case L2CEVT_SEC_COMP_NEG:
455 /* If last channel immediately disconnect the ACL for better security.
456 Also prevents a race condition between BTM and L2CAP */
457 if ((p_ccb == p_ccb->p_lcb->ccb_queue.p_first_ccb) &&
458 (p_ccb == p_ccb->p_lcb->ccb_queue.p_last_ccb)) {
459 p_ccb->p_lcb->idle_timeout = 0;
460 }
461
462 l2cu_release_ccb(p_ccb);
463 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(
464 local_cid, L2CAP_CONN_CLIENT_SECURITY_CLEARANCE_FAILED);
465 bluetooth::shim::CountCounterMetrics(
466 android::bluetooth::CodePathCounterKeyEnum::
467 L2CAP_SECURITY_NEG_AT_W4_SEC,
468 1);
469 break;
470
471 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
472 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
473 osi_free(p_data);
474 break;
475
476 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
477 /* Tell security manager to abort */
478 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr);
479
480 l2cu_release_ccb(p_ccb);
481 break;
482
483 default:
484 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
485 }
486 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
487 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
488 l2c_csm_get_event_name(event), event);
489 }
490
491 /*******************************************************************************
492 *
493 * Function l2c_csm_term_w4_sec_comp
494 *
495 * Description This function handles events when the channel is in
496 * CST_TERM_W4_SEC_COMP state.
497 *
498 * Returns void
499 *
500 ******************************************************************************/
l2c_csm_term_w4_sec_comp(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)501 static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, tL2CEVT event,
502 void* p_data) {
503 log::debug("LCID: 0x{:04x} st: TERM_W4_SEC_COMP evt: {}", p_ccb->local_cid,
504 l2c_csm_get_event_name(event));
505
506 switch (event) {
507 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
508 /* Tell security manager to abort */
509 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr);
510
511 l2cu_release_ccb(p_ccb);
512 break;
513
514 case L2CEVT_SEC_COMP:
515 p_ccb->chnl_state = CST_W4_L2CA_CONNECT_RSP;
516
517 /* Wait for the info resp in next state before sending connect ind (if
518 * needed) */
519 if (!p_ccb->p_lcb->w4_info_rsp) {
520 log::debug("Not waiting for info response, sending connect response");
521 /* Don't need to get info from peer or already retrieved so continue */
522 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
523 l2c_ccb_timer_timeout, p_ccb);
524
525 if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
526 log::debug("Not LE connection, sending configure request");
527 l2c_csm_send_connect_rsp(p_ccb);
528 l2c_csm_send_config_req(p_ccb);
529 } else {
530 if (p_ccb->ecoc) {
531 /* Handle Credit Based Connection */
532 log::debug("Calling CreditBasedConnect_Ind_Cb(), num of cids: {}",
533 p_ccb->p_lcb->pending_ecoc_conn_cnt);
534
535 std::vector<uint16_t> pending_cids;
536 for (int i = 0; i < p_ccb->p_lcb->pending_ecoc_conn_cnt; i++) {
537 uint16_t cid = p_ccb->p_lcb->pending_ecoc_connection_cids[i];
538 if (cid != 0) pending_cids.push_back(cid);
539 }
540
541 (*p_ccb->p_rcb->api.pL2CA_CreditBasedConnectInd_Cb)(
542 p_ccb->p_lcb->remote_bd_addr, pending_cids, p_ccb->p_rcb->psm,
543 p_ccb->peer_conn_cfg.mtu, p_ccb->remote_id);
544 } else {
545 /* Handle BLE CoC */
546 log::debug("Calling Connect_Ind_Cb(), CID: 0x{:04x}",
547 p_ccb->local_cid);
548 l2c_csm_send_connect_rsp(p_ccb);
549 l2c_csm_indicate_connection_open(p_ccb);
550 }
551 }
552 } else {
553 /*
554 ** L2CAP Connect Response will be sent out by 3 sec timer expiration
555 ** because Bluesoleil doesn't respond to L2CAP Information Request.
556 ** Bluesoleil seems to disconnect ACL link as failure case, because
557 ** it takes too long (4~7secs) to get response.
558 ** product version : Bluesoleil 2.1.1.0 EDR Release 060123
559 ** stack version : 05.04.11.20060119
560 */
561
562 /* Cancel ccb timer as security complete. waiting for w4_info_rsp
563 ** once info rsp received, connection rsp timer will be started
564 ** while sending connection ind to profiles
565 */
566 alarm_cancel(p_ccb->l2c_ccb_timer);
567
568 /* Waiting for the info resp, tell the peer to set a longer timer */
569 log::debug("Waiting for info response, sending connect pending");
570 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_PENDING, 0);
571 }
572 break;
573
574 case L2CEVT_SEC_COMP_NEG:
575 if (((tL2C_CONN_INFO*)p_data)->status == BTM_DELAY_CHECK) {
576 /* start a timer - encryption change not received before L2CAP connect
577 * req */
578 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
579 L2CAP_DELAY_CHECK_SM4_TIMEOUT_MS,
580 l2c_ccb_timer_timeout, p_ccb);
581 } else {
582 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
583 l2cu_reject_ble_connection(
584 p_ccb, p_ccb->remote_id,
585 L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION);
586 else
587 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_SECURITY_BLOCK, 0);
588 l2cu_release_ccb(p_ccb);
589 }
590 break;
591
592 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
593 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
594 osi_free(p_data);
595 break;
596
597 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
598 l2cu_release_ccb(p_ccb);
599 break;
600
601 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
602 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
603 p_ccb->remote_cid);
604
605 /* Tell security manager to abort */
606 btm_sec_abort_access_req(p_ccb->p_lcb->remote_bd_addr);
607
608 l2cu_release_ccb(p_ccb);
609 break;
610
611 case L2CEVT_TIMEOUT:
612 /* SM4 related. */
613 acl_disconnect_from_handle(
614 p_ccb->p_lcb->Handle(), HCI_ERR_AUTH_FAILURE,
615 "stack::l2cap::l2c_csm::l2c_csm_term_w4_sec_comp Event timeout");
616 break;
617
618 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
619 btm_sec_l2cap_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
620 false, &l2c_link_sec_comp, p_ccb);
621 break;
622
623 default:
624 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
625 }
626 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
627 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
628 l2c_csm_get_event_name(event), event);
629 }
630
631 /*******************************************************************************
632 *
633 * Function l2c_csm_w4_l2cap_connect_rsp
634 *
635 * Description This function handles events when the channel is in
636 * CST_W4_L2CAP_CONNECT_RSP state.
637 *
638 * Returns void
639 *
640 ******************************************************************************/
l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)641 static void l2c_csm_w4_l2cap_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
642 void* p_data) {
643 tL2C_CONN_INFO* p_ci = (tL2C_CONN_INFO*)p_data;
644 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
645 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
646 tL2CA_CREDIT_BASED_CONNECT_CFM_CB* credit_based_connect_cfm =
647 p_ccb->p_rcb->api.pL2CA_CreditBasedConnectCfm_Cb;
648 uint16_t local_cid = p_ccb->local_cid;
649 tL2C_LCB* p_lcb = p_ccb->p_lcb;
650
651 log::debug("LCID: 0x{:04x} st: W4_L2CAP_CON_RSP evt: {}", p_ccb->local_cid,
652 l2c_csm_get_event_name(event));
653
654 switch (event) {
655 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
656 /* Send disc indication unless peer to peer race condition AND normal
657 * disconnect */
658 /* *((uint8_t *)p_data) != HCI_ERR_PEER_USER happens when peer device try
659 * to disconnect for normal reason */
660 p_ccb->chnl_state = CST_CLOSED;
661 if ((p_ccb->flags & CCB_FLAG_NO_RETRY) || !p_data ||
662 (*((uint8_t*)p_data) != HCI_ERR_PEER_USER)) {
663 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
664 p_ccb->local_cid);
665 l2cu_release_ccb(p_ccb);
666 (*disconnect_ind)(local_cid, false);
667 }
668 p_ccb->flags |= CCB_FLAG_NO_RETRY;
669 break;
670
671 case L2CEVT_L2CAP_CONNECT_RSP: /* Got peer connect confirm */
672 p_ccb->remote_cid = p_ci->remote_cid;
673 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
674 /* Connection is completed */
675 alarm_cancel(p_ccb->l2c_ccb_timer);
676 p_ccb->chnl_state = CST_OPEN;
677 l2c_csm_indicate_connection_open(p_ccb);
678 p_ccb->local_conn_cfg = p_ccb->p_rcb->coc_cfg;
679 p_ccb->remote_credit_count = p_ccb->p_rcb->coc_cfg.credits;
680 l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP, NULL);
681 } else {
682 p_ccb->chnl_state = CST_CONFIG;
683 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
684 l2c_ccb_timer_timeout, p_ccb);
685 }
686 log::debug("Calling Connect_Cfm_Cb(), CID: 0x{:04x}, Success",
687 p_ccb->local_cid);
688
689 l2c_csm_send_config_req(p_ccb);
690 break;
691
692 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Got peer connect pending */
693 p_ccb->remote_cid = p_ci->remote_cid;
694 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
695 L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS,
696 l2c_ccb_timer_timeout, p_ccb);
697 break;
698
699 case L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP:
700 alarm_cancel(p_ccb->l2c_ccb_timer);
701 p_ccb->chnl_state = CST_OPEN;
702 log::debug("Calling credit_based_connect_cfm(),cid {}, result 0x{:04x}",
703 p_ccb->local_cid, L2CAP_CONN_OK);
704
705 (*credit_based_connect_cfm)(p_lcb->remote_bd_addr, p_ccb->local_cid,
706 p_ci->peer_mtu, L2CAP_CONN_OK);
707 break;
708
709 case L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP_NEG:
710 log::debug("Calling pL2CA_Error_Cb(),cid {}, result 0x{:04x}", local_cid,
711 p_ci->l2cap_result);
712 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid, p_ci->l2cap_result);
713 bluetooth::shim::CountCounterMetrics(
714 android::bluetooth::CodePathCounterKeyEnum::
715 L2CAP_CREDIT_BASED_CONNECT_RSP_NEG,
716 1);
717
718 l2cu_release_ccb(p_ccb);
719 break;
720
721 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer rejected connection */
722 log::warn("L2CAP connection rejected, lcid=0x{:x}, reason=0x{:x}",
723 p_ccb->local_cid, p_ci->l2cap_result);
724 l2cu_release_ccb(p_ccb);
725 if (p_lcb->transport == BT_TRANSPORT_LE) {
726 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(
727 local_cid, le_result_to_l2c_conn(p_ci->l2cap_result));
728 } else {
729 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid, L2CAP_CONN_OTHER_ERROR);
730 }
731 bluetooth::shim::CountCounterMetrics(
732 android::bluetooth::CodePathCounterKeyEnum::L2CAP_CONNECT_RSP_NEG, 1);
733 break;
734
735 case L2CEVT_TIMEOUT:
736 log::warn("L2CAP connection timeout");
737
738 if (p_ccb->ecoc) {
739 for (int i = 0; i < p_lcb->pending_ecoc_conn_cnt; i++) {
740 uint16_t cid = p_lcb->pending_ecoc_connection_cids[i];
741 tL2C_CCB* temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid);
742 log::warn("lcid= 0x{:x}", cid);
743 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(p_ccb->local_cid,
744 L2CAP_CONN_TIMEOUT);
745 bluetooth::shim::CountCounterMetrics(
746 android::bluetooth::CodePathCounterKeyEnum::
747 L2CAP_TIMEOUT_AT_CONNECT_RSP,
748 1);
749 l2cu_release_ccb(temp_p_ccb);
750 }
751 p_lcb->pending_ecoc_conn_cnt = 0;
752 memset(p_lcb->pending_ecoc_connection_cids, 0,
753 L2CAP_CREDIT_BASED_MAX_CIDS);
754
755 } else {
756 log::warn("lcid= 0x{:x}", p_ccb->local_cid);
757 l2cu_release_ccb(p_ccb);
758 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid, L2CAP_CONN_OTHER_ERROR);
759 bluetooth::shim::CountCounterMetrics(
760 android::bluetooth::CodePathCounterKeyEnum::
761 L2CAP_CONN_OTHER_ERROR_AT_CONNECT_RSP,
762 1);
763 }
764 break;
765
766 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
767 /* If we know peer CID from connect pending, we can send disconnect */
768 if (p_ccb->remote_cid != 0) {
769 l2cu_send_peer_disc_req(p_ccb);
770 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
771 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
772 L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
773 l2c_ccb_timer_timeout, p_ccb);
774 } else {
775 tL2CA_DISCONNECT_CFM_CB* disconnect_cfm =
776 p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
777 l2cu_release_ccb(p_ccb);
778 if (disconnect_cfm != nullptr) {
779 (*disconnect_cfm)(local_cid, L2CAP_CONN_NO_LINK);
780 }
781 }
782 break;
783
784 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
785 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
786 osi_free(p_data);
787 break;
788
789 case L2CEVT_L2CAP_INFO_RSP:
790 /* Need to have at least one compatible channel to continue */
791 if (!l2c_fcr_chk_chan_modes(p_ccb)) {
792 l2cu_release_ccb(p_ccb);
793 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(local_cid, L2CAP_CONN_OTHER_ERROR);
794 bluetooth::shim::CountCounterMetrics(
795 android::bluetooth::CodePathCounterKeyEnum::
796 L2CAP_INFO_NO_COMPATIBLE_CHANNEL_AT_RSP,
797 1);
798 } else {
799 /* We have feature info, so now send peer connect request */
800 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
801 l2c_ccb_timer_timeout, p_ccb);
802 l2cu_send_peer_connect_req(p_ccb); /* Start Connection */
803 }
804 break;
805
806 default:
807 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
808 }
809 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
810 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
811 l2c_csm_get_event_name(event), event);
812 }
813
814 /*******************************************************************************
815 *
816 * Function l2c_csm_w4_l2ca_connect_rsp
817 *
818 * Description This function handles events when the channel is in
819 * CST_W4_L2CA_CONNECT_RSP state.
820 *
821 * Returns void
822 *
823 ******************************************************************************/
l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)824 static void l2c_csm_w4_l2ca_connect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
825 void* p_data) {
826 tL2C_CONN_INFO* p_ci;
827 tL2C_LCB* p_lcb = p_ccb->p_lcb;
828 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
829 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
830 uint16_t local_cid = p_ccb->local_cid;
831
832 log::debug("LCID: 0x{:04x} st: W4_L2CA_CON_RSP evt: {}", p_ccb->local_cid,
833 l2c_csm_get_event_name(event));
834
835 switch (event) {
836 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
837 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
838 p_ccb->local_cid);
839 l2cu_release_ccb(p_ccb);
840 (*disconnect_ind)(local_cid, false);
841 break;
842
843 case L2CEVT_L2CA_CREDIT_BASED_CONNECT_RSP:
844 p_ci = (tL2C_CONN_INFO*)p_data;
845 if ((p_lcb == nullptr) || (p_lcb && p_lcb->transport != BT_TRANSPORT_LE)) {
846 log::warn("LE link doesn't exist");
847 return;
848 }
849 l2cu_send_peer_credit_based_conn_res(p_ccb, p_ci->lcids,
850 p_ci->l2cap_result);
851 alarm_cancel(p_ccb->l2c_ccb_timer);
852
853 for (int i = 0; i < p_lcb->pending_ecoc_conn_cnt; i++) {
854 uint16_t cid = p_lcb->pending_ecoc_connection_cids[i];
855 if (cid == 0) {
856 log::warn("pending_ecoc_connection_cids[{}] is {}", i, cid);
857 continue;
858 }
859
860 tL2C_CCB* temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid);
861 if (temp_p_ccb) {
862 auto it = std::find(p_ci->lcids.begin(), p_ci->lcids.end(), cid);
863 if (it != p_ci->lcids.end()) {
864 temp_p_ccb->chnl_state = CST_OPEN;
865 } else {
866 l2cu_release_ccb(temp_p_ccb);
867 }
868 }
869 else {
870 log::warn(
871 "temp_p_ccb is NULL, pending_ecoc_connection_cids[{}] is {}", i,
872 cid);
873 }
874 }
875 p_lcb->pending_ecoc_conn_cnt = 0;
876 memset(p_lcb->pending_ecoc_connection_cids, 0,
877 L2CAP_CREDIT_BASED_MAX_CIDS);
878
879 break;
880 case L2CEVT_L2CA_CONNECT_RSP:
881 p_ci = (tL2C_CONN_INFO*)p_data;
882 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
883 /* Result should be OK or Reject */
884 if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK)) {
885 l2cble_credit_based_conn_res(p_ccb, L2CAP_CONN_OK);
886 p_ccb->chnl_state = CST_OPEN;
887 alarm_cancel(p_ccb->l2c_ccb_timer);
888 } else {
889 l2cble_credit_based_conn_res(p_ccb, p_ci->l2cap_result);
890 l2cu_release_ccb(p_ccb);
891 }
892 } else {
893 /* Result should be OK or PENDING */
894 if ((!p_ci) || (p_ci->l2cap_result == L2CAP_CONN_OK)) {
895 log::debug("Sending connection ok for BR_EDR");
896 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_OK, 0);
897 p_ccb->chnl_state = CST_CONFIG;
898 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
899 l2c_ccb_timer_timeout, p_ccb);
900 } else {
901 /* If pending, stay in same state and start extended timer */
902 log::debug("Sending connection result {} and status {}",
903 p_ci->l2cap_result, p_ci->l2cap_status);
904 l2cu_send_peer_connect_rsp(p_ccb, p_ci->l2cap_result,
905 p_ci->l2cap_status);
906 alarm_set_on_mloop(p_ccb->l2c_ccb_timer,
907 L2CAP_CHNL_CONNECT_EXT_TIMEOUT_MS,
908 l2c_ccb_timer_timeout, p_ccb);
909 }
910 }
911 break;
912
913 case L2CEVT_L2CA_CREDIT_BASED_CONNECT_RSP_NEG:
914 p_ci = (tL2C_CONN_INFO*)p_data;
915 alarm_cancel(p_ccb->l2c_ccb_timer);
916 if (p_lcb != nullptr) {
917 if (p_lcb->transport == BT_TRANSPORT_LE) {
918 l2cu_send_peer_credit_based_conn_res(p_ccb, p_ci->lcids,
919 p_ci->l2cap_result);
920 }
921 for (int i = 0; i < p_lcb->pending_ecoc_conn_cnt; i++) {
922 uint16_t cid = p_lcb->pending_ecoc_connection_cids[i];
923 tL2C_CCB* temp_p_ccb = l2cu_find_ccb_by_cid(p_lcb, cid);
924 l2cu_release_ccb(temp_p_ccb);
925 }
926
927 p_lcb->pending_ecoc_conn_cnt = 0;
928 memset(p_lcb->pending_ecoc_connection_cids, 0,
929 L2CAP_CREDIT_BASED_MAX_CIDS);
930 }
931 break;
932 case L2CEVT_L2CA_CONNECT_RSP_NEG:
933 p_ci = (tL2C_CONN_INFO*)p_data;
934 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
935 l2cble_credit_based_conn_res(p_ccb, p_ci->l2cap_result);
936 else
937 l2cu_send_peer_connect_rsp(p_ccb, p_ci->l2cap_result,
938 p_ci->l2cap_status);
939 l2cu_release_ccb(p_ccb);
940 break;
941
942 case L2CEVT_TIMEOUT:
943 l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_NO_PSM, 0);
944 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
945 p_ccb->local_cid);
946 l2cu_release_ccb(p_ccb);
947 (*disconnect_ind)(local_cid, false);
948 break;
949
950 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
951 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
952 osi_free(p_data);
953 break;
954
955 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
956 l2cu_send_peer_disc_req(p_ccb);
957 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
958 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
959 l2c_ccb_timer_timeout, p_ccb);
960 break;
961
962 case L2CEVT_L2CAP_INFO_RSP:
963 /* We have feature info, so now give the upper layer connect IND */
964 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CONNECT_TIMEOUT_MS,
965 l2c_ccb_timer_timeout, p_ccb);
966 log::debug("Calling Connect_Ind_Cb(), CID: 0x{:04x}", p_ccb->local_cid);
967
968 l2c_csm_send_connect_rsp(p_ccb);
969 l2c_csm_send_config_req(p_ccb);
970 break;
971 default:
972 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
973 }
974 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
975 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
976 l2c_csm_get_event_name(event), event);
977 }
978
979 /*******************************************************************************
980 *
981 * Function l2c_csm_config
982 *
983 * Description This function handles events when the channel is in
984 * CONFIG state.
985 *
986 * Returns void
987 *
988 ******************************************************************************/
l2c_csm_config(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)989 static void l2c_csm_config(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
990 tL2CAP_CFG_INFO* p_cfg = (tL2CAP_CFG_INFO*)p_data;
991 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
992 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
993 uint16_t local_cid = p_ccb->local_cid;
994 uint8_t cfg_result;
995 tL2C_LCB* p_lcb = p_ccb->p_lcb;
996 tL2C_CCB* temp_p_ccb;
997 tL2CAP_LE_CFG_INFO* p_le_cfg = (tL2CAP_LE_CFG_INFO*)p_data;
998
999 log::debug("LCID: 0x{:04x} st: CONFIG evt: {}", p_ccb->local_cid,
1000 l2c_csm_get_event_name(event));
1001
1002 switch (event) {
1003 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1004 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
1005 p_ccb->local_cid);
1006 l2cu_release_ccb(p_ccb);
1007 (*disconnect_ind)(local_cid, false);
1008 break;
1009
1010 case L2CEVT_L2CAP_CREDIT_BASED_RECONFIG_REQ:
1011 /* For ecoc reconfig is handled below in l2c_ble. In case of success
1012 * let us notify upper layer about the reconfig
1013 */
1014 log::debug("Calling LeReconfigCompleted_Cb(), CID: 0x{:04x}",
1015 p_ccb->local_cid);
1016
1017 (*p_ccb->p_rcb->api.pL2CA_CreditBasedReconfigCompleted_Cb)(
1018 p_lcb->remote_bd_addr, p_ccb->local_cid, false, p_le_cfg);
1019 break;
1020 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
1021 cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
1022 if (cfg_result == L2CAP_PEER_CFG_OK) {
1023 log::debug("Calling Config_Req_Cb(), CID: 0x{:04x}, C-bit {}",
1024 p_ccb->local_cid, p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT);
1025 l2c_csm_send_config_rsp_ok(p_ccb,
1026 p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT);
1027 if (p_ccb->config_done & OB_CFG_DONE) {
1028 if (p_ccb->remote_config_rsp_result == L2CAP_CFG_OK) {
1029 l2c_csm_indicate_connection_open(p_ccb);
1030 } else {
1031 if (p_ccb->connection_initiator == L2CAP_INITIATOR_LOCAL) {
1032 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(p_ccb->local_cid,
1033 L2CAP_CFG_FAILED_NO_REASON);
1034 bluetooth::shim::CountCounterMetrics(
1035 android::bluetooth::CodePathCounterKeyEnum::
1036 L2CAP_CONFIG_REQ_FAILURE,
1037 1);
1038 }
1039 }
1040 }
1041 } else if (cfg_result == L2CAP_PEER_CFG_DISCONNECT) {
1042 /* Disconnect if channels are incompatible */
1043 log::debug("incompatible configurations disconnect");
1044 l2cu_disconnect_chnl(p_ccb);
1045 } else /* Return error to peer so it can renegotiate if possible */
1046 {
1047 log::debug("incompatible configurations trying reconfig");
1048 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
1049 }
1050 break;
1051
1052 case L2CEVT_L2CAP_CREDIT_BASED_RECONFIG_RSP:
1053 p_ccb->config_done |= OB_CFG_DONE;
1054 p_ccb->config_done |= RECONFIG_FLAG;
1055 p_ccb->chnl_state = CST_OPEN;
1056 alarm_cancel(p_ccb->l2c_ccb_timer);
1057
1058 log::debug("Calling Config_Rsp_Cb(), CID: 0x{:04x}", p_ccb->local_cid);
1059
1060 p_ccb->p_rcb->api.pL2CA_CreditBasedReconfigCompleted_Cb(
1061 p_lcb->remote_bd_addr, p_ccb->local_cid, true, p_le_cfg);
1062
1063 break;
1064 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer config response */
1065 l2cu_process_peer_cfg_rsp(p_ccb, p_cfg);
1066
1067 /* TBD: When config options grow beyong minimum MTU (48 bytes)
1068 * logic needs to be added to handle responses with
1069 * continuation bit set in flags field.
1070 * 1. Send additional config request out until C-bit is cleared in
1071 * response
1072 */
1073 p_ccb->config_done |= OB_CFG_DONE;
1074
1075 if (p_ccb->config_done & IB_CFG_DONE) {
1076 /* Verify two sides are in compatible modes before continuing */
1077 if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) {
1078 l2cu_send_peer_disc_req(p_ccb);
1079 log::warn(
1080 "Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x{:04x} No "
1081 "Conf Needed",
1082 p_ccb->local_cid);
1083 l2cu_release_ccb(p_ccb);
1084 (*disconnect_ind)(local_cid, false);
1085 break;
1086 }
1087
1088 p_ccb->config_done |= RECONFIG_FLAG;
1089 p_ccb->chnl_state = CST_OPEN;
1090 l2c_link_adjust_chnl_allocation();
1091 alarm_cancel(p_ccb->l2c_ccb_timer);
1092
1093 /* If using eRTM and waiting for an ACK, restart the ACK timer */
1094 if (p_ccb->fcrb.wait_ack) l2c_fcr_start_timer(p_ccb);
1095
1096 /*
1097 ** check p_ccb->our_cfg.fcr.mon_tout and
1098 *p_ccb->our_cfg.fcr.rtrans_tout
1099 ** we may set them to zero when sending config request during
1100 *renegotiation
1101 */
1102 if ((p_ccb->our_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
1103 ((p_ccb->our_cfg.fcr.mon_tout == 0) ||
1104 (p_ccb->our_cfg.fcr.rtrans_tout))) {
1105 l2c_fcr_adj_monitor_retran_timeout(p_ccb);
1106 }
1107
1108 /* See if we can forward anything on the hold queue */
1109 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
1110 l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
1111 }
1112 }
1113
1114 if (p_ccb->config_done & RECONFIG_FLAG) {
1115 // Notify only once
1116 bluetooth::shim::GetSnoopLogger()->SetL2capChannelOpen(
1117 p_ccb->p_lcb->Handle(), p_ccb->local_cid, p_ccb->remote_cid,
1118 p_ccb->p_rcb->psm,
1119 p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE);
1120 }
1121
1122 log::debug("Calling Config_Rsp_Cb(), CID: 0x{:04x}", p_ccb->local_cid);
1123 p_ccb->remote_config_rsp_result = p_cfg->result;
1124 if (p_ccb->config_done & IB_CFG_DONE) {
1125 l2c_csm_indicate_connection_open(p_ccb);
1126 }
1127 break;
1128
1129 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer config error rsp */
1130 /* Disable the Timer */
1131 alarm_cancel(p_ccb->l2c_ccb_timer);
1132
1133 /* If failure was channel mode try to renegotiate */
1134 if (!l2c_fcr_renegotiate_chan(p_ccb, p_cfg)) {
1135 log::debug("Calling Config_Rsp_Cb(), CID: 0x{:04x}, Failure: {}",
1136 p_ccb->local_cid, p_cfg->result);
1137 if (p_ccb->connection_initiator == L2CAP_INITIATOR_LOCAL) {
1138 (*p_ccb->p_rcb->api.pL2CA_Error_Cb)(p_ccb->local_cid,
1139 L2CAP_CFG_FAILED_NO_REASON);
1140 bluetooth::shim::CountCounterMetrics(
1141 android::bluetooth::CodePathCounterKeyEnum::L2CAP_CONFIG_RSP_NEG,
1142 1);
1143 }
1144 }
1145 break;
1146
1147 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
1148 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
1149 l2c_ccb_timer_timeout, p_ccb);
1150 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
1151 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} Conf Needed",
1152 p_ccb->local_cid);
1153 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true);
1154 l2c_csm_send_disconnect_rsp(p_ccb);
1155 break;
1156
1157 case L2CEVT_L2CA_CREDIT_BASED_RECONFIG_REQ:
1158 l2cu_send_credit_based_reconfig_req(p_ccb, (tL2CAP_LE_CFG_INFO*)p_data);
1159 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
1160 l2c_ccb_timer_timeout, p_ccb);
1161 break;
1162 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
1163 l2cu_process_our_cfg_req(p_ccb, p_cfg);
1164 l2cu_send_peer_config_req(p_ccb, p_cfg);
1165 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
1166 l2c_ccb_timer_timeout, p_ccb);
1167 break;
1168
1169 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config rsp */
1170 l2cu_process_our_cfg_rsp(p_ccb, p_cfg);
1171
1172 p_ccb->config_done |= IB_CFG_DONE;
1173
1174 if (p_ccb->config_done & OB_CFG_DONE) {
1175 /* Verify two sides are in compatible modes before continuing */
1176 if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) {
1177 l2cu_send_peer_disc_req(p_ccb);
1178 log::warn(
1179 "Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x{:04x} No "
1180 "Conf Needed",
1181 p_ccb->local_cid);
1182 l2cu_release_ccb(p_ccb);
1183 (*disconnect_ind)(local_cid, false);
1184 break;
1185 }
1186
1187 p_ccb->config_done |= RECONFIG_FLAG;
1188 p_ccb->chnl_state = CST_OPEN;
1189 l2c_link_adjust_chnl_allocation();
1190 alarm_cancel(p_ccb->l2c_ccb_timer);
1191 }
1192
1193 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
1194
1195 /* If using eRTM and waiting for an ACK, restart the ACK timer */
1196 if (p_ccb->fcrb.wait_ack) l2c_fcr_start_timer(p_ccb);
1197
1198 if (p_ccb->config_done & RECONFIG_FLAG) {
1199 // Notify only once
1200 bluetooth::shim::GetSnoopLogger()->SetL2capChannelOpen(
1201 p_ccb->p_lcb->Handle(), p_ccb->local_cid, p_ccb->remote_cid,
1202 p_ccb->p_rcb->psm,
1203 p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE);
1204 }
1205
1206 /* See if we can forward anything on the hold queue */
1207 if ((p_ccb->chnl_state == CST_OPEN) &&
1208 (!fixed_queue_is_empty(p_ccb->xmit_hold_q))) {
1209 l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
1210 }
1211 break;
1212
1213 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
1214 l2cu_send_peer_disc_req(p_ccb);
1215 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
1216 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
1217 l2c_ccb_timer_timeout, p_ccb);
1218 break;
1219
1220 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1221 log::debug("Calling DataInd_Cb(), CID: 0x{:04x}", p_ccb->local_cid);
1222 if (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL &&
1223 p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL) {
1224 if (p_ccb->local_cid < L2CAP_BASE_APPL_CID) {
1225 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL]
1226 .pL2CA_FixedData_Cb != nullptr) {
1227 p_ccb->metrics.rx(static_cast<BT_HDR*>(p_data)->len);
1228 (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL]
1229 .pL2CA_FixedData_Cb)(p_ccb->local_cid,
1230 p_ccb->p_lcb->remote_bd_addr,
1231 (BT_HDR*)p_data);
1232 } else {
1233 if (p_data != nullptr) osi_free_and_reset(&p_data);
1234 }
1235 break;
1236 }
1237 }
1238 if (p_data) p_ccb->metrics.rx(static_cast<BT_HDR*>(p_data)->len);
1239 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR*)p_data);
1240 break;
1241
1242 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1243 if (p_ccb->config_done & OB_CFG_DONE)
1244 l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
1245 else
1246 osi_free(p_data);
1247 break;
1248
1249 case L2CEVT_TIMEOUT:
1250 if (p_ccb->ecoc) {
1251 for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb;
1252 temp_p_ccb = temp_p_ccb->p_next_ccb) {
1253 if ((temp_p_ccb->in_use) && (temp_p_ccb->reconfig_started)) {
1254 (*temp_p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(
1255 temp_p_ccb->local_cid, false);
1256 l2cu_release_ccb(temp_p_ccb);
1257 }
1258 }
1259
1260 acl_disconnect_from_handle(
1261 p_ccb->p_lcb->Handle(), HCI_ERR_CONN_CAUSE_LOCAL_HOST,
1262 "stack::l2cap::l2c_csm::l2c_csm_config timeout");
1263 return;
1264 }
1265
1266 l2cu_send_peer_disc_req(p_ccb);
1267 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
1268 p_ccb->local_cid);
1269 l2cu_release_ccb(p_ccb);
1270 (*disconnect_ind)(local_cid, false);
1271 break;
1272 default:
1273 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
1274 }
1275 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
1276 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
1277 l2c_csm_get_event_name(event), event);
1278 }
1279
1280 /*******************************************************************************
1281 *
1282 * Function l2c_csm_open
1283 *
1284 * Description This function handles events when the channel is in
1285 * OPEN state.
1286 *
1287 * Returns void
1288 *
1289 ******************************************************************************/
l2c_csm_open(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)1290 static void l2c_csm_open(tL2C_CCB* p_ccb, tL2CEVT event, void* p_data) {
1291 uint16_t local_cid = p_ccb->local_cid;
1292 tL2CAP_CFG_INFO* p_cfg;
1293 tL2C_CHNL_STATE tempstate;
1294 uint8_t tempcfgdone;
1295 uint8_t cfg_result = L2CAP_PEER_CFG_DISCONNECT;
1296 uint16_t credit = 0;
1297 tL2CAP_LE_CFG_INFO* p_le_cfg = (tL2CAP_LE_CFG_INFO*)p_data;
1298
1299 log::verbose("LCID: 0x{:04x} st: OPEN evt: {}", p_ccb->local_cid,
1300 l2c_csm_get_event_name(event));
1301
1302 switch (event) {
1303 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1304 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
1305 p_ccb->local_cid);
1306 power_telemetry::GetInstance().LogChannelDisconnected(
1307 p_ccb->p_rcb->psm, p_ccb->local_cid, p_ccb->remote_id,
1308 p_ccb->p_lcb->remote_bd_addr);
1309 l2cu_release_ccb(p_ccb);
1310 if (p_ccb->p_rcb)
1311 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, false);
1312 break;
1313
1314 case L2CEVT_L2CAP_CREDIT_BASED_RECONFIG_REQ:
1315 /* For ecoc reconfig is handled below in l2c_ble. In case of success
1316 * let us notify upper layer about the reconfig
1317 */
1318 if (p_le_cfg) {
1319 log::debug("Calling LeReconfigCompleted_Cb(), CID: 0x{:04x}",
1320 p_ccb->local_cid);
1321 (*p_ccb->p_rcb->api.pL2CA_CreditBasedReconfigCompleted_Cb)(
1322 p_ccb->p_lcb->remote_bd_addr, p_ccb->local_cid, false, p_le_cfg);
1323 }
1324 break;
1325
1326 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
1327 p_cfg = (tL2CAP_CFG_INFO*)p_data;
1328
1329 tempstate = p_ccb->chnl_state;
1330 tempcfgdone = p_ccb->config_done;
1331 p_ccb->chnl_state = CST_CONFIG;
1332 // clear cached configuration in case reconfig takes place later
1333 p_ccb->peer_cfg.mtu_present = false;
1334 p_ccb->peer_cfg.flush_to_present = false;
1335 p_ccb->peer_cfg.qos_present = false;
1336 p_ccb->config_done &= ~IB_CFG_DONE;
1337
1338 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
1339 l2c_ccb_timer_timeout, p_ccb);
1340 if (p_cfg) {
1341 cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
1342 }
1343 if (cfg_result == L2CAP_PEER_CFG_OK) {
1344 (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
1345 l2c_csm_send_config_rsp_ok(p_ccb,
1346 p_cfg->flags & L2CAP_CFG_FLAGS_MASK_CONT);
1347 }
1348
1349 /* Error in config parameters: reset state and config flag */
1350 else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE) {
1351 alarm_cancel(p_ccb->l2c_ccb_timer);
1352 p_ccb->chnl_state = tempstate;
1353 p_ccb->config_done = tempcfgdone;
1354 l2cu_send_peer_config_rsp(p_ccb, p_cfg);
1355 } else /* L2CAP_PEER_CFG_DISCONNECT */
1356 {
1357 /* Disconnect if channels are incompatible
1358 * Note this should not occur if reconfigure
1359 * since this should have never passed original config.
1360 */
1361 l2cu_disconnect_chnl(p_ccb);
1362 }
1363 break;
1364
1365 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
1366 if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1367 if (!BTM_SetLinkPolicyActiveMode(p_ccb->p_lcb->remote_bd_addr)) {
1368 log::warn("Unable to set link policy active");
1369 }
1370 }
1371
1372 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
1373 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
1374 l2c_ccb_timer_timeout, p_ccb);
1375 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} Conf Needed",
1376 p_ccb->local_cid);
1377 power_telemetry::GetInstance().LogChannelDisconnected(
1378 p_ccb->p_rcb->psm, p_ccb->local_cid, p_ccb->remote_id,
1379 p_ccb->p_lcb->remote_bd_addr);
1380 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true);
1381 l2c_csm_send_disconnect_rsp(p_ccb);
1382 break;
1383
1384 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1385 if (p_data && (p_ccb->p_rcb)) {
1386 uint16_t package_len = ((BT_HDR*)p_data)->len;
1387 if (p_ccb->p_rcb->api.pL2CA_DataInd_Cb) {
1388 p_ccb->metrics.rx(static_cast<BT_HDR*>(p_data)->len);
1389 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid,
1390 (BT_HDR*)p_data);
1391 }
1392
1393 power_telemetry::GetInstance().LogRxBytes(
1394 p_ccb->p_rcb->psm, p_ccb->local_cid, p_ccb->remote_id,
1395 p_ccb->p_lcb->remote_bd_addr, package_len);
1396 }
1397 break;
1398
1399 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
1400 if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
1401 /* Make sure we are not in sniff mode */
1402 if (!BTM_SetLinkPolicyActiveMode(p_ccb->p_lcb->remote_bd_addr)) {
1403 log::warn("Unable to set link policy active");
1404 }
1405 }
1406 power_telemetry::GetInstance().LogChannelDisconnected(
1407 p_ccb->p_rcb->psm, p_ccb->local_cid, p_ccb->remote_id,
1408 p_ccb->p_lcb->remote_bd_addr);
1409 if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
1410 l2cble_send_peer_disc_req(p_ccb);
1411 else
1412 l2cu_send_peer_disc_req(p_ccb);
1413
1414 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
1415 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
1416 l2c_ccb_timer_timeout, p_ccb);
1417 break;
1418
1419 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1420 if (p_data) {
1421 uint16_t package_len = ((BT_HDR*)p_data)->len;
1422 l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
1423 l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
1424 power_telemetry::GetInstance().LogTxBytes(
1425 p_ccb->p_rcb->psm, p_ccb->local_cid, p_ccb->remote_id,
1426 p_ccb->p_lcb->remote_bd_addr, package_len);
1427 }
1428 break;
1429
1430 case L2CEVT_L2CA_CREDIT_BASED_RECONFIG_REQ:
1431 p_ccb->chnl_state = CST_CONFIG;
1432 p_ccb->config_done &= ~OB_CFG_DONE;
1433
1434 if (p_data) {
1435 l2cu_send_credit_based_reconfig_req(p_ccb, (tL2CAP_LE_CFG_INFO*)p_data);
1436
1437 alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
1438 l2c_ccb_timer_timeout, p_ccb);
1439 }
1440 break;
1441
1442 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
1443 log::error(
1444 "Dropping L2CAP re-config request because there is no usage and "
1445 "should not be invoked");
1446 break;
1447
1448 case L2CEVT_TIMEOUT:
1449 /* Process the monitor/retransmission time-outs in flow control/retrans
1450 * mode */
1451 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
1452 l2c_fcr_proc_tout(p_ccb);
1453 break;
1454
1455 case L2CEVT_ACK_TIMEOUT:
1456 l2c_fcr_proc_ack_tout(p_ccb);
1457 break;
1458
1459 case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
1460 if (p_data) {
1461 log::debug("Sending credit");
1462 credit = *(uint16_t*)p_data;
1463 l2cble_send_flow_control_credit(p_ccb, credit);
1464 }
1465 break;
1466
1467 case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
1468 if (p_data) {
1469 credit = *(uint16_t*)p_data;
1470 log::debug("Credits received {}", credit);
1471 if ((p_ccb->peer_conn_cfg.credits + credit) > L2CAP_LE_CREDIT_MAX) {
1472 /* we have received credits more than max coc credits,
1473 * so disconnecting the Le Coc Channel
1474 */
1475 l2cble_send_peer_disc_req(p_ccb);
1476 } else {
1477 p_ccb->peer_conn_cfg.credits += credit;
1478 l2c_link_check_send_pkts(p_ccb->p_lcb, 0, NULL);
1479 }
1480 }
1481 break;
1482 default:
1483 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
1484 }
1485 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
1486 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
1487 l2c_csm_get_event_name(event), event);
1488 }
1489
1490 /*******************************************************************************
1491 *
1492 * Function l2c_csm_w4_l2cap_disconnect_rsp
1493 *
1494 * Description This function handles events when the channel is in
1495 * CST_W4_L2CAP_DISCONNECT_RSP state.
1496 *
1497 * Returns void
1498 *
1499 ******************************************************************************/
l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)1500 static void l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
1501 void* p_data) {
1502 tL2CA_DISCONNECT_CFM_CB* disconnect_cfm =
1503 p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
1504 uint16_t local_cid = p_ccb->local_cid;
1505
1506 log::debug("LCID: 0x{:04x} st: W4_L2CAP_DISC_RSP evt: {}", p_ccb->local_cid,
1507 l2c_csm_get_event_name(event));
1508
1509 switch (event) {
1510 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1511 l2cu_release_ccb(p_ccb);
1512 if (disconnect_cfm != nullptr) {
1513 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1514 }
1515 break;
1516
1517 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1518 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
1519 p_ccb->remote_cid);
1520 l2cu_release_ccb(p_ccb);
1521 if (disconnect_cfm != nullptr) {
1522 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1523 }
1524 break;
1525
1526 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1527 case L2CEVT_TIMEOUT: /* Timeout */
1528 l2cu_release_ccb(p_ccb);
1529 if (disconnect_cfm != nullptr) {
1530 (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT);
1531 }
1532
1533 break;
1534
1535 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1536 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1537 osi_free(p_data);
1538 break;
1539 default:
1540 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
1541 }
1542 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
1543 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
1544 l2c_csm_get_event_name(event), event);
1545 }
1546
1547 /*******************************************************************************
1548 *
1549 * Function l2c_csm_w4_l2ca_disconnect_rsp
1550 *
1551 * Description This function handles events when the channel is in
1552 * CST_W4_L2CA_DISCONNECT_RSP state.
1553 *
1554 * Returns void
1555 *
1556 ******************************************************************************/
l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB * p_ccb,tL2CEVT event,void * p_data)1557 static void l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB* p_ccb, tL2CEVT event,
1558 void* p_data) {
1559 tL2CA_DISCONNECT_IND_CB* disconnect_ind =
1560 p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1561 uint16_t local_cid = p_ccb->local_cid;
1562
1563 log::debug("LCID: 0x{:04x} st: W4_L2CA_DISC_RSP evt: {}", p_ccb->local_cid,
1564 l2c_csm_get_event_name(event));
1565
1566 switch (event) {
1567 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1568 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
1569 p_ccb->local_cid);
1570 l2cu_release_ccb(p_ccb);
1571 (*disconnect_ind)(local_cid, false);
1572 break;
1573
1574 case L2CEVT_TIMEOUT:
1575 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
1576 p_ccb->remote_cid);
1577 log::debug("Calling Disconnect_Ind_Cb(), CID: 0x{:04x} No Conf Needed",
1578 p_ccb->local_cid);
1579 l2cu_release_ccb(p_ccb);
1580 (*disconnect_ind)(local_cid, false);
1581 break;
1582
1583 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper disconnect request */
1584 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper disconnect response */
1585 l2cu_send_peer_disc_rsp(p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid,
1586 p_ccb->remote_cid);
1587 l2cu_release_ccb(p_ccb);
1588 break;
1589
1590 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1591 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1592 osi_free(p_data);
1593 break;
1594 default:
1595 log::error("Handling unexpected event:{}", l2c_csm_get_event_name(event));
1596 }
1597 log::verbose("Exit chnl_state={} [{}], event={} [{}]",
1598 channel_state_text(p_ccb->chnl_state), p_ccb->chnl_state,
1599 l2c_csm_get_event_name(event), event);
1600 }
1601
1602 /*******************************************************************************
1603 *
1604 * Function l2c_csm_get_event_name
1605 *
1606 * Description This function returns the event name.
1607 *
1608 * NOTE conditionally compiled to save memory.
1609 *
1610 * Returns pointer to the name
1611 *
1612 ******************************************************************************/
l2c_csm_get_event_name(tL2CEVT event)1613 static const char* l2c_csm_get_event_name(tL2CEVT event) {
1614 switch (event) {
1615 case L2CEVT_LP_CONNECT_CFM: /* Lower layer connect confirm */
1616 return ("LOWER_LAYER_CONNECT_CFM");
1617 case L2CEVT_LP_CONNECT_CFM_NEG: /* Lower layer connect confirm (failed) */
1618 return ("LOWER_LAYER_CONNECT_CFM_NEG");
1619 case L2CEVT_LP_CONNECT_IND: /* Lower layer connect indication */
1620 return ("LOWER_LAYER_CONNECT_IND");
1621 case L2CEVT_LP_DISCONNECT_IND: /* Lower layer disconnect indication */
1622 return ("LOWER_LAYER_DISCONNECT_IND");
1623
1624 case L2CEVT_SEC_COMP: /* Security cleared successfully */
1625 return ("SECURITY_COMPLETE");
1626 case L2CEVT_SEC_COMP_NEG: /* Security procedure failed */
1627 return ("SECURITY_COMPLETE_NEG");
1628
1629 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connection request */
1630 return ("PEER_CONNECT_REQ");
1631 case L2CEVT_L2CAP_CONNECT_RSP: /* Peer connection response */
1632 return ("PEER_CONNECT_RSP");
1633 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Peer connection response pending */
1634 return ("PEER_CONNECT_RSP_PND");
1635 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer connection response (failed) */
1636 return ("PEER_CONNECT_RSP_NEG");
1637 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer configuration request */
1638 return ("PEER_CONFIG_REQ");
1639 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer configuration response */
1640 return ("PEER_CONFIG_RSP");
1641 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer configuration response (failed) */
1642 return ("PEER_CONFIG_RSP_NEG");
1643 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1644 return ("PEER_DISCONNECT_REQ");
1645 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1646 return ("PEER_DISCONNECT_RSP");
1647 case L2CEVT_L2CAP_DATA: /* Peer data */
1648 return ("PEER_DATA");
1649
1650 case L2CEVT_L2CA_CONNECT_REQ: /* Upper layer connect request */
1651 return ("UPPER_LAYER_CONNECT_REQ");
1652 case L2CEVT_L2CA_CONNECT_RSP: /* Upper layer connect response */
1653 return ("UPPER_LAYER_CONNECT_RSP");
1654 case L2CEVT_L2CA_CONNECT_RSP_NEG: /* Upper layer connect response (failed)*/
1655 return ("UPPER_LAYER_CONNECT_RSP_NEG");
1656 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config request */
1657 return ("UPPER_LAYER_CONFIG_REQ");
1658 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config response */
1659 return ("UPPER_LAYER_CONFIG_RSP");
1660 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper layer disconnect request */
1661 return ("UPPER_LAYER_DISCONNECT_REQ");
1662 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper layer disconnect response */
1663 return ("UPPER_LAYER_DISCONNECT_RSP");
1664 case L2CEVT_L2CA_DATA_READ: /* Upper layer data read */
1665 return ("UPPER_LAYER_DATA_READ");
1666 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data write */
1667 return ("UPPER_LAYER_DATA_WRITE");
1668 case L2CEVT_TIMEOUT: /* Timeout */
1669 return ("TIMEOUT");
1670 case L2CEVT_SEC_RE_SEND_CMD:
1671 return ("SEC_RE_SEND_CMD");
1672 case L2CEVT_L2CAP_INFO_RSP: /* Peer information response */
1673 return ("L2CEVT_L2CAP_INFO_RSP");
1674 case L2CEVT_ACK_TIMEOUT:
1675 return ("L2CEVT_ACK_TIMEOUT");
1676 case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT: /* Upper layer send credit packet
1677 */
1678 return ("SEND_FLOW_CONTROL_CREDIT");
1679 case L2CEVT_L2CA_CREDIT_BASED_CONNECT_REQ: /* Upper layer credit based
1680 connect request */
1681 return ("SEND_CREDIT_BASED_CONNECT_REQ");
1682 case L2CEVT_L2CA_CREDIT_BASED_CONNECT_RSP: /* Upper layer credit based
1683 connect response */
1684 return ("SEND_CREDIT_BASED_CONNECT_RSP");
1685 case L2CEVT_L2CA_CREDIT_BASED_CONNECT_RSP_NEG: /* Upper layer credit based
1686 connect response
1687 (failed)*/
1688 return ("SEND_CREDIT_BASED_CONNECT_RSP_NEG");
1689 case L2CEVT_L2CA_CREDIT_BASED_RECONFIG_REQ: /* Upper layer credit based
1690 reconfig request */
1691 return ("SEND_CREDIT_BASED_RECONFIG_REQ");
1692 case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT: /* Peer send credit packet */
1693 return ("RECV_FLOW_CONTROL_CREDIT");
1694 case L2CEVT_L2CAP_CREDIT_BASED_CONNECT_REQ: /* Peer send credit based
1695 connect request */
1696 return ("RECV_CREDIT_BASED_CONNECT_REQ");
1697 case L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP: /* Peer send credit based
1698 connect response */
1699 return ("RECV_CREDIT_BASED_CONNECT_RSP");
1700 case L2CEVT_L2CAP_CREDIT_BASED_CONNECT_RSP_NEG: /* Peer send reject credit
1701 based connect response */
1702 return ("RECV_CREDIT_BASED_CONNECT_RSP_NEG");
1703 case L2CEVT_L2CAP_CREDIT_BASED_RECONFIG_REQ: /* Peer send credit based
1704 reconfig request */
1705 return ("RECV_CREDIT_BASED_RECONFIG_REQ");
1706 case L2CEVT_L2CAP_CREDIT_BASED_RECONFIG_RSP: /* Peer send credit based
1707 reconfig response */
1708 return ("RECV_CREDIT_BASED_RECONFIG_RSP");
1709 default:
1710 return ("???? UNKNOWN EVENT");
1711 }
1712 }
1713
1714 /*******************************************************************************
1715 *
1716 * Function l2c_enqueue_peer_data
1717 *
1718 * Description Enqueues data destined for the peer in the ccb. Handles
1719 * FCR segmentation and checks for congestion.
1720 *
1721 * Returns void
1722 *
1723 ******************************************************************************/
l2c_enqueue_peer_data(tL2C_CCB * p_ccb,BT_HDR * p_buf)1724 void l2c_enqueue_peer_data(tL2C_CCB* p_ccb, BT_HDR* p_buf) {
1725 log::assert_that(p_ccb != nullptr, "assert failed: p_ccb != nullptr");
1726
1727 p_ccb->metrics.tx(p_buf->len);
1728
1729 uint8_t* p;
1730
1731 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
1732 p_buf->event = 0;
1733 } else {
1734 /* Save the channel ID for faster counting */
1735 p_buf->event = p_ccb->local_cid;
1736
1737 /* Step back to add the L2CAP header */
1738 p_buf->offset -= L2CAP_PKT_OVERHEAD;
1739 p_buf->len += L2CAP_PKT_OVERHEAD;
1740
1741 /* Set the pointer to the beginning of the data */
1742 p = (uint8_t*)(p_buf + 1) + p_buf->offset;
1743
1744 /* Now the L2CAP header */
1745 UINT16_TO_STREAM(p, p_buf->len - L2CAP_PKT_OVERHEAD);
1746 UINT16_TO_STREAM(p, p_ccb->remote_cid);
1747 }
1748
1749 if (p_ccb->xmit_hold_q == NULL) {
1750 log::error(
1751 "empty queue: p_ccb = {} p_ccb->in_use = {} p_ccb->chnl_state = {} "
1752 "p_ccb->local_cid = {} p_ccb->remote_cid = {}",
1753 fmt::ptr(p_ccb), p_ccb->in_use, p_ccb->chnl_state, p_ccb->local_cid,
1754 p_ccb->remote_cid);
1755 } else {
1756 fixed_queue_enqueue(p_ccb->xmit_hold_q, p_buf);
1757 }
1758
1759 l2cu_check_channel_congestion(p_ccb);
1760
1761 /* if new packet is higher priority than serving ccb and it is not overrun */
1762 if ((p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority) &&
1763 (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0)) {
1764 /* send out higher priority packet */
1765 p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;
1766 }
1767
1768 /* if we are doing a round robin scheduling, set the flag */
1769 if (p_ccb->p_lcb->link_xmit_quota == 0) l2cb.check_round_robin = true;
1770 }
1771