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
41extern fixed_queue_t *btu_bta_alarm_queue;
42
43static 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*******************************************************************************/
54static 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*******************************************************************************/
93static 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*******************************************************************************/
127static 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*******************************************************************************/
161static 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*******************************************************************************/
175static 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*******************************************************************************/
189static 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*******************************************************************************/
205BOOLEAN 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*******************************************************************************/
268BOOLEAN 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*******************************************************************************/
329BOOLEAN 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*******************************************************************************/
395UINT16 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*******************************************************************************/
486BOOLEAN 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*******************************************************************************/
519BOOLEAN 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*******************************************************************************/
558static 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*******************************************************************************/
644void 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*******************************************************************************/
667BOOLEAN 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*******************************************************************************/
745void 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*******************************************************************************/
760BOOLEAN 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*******************************************************************************/
790void 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*******************************************************************************/
811void 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*******************************************************************************/
828BOOLEAN 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*******************************************************************************/
857void 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*******************************************************************************/
877void 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*******************************************************************************/
893BOOLEAN 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*******************************************************************************/
946BOOLEAN 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