• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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