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