1/******************************************************************************
2 *
3 *  Copyright (C) 2014  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#include <string.h>
20#include "bt_target.h"
21
22#if (BLE_INCLUDED == TRUE)
23#include "bt_types.h"
24#include "hcimsgs.h"
25#include "btu.h"
26#include "btm_int.h"
27#include "bt_utils.h"
28#include "hcidefs.h"
29#include "btm_ble_api.h"
30#include "vendor_ble.h"
31
32#define BTM_BLE_ADV_FILT_META_HDR_LENGTH 3
33#define BTM_BLE_ADV_FILT_FEAT_SELN_LEN 13
34
35#define BTM_BLE_PF_BIT_TO_MASK(x)          (UINT16)(1 << (x))
36
37
38tBTM_BLE_ADV_FILTER_CB btm_ble_adv_filt_cb;
39tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
40static const BD_ADDR     na_bda= {0};
41
42static UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
43                                  UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr, UINT8 num_available);
44
45#define BTM_BLE_SET_SCAN_PF_OPCODE(x, y) (((x)<<4)|y)
46#define BTM_BLE_GET_SCAN_PF_SUBCODE(x)    ((x) >> 4)
47#define BTM_BLE_GET_SCAN_PF_ACTION(x)    ((x) & 0x0f)
48#define BTM_BLE_INVALID_COUNTER     0xff
49
50
51/* length of each multi adv sub command */
52#define BTM_BLE_ADV_FILTER_ENB_LEN                       3
53
54/* length of each batch scan command */
55#define BTM_BLE_ADV_FILTER_CLEAR_LEN            3
56#define BTM_BLE_ADV_FILTER_LEN     2
57
58#define BTM_BLE_ADV_FILT_CB_EVT_MASK       0xF0
59#define BTM_BLE_ADV_FILT_SUBCODE_MASK      0x0F
60
61/*******************************************************************************
62**
63** Function         btm_ble_obtain_vsc_details
64**
65** Description      This function obtains the VSC details
66**
67** Parameters
68**
69** Returns          status
70**
71*******************************************************************************/
72tBTM_STATUS btm_ble_obtain_vsc_details()
73{
74    tBTM_STATUS st = BTM_SUCCESS;
75
76#if BLE_VND_INCLUDED == TRUE
77    BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
78    if (0 == cmn_ble_vsc_cb.max_filter)
79    {
80        st = BTM_MODE_UNSUPPORTED;
81        return st;
82    }
83#else
84    cmn_ble_vsc_cb.max_filter = BTM_BLE_MAX_FILTER_COUNTER;
85#endif
86    return st;
87}
88
89/*******************************************************************************
90**
91** Function         btm_ble_advfilt_enq_op_q
92**
93** Description      enqueue an adv filter operation in q to check command complete
94**                  status
95**
96** Returns          void
97**
98*******************************************************************************/
99void btm_ble_advfilt_enq_op_q(UINT8 action, UINT8 ocf, tBTM_BLE_FILT_CB_EVT cb_evt,
100                              tBTM_BLE_REF_VALUE ref, tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback,
101                              tBTM_BLE_PF_PARAM_CBACK  *p_filt_param_cback)
102{
103    btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx] = (action |(ocf << 4));
104    btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.next_idx] = ref;
105    btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.next_idx] = cb_evt;
106    btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.next_idx] = p_cmpl_cback;
107    btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.next_idx]
108        = p_filt_param_cback;
109    BTM_TRACE_DEBUG("btm_ble_advfilt_enq_op_q: act_ocf:%d, action:%d, ocf:%d,cb_evt;%d, cback:%x",
110        btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx], action,
111        ocf, cb_evt, p_cmpl_cback);
112    btm_ble_adv_filt_cb.op_q.next_idx = (btm_ble_adv_filt_cb.op_q.next_idx + 1)
113                    % BTM_BLE_PF_TYPE_MAX;
114}
115
116/*******************************************************************************
117**
118** Function         btm_ble_advfilt_deq_op_q
119**
120** Description      dequeue an adv filter operation from q when command complete
121**                  is received
122**
123** Returns          void
124**
125*******************************************************************************/
126void btm_ble_advfilt_deq_op_q(UINT8 *p_action,UINT8 *p_ocf, tBTM_BLE_FILT_CB_EVT *p_cb_evt,
127                              tBTM_BLE_REF_VALUE *p_ref, tBTM_BLE_PF_CFG_CBACK ** p_cmpl_cback,
128                              tBTM_BLE_PF_PARAM_CBACK  **p_filt_param_cback)
129{
130    *p_ocf = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx] >> 4);
131    *p_action = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx]
132                & BTM_BLE_ADV_FILT_SUBCODE_MASK);
133    *p_ref = btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.pending_idx];
134    *p_cb_evt = btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.pending_idx];
135    *p_cmpl_cback = btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.pending_idx];
136    *p_filt_param_cback =
137        btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.pending_idx];
138
139    btm_ble_adv_filt_cb.op_q.pending_idx = (btm_ble_adv_filt_cb.op_q.pending_idx + 1)
140        % BTM_BLE_PF_TYPE_MAX;
141    BTM_TRACE_DEBUG("btm_ble_advfilt_deq_op_q: ocf:%d, action:%d, ref_value:%d, cb_evt:%x",
142        *p_ocf,*p_action, *p_ref, *p_cb_evt);
143}
144
145/*******************************************************************************
146**
147** Function         btm_ble_condtype_to_ocf
148**
149** Description      Convert cond_type to OCF
150**
151** Returns          Returns ocf value
152**
153*******************************************************************************/
154UINT8 btm_ble_condtype_to_ocf(UINT8 cond_type)
155{
156    UINT8 ocf = 0;
157
158    switch(cond_type)
159    {
160        case BTM_BLE_PF_ADDR_FILTER:
161          ocf = BTM_BLE_META_PF_ADDR;
162          break;
163        case BTM_BLE_PF_SRVC_UUID:
164          ocf = BTM_BLE_META_PF_UUID;
165          break;
166        case BTM_BLE_PF_SRVC_SOL_UUID:
167           ocf = BTM_BLE_META_PF_SOL_UUID;
168           break;
169        case BTM_BLE_PF_LOCAL_NAME:
170           ocf = BTM_BLE_META_PF_LOCAL_NAME;
171           break;
172        case BTM_BLE_PF_MANU_DATA:
173           ocf = BTM_BLE_META_PF_MANU_DATA;
174           break;
175        case BTM_BLE_PF_SRVC_DATA_PATTERN:
176           ocf = BTM_BLE_META_PF_SRVC_DATA;
177           break;
178        case BTM_BLE_PF_TYPE_ALL:
179           ocf = BTM_BLE_META_PF_ALL;
180           break;
181        default:
182           ocf = BTM_BLE_PF_TYPE_MAX;
183           break;
184    }
185    return ocf;
186}
187
188/*******************************************************************************
189**
190** Function         btm_ble_ocf_to_condtype
191**
192** Description      Convert OCF to cond type
193**
194** Returns          Returns condtype value
195**
196*******************************************************************************/
197UINT8 btm_ble_ocf_to_condtype(UINT8 ocf)
198{
199    UINT8 cond_type = 0;
200
201    switch(ocf)
202    {
203        case BTM_BLE_META_PF_FEAT_SEL:
204           cond_type = BTM_BLE_META_PF_FEAT_SEL;
205           break;
206        case BTM_BLE_META_PF_ADDR:
207          cond_type = BTM_BLE_PF_ADDR_FILTER;
208          break;
209        case BTM_BLE_META_PF_UUID:
210          cond_type = BTM_BLE_PF_SRVC_UUID;
211          break;
212        case BTM_BLE_META_PF_SOL_UUID:
213           cond_type = BTM_BLE_PF_SRVC_SOL_UUID;
214           break;
215        case BTM_BLE_META_PF_LOCAL_NAME:
216           cond_type = BTM_BLE_PF_LOCAL_NAME;
217           break;
218        case BTM_BLE_META_PF_MANU_DATA:
219           cond_type = BTM_BLE_PF_MANU_DATA;
220           break;
221        case BTM_BLE_META_PF_SRVC_DATA:
222           cond_type = BTM_BLE_PF_SRVC_DATA_PATTERN;
223           break;
224        case BTM_BLE_META_PF_ALL:
225           cond_type = BTM_BLE_PF_TYPE_ALL;
226           break;
227        default:
228           cond_type = BTM_BLE_PF_TYPE_MAX;
229           break;
230    }
231    return cond_type;
232}
233
234/*******************************************************************************
235**
236** Function         btm_ble_scan_pf_cmpl_cback
237**
238** Description      the BTM BLE customer feature VSC complete callback for ADV PF filtering
239**
240** Returns          pointer to the counter if found; NULL otherwise.
241**
242*******************************************************************************/
243void btm_ble_scan_pf_cmpl_cback(tBTM_VSC_CMPL *p_params)
244{
245    UINT8  status = 0;
246    UINT8  *p = p_params->p_param_buf, op_subcode = 0, action = 0xff;
247    UINT16  evt_len = p_params->param_len;
248    UINT8   ocf = BTM_BLE_META_PF_ALL, cond_type = 0;
249    UINT8   num_avail = 0, cb_evt = 0;
250    tBTM_BLE_REF_VALUE ref_value = 0;
251    tBTM_BLE_PF_CFG_CBACK *p_scan_cfg_cback = NULL;
252    tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback = NULL;
253
254    if (evt_len < 3 || evt_len > 4)
255    {
256        BTM_TRACE_ERROR("cannot interpret APCF callback status = %d, length = %d", status, evt_len);
257        btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback,
258                                 &p_filt_param_cback);
259        return;
260    }
261
262    btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback,
263                             &p_filt_param_cback);
264
265    STREAM_TO_UINT8(status, p);
266    STREAM_TO_UINT8(op_subcode, p);
267    STREAM_TO_UINT8(action, p);
268
269    /* Ignore the event, if it is not the same one expected */
270    if (3 == evt_len)
271    {
272        if(ocf != op_subcode)
273        {
274             BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:3-Incorrect opcode :%d, %d, %d, %d, %d, %d",
275                                        ocf, op_subcode, action, evt_len, ref_value, status);
276             return;
277        }
278        else
279        {
280            if(NULL != btm_ble_adv_filt_cb.p_filt_stat_cback)
281               btm_ble_adv_filt_cb.p_filt_stat_cback(action, status, ref_value);
282            BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback enabled/disabled, %d, %d, %d, %d",
283                                         ocf, action, status, ref_value);
284            return;
285        }
286    }
287
288    if (4 == evt_len && ocf != op_subcode)
289    {
290        BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:4-Incorrect opcode: %d, %d, %d, %d, %d",
291                                ocf, op_subcode, action, status, ref_value);
292        return;
293    }
294
295    STREAM_TO_UINT8(num_avail, p);
296    switch (op_subcode)
297    {
298        case BTM_BLE_META_PF_ADDR:
299        case BTM_BLE_META_PF_UUID:
300        case BTM_BLE_META_PF_SOL_UUID:
301        case BTM_BLE_META_PF_LOCAL_NAME:
302        case BTM_BLE_META_PF_MANU_DATA:
303        case BTM_BLE_META_PF_SRVC_DATA:
304           cond_type = btm_ble_ocf_to_condtype(ocf);
305           BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback Recd: %d, %d, %d, %d, %d, %d", op_subcode,
306                                        ocf, action, status, ref_value, num_avail);
307           if (HCI_SUCCESS == status)
308           {
309               if (memcmp(&btm_ble_adv_filt_cb.cur_filter_target.bda, &na_bda, BD_ADDR_LEN) == 0)
310                   btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail);
311               else
312                   btm_ble_cs_update_pf_counter(action, cond_type,
313                            &btm_ble_adv_filt_cb.cur_filter_target, num_avail);
314           }
315
316           /* send ADV PF operation complete */
317           btm_ble_adv_filt_cb.op_type = 0;
318           break;
319
320        case BTM_BLE_META_PF_FEAT_SEL:
321            BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback-Feat sel event: %d, %d, %d, %d",
322                                action, status, ref_value, num_avail);
323            break;
324
325        default:
326            BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback: unknown operation: %d", op_subcode);
327            break;
328    }
329
330    switch(cb_evt)
331    {
332        BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback: calling the cback: %d", cb_evt);
333        case BTM_BLE_FILT_CFG:
334            if(NULL != p_scan_cfg_cback)
335               p_scan_cfg_cback(action, cond_type, num_avail, status, ref_value);
336            break;
337        case BTM_BLE_FILT_ADV_PARAM:
338            if(NULL != p_filt_param_cback)
339               p_filt_param_cback(action, num_avail, ref_value, status);
340            break;
341        default:
342            break;
343    }
344}
345
346/*******************************************************************************
347**
348** Function         btm_ble_find_addr_filter_counter
349**
350** Description      find the per bd address ADV payload filter counter by BD_ADDR.
351**
352** Returns          pointer to the counter if found; NULL otherwise.
353**
354*******************************************************************************/
355tBTM_BLE_PF_COUNT* btm_ble_find_addr_filter_counter(tBLE_BD_ADDR *p_le_bda)
356{
357    UINT8               i;
358    tBTM_BLE_PF_COUNT   *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1];
359
360    if (p_le_bda == NULL)
361        return &btm_ble_adv_filt_cb.p_addr_filter_count[0];
362
363    for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++)
364    {
365        if (p_addr_filter->in_use &&
366            memcmp(p_le_bda->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)
367        {
368            return p_addr_filter;
369        }
370    }
371    return NULL;
372}
373
374/*******************************************************************************
375**
376** Function         btm_ble_alloc_addr_filter_counter
377**
378** Description      allocate the per device adv payload filter counter.
379**
380** Returns          pointer to the counter if allocation succeed; NULL otherwise.
381**
382*******************************************************************************/
383tBTM_BLE_PF_COUNT * btm_ble_alloc_addr_filter_counter(BD_ADDR bd_addr)
384{
385    UINT8               i;
386    tBTM_BLE_PF_COUNT   *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1];
387
388    for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++)
389    {
390        if (memcmp(na_bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)
391        {
392            memcpy(p_addr_filter->bd_addr, bd_addr, BD_ADDR_LEN);
393            p_addr_filter->in_use = TRUE;
394            return p_addr_filter;
395        }
396    }
397    return NULL;
398}
399/*******************************************************************************
400**
401** Function         btm_ble_dealloc_addr_filter_counter
402**
403** Description      de-allocate the per device adv payload filter counter.
404**
405** Returns          TRUE if deallocation succeed; FALSE otherwise.
406**
407*******************************************************************************/
408BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filter_type)
409{
410    UINT8               i;
411    tBTM_BLE_PF_COUNT   *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1];
412    BOOLEAN             found = FALSE;
413
414    if (BTM_BLE_PF_TYPE_ALL == filter_type && NULL == p_bd_addr)
415        memset(&btm_ble_adv_filt_cb.p_addr_filter_count[0], 0, sizeof(tBTM_BLE_PF_COUNT));
416
417    for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++)
418    {
419        if ((p_addr_filter->in_use) && (NULL == p_bd_addr ||
420            (NULL != p_bd_addr &&
421            memcmp(p_bd_addr->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)))
422        {
423            found = TRUE;
424            memset(p_addr_filter, 0, sizeof(tBTM_BLE_PF_COUNT));
425
426            if (NULL != p_bd_addr) break;
427        }
428    }
429    return found;
430}
431
432/*******************************************************************************
433**
434** Function         btm_ble_update_pf_local_name
435**
436** Description      this function update(add,delete or clear) the adv lcoal name filtering condition.
437**
438**
439** Returns          BTM_SUCCESS if sucessful,
440**                  BTM_ILLEGAL_VALUE if paramter is not valid.
441**
442*******************************************************************************/
443tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action,
444                                         tBTM_BLE_PF_FILT_INDEX filt_index,
445                                         tBTM_BLE_PF_COND_PARAM *p_cond)
446{
447    tBTM_BLE_PF_LOCAL_NAME_COND *p_local_name = (p_cond == NULL) ? NULL : &p_cond->local_name;
448    UINT8       param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
449                *p = param,
450                len = BTM_BLE_ADV_FILT_META_HDR_LENGTH;
451    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
452
453    memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
454
455    UINT8_TO_STREAM(p, BTM_BLE_META_PF_LOCAL_NAME);
456    UINT8_TO_STREAM(p, action);
457
458    /* Filter index */
459    UINT8_TO_STREAM(p, filt_index);
460
461    if (BTM_BLE_SCAN_COND_ADD == action ||
462        BTM_BLE_SCAN_COND_DELETE == action)
463    {
464        if (NULL == p_local_name)
465            return st;
466
467        if (p_local_name->data_len > BTM_BLE_PF_STR_LEN_MAX)
468            p_local_name->data_len = BTM_BLE_PF_STR_LEN_MAX;
469
470        ARRAY_TO_STREAM(p, p_local_name->p_data, p_local_name->data_len);
471        len += p_local_name->data_len;
472    }
473
474    /* send local name filter */
475    if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
476                              len,
477                              param,
478                              btm_ble_scan_pf_cmpl_cback))
479            != BTM_NO_RESOURCES)
480    {
481        memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
482    }
483    else
484    {
485        BTM_TRACE_ERROR("Local Name PF filter update failed");
486    }
487
488    return st;
489}
490
491
492/*******************************************************************************
493**
494** Function         btm_ble_update_srvc_data_change
495**
496** Description      this function update(add/remove) service data change filter.
497**
498**
499** Returns          BTM_SUCCESS if sucessful,
500**                  BTM_ILLEGAL_VALUE if paramter is not valid.
501**
502*******************************************************************************/
503tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action,
504                                       tBTM_BLE_PF_FILT_INDEX filt_index,
505                                       tBTM_BLE_PF_COND_PARAM *p_cond)
506{
507    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
508    tBLE_BD_ADDR   *p_bd_addr = p_cond ? &p_cond->target_addr : NULL;
509    UINT8           num_avail = (action == BTM_BLE_SCAN_COND_ADD) ? 0 : 1;
510
511    if (btm_ble_cs_update_pf_counter (action, BTM_BLE_PF_SRVC_DATA, p_bd_addr, num_avail)
512                    != BTM_BLE_INVALID_COUNTER)
513        st = BTM_SUCCESS;
514
515    return st;
516}
517
518/*******************************************************************************
519**
520** Function         btm_ble_update_pf_manu_data
521**
522** Description      this function update(add,delete or clear) the adv manufacturer
523**                  data filtering condition.
524**
525**
526** Returns          BTM_SUCCESS if sucessful,
527**                  BTM_ILLEGAL_VALUE if paramter is not valid.
528**
529*******************************************************************************/
530tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action,
531                                        tBTM_BLE_PF_FILT_INDEX filt_index,
532                                        tBTM_BLE_PF_COND_PARAM *p_data,
533                                        tBTM_BLE_PF_COND_TYPE cond_type,
534                                        tBTM_BLE_FILT_CB_EVT cb_evt,
535                                        tBTM_BLE_REF_VALUE ref_value)
536{
537    tBTM_BLE_PF_MANU_COND *p_manu_data = (p_data == NULL) ? NULL : &p_data->manu_data;
538    tBTM_BLE_PF_SRVC_PATTERN_COND *p_srvc_data = (p_data == NULL) ? NULL : &p_data->srvc_data;
539
540    UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
541          *p = param,
542          len = BTM_BLE_ADV_FILT_META_HDR_LENGTH;
543    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
544
545    if (NULL == p_data)
546        return st;
547
548    memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX
549                    + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
550
551    if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type)
552    {
553        UINT8_TO_STREAM(p, BTM_BLE_META_PF_SRVC_DATA);
554    }
555    else
556    {
557        UINT8_TO_STREAM(p, BTM_BLE_META_PF_MANU_DATA);
558    }
559
560    UINT8_TO_STREAM(p, action);
561
562    /* Filter index */
563    UINT8_TO_STREAM(p, filt_index);
564
565    if (BTM_BLE_SCAN_COND_ADD == action || BTM_BLE_SCAN_COND_DELETE == action)
566    {
567        if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type)
568        {
569            if (NULL == p_srvc_data)
570                return st;
571            if (p_srvc_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2))
572                p_srvc_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
573
574            if (p_srvc_data->data_len > 0)
575            {
576                ARRAY_TO_STREAM(p, p_srvc_data->p_pattern, p_srvc_data->data_len);
577                len += (p_srvc_data->data_len);
578                ARRAY_TO_STREAM(p, p_srvc_data->p_pattern_mask, p_srvc_data->data_len);
579            }
580
581            len += (p_srvc_data->data_len);
582            BTM_TRACE_DEBUG("Service data length: %d", len);
583        }
584        else
585        {
586            if (NULL == p_manu_data)
587            {
588                BTM_TRACE_ERROR("btm_ble_update_pf_manu_data - No manuf data");
589                return st;
590            }
591            BTM_TRACE_EVENT("btm_ble_update_pf_manu_data length: %d",
592                                    p_manu_data->data_len);
593            if (p_manu_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2))
594                p_manu_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
595
596            UINT16_TO_STREAM(p, p_manu_data->company_id);
597            if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL)
598            {
599                ARRAY_TO_STREAM(p, p_manu_data->p_pattern, p_manu_data->data_len);
600                len += (p_manu_data->data_len + 2);
601            }
602            else
603                len += 2;
604
605            if (p_manu_data->company_id_mask != 0)
606            {
607                UINT16_TO_STREAM (p, p_manu_data->company_id_mask);
608            }
609            else
610            {
611                memset(p, 0xff, 2);
612                p += 2;
613            }
614            len += 2;
615
616            if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL)
617            {
618                ARRAY_TO_STREAM(p, p_manu_data->p_pattern_mask, p_manu_data->data_len);
619                len += (p_manu_data->data_len);
620            }
621
622            BTM_TRACE_DEBUG("Manuf data length: %d", len);
623        }
624    }
625
626    /* send manufacturer*/
627    if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
628                              len,
629                              param,
630                              btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
631    {
632        memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
633    }
634    else
635    {
636        BTM_TRACE_ERROR("manufacturer data PF filter update failed");
637    }
638
639    return st;
640}
641
642/*******************************************************************************
643**
644** Function         btm_ble_cs_update_pf_counter
645**
646** Description      this function is to update the adv data payload filter counter
647**
648** Returns          current number of the counter; BTM_BLE_INVALID_COUNTER if
649**                  counter update failed.
650**
651*******************************************************************************/
652UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
653                                  UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr,
654                                  UINT8 num_available)
655{
656    tBTM_BLE_PF_COUNT   *p_addr_filter = NULL;
657    UINT8               *p_counter = NULL;
658
659    btm_ble_obtain_vsc_details();
660
661    if (cond_type > BTM_BLE_PF_TYPE_ALL)
662    {
663        BTM_TRACE_ERROR("unknown PF filter condition type %d", cond_type);
664        return BTM_BLE_INVALID_COUNTER;
665    }
666
667    /* for these three types of filter, always generic */
668    if (BTM_BLE_PF_ADDR_FILTER == cond_type ||
669        BTM_BLE_PF_MANU_DATA == cond_type ||
670        BTM_BLE_PF_LOCAL_NAME == cond_type ||
671        BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type)
672        p_bd_addr = NULL;
673
674    if ((p_addr_filter = btm_ble_find_addr_filter_counter(p_bd_addr)) == NULL &&
675        BTM_BLE_SCAN_COND_ADD == action)
676    {
677        p_addr_filter = btm_ble_alloc_addr_filter_counter(p_bd_addr->bda);
678    }
679
680    if (NULL != p_addr_filter)
681    {
682        /* all filter just cleared */
683        if ((BTM_BLE_PF_TYPE_ALL == cond_type && BTM_BLE_SCAN_COND_CLEAR == action) ||
684            /* or bd address filter been deleted */
685            (BTM_BLE_PF_ADDR_FILTER == cond_type &&
686             (BTM_BLE_SCAN_COND_DELETE == action || BTM_BLE_SCAN_COND_CLEAR == action)))
687        {
688            btm_ble_dealloc_addr_filter_counter(p_bd_addr, cond_type);
689        }
690        /* if not feature selection, update new addition/reduction of the filter counter */
691        else if (cond_type != BTM_BLE_PF_TYPE_ALL)
692        {
693            p_counter = p_addr_filter->pf_counter;
694            if (num_available > 0)
695                p_counter[cond_type] += 1;
696
697            BTM_TRACE_DEBUG("counter = %d, maxfilt = %d, num_avbl=%d",
698                p_counter[cond_type], cmn_ble_vsc_cb.max_filter, num_available);
699            return p_counter[cond_type];
700        }
701    }
702    else
703    {
704        BTM_TRACE_ERROR("no matching filter counter found");
705    }
706    /* no matching filter located and updated */
707    return BTM_BLE_INVALID_COUNTER;
708}
709
710
711/*******************************************************************************
712**
713** Function         btm_ble_update_addr_filter
714**
715** Description      this function update(add,delete or clear) the address filter of adv.
716**
717**
718** Returns          BTM_SUCCESS if sucessful,
719**                  BTM_ILLEGAL_VALUE if paramter is not valid.
720**
721*******************************************************************************/
722tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action,
723                                       tBTM_BLE_PF_FILT_INDEX filt_index,
724                                       tBTM_BLE_PF_COND_PARAM *p_cond)
725{
726    UINT8       param[BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
727                * p= param;
728    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
729    tBLE_BD_ADDR *p_addr = (p_cond == NULL) ? NULL : &p_cond->target_addr;
730
731    memset(param, 0, BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
732
733    UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
734    UINT8_TO_STREAM(p, action);
735
736    /* Filter index */
737    UINT8_TO_STREAM(p, filt_index);
738
739    if (BTM_BLE_SCAN_COND_ADD == action ||
740        BTM_BLE_SCAN_COND_DELETE == action)
741    {
742        if (NULL == p_addr)
743            return st;
744
745        BDADDR_TO_STREAM(p, p_addr->bda);
746        UINT8_TO_STREAM(p, p_addr->type);
747    }
748    /* send address filter */
749    if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
750                              (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
751                              param,
752                              btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
753    {
754        memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
755    }
756    else
757    {
758        BTM_TRACE_ERROR("Broadcaster Address Filter Update failed");
759    }
760    return st;
761}
762
763/*******************************************************************************
764**
765** Function         btm_ble_update_uuid_filter
766**
767** Description      this function update(add,delete or clear) service UUID filter.
768**
769**
770** Returns          BTM_SUCCESS if sucessful,
771**                  BTM_ILLEGAL_VALUE if paramter is not valid.
772**
773*******************************************************************************/
774tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action,
775                                       tBTM_BLE_PF_FILT_INDEX filt_index,
776                                       tBTM_BLE_PF_COND_TYPE filter_type,
777                                       tBTM_BLE_PF_COND_PARAM *p_cond,
778                                       tBTM_BLE_FILT_CB_EVT cb_evt,
779                                       tBTM_BLE_REF_VALUE ref_value)
780{
781    UINT8       param[BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
782                * p= param,
783                len = BTM_BLE_ADV_FILT_META_HDR_LENGTH;
784    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
785    tBTM_BLE_PF_UUID_COND *p_uuid_cond;
786    UINT8           evt_type;
787
788    memset(param, 0, BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
789
790    if (BTM_BLE_PF_SRVC_UUID == filter_type)
791    {
792        evt_type = BTM_BLE_META_PF_UUID;
793        p_uuid_cond = p_cond ? &p_cond->srvc_uuid : NULL;
794    }
795    else
796    {
797        evt_type = BTM_BLE_META_PF_SOL_UUID;
798        p_uuid_cond = p_cond ? &p_cond->solicitate_uuid : NULL;
799    }
800
801    if (NULL == p_uuid_cond && action != BTM_BLE_SCAN_COND_CLEAR)
802    {
803        BTM_TRACE_ERROR("Illegal param for add/delete UUID filter");
804        return st;
805    }
806
807    /* need to add address filter first, if adding per bda UUID filter without address filter */
808    if (BTM_BLE_SCAN_COND_ADD == action && NULL != p_uuid_cond &&
809        p_uuid_cond->p_target_addr &&
810        btm_ble_find_addr_filter_counter(p_uuid_cond->p_target_addr) == NULL)
811    {
812        UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
813        UINT8_TO_STREAM(p, action);
814
815        /* Filter index */
816        UINT8_TO_STREAM(p, filt_index);
817
818        BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda);
819        UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type);
820
821        /* send address filter */
822        if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
823                                  (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
824                                  param,
825                                  btm_ble_scan_pf_cmpl_cback)) == BTM_NO_RESOURCES)
826        {
827            BTM_TRACE_ERROR("Update Address filter into controller failed.");
828            return st;
829        }
830
831        btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_ADDR, cb_evt, ref_value, NULL, NULL);
832        BTM_TRACE_DEBUG("Updated Address filter");
833    }
834
835    p = param;
836    UINT8_TO_STREAM(p, evt_type);
837    UINT8_TO_STREAM(p, action);
838
839    /* Filter index */
840    UINT8_TO_STREAM(p, filt_index);
841
842    if ((BTM_BLE_SCAN_COND_ADD == action ||
843        BTM_BLE_SCAN_COND_DELETE == action) &&
844        NULL != p_uuid_cond)
845    {
846        if (p_uuid_cond->uuid.len == LEN_UUID_16)
847        {
848            UINT16_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid16);
849            len += LEN_UUID_16;
850        }
851        else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */
852        {
853            UINT32_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid32);
854            len += LEN_UUID_32;
855        }
856        else if (p_uuid_cond->uuid.len == LEN_UUID_128)
857        {
858            ARRAY_TO_STREAM (p, p_uuid_cond->uuid.uu.uuid128, LEN_UUID_128);
859            len += LEN_UUID_128;
860        }
861        else
862        {
863            BTM_TRACE_ERROR("illegal UUID length: %d", p_uuid_cond->uuid.len);
864            return BTM_ILLEGAL_VALUE;
865        }
866
867        if (NULL != p_uuid_cond->p_uuid_mask)
868        {
869            if (p_uuid_cond->uuid.len == LEN_UUID_16)
870            {
871                UINT16_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid16_mask);
872                len += LEN_UUID_16;
873            }
874            else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */
875            {
876                UINT32_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid32_mask);
877                len += LEN_UUID_32;
878            }
879            else if (p_uuid_cond->uuid.len == LEN_UUID_128)
880            {
881                ARRAY_TO_STREAM (p, p_uuid_cond->p_uuid_mask->uuid128_mask, LEN_UUID_128);
882                len += LEN_UUID_128;
883            }
884        }
885        else
886        {
887            memset(p, 0xff, p_uuid_cond->uuid.len);
888            len += p_uuid_cond->uuid.len;
889        }
890        BTM_TRACE_DEBUG("btm_ble_update_uuid_filter : %d, %d, %d, %d", filter_type, evt_type,
891                        p_uuid_cond->uuid.len, len);
892    }
893
894    /* send UUID filter update */
895    if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
896                              len,
897                              param,
898                              btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
899    {
900        if (p_uuid_cond && p_uuid_cond->p_target_addr)
901            memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_uuid_cond->p_target_addr,
902                    sizeof(tBLE_BD_ADDR));
903        else
904            memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
905    }
906    else
907    {
908        BTM_TRACE_ERROR("UUID filter udpating failed");
909    }
910
911    return st;
912}
913
914
915/*******************************************************************************
916**
917** Function         btm_ble_clear_scan_pf_filter
918**
919** Description      clear all adv payload filter by de-select all the adv pf feature bits
920**
921**
922** Returns          BTM_SUCCESS if sucessful,
923**                  BTM_ILLEGAL_VALUE if paramter is not valid.
924**
925*******************************************************************************/
926tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action,
927                                       tBTM_BLE_PF_FILT_INDEX filt_index,
928                                       tBTM_BLE_PF_COND_PARAM *p_cond,
929                                       tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback,
930                                       tBTM_BLE_FILT_CB_EVT cb_evt,
931                                       tBTM_BLE_REF_VALUE ref_value)
932{
933    tBLE_BD_ADDR *p_target = (p_cond == NULL)? NULL : &p_cond->target_addr;
934    tBTM_BLE_PF_COUNT *p_bda_filter;
935    tBTM_STATUS     st = BTM_WRONG_MODE;
936    UINT8           param[20], *p;
937
938    if (BTM_BLE_SCAN_COND_CLEAR != action)
939    {
940        BTM_TRACE_ERROR("unable to perform action:%d for generic adv filter type", action);
941        return BTM_ILLEGAL_VALUE;
942    }
943
944    p = param;
945    memset(param, 0, 20);
946
947    p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
948
949    if (NULL == p_bda_filter ||
950        /* not a generic filter */
951        (p_target != NULL && p_bda_filter))
952    {
953        BTM_TRACE_ERROR("Error: Can not clear filter, No PF filter has been configured!");
954        return st;
955    }
956
957    /* clear the general filter entry */
958    if (NULL == p_target)
959    {
960        /* clear manufactuer data filter */
961        st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL,
962                                    BTM_BLE_PF_MANU_DATA, cb_evt, ref_value);
963        if(BTM_CMD_STARTED == st)
964           btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_MANU_DATA, cb_evt,
965                                    ref_value, NULL, NULL);
966
967        /* clear local name filter */
968        st = btm_ble_update_pf_local_name(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL);
969        if(BTM_CMD_STARTED == st)
970           btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_LOCAL_NAME, cb_evt,
971                                    ref_value, NULL, NULL);
972
973        /* update the counter for service data */
974        st = btm_ble_update_srvc_data_change(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL);
975
976        /* clear UUID filter */
977        st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index,
978                                   BTM_BLE_PF_SRVC_UUID, NULL, cb_evt, ref_value);
979        if(BTM_CMD_STARTED == st)
980           btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_UUID, cb_evt, ref_value, NULL, NULL);
981
982        st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index,
983                                   BTM_BLE_PF_SRVC_SOL_UUID, NULL, cb_evt, ref_value);
984        if(BTM_CMD_STARTED == st)
985           btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SOL_UUID, cb_evt,
986                                    ref_value, NULL, NULL);
987
988        /* clear service data filter */
989        st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL,
990                                    BTM_BLE_PF_SRVC_DATA_PATTERN, cb_evt, ref_value);
991        if(BTM_CMD_STARTED == st)
992           btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SRVC_DATA, cb_evt,
993                                    ref_value, NULL, NULL);
994    }
995
996    /* select feature based on control block settings */
997    UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
998    UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR);
999
1000    /* Filter index */
1001    UINT8_TO_STREAM(p, filt_index);
1002
1003    /* set PCF selection */
1004    UINT32_TO_STREAM(p, BTM_BLE_PF_SELECT_NONE);
1005    /* set logic condition as OR as default */
1006    UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR);
1007
1008    if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1009                               (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN),
1010                                param,
1011                                btm_ble_scan_pf_cmpl_cback))
1012            != BTM_NO_RESOURCES)
1013    {
1014        if (p_target)
1015            memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_target, sizeof(tBLE_BD_ADDR));
1016        else
1017            memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
1018    }
1019    return st;
1020}
1021
1022/*******************************************************************************
1023**
1024** Function         BTM_BleAdvFilterParamSetup
1025**
1026** Description      This function is called to setup the adv data payload filter
1027**                  condition.
1028**
1029** Parameters       action - Type of action to be performed
1030**                       filt_index - Filter index
1031**                       p_filt_params - Filter parameters
1032**                       p_target - Target device
1033**                       p_cmpl_back - Callback pointer
1034**                       ref_value - reference value
1035**
1036** Returns          void
1037**
1038*******************************************************************************/
1039tBTM_STATUS BTM_BleAdvFilterParamSetup(int action, tBTM_BLE_PF_FILT_INDEX filt_index,
1040                                tBTM_BLE_PF_FILT_PARAMS *p_filt_params,
1041                                tBLE_BD_ADDR *p_target, tBTM_BLE_PF_PARAM_CBACK *p_cmpl_cback,
1042                                tBTM_BLE_REF_VALUE ref_value)
1043{
1044    UINT8           param[20], *p;
1045    tBTM_STATUS     st = BTM_WRONG_MODE;
1046    tBTM_BLE_PF_COUNT *p_bda_filter = NULL;
1047    UINT8 len =0;
1048
1049    if (BTM_SUCCESS  != btm_ble_obtain_vsc_details())
1050        return st;
1051
1052    p = param;
1053    memset(param, 0, 20);
1054    BTM_TRACE_EVENT (" BTM_BleAdvFilterParamSetup");
1055
1056    if (BTM_BLE_SCAN_COND_ADD == action)
1057    {
1058        p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
1059        if (NULL == p_bda_filter)
1060        {
1061           BTM_TRACE_ERROR("BD Address not found!");
1062           return st;
1063        }
1064
1065        BTM_TRACE_DEBUG("BTM_BleAdvFilterParamSetup : Feat mask:%d", p_filt_params->feat_seln);
1066        /* select feature based on control block settings */
1067        UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
1068        UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_ADD);
1069
1070        /* Filter index */
1071        UINT8_TO_STREAM(p, filt_index);
1072
1073        /* set PCF selection */
1074        UINT16_TO_STREAM(p, p_filt_params->feat_seln);
1075        /* set logic type */
1076        UINT16_TO_STREAM(p, p_filt_params->logic_type);
1077        /* set logic condition */
1078        UINT8_TO_STREAM(p, p_filt_params->filt_logic_type);
1079        /* set RSSI high threshold */
1080        UINT8_TO_STREAM(p, p_filt_params->rssi_high_thres);
1081        /* set delivery mode */
1082        UINT8_TO_STREAM(p, p_filt_params->dely_mode);
1083
1084        if (0x01 == p_filt_params->dely_mode)
1085        {
1086            /* set onfound timeout */
1087            UINT16_TO_STREAM(p, p_filt_params->found_timeout);
1088            /* set onfound timeout count*/
1089            UINT8_TO_STREAM(p, p_filt_params->found_timeout_cnt);
1090            /* set RSSI low threshold */
1091            UINT8_TO_STREAM(p, p_filt_params->rssi_low_thres);
1092            /* set onlost timeout */
1093            UINT16_TO_STREAM(p, p_filt_params->lost_timeout);
1094        }
1095
1096        len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN;
1097
1098        if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1099                                (UINT8)len,
1100                                 param,
1101                                 btm_ble_scan_pf_cmpl_cback))
1102               == BTM_NO_RESOURCES)
1103        {
1104            return st;
1105        }
1106        btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM,
1107                                 ref_value, NULL, p_cmpl_cback);
1108    }
1109    else
1110    if (BTM_BLE_SCAN_COND_DELETE == action)
1111    {
1112        /* select feature based on control block settings */
1113        UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
1114        UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_DELETE);
1115        /* Filter index */
1116        UINT8_TO_STREAM(p, filt_index);
1117
1118        if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1119                                (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH),
1120                                 param,
1121                                 btm_ble_scan_pf_cmpl_cback))
1122               == BTM_NO_RESOURCES)
1123        {
1124            return st;
1125        }
1126        btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL,  BTM_BLE_FILT_ADV_PARAM,
1127                                 ref_value, NULL, p_cmpl_cback);
1128    }
1129    else
1130    if (BTM_BLE_SCAN_COND_CLEAR == action)
1131    {
1132        /* Deallocate all filters here */
1133        btm_ble_dealloc_addr_filter_counter(NULL, BTM_BLE_PF_TYPE_ALL);
1134
1135        /* select feature based on control block settings */
1136        UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
1137        UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR);
1138
1139        if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1140                                (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH-1),
1141                                 param,
1142                                 btm_ble_scan_pf_cmpl_cback))
1143               == BTM_NO_RESOURCES)
1144        {
1145            return st;
1146        }
1147        btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL,  BTM_BLE_FILT_ADV_PARAM,
1148                                 ref_value, NULL, p_cmpl_cback);
1149    }
1150
1151    return st;
1152}
1153
1154/*******************************************************************************
1155**
1156** Function         BTM_BleEnableDisableFilterFeature
1157**
1158** Description      This function is called to enable / disable the APCF feature
1159**
1160** Parameters  enable the generic scan condition.
1161**                  enable: enable or disable the filter condition
1162**                  p_stat_cback - Status callback pointer
1163**                  ref_value   - Ref value
1164** Returns          void
1165**
1166*******************************************************************************/
1167tBTM_STATUS BTM_BleEnableDisableFilterFeature(UINT8 enable,
1168                                     tBTM_BLE_PF_STATUS_CBACK *p_stat_cback,
1169                                     tBTM_BLE_REF_VALUE ref_value)
1170{
1171    UINT8           param[20], *p;
1172    tBTM_STATUS     st = BTM_WRONG_MODE;
1173
1174    if (BTM_SUCCESS  != btm_ble_obtain_vsc_details())
1175       return st;
1176
1177    p = param;
1178    memset(param, 0, 20);
1179
1180    /* enable the content filter in controller */
1181    p = param;
1182    UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE);
1183    /* enable adv data payload filtering */
1184    UINT8_TO_STREAM(p, enable);
1185
1186    if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1187                              BTM_BLE_PCF_ENABLE_LEN, param,
1188                              btm_ble_scan_pf_cmpl_cback)) == BTM_CMD_STARTED)
1189    {
1190         btm_ble_adv_filt_cb.p_filt_stat_cback = p_stat_cback;
1191         btm_ble_advfilt_enq_op_q(enable, BTM_BLE_META_PF_ENABLE, BTM_BLE_FILT_ENABLE_DISABLE,
1192                                  ref_value, NULL, NULL);
1193    }
1194    return st;
1195}
1196
1197/*******************************************************************************
1198**
1199** Function         BTM_BleCfgFilterCondition
1200**
1201** Description      This function is called to configure the adv data payload filter
1202**                  condition.
1203**
1204** Parameters       action: to read/write/clear
1205**                  cond_type: filter condition type.
1206**                  filt_index - Filter index
1207**                  p_cond: filter condition parameter
1208**                  p_cmpl_cback  - Config callback pointer
1209**                  ref_value - Reference value
1210**
1211** Returns          void
1212**
1213*******************************************************************************/
1214tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action,
1215                                      tBTM_BLE_PF_COND_TYPE cond_type,
1216                                      tBTM_BLE_PF_FILT_INDEX filt_index,
1217                                      tBTM_BLE_PF_COND_PARAM *p_cond,
1218                                      tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback,
1219                                      tBTM_BLE_REF_VALUE ref_value)
1220{
1221    tBTM_STATUS     st = BTM_ILLEGAL_VALUE;
1222    UINT8 ocf = 0;
1223    BTM_TRACE_EVENT (" BTM_BleCfgFilterCondition action:%d, cond_type:%d, index:%d", action,
1224                        cond_type, filt_index);
1225
1226    if (BTM_SUCCESS  != btm_ble_obtain_vsc_details())
1227        return st;
1228
1229    switch (cond_type)
1230    {
1231        /* write service data filter */
1232        case BTM_BLE_PF_SRVC_DATA_PATTERN:
1233        /* write manufacturer data filter */
1234        case BTM_BLE_PF_MANU_DATA:
1235            st = btm_ble_update_pf_manu_data(action, filt_index, p_cond, cond_type, 0, ref_value);
1236            break;
1237
1238        /* write local name filter */
1239        case BTM_BLE_PF_LOCAL_NAME:
1240            st = btm_ble_update_pf_local_name(action, filt_index, p_cond);
1241            break;
1242
1243        /* filter on advertiser address */
1244        case BTM_BLE_PF_ADDR_FILTER:
1245            st = btm_ble_update_addr_filter(action, filt_index, p_cond);
1246            break;
1247
1248        /* filter on service/solicitated UUID */
1249        case BTM_BLE_PF_SRVC_UUID:
1250        case BTM_BLE_PF_SRVC_SOL_UUID:
1251            st = btm_ble_update_uuid_filter(action, filt_index, cond_type, p_cond, 0, ref_value);
1252            break;
1253
1254        case BTM_BLE_PF_SRVC_DATA:
1255            st = btm_ble_update_srvc_data_change(action, filt_index, p_cond);
1256            break;
1257
1258        case BTM_BLE_PF_TYPE_ALL: /* only used to clear filter */
1259            st = btm_ble_clear_scan_pf_filter(action, filt_index, p_cond, p_cmpl_cback,
1260                                              0, ref_value);
1261            break;
1262
1263        default:
1264            BTM_TRACE_WARNING("condition type [%d] not supported currently.", cond_type);
1265            break;
1266    }
1267
1268    if(BTM_CMD_STARTED == st && cond_type != BTM_BLE_PF_TYPE_ALL)
1269    {
1270       ocf = btm_ble_condtype_to_ocf(cond_type);
1271       btm_ble_advfilt_enq_op_q(action, ocf, BTM_BLE_FILT_CFG, ref_value, p_cmpl_cback, NULL);
1272    }
1273    else
1274    if(BTM_CMD_STARTED == st && BTM_BLE_PF_TYPE_ALL == cond_type)
1275    {
1276       btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_CFG,
1277                                ref_value, p_cmpl_cback, NULL);
1278    }
1279    return st;
1280}
1281
1282/*******************************************************************************
1283**
1284** Function         btm_ble_adv_filter_init
1285**
1286** Description      This function initializes the adv filter control block
1287**
1288** Parameters
1289**
1290** Returns          status
1291**
1292*******************************************************************************/
1293void btm_ble_adv_filter_init(void)
1294{
1295    memset(&btm_ble_adv_filt_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
1296    if (BTM_SUCCESS != btm_ble_obtain_vsc_details())
1297       return;
1298
1299    if (cmn_ble_vsc_cb.max_filter > 0)
1300    {
1301        btm_ble_adv_filt_cb.p_addr_filter_count =
1302            (tBTM_BLE_PF_COUNT*) GKI_getbuf( sizeof(tBTM_BLE_PF_COUNT) * cmn_ble_vsc_cb.max_filter);
1303    }
1304
1305    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
1306        return;
1307}
1308
1309/*******************************************************************************
1310**
1311** Function         btm_ble_adv_filter_cleanup
1312**
1313** Description      This function de-initializes the adv filter control block
1314**
1315** Parameters
1316**
1317** Returns          status
1318**
1319*******************************************************************************/
1320void btm_ble_adv_filter_cleanup(void)
1321{
1322    if (btm_ble_adv_filt_cb.p_addr_filter_count)
1323        GKI_freebuf (btm_ble_adv_filt_cb.p_addr_filter_count);
1324}
1325
1326#endif
1327