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