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