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