Home | History | Annotate | Download | only in l2cap
      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 *******************************************************************************/
     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 *******************************************************************************/
     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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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