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