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 UCD code
22 *
23 ******************************************************************************/
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "bt_common.h"
30 #include "bt_types.h"
31 #include "hcidefs.h"
32 #include "hcimsgs.h"
33 #include "l2cdefs.h"
34 #include "l2c_int.h"
35 #include "btu.h"
36 #include "btm_api.h"
37 #include "btm_int.h"
38
39 #if (L2CAP_UCD_INCLUDED == TRUE)
40
41 extern fixed_queue_t *btu_bta_alarm_queue;
42
43 static BOOLEAN l2c_ucd_connect ( BD_ADDR rem_bda );
44
45 /*******************************************************************************
46 **
47 ** Function l2c_ucd_discover_cback
48 **
49 ** Description UCD Discover callback
50 **
51 ** Returns void
52 **
53 *******************************************************************************/
l2c_ucd_discover_cback(BD_ADDR rem_bda,UINT8 info_type,UINT32 data)54 static void l2c_ucd_discover_cback (BD_ADDR rem_bda, UINT8 info_type, UINT32 data)
55 {
56 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
57 UINT16 xx;
58
59 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_discover_cback");
60
61 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
62 {
63 if (p_rcb->in_use)
64 {
65 /* if this application is waiting UCD reception info */
66 if (( info_type == L2CAP_UCD_INFO_TYPE_RECEPTION )
67 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION ))
68 {
69 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data);
70 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_RECEPTION);
71 }
72
73 /* if this application is waiting UCD MTU info */
74 if (( info_type == L2CAP_UCD_INFO_TYPE_MTU )
75 && ( p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU ))
76 {
77 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (rem_bda, info_type, data);
78 p_rcb->ucd.state &= ~(L2C_UCD_STATE_W4_MTU);
79 }
80 }
81 }
82 }
83
84 /*******************************************************************************
85 **
86 ** Function l2c_ucd_data_ind_cback
87 **
88 ** Description UCD Data callback
89 **
90 ** Returns void
91 **
92 *******************************************************************************/
l2c_ucd_data_ind_cback(BD_ADDR rem_bda,BT_HDR * p_buf)93 static void l2c_ucd_data_ind_cback (BD_ADDR rem_bda, BT_HDR *p_buf)
94 {
95 UINT8 *p;
96 UINT16 psm;
97 tL2C_RCB *p_rcb;
98
99 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_data_ind_cback");
100
101 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
102 STREAM_TO_UINT16(psm, p)
103
104 p_buf->offset += L2CAP_UCD_OVERHEAD;
105 p_buf->len -= L2CAP_UCD_OVERHEAD;
106
107 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
108 {
109 L2CAP_TRACE_ERROR ("L2CAP - no RCB for l2c_ucd_data_ind_cback, PSM: 0x%04x", psm);
110 osi_free(p_buf);
111 }
112 else
113 {
114 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(rem_bda, p_buf);
115 }
116 }
117
118 /*******************************************************************************
119 **
120 ** Function l2c_ucd_congestion_status_cback
121 **
122 ** Description UCD Congestion Status callback
123 **
124 ** Returns void
125 **
126 *******************************************************************************/
l2c_ucd_congestion_status_cback(BD_ADDR rem_bda,BOOLEAN is_congested)127 static void l2c_ucd_congestion_status_cback (BD_ADDR rem_bda, BOOLEAN is_congested)
128 {
129 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
130 UINT16 xx;
131
132 L2CAP_TRACE_DEBUG ("L2CAP - l2c_ucd_congestion_status_cback");
133
134 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
135 {
136 if (( p_rcb->in_use )
137 &&( p_rcb->ucd.state != L2C_UCD_STATE_UNUSED ))
138 {
139 if ( p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb )
140 {
141 L2CAP_TRACE_DEBUG ("L2CAP - Calling UCDCongestionStatus_Cb (%d), PSM=0x%04x, BDA: %08x%04x,",
142 is_congested, p_rcb->psm,
143 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
144 (rem_bda[4]<<8)+rem_bda[5]);
145
146 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb ( rem_bda, is_congested );
147 }
148 }
149 }
150 }
151
152 /*******************************************************************************
153 **
154 ** Function l2c_ucd_disconnect_ind_cback
155 **
156 ** Description UCD disconnect callback (This prevent to access null pointer)
157 **
158 ** Returns void
159 **
160 *******************************************************************************/
l2c_ucd_disconnect_ind_cback(UINT16 cid,BOOLEAN result)161 static void l2c_ucd_disconnect_ind_cback (UINT16 cid, BOOLEAN result)
162 {
163 /* do nothing */
164 }
165
166 /*******************************************************************************
167 **
168 ** Function l2c_ucd_config_ind_cback
169 **
170 ** Description UCD config callback (This prevent to access null pointer)
171 **
172 ** Returns void
173 **
174 *******************************************************************************/
l2c_ucd_config_ind_cback(UINT16 cid,tL2CAP_CFG_INFO * p_cfg)175 static void l2c_ucd_config_ind_cback (UINT16 cid, tL2CAP_CFG_INFO *p_cfg)
176 {
177 /* do nothing */
178 }
179
180 /*******************************************************************************
181 **
182 ** Function l2c_ucd_config_cfm_cback
183 **
184 ** Description UCD config callback (This prevent to access null pointer)
185 **
186 ** Returns void
187 **
188 *******************************************************************************/
l2c_ucd_config_cfm_cback(UINT16 cid,tL2CAP_CFG_INFO * p_cfg)189 static void l2c_ucd_config_cfm_cback (UINT16 cid, tL2CAP_CFG_INFO *p_cfg)
190 {
191 /* do nothing */
192 }
193
194 /*******************************************************************************
195 **
196 ** Function L2CA_UcdRegister
197 **
198 ** Description Register PSM on UCD.
199 **
200 ** Parameters: tL2CAP_UCD_CB_INFO
201 **
202 ** Return value: TRUE if successs
203 **
204 *******************************************************************************/
L2CA_UcdRegister(UINT16 psm,tL2CAP_UCD_CB_INFO * p_cb_info)205 BOOLEAN L2CA_UcdRegister ( UINT16 psm, tL2CAP_UCD_CB_INFO *p_cb_info )
206 {
207 tL2C_RCB *p_rcb;
208
209 L2CAP_TRACE_API ("L2CA_UcdRegister() PSM: 0x%04x", psm);
210
211 if ((!p_cb_info->pL2CA_UCD_Discover_Cb)
212 || (!p_cb_info->pL2CA_UCD_Data_Cb))
213 {
214 L2CAP_TRACE_ERROR ("L2CAP - no callback registering PSM(0x%04x) on UCD", psm);
215 return (FALSE);
216 }
217
218 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
219 {
220 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdRegister, PSM: 0x%04x", psm);
221 return (FALSE);
222 }
223
224 p_rcb->ucd.state = L2C_UCD_STATE_W4_DATA;
225 p_rcb->ucd.cb_info = *p_cb_info;
226
227 /* check if master rcb is created for UCD */
228 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL)
229 {
230 if ((p_rcb = l2cu_allocate_rcb (L2C_UCD_RCB_ID)) == NULL)
231 {
232 L2CAP_TRACE_ERROR ("L2CAP - no RCB available for L2CA_UcdRegister");
233 return (FALSE);
234 }
235 else
236 {
237 /* these callback functions will forward data to each UCD application */
238 p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb = l2c_ucd_discover_cback;
239 p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb = l2c_ucd_data_ind_cback;
240 p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb = l2c_ucd_congestion_status_cback;
241
242 memset (&p_rcb->api, 0, sizeof(tL2CAP_APPL_INFO));
243 p_rcb->api.pL2CA_DisconnectInd_Cb = l2c_ucd_disconnect_ind_cback;
244
245 /* This will make L2CAP check UCD congestion callback */
246 p_rcb->api.pL2CA_CongestionStatus_Cb = NULL;
247
248 /* do nothing but prevent crash */
249 p_rcb->api.pL2CA_ConfigInd_Cb = l2c_ucd_config_ind_cback;
250 p_rcb->api.pL2CA_ConfigCfm_Cb = l2c_ucd_config_cfm_cback;
251 }
252 }
253
254 return (TRUE);
255 }
256
257 /*******************************************************************************
258 **
259 ** Function L2CA_UcdDeregister
260 **
261 ** Description Deregister PSM on UCD.
262 **
263 ** Parameters: PSM
264 **
265 ** Return value: TRUE if successs
266 **
267 *******************************************************************************/
L2CA_UcdDeregister(UINT16 psm)268 BOOLEAN L2CA_UcdDeregister ( UINT16 psm )
269 {
270 tL2C_CCB *p_ccb;
271 tL2C_RCB *p_rcb;
272 UINT16 xx;
273
274 L2CAP_TRACE_API ("L2CA_UcdDeregister() PSM: 0x%04x", psm);
275
276 if ((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
277 {
278 L2CAP_TRACE_ERROR ("L2CAP - no RCB for L2CA_UcdDeregister, PSM: 0x%04x", psm);
279 return (FALSE);
280 }
281
282 p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
283
284 /* check this was the last UCD registration */
285 p_rcb = &l2cb.rcb_pool[0];
286
287 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
288 {
289 if ((p_rcb->in_use) && (p_rcb->ucd.state != L2C_UCD_STATE_UNUSED))
290 return (TRUE);
291 }
292
293 /* delete master rcb for UCD */
294 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL)
295 {
296 l2cu_release_rcb (p_rcb);
297 }
298
299 /* delete CCB for UCD */
300 p_ccb = l2cb.ccb_pool;
301 for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ )
302 {
303 if (( p_ccb->in_use )
304 &&( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID ))
305 {
306 l2cu_release_ccb (p_ccb);
307 }
308 p_ccb++;
309 }
310
311 return (TRUE);
312 }
313
314 /*******************************************************************************
315 **
316 ** Function L2CA_UcdDiscover
317 **
318 ** Description Discover UCD of remote device.
319 **
320 ** Parameters: PSM
321 ** BD_ADDR of remote device
322 ** info_type : L2CAP_UCD_INFO_TYPE_RECEPTION
323 ** L2CAP_UCD_INFO_TYPE_MTU
324 **
325 **
326 ** Return value: TRUE if successs
327 **
328 *******************************************************************************/
L2CA_UcdDiscover(UINT16 psm,BD_ADDR rem_bda,UINT8 info_type)329 BOOLEAN L2CA_UcdDiscover ( UINT16 psm, BD_ADDR rem_bda, UINT8 info_type )
330 {
331 tL2C_LCB *p_lcb;
332 tL2C_CCB *p_ccb;
333 tL2C_RCB *p_rcb;
334
335 L2CAP_TRACE_API ("L2CA_UcdDiscover() PSM: 0x%04x BDA: %08x%04x, InfoType=0x%02x", psm,
336 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
337 (rem_bda[4]<<8)+rem_bda[5], info_type);
338
339 /* Fail if the PSM is not registered */
340 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
341 ||( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED ))
342 {
343 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDiscover, PSM: 0x%04x", psm);
344 return (FALSE);
345 }
346
347 /* First, see if we already have a link to the remote */
348 /* then find the channel control block for UCD. */
349 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
350 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
351 {
352 if ( l2c_ucd_connect (rem_bda) == FALSE )
353 {
354 return (FALSE);
355 }
356 }
357
358 /* set waiting flags in rcb */
359
360 if ( info_type & L2CAP_UCD_INFO_TYPE_RECEPTION )
361 p_rcb->ucd.state |= L2C_UCD_STATE_W4_RECEPTION;
362
363 if ( info_type & L2CAP_UCD_INFO_TYPE_MTU )
364 p_rcb->ucd.state |= L2C_UCD_STATE_W4_MTU;
365
366 /* if link is already established */
367 if ((p_lcb)&&(p_lcb->link_state == LST_CONNECTED))
368 {
369 if (!p_ccb)
370 {
371 p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID);
372 }
373 l2c_ucd_check_pending_info_req(p_ccb);
374 }
375 return (TRUE);
376 }
377
378 /*******************************************************************************
379 **
380 ** Function L2CA_UcdDataWrite
381 **
382 ** Description Send UCD to remote device
383 **
384 ** Parameters: PSM
385 ** BD Address of remote
386 ** Pointer to buffer of type BT_HDR
387 ** flags : L2CAP_FLUSHABLE_CH_BASED
388 ** L2CAP_FLUSHABLE_PKT
389 ** L2CAP_NON_FLUSHABLE_PKT
390 **
391 ** Return value L2CAP_DW_SUCCESS, if data accepted
392 ** L2CAP_DW_FAILED, if error
393 **
394 *******************************************************************************/
L2CA_UcdDataWrite(UINT16 psm,BD_ADDR rem_bda,BT_HDR * p_buf,UINT16 flags)395 UINT16 L2CA_UcdDataWrite (UINT16 psm, BD_ADDR rem_bda, BT_HDR *p_buf, UINT16 flags)
396 {
397 tL2C_LCB *p_lcb;
398 tL2C_CCB *p_ccb;
399 tL2C_RCB *p_rcb;
400 UINT8 *p;
401
402 L2CAP_TRACE_API ("L2CA_UcdDataWrite() PSM: 0x%04x BDA: %08x%04x", psm,
403 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
404 (rem_bda[4]<<8)+rem_bda[5]);
405
406 /* Fail if the PSM is not registered */
407 if (((p_rcb = l2cu_find_rcb_by_psm (psm)) == NULL)
408 ||( p_rcb->ucd.state == L2C_UCD_STATE_UNUSED ))
409 {
410 L2CAP_TRACE_WARNING ("L2CAP - no RCB for L2CA_UcdDataWrite, PSM: 0x%04x", psm);
411 osi_free(p_buf);
412 return (L2CAP_DW_FAILED);
413 }
414
415 /* First, see if we already have a link to the remote */
416 /* then find the channel control block for UCD */
417 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
418 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
419 {
420 if ( l2c_ucd_connect (rem_bda) == FALSE )
421 {
422 osi_free(p_buf);
423 return (L2CAP_DW_FAILED);
424 }
425
426 /* If we still don't have lcb and ccb after connect attempt, then can't proceed */
427 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
428 || ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
429 {
430 osi_free(p_buf);
431 return (L2CAP_DW_FAILED);
432 }
433 }
434
435 /* write PSM */
436 p_buf->offset -= L2CAP_UCD_OVERHEAD;
437 p_buf->len += L2CAP_UCD_OVERHEAD;
438 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
439
440 UINT16_TO_STREAM (p, psm);
441
442 /* UCD MTU check */
443 if ((p_lcb->ucd_mtu) && (p_buf->len > p_lcb->ucd_mtu))
444 {
445 L2CAP_TRACE_WARNING ("L2CAP - Handle: 0x%04x UCD bigger than peer's UCD mtu size cannot be sent", p_lcb->handle);
446 osi_free(p_buf);
447 return (L2CAP_DW_FAILED);
448 }
449
450 /* If already congested, do not accept any more packets */
451 if (p_ccb->cong_sent)
452 {
453 L2CAP_TRACE_ERROR ("L2CAP - Handle: 0x%04x UCD cannot be sent, already congested count: %u buff_quota: %u",
454 p_lcb->handle,
455 (fixed_queue_length(p_ccb->xmit_hold_q) +
456 fixed_queue_length(p_lcb->ucd_out_sec_pending_q)),
457 p_ccb->buff_quota);
458
459 osi_free(p_buf);
460 return (L2CAP_DW_FAILED);
461 }
462
463 /* channel based, packet based flushable or non-flushable */
464 p_buf->layer_specific = flags;
465
466 l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_buf);
467
468 if (p_ccb->cong_sent)
469 return (L2CAP_DW_CONGESTED);
470 else
471 return (L2CAP_DW_SUCCESS);
472 }
473
474 /*******************************************************************************
475 **
476 ** Function L2CA_UcdSetIdleTimeout
477 **
478 ** Description Set UCD Idle timeout.
479 **
480 ** Parameters: BD Addr
481 ** Timeout in second
482 **
483 ** Return value: TRUE if successs
484 **
485 *******************************************************************************/
L2CA_UcdSetIdleTimeout(BD_ADDR rem_bda,UINT16 timeout)486 BOOLEAN L2CA_UcdSetIdleTimeout ( BD_ADDR rem_bda, UINT16 timeout )
487 {
488 tL2C_LCB *p_lcb;
489 tL2C_CCB *p_ccb;
490
491 L2CAP_TRACE_API ("L2CA_UcdSetIdleTimeout() Timeout: 0x%04x BDA: %08x%04x", timeout,
492 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
493 (rem_bda[4]<<8)+rem_bda[5]);
494
495 /* First, see if we already have a link to the remote */
496 /* then find the channel control block. */
497 if (((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
498 ||((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL))
499 {
500 L2CAP_TRACE_WARNING ("L2CAP - no UCD channel");
501 return (FALSE);
502 }
503 else
504 {
505 p_ccb->fixed_chnl_idle_tout = timeout;
506 return (TRUE);
507 }
508 }
509
510 /*******************************************************************************
511 **
512 ** Function L2CA_UCDSetTxPriority
513 **
514 ** Description Sets the transmission priority for a connectionless channel.
515 **
516 ** Returns TRUE if a valid channel, else FALSE
517 **
518 *******************************************************************************/
L2CA_UCDSetTxPriority(BD_ADDR rem_bda,tL2CAP_CHNL_PRIORITY priority)519 BOOLEAN L2CA_UCDSetTxPriority ( BD_ADDR rem_bda, tL2CAP_CHNL_PRIORITY priority )
520 {
521 tL2C_LCB *p_lcb;
522 tL2C_CCB *p_ccb;
523
524 L2CAP_TRACE_API ("L2CA_UCDSetTxPriority() priority: 0x%02x BDA: %08x%04x", priority,
525 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
526 (rem_bda[4]<<8)+rem_bda[5]);
527
528 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
529 {
530 L2CAP_TRACE_WARNING ("L2CAP - no LCB for L2CA_UCDSetTxPriority");
531 return (FALSE);
532 }
533
534 /* Find the channel control block */
535 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)
536 {
537 L2CAP_TRACE_WARNING ("L2CAP - no CCB for L2CA_UCDSetTxPriority");
538 return (FALSE);
539 }
540
541 /* it will update the order of CCB in LCB by priority and update round robin service variables */
542 l2cu_change_pri_ccb (p_ccb, priority);
543
544 return (TRUE);
545 }
546
547 /*******************************************************************************
548 **
549 ** Function l2c_ucd_connect
550 **
551 ** Description Connect UCD to remote device.
552 **
553 ** Parameters: BD_ADDR of remote device
554 **
555 ** Return value: TRUE if successs
556 **
557 *******************************************************************************/
l2c_ucd_connect(BD_ADDR rem_bda)558 static BOOLEAN l2c_ucd_connect ( BD_ADDR rem_bda )
559 {
560 tL2C_LCB *p_lcb;
561 tL2C_CCB *p_ccb;
562 tL2C_RCB *p_rcb;
563
564 L2CAP_TRACE_DEBUG ("l2c_ucd_connect() BDA: %08x%04x",
565 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
566 (rem_bda[4]<<8)+rem_bda[5]);
567
568 /* Fail if we have not established communications with the controller */
569 if (!BTM_IsDeviceUp())
570 {
571 L2CAP_TRACE_WARNING ("l2c_ucd_connect - BTU not ready");
572 return (FALSE);
573 }
574
575 /* First, see if we already have a link to the remote */
576 if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_BR_EDR)) == NULL)
577 {
578 /* No link. Get an LCB and start link establishment */
579 if ( ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE, BT_TRANSPORT_BR_EDR)) == NULL)
580 || (l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR) == FALSE) )
581 {
582 L2CAP_TRACE_WARNING ("L2CAP - conn not started l2c_ucd_connect");
583 return (FALSE);
584 }
585 }
586 else if ( p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) )
587 {
588 if (!(p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION))
589 {
590 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_connect");
591 return (FALSE);
592 }
593 }
594
595 /* Find the channel control block. */
596 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) == NULL)
597 {
598 /* Allocate a channel control block */
599 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL)
600 {
601 L2CAP_TRACE_WARNING ("L2CAP - no CCB for l2c_ucd_connect");
602 return (FALSE);
603 }
604 else
605 {
606 /* Set CID for the connection */
607 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
608 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
609
610 /* Set the default idle timeout value to use */
611 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
612
613 /* Set the default channel priority value to use */
614 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY);
615
616 if ((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) == NULL)
617 {
618 L2CAP_TRACE_WARNING ("L2CAP - no UCD registered, l2c_ucd_connect");
619 return (FALSE);
620 }
621 /* Save UCD registration info */
622 p_ccb->p_rcb = p_rcb;
623
624 /* There is no configuration, so if the link is up, the channel is up */
625 if (p_lcb->link_state == LST_CONNECTED)
626 {
627 p_ccb->chnl_state = CST_OPEN;
628 }
629 }
630 }
631
632 return (TRUE);
633 }
634
635 /*******************************************************************************
636 **
637 ** Function l2c_ucd_delete_sec_pending_q
638 **
639 ** Description discard all of UCD packets in security pending queue
640 **
641 ** Returns None
642 **
643 *******************************************************************************/
l2c_ucd_delete_sec_pending_q(tL2C_LCB * p_lcb)644 void l2c_ucd_delete_sec_pending_q(tL2C_LCB *p_lcb)
645 {
646 /* clean up any security pending UCD */
647 while (! fixed_queue_is_empty(p_lcb->ucd_out_sec_pending_q))
648 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_out_sec_pending_q));
649 fixed_queue_free(p_lcb->ucd_out_sec_pending_q, NULL);
650 p_lcb->ucd_out_sec_pending_q = NULL;
651
652 while (! fixed_queue_is_empty(p_lcb->ucd_in_sec_pending_q))
653 osi_free(fixed_queue_try_dequeue(p_lcb->ucd_in_sec_pending_q));
654 fixed_queue_free(p_lcb->ucd_in_sec_pending_q);
655 p_lcb->ucd_in_sec_pending_q = NULL;
656 }
657
658 /*******************************************************************************
659 **
660 ** Function l2c_ucd_check_pending_info_req
661 **
662 ** Description check if any application is waiting for UCD information
663 **
664 ** Return TRUE if any pending UCD info request
665 **
666 *******************************************************************************/
l2c_ucd_check_pending_info_req(tL2C_CCB * p_ccb)667 BOOLEAN l2c_ucd_check_pending_info_req(tL2C_CCB *p_ccb)
668 {
669 tL2C_RCB *p_rcb = &l2cb.rcb_pool[0];
670 UINT16 xx;
671 BOOLEAN pending = FALSE;
672
673 if (p_ccb == NULL)
674 {
675 L2CAP_TRACE_ERROR ("L2CAP - NULL p_ccb in l2c_ucd_check_pending_info_req");
676 return (FALSE);
677 }
678
679 for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++)
680 {
681 if (p_rcb->in_use)
682 {
683 /* if application is waiting UCD reception info */
684 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_RECEPTION)
685 {
686 /* if this information is available */
687 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_EXTENDED_FEATURES_INFO_TYPE) )
688 {
689 if (!(p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION))
690 {
691 L2CAP_TRACE_WARNING ("L2CAP - UCD is not supported by peer, l2c_ucd_check_pending_info_req");
692
693 l2c_ucd_delete_sec_pending_q(p_ccb->p_lcb);
694 l2cu_release_ccb (p_ccb);
695 }
696
697 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr,
698 L2CAP_UCD_INFO_TYPE_RECEPTION,
699 p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_UCD_RECEPTION);
700 }
701 else
702 {
703 pending = TRUE;
704 if (p_ccb->p_lcb->w4_info_rsp == FALSE)
705 {
706 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_EXTENDED_FEATURES_INFO_TYPE);
707 }
708 }
709 }
710
711 /* if application is waiting for UCD MTU */
712 if (p_rcb->ucd.state & L2C_UCD_STATE_W4_MTU)
713 {
714 /* if this information is available */
715 if ( p_ccb->p_lcb->info_rx_bits & (1 << L2CAP_CONNLESS_MTU_INFO_TYPE))
716 {
717 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Discover_Cb (p_ccb->p_lcb->remote_bd_addr,
718 L2CAP_UCD_INFO_TYPE_MTU,
719 p_ccb->p_lcb->ucd_mtu);
720 }
721 else
722 {
723 pending = TRUE;
724 if (p_ccb->p_lcb->w4_info_rsp == FALSE)
725 {
726 l2cu_send_peer_info_req (p_ccb->p_lcb, L2CAP_CONNLESS_MTU_INFO_TYPE);
727 }
728 }
729 }
730 }
731 }
732 return (pending);
733 }
734
735 /*******************************************************************************
736 **
737 ** Function l2c_ucd_enqueue_pending_out_sec_q
738 **
739 ** Description enqueue outgoing UCD packet into security pending queue
740 ** and check congestion
741 **
742 ** Return None
743 **
744 *******************************************************************************/
l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB * p_ccb,void * p_data)745 void l2c_ucd_enqueue_pending_out_sec_q(tL2C_CCB *p_ccb, void *p_data)
746 {
747 fixed_queue_enqueue(p_ccb->p_lcb->ucd_out_sec_pending_q, p_data);
748 l2cu_check_channel_congestion (p_ccb);
749 }
750
751 /*******************************************************************************
752 **
753 ** Function l2c_ucd_check_pending_out_sec_q
754 **
755 ** Description check outgoing security
756 **
757 ** Return TRUE if any UCD packet for security
758 **
759 *******************************************************************************/
l2c_ucd_check_pending_out_sec_q(tL2C_CCB * p_ccb)760 BOOLEAN l2c_ucd_check_pending_out_sec_q(tL2C_CCB *p_ccb)
761 {
762 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_peek_first(p_ccb->p_lcb->ucd_out_sec_pending_q);
763
764 if (p_buf != NULL)
765 {
766 UINT16 psm;
767 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
768
769 STREAM_TO_UINT16(psm, p)
770
771 p_ccb->chnl_state = CST_ORIG_W4_SEC_COMP;
772 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm,
773 p_ccb->p_lcb->handle, CONNLESS_ORIG, &l2c_link_sec_comp, p_ccb);
774
775 return (TRUE);
776 }
777 return (FALSE);
778 }
779
780 /*******************************************************************************
781 **
782 ** Function l2c_ucd_send_pending_out_sec_q
783 **
784 ** Description dequeue UCD packet from security pending queue and
785 ** enqueue it into CCB
786 **
787 ** Return None
788 **
789 *******************************************************************************/
l2c_ucd_send_pending_out_sec_q(tL2C_CCB * p_ccb)790 void l2c_ucd_send_pending_out_sec_q(tL2C_CCB *p_ccb)
791 {
792 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
793
794 if (p_buf != NULL)
795 {
796 l2c_enqueue_peer_data (p_ccb, (BT_HDR *)p_buf);
797 l2c_link_check_send_pkts (p_ccb->p_lcb, NULL, NULL);
798 }
799 }
800
801 /*******************************************************************************
802 **
803 ** Function l2c_ucd_discard_pending_out_sec_q
804 **
805 ** Description dequeue UCD packet from security pending queue and
806 ** discard it.
807 **
808 ** Return None
809 **
810 *******************************************************************************/
l2c_ucd_discard_pending_out_sec_q(tL2C_CCB * p_ccb)811 void l2c_ucd_discard_pending_out_sec_q(tL2C_CCB *p_ccb)
812 {
813 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_out_sec_pending_q);
814
815 /* we may need to report to application */
816 osi_free(p_buf);
817 }
818
819 /*******************************************************************************
820 **
821 ** Function l2c_ucd_check_pending_in_sec_q
822 **
823 ** Description check incoming security
824 **
825 ** Return TRUE if any UCD packet for security
826 **
827 *******************************************************************************/
l2c_ucd_check_pending_in_sec_q(tL2C_CCB * p_ccb)828 BOOLEAN l2c_ucd_check_pending_in_sec_q(tL2C_CCB *p_ccb)
829 {
830 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
831
832 if (p_buf != NULL)
833 {
834 UINT16 psm;
835 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
836 STREAM_TO_UINT16(psm, p)
837
838 p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
839 btm_sec_l2cap_access_req (p_ccb->p_lcb->remote_bd_addr, psm,
840 p_ccb->p_lcb->handle, CONNLESS_TERM, &l2c_link_sec_comp, p_ccb);
841
842 return (TRUE);
843 }
844 return (FALSE);
845 }
846
847 /*******************************************************************************
848 **
849 ** Function l2c_ucd_send_pending_in_sec_q
850 **
851 ** Description dequeue UCD packet from security pending queue and
852 ** send it to application
853 **
854 ** Return None
855 **
856 *******************************************************************************/
l2c_ucd_send_pending_in_sec_q(tL2C_CCB * p_ccb)857 void l2c_ucd_send_pending_in_sec_q(tL2C_CCB *p_ccb)
858 {
859 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q)
860
861 if (p_buf != NULL)
862 {
863 p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Data_Cb(p_ccb->p_lcb->remote_bd_addr, (BT_HDR *)p_buf);
864 }
865 }
866
867 /*******************************************************************************
868 **
869 ** Function l2c_ucd_discard_pending_in_sec_q
870 **
871 ** Description dequeue UCD packet from security pending queue and
872 ** discard it.
873 **
874 ** Return None
875 **
876 *******************************************************************************/
l2c_ucd_discard_pending_in_sec_q(tL2C_CCB * p_ccb)877 void l2c_ucd_discard_pending_in_sec_q(tL2C_CCB *p_ccb)
878 {
879 BT_HDR *p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->p_lcb->ucd_in_sec_pending_q);
880 osi_free(p_buf);
881 }
882
883 /*******************************************************************************
884 **
885 ** Function l2c_ucd_check_rx_pkts
886 **
887 ** Description Check if UCD reception is registered.
888 ** Process received UCD packet if application is expecting.
889 **
890 ** Return TRUE if UCD reception is registered
891 **
892 *******************************************************************************/
l2c_ucd_check_rx_pkts(tL2C_LCB * p_lcb,BT_HDR * p_msg)893 BOOLEAN l2c_ucd_check_rx_pkts(tL2C_LCB *p_lcb, BT_HDR *p_msg)
894 {
895 tL2C_CCB *p_ccb;
896 tL2C_RCB *p_rcb;
897
898 if (((p_ccb = l2cu_find_ccb_by_cid (p_lcb, L2CAP_CONNECTIONLESS_CID)) != NULL)
899 ||((p_rcb = l2cu_find_rcb_by_psm (L2C_UCD_RCB_ID)) != NULL))
900 {
901 if (p_ccb == NULL)
902 {
903 /* Allocate a channel control block */
904 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL)
905 {
906 L2CAP_TRACE_WARNING ("L2CAP - no CCB for UCD reception");
907 osi_free(p_msg);
908 return TRUE;
909 }
910 else
911 {
912 /* Set CID for the connection */
913 p_ccb->local_cid = L2CAP_CONNECTIONLESS_CID;
914 p_ccb->remote_cid = L2CAP_CONNECTIONLESS_CID;
915
916 /* Set the default idle timeout value to use */
917 p_ccb->fixed_chnl_idle_tout = L2CAP_UCD_IDLE_TIMEOUT;
918
919 /* Set the default channel priority value to use */
920 l2cu_change_pri_ccb (p_ccb, L2CAP_UCD_CH_PRIORITY);
921
922 /* Save registration info */
923 p_ccb->p_rcb = p_rcb;
924
925 p_ccb->chnl_state = CST_OPEN;
926 }
927 }
928 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
929 return TRUE;
930 }
931 else
932 return FALSE;
933 }
934
935 /*******************************************************************************
936 **
937 ** Function l2c_ucd_process_event
938 **
939 ** Description This is called from main state machine when LCID is connectionless
940 ** Process the event if it is for UCD.
941 **
942 ** Return TRUE if the event is consumed by UCD
943 ** FALSE if the event needs to be processed by main state machine
944 **
945 *******************************************************************************/
l2c_ucd_process_event(tL2C_CCB * p_ccb,UINT16 event,void * p_data)946 BOOLEAN l2c_ucd_process_event(tL2C_CCB *p_ccb, UINT16 event, void *p_data)
947 {
948 /* if the event is not processed by this function, this variable will be set to FALSE */
949 BOOLEAN done = TRUE;
950
951 switch (p_ccb->chnl_state)
952 {
953 case CST_CLOSED:
954 switch (event)
955 {
956 case L2CEVT_LP_CONNECT_CFM: /* Link came up */
957 /* check if waiting for UCD info */
958 if (!l2c_ucd_check_pending_info_req (p_ccb))
959 {
960 /* check if any outgoing UCD packet is waiting security check */
961 if (!l2c_ucd_check_pending_out_sec_q(p_ccb))
962 {
963 p_ccb->chnl_state = CST_OPEN;
964 }
965 }
966 break;
967
968 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
969 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
970 break;
971
972 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
973 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
974 break;
975
976 case L2CEVT_L2CAP_INFO_RSP:
977 /* check if waiting for UCD info */
978 if (!l2c_ucd_check_pending_info_req (p_ccb))
979 {
980 /* check if any outgoing UCD packet is waiting security check */
981 if (!l2c_ucd_check_pending_out_sec_q(p_ccb))
982 {
983 p_ccb->chnl_state = CST_OPEN;
984 }
985 }
986 break;
987
988 default:
989 done = FALSE; /* main state machine continues to process event */
990 break;
991 }
992 break;
993
994 case CST_ORIG_W4_SEC_COMP:
995 switch (event)
996 {
997 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
998 /* check if any outgoing UCD packet is waiting security check */
999 if (!l2c_ucd_check_pending_out_sec_q(p_ccb))
1000 {
1001 p_ccb->chnl_state = CST_OPEN;
1002 }
1003 break;
1004
1005 case L2CEVT_SEC_COMP: /* Security completed success */
1006 p_ccb->chnl_state = CST_OPEN;
1007 l2c_ucd_send_pending_out_sec_q(p_ccb);
1008
1009 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_out_sec_pending_q))
1010 {
1011 /* start a timer to send next UCD packet in OPEN state */
1012 /* it will prevent stack overflow */
1013 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0,
1014 l2c_ccb_timer_timeout, p_ccb,
1015 btu_general_alarm_queue);
1016 }
1017 else
1018 {
1019 /* start a timer for idle timeout of UCD */
1020 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1021 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1022 l2c_ccb_timer_timeout, p_ccb,
1023 btu_general_alarm_queue);
1024 }
1025 break;
1026
1027 case L2CEVT_SEC_COMP_NEG:
1028 p_ccb->chnl_state = CST_OPEN;
1029 l2c_ucd_discard_pending_out_sec_q(p_ccb);
1030
1031 /* start a timer for idle timeout of UCD */
1032 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1033 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1034 l2c_ccb_timer_timeout, p_ccb,
1035 btu_general_alarm_queue);
1036 break;
1037
1038 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1039 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1040 break;
1041
1042 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1043 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
1044 break;
1045
1046 case L2CEVT_L2CAP_INFO_RSP:
1047 /* check if waiting for UCD info */
1048 l2c_ucd_check_pending_info_req (p_ccb);
1049 break;
1050
1051 default:
1052 done = FALSE; /* main state machine continues to process event */
1053 break;
1054 }
1055 break;
1056
1057
1058 case CST_TERM_W4_SEC_COMP:
1059 switch (event)
1060 {
1061 case L2CEVT_SEC_COMP:
1062 p_ccb->chnl_state = CST_OPEN;
1063 l2c_ucd_send_pending_in_sec_q (p_ccb);
1064
1065 if (! fixed_queue_is_empty(p_ccb->p_lcb->ucd_in_sec_pending_q))
1066 {
1067 /* start a timer to check next UCD packet in OPEN state */
1068 /* it will prevent stack overflow */
1069 alarm_set_on_queue(p_ccb->l2c_ccb_timer, 0,
1070 l2c_ccb_timer_timeout, p_ccb,
1071 btu_general_alarm_queue);
1072 }
1073 else
1074 {
1075 /* start a timer for idle timeout of UCD */
1076 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1077 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1078 l2c_ccb_timer_timeout, p_ccb,
1079 btu_general_alarm_queue);
1080 }
1081 break;
1082
1083 case L2CEVT_SEC_COMP_NEG:
1084 if (((tL2C_CONN_INFO *)p_data)->status == BTM_DELAY_CHECK)
1085 {
1086 done = FALSE;
1087 break;
1088 }
1089 p_ccb->chnl_state = CST_OPEN;
1090 l2c_ucd_discard_pending_in_sec_q (p_ccb);
1091
1092 /* start a timer for idle timeout of UCD */
1093 period_ms_t timeout_ms = p_ccb->fixed_chnl_idle_tout * 1000;
1094 alarm_set_on_queue(p_ccb->l2c_ccb_timer, timeout_ms,
1095 l2c_ccb_timer_timeout, p_ccb,
1096 btu_general_alarm_queue);
1097 break;
1098
1099 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1100 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1101 break;
1102
1103 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1104 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
1105 break;
1106
1107 case L2CEVT_SEC_RE_SEND_CMD: /* BTM has enough info to proceed */
1108 /* check if any incoming UCD packet is waiting security check */
1109 if (!l2c_ucd_check_pending_in_sec_q(p_ccb))
1110 {
1111 p_ccb->chnl_state = CST_OPEN;
1112 }
1113 break;
1114
1115 case L2CEVT_L2CAP_INFO_RSP:
1116 /* check if waiting for UCD info */
1117 l2c_ucd_check_pending_info_req (p_ccb);
1118 break;
1119
1120 default:
1121 done = FALSE; /* main state machine continues to process event */
1122 break;
1123 }
1124 break;
1125
1126 case CST_OPEN:
1127 switch (event)
1128 {
1129 case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd */
1130 /* stop idle timer of UCD */
1131 alarm_cancel(p_ccb->l2c_ccb_timer);
1132
1133 fixed_queue_enqueue(p_ccb->p_lcb->ucd_in_sec_pending_q, p_data);
1134 l2c_ucd_check_pending_in_sec_q (p_ccb);
1135 break;
1136
1137 case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
1138 /* stop idle timer of UCD */
1139 alarm_cancel(p_ccb->l2c_ccb_timer);
1140
1141 l2c_ucd_enqueue_pending_out_sec_q(p_ccb, p_data);
1142
1143 /* coverity[check_return] */ /* coverity[unchecked_value] */
1144 /* success changes state, failure stays in current state */
1145 l2c_ucd_check_pending_out_sec_q (p_ccb);
1146 break;
1147
1148 case L2CEVT_TIMEOUT:
1149 /* check if any UCD packet is waiting security check */
1150 if ((!l2c_ucd_check_pending_in_sec_q(p_ccb))
1151 &&(!l2c_ucd_check_pending_out_sec_q(p_ccb)))
1152 {
1153 l2cu_release_ccb (p_ccb);
1154 }
1155 break;
1156
1157 case L2CEVT_L2CAP_INFO_RSP:
1158 /* check if waiting for UCD info */
1159 l2c_ucd_check_pending_info_req (p_ccb);
1160 break;
1161
1162 default:
1163 done = FALSE; /* main state machine continues to process event */
1164 break;
1165 }
1166 break;
1167
1168 default:
1169 done = FALSE; /* main state machine continues to process event */
1170 break;
1171 }
1172
1173 return done;
1174 }
1175 #endif /* (L2CAP_UCD_INCLUDED == TRUE) */
1176