1 /******************************************************************************
3 * Copyright (C) 2014 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 //#define LOG_TAG "bt_btm_ble"
22 #include "common/bt_target.h"
24 #if (BLE_INCLUDED == TRUE)
25 #include "stack/bt_types.h"
26 #include "stack/hcimsgs.h"
27 #include "stack/btu.h"
29 #include "osi/allocator.h"
30 #include "stack/hcidefs.h"
31 #include "stack/btm_ble_api.h"
32 #include "device/controller.h"
34 #define BTM_BLE_ADV_FILT_META_HDR_LENGTH 3
35 #define BTM_BLE_ADV_FILT_FEAT_SELN_LEN 13
36 #define BTM_BLE_ADV_FILT_TRACK_NUM 2
38 #define BTM_BLE_PF_SELECT_NONE 0
40 /* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */
41 #define BTM_BLE_META_HDR_LENGTH 3
42 #define BTM_BLE_PF_FEAT_SEL_LEN 18
43 #define BTM_BLE_PCF_ENABLE_LEN 2
45 #define BTM_BLE_META_ADDR_LEN 7
46 #define BTM_BLE_META_UUID_LEN 40
48 #define BTM_BLE_PF_BIT_TO_MASK(x) (UINT16)(1 << (x))
51 tBTM_BLE_ADV_FILTER_CB btm_ble_adv_filt_cb;
52 tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
53 static const BD_ADDR na_bda = {0};
55 static UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
56 UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr, UINT8 num_available);
58 #define BTM_BLE_SET_SCAN_PF_OPCODE(x, y) (((x)<<4)|y)
59 #define BTM_BLE_GET_SCAN_PF_SUBCODE(x) ((x) >> 4)
60 #define BTM_BLE_GET_SCAN_PF_ACTION(x) ((x) & 0x0f)
61 #define BTM_BLE_INVALID_COUNTER 0xff
64 /* length of each multi adv sub command */
65 #define BTM_BLE_ADV_FILTER_ENB_LEN 3
67 /* length of each batch scan command */
68 #define BTM_BLE_ADV_FILTER_CLEAR_LEN 3
69 #define BTM_BLE_ADV_FILTER_LEN 2
71 #define BTM_BLE_ADV_FILT_CB_EVT_MASK 0xF0
72 #define BTM_BLE_ADV_FILT_SUBCODE_MASK 0x0F
74 /*******************************************************************************
76 ** Function btm_ble_obtain_vsc_details
78 ** Description This function obtains the VSC details
84 *******************************************************************************/
85 tBTM_STATUS btm_ble_obtain_vsc_details()
87 tBTM_STATUS st = BTM_SUCCESS;
89 #if BLE_VND_INCLUDED == TRUE
90 BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
91 if (0 == cmn_ble_vsc_cb.max_filter) {
92 st = BTM_MODE_UNSUPPORTED;
96 cmn_ble_vsc_cb.max_filter = BTM_BLE_MAX_FILTER_COUNTER;
101 /*******************************************************************************
103 ** Function btm_ble_advfilt_enq_op_q
105 ** Description enqueue an adv filter operation in q to check command complete
110 *******************************************************************************/
111 void btm_ble_advfilt_enq_op_q(UINT8 action, UINT8 ocf, tBTM_BLE_FILT_CB_EVT cb_evt,
112 tBTM_BLE_REF_VALUE ref, tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback,
113 tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback)
115 btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx] = (action | (ocf << 4));
116 btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.next_idx] = ref;
117 btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.next_idx] = cb_evt;
118 btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.next_idx] = p_cmpl_cback;
119 btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.next_idx]
120 = p_filt_param_cback;
121 BTM_TRACE_DEBUG("btm_ble_advfilt_enq_op_q: act_ocf:%d, action:%d, ocf:%d,cb_evt;%d, cback:%p",
122 btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.next_idx], action,
123 ocf, cb_evt, p_cmpl_cback);
124 btm_ble_adv_filt_cb.op_q.next_idx = (btm_ble_adv_filt_cb.op_q.next_idx + 1)
125 % BTM_BLE_PF_TYPE_MAX;
128 /*******************************************************************************
130 ** Function btm_ble_advfilt_deq_op_q
132 ** Description dequeue an adv filter operation from q when command complete
137 *******************************************************************************/
138 void btm_ble_advfilt_deq_op_q(UINT8 *p_action, UINT8 *p_ocf, tBTM_BLE_FILT_CB_EVT *p_cb_evt,
139 tBTM_BLE_REF_VALUE *p_ref, tBTM_BLE_PF_CFG_CBACK **p_cmpl_cback,
140 tBTM_BLE_PF_PARAM_CBACK **p_filt_param_cback)
142 *p_ocf = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx] >> 4);
143 *p_action = (btm_ble_adv_filt_cb.op_q.action_ocf[btm_ble_adv_filt_cb.op_q.pending_idx]
144 & BTM_BLE_ADV_FILT_SUBCODE_MASK);
145 *p_ref = btm_ble_adv_filt_cb.op_q.ref_value[btm_ble_adv_filt_cb.op_q.pending_idx];
146 *p_cb_evt = btm_ble_adv_filt_cb.op_q.cb_evt[btm_ble_adv_filt_cb.op_q.pending_idx];
147 *p_cmpl_cback = btm_ble_adv_filt_cb.op_q.p_scan_cfg_cback[btm_ble_adv_filt_cb.op_q.pending_idx];
148 *p_filt_param_cback =
149 btm_ble_adv_filt_cb.op_q.p_filt_param_cback[btm_ble_adv_filt_cb.op_q.pending_idx];
151 btm_ble_adv_filt_cb.op_q.pending_idx = (btm_ble_adv_filt_cb.op_q.pending_idx + 1)
152 % BTM_BLE_PF_TYPE_MAX;
153 BTM_TRACE_DEBUG("btm_ble_advfilt_deq_op_q: ocf:%d, action:%d, ref_value:%d, cb_evt:%x",
154 *p_ocf, *p_action, *p_ref, *p_cb_evt);
157 /*******************************************************************************
159 ** Function btm_ble_condtype_to_ocf
161 ** Description Convert cond_type to OCF
163 ** Returns Returns ocf value
165 *******************************************************************************/
166 UINT8 btm_ble_condtype_to_ocf(UINT8 cond_type)
171 case BTM_BLE_PF_ADDR_FILTER:
172 ocf = BTM_BLE_META_PF_ADDR;
174 case BTM_BLE_PF_SRVC_UUID:
175 ocf = BTM_BLE_META_PF_UUID;
177 case BTM_BLE_PF_SRVC_SOL_UUID:
178 ocf = BTM_BLE_META_PF_SOL_UUID;
180 case BTM_BLE_PF_LOCAL_NAME:
181 ocf = BTM_BLE_META_PF_LOCAL_NAME;
183 case BTM_BLE_PF_MANU_DATA:
184 ocf = BTM_BLE_META_PF_MANU_DATA;
186 case BTM_BLE_PF_SRVC_DATA_PATTERN:
187 ocf = BTM_BLE_META_PF_SRVC_DATA;
189 case BTM_BLE_PF_TYPE_ALL:
190 ocf = BTM_BLE_META_PF_ALL;
193 ocf = BTM_BLE_PF_TYPE_MAX;
199 /*******************************************************************************
201 ** Function btm_ble_ocf_to_condtype
203 ** Description Convert OCF to cond type
205 ** Returns Returns condtype value
207 *******************************************************************************/
208 UINT8 btm_ble_ocf_to_condtype(UINT8 ocf)
213 case BTM_BLE_META_PF_FEAT_SEL:
214 cond_type = BTM_BLE_META_PF_FEAT_SEL;
216 case BTM_BLE_META_PF_ADDR:
217 cond_type = BTM_BLE_PF_ADDR_FILTER;
219 case BTM_BLE_META_PF_UUID:
220 cond_type = BTM_BLE_PF_SRVC_UUID;
222 case BTM_BLE_META_PF_SOL_UUID:
223 cond_type = BTM_BLE_PF_SRVC_SOL_UUID;
225 case BTM_BLE_META_PF_LOCAL_NAME:
226 cond_type = BTM_BLE_PF_LOCAL_NAME;
228 case BTM_BLE_META_PF_MANU_DATA:
229 cond_type = BTM_BLE_PF_MANU_DATA;
231 case BTM_BLE_META_PF_SRVC_DATA:
232 cond_type = BTM_BLE_PF_SRVC_DATA_PATTERN;
234 case BTM_BLE_META_PF_ALL:
235 cond_type = BTM_BLE_PF_TYPE_ALL;
238 cond_type = BTM_BLE_PF_TYPE_MAX;
244 /*******************************************************************************
246 ** Function btm_ble_scan_pf_cmpl_cback
248 ** Description the BTM BLE customer feature VSC complete callback for ADV PF filtering
250 ** Returns pointer to the counter if found; NULL otherwise.
252 *******************************************************************************/
253 void btm_ble_scan_pf_cmpl_cback(tBTM_VSC_CMPL *p_params)
256 UINT8 *p = p_params->p_param_buf, op_subcode = 0, action = 0xff;
257 UINT16 evt_len = p_params->param_len;
258 UINT8 ocf = BTM_BLE_META_PF_ALL, cond_type = 0;
259 UINT8 num_avail = 0, cb_evt = 0;
260 tBTM_BLE_REF_VALUE ref_value = 0;
261 tBTM_BLE_PF_CFG_CBACK *p_scan_cfg_cback = NULL;
262 tBTM_BLE_PF_PARAM_CBACK *p_filt_param_cback = NULL;
264 if (evt_len < 3 || evt_len > 4) {
265 BTM_TRACE_ERROR("%s cannot interpret APCF callback status = %d, length = %d",
266 __func__, status, evt_len);
267 btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback,
268 &p_filt_param_cback);
272 btm_ble_advfilt_deq_op_q(&action, &ocf, &cb_evt, &ref_value, &p_scan_cfg_cback,
273 &p_filt_param_cback);
275 STREAM_TO_UINT8(status, p);
276 STREAM_TO_UINT8(op_subcode, p);
277 STREAM_TO_UINT8(action, p);
279 /* Ignore the event, if it is not the same one expected */
281 if (ocf != op_subcode) {
282 BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:3-Incorrect opcode :%d, %d, %d, %d, %d, %d",
283 ocf, op_subcode, action, evt_len, ref_value, status);
286 if (NULL != btm_ble_adv_filt_cb.p_filt_stat_cback) {
287 btm_ble_adv_filt_cb.p_filt_stat_cback(action, status, ref_value);
289 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback enabled/disabled, %d, %d, %d, %d",
290 ocf, action, status, ref_value);
295 if (4 == evt_len && ocf != op_subcode) {
296 BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback:4-Incorrect opcode: %d, %d, %d, %d, %d",
297 ocf, op_subcode, action, status, ref_value);
301 STREAM_TO_UINT8(num_avail, p);
302 switch (op_subcode) {
303 case BTM_BLE_META_PF_ADDR:
304 case BTM_BLE_META_PF_UUID:
305 case BTM_BLE_META_PF_SOL_UUID:
306 case BTM_BLE_META_PF_LOCAL_NAME:
307 case BTM_BLE_META_PF_MANU_DATA:
308 case BTM_BLE_META_PF_SRVC_DATA:
309 cond_type = btm_ble_ocf_to_condtype(ocf);
310 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback Recd: %d, %d, %d, %d, %d, %d", op_subcode,
311 ocf, action, status, ref_value, num_avail);
312 if (HCI_SUCCESS == status) {
313 if (memcmp(&btm_ble_adv_filt_cb.cur_filter_target.bda, &na_bda, BD_ADDR_LEN) == 0) {
314 btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail);
316 btm_ble_cs_update_pf_counter(action, cond_type,
317 &btm_ble_adv_filt_cb.cur_filter_target, num_avail);
320 /* send ADV PF operation complete */
321 btm_ble_adv_filt_cb.op_type = 0;
324 case BTM_BLE_META_PF_FEAT_SEL:
325 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback-Feat sel event: %d, %d, %d, %d",
326 action, status, ref_value, num_avail);
330 BTM_TRACE_ERROR("btm_ble_scan_pf_cmpl_cback: unknown operation: %d", op_subcode);
335 BTM_TRACE_DEBUG("btm_ble_scan_pf_cmpl_cback: calling the cback: %d", cb_evt);
336 case BTM_BLE_FILT_CFG:
337 if (NULL != p_scan_cfg_cback) {
338 p_scan_cfg_cback(action, cond_type, num_avail, status, ref_value);
341 case BTM_BLE_FILT_ADV_PARAM:
342 if (NULL != p_filt_param_cback) {
343 p_filt_param_cback(action, num_avail, ref_value, status);
351 /*******************************************************************************
353 ** Function btm_ble_find_addr_filter_counter
355 ** Description find the per bd address ADV payload filter counter by BD_ADDR.
357 ** Returns pointer to the counter if found; NULL otherwise.
359 *******************************************************************************/
360 tBTM_BLE_PF_COUNT *btm_ble_find_addr_filter_counter(tBLE_BD_ADDR *p_le_bda)
363 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1];
365 if (p_le_bda == NULL) {
366 return &btm_ble_adv_filt_cb.p_addr_filter_count[0];
369 for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++) {
370 if (p_addr_filter->in_use &&
371 memcmp(p_le_bda->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) {
372 return p_addr_filter;
378 /*******************************************************************************
380 ** Function btm_ble_alloc_addr_filter_counter
382 ** Description allocate the per device adv payload filter counter.
384 ** Returns pointer to the counter if allocation succeed; NULL otherwise.
386 *******************************************************************************/
387 tBTM_BLE_PF_COUNT *btm_ble_alloc_addr_filter_counter(BD_ADDR bd_addr)
390 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1];
392 for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++) {
393 if (memcmp(na_bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0) {
394 memcpy(p_addr_filter->bd_addr, bd_addr, BD_ADDR_LEN);
395 p_addr_filter->in_use = TRUE;
396 return p_addr_filter;
401 /*******************************************************************************
403 ** Function btm_ble_dealloc_addr_filter_counter
405 ** Description de-allocate the per device adv payload filter counter.
407 ** Returns TRUE if deallocation succeed; FALSE otherwise.
409 *******************************************************************************/
410 BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filter_type)
413 tBTM_BLE_PF_COUNT *p_addr_filter = &btm_ble_adv_filt_cb.p_addr_filter_count[1];
414 BOOLEAN found = FALSE;
416 if (BTM_BLE_PF_TYPE_ALL == filter_type && NULL == p_bd_addr) {
417 memset(&btm_ble_adv_filt_cb.p_addr_filter_count[0], 0, sizeof(tBTM_BLE_PF_COUNT));
420 for (i = 0; i < cmn_ble_vsc_cb.max_filter; i ++, p_addr_filter ++) {
421 if ((p_addr_filter->in_use) && (NULL == p_bd_addr ||
422 (NULL != p_bd_addr &&
423 memcmp(p_bd_addr->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0))) {
425 memset(p_addr_filter, 0, sizeof(tBTM_BLE_PF_COUNT));
427 if (NULL != p_bd_addr) {
435 /*******************************************************************************
437 ** Function btm_ble_update_pf_local_name
439 ** Description this function update(add,delete or clear) the adv lcoal name filtering condition.
442 ** Returns BTM_SUCCESS if sucessful,
443 ** BTM_ILLEGAL_VALUE if paramter is not valid.
445 *******************************************************************************/
446 tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action,
447 tBTM_BLE_PF_FILT_INDEX filt_index,
448 tBTM_BLE_PF_COND_PARAM *p_cond)
450 tBTM_BLE_PF_LOCAL_NAME_COND *p_local_name = (p_cond == NULL) ? NULL : &p_cond->local_name;
451 UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
453 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH;
454 tBTM_STATUS st = BTM_ILLEGAL_VALUE;
456 memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
458 UINT8_TO_STREAM(p, BTM_BLE_META_PF_LOCAL_NAME);
459 UINT8_TO_STREAM(p, action);
462 UINT8_TO_STREAM(p, filt_index);
464 if (BTM_BLE_SCAN_COND_ADD == action ||
465 BTM_BLE_SCAN_COND_DELETE == action) {
466 if (NULL == p_local_name) {
470 if (p_local_name->data_len > BTM_BLE_PF_STR_LEN_MAX) {
471 p_local_name->data_len = BTM_BLE_PF_STR_LEN_MAX;
474 ARRAY_TO_STREAM(p, p_local_name->p_data, p_local_name->data_len);
475 len += p_local_name->data_len;
478 /* send local name filter */
479 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
482 btm_ble_scan_pf_cmpl_cback))
483 != BTM_NO_RESOURCES) {
484 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
486 BTM_TRACE_ERROR("Local Name PF filter update failed");
493 /*******************************************************************************
495 ** Function btm_ble_update_srvc_data_change
497 ** Description this function update(add/remove) service data change filter.
500 ** Returns BTM_SUCCESS if sucessful,
501 ** BTM_ILLEGAL_VALUE if paramter is not valid.
503 *******************************************************************************/
504 tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action,
505 tBTM_BLE_PF_FILT_INDEX filt_index,
506 tBTM_BLE_PF_COND_PARAM *p_cond)
508 tBTM_STATUS st = BTM_ILLEGAL_VALUE;
509 tBLE_BD_ADDR *p_bd_addr = p_cond ? &p_cond->target_addr : NULL;
510 UINT8 num_avail = (action == BTM_BLE_SCAN_COND_ADD) ? 0 : 1;
512 if (btm_ble_cs_update_pf_counter (action, BTM_BLE_PF_SRVC_DATA, p_bd_addr, num_avail)
513 != BTM_BLE_INVALID_COUNTER) {
520 /*******************************************************************************
522 ** Function btm_ble_update_pf_manu_data
524 ** Description this function update(add,delete or clear) the adv manufacturer
525 ** data filtering condition.
528 ** Returns BTM_SUCCESS if sucessful,
529 ** BTM_ILLEGAL_VALUE if paramter is not valid.
531 *******************************************************************************/
532 tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action,
533 tBTM_BLE_PF_FILT_INDEX filt_index,
534 tBTM_BLE_PF_COND_PARAM *p_data,
535 tBTM_BLE_PF_COND_TYPE cond_type,
536 tBTM_BLE_FILT_CB_EVT cb_evt,
537 tBTM_BLE_REF_VALUE ref_value)
539 tBTM_BLE_PF_MANU_COND *p_manu_data = (p_data == NULL) ? NULL : &p_data->manu_data;
540 tBTM_BLE_PF_SRVC_PATTERN_COND *p_srvc_data = (p_data == NULL) ? NULL : &p_data->srvc_data;
542 UINT8 param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
544 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH;
545 tBTM_STATUS st = BTM_ILLEGAL_VALUE;
547 if (NULL == p_data) {
551 memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX
552 + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
554 if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) {
555 UINT8_TO_STREAM(p, BTM_BLE_META_PF_SRVC_DATA);
557 UINT8_TO_STREAM(p, BTM_BLE_META_PF_MANU_DATA);
560 UINT8_TO_STREAM(p, action);
563 UINT8_TO_STREAM(p, filt_index);
565 if (BTM_BLE_SCAN_COND_ADD == action || BTM_BLE_SCAN_COND_DELETE == action) {
566 if (BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) {
567 if (NULL == p_srvc_data) {
570 if (p_srvc_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) {
571 p_srvc_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
574 if (p_srvc_data->data_len > 0) {
575 ARRAY_TO_STREAM(p, p_srvc_data->p_pattern, p_srvc_data->data_len);
576 len += (p_srvc_data->data_len);
577 ARRAY_TO_STREAM(p, p_srvc_data->p_pattern_mask, p_srvc_data->data_len);
580 len += (p_srvc_data->data_len);
581 BTM_TRACE_DEBUG("Service data length: %d", len);
583 if (NULL == p_manu_data) {
584 BTM_TRACE_ERROR("btm_ble_update_pf_manu_data - No manuf data");
587 BTM_TRACE_EVENT("btm_ble_update_pf_manu_data length: %d",
588 p_manu_data->data_len);
589 if (p_manu_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2)) {
590 p_manu_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
593 UINT16_TO_STREAM(p, p_manu_data->company_id);
594 if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL) {
595 ARRAY_TO_STREAM(p, p_manu_data->p_pattern, p_manu_data->data_len);
596 len += (p_manu_data->data_len + 2);
601 if (p_manu_data->company_id_mask != 0) {
602 UINT16_TO_STREAM (p, p_manu_data->company_id_mask);
609 if (p_manu_data->data_len > 0 && p_manu_data->p_pattern_mask != NULL) {
610 ARRAY_TO_STREAM(p, p_manu_data->p_pattern_mask, p_manu_data->data_len);
611 len += (p_manu_data->data_len);
614 BTM_TRACE_DEBUG("Manuf data length: %d", len);
618 /* send manufacturer*/
619 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
622 btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) {
623 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
625 BTM_TRACE_ERROR("manufacturer data PF filter update failed");
631 /*******************************************************************************
633 ** Function btm_ble_cs_update_pf_counter
635 ** Description this function is to update the adv data payload filter counter
637 ** Returns current number of the counter; BTM_BLE_INVALID_COUNTER if
638 ** counter update failed.
640 *******************************************************************************/
641 UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
642 UINT8 cond_type, tBLE_BD_ADDR *p_bd_addr,
645 tBTM_BLE_PF_COUNT *p_addr_filter = NULL;
646 UINT8 *p_counter = NULL;
648 btm_ble_obtain_vsc_details();
650 if (cond_type > BTM_BLE_PF_TYPE_ALL) {
651 BTM_TRACE_ERROR("unknown PF filter condition type %d", cond_type);
652 return BTM_BLE_INVALID_COUNTER;
655 /* for these three types of filter, always generic */
656 if (BTM_BLE_PF_ADDR_FILTER == cond_type ||
657 BTM_BLE_PF_MANU_DATA == cond_type ||
658 BTM_BLE_PF_LOCAL_NAME == cond_type ||
659 BTM_BLE_PF_SRVC_DATA_PATTERN == cond_type) {
663 if ((p_addr_filter = btm_ble_find_addr_filter_counter(p_bd_addr)) == NULL &&
664 BTM_BLE_SCAN_COND_ADD == action) {
665 p_addr_filter = btm_ble_alloc_addr_filter_counter(p_bd_addr->bda);
668 if (NULL != p_addr_filter) {
669 /* all filter just cleared */
670 if ((BTM_BLE_PF_TYPE_ALL == cond_type && BTM_BLE_SCAN_COND_CLEAR == action) ||
671 /* or bd address filter been deleted */
672 (BTM_BLE_PF_ADDR_FILTER == cond_type &&
673 (BTM_BLE_SCAN_COND_DELETE == action || BTM_BLE_SCAN_COND_CLEAR == action))) {
674 btm_ble_dealloc_addr_filter_counter(p_bd_addr, cond_type);
676 /* if not feature selection, update new addition/reduction of the filter counter */
677 else if (cond_type != BTM_BLE_PF_TYPE_ALL) {
678 p_counter = p_addr_filter->pf_counter;
679 if (num_available > 0) {
680 p_counter[cond_type] += 1;
683 BTM_TRACE_DEBUG("counter = %d, maxfilt = %d, num_avbl=%d",
684 p_counter[cond_type], cmn_ble_vsc_cb.max_filter, num_available);
685 return p_counter[cond_type];
688 BTM_TRACE_ERROR("no matching filter counter found");
690 /* no matching filter located and updated */
691 return BTM_BLE_INVALID_COUNTER;
695 /*******************************************************************************
697 ** Function btm_ble_update_addr_filter
699 ** Description this function update(add,delete or clear) the address filter of adv.
702 ** Returns BTM_SUCCESS if sucessful,
703 ** BTM_ILLEGAL_VALUE if paramter is not valid.
705 *******************************************************************************/
706 tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action,
707 tBTM_BLE_PF_FILT_INDEX filt_index,
708 tBTM_BLE_PF_COND_PARAM *p_cond)
710 UINT8 param[BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
712 tBTM_STATUS st = BTM_ILLEGAL_VALUE;
713 tBLE_BD_ADDR *p_addr = (p_cond == NULL) ? NULL : &p_cond->target_addr;
715 memset(param, 0, BTM_BLE_META_ADDR_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
717 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
718 UINT8_TO_STREAM(p, action);
721 UINT8_TO_STREAM(p, filt_index);
723 if (BTM_BLE_SCAN_COND_ADD == action ||
724 BTM_BLE_SCAN_COND_DELETE == action) {
725 if (NULL == p_addr) {
729 BDADDR_TO_STREAM(p, p_addr->bda);
730 UINT8_TO_STREAM(p, p_addr->type);
732 /* send address filter */
733 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
734 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
736 btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) {
737 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
739 BTM_TRACE_ERROR("Broadcaster Address Filter Update failed");
744 /*******************************************************************************
746 ** Function btm_ble_update_uuid_filter
748 ** Description this function update(add,delete or clear) service UUID filter.
751 ** Returns BTM_SUCCESS if sucessful,
752 ** BTM_ILLEGAL_VALUE if paramter is not valid.
754 *******************************************************************************/
755 tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action,
756 tBTM_BLE_PF_FILT_INDEX filt_index,
757 tBTM_BLE_PF_COND_TYPE filter_type,
758 tBTM_BLE_PF_COND_PARAM *p_cond,
759 tBTM_BLE_FILT_CB_EVT cb_evt,
760 tBTM_BLE_REF_VALUE ref_value)
762 UINT8 param[BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH],
764 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH;
765 tBTM_STATUS st = BTM_ILLEGAL_VALUE;
766 tBTM_BLE_PF_UUID_COND *p_uuid_cond;
769 memset(param, 0, BTM_BLE_META_UUID_LEN + BTM_BLE_ADV_FILT_META_HDR_LENGTH);
771 if (BTM_BLE_PF_SRVC_UUID == filter_type) {
772 evt_type = BTM_BLE_META_PF_UUID;
773 p_uuid_cond = p_cond ? &p_cond->srvc_uuid : NULL;
775 evt_type = BTM_BLE_META_PF_SOL_UUID;
776 p_uuid_cond = p_cond ? &p_cond->solicitate_uuid : NULL;
779 if (NULL == p_uuid_cond && action != BTM_BLE_SCAN_COND_CLEAR) {
780 BTM_TRACE_ERROR("Illegal param for add/delete UUID filter");
784 /* need to add address filter first, if adding per bda UUID filter without address filter */
785 if (BTM_BLE_SCAN_COND_ADD == action && NULL != p_uuid_cond &&
786 p_uuid_cond->p_target_addr &&
787 btm_ble_find_addr_filter_counter(p_uuid_cond->p_target_addr) == NULL) {
788 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
789 UINT8_TO_STREAM(p, action);
792 UINT8_TO_STREAM(p, filt_index);
794 BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda);
795 UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type);
797 /* send address filter */
798 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
799 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
801 btm_ble_scan_pf_cmpl_cback)) == BTM_NO_RESOURCES) {
802 BTM_TRACE_ERROR("Update Address filter into controller failed.");
806 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_ADDR, cb_evt, ref_value, NULL, NULL);
807 BTM_TRACE_DEBUG("Updated Address filter");
811 UINT8_TO_STREAM(p, evt_type);
812 UINT8_TO_STREAM(p, action);
815 UINT8_TO_STREAM(p, filt_index);
817 if ((BTM_BLE_SCAN_COND_ADD == action ||
818 BTM_BLE_SCAN_COND_DELETE == action) &&
819 NULL != p_uuid_cond) {
820 if (p_uuid_cond->uuid.len == LEN_UUID_16) {
821 UINT16_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid16);
823 } else if (p_uuid_cond->uuid.len == LEN_UUID_32) { /*4 bytes */
824 UINT32_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid32);
826 } else if (p_uuid_cond->uuid.len == LEN_UUID_128) {
827 ARRAY_TO_STREAM (p, p_uuid_cond->uuid.uu.uuid128, LEN_UUID_128);
830 BTM_TRACE_ERROR("illegal UUID length: %d", p_uuid_cond->uuid.len);
831 return BTM_ILLEGAL_VALUE;
834 if (NULL != p_uuid_cond->p_uuid_mask) {
835 if (p_uuid_cond->uuid.len == LEN_UUID_16) {
836 UINT16_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid16_mask);
838 } else if (p_uuid_cond->uuid.len == LEN_UUID_32) { /*4 bytes */
839 UINT32_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid32_mask);
841 } else if (p_uuid_cond->uuid.len == LEN_UUID_128) {
842 ARRAY_TO_STREAM (p, p_uuid_cond->p_uuid_mask->uuid128_mask, LEN_UUID_128);
846 memset(p, 0xff, p_uuid_cond->uuid.len);
847 len += p_uuid_cond->uuid.len;
849 BTM_TRACE_DEBUG("btm_ble_update_uuid_filter : %d, %d, %d, %d", filter_type, evt_type,
850 p_uuid_cond->uuid.len, len);
853 /* send UUID filter update */
854 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
857 btm_ble_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES) {
858 if (p_uuid_cond && p_uuid_cond->p_target_addr)
859 memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_uuid_cond->p_target_addr,
860 sizeof(tBLE_BD_ADDR));
862 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
865 BTM_TRACE_ERROR("UUID filter udpating failed");
872 /*******************************************************************************
874 ** Function btm_ble_clear_scan_pf_filter
876 ** Description clear all adv payload filter by de-select all the adv pf feature bits
879 ** Returns BTM_SUCCESS if sucessful,
880 ** BTM_ILLEGAL_VALUE if paramter is not valid.
882 *******************************************************************************/
883 tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action,
884 tBTM_BLE_PF_FILT_INDEX filt_index,
885 tBTM_BLE_PF_COND_PARAM *p_cond,
886 tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback,
887 tBTM_BLE_FILT_CB_EVT cb_evt,
888 tBTM_BLE_REF_VALUE ref_value)
890 tBLE_BD_ADDR *p_target = (p_cond == NULL) ? NULL : &p_cond->target_addr;
891 tBTM_BLE_PF_COUNT *p_bda_filter;
892 tBTM_STATUS st = BTM_WRONG_MODE;
895 if (BTM_BLE_SCAN_COND_CLEAR != action) {
896 BTM_TRACE_ERROR("unable to perform action:%d for generic adv filter type", action);
897 return BTM_ILLEGAL_VALUE;
901 memset(param, 0, 20);
903 p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
905 if (NULL == p_bda_filter ||
906 /* not a generic filter */
907 (p_target != NULL && p_bda_filter)) {
908 BTM_TRACE_ERROR("Error: Can not clear filter, No PF filter has been configured!");
912 /* clear the general filter entry */
913 if (NULL == p_target) {
914 /* clear manufactuer data filter */
915 st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL,
916 BTM_BLE_PF_MANU_DATA, cb_evt, ref_value);
917 if (BTM_CMD_STARTED == st)
918 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_MANU_DATA, cb_evt,
919 ref_value, NULL, NULL);
921 /* clear local name filter */
922 st = btm_ble_update_pf_local_name(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL);
923 if (BTM_CMD_STARTED == st)
924 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_LOCAL_NAME, cb_evt,
925 ref_value, NULL, NULL);
927 /* update the counter for service data */
928 st = btm_ble_update_srvc_data_change(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL);
930 /* clear UUID filter */
931 st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index,
932 BTM_BLE_PF_SRVC_UUID, NULL, cb_evt, ref_value);
933 if (BTM_CMD_STARTED == st) {
934 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_UUID, cb_evt, ref_value, NULL, NULL);
937 st = btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, filt_index,
938 BTM_BLE_PF_SRVC_SOL_UUID, NULL, cb_evt, ref_value);
939 if (BTM_CMD_STARTED == st)
940 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SOL_UUID, cb_evt,
941 ref_value, NULL, NULL);
943 /* clear service data filter */
944 st = btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, filt_index, NULL,
945 BTM_BLE_PF_SRVC_DATA_PATTERN, cb_evt, ref_value);
946 if (BTM_CMD_STARTED == st)
947 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_SRVC_DATA, cb_evt,
948 ref_value, NULL, NULL);
951 /* select feature based on control block settings */
952 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
953 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR);
956 UINT8_TO_STREAM(p, filt_index);
958 /* set PCF selection */
959 UINT32_TO_STREAM(p, BTM_BLE_PF_SELECT_NONE);
960 /* set logic condition as OR as default */
961 UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR);
963 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
964 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN),
966 btm_ble_scan_pf_cmpl_cback))
967 != BTM_NO_RESOURCES) {
969 memcpy(&btm_ble_adv_filt_cb.cur_filter_target, p_target, sizeof(tBLE_BD_ADDR));
971 memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
977 /*******************************************************************************
979 ** Function BTM_BleAdvFilterParamSetup
981 ** Description This function is called to setup the adv data payload filter
984 ** Parameters action - Type of action to be performed
985 ** filt_index - Filter index
986 ** p_filt_params - Filter parameters
987 ** p_target - Target device
988 ** p_cmpl_back - Callback pointer
989 ** ref_value - reference value
993 *******************************************************************************/
994 tBTM_STATUS BTM_BleAdvFilterParamSetup(int action, tBTM_BLE_PF_FILT_INDEX filt_index,
995 tBTM_BLE_PF_FILT_PARAMS *p_filt_params,
996 tBLE_BD_ADDR *p_target, tBTM_BLE_PF_PARAM_CBACK *p_cmpl_cback,
997 tBTM_BLE_REF_VALUE ref_value)
999 tBTM_STATUS st = BTM_WRONG_MODE;
1000 tBTM_BLE_PF_COUNT *p_bda_filter = NULL;
1001 UINT8 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN +
1002 BTM_BLE_ADV_FILT_TRACK_NUM;
1003 UINT8 param[len], *p;
1005 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) {
1010 memset(param, 0, len);
1011 BTM_TRACE_EVENT (" BTM_BleAdvFilterParamSetup");
1013 if (BTM_BLE_SCAN_COND_ADD == action) {
1014 p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
1015 if (NULL == p_bda_filter) {
1016 BTM_TRACE_ERROR("BD Address not found!");
1020 BTM_TRACE_DEBUG("BTM_BleAdvFilterParamSetup : Feat mask:%d", p_filt_params->feat_seln);
1021 /* select feature based on control block settings */
1022 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
1023 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_ADD);
1026 UINT8_TO_STREAM(p, filt_index);
1028 /* set PCF selection */
1029 UINT16_TO_STREAM(p, p_filt_params->feat_seln);
1030 /* set logic type */
1031 UINT16_TO_STREAM(p, p_filt_params->logic_type);
1032 /* set logic condition */
1033 UINT8_TO_STREAM(p, p_filt_params->filt_logic_type);
1034 /* set RSSI high threshold */
1035 UINT8_TO_STREAM(p, p_filt_params->rssi_high_thres);
1036 /* set delivery mode */
1037 UINT8_TO_STREAM(p, p_filt_params->dely_mode);
1039 if (0x01 == p_filt_params->dely_mode) {
1040 /* set onfound timeout */
1041 UINT16_TO_STREAM(p, p_filt_params->found_timeout);
1042 /* set onfound timeout count*/
1043 UINT8_TO_STREAM(p, p_filt_params->found_timeout_cnt);
1044 /* set RSSI low threshold */
1045 UINT8_TO_STREAM(p, p_filt_params->rssi_low_thres);
1046 /* set onlost timeout */
1047 UINT16_TO_STREAM(p, p_filt_params->lost_timeout);
1048 /* set num_of_track_entries for firmware greater than L-release version */
1049 if (cmn_ble_vsc_cb.version_supported > BTM_VSC_CHIP_CAPABILITY_L_VERSION) {
1050 UINT16_TO_STREAM(p, p_filt_params->num_of_tracking_entries);
1054 if (cmn_ble_vsc_cb.version_supported == BTM_VSC_CHIP_CAPABILITY_L_VERSION) {
1055 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN;
1057 len = BTM_BLE_ADV_FILT_META_HDR_LENGTH + BTM_BLE_ADV_FILT_FEAT_SELN_LEN +
1058 BTM_BLE_ADV_FILT_TRACK_NUM;
1060 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1063 btm_ble_scan_pf_cmpl_cback))
1064 == BTM_NO_RESOURCES) {
1067 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM,
1068 ref_value, NULL, p_cmpl_cback);
1069 } else if (BTM_BLE_SCAN_COND_DELETE == action) {
1070 /* select feature based on control block settings */
1071 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
1072 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_DELETE);
1074 UINT8_TO_STREAM(p, filt_index);
1076 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1077 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH),
1079 btm_ble_scan_pf_cmpl_cback))
1080 == BTM_NO_RESOURCES) {
1083 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM,
1084 ref_value, NULL, p_cmpl_cback);
1085 } else if (BTM_BLE_SCAN_COND_CLEAR == action) {
1086 /* Deallocate all filters here */
1087 btm_ble_dealloc_addr_filter_counter(NULL, BTM_BLE_PF_TYPE_ALL);
1089 /* select feature based on control block settings */
1090 UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
1091 UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR);
1093 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1094 (UINT8)(BTM_BLE_ADV_FILT_META_HDR_LENGTH - 1),
1096 btm_ble_scan_pf_cmpl_cback))
1097 == BTM_NO_RESOURCES) {
1100 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_ADV_PARAM,
1101 ref_value, NULL, p_cmpl_cback);
1107 /*******************************************************************************
1109 ** Function BTM_BleEnableDisableFilterFeature
1111 ** Description This function is called to enable / disable the APCF feature
1113 ** Parameters enable the generic scan condition.
1114 ** enable: enable or disable the filter condition
1115 ** p_stat_cback - Status callback pointer
1116 ** ref_value - Ref value
1119 *******************************************************************************/
1120 tBTM_STATUS BTM_BleEnableDisableFilterFeature(UINT8 enable,
1121 tBTM_BLE_PF_STATUS_CBACK *p_stat_cback,
1122 tBTM_BLE_REF_VALUE ref_value)
1124 UINT8 param[20], *p;
1125 tBTM_STATUS st = BTM_WRONG_MODE;
1127 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) {
1132 memset(param, 0, 20);
1134 /* enable the content filter in controller */
1136 UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE);
1137 /* enable adv data payload filtering */
1138 UINT8_TO_STREAM(p, enable);
1140 if ((st = BTM_VendorSpecificCommand (HCI_BLE_ADV_FILTER_OCF,
1141 BTM_BLE_PCF_ENABLE_LEN, param,
1142 btm_ble_scan_pf_cmpl_cback)) == BTM_CMD_STARTED) {
1143 btm_ble_adv_filt_cb.p_filt_stat_cback = p_stat_cback;
1144 btm_ble_advfilt_enq_op_q(enable, BTM_BLE_META_PF_ENABLE, BTM_BLE_FILT_ENABLE_DISABLE,
1145 ref_value, NULL, NULL);
1150 /*******************************************************************************
1152 ** Function BTM_BleCfgFilterCondition
1154 ** Description This function is called to configure the adv data payload filter
1157 ** Parameters action: to read/write/clear
1158 ** cond_type: filter condition type.
1159 ** filt_index - Filter index
1160 ** p_cond: filter condition parameter
1161 ** p_cmpl_cback - Config callback pointer
1162 ** ref_value - Reference value
1166 *******************************************************************************/
1167 tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action,
1168 tBTM_BLE_PF_COND_TYPE cond_type,
1169 tBTM_BLE_PF_FILT_INDEX filt_index,
1170 tBTM_BLE_PF_COND_PARAM *p_cond,
1171 tBTM_BLE_PF_CFG_CBACK *p_cmpl_cback,
1172 tBTM_BLE_REF_VALUE ref_value)
1174 tBTM_STATUS st = BTM_ILLEGAL_VALUE;
1176 BTM_TRACE_EVENT (" BTM_BleCfgFilterCondition action:%d, cond_type:%d, index:%d", action,
1177 cond_type, filt_index);
1179 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) {
1183 switch (cond_type) {
1184 /* write service data filter */
1185 case BTM_BLE_PF_SRVC_DATA_PATTERN:
1186 /* write manufacturer data filter */
1187 case BTM_BLE_PF_MANU_DATA:
1188 st = btm_ble_update_pf_manu_data(action, filt_index, p_cond, cond_type, 0, ref_value);
1191 /* write local name filter */
1192 case BTM_BLE_PF_LOCAL_NAME:
1193 st = btm_ble_update_pf_local_name(action, filt_index, p_cond);
1196 /* filter on advertiser address */
1197 case BTM_BLE_PF_ADDR_FILTER:
1198 st = btm_ble_update_addr_filter(action, filt_index, p_cond);
1201 /* filter on service/solicitated UUID */
1202 case BTM_BLE_PF_SRVC_UUID:
1203 case BTM_BLE_PF_SRVC_SOL_UUID:
1204 st = btm_ble_update_uuid_filter(action, filt_index, cond_type, p_cond, 0, ref_value);
1207 case BTM_BLE_PF_SRVC_DATA:
1208 st = btm_ble_update_srvc_data_change(action, filt_index, p_cond);
1211 case BTM_BLE_PF_TYPE_ALL: /* only used to clear filter */
1212 st = btm_ble_clear_scan_pf_filter(action, filt_index, p_cond, p_cmpl_cback,
1217 BTM_TRACE_WARNING("condition type [%d] not supported currently.", cond_type);
1221 if (BTM_CMD_STARTED == st && cond_type != BTM_BLE_PF_TYPE_ALL) {
1222 ocf = btm_ble_condtype_to_ocf(cond_type);
1223 btm_ble_advfilt_enq_op_q(action, ocf, BTM_BLE_FILT_CFG, ref_value, p_cmpl_cback, NULL);
1224 } else if (BTM_CMD_STARTED == st && BTM_BLE_PF_TYPE_ALL == cond_type) {
1225 btm_ble_advfilt_enq_op_q(action, BTM_BLE_META_PF_FEAT_SEL, BTM_BLE_FILT_CFG,
1226 ref_value, p_cmpl_cback, NULL);
1231 /*******************************************************************************
1233 ** Function btm_ble_adv_filter_init
1235 ** Description This function initializes the adv filter control block
1241 *******************************************************************************/
1242 void btm_ble_adv_filter_init(void)
1244 memset(&btm_ble_adv_filt_cb, 0, sizeof(tBTM_BLE_MULTI_ADV_CB));
1245 if (BTM_SUCCESS != btm_ble_obtain_vsc_details()) {
1249 if (cmn_ble_vsc_cb.max_filter > 0) {
1250 btm_ble_adv_filt_cb.p_addr_filter_count =
1251 (tBTM_BLE_PF_COUNT *) osi_malloc( sizeof(tBTM_BLE_PF_COUNT) * cmn_ble_vsc_cb.max_filter);
1255 /*******************************************************************************
1257 ** Function btm_ble_adv_filter_cleanup
1259 ** Description This function de-initializes the adv filter control block
1265 *******************************************************************************/
1266 void btm_ble_adv_filter_cleanup(void)
1268 if (btm_ble_adv_filt_cb.p_addr_filter_count) {
1269 osi_free(btm_ble_adv_filt_cb.p_addr_filter_count);
1270 btm_ble_adv_filt_cb.p_addr_filter_count = NULL;