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