• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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