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