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