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