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