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 functions for BLE whitelist operation.
22 *
23 ******************************************************************************/
24
25#include <string.h>
26
27#include "bt_types.h"
28#include "btu.h"
29#include "btm_int.h"
30#include "l2c_int.h"
31#include "hcimsgs.h"
32#include "bt_utils.h"
33#include "vendor_ble.h"
34
35#ifndef BTM_BLE_SCAN_PARAM_TOUT
36#define BTM_BLE_SCAN_PARAM_TOUT      50    /* 50 seconds */
37#endif
38
39#if (BLE_INCLUDED == TRUE)
40
41static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state);
42static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state);
43
44/*******************************************************************************
45**
46** Function         btm_update_scanner_filter_policy
47**
48** Description      This function update the filter policy of scnner or advertiser.
49*******************************************************************************/
50void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy)
51{
52    tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
53    BTM_TRACE_EVENT ("btm_update_scanner_filter_policy");
54
55    p_inq->sfp = scan_policy;
56    p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
57
58    btsnd_hcic_ble_set_scan_params (p_inq->scan_type,
59                                    (UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval),
60                                    (UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window),
61                                     btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,
62                                     scan_policy);
63}
64/*******************************************************************************
65**
66** Function         btm_add_dev_to_controller
67**
68** Description      This function load the device into controller white list
69*******************************************************************************/
70BOOLEAN btm_add_dev_to_controller (BOOLEAN to_add, BD_ADDR bd_addr)
71{
72    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev (bd_addr);
73    tBLE_ADDR_TYPE  addr_type = BLE_ADDR_PUBLIC;
74    BOOLEAN             started = FALSE;
75    BD_ADDR             dummy_bda = {0};
76    tBT_DEVICE_TYPE dev_type;
77
78    if (p_dev_rec != NULL &&
79        p_dev_rec->device_type & BT_DEVICE_TYPE_BLE)
80    {
81
82        if (to_add)
83        {
84            if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
85            {
86#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
87                /* add device into IRK list */
88                btm_ble_vendor_irk_list_load_dev(p_dev_rec);
89#endif
90                started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
91            }
92            if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
93                memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
94            {
95                started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type,
96                                                         p_dev_rec->ble.static_addr);
97            }
98        }
99        else
100        {
101            if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
102            {
103                    started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
104            }
105            if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0 &&
106                memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0)
107            {
108                    started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
109            }
110        }
111    }    /* if not a known device, shall we add it? */
112    else
113    {
114        BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
115
116        if (to_add)
117            started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
118        else
119            started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
120    }
121
122    return started;
123
124}
125/*******************************************************************************
126**
127** Function         btm_execute_wl_dev_operation
128**
129** Description      execute the pending whitelist device operation(loading or removing)
130*******************************************************************************/
131BOOLEAN btm_execute_wl_dev_operation(void)
132{
133    tBTM_BLE_WL_OP *p_dev_op = btm_cb.ble_ctr_cb.wl_op_q;
134    UINT8   i = 0;
135    BOOLEAN rt = TRUE;
136
137    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && rt; i ++, p_dev_op ++)
138    {
139        if (p_dev_op->in_use)
140        {
141            rt = btm_add_dev_to_controller(p_dev_op->to_add, p_dev_op->bd_addr);
142            memset(p_dev_op, 0, sizeof(tBTM_BLE_WL_OP));
143        }
144        else
145            break;
146    }
147    return rt;
148}
149/*******************************************************************************
150**
151** Function         btm_enq_wl_dev_operation
152**
153** Description      enqueue the pending whitelist device operation(loading or removing).
154*******************************************************************************/
155void btm_enq_wl_dev_operation(BOOLEAN to_add, BD_ADDR bd_addr)
156{
157    tBTM_BLE_WL_OP *p_dev_op = btm_cb.ble_ctr_cb.wl_op_q;
158    UINT8   i = 0;
159
160    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_dev_op ++)
161    {
162        if (p_dev_op->in_use && !memcmp(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN))
163        {
164            p_dev_op->to_add = to_add;
165            return;
166        }
167        else if (!p_dev_op->in_use)
168            break;
169    }
170    if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM)
171    {
172        p_dev_op->in_use = TRUE;
173        p_dev_op->to_add = to_add;
174        memcpy(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN);
175    }
176    else
177    {
178        BTM_TRACE_ERROR("max pending WL operation reached, discard");
179    }
180    return;
181}
182/*******************************************************************************
183**
184** Function         btm_update_dev_to_white_list
185**
186** Description      This function adds a device into white list.
187*******************************************************************************/
188BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr)
189{
190    /* look up the sec device record, and find the address */
191    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
192    UINT8       wl_state = p_cb->wl_state;
193
194    if ((to_add && p_cb->num_empty_filter == 0) ||
195        (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
196    {
197        BTM_TRACE_ERROR("WL full or empty, unable to update to WL. num_entry available: %d",
198                          p_cb->num_empty_filter);
199        return FALSE;
200    }
201
202    btm_suspend_wl_activity(wl_state);
203
204    /* enq pending WL device operation */
205    btm_enq_wl_dev_operation(to_add, bd_addr);
206
207    btm_resume_wl_activity(wl_state);
208
209    return TRUE;
210}
211/*******************************************************************************
212**
213** Function         btm_ble_clear_white_list
214**
215** Description      This function clears the white list.
216*******************************************************************************/
217void btm_ble_clear_white_list (void)
218{
219    BTM_TRACE_EVENT ("btm_ble_clear_white_list");
220    btsnd_hcic_ble_clear_white_list();
221    memset(&btm_cb.ble_ctr_cb.bg_dev_list, 0, (sizeof(tBTM_LE_BG_CONN_DEV)*BTM_BLE_MAX_BG_CONN_DEV_NUM));
222}
223
224/*******************************************************************************
225**
226** Function         btm_ble_clear_white_list_complete
227**
228** Description      This function clears the white list complete.
229*******************************************************************************/
230void btm_ble_clear_white_list_complete(UINT8 *p_data, UINT16 evt_len)
231{
232    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
233    UINT8       status;
234    UNUSED(evt_len);
235
236    BTM_TRACE_EVENT ("btm_ble_clear_white_list_complete");
237    STREAM_TO_UINT8  (status, p_data);
238
239    if (status == HCI_SUCCESS)
240        p_cb->num_empty_filter = p_cb->max_filter_entries;
241
242}
243/*******************************************************************************
244**
245** Function         btm_ble_add_2_white_list_complete
246**
247** Description      This function read the current white list size.
248*******************************************************************************/
249void btm_ble_add_2_white_list_complete(UINT8 status)
250{
251    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
252    BTM_TRACE_EVENT ("btm_ble_add_2_white_list_complete");
253
254    if (status == HCI_SUCCESS)
255    {
256        p_cb->num_empty_filter --;
257    }
258}
259/*******************************************************************************
260**
261** Function         btm_ble_remove_from_white_list_complete
262**
263** Description      This function remove the white list element complete.
264*******************************************************************************/
265void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len)
266{
267    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
268    UNUSED(evt_len);
269
270    BTM_TRACE_EVENT ("btm_ble_remove_from_white_list_complete");
271    if (*p == HCI_SUCCESS)
272    {
273        p_cb->num_empty_filter ++;
274    }
275}
276/*******************************************************************************
277**
278** Function         btm_ble_count_unconn_dev_in_whitelist
279**
280** Description      This function find the number of un-connected background device
281*******************************************************************************/
282UINT8 btm_ble_count_unconn_dev_in_whitelist(void)
283{
284    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
285    UINT8 i, count = 0;
286
287    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++)
288    {
289        if (p_cb->bg_dev_list[i].in_use &&
290            !BTM_IsAclConnectionUp(p_cb->bg_dev_list[i].bd_addr, BT_TRANSPORT_LE))
291        {
292            count ++;
293        }
294    }
295    return count;
296
297}
298/*******************************************************************************
299**
300** Function         btm_update_bg_conn_list
301**
302** Description      This function update the local background connection device list.
303*******************************************************************************/
304BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr)
305{
306    tBTM_BLE_CB             *p_cb = &btm_cb.ble_ctr_cb;
307    tBTM_LE_BG_CONN_DEV     *p_bg_dev = &p_cb->bg_dev_list[0], *p_next, *p_cur;
308    UINT8                   i, j;
309    BOOLEAN             ret = FALSE;
310
311    BTM_TRACE_EVENT ("btm_update_bg_conn_list");
312
313    if ((to_add && (p_cb->bg_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0)))
314    {
315        BTM_TRACE_DEBUG("num_empty_filter = %d", p_cb->num_empty_filter);
316        return ret;
317    }
318
319    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++)
320    {
321        if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0)
322        {
323            if (!to_add)
324            {
325                memset(p_bg_dev, 0, sizeof(tBTM_LE_BG_CONN_DEV));
326                p_cb->bg_dev_num --;
327                p_cur = p_bg_dev;
328                p_next = p_bg_dev + 1;
329                for (j = i + 1; j < BTM_BLE_MAX_BG_CONN_DEV_NUM && p_next->in_use;
330                     j ++, p_cur ++, p_next ++)
331                {
332                    memcpy(p_cur, p_next, sizeof(tBTM_LE_BG_CONN_DEV));
333                    memset(p_next, 0, sizeof(tBTM_LE_BG_CONN_DEV));
334                }
335            }
336            ret = TRUE;
337            break;
338        }
339        else if (!p_bg_dev->in_use && to_add)
340        {
341            BTM_TRACE_DEBUG("add new WL entry in bg_dev_list");
342
343            memcpy(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN);
344            p_bg_dev->in_use = TRUE;
345            p_cb->bg_dev_num ++;
346
347            ret = TRUE;
348            break;
349        }
350    }
351
352
353    return ret;
354}
355
356/*******************************************************************************
357**
358** Function         btm_ble_start_auto_conn
359**
360** Description      This function is to start/stop auto connection procedure.
361**
362** Parameters       start: TRUE to start; FALSE to stop.
363**
364** Returns          void
365**
366*******************************************************************************/
367BOOLEAN btm_ble_start_auto_conn(BOOLEAN start)
368{
369    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
370    BD_ADDR dummy_bda = {0};
371    BOOLEAN exec = TRUE;
372    UINT16 scan_int, scan_win;
373
374    if (start)
375    {
376        if ( p_cb->conn_state == BLE_CONN_IDLE )
377        {
378            exec = btm_execute_wl_dev_operation();
379        }
380        if ((p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
381            && btm_ble_topology_check(BTM_BLE_STATE_INIT))
382        {
383            scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
384            scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
385
386            if (!btsnd_hcic_ble_create_ll_conn (scan_int,  /* UINT16 scan_int      */
387                                                scan_win,    /* UINT16 scan_win      */
388                                                0x01,                   /* UINT8 white_list     */
389                                                BLE_ADDR_PUBLIC,        /* UINT8 addr_type_peer */
390                                                dummy_bda,              /* BD_ADDR bda_peer     */
391                                                p_cb->addr_mgnt_cb.own_addr_type,
392                                                   /* UINT8 addr_type_own,
393                                                   not allow random address for central  */
394                                                BTM_BLE_CONN_INT_MIN_DEF,   /* UINT16 conn_int_min  */
395                                                BTM_BLE_CONN_INT_MAX_DEF,   /* UINT16 conn_int_max  */
396                                                BTM_BLE_CONN_SLAVE_LATENCY_DEF,  /* UINT16 conn_latency  */
397                                                BTM_BLE_CONN_TIMEOUT_DEF,        /* UINT16 conn_timeout  */
398                                                0,                       /* UINT16 min_len       */
399                                                0))                      /* UINT16 max_len       */
400            {
401                /* start auto connection failed */
402                exec =  FALSE;
403            }
404            else
405            {
406                btm_ble_set_conn_st (BLE_BG_CONN);
407                p_cb->wl_state |= BTM_BLE_WL_INIT;
408            }
409        }
410        else
411        {
412            exec = FALSE;
413        }
414    }
415    else
416    {
417        if (p_cb->conn_state == BLE_BG_CONN)
418        {
419            btsnd_hcic_ble_create_conn_cancel();
420            btm_ble_set_conn_st (BLE_CONN_CANCEL);
421            p_cb->wl_state |= BTM_BLE_WL_INIT;
422
423#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
424            if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
425                btm_ble_vendor_disable_irk_list();
426#endif
427        }
428        else
429        {
430#if 0
431            BTM_TRACE_ERROR("conn_st = %d, not in auto conn state, can not stop.", p_cb->conn_state);
432            exec = FALSE;
433#endif
434        }
435    }
436    return exec;
437}
438
439/*******************************************************************************
440**
441** Function         btm_ble_start_select_conn
442**
443** Description      This function is to start/stop selective connection procedure.
444**
445** Parameters       start: TRUE to start; FALSE to stop.
446**                  p_select_cback: callback function to return application
447**                                  selection.
448**
449** Returns          BOOLEAN: selective connectino procedure is started.
450**
451*******************************************************************************/
452BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK   *p_select_cback)
453{
454    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
455    UINT16 scan_int, scan_win;
456
457    BTM_TRACE_EVENT ("btm_ble_start_select_conn");
458
459    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
460    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
461
462    if (start)
463    {
464        if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
465        {
466            if (p_select_cback != NULL)
467                btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
468
469            btm_execute_wl_dev_operation();
470
471            btm_update_scanner_filter_policy(SP_ADV_WL);
472            btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;
473
474            if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS,  /* use passive scan by default */
475                                                scan_int, /* scan interval */
476                                                scan_win,    /* scan window */
477                                                p_cb->addr_mgnt_cb.own_addr_type,
478                                                SP_ADV_WL)              /* process advertising packets only from devices in the White List */
479                )
480                return FALSE;
481
482            if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN))
483            {
484                BTM_TRACE_ERROR("peripheral device cannot initiate passive scan for a selective connection");
485                return FALSE;
486            }
487            else if (p_cb->bg_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
488            {
489
490                if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
491                    return FALSE;
492
493                /* mark up inquiry status flag */
494                p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
495                p_cb->wl_state |= BTM_BLE_WL_SCAN;
496            }
497        }
498        else
499        {
500            BTM_TRACE_ERROR("scan active, can not start selective connection procedure");
501            return FALSE;
502        }
503    }
504    else /* disable selective connection mode */
505    {
506        p_cb->scan_activity &= ~BTM_LE_SELECT_CONN_ACTIVE;
507        p_cb->p_select_cback = NULL;
508
509#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
510        if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
511            btm_ble_vendor_disable_irk_list();
512#endif
513        p_cb->wl_state |= BTM_BLE_WL_SCAN;
514
515        /* stop scanning */
516        if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
517            btm_ble_stop_scan(); /* duplicate filtering enabled */
518        btm_update_scanner_filter_policy(SP_ADV_ALL);
519    }
520    return TRUE;
521}
522/*******************************************************************************
523**
524** Function         btm_ble_initiate_select_conn
525**
526** Description      This function is to start/stop selective connection procedure.
527**
528** Parameters       start: TRUE to start; FALSE to stop.
529**                  p_select_cback: callback function to return application
530**                                  selection.
531**
532** Returns          BOOLEAN: selective connectino procedure is started.
533**
534*******************************************************************************/
535void btm_ble_initiate_select_conn(BD_ADDR bda)
536{
537    BTM_TRACE_EVENT ("btm_ble_initiate_select_conn");
538
539    /* use direct connection procedure to initiate connection */
540    if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda))
541    {
542        BTM_TRACE_ERROR("btm_ble_initiate_select_conn failed");
543    }
544}
545/*******************************************************************************
546**
547** Function         btm_ble_suspend_bg_conn
548**
549** Description      This function is to suspend an active background connection
550**                  procedure.
551**
552** Parameters       none.
553**
554** Returns          none.
555**
556*******************************************************************************/
557void btm_ble_suspend_bg_conn(void)
558{
559    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
560    BTM_TRACE_EVENT ("btm_ble_suspend_bg_conn");
561
562    if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
563    {
564        btm_ble_start_auto_conn(FALSE);
565    }
566    else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
567    {
568        btm_ble_start_select_conn(FALSE, NULL);
569    }
570}
571/*******************************************************************************
572**
573** Function         btm_suspend_wl_activity
574**
575** Description      This function is to suspend white list related activity
576**
577** Returns          none.
578**
579*******************************************************************************/
580static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state)
581{
582    if (wl_state & BTM_BLE_WL_INIT)
583    {
584        btm_ble_start_auto_conn(FALSE);
585    }
586    if (wl_state & BTM_BLE_WL_SCAN)
587    {
588        btm_ble_start_select_conn(FALSE, NULL);
589    }
590    if (wl_state & BTM_BLE_WL_ADV)
591    {
592        btm_ble_stop_adv();
593    }
594
595}
596/*******************************************************************************
597**
598** Function         btm_resume_wl_activity
599**
600** Description      This function is to resume white list related activity
601**
602** Returns          none.
603**
604*******************************************************************************/
605static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state)
606{
607    btm_ble_resume_bg_conn();
608
609    if (wl_state & BTM_BLE_WL_ADV)
610    {
611       btm_ble_start_adv();
612    }
613
614}
615/*******************************************************************************
616**
617** Function         btm_ble_resume_bg_conn
618**
619** Description      This function is to resume a background auto connection
620**                  procedure.
621**
622** Parameters       none.
623**
624** Returns          none.
625**
626*******************************************************************************/
627BOOLEAN btm_ble_resume_bg_conn(void)
628{
629    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
630    BOOLEAN ret = FALSE;
631
632    if (p_cb->bg_conn_type != BTM_BLE_CONN_NONE)
633    {
634        if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
635            ret = btm_ble_start_auto_conn(TRUE);
636
637        if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
638            ret = btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
639    }
640
641    return ret;
642}
643/*******************************************************************************
644**
645** Function         btm_ble_get_conn_st
646**
647** Description      This function get BLE connection state
648**
649** Returns          connection state
650**
651*******************************************************************************/
652tBTM_BLE_CONN_ST btm_ble_get_conn_st(void)
653{
654    return btm_cb.ble_ctr_cb.conn_state;
655}
656/*******************************************************************************
657**
658** Function         btm_ble_set_conn_st
659**
660** Description      This function set BLE connection state
661**
662** Returns          None.
663**
664*******************************************************************************/
665void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
666{
667    btm_cb.ble_ctr_cb.conn_state = new_st;
668    if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN) {
669        btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_INIT;
670        btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT);
671    } else {
672        btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_INIT;
673        btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
674    }
675}
676
677/*******************************************************************************
678**
679** Function         btm_ble_enqueue_direct_conn_req
680**
681** Description      This function enqueue the direct connection request
682**
683** Returns          None.
684**
685*******************************************************************************/
686void btm_ble_enqueue_direct_conn_req(void *p_param)
687{
688    tBTM_BLE_CONN_REQ   *p = (tBTM_BLE_CONN_REQ *)GKI_getbuf(sizeof(tBTM_BLE_CONN_REQ));
689
690    p->p_param = p_param;
691
692    GKI_enqueue (&btm_cb.ble_ctr_cb.conn_pending_q, p);
693}
694/*******************************************************************************
695**
696** Function         btm_send_pending_direct_conn
697**
698** Description      This function send the pending direct connection request in queue
699**
700** Returns          TRUE if started, FALSE otherwise
701**
702*******************************************************************************/
703BOOLEAN btm_send_pending_direct_conn(void )
704{
705    tBTM_BLE_CONN_REQ *p_req;
706    BOOLEAN     rt = FALSE;
707
708    if ( btm_cb.ble_ctr_cb.conn_pending_q.count )
709    {
710        p_req = (tBTM_BLE_CONN_REQ*)GKI_dequeue (&btm_cb.ble_ctr_cb.conn_pending_q);
711
712        rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param));
713
714        GKI_freebuf((void *)p_req);
715    }
716
717    return rt;
718}
719
720#endif
721
722
723