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