blob: 994f0ae6420eee2b73d6e1d1608e4d5ca9fac9d6 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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/********************************************************************************/
42static void l2c_csm_closed (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
43static void l2c_csm_orig_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
44static void l2c_csm_term_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
45static void l2c_csm_w4_l2cap_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
46static void l2c_csm_w4_l2ca_connect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
47static void l2c_csm_config (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
48static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
49static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
50static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data);
51
52#if (BT_TRACE_VERBOSE == TRUE)
53static 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*******************************************************************************/
65void 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:
Kim Schulz8372aa52015-03-25 10:39:40 +0100106 L2CAP_TRACE_DEBUG("Unhandled event! event = %d",event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800107 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*******************************************************************************/
122static 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)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700132 L2CAP_TRACE_ERROR ("L2CAP - LCID: 0x%04x st: CLOSED evt: %s p_rcb == NULL", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800133#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700134 L2CAP_TRACE_ERROR ("L2CAP - LCID: 0x%04x st: CLOSED evt: 0x%04x p_rcb == NULL", p_ccb->local_cid, event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800135#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)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700155 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: CLOSED evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800156#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700157 L2CAP_TRACE_EVENT ("L2CAP - st: CLOSED evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800158#endif
159
160 switch (event)
161 {
162 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700163 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800164 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 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700179 L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, p_ci->status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800180 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 */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800187 {
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
194Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details]
195Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details]
196Event 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 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800202
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 */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700230 L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800231 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 */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800240 {
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
247Event uninit_use_in_call: Using uninitialized value "settings" (field "settings".timeout uninitialized) in call to function "BTM_SetPowerMode" [details]
248Event uninit_use_in_call: Using uninitialized value "settings.max" in call to function "BTM_SetPowerMode" [details]
249Event 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 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800255
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:
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700266 L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, L2CAP_CONN_TIMEOUT);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800267 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*******************************************************************************/
293static 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)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700300 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: ORIG_W4_SEC_COMP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800301#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700302 L2CAP_TRACE_EVENT ("L2CAP - st: ORIG_W4_SEC_COMP evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800303#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 */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700320 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800321 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:
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700351 L2CAP_TRACE_API ("L2CAP - Calling ConnectCfm_Cb(), CID: 0x%04x Status: %d", p_ccb->local_cid, HCI_ERR_AUTH_FAILURE);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800352
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*******************************************************************************/
389static void l2c_csm_term_w4_sec_comp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
390{
391#if (BT_TRACE_VERBOSE == TRUE)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700392 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: TERM_W4_SEC_COMP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800393#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700394 L2CAP_TRACE_EVENT ("L2CAP - st: TERM_W4_SEC_COMP evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800395#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);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700426 L2CAP_TRACE_API ("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800427
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 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700482 L2CAP_TRACE_API ("L2CAP - Calling btsnd_hcic_disconnect for handle %i failed", p_ccb->p_lcb->handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800483 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*******************************************************************************/
505static 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)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700513 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CAP_CON_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800514#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700515 L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_CON_RSP evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800516#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 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700526 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800527 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);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700538 L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Success", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800539
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 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700548 L2CAP_TRACE_API ("L2CAP - Calling Connect_Pnd_Cb(), CID: 0x%04x", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800549 (*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 */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700554 L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Failure Code: %d", p_ccb->local_cid, p_ci->l2cap_result);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800555 l2cu_release_ccb (p_ccb);
556 (*connect_cfm)(local_cid, p_ci->l2cap_result);
557 break;
558
559 case L2CEVT_TIMEOUT:
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700560 L2CAP_TRACE_API ("L2CAP - Calling Connect_Cfm_Cb(), CID: 0x%04x, Timeout", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800561 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*******************************************************************************/
610static 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)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700617 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CA_CON_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800618#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700619 L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_CON_RSP evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800620#endif
621
622 switch (event)
623 {
624 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700625 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800626 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);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700656 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800657 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);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700675 L2CAP_TRACE_API ("L2CAP - Calling Connect_Ind_Cb(), CID: 0x%04x", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800676
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*******************************************************************************/
696static 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)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700704 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: CONFIG evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800705#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700706 L2CAP_TRACE_EVENT ("L2CAP - st: CONFIG evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800707#endif
708
709 switch (event)
710 {
711 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700712 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800713 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 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700721 L2CAP_TRACE_EVENT ("L2CAP - Calling Config_Req_Cb(), CID: 0x%04x, C-bit %d",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800722 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 */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700728 L2CAP_TRACE_EVENT ("L2CAP - incompatible configurations disconnect");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800729 l2cu_disconnect_chnl (p_ccb);
730 }
731 else /* Return error to peer so he can renegotiate if possible */
732 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700733 L2CAP_TRACE_EVENT ("L2CAP - incompatible configurations trying reconfig");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800734 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);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700756 L2CAP_TRACE_WARNING ("L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800757 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)
Pavlin Radoslavovc196f212015-09-23 20:39:53 -0700782 p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800783#endif
784 /* See if we can forward anything on the hold queue */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700785 if (!fixed_queue_is_empty(p_ccb->xmit_hold_q))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800786 {
787 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
788 }
789 }
790 }
791
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700792 L2CAP_TRACE_API ("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800793 (*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 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700803 L2CAP_TRACE_API ("L2CAP - Calling Config_Rsp_Cb(), CID: 0x%04x, Failure: %d", p_ccb->local_cid, p_cfg->result);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800804 (*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;
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700811 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800812 (*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);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700845 L2CAP_TRACE_WARNING ("L2CAP - Calling Disconnect_Ind_Cb(Incompatible CFG), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800846 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)
Pavlin Radoslavovc196f212015-09-23 20:39:53 -0700864 p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800865#endif
866
867 /* See if we can forward anything on the hold queue */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700868 if ( (p_ccb->chnl_state == CST_OPEN) &&
869 (!fixed_queue_is_empty(p_ccb->xmit_hold_q)))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800870 {
871 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
872 }
873 break;
874
875 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config reject */
876 l2cu_send_peer_config_rsp (p_ccb, p_cfg);
877 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
878 break;
879
880 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
881 l2cu_send_peer_disc_req (p_ccb);
882 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
883 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
884 break;
885
886 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700887 L2CAP_TRACE_API ("L2CAP - Calling DataInd_Cb(), CID: 0x%04x", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800888#if (L2CAP_NUM_FIXED_CHNLS > 0)
Kim Schulz2a2701c2013-09-16 15:59:33 +0200889 if (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL &&
890 p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800891 {
Kim Schulz2a2701c2013-09-16 15:59:33 +0200892 if (p_ccb->local_cid < L2CAP_BASE_APPL_CID)
893 {
894 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
Kim Schulz8372aa52015-03-25 10:39:40 +0100895 (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
896 (p_ccb->local_cid, p_ccb->p_lcb->remote_bd_addr,(BT_HDR *)p_data);
Kim Schulz2a2701c2013-09-16 15:59:33 +0200897 else
898 GKI_freebuf (p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800899 break;
Kim Schulz2a2701c2013-09-16 15:59:33 +0200900 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800901 }
902#endif
903 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
904 break;
905
906 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
907 if (p_ccb->config_done & OB_CFG_DONE)
908 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
909 else
910 GKI_freebuf (p_data);
911 break;
912
913 case L2CEVT_TIMEOUT:
914 l2cu_send_peer_disc_req (p_ccb);
Kim Schulz8372aa52015-03-25 10:39:40 +0100915 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
916 p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800917 l2cu_release_ccb (p_ccb);
918 (*disconnect_ind)(local_cid, FALSE);
919 break;
920 }
921}
922
923
924/*******************************************************************************
925**
926** Function l2c_csm_open
927**
928** Description This function handles events when the channel is in
929** OPEN state.
930**
931** Returns void
932**
933*******************************************************************************/
934static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
935{
936 UINT16 local_cid = p_ccb->local_cid;
937 tL2CAP_CFG_INFO *p_cfg;
938 tL2C_CHNL_STATE tempstate;
939 UINT8 tempcfgdone;
940 UINT8 cfg_result;
941
942#if (BT_TRACE_VERBOSE == TRUE)
Kim Schulz8372aa52015-03-25 10:39:40 +0100943 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: OPEN evt: %s",
944 p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800945#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -0700946 L2CAP_TRACE_EVENT ("L2CAP - st: OPEN evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800947#endif
948
949#if (L2CAP_UCD_INCLUDED == TRUE)
950 if ( local_cid == L2CAP_CONNECTIONLESS_CID )
951 {
952 /* check if this event can be processed by UCD */
953 if ( l2c_ucd_process_event (p_ccb, event, p_data) )
954 {
955 /* The event is processed by UCD state machine */
956 return;
957 }
958 }
959#endif
960
961 switch (event)
962 {
963 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
Kim Schulz8372aa52015-03-25 10:39:40 +0100964 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed",
965 p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800966 l2cu_release_ccb (p_ccb);
967 if (p_ccb->p_rcb)
968 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, FALSE);
969 break;
970
971 case L2CEVT_LP_QOS_VIOLATION_IND: /* QOS violation */
972 /* Tell upper layer. If service guaranteed, then clear the channel */
973 if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)
974 (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(p_ccb->p_lcb->remote_bd_addr);
975 break;
976
977 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
978 p_cfg = (tL2CAP_CFG_INFO *)p_data;
979
980 tempstate = p_ccb->chnl_state;
981 tempcfgdone = p_ccb->config_done;
982 p_ccb->chnl_state = CST_CONFIG;
983 p_ccb->config_done &= ~CFG_DONE_MASK;
984
985 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
986
987 if ((cfg_result = l2cu_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_OK)
988 {
989 (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
990 }
991
992 /* Error in config parameters: reset state and config flag */
993 else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE)
994 {
995 btu_stop_timer(&p_ccb->timer_entry);
996 p_ccb->chnl_state = tempstate;
997 p_ccb->config_done = tempcfgdone;
998 l2cu_send_peer_config_rsp (p_ccb, p_cfg);
999 }
1000 else /* L2CAP_PEER_CFG_DISCONNECT */
1001 {
1002 /* Disconnect if channels are incompatible
1003 * Note this should not occur if reconfigure
1004 * since this should have never passed original config.
1005 */
1006 l2cu_disconnect_chnl (p_ccb);
1007 }
1008 break;
1009
1010 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
1011// btla-specific ++
1012 /* Make sure we are not in sniff mode */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001013 {
1014 tBTM_PM_PWR_MD settings;
Adam Hampsonf6418a12014-05-16 16:41:22 -07001015 memset((void*)&settings, 0, sizeof(settings));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001016 settings.mode = BTM_PM_MD_ACTIVE;
1017 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
1018 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001019// btla-specific --
1020
1021 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
1022 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001023 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001024 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE);
1025 break;
1026
1027 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
Srinu Jella780afa32014-05-30 21:15:01 +05301028 if((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb))
1029 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001030 break;
1031
1032 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
1033 /* Make sure we are not in sniff mode */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001034 {
1035 tBTM_PM_PWR_MD settings;
Adam Hampsonf6418a12014-05-16 16:41:22 -07001036 memset((void*)&settings, 0, sizeof(settings));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001037 settings.mode = BTM_PM_MD_ACTIVE;
1038 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
1039 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001040
1041 l2cu_send_peer_disc_req (p_ccb);
1042 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
1043 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
1044 break;
1045
1046 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1047 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
1048 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
1049 break;
1050
1051 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
1052 p_ccb->chnl_state = CST_CONFIG;
1053 p_ccb->config_done &= ~CFG_DONE_MASK;
1054 l2cu_process_our_cfg_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
1055 l2cu_send_peer_config_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
1056 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
1057 break;
1058
1059 case L2CEVT_TIMEOUT:
1060 /* Process the monitor/retransmission time-outs in flow control/retrans mode */
1061 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
1062 l2c_fcr_proc_tout (p_ccb);
1063 break;
1064
1065 case L2CEVT_ACK_TIMEOUT:
1066 l2c_fcr_proc_ack_tout (p_ccb);
1067 break;
1068 }
1069}
1070
1071
1072/*******************************************************************************
1073**
1074** Function l2c_csm_w4_l2cap_disconnect_rsp
1075**
1076** Description This function handles events when the channel is in
1077** CST_W4_L2CAP_DISCONNECT_RSP state.
1078**
1079** Returns void
1080**
1081*******************************************************************************/
1082static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
1083{
1084 tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
1085 UINT16 local_cid = p_ccb->local_cid;
1086
1087#if (BT_TRACE_VERBOSE == TRUE)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001088 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CAP_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001089#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001090 L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001091#endif
1092
1093 switch (event)
1094 {
1095 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1096 l2cu_release_ccb (p_ccb);
1097 if (disconnect_cfm)
1098 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001099 L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001100 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1101 }
1102 break;
1103
1104 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1105 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
1106 l2cu_release_ccb (p_ccb);
1107 if (disconnect_cfm)
1108 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001109 L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001110 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1111 }
1112 break;
1113
1114 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1115 case L2CEVT_TIMEOUT: /* Timeout */
1116 l2cu_release_ccb (p_ccb);
1117 if (disconnect_cfm)
1118 {
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001119 L2CAP_TRACE_API ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001120 (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT);
1121 }
1122 break;
1123
1124 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1125 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1126 GKI_freebuf (p_data);
1127 break;
1128 }
1129}
1130
1131
1132/*******************************************************************************
1133**
1134** Function l2c_csm_w4_l2ca_disconnect_rsp
1135**
1136** Description This function handles events when the channel is in
1137** CST_W4_L2CA_DISCONNECT_RSP state.
1138**
1139** Returns void
1140**
1141*******************************************************************************/
1142static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
1143{
1144 tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1145 UINT16 local_cid = p_ccb->local_cid;
1146
1147#if (BT_TRACE_VERBOSE == TRUE)
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001148 L2CAP_TRACE_EVENT ("L2CAP - LCID: 0x%04x st: W4_L2CA_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001149#else
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001150 L2CAP_TRACE_EVENT ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001151#endif
1152
1153 switch (event)
1154 {
1155 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001156 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001157 l2cu_release_ccb (p_ccb);
1158 (*disconnect_ind)(local_cid, FALSE);
1159 break;
1160
1161 case L2CEVT_TIMEOUT:
1162 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
Sharvil Nanavatia51c9d92014-05-04 01:08:21 -07001163 L2CAP_TRACE_API ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001164 l2cu_release_ccb (p_ccb);
1165 (*disconnect_ind)(local_cid, FALSE);
1166 break;
1167
1168 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper disconnect request */
1169 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper disconnect response */
1170 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
1171 l2cu_release_ccb (p_ccb);
1172 break;
1173
1174 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1175 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1176 GKI_freebuf (p_data);
1177 break;
1178 }
1179}
1180
1181
1182#if (BT_TRACE_VERBOSE == TRUE)
1183/*******************************************************************************
1184**
1185** Function l2c_csm_get_event_name
1186**
1187** Description This function returns the event name.
1188**
1189** NOTE conditionally compiled to save memory.
1190**
1191** Returns pointer to the name
1192**
1193*******************************************************************************/
1194static char *l2c_csm_get_event_name (UINT16 event)
1195{
1196 switch (event)
1197 {
1198 case L2CEVT_LP_CONNECT_CFM: /* Lower layer connect confirm */
1199 return ("LOWER_LAYER_CONNECT_CFM");
1200 case L2CEVT_LP_CONNECT_CFM_NEG: /* Lower layer connect confirm (failed) */
1201 return ("LOWER_LAYER_CONNECT_CFM_NEG");
1202 case L2CEVT_LP_CONNECT_IND: /* Lower layer connect indication */
1203 return ("LOWER_LAYER_CONNECT_IND");
1204 case L2CEVT_LP_DISCONNECT_IND: /* Lower layer disconnect indication */
1205 return ("LOWER_LAYER_DISCONNECT_IND");
1206 case L2CEVT_LP_QOS_CFM: /* Lower layer QOS confirmation */
1207 return ("LOWER_LAYER_QOS_CFM");
1208 case L2CEVT_LP_QOS_CFM_NEG: /* Lower layer QOS confirmation (failed)*/
1209 return ("LOWER_LAYER_QOS_CFM_NEG");
1210 case L2CEVT_LP_QOS_VIOLATION_IND: /* Lower layer QOS violation indication */
1211 return ("LOWER_LAYER_QOS_VIOLATION_IND");
1212
1213 case L2CEVT_SEC_COMP: /* Security cleared successfully */
1214 return ("SECURITY_COMPLETE");
1215 case L2CEVT_SEC_COMP_NEG: /* Security procedure failed */
1216 return ("SECURITY_COMPLETE_NEG");
1217
1218 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connection request */
1219 return ("PEER_CONNECT_REQ");
1220 case L2CEVT_L2CAP_CONNECT_RSP: /* Peer connection response */
1221 return ("PEER_CONNECT_RSP");
1222 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Peer connection response pending */
1223 return ("PEER_CONNECT_RSP_PND");
1224 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer connection response (failed) */
1225 return ("PEER_CONNECT_RSP_NEG");
1226 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer configuration request */
1227 return ("PEER_CONFIG_REQ");
1228 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer configuration response */
1229 return ("PEER_CONFIG_RSP");
1230 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer configuration response (failed) */
1231 return ("PEER_CONFIG_RSP_NEG");
1232 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1233 return ("PEER_DISCONNECT_REQ");
1234 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1235 return ("PEER_DISCONNECT_RSP");
1236 case L2CEVT_L2CAP_DATA: /* Peer data */
1237 return ("PEER_DATA");
1238
1239 case L2CEVT_L2CA_CONNECT_REQ: /* Upper layer connect request */
1240 return ("UPPER_LAYER_CONNECT_REQ");
1241 case L2CEVT_L2CA_CONNECT_RSP: /* Upper layer connect response */
1242 return ("UPPER_LAYER_CONNECT_RSP");
1243 case L2CEVT_L2CA_CONNECT_RSP_NEG: /* Upper layer connect response (failed)*/
1244 return ("UPPER_LAYER_CONNECT_RSP_NEG");
1245 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config request */
1246 return ("UPPER_LAYER_CONFIG_REQ");
1247 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config response */
1248 return ("UPPER_LAYER_CONFIG_RSP");
1249 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config response (failed) */
1250 return ("UPPER_LAYER_CONFIG_RSP_NEG");
1251 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper layer disconnect request */
1252 return ("UPPER_LAYER_DISCONNECT_REQ");
1253 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper layer disconnect response */
1254 return ("UPPER_LAYER_DISCONNECT_RSP");
1255 case L2CEVT_L2CA_DATA_READ: /* Upper layer data read */
1256 return ("UPPER_LAYER_DATA_READ");
1257 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data write */
1258 return ("UPPER_LAYER_DATA_WRITE");
1259 case L2CEVT_TIMEOUT: /* Timeout */
1260 return ("TIMEOUT");
1261 case L2CEVT_SEC_RE_SEND_CMD:
1262 return ("SEC_RE_SEND_CMD");
1263 case L2CEVT_L2CAP_INFO_RSP: /* Peer information response */
1264 return ("L2CEVT_L2CAP_INFO_RSP");
1265 case L2CEVT_ACK_TIMEOUT:
1266 return ("L2CEVT_ACK_TIMEOUT");
1267
1268 default:
1269 return ("???? UNKNOWN EVENT");
1270 }
1271}
1272#endif /* (BT_TRACE_VERBOSE == TRUE) */
1273
1274
1275/*******************************************************************************
1276**
1277** Function l2c_enqueue_peer_data
1278**
1279** Description Enqueues data destined for the peer in the ccb. Handles
1280** FCR segmentation and checks for congestion.
1281**
1282** Returns void
1283**
1284*******************************************************************************/
1285void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf)
1286{
1287 UINT8 *p;
1288
1289 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
1290 {
1291 p_buf->event = 0;
1292 }
1293 else
1294 {
1295 /* Save the channel ID for faster counting */
1296 p_buf->event = p_ccb->local_cid;
1297
1298 /* Step back to add the L2CAP header */
1299 p_buf->offset -= L2CAP_PKT_OVERHEAD;
1300 p_buf->len += L2CAP_PKT_OVERHEAD;
1301
1302 /* Set the pointer to the beginning of the data */
1303 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1304
1305 /* Now the L2CAP header */
1306 UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD);
1307 UINT16_TO_STREAM (p, p_ccb->remote_cid);
1308 }
1309
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001310 fixed_queue_enqueue(p_ccb->xmit_hold_q, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001311
1312 l2cu_check_channel_congestion (p_ccb);
1313
1314#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1315 /* if new packet is higher priority than serving ccb and it is not overrun */
1316 if (( p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority )
1317 &&( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0))
1318 {
1319 /* send out higher priority packet */
1320 p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;
1321 }
1322#endif
1323
1324 /* if we are doing a round robin scheduling, set the flag */
1325 if (p_ccb->p_lcb->link_xmit_quota == 0)
1326 l2cb.check_round_robin = TRUE;
1327}
1328
1329