btm_ble_batchscan.c 37 KB

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