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