vendor_ble.c revision b203d478f4835f5e35217874a1787e1914328f7c
1/******************************************************************************
2 *
3 *  Copyright (C) 2003-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/*****************************************************************************
20**
21**  Name:          vendor_ble.c
22**
23**  Description:   This file contains vendor specific feature for BLE
24**
25******************************************************************************/
26#include <string.h>
27#include "bt_target.h"
28
29#if (BLE_INCLUDED == TRUE && BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE)
30#include "bt_types.h"
31#include "hcimsgs.h"
32#include "btu.h"
33#include "vendor_ble.h"
34#include "vendor_hcidefs.h"
35#include "gatt_int.h"
36
37#define BTM_BLE_INVALID_COUNTER     0xff
38
39
40static UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
41                                  UINT8 cond_type,
42                                  tBLE_BD_ADDR   *p_bd_addr,
43                                  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
49/* max number of filter available for different filter type, controller dependent number */
50const static UINT8 btm_ble_cs_filter_max[BTM_BLE_PF_TYPE_MAX] =
51{
52    BTM_BLE_MAX_ADDR_FILTER,        /* address filter */
53    1,                              /* no limit for service data change, always enable or disable */
54    BTM_BLE_MAX_UUID_FILTER,        /* service UUID filter */
55    BTM_BLE_MAX_UUID_FILTER,        /* solicitated UUID filter */
56    BTM_BLE_PF_STR_COND_MAX,        /* local name filter */
57    BTM_BLE_PF_STR_COND_MAX         /* manufacturer data filter */
58};
59
60/*** This needs to be moved to a VSC control block eventually per coding conventions ***/
61#if VENDOR_DYNAMIC_MEMORY == FALSE
62tBTM_BLE_VENDOR_CB  btm_ble_vendor_cb;
63#endif
64
65static const UINT8 op_code_to_cond_type[] =
66{
67    BTM_BLE_PF_TYPE_ALL,
68    BTM_BLE_PF_ADDR_FILTER,
69    BTM_BLE_PF_SRVC_UUID,
70    BTM_BLE_PF_SRVC_SOL_UUID,
71    BTM_BLE_PF_LOCAL_NAME,
72    BTM_BLE_PF_MANU_DATA,
73    BTM_BLE_PF_SRVC_DATA_PATTERN
74};
75
76static const BD_ADDR     na_bda= {0};
77
78/*******************************************************************************
79**
80** Function         btm_ble_vendor_scan_pf_cmpl_cback
81**
82** Description      the BTM BLE customer feature VSC complete callback for ADV PF
83**                  filtering
84**
85** Returns          pointer to the counter if found; NULL otherwise.
86**
87*******************************************************************************/
88void btm_ble_vendor_scan_pf_cmpl_cback(tBTM_VSC_CMPL *p_params)
89{
90    UINT8  status;
91    UINT8  *p = p_params->p_param_buf, op_subcode, action = 0xff;
92    UINT16  evt_len = p_params->param_len;
93    UINT8   num_avail = 0, cond_type = BTM_BLE_PF_TYPE_MAX;
94    tBTM_BLE_PF_CMPL_CBACK  *p_cmpl_cback =   btm_ble_vendor_cb.p_scan_pf_cback;
95    UINT8   op = BTM_BLE_GET_SCAN_PF_ACTION(btm_ble_vendor_cb.op_type);
96    UINT8   subcode = BTM_BLE_GET_SCAN_PF_SUBCODE(btm_ble_vendor_cb.op_type);
97
98    STREAM_TO_UINT8(status, p);
99
100    evt_len--;
101
102    if (evt_len < 1 )
103    {
104        BTM_TRACE_ERROR1("can not interpret ADV PF filter setting callback. status = %d", status);
105        return;
106    }
107    op_subcode   = *p ++;
108
109        switch (op_subcode)
110        {
111        case BTM_BLE_META_PF_LOCAL_NAME:
112        case BTM_BLE_META_PF_MANU_DATA:
113        case BTM_BLE_META_PF_ADDR:
114        case BTM_BLE_META_PF_UUID:
115        case BTM_BLE_META_PF_SOL_UUID:
116        case BTM_BLE_META_PF_FEAT_SEL:
117        case BTM_BLE_META_PF_SRVC_DATA:
118            cond_type = op_code_to_cond_type[op_subcode - BTM_BLE_META_PF_FEAT_SEL];
119            if (status == HCI_SUCCESS)
120            {
121                action       = *p ++;
122                if (op_subcode != BTM_BLE_META_PF_FEAT_SEL)
123                {
124                STREAM_TO_UINT8(num_avail, p);
125                }
126
127                if (memcmp(&btm_ble_vendor_cb.cur_filter_target.bda, &na_bda, BD_ADDR_LEN) == 0)
128                    btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail);
129                else
130                    btm_ble_cs_update_pf_counter(action, cond_type, &btm_ble_vendor_cb.cur_filter_target, num_avail);
131            }
132            break;
133
134        case BTM_BLE_META_PF_ENABLE:
135            cond_type = BTM_BLE_META_PF_ENABLE;
136            BTM_TRACE_DEBUG0("CS feature Enabled");
137            break;
138
139        default:
140            BTM_TRACE_ERROR1("unknow operation: %d", op_subcode);
141            break;
142        }
143
144    /* send ADV PF opeartion complete */
145    if (p_cmpl_cback && subcode == cond_type)
146    {
147        btm_ble_vendor_cb.p_scan_pf_cback = NULL;
148        btm_ble_vendor_cb.op_type = 0;
149        (* p_cmpl_cback)(op, subcode, status);
150    }
151}
152/*******************************************************************************
153**         adv payload filtering functions
154*******************************************************************************/
155/*******************************************************************************
156**
157** Function         btm_ble_find_addr_filter_counter
158**
159** Description      find the per bd address ADV payload filter counter by BD_ADDR.
160**
161** Returns          pointer to the counter if found; NULL otherwise.
162**
163*******************************************************************************/
164tBTM_BLE_PF_COUNT   * btm_ble_find_addr_filter_counter(tBLE_BD_ADDR *p_le_bda)
165{
166    UINT8               i;
167    tBTM_BLE_PF_COUNT   *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1];
168
169    if (p_le_bda == NULL)
170        return &btm_ble_vendor_cb.addr_filter_count[0];
171
172    for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++)
173    {
174        if (p_addr_filter->in_use &&
175            memcmp(p_le_bda->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)
176        {
177            return p_addr_filter;
178        }
179    }
180    return NULL;
181}
182
183/*******************************************************************************
184**
185** Function         btm_ble_alloc_addr_filter_counter
186**
187** Description      allocate the per device adv payload filter counter.
188**
189** Returns          pointer to the counter if allocation succeed; NULL otherwise.
190**
191*******************************************************************************/
192tBTM_BLE_PF_COUNT * btm_ble_alloc_addr_filter_counter(BD_ADDR bd_addr)
193{
194    UINT8               i;
195    tBTM_BLE_PF_COUNT   *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1];
196
197    for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++)
198    {
199        if (memcmp(na_bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)
200        {
201            memcpy(p_addr_filter->bd_addr, bd_addr, BD_ADDR_LEN);
202            p_addr_filter->in_use = TRUE;
203            return p_addr_filter;
204        }
205    }
206    return NULL;
207}
208/*******************************************************************************
209**
210** Function         btm_ble_dealloc_addr_filter_counter
211**
212** Description      de-allocate the per device adv payload filter counter.
213**
214** Returns          TRUE if deallocation succeed; FALSE otherwise.
215**
216*******************************************************************************/
217BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filter_type)
218{
219    UINT8               i;
220    tBTM_BLE_PF_COUNT   *p_addr_filter = &btm_ble_vendor_cb.addr_filter_count[1];
221    BOOLEAN             found = FALSE;
222
223    if (filter_type == BTM_BLE_PF_TYPE_ALL && p_bd_addr == NULL)
224        memset(&btm_ble_vendor_cb.addr_filter_count[0], 0, sizeof(tBTM_BLE_PF_COUNT));
225
226    for (i = 0; i < BTM_BLE_MAX_FILTER_COUNTER; i ++, p_addr_filter ++)
227    {
228        if ((p_addr_filter->in_use) &&
229            (p_bd_addr == NULL ||
230             (p_bd_addr != NULL && memcmp(p_bd_addr->bda, p_addr_filter->bd_addr, BD_ADDR_LEN) == 0)))
231        {
232            found = TRUE;
233            memset(p_addr_filter, 0, sizeof(tBTM_BLE_PF_COUNT));
234
235            if (p_bd_addr != NULL) break;
236        }
237    }
238    return found;
239}
240/*******************************************************************************
241**
242** Function         btm_ble_cs_update_pf_counter
243**
244** Description      this function is to update the adv data payload filter counter
245**
246** Returns          current number of the counter; BTM_BLE_INVALID_COUNTER if
247**                  counter update failed.
248**
249*******************************************************************************/
250UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action,
251                                  UINT8 cond_type,
252                                  tBLE_BD_ADDR   *p_bd_addr,
253                                  UINT8           num_available)
254{
255    tBTM_BLE_PF_COUNT   *p_addr_filter = NULL;
256    UINT8               *p_counter = NULL;
257    UINT32              *p_feat_mask = NULL;
258
259
260    if (cond_type > BTM_BLE_PF_TYPE_ALL)
261    {
262        BTM_TRACE_ERROR1("unknown PF filter condition type %d", cond_type);
263        return BTM_BLE_INVALID_COUNTER;
264    }
265    /* for these three types of filter, always generic */
266    if (cond_type == BTM_BLE_PF_ADDR_FILTER ||
267        cond_type == BTM_BLE_PF_MANU_DATA ||
268        cond_type == BTM_BLE_PF_LOCAL_NAME ||
269        cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN)
270        p_bd_addr = NULL;
271
272    if ((p_addr_filter = btm_ble_find_addr_filter_counter(p_bd_addr)) == NULL &&
273        action == BTM_BLE_SCAN_COND_ADD)
274    {
275        p_addr_filter = btm_ble_alloc_addr_filter_counter(p_bd_addr->bda);
276    }
277
278    if (p_addr_filter != NULL)
279    {
280        /* all filter just cleared */
281        if ((cond_type == BTM_BLE_PF_TYPE_ALL && action == BTM_BLE_SCAN_COND_CLEAR) ||
282            /* or bd address filter been deleted */
283            (cond_type == BTM_BLE_PF_ADDR_FILTER &&
284             (action == BTM_BLE_SCAN_COND_DELETE || action == BTM_BLE_SCAN_COND_CLEAR)))
285        {
286            btm_ble_dealloc_addr_filter_counter(p_bd_addr, cond_type);
287        }
288        /* if not feature selection, update new addition/reduction of the filter counter */
289        else if (cond_type != BTM_BLE_PF_TYPE_ALL)
290        {
291        p_counter = p_addr_filter->pf_counter;
292        p_feat_mask = &p_addr_filter->feat_mask;
293
294        p_counter[cond_type] = btm_ble_cs_filter_max[cond_type] - num_available;
295
296        BTM_TRACE_DEBUG1("current filter counter number = %d", p_counter[cond_type]);
297
298        /* update corresponding feature mask */
299        if (p_counter[cond_type] > 0)
300            *p_feat_mask |= (BTM_BLE_PF_BIT_TO_MASK(cond_type));
301        else
302            *p_feat_mask &= ~(BTM_BLE_PF_BIT_TO_MASK(cond_type));
303
304        return p_counter[cond_type];
305    }
306    }
307    else
308    {
309        BTM_TRACE_ERROR0("no matching filter counter found");
310    }
311    /* no matching filter located and updated */
312    return BTM_BLE_INVALID_COUNTER;
313}
314/*******************************************************************************
315**
316** Function         btm_ble_update_pf_manu_data
317**
318** Description      this function update(add,delete or clear) the adv manufacturer
319**                  data filtering condition.
320**
321**
322** Returns          BTM_SUCCESS if sucessful,
323**                  BTM_ILLEGAL_VALUE if paramter is not valid.
324**
325*******************************************************************************/
326tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action,
327                                        tBTM_BLE_PF_COND_PARAM *p_data,
328                                        tBTM_BLE_PF_COND_TYPE cond_type)
329{
330    tBTM_BLE_PF_MANU_COND *p_manu_data = (p_data == NULL) ? NULL : &p_data->manu_data;
331    tBTM_BLE_PF_SRVC_PATTERN_COND *p_srvc_data = (p_data == NULL) ? NULL : &p_data->srvc_data;
332    UINT8       param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH],
333                *p = param,
334                len = BTM_BLE_META_HDR_LENGTH;
335    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
336
337    memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH);
338
339    if (cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN)
340    {
341        UINT8_TO_STREAM(p, BTM_BLE_META_PF_SRVC_DATA);
342    }
343    else
344    {
345        UINT8_TO_STREAM(p, BTM_BLE_META_PF_MANU_DATA);
346    }
347    UINT8_TO_STREAM(p, action);
348
349    if (action == BTM_BLE_SCAN_COND_ADD ||
350        action == BTM_BLE_SCAN_COND_DELETE)
351    {
352        if (p_manu_data == NULL)
353            return st;
354        if (cond_type == BTM_BLE_PF_SRVC_DATA_PATTERN)
355        {
356            if (p_srvc_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2))
357                p_srvc_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
358
359            UINT16_TO_STREAM(p, p_srvc_data->uuid);
360            ARRAY_TO_STREAM(p, p_srvc_data->p_pattern, p_srvc_data->data_len);
361            len += (p_srvc_data->data_len + 2);
362        }
363        else
364        {
365            if (p_manu_data->data_len > (BTM_BLE_PF_STR_LEN_MAX - 2))
366                p_manu_data->data_len = (BTM_BLE_PF_STR_LEN_MAX - 2);
367
368            UINT16_TO_STREAM(p, p_manu_data->company_id);
369            ARRAY_TO_STREAM(p, p_manu_data->p_pattern, p_manu_data->data_len);
370            len += (p_manu_data->data_len + 2);
371
372            if (p_manu_data->company_id_mask != 0)
373            {
374                UINT16_TO_STREAM (p, p_manu_data->company_id_mask);
375            }
376            else
377            {
378                memset(p, 0xff, 2);
379                p += 2;
380            }
381            if (p_manu_data->p_pattern_mask != NULL)
382            {
383                ARRAY_TO_STREAM(p, p_manu_data->p_pattern_mask, p_manu_data->data_len);
384            }
385            else
386                memset(p, 0xff, p_manu_data->data_len);
387            len += (p_manu_data->data_len + 2);
388        }
389    }
390
391    /* send manufacturer*/
392    if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
393                              len,
394                              param,
395                              btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
396    {
397        memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
398    }
399    else
400    {
401        BTM_TRACE_ERROR0("manufacturer data PF filter update failed");
402    }
403
404    return st;
405}
406/*******************************************************************************
407**
408** Function         btm_ble_update_pf_local_name
409**
410** Description      this function update(add,delete or clear) the adv lcoal name
411**                  filtering condition.
412**
413**
414** Returns          BTM_SUCCESS if sucessful,
415**                  BTM_ILLEGAL_VALUE if paramter is not valid.
416**
417*******************************************************************************/
418tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action,
419                                         tBTM_BLE_PF_COND_PARAM *p_cond)
420{
421    tBTM_BLE_PF_LOCAL_NAME_COND *p_local_name = (p_cond == NULL) ? NULL : &p_cond->local_name;
422    UINT8       param[BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH],
423                *p = param,
424                len = BTM_BLE_META_HDR_LENGTH;
425    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
426
427    memset(param, 0, BTM_BLE_PF_STR_LEN_MAX + BTM_BLE_META_HDR_LENGTH);
428
429    UINT8_TO_STREAM(p, BTM_BLE_META_PF_LOCAL_NAME);
430    UINT8_TO_STREAM(p, action);
431
432    if (action == BTM_BLE_SCAN_COND_ADD ||
433        action == BTM_BLE_SCAN_COND_DELETE)
434    {
435        if (p_local_name == NULL)
436            return st;
437
438        if (p_local_name->data_len > BTM_BLE_PF_STR_LEN_MAX)
439            p_local_name->data_len = BTM_BLE_PF_STR_LEN_MAX;
440
441        ARRAY_TO_STREAM(p, p_local_name->p_data, p_local_name->data_len);
442        len += p_local_name->data_len;
443    }
444    /* send local name filter */
445    if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
446                              len,
447                              param,
448                              btm_ble_vendor_scan_pf_cmpl_cback))
449            != BTM_NO_RESOURCES)
450    {
451        memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
452    }
453    else
454    {
455        BTM_TRACE_ERROR0("Local Name PF filter update failed");
456    }
457
458    return st;
459}
460/*******************************************************************************
461**
462** Function         btm_ble_update_addr_filter
463**
464** Description      this function update(add,delete or clear) the address filter of adv.
465**
466**
467** Returns          BTM_SUCCESS if sucessful,
468**                  BTM_ILLEGAL_VALUE if paramter is not valid.
469**
470*******************************************************************************/
471tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action,
472                                       tBTM_BLE_PF_COND_PARAM *p_cond)
473{
474    UINT8       param[BTM_BLE_META_ADDR_LEN + BTM_BLE_META_HDR_LENGTH],
475                * p= param;
476    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
477    tBLE_BD_ADDR *p_addr = (p_cond == NULL) ? NULL : &p_cond->target_addr;
478
479    memset(param, 0, BTM_BLE_META_ADDR_LEN + BTM_BLE_META_HDR_LENGTH);
480
481    UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
482    UINT8_TO_STREAM(p, action);
483
484    if (action == BTM_BLE_SCAN_COND_ADD ||
485        action == BTM_BLE_SCAN_COND_DELETE)
486    {
487        if (p_addr == NULL)
488            return st;
489
490        BDADDR_TO_STREAM(p, p_addr->bda);
491        UINT8_TO_STREAM(p, p_addr->type);
492    }
493    /* send address filter */
494    if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
495                              (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
496                              param,
497                              btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
498    {
499        memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
500    }
501    else
502    {
503        BTM_TRACE_ERROR0("Broadcaster Address Filter Update failed");
504    }
505    return st;
506}
507/*******************************************************************************
508**
509** Function         btm_ble_update_uuid_filter
510**
511** Description      this function update(add,delete or clear) service UUID filter.
512**
513**
514** Returns          BTM_SUCCESS if sucessful,
515**                  BTM_ILLEGAL_VALUE if paramter is not valid.
516**
517*******************************************************************************/
518tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action,
519                                       tBTM_BLE_PF_COND_TYPE filter_type,
520                                       tBTM_BLE_PF_COND_PARAM *p_cond)
521{
522    UINT8       param[BTM_BLE_META_UUID_LEN + BTM_BLE_META_HDR_LENGTH],
523                * p= param,
524                len = BTM_BLE_META_HDR_LENGTH + 7;
525    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
526    tBTM_BLE_PF_UUID_COND *p_uuid_cond;
527    UINT8           evt_type;
528
529    memset(param, 0, BTM_BLE_META_UUID_LEN + BTM_BLE_META_HDR_LENGTH);
530
531    if (filter_type == BTM_BLE_PF_SRVC_UUID)
532    {
533        evt_type = BTM_BLE_META_PF_UUID;
534        p_uuid_cond = p_cond ? &p_cond->srvc_uuid : NULL;
535    }
536    else
537    {
538        evt_type = BTM_BLE_META_PF_SOL_UUID;
539        p_uuid_cond = p_cond ? &p_cond->solicitate_uuid : NULL;
540    }
541
542    if (p_uuid_cond == NULL && action != BTM_BLE_SCAN_COND_CLEAR)
543    {
544        BTM_TRACE_ERROR0("Illegal param for add/delete UUID filter");
545        return st;
546    }
547
548    /* need to add address fitler first, if adding per bda UUID filter without address filter */
549    if (action == BTM_BLE_SCAN_COND_ADD &&
550        p_uuid_cond->p_target_addr &&
551        btm_ble_find_addr_filter_counter(p_uuid_cond->p_target_addr) == NULL)
552    {
553        UINT8_TO_STREAM(p, BTM_BLE_META_PF_ADDR);
554        UINT8_TO_STREAM(p, action);
555
556        BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda);
557        UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type);
558
559        /* send address filter */
560        if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
561                                  (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_META_ADDR_LEN),
562                                  param,
563                                  btm_ble_vendor_scan_pf_cmpl_cback)) == BTM_NO_RESOURCES)
564        {
565            BTM_TRACE_ERROR0("Update Address filter into controller failed.");
566            return st;
567        }
568    }
569
570    p= param;
571    UINT8_TO_STREAM(p, evt_type);
572    UINT8_TO_STREAM(p, action);
573
574    /* per BD ADDR UUID filter */
575    if (p_uuid_cond && p_uuid_cond->p_target_addr)
576    {
577        BDADDR_TO_STREAM(p, p_uuid_cond->p_target_addr->bda);
578        UINT8_TO_STREAM(p, p_uuid_cond->p_target_addr->type);
579    }
580    else /* generic UUID filter */
581    {
582        BDADDR_TO_STREAM(p, na_bda);
583        UINT8_TO_STREAM(p, 0x02);
584    }
585
586    if (action == BTM_BLE_SCAN_COND_ADD ||
587        action == BTM_BLE_SCAN_COND_DELETE)
588    {
589        UINT8_TO_STREAM(p, p_uuid_cond->cond_logic);
590        len ++;
591
592        if (p_uuid_cond->uuid.len == LEN_UUID_16)
593        {
594            UINT16_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid16);
595            len += LEN_UUID_16;
596        }
597        else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */
598        {
599            UINT32_TO_STREAM(p, p_uuid_cond->uuid.uu.uuid32);
600            len += LEN_UUID_32;
601        }
602        else if (p_uuid_cond->uuid.len == LEN_UUID_128)
603        {
604            ARRAY_TO_STREAM (p, p_uuid_cond->uuid.uu.uuid128, LEN_UUID_128);
605            len += LEN_UUID_128;
606        }
607        else
608        {
609            BTM_TRACE_ERROR1("illegal UUID length: %d", p_uuid_cond->uuid.len);
610            return BTM_ILLEGAL_VALUE;
611        }
612#if !(defined VENDOR_ADV_PCF_LEGACY && VENDOR_ADV_PCF_LEGACY == TRUE)
613        if (p_uuid_cond->p_uuid_mask != NULL)
614        {
615            if (p_uuid_cond->uuid.len == LEN_UUID_16)
616            {
617                UINT16_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid16_mask);
618                len += LEN_UUID_16;
619            }
620            else if (p_uuid_cond->uuid.len == LEN_UUID_32)/*4 bytes */
621            {
622                UINT32_TO_STREAM(p, p_uuid_cond->p_uuid_mask->uuid32_mask);
623                len += LEN_UUID_32;
624            }
625            else if (p_uuid_cond->uuid.len == LEN_UUID_128)
626            {
627                ARRAY_TO_STREAM (p, p_uuid_cond->p_uuid_mask->uuid128_mask, LEN_UUID_128);
628                len += LEN_UUID_128;
629            }
630        }
631        else
632        {
633            memset(p, 0xff, p_uuid_cond->uuid.len);
634            len += p_uuid_cond->uuid.len;
635        }
636#endif
637    }
638
639    /* send UUID filter update */
640    if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
641                              len,
642                              param,
643                              btm_ble_vendor_scan_pf_cmpl_cback)) != BTM_NO_RESOURCES)
644    {
645        if (p_uuid_cond && p_uuid_cond->p_target_addr)
646            memcpy(&btm_ble_vendor_cb.cur_filter_target, p_uuid_cond->p_target_addr, sizeof(tBLE_BD_ADDR));
647        else
648            memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
649    }
650    else
651    {
652        BTM_TRACE_ERROR0("UUID filter udpating failed");
653    }
654
655    return st;
656}
657/*******************************************************************************
658**
659** Function         btm_ble_update_srvc_data_change
660**
661** Description      this function update(add/remove) service data change filter.
662**
663**
664** Returns          BTM_SUCCESS if sucessful,
665**                  BTM_ILLEGAL_VALUE if paramter is not valid.
666**
667*******************************************************************************/
668tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action,
669                                       tBTM_BLE_PF_COND_PARAM *p_cond)
670{
671    tBTM_STATUS st = BTM_ILLEGAL_VALUE;
672    tBLE_BD_ADDR   *p_bd_addr = p_cond ? &p_cond->target_addr : NULL;
673    UINT8           num_avail = (action == BTM_BLE_SCAN_COND_ADD) ? 0 : 1;
674
675    if (btm_ble_cs_update_pf_counter (action, BTM_BLE_PF_SRVC_DATA, p_bd_addr, num_avail)
676                    != BTM_BLE_INVALID_COUNTER)
677        st = BTM_SUCCESS;
678
679    return st;
680}
681
682/*******************************************************************************
683**
684** Function         btm_ble_clear_scan_pf_filter
685**
686** Description      clear all adv payload filter by de-select all the adv pf feature bits
687**
688**
689** Returns          BTM_SUCCESS if sucessful,
690**                  BTM_ILLEGAL_VALUE if paramter is not valid.
691**
692*******************************************************************************/
693tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action,
694                                       tBTM_BLE_PF_COND_PARAM *p_cond)
695{
696    tBLE_BD_ADDR *p_target = (p_cond == NULL)? NULL : &p_cond->target_addr;
697    tBTM_BLE_PF_COUNT *p_bda_filter;
698    tBTM_STATUS     st = BTM_WRONG_MODE;
699    UINT8           param[20], *p;
700
701    if (action != BTM_BLE_SCAN_COND_CLEAR)
702    {
703        BTM_TRACE_ERROR1("unable to perform action:%d for generic adv filter type", action);
704        return BTM_ILLEGAL_VALUE;
705    }
706
707    p = param;
708    memset(param, 0, 20);
709
710    p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
711
712    if (p_bda_filter == NULL ||
713        /* not a generic filter, and feature selection is empty */
714        (p_target != NULL && p_bda_filter && p_bda_filter->feat_mask == 0))
715    {
716        BTM_TRACE_ERROR0("Error: Can not clear filter, No PF filter has been configured!");
717        return st;
718    }
719
720    /* clear the general filter entry */
721    if (p_target == NULL)
722    {
723        /* clear manufactuer data filter */
724        btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, NULL, BTM_BLE_PF_MANU_DATA);
725        /* clear local name filter */
726        btm_ble_update_pf_local_name(BTM_BLE_SCAN_COND_CLEAR, NULL);
727        /* update the counter  for service data */
728        btm_ble_update_srvc_data_change(BTM_BLE_SCAN_COND_CLEAR, NULL);
729        /* clear UUID filter */
730        btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, BTM_BLE_PF_SRVC_UUID, NULL);
731        btm_ble_update_uuid_filter(BTM_BLE_SCAN_COND_CLEAR, BTM_BLE_META_PF_SOL_UUID, NULL);
732        /* clear service data filter */
733        btm_ble_update_pf_manu_data(BTM_BLE_SCAN_COND_CLEAR, NULL, BTM_BLE_PF_MANU_DATA);
734    }
735
736    /* select feature based on control block settings */
737    UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
738    UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_CLEAR);
739
740    if (p_target != NULL)
741    {
742        BDADDR_TO_STREAM(p, p_target->bda);
743        UINT8_TO_STREAM(p, p_target->type);
744    }
745    else
746    {
747        BDADDR_TO_STREAM(p, na_bda);
748        UINT8_TO_STREAM(p, 0x02);
749    }
750
751    /* set PCF selection */
752    UINT32_TO_STREAM(p, BTM_BLE_PF_SELECT_NONE);
753    /* set logic condition as OR as default */
754    UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR);
755
756    if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
757                               (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN),
758                                param,
759                                btm_ble_vendor_scan_pf_cmpl_cback))
760            != BTM_NO_RESOURCES)
761    {
762        if (p_bda_filter)
763            p_bda_filter->feat_mask = BTM_BLE_PF_SELECT_NONE;
764
765        if (p_target)
766            memcpy(&btm_ble_vendor_cb.cur_filter_target, p_target, sizeof(tBLE_BD_ADDR));
767        else
768            memset(&btm_ble_vendor_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
769    }
770
771    return st;
772}
773/*******************************************************************************
774**
775** Function         BTM_BleEnableFilterCondition
776**
777** Description      This function is called to enable the adv data payload filter
778**                  condition.
779**
780** Parameters       p_target: enabble the filter condition on a target device; if NULL
781**                            enable the generic scan condition.
782**                  enable: enable or disable the filter condition
783**
784** Returns          void
785**
786*******************************************************************************/
787tBTM_STATUS BTM_BleEnableFilterCondition(BOOLEAN enable, tBLE_BD_ADDR *p_target,
788                                         tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback)
789{
790    UINT8           param[20], *p;
791    tBTM_STATUS     st = BTM_WRONG_MODE;
792    tBTM_BLE_PF_COUNT *p_bda_filter;
793
794    p = param;
795    memset(param, 0, 20);
796
797    if (btm_ble_vendor_cb.p_scan_pf_cback)
798    {
799        BTM_TRACE_ERROR0("ADV PF Filter activity busy");
800        return BTM_BUSY;
801    }
802
803    if (enable)
804    {
805        p_bda_filter = btm_ble_find_addr_filter_counter(p_target);
806
807        if (p_bda_filter == NULL ||
808            (p_bda_filter && p_bda_filter->feat_mask == BTM_BLE_PF_SELECT_NONE))
809        {
810            BTM_TRACE_ERROR0("No PF filter has been configured!");
811            return st;
812        }
813
814        /* select feature based on control block settings */
815        UINT8_TO_STREAM(p, BTM_BLE_META_PF_FEAT_SEL);
816        UINT8_TO_STREAM(p, BTM_BLE_SCAN_COND_ADD);
817
818        if (p_target != NULL)
819        {
820            BDADDR_TO_STREAM(p, p_target->bda);
821            UINT8_TO_STREAM(p, p_target->type);
822        }
823        else
824        {
825            BDADDR_TO_STREAM(p, na_bda);
826            UINT8_TO_STREAM(p, 0x02);
827        }
828
829        /* set PCF selection */
830        UINT32_TO_STREAM(p, p_bda_filter->feat_mask);
831        /* set logic condition as OR as default */
832        UINT8_TO_STREAM(p, BTM_BLE_PF_LOGIC_OR);
833
834        if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
835                                   (UINT8)(BTM_BLE_META_HDR_LENGTH + BTM_BLE_PF_FEAT_SEL_LEN),
836                                    param,
837                                    btm_ble_vendor_scan_pf_cmpl_cback))
838               == BTM_NO_RESOURCES)
839        {
840            return st;
841        }
842
843        /* enable the content filter in controller */
844        p = param;
845        UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE);
846        /* enable adv data payload filtering */
847        UINT8_TO_STREAM(p, enable);
848    }
849    else
850    {
851        UINT8_TO_STREAM(p, BTM_BLE_META_PF_ENABLE);
852        /* disable adv data payload filtering */
853        UINT8_TO_STREAM(p, enable);
854    }
855
856    if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_PCF_VSC,
857                               BTM_BLE_PCF_ENABLE_LEN,
858                               param,
859                               btm_ble_vendor_scan_pf_cmpl_cback))
860         == BTM_CMD_STARTED)
861    {
862        btm_ble_vendor_cb.op_type =  BTM_BLE_SET_SCAN_PF_OPCODE(BTM_BLE_META_PF_ENABLE, BTM_BLE_PF_ENABLE);
863        btm_ble_vendor_cb.p_scan_pf_cback = p_cmpl_cback;
864    }
865
866    return st;
867}
868/*******************************************************************************
869**
870** Function         BTM_BleCfgFilterCondition
871**
872** Description      This function is called to configure the adv data payload filter
873**                  condition.
874**
875** Parameters       action: to read/write/clear
876**                  cond_type: filter condition type.
877**                  p_cond: filter condition paramter
878**
879** Returns          void
880**
881*******************************************************************************/
882tBTM_STATUS BTM_BleCfgFilterCondition(tBTM_BLE_SCAN_COND_OP action,
883                                      tBTM_BLE_PF_COND_TYPE cond_type,
884                                      tBTM_BLE_PF_COND_PARAM *p_cond,
885                                      tBTM_BLE_PF_CMPL_CBACK *p_cmpl_cback)
886{
887    tBTM_STATUS     st = BTM_ILLEGAL_VALUE;
888
889    if (btm_ble_vendor_cb.p_scan_pf_cback != NULL)
890        return BTM_BUSY;
891
892    switch (cond_type)
893    {
894    case BTM_BLE_PF_SRVC_DATA_PATTERN:
895    /* write manufacture data filter */
896    case BTM_BLE_PF_MANU_DATA:
897        st = btm_ble_update_pf_manu_data(action, p_cond, cond_type);
898        break;
899
900    /* write local name filter */
901    case BTM_BLE_PF_LOCAL_NAME:
902        st = btm_ble_update_pf_local_name(action, p_cond);
903        break;
904
905    /* filter on advertiser address */
906    case BTM_BLE_PF_ADDR_FILTER:
907        st = btm_ble_update_addr_filter(action, p_cond);
908        break;
909
910    /* filter on service/solicitated UUID */
911    case BTM_BLE_PF_SRVC_UUID:
912    case BTM_BLE_PF_SRVC_SOL_UUID:
913        st = btm_ble_update_uuid_filter(action, cond_type, p_cond);
914        break;
915
916    case BTM_BLE_PF_SRVC_DATA:
917        st = btm_ble_update_srvc_data_change(action, p_cond);
918        break;
919
920    case BTM_BLE_PF_TYPE_ALL: /* only used to clear filter */
921        st = btm_ble_clear_scan_pf_filter(action, p_cond);
922        break;
923
924    default:
925        BTM_TRACE_WARNING1("condition type [%d] not supported currently.", cond_type);
926        break;
927    }
928    if (st == BTM_CMD_STARTED
929        /* no vsc needed for service data change */
930        && cond_type != BTM_BLE_PF_SRVC_DATA)
931    {
932        btm_ble_vendor_cb.op_type        = BTM_BLE_SET_SCAN_PF_OPCODE(cond_type, BTM_BLE_PF_CONFIG);
933        btm_ble_vendor_cb.p_scan_pf_cback = p_cmpl_cback;
934    }
935
936    return st;
937}
938
939
940/*******************************************************************************
941**
942** Function         btm_ble_vendor_init
943**
944** Description      Initialize customer specific feature information in host stack
945**
946** Parameters
947**
948** Returns          status
949**
950*******************************************************************************/
951void btm_ble_vendor_init(void)
952{
953    memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB));
954
955    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
956        return;
957}
958
959#endif
960
961
962