btm_ble_batchscan.c 38 KB

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