Home | History | Annotate | Download | only in btm
      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 #include <string.h>
     19 #include <stdio.h>
     20 #include <stddef.h>
     21 #include "bt_target.h"
     22 
     23 #include "btm_ble_api.h"
     24 #include "bt_types.h"
     25 #include "bt_utils.h"
     26 #include "btu.h"
     27 #include "btm_int.h"
     28 #include "hcimsgs.h"
     29 
     30 #if (BLE_INCLUDED == TRUE)
     31 
     32 tBTM_BLE_BATCH_SCAN_CB ble_batchscan_cb;
     33 tBTM_BLE_ADV_TRACK_CB ble_advtrack_cb;
     34 
     35 
     36 /* length of each batch scan command */
     37 #define BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN      4
     38 #define BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN    12
     39 #define BTM_BLE_BATCH_SCAN_ENB_DISB_LEN         2
     40 #define BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN     2
     41 
     42 #define BTM_BLE_BATCH_SCAN_CB_EVT_MASK       0xF0
     43 #define BTM_BLE_BATCH_SCAN_SUBCODE_MASK      0x0F
     44 
     45 #define BTM_BLE_TRACK_ADV_CMD_LEN               9
     46 
     47 /*******************************************************************************
     48 **  Local functions
     49 *******************************************************************************/
     50 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params);
     51 void btm_ble_batchscan_cleanup(void);
     52 
     53 /*******************************************************************************
     54 **
     55 ** Function         btm_ble_batchscan_filter_track_adv_vse_cback
     56 **
     57 ** Description      VSE callback for batch scan, filter, and tracking events.
     58 **
     59 ** Returns          None
     60 **
     61 *******************************************************************************/
     62 void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p)
     63 {
     64     UINT8   sub_event = 0, filt_index = 0, addr_type = 0, adv_state = 0;
     65     BD_ADDR bd_addr;
     66     STREAM_TO_UINT8(sub_event, p);
     67 
     68     BTM_TRACE_EVENT("btm_ble_batchscan_filter_track_adv_vse_cback called with event:%x", sub_event);
     69     if (HCI_VSE_SUBCODE_BLE_THRESHOLD_SUB_EVT == sub_event &&
     70         NULL != ble_batchscan_cb.p_thres_cback)
     71     {
     72         ble_batchscan_cb.p_thres_cback(ble_batchscan_cb.ref_value);
     73         return;
     74     }
     75 
     76     if (HCI_VSE_SUBCODE_BLE_TRACKING_SUB_EVT == sub_event && NULL != ble_advtrack_cb.p_track_cback)
     77     {
     78         if (len < 10)
     79             return;
     80         STREAM_TO_UINT8(filt_index, p);
     81         STREAM_TO_UINT8(addr_type, p);
     82         STREAM_TO_BDADDR(bd_addr, p);
     83         STREAM_TO_UINT8(adv_state, p);
     84         BTM_TRACE_EVENT("track_adv_vse_cback called: %d, %d, %d", filt_index, addr_type, adv_state);
     85         ble_advtrack_cb.p_track_cback(filt_index, addr_type, bd_addr, adv_state,
     86             ble_advtrack_cb.ref_value);
     87         return;
     88     }
     89 }
     90 
     91 /*******************************************************************************
     92 **
     93 ** Function         btm_ble_batchscan_enq_op_q
     94 **
     95 ** Description      enqueue a batchscan operation in q to check command complete
     96 **                  status
     97 **
     98 ** Returns          void
     99 **
    100 *******************************************************************************/
    101 void btm_ble_batchscan_enq_op_q(UINT8 opcode, tBTM_BLE_BATCH_SCAN_STATE cur_state,
    102                                           UINT8 cb_evt, tBTM_BLE_REF_VALUE ref_value)
    103 {
    104     ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx] = (opcode |(cb_evt << 4));
    105     ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx] = cur_state;
    106     ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx] = ref_value;
    107     BTM_TRACE_DEBUG("btm_ble_batchscan_enq_op_q: subcode:%d, Cur_state:%d, ref_value:%d",
    108         ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.next_idx],
    109         ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.next_idx],
    110         ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.next_idx]);
    111     ble_batchscan_cb.op_q.next_idx = (ble_batchscan_cb.op_q.next_idx + 1)
    112                                         % BTM_BLE_BATCH_SCAN_MAX;
    113 }
    114 
    115 /*******************************************************************************
    116 **
    117 ** Function         btm_ble_batchscan_enq_rep_q
    118 **
    119 ** Description      enqueue a batchscan report operation in q to check command complete
    120 **                  status
    121 **
    122 ** Returns          void
    123 **
    124 *******************************************************************************/
    125 tBTM_STATUS btm_ble_batchscan_enq_rep_q(UINT8 report_format, tBTM_BLE_REF_VALUE ref_value)
    126 {
    127     int i = 0;
    128     for (i = 0; i < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; i++)
    129     {
    130         if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[i])
    131             return BTM_ILLEGAL_VALUE;
    132     }
    133 
    134     ble_batchscan_cb.main_rep_q.rep_mode[ble_batchscan_cb.main_rep_q.next_idx] = report_format;
    135     ble_batchscan_cb.main_rep_q.ref_value[ble_batchscan_cb.main_rep_q.next_idx] = ref_value;
    136     ble_batchscan_cb.main_rep_q.num_records[ble_batchscan_cb.main_rep_q.next_idx] = 0;
    137     ble_batchscan_cb.main_rep_q.data_len[ble_batchscan_cb.main_rep_q.next_idx] = 0;
    138     ble_batchscan_cb.main_rep_q.p_data[ble_batchscan_cb.main_rep_q.next_idx] = NULL;
    139     BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_q: index:%d, rep %d, ref %d",
    140             ble_batchscan_cb.main_rep_q.next_idx, report_format, ref_value);
    141 
    142     ble_batchscan_cb.main_rep_q.next_idx = (ble_batchscan_cb.main_rep_q.next_idx + 1)
    143                                             % BTM_BLE_BATCH_REP_MAIN_Q_SIZE;
    144     return BTM_SUCCESS;
    145 }
    146 
    147 /*******************************************************************************
    148 **
    149 ** Function         btm_ble_batchscan_enq_rep_data
    150 **
    151 ** Description      setup the data in the main report queue
    152 **
    153 ** Returns          void
    154 **
    155 *******************************************************************************/
    156 void btm_ble_batchscan_enq_rep_data(UINT8 report_format, UINT8 num_records, UINT8 *p_data,
    157                                     UINT8 data_len)
    158 {
    159     int index = 0, len = 0;
    160     UINT8 *p_orig_data = NULL, *p_app_data = NULL;
    161 
    162     for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
    163     {
    164         if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index])
    165             break;
    166     }
    167 
    168     BTM_TRACE_DEBUG("btm_ble_batchscan_enq_rep_data: index:%d, rep %d, num %d len : %d",
    169         index, report_format, num_records, data_len);
    170 
    171     if (index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE && data_len > 0 && num_records > 0)
    172     {
    173         len = ble_batchscan_cb.main_rep_q.data_len[index];
    174         p_orig_data = ble_batchscan_cb.main_rep_q.p_data[index];
    175         if (NULL != p_orig_data)
    176         {
    177             p_app_data = GKI_getbuf(len + data_len);
    178             memcpy(p_app_data, p_orig_data, len);
    179             memcpy(p_app_data+len, p_data, data_len);
    180             GKI_freebuf(p_orig_data);
    181             ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
    182             ble_batchscan_cb.main_rep_q.num_records[index] += num_records;
    183             ble_batchscan_cb.main_rep_q.data_len[index] += data_len;
    184         }
    185         else
    186         {
    187             p_app_data = GKI_getbuf(data_len);
    188             memcpy(p_app_data, p_data, data_len);
    189             ble_batchscan_cb.main_rep_q.p_data[index] = p_app_data;
    190             ble_batchscan_cb.main_rep_q.num_records[index] = num_records;
    191             ble_batchscan_cb.main_rep_q.data_len[index] = data_len;
    192         }
    193     }
    194 }
    195 
    196 /*******************************************************************************
    197 **
    198 ** Function         btm_ble_batchscan_deq_rep_q
    199 **
    200 ** Description      dequeue a batchscan report  in q when command complete
    201 **                  is received
    202 **
    203 ** Returns          void
    204 **
    205 *******************************************************************************/
    206 void btm_ble_batchscan_deq_rep_data(UINT8 report_format, tBTM_BLE_REF_VALUE *p_ref_value,
    207                                  UINT8 *p_num_records, UINT8 **p_data, UINT16 *p_data_len)
    208 {
    209     int index = 0;
    210 
    211     for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
    212     {
    213         if (report_format == ble_batchscan_cb.main_rep_q.rep_mode[index])
    214             break;
    215     }
    216 
    217     if (BTM_BLE_BATCH_REP_MAIN_Q_SIZE == index)
    218     {
    219         BTM_TRACE_ERROR("btm_ble_batchscan_deq_rep_data: rep_format:%d not found", report_format);
    220         return;
    221     }
    222 
    223     *p_num_records = ble_batchscan_cb.main_rep_q.num_records[index];
    224     *p_ref_value = ble_batchscan_cb.main_rep_q.ref_value[index];
    225     *p_data = ble_batchscan_cb.main_rep_q.p_data[index];
    226     *p_data_len = ble_batchscan_cb.main_rep_q.data_len[index];
    227 
    228     ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
    229     ble_batchscan_cb.main_rep_q.data_len[index] = 0;
    230     ble_batchscan_cb.main_rep_q.rep_mode[index] = 0;
    231     ble_batchscan_cb.main_rep_q.ref_value[index] = 0;
    232     ble_batchscan_cb.main_rep_q.num_records[index] = 0;
    233 
    234     BTM_TRACE_DEBUG("btm_ble_batchscan_deq_rep_data: index:%d, rep %d, num %d, data_len %d",
    235         index, report_format, *p_num_records, *p_data_len);
    236 
    237     ble_batchscan_cb.main_rep_q.pending_idx = (ble_batchscan_cb.main_rep_q.pending_idx + 1)
    238                                             % BTM_BLE_BATCH_SCAN_MAX;
    239 }
    240 
    241 /*******************************************************************************
    242 **
    243 ** Function         btm_ble_batchscan_deq_op_q
    244 **
    245 ** Description      dequeue a batch scan operation from q when command complete
    246 **                  is received
    247 **
    248 ** Returns          void
    249 **
    250 *******************************************************************************/
    251 void btm_ble_batchscan_deq_op_q(UINT8 *p_opcode,tBTM_BLE_BATCH_SCAN_STATE *cur_state,
    252                                           UINT8 *p_cb_evt, tBTM_BLE_REF_VALUE *p_ref)
    253 {
    254     *p_cb_evt = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx] >> 4);
    255     *p_opcode = (ble_batchscan_cb.op_q.sub_code[ble_batchscan_cb.op_q.pending_idx]
    256                                             & BTM_BLE_BATCH_SCAN_SUBCODE_MASK);
    257     *p_ref = ble_batchscan_cb.op_q.ref_value[ble_batchscan_cb.op_q.pending_idx];
    258     *cur_state = (ble_batchscan_cb.op_q.cur_state[ble_batchscan_cb.op_q.pending_idx]);
    259     ble_batchscan_cb.op_q.pending_idx = (ble_batchscan_cb.op_q.pending_idx + 1)
    260                                             % BTM_BLE_BATCH_SCAN_MAX;
    261 }
    262 
    263 /*******************************************************************************
    264 **
    265 ** Function         btm_ble_read_batchscan_reports
    266 **
    267 ** Description      This function reads the reports from controller
    268 **
    269 ** Parameters       scan_mode - The mode for which the reports are to be read out from the controller
    270 **                  ref_value - Reference value
    271 **
    272 ** Returns          status
    273 **
    274 *******************************************************************************/
    275 tBTM_STATUS btm_ble_read_batchscan_reports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
    276                                           tBTM_BLE_REF_VALUE ref_value)
    277 {
    278     tBTM_STATUS     status = BTM_NO_RESOURCES;
    279     UINT8 param[BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN], *pp;
    280     pp = param;
    281 
    282     memset(param, 0, BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN);
    283 
    284     UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_READ_RESULTS);
    285     UINT8_TO_STREAM (pp, scan_mode);
    286 
    287     if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
    288             BTM_BLE_BATCH_SCAN_READ_RESULTS_LEN, param, btm_ble_batchscan_vsc_cmpl_cback))
    289             != BTM_CMD_STARTED)
    290     {
    291         BTM_TRACE_ERROR("btm_ble_read_batchscan_reports %d", status);
    292         return BTM_ILLEGAL_VALUE;
    293     }
    294 
    295     if (BTM_CMD_STARTED == status)
    296     {
    297         /* The user needs to be provided scan read reports event */
    298         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_READ_RESULTS, ble_batchscan_cb.cur_state,
    299                                    BTM_BLE_BATCH_SCAN_READ_REPTS_EVT, ref_value);
    300     }
    301 
    302     return status;
    303 }
    304 
    305 /*******************************************************************************
    306 **
    307 ** Function         btm_ble_batchscan_vsc_cmpl_cback
    308 **
    309 ** Description      Batch scan VSC complete callback
    310 **
    311 ** Parameters       p_params - VSC completed callback parameters
    312 **
    313 ** Returns          void
    314 **
    315 *******************************************************************************/
    316 void btm_ble_batchscan_vsc_cmpl_cback (tBTM_VSC_CMPL *p_params)
    317 {
    318     UINT8  *p = p_params->p_param_buf;
    319     UINT16  len = p_params->param_len;
    320     tBTM_BLE_REF_VALUE ref_value = 0;
    321     int index = 0;
    322 
    323     UINT8  status = 0, subcode = 0, opcode = 0;
    324     UINT8 report_format = 0, num_records = 0, cb_evt = 0;
    325     UINT16 data_len = 0;
    326     tBTM_BLE_BATCH_SCAN_STATE cur_state = 0;
    327     tBTM_STATUS btm_status = 0;
    328     UINT8 *p_data = NULL;
    329 
    330     if (len < 2)
    331     {
    332         BTM_TRACE_ERROR("wrong length for btm_ble_batch_scan_vsc_cmpl_cback");
    333         btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
    334         return;
    335     }
    336 
    337     STREAM_TO_UINT8(status, p);
    338     STREAM_TO_UINT8(subcode, p);
    339 
    340     btm_ble_batchscan_deq_op_q(&opcode, &cur_state, &cb_evt, &ref_value);
    341 
    342     BTM_TRACE_DEBUG("btm_ble_batchscan op_code = %02x state = %02x cb_evt = %02x,ref_value=%d",
    343         opcode, cur_state, cb_evt, ref_value);
    344 
    345     if (opcode != subcode)
    346     {
    347         BTM_TRACE_ERROR("Got unexpected VSC cmpl, expected: %d got: %d",subcode,opcode);
    348         return;
    349     }
    350 
    351     switch (subcode)
    352     {
    353         case BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE:
    354         {
    355              if (BTM_SUCCESS == status && BTM_BLE_SCAN_ENABLE_CALLED == cur_state)
    356                  ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLED_STATE;
    357              else
    358              if (BTM_BLE_SCAN_ENABLE_CALLED == cur_state)
    359              {
    360                  BTM_TRACE_ERROR("SCAN_ENB_DISAB_CUST_FEATURE - Invalid state after enb");
    361                  ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
    362              }
    363 
    364              BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEAT status = %d, state: %d,evt=%d",
    365                                 status, ble_batchscan_cb.cur_state, cb_evt);
    366 
    367              if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
    368                 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
    369              break;
    370         }
    371 
    372         case BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM:
    373         {
    374             BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM status = %d, evt=%d",
    375                             status, cb_evt);
    376             if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
    377                 ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
    378             break;
    379         }
    380 
    381         case BTM_BLE_BATCH_SCAN_SET_PARAMS:
    382         {
    383             BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_SET_PARAMS status = %d,evt=%d", status, cb_evt);
    384 
    385             if (BTM_BLE_SCAN_DISABLE_CALLED == cur_state)
    386             {
    387                 if (BTM_SUCCESS == status)
    388                 {
    389                     ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLED_STATE;
    390                 }
    391                 else
    392                 {
    393                     BTM_TRACE_ERROR("BTM_BLE_BATCH_SCAN_SET_PARAMS - Invalid state after disabled");
    394                     ble_batchscan_cb.cur_state = BTM_BLE_SCAN_INVALID_STATE;
    395                 }
    396             }
    397 
    398             if (cb_evt != 0 && NULL != ble_batchscan_cb.p_setup_cback)
    399                ble_batchscan_cb.p_setup_cback(cb_evt, ref_value, status);
    400             break;
    401         }
    402 
    403         case BTM_BLE_BATCH_SCAN_READ_RESULTS:
    404         {
    405             if (cb_evt != 0 && NULL != ble_batchscan_cb.p_scan_rep_cback)
    406             {
    407                 STREAM_TO_UINT8(report_format,p);
    408                 STREAM_TO_UINT8(num_records, p);
    409                 p = (uint8_t *)(p_params->p_param_buf + 4);
    410                 BTM_TRACE_DEBUG("BTM_BLE_BATCH_SCAN_READ_RESULTS status=%d,len=%d,rec=%d",
    411                     status, len-4, num_records);
    412 
    413                 if (0 == num_records)
    414                 {
    415                     btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
    416                                                    &p_data, &data_len);
    417                     if (NULL != ble_batchscan_cb.p_scan_rep_cback)
    418                         ble_batchscan_cb.p_scan_rep_cback(ref_value,report_format, num_records,
    419                                                           data_len, p_data, status);
    420                 }
    421                 else
    422                 {
    423                     if ((len-4) > 0)
    424                     {
    425                         btm_ble_batchscan_enq_rep_data(report_format, num_records, p, len-4);
    426                         /* More records could be in the buffer and needs to be pulled out */
    427                         btm_status = btm_ble_read_batchscan_reports(report_format, ref_value);
    428                         if (BTM_CMD_STARTED != btm_status)
    429                         {
    430                             btm_ble_batchscan_deq_rep_data(report_format, &ref_value, &num_records,
    431                                                            &p_data, &data_len);
    432                             /* Send whatever is available, in case of a command failure */
    433                             if (NULL != ble_batchscan_cb.p_scan_rep_cback && NULL != p_data)
    434                                 ble_batchscan_cb.p_scan_rep_cback(ref_value,report_format,
    435                                                  num_records, data_len, p_data, status);
    436                         }
    437                     }
    438                 }
    439             }
    440             break;
    441         }
    442 
    443         default:
    444             break;
    445     }
    446 
    447     return;
    448 }
    449 
    450 /*******************************************************************************
    451 **
    452 ** Function         btm_ble_set_storage_config
    453 **
    454 ** Description      This function writes the storage configuration in controller
    455 **
    456 ** Parameters       batch_scan_full_max -Max storage space (in %) allocated to full scanning
    457 **                  batch_scan_trunc_max -Max storage space (in %) allocated to truncated scanning
    458 **                  batch_scan_notify_threshold - Setup notification level based on total space
    459 **
    460 ** Returns          status
    461 **
    462 *******************************************************************************/
    463 tBTM_STATUS btm_ble_set_storage_config(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max,
    464                                        UINT8 batch_scan_notify_threshold)
    465 {
    466     tBTM_STATUS     status = BTM_NO_RESOURCES;
    467     UINT8 param[BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN], *pp;
    468 
    469     pp = param;
    470     memset(param, 0, BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN);
    471 
    472     UINT8_TO_STREAM (pp, BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM);
    473     UINT8_TO_STREAM (pp, batch_scan_full_max);
    474     UINT8_TO_STREAM (pp, batch_scan_trunc_max);
    475     UINT8_TO_STREAM (pp, batch_scan_notify_threshold);
    476 
    477     if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
    478                 BTM_BLE_BATCH_SCAN_STORAGE_CFG_LEN, param,
    479                 btm_ble_batchscan_vsc_cmpl_cback))!= BTM_CMD_STARTED)
    480     {
    481         BTM_TRACE_ERROR("btm_ble_set_storage_config %d", status);
    482         return BTM_ILLEGAL_VALUE;
    483     }
    484 
    485     return status;
    486 }
    487 
    488 /*******************************************************************************
    489 **
    490 ** Function         btm_ble_set_batchscan_param
    491 **
    492 ** Description      This function writes the batch scan params in controller
    493 **
    494 ** Parameters       scan_mode -Batch scan mode
    495 **                  scan_interval - Scan interval
    496 **                  scan_window  - Scan window
    497 **                  discard_rule -Discard rules
    498 **                  addr_type - Address type
    499 **
    500 ** Returns          status
    501 **
    502 *******************************************************************************/
    503 tBTM_STATUS btm_ble_set_batchscan_param(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
    504                      UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type,
    505                      tBTM_BLE_DISCARD_RULE discard_rule)
    506 {
    507     tBTM_STATUS     status = BTM_NO_RESOURCES;
    508     UINT8 scan_param[BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN], *pp_scan;
    509 
    510     pp_scan = scan_param;
    511     memset(scan_param, 0, BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN);
    512 
    513     UINT8_TO_STREAM (pp_scan, BTM_BLE_BATCH_SCAN_SET_PARAMS);
    514     UINT8_TO_STREAM (pp_scan, scan_mode);
    515     UINT32_TO_STREAM (pp_scan, scan_window);
    516     UINT32_TO_STREAM (pp_scan, scan_interval);
    517     UINT8_TO_STREAM (pp_scan, addr_type);
    518     UINT8_TO_STREAM (pp_scan, discard_rule);
    519 
    520     if ((status = BTM_VendorSpecificCommand (HCI_BLE_BATCH_SCAN_OCF,
    521             BTM_BLE_BATCH_SCAN_PARAM_CONFIG_LEN,
    522             scan_param, btm_ble_batchscan_vsc_cmpl_cback))!= BTM_CMD_STARTED)
    523     {
    524         BTM_TRACE_ERROR("btm_ble_set_batchscan_param %d", status);
    525         return BTM_ILLEGAL_VALUE;
    526     }
    527 
    528     return status;
    529 }
    530 
    531 /*******************************************************************************
    532 **
    533 ** Function         btm_ble_enable_disable_batchscan
    534 **
    535 ** Description      This function enables the customer specific feature in controller
    536 **
    537 ** Parameters       enable_disable: true - enable, false - disable
    538 **
    539 ** Returns          status
    540 **
    541 *******************************************************************************/
    542 tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN should_enable)
    543 {
    544     tBTM_STATUS     status = BTM_NO_RESOURCES;
    545     UINT8 shld_enable = 0x01;
    546     UINT8 enable_param[BTM_BLE_BATCH_SCAN_ENB_DISB_LEN], *pp_enable;
    547 
    548     if (!should_enable)
    549         shld_enable = 0x00;
    550 
    551     if (should_enable)
    552     {
    553         pp_enable = enable_param;
    554         memset(enable_param, 0, BTM_BLE_BATCH_SCAN_ENB_DISB_LEN);
    555 
    556         UINT8_TO_STREAM (pp_enable, BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE);
    557         UINT8_TO_STREAM (pp_enable, shld_enable);
    558 
    559         if ((status = BTM_VendorSpecificCommand(HCI_BLE_BATCH_SCAN_OCF,
    560                  BTM_BLE_BATCH_SCAN_ENB_DISB_LEN, enable_param,
    561                  btm_ble_batchscan_vsc_cmpl_cback)) != BTM_CMD_STARTED)
    562         {
    563             status = BTM_MODE_UNSUPPORTED;
    564             BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
    565             return BTM_ILLEGAL_VALUE;
    566         }
    567     }
    568     else
    569     if ((status = btm_ble_set_batchscan_param(BTM_BLE_BATCH_SCAN_MODE_DISABLE,
    570                    ble_batchscan_cb.scan_interval, ble_batchscan_cb.scan_window,
    571                    ble_batchscan_cb.addr_type, ble_batchscan_cb.discard_rule)) != BTM_CMD_STARTED)
    572     {
    573          status = BTM_MODE_UNSUPPORTED;
    574          BTM_TRACE_ERROR("btm_ble_enable_disable_batchscan %d", status);
    575          return BTM_ILLEGAL_VALUE;
    576     }
    577 
    578     if (should_enable)
    579         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
    580     else
    581         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_DISABLE_CALLED;
    582     return status;
    583 }
    584 
    585 /*******************************************************************************
    586 **
    587 ** Function         BTM_BleSetStorageConfig
    588 **
    589 ** Description      This function is called to write storage config params.
    590 **
    591 ** Parameters:      batch_scan_full_max - Max storage space (in %) allocated to full style
    592 **                  batch_scan_trunc_max - Max storage space (in %) allocated to trunc style
    593 **                  batch_scan_notify_threshold - Setup notification level based on total space
    594 **                  p_setup_cback - Setup callback pointer
    595 **                  p_thres_cback - Threshold callback pointer
    596 **                  p_rep_cback - Reports callback pointer
    597 **                  ref_value - Reference value
    598 **
    599 ** Returns          tBTM_STATUS
    600 **
    601 *******************************************************************************/
    602 tBTM_STATUS BTM_BleSetStorageConfig(UINT8 batch_scan_full_max, UINT8 batch_scan_trunc_max,
    603                                         UINT8 batch_scan_notify_threshold,
    604                                         tBTM_BLE_SCAN_SETUP_CBACK *p_setup_cback,
    605                                         tBTM_BLE_SCAN_THRESHOLD_CBACK *p_thres_cback,
    606                                         tBTM_BLE_SCAN_REP_CBACK* p_rep_cback,
    607                                         tBTM_BLE_REF_VALUE ref_value)
    608 {
    609     tBTM_STATUS     status = BTM_NO_RESOURCES;
    610     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
    611 
    612     BTM_TRACE_EVENT (" BTM_BleSetStorageConfig: %d, %d, %d, %d, %d",
    613         ble_batchscan_cb.cur_state, ref_value, batch_scan_full_max, batch_scan_trunc_max,
    614         batch_scan_notify_threshold);
    615 
    616     if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
    617         return BTM_ILLEGAL_VALUE;
    618 
    619     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
    620 
    621     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
    622     {
    623         BTM_TRACE_ERROR("Controller does not support batch scan");
    624         return BTM_ERR_PROCESSING;
    625     }
    626 
    627     ble_batchscan_cb.p_setup_cback = p_setup_cback;
    628     ble_batchscan_cb.p_thres_cback = p_thres_cback;
    629     ble_batchscan_cb.p_scan_rep_cback = p_rep_cback;
    630     ble_batchscan_cb.ref_value = ref_value;
    631 
    632     if (batch_scan_full_max > BTM_BLE_ADV_SCAN_FULL_MAX ||
    633         batch_scan_trunc_max > BTM_BLE_ADV_SCAN_TRUNC_MAX ||
    634         batch_scan_notify_threshold > BTM_BLE_ADV_SCAN_THR_MAX)
    635     {
    636         BTM_TRACE_ERROR("Illegal set storage config params");
    637         return BTM_ILLEGAL_VALUE;
    638     }
    639 
    640      if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
    641          BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
    642          BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state)
    643     {
    644         status = btm_ble_enable_disable_batchscan(TRUE);
    645         if (BTM_CMD_STARTED != status)
    646             return status;
    647 
    648         ble_batchscan_cb.cur_state = BTM_BLE_SCAN_ENABLE_CALLED;
    649         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
    650                                     BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
    651     }
    652 
    653     status = btm_ble_set_storage_config(batch_scan_full_max, batch_scan_trunc_max,
    654                                         batch_scan_notify_threshold);
    655     if (BTM_CMD_STARTED != status)
    656        return status;
    657             /* The user needs to be provided scan config storage event */
    658      btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_STORAGE_PARAM, ble_batchscan_cb.cur_state,
    659                                    BTM_BLE_BATCH_SCAN_CFG_STRG_EVT, ref_value);
    660 
    661     return status;
    662 }
    663 
    664 
    665 /*******************************************************************************
    666 **
    667 ** Function         BTM_BleEnableBatchScan
    668 **
    669 ** Description      This function is called to configure and enable batch scanning
    670 **
    671 ** Parameters:      scan_mode -Batch scan mode
    672 **                  scan_interval - Scan interval value
    673 **                  scan_window - Scan window value
    674 **                  discard_rule - Data discard rule
    675 **                  ref_value - Reference value
    676 **
    677 ** Returns          tBTM_STATUS
    678 **
    679 *******************************************************************************/
    680 tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
    681             UINT32 scan_interval, UINT32 scan_window, tBLE_ADDR_TYPE addr_type,
    682             tBTM_BLE_DISCARD_RULE discard_rule, tBTM_BLE_REF_VALUE ref_value)
    683 {
    684     tBTM_STATUS     status = BTM_NO_RESOURCES;
    685     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
    686     BTM_TRACE_EVENT (" BTM_BleEnableBatchScan: %d, %d, %d, %d, %d, %d",
    687         scan_mode, scan_interval, scan_window, addr_type, discard_rule, ref_value);
    688 
    689     if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
    690         return BTM_ILLEGAL_VALUE;
    691 
    692     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
    693 
    694     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
    695     {
    696         BTM_TRACE_ERROR("Controller does not support batch scan");
    697         return BTM_ERR_PROCESSING;
    698     }
    699 
    700     BTM_TRACE_DEBUG("BTM_BleEnableBatchScan: %d, %x, %x, %d, %d", scan_mode, scan_interval,
    701                                         scan_window, discard_rule, ble_batchscan_cb.cur_state);
    702 
    703     /* Only 16 bits will be used for scan interval and scan window as per agreement with Google */
    704     /* So the standard LE range would suffice for scan interval and scan window */
    705     if ((BTM_BLE_VALID_PRAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) ||
    706         BTM_BLE_VALID_PRAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX))
    707         && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode || BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode
    708         || BTM_BLE_BATCH_SCAN_MODE_PASS_ACTI == scan_mode)
    709         && (BTM_BLE_DISCARD_OLD_ITEMS == discard_rule ||
    710         BTM_BLE_DISCARD_LOWER_RSSI_ITEMS == discard_rule))
    711     {
    712         if (BTM_BLE_SCAN_INVALID_STATE == ble_batchscan_cb.cur_state ||
    713             BTM_BLE_SCAN_DISABLED_STATE == ble_batchscan_cb.cur_state ||
    714             BTM_BLE_SCAN_DISABLE_CALLED == ble_batchscan_cb.cur_state)
    715         {
    716             status = btm_ble_enable_disable_batchscan(TRUE);
    717             if (BTM_CMD_STARTED != status)
    718                return status;
    719             btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_ENB_DISAB_CUST_FEATURE,
    720                                        BTM_BLE_SCAN_ENABLE_CALLED, 0, ref_value);
    721         }
    722 
    723         ble_batchscan_cb.scan_mode = scan_mode;
    724         ble_batchscan_cb.scan_interval = scan_interval;
    725         ble_batchscan_cb.scan_window = scan_window;
    726         ble_batchscan_cb.addr_type = addr_type;
    727         ble_batchscan_cb.discard_rule = discard_rule;
    728         /* This command starts batch scanning, if enabled */
    729         status = btm_ble_set_batchscan_param(scan_mode, scan_interval, scan_window, addr_type,
    730                     discard_rule);
    731         if (BTM_CMD_STARTED != status)
    732             return status;
    733 
    734         /* The user needs to be provided scan enable event */
    735         btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS, ble_batchscan_cb.cur_state,
    736                                    BTM_BLE_BATCH_SCAN_ENABLE_EVT, ref_value);
    737     }
    738     else
    739     {
    740         BTM_TRACE_ERROR("Illegal enable scan params");
    741         return BTM_ILLEGAL_VALUE;
    742     }
    743     return status;
    744 }
    745 
    746 /*******************************************************************************
    747 **
    748 ** Function         BTM_BleDisableBatchScan
    749 **
    750 ** Description      This function is called to disable batch scanning
    751 **
    752 ** Parameters:      ref_value - Reference value
    753 **
    754 ** Returns          tBTM_STATUS
    755 **
    756 *******************************************************************************/
    757 tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value)
    758 {
    759     tBTM_STATUS     status = BTM_NO_RESOURCES;
    760     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
    761     BTM_TRACE_EVENT (" BTM_BleDisableBatchScan");
    762 
    763     if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
    764         return BTM_ILLEGAL_VALUE;
    765 
    766     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
    767 
    768     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
    769     {
    770         BTM_TRACE_ERROR("Controller does not support batch scan");
    771         return BTM_ERR_PROCESSING;
    772     }
    773 
    774     status = btm_ble_enable_disable_batchscan(FALSE);
    775     if (BTM_CMD_STARTED == status)
    776     {
    777        /* The user needs to be provided scan disable event */
    778        btm_ble_batchscan_enq_op_q(BTM_BLE_BATCH_SCAN_SET_PARAMS,
    779                                   BTM_BLE_SCAN_DISABLE_CALLED, BTM_BLE_BATCH_SCAN_DISABLE_EVT,
    780                                   ref_value);
    781     }
    782 
    783     return status;
    784 }
    785 
    786 /*******************************************************************************
    787 **
    788 ** Function         BTM_BleReadScanReports
    789 **
    790 ** Description      This function is called to start reading batch scan reports
    791 **
    792 ** Parameters:      scan_mode - Batch scan mode
    793 **                  ref_value - Reference value
    794 **
    795 ** Returns          tBTM_STATUS
    796 **
    797 *******************************************************************************/
    798 tBTM_STATUS BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode,
    799                                              tBTM_BLE_REF_VALUE ref_value)
    800 {
    801     tBTM_STATUS     status = BTM_NO_RESOURCES;
    802     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
    803     UINT8 read_scan_mode = 0;
    804     UINT8  *p_data = NULL, report_format = 0, num_records = 0;
    805     UINT16 data_len = 0;
    806 
    807     BTM_TRACE_EVENT (" BTM_BleReadScanReports; %d, %d", scan_mode, ref_value);
    808 
    809     if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
    810         return BTM_ILLEGAL_VALUE;
    811 
    812     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
    813 
    814     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
    815     {
    816         BTM_TRACE_ERROR("Controller does not support batch scan");
    817         return BTM_ERR_PROCESSING;
    818     }
    819 
    820     /*  Check if the requested scan mode has already been setup by the user */
    821     read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_ACTI;
    822     if (0 == read_scan_mode)
    823         read_scan_mode = ble_batchscan_cb.scan_mode & BTM_BLE_BATCH_SCAN_MODE_PASS;
    824 
    825     /* Check only for modes, as scan reports can be called after disabling batch scan */
    826     if (read_scan_mode > 0 && (BTM_BLE_BATCH_SCAN_MODE_PASS == scan_mode ||
    827         BTM_BLE_BATCH_SCAN_MODE_ACTI == scan_mode))
    828     {
    829         status = btm_ble_batchscan_enq_rep_q(scan_mode, ref_value);
    830         if (BTM_SUCCESS == status)
    831         {
    832             status = btm_ble_read_batchscan_reports(scan_mode, ref_value);
    833             if (BTM_CMD_STARTED != status)
    834             {
    835                 btm_ble_batchscan_deq_rep_data(scan_mode, &ref_value,
    836                                                &num_records, &p_data, &data_len);
    837             }
    838         }
    839     }
    840     else
    841     {
    842         BTM_TRACE_ERROR("Illegal read scan params: %d, %d, %d", read_scan_mode, scan_mode,
    843             ble_batchscan_cb.cur_state);
    844         return BTM_ILLEGAL_VALUE;
    845     }
    846     return status;
    847 }
    848 
    849 
    850 /*******************************************************************************
    851 **
    852 ** Function         BTM_BleTrackAdvertiser
    853 **
    854 ** Description      This function is called to setup the callback for tracking advertisers
    855 **
    856 ** Parameters:      p_track_cback - Tracking callback pointer
    857 **                  ref_value - Reference value
    858 **
    859 ** Returns          tBTM_STATUS
    860 **
    861 *******************************************************************************/
    862 tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback,
    863                                         tBTM_BLE_REF_VALUE ref_value)
    864 {
    865     tBTM_BLE_VSC_CB cmn_ble_vsc_cb;
    866     BTM_TRACE_EVENT (" BTM_BleTrackAdvertiser");
    867     if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
    868         return BTM_ILLEGAL_VALUE;
    869 
    870     BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
    871 
    872     if (0 == cmn_ble_vsc_cb.tot_scan_results_strg)
    873     {
    874         BTM_TRACE_ERROR("Controller does not support scan storage");
    875         return BTM_ERR_PROCESSING;
    876     }
    877 
    878     ble_advtrack_cb.p_track_cback = p_track_cback;
    879     ble_advtrack_cb.ref_value = ref_value;
    880     return BTM_SUCCESS;
    881 }
    882 
    883 /*******************************************************************************
    884 **
    885 ** Function         btm_ble_batchscan_init
    886 **
    887 ** Description      This function initialize the batch scan control block.
    888 **
    889 ** Parameters       None
    890 **
    891 ** Returns          status
    892 **
    893 *******************************************************************************/
    894 void btm_ble_batchscan_init(void)
    895 {
    896     BTM_TRACE_EVENT (" btm_ble_batchscan_init");
    897     memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
    898     memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
    899     BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, TRUE);
    900 }
    901 
    902 /*******************************************************************************
    903 **
    904 ** Function         btm_ble_batchscan_cleanup
    905 **
    906 ** Description      This function cleans the batch scan control block.
    907 **
    908 ** Parameters       None
    909 **
    910 ** Returns          void
    911 **
    912 *******************************************************************************/
    913 void btm_ble_batchscan_cleanup(void)
    914 {
    915     int index = 0;
    916     BTM_TRACE_EVENT (" btm_ble_batchscan_cleanup");
    917 
    918     for (index = 0; index < BTM_BLE_BATCH_REP_MAIN_Q_SIZE; index++)
    919     {
    920         if (NULL != ble_batchscan_cb.main_rep_q.p_data[index])
    921             GKI_freebuf(ble_batchscan_cb.main_rep_q.p_data[index]);
    922         ble_batchscan_cb.main_rep_q.p_data[index] = NULL;
    923     }
    924 
    925     memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB));
    926     memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB));
    927 }
    928 
    929 #endif
    930