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_ERROR2 ("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_ERROR2 ("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_EVENT2 ("L2CAP - LCID: 0x%04x st: CLOSED evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
155 #else
156 L2CAP_TRACE_EVENT1 ("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_API1 ("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_API2 ("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_API2 ("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_API2 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API2 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API1 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API1 ("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_API1 ("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_API2 ("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_API1 ("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_EVENT2 ("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_EVENT1 ("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_API1 ("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_API1 ("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_API1 ("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_EVENT2 ("L2CAP - LCID: 0x%04x st: CONFIG evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
712 #else
713 L2CAP_TRACE_EVENT1 ("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_API1 ("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_EVENT2 ("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_EVENT0 ("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_EVENT0 ("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_WARNING1 ("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_API1 ("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_API2 ("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_API1 ("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_WARNING1 ("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_API1 ("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_BASE_APPL_CID)
896 {
897 if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
898 (*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);
899 else
900 GKI_freebuf (p_data);
901
902 break;
903 }
904 #endif
905 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
906 break;
907
908 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
909 if (p_ccb->config_done & OB_CFG_DONE)
910 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
911 else
912 GKI_freebuf (p_data);
913 break;
914
915 case L2CEVT_TIMEOUT:
916 l2cu_send_peer_disc_req (p_ccb);
917 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
918 l2cu_release_ccb (p_ccb);
919 (*disconnect_ind)(local_cid, FALSE);
920 break;
921 }
922 }
923
924
925 /*******************************************************************************
926 **
927 ** Function l2c_csm_open
928 **
929 ** Description This function handles events when the channel is in
930 ** OPEN state.
931 **
932 ** Returns void
933 **
934 *******************************************************************************/
l2c_csm_open(tL2C_CCB * p_ccb,UINT16 event,void * p_data)935 static void l2c_csm_open (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
936 {
937 UINT16 local_cid = p_ccb->local_cid;
938 tL2CAP_CFG_INFO *p_cfg;
939 tL2C_CHNL_STATE tempstate;
940 UINT8 tempcfgdone;
941 UINT8 cfg_result;
942
943 #if (BT_TRACE_VERBOSE == TRUE)
944 L2CAP_TRACE_EVENT2 ("L2CAP - LCID: 0x%04x st: OPEN evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
945 #else
946 L2CAP_TRACE_EVENT1 ("L2CAP - st: OPEN evt: %d", event);
947 #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 */
964 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
965 l2cu_release_ccb (p_ccb);
966 if (p_ccb->p_rcb)
967 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, FALSE);
968 break;
969
970 case L2CEVT_LP_QOS_VIOLATION_IND: /* QOS violation */
971 /* Tell upper layer. If service guaranteed, then clear the channel */
972 if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)
973 (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(p_ccb->p_lcb->remote_bd_addr);
974 break;
975
976 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request */
977 p_cfg = (tL2CAP_CFG_INFO *)p_data;
978
979 tempstate = p_ccb->chnl_state;
980 tempcfgdone = p_ccb->config_done;
981 p_ccb->chnl_state = CST_CONFIG;
982 p_ccb->config_done &= ~CFG_DONE_MASK;
983
984 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
985
986 if ((cfg_result = l2cu_process_peer_cfg_req (p_ccb, p_cfg)) == L2CAP_PEER_CFG_OK)
987 {
988 (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
989 }
990
991 /* Error in config parameters: reset state and config flag */
992 else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE)
993 {
994 btu_stop_timer(&p_ccb->timer_entry);
995 p_ccb->chnl_state = tempstate;
996 p_ccb->config_done = tempcfgdone;
997 l2cu_send_peer_config_rsp (p_ccb, p_cfg);
998 }
999 else /* L2CAP_PEER_CFG_DISCONNECT */
1000 {
1001 /* Disconnect if channels are incompatible
1002 * Note this should not occur if reconfigure
1003 * since this should have never passed original config.
1004 */
1005 l2cu_disconnect_chnl (p_ccb);
1006 }
1007 break;
1008
1009 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
1010 // btla-specific ++
1011 /* Make sure we are not in sniff mode */
1012 #if BTM_PWR_MGR_INCLUDED == TRUE
1013 {
1014 tBTM_PM_PWR_MD settings;
1015 settings.mode = BTM_PM_MD_ACTIVE;
1016 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
1017 }
1018 #else
1019 BTM_CancelSniffMode (p_ccb->p_lcb->remote_bd_addr);
1020 #endif
1021 // btla-specific --
1022
1023 p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
1024 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
1025 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x Conf Needed", p_ccb->local_cid);
1026 (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, TRUE);
1027 break;
1028
1029 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1030 (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR *)p_data);
1031 break;
1032
1033 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
1034 /* Make sure we are not in sniff mode */
1035 #if BTM_PWR_MGR_INCLUDED == TRUE
1036 {
1037 tBTM_PM_PWR_MD settings;
1038 settings.mode = BTM_PM_MD_ACTIVE;
1039 BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr, &settings);
1040 }
1041 #else
1042 BTM_CancelSniffMode (p_ccb->p_lcb->remote_bd_addr);
1043 #endif
1044
1045 l2cu_send_peer_disc_req (p_ccb);
1046 p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
1047 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_DISCONNECT_TOUT);
1048 break;
1049
1050 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1051 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_data);
1052 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
1053 break;
1054
1055 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req */
1056 p_ccb->chnl_state = CST_CONFIG;
1057 p_ccb->config_done &= ~CFG_DONE_MASK;
1058 l2cu_process_our_cfg_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
1059 l2cu_send_peer_config_req (p_ccb, (tL2CAP_CFG_INFO *)p_data);
1060 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_L2CAP_CHNL, L2CAP_CHNL_CFG_TIMEOUT);
1061 break;
1062
1063 case L2CEVT_TIMEOUT:
1064 /* Process the monitor/retransmission time-outs in flow control/retrans mode */
1065 if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
1066 l2c_fcr_proc_tout (p_ccb);
1067 break;
1068
1069 case L2CEVT_ACK_TIMEOUT:
1070 l2c_fcr_proc_ack_tout (p_ccb);
1071 break;
1072 }
1073 }
1074
1075
1076 /*******************************************************************************
1077 **
1078 ** Function l2c_csm_w4_l2cap_disconnect_rsp
1079 **
1080 ** Description This function handles events when the channel is in
1081 ** CST_W4_L2CAP_DISCONNECT_RSP state.
1082 **
1083 ** Returns void
1084 **
1085 *******************************************************************************/
l2c_csm_w4_l2cap_disconnect_rsp(tL2C_CCB * p_ccb,UINT16 event,void * p_data)1086 static void l2c_csm_w4_l2cap_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
1087 {
1088 tL2CA_DISCONNECT_CFM_CB *disconnect_cfm = p_ccb->p_rcb->api.pL2CA_DisconnectCfm_Cb;
1089 UINT16 local_cid = p_ccb->local_cid;
1090
1091 #if (BT_TRACE_VERBOSE == TRUE)
1092 L2CAP_TRACE_EVENT2 ("L2CAP - LCID: 0x%04x st: W4_L2CAP_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
1093 #else
1094 L2CAP_TRACE_EVENT1 ("L2CAP - st: W4_L2CAP_DISC_RSP evt: %d", event);
1095 #endif
1096
1097 switch (event)
1098 {
1099 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1100 l2cu_release_ccb (p_ccb);
1101 if (disconnect_cfm)
1102 {
1103 L2CAP_TRACE_API1 ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
1104 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1105 }
1106 break;
1107
1108 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1109 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
1110 l2cu_release_ccb (p_ccb);
1111 if (disconnect_cfm)
1112 {
1113 L2CAP_TRACE_API1 ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
1114 (*disconnect_cfm)(local_cid, L2CAP_DISC_OK);
1115 }
1116 break;
1117
1118 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1119 case L2CEVT_TIMEOUT: /* Timeout */
1120 l2cu_release_ccb (p_ccb);
1121 if (disconnect_cfm)
1122 {
1123 L2CAP_TRACE_API1 ("L2CAP - Calling DisconnectCfm_Cb(), CID: 0x%04x", local_cid);
1124 (*disconnect_cfm)(local_cid, L2CAP_DISC_TIMEOUT);
1125 }
1126 break;
1127
1128 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1129 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1130 GKI_freebuf (p_data);
1131 break;
1132 }
1133 }
1134
1135
1136 /*******************************************************************************
1137 **
1138 ** Function l2c_csm_w4_l2ca_disconnect_rsp
1139 **
1140 ** Description This function handles events when the channel is in
1141 ** CST_W4_L2CA_DISCONNECT_RSP state.
1142 **
1143 ** Returns void
1144 **
1145 *******************************************************************************/
l2c_csm_w4_l2ca_disconnect_rsp(tL2C_CCB * p_ccb,UINT16 event,void * p_data)1146 static void l2c_csm_w4_l2ca_disconnect_rsp (tL2C_CCB *p_ccb, UINT16 event, void *p_data)
1147 {
1148 tL2CA_DISCONNECT_IND_CB *disconnect_ind = p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
1149 UINT16 local_cid = p_ccb->local_cid;
1150
1151 #if (BT_TRACE_VERBOSE == TRUE)
1152 L2CAP_TRACE_EVENT2 ("L2CAP - LCID: 0x%04x st: W4_L2CA_DISC_RSP evt: %s", p_ccb->local_cid, l2c_csm_get_event_name (event));
1153 #else
1154 L2CAP_TRACE_EVENT1 ("L2CAP - st: W4_L2CA_DISC_RSP evt: %d", event);
1155 #endif
1156
1157 switch (event)
1158 {
1159 case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
1160 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
1161 l2cu_release_ccb (p_ccb);
1162 (*disconnect_ind)(local_cid, FALSE);
1163 break;
1164
1165 case L2CEVT_TIMEOUT:
1166 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
1167 L2CAP_TRACE_API1 ("L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x No Conf Needed", p_ccb->local_cid);
1168 l2cu_release_ccb (p_ccb);
1169 (*disconnect_ind)(local_cid, FALSE);
1170 break;
1171
1172 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper disconnect request */
1173 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper disconnect response */
1174 l2cu_send_peer_disc_rsp (p_ccb->p_lcb, p_ccb->remote_id, p_ccb->local_cid, p_ccb->remote_cid);
1175 l2cu_release_ccb (p_ccb);
1176 break;
1177
1178 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1179 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1180 GKI_freebuf (p_data);
1181 break;
1182 }
1183 }
1184
1185
1186 #if (BT_TRACE_VERBOSE == TRUE)
1187 /*******************************************************************************
1188 **
1189 ** Function l2c_csm_get_event_name
1190 **
1191 ** Description This function returns the event name.
1192 **
1193 ** NOTE conditionally compiled to save memory.
1194 **
1195 ** Returns pointer to the name
1196 **
1197 *******************************************************************************/
l2c_csm_get_event_name(UINT16 event)1198 static char *l2c_csm_get_event_name (UINT16 event)
1199 {
1200 switch (event)
1201 {
1202 case L2CEVT_LP_CONNECT_CFM: /* Lower layer connect confirm */
1203 return ("LOWER_LAYER_CONNECT_CFM");
1204 case L2CEVT_LP_CONNECT_CFM_NEG: /* Lower layer connect confirm (failed) */
1205 return ("LOWER_LAYER_CONNECT_CFM_NEG");
1206 case L2CEVT_LP_CONNECT_IND: /* Lower layer connect indication */
1207 return ("LOWER_LAYER_CONNECT_IND");
1208 case L2CEVT_LP_DISCONNECT_IND: /* Lower layer disconnect indication */
1209 return ("LOWER_LAYER_DISCONNECT_IND");
1210 case L2CEVT_LP_QOS_CFM: /* Lower layer QOS confirmation */
1211 return ("LOWER_LAYER_QOS_CFM");
1212 case L2CEVT_LP_QOS_CFM_NEG: /* Lower layer QOS confirmation (failed)*/
1213 return ("LOWER_LAYER_QOS_CFM_NEG");
1214 case L2CEVT_LP_QOS_VIOLATION_IND: /* Lower layer QOS violation indication */
1215 return ("LOWER_LAYER_QOS_VIOLATION_IND");
1216
1217 case L2CEVT_SEC_COMP: /* Security cleared successfully */
1218 return ("SECURITY_COMPLETE");
1219 case L2CEVT_SEC_COMP_NEG: /* Security procedure failed */
1220 return ("SECURITY_COMPLETE_NEG");
1221
1222 case L2CEVT_L2CAP_CONNECT_REQ: /* Peer connection request */
1223 return ("PEER_CONNECT_REQ");
1224 case L2CEVT_L2CAP_CONNECT_RSP: /* Peer connection response */
1225 return ("PEER_CONNECT_RSP");
1226 case L2CEVT_L2CAP_CONNECT_RSP_PND: /* Peer connection response pending */
1227 return ("PEER_CONNECT_RSP_PND");
1228 case L2CEVT_L2CAP_CONNECT_RSP_NEG: /* Peer connection response (failed) */
1229 return ("PEER_CONNECT_RSP_NEG");
1230 case L2CEVT_L2CAP_CONFIG_REQ: /* Peer configuration request */
1231 return ("PEER_CONFIG_REQ");
1232 case L2CEVT_L2CAP_CONFIG_RSP: /* Peer configuration response */
1233 return ("PEER_CONFIG_RSP");
1234 case L2CEVT_L2CAP_CONFIG_RSP_NEG: /* Peer configuration response (failed) */
1235 return ("PEER_CONFIG_RSP_NEG");
1236 case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnect request */
1237 return ("PEER_DISCONNECT_REQ");
1238 case L2CEVT_L2CAP_DISCONNECT_RSP: /* Peer disconnect response */
1239 return ("PEER_DISCONNECT_RSP");
1240 case L2CEVT_L2CAP_DATA: /* Peer data */
1241 return ("PEER_DATA");
1242
1243 case L2CEVT_L2CA_CONNECT_REQ: /* Upper layer connect request */
1244 return ("UPPER_LAYER_CONNECT_REQ");
1245 case L2CEVT_L2CA_CONNECT_RSP: /* Upper layer connect response */
1246 return ("UPPER_LAYER_CONNECT_RSP");
1247 case L2CEVT_L2CA_CONNECT_RSP_NEG: /* Upper layer connect response (failed)*/
1248 return ("UPPER_LAYER_CONNECT_RSP_NEG");
1249 case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config request */
1250 return ("UPPER_LAYER_CONFIG_REQ");
1251 case L2CEVT_L2CA_CONFIG_RSP: /* Upper layer config response */
1252 return ("UPPER_LAYER_CONFIG_RSP");
1253 case L2CEVT_L2CA_CONFIG_RSP_NEG: /* Upper layer config response (failed) */
1254 return ("UPPER_LAYER_CONFIG_RSP_NEG");
1255 case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper layer disconnect request */
1256 return ("UPPER_LAYER_DISCONNECT_REQ");
1257 case L2CEVT_L2CA_DISCONNECT_RSP: /* Upper layer disconnect response */
1258 return ("UPPER_LAYER_DISCONNECT_RSP");
1259 case L2CEVT_L2CA_DATA_READ: /* Upper layer data read */
1260 return ("UPPER_LAYER_DATA_READ");
1261 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data write */
1262 return ("UPPER_LAYER_DATA_WRITE");
1263 case L2CEVT_TIMEOUT: /* Timeout */
1264 return ("TIMEOUT");
1265 case L2CEVT_SEC_RE_SEND_CMD:
1266 return ("SEC_RE_SEND_CMD");
1267 case L2CEVT_L2CAP_INFO_RSP: /* Peer information response */
1268 return ("L2CEVT_L2CAP_INFO_RSP");
1269 case L2CEVT_ACK_TIMEOUT:
1270 return ("L2CEVT_ACK_TIMEOUT");
1271
1272 default:
1273 return ("???? UNKNOWN EVENT");
1274 }
1275 }
1276 #endif /* (BT_TRACE_VERBOSE == TRUE) */
1277
1278
1279 /*******************************************************************************
1280 **
1281 ** Function l2c_enqueue_peer_data
1282 **
1283 ** Description Enqueues data destined for the peer in the ccb. Handles
1284 ** FCR segmentation and checks for congestion.
1285 **
1286 ** Returns void
1287 **
1288 *******************************************************************************/
l2c_enqueue_peer_data(tL2C_CCB * p_ccb,BT_HDR * p_buf)1289 void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf)
1290 {
1291 UINT8 *p;
1292
1293 if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
1294 {
1295 p_buf->event = 0;
1296 }
1297 else
1298 {
1299 /* Save the channel ID for faster counting */
1300 p_buf->event = p_ccb->local_cid;
1301
1302 /* Step back to add the L2CAP header */
1303 p_buf->offset -= L2CAP_PKT_OVERHEAD;
1304 p_buf->len += L2CAP_PKT_OVERHEAD;
1305
1306 /* Set the pointer to the beginning of the data */
1307 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
1308
1309 /* Now the L2CAP header */
1310 UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD);
1311 UINT16_TO_STREAM (p, p_ccb->remote_cid);
1312 }
1313
1314 GKI_enqueue (&p_ccb->xmit_hold_q, p_buf);
1315
1316 l2cu_check_channel_congestion (p_ccb);
1317
1318 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1319 /* if new packet is higher priority than serving ccb and it is not overrun */
1320 if (( p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority )
1321 &&( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0))
1322 {
1323 /* send out higher priority packet */
1324 p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;
1325 }
1326 #endif
1327
1328 /* if we are doing a round robin scheduling, set the flag */
1329 if (p_ccb->p_lcb->link_xmit_quota == 0)
1330 l2cb.check_round_robin = TRUE;
1331 }
1332
1333
1334