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