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