wmi_unified_extscan_tlv.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. /*
  2. * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <osdep.h>
  19. #include "wmi.h"
  20. #include "wmi_unified_priv.h"
  21. /**
  22. * send_reset_passpoint_network_list_cmd_tlv() - reset passpoint network list
  23. * @wmi_handle: wmi handle
  24. * @req: passpoint network request structure
  25. *
  26. * This function sends down WMI command with network id set to wildcard id.
  27. * firmware shall clear all the config entries
  28. *
  29. * Return: QDF_STATUS enumeration
  30. */
  31. static QDF_STATUS send_reset_passpoint_network_list_cmd_tlv
  32. (wmi_unified_t wmi_handle,
  33. struct wifi_passpoint_req_param *req)
  34. {
  35. wmi_passpoint_config_cmd_fixed_param *cmd;
  36. wmi_buf_t buf;
  37. uint32_t len;
  38. int ret;
  39. len = sizeof(*cmd);
  40. buf = wmi_buf_alloc(wmi_handle, len);
  41. if (!buf) {
  42. WMI_LOGE("%s: Failed allocate wmi buffer", __func__);
  43. return QDF_STATUS_E_NOMEM;
  44. }
  45. cmd = (wmi_passpoint_config_cmd_fixed_param *) wmi_buf_data(buf);
  46. WMITLV_SET_HDR(&cmd->tlv_header,
  47. WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
  48. WMITLV_GET_STRUCT_TLVLEN(
  49. wmi_passpoint_config_cmd_fixed_param));
  50. cmd->id = WMI_PASSPOINT_NETWORK_ID_WILDCARD;
  51. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  52. WMI_PASSPOINT_LIST_CONFIG_CMDID);
  53. if (ret) {
  54. WMI_LOGE("%s: Failed to send reset passpoint network list wmi cmd",
  55. __func__);
  56. wmi_buf_free(buf);
  57. return QDF_STATUS_E_FAILURE;
  58. }
  59. return QDF_STATUS_SUCCESS;
  60. }
  61. /**
  62. * send_set_passpoint_network_list_cmd_tlv() - set passpoint network list
  63. * @wmi_handle: wmi handle
  64. * @req: passpoint network request structure
  65. *
  66. * This function reads the incoming @req and fill in the destination
  67. * WMI structure and send down the passpoint configs down to the firmware
  68. *
  69. * Return: QDF_STATUS enumeration
  70. */
  71. static QDF_STATUS send_set_passpoint_network_list_cmd_tlv
  72. (wmi_unified_t wmi_handle,
  73. struct wifi_passpoint_req_param *req)
  74. {
  75. wmi_passpoint_config_cmd_fixed_param *cmd;
  76. u_int8_t i, j, *bytes;
  77. wmi_buf_t buf;
  78. uint32_t len;
  79. int ret;
  80. len = sizeof(*cmd);
  81. for (i = 0; i < req->num_networks; i++) {
  82. buf = wmi_buf_alloc(wmi_handle, len);
  83. if (!buf) {
  84. WMI_LOGE("%s: Failed allocate wmi buffer", __func__);
  85. return QDF_STATUS_E_NOMEM;
  86. }
  87. cmd = (wmi_passpoint_config_cmd_fixed_param *)
  88. wmi_buf_data(buf);
  89. WMITLV_SET_HDR(&cmd->tlv_header,
  90. WMITLV_TAG_STRUC_wmi_passpoint_config_cmd_fixed_param,
  91. WMITLV_GET_STRUCT_TLVLEN(
  92. wmi_passpoint_config_cmd_fixed_param));
  93. cmd->id = req->networks[i].id;
  94. WMI_LOGD("%s: network id: %u", __func__, cmd->id);
  95. qdf_mem_copy(cmd->realm, req->networks[i].realm,
  96. strlen(req->networks[i].realm) + 1);
  97. WMI_LOGD("%s: realm: %s", __func__, cmd->realm);
  98. for (j = 0; j < PASSPOINT_ROAMING_CONSORTIUM_ID_NUM; j++) {
  99. bytes = (uint8_t *) &req->networks[i].roaming_consortium_ids[j];
  100. WMI_LOGD("index: %d rcids: %02x %02x %02x %02x %02x %02x %02x %02x",
  101. j, bytes[0], bytes[1], bytes[2], bytes[3],
  102. bytes[4], bytes[5], bytes[6], bytes[7]);
  103. qdf_mem_copy(&cmd->roaming_consortium_ids[j],
  104. &req->networks[i].roaming_consortium_ids[j],
  105. PASSPOINT_ROAMING_CONSORTIUM_ID_LEN);
  106. }
  107. qdf_mem_copy(cmd->plmn, req->networks[i].plmn,
  108. PASSPOINT_PLMN_ID_LEN);
  109. WMI_LOGD("%s: plmn: %02x:%02x:%02x", __func__,
  110. cmd->plmn[0], cmd->plmn[1], cmd->plmn[2]);
  111. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  112. WMI_PASSPOINT_LIST_CONFIG_CMDID);
  113. if (ret) {
  114. WMI_LOGE("%s: Failed to send set passpoint network list wmi cmd",
  115. __func__);
  116. wmi_buf_free(buf);
  117. return QDF_STATUS_E_FAILURE;
  118. }
  119. }
  120. return QDF_STATUS_SUCCESS;
  121. }
  122. /** send_set_epno_network_list_cmd_tlv() - set epno network list
  123. * @wmi_handle: wmi handle
  124. * @req: epno config params request structure
  125. *
  126. * This function reads the incoming epno config request structure
  127. * and constructs the WMI message to the firmware.
  128. *
  129. * Returns: 0 on success, error number otherwise
  130. */
  131. static QDF_STATUS send_set_epno_network_list_cmd_tlv(wmi_unified_t wmi_handle,
  132. struct wifi_enhanced_pno_params *req)
  133. {
  134. wmi_nlo_config_cmd_fixed_param *cmd;
  135. nlo_configured_parameters *nlo_list;
  136. enlo_candidate_score_params *cand_score_params;
  137. u_int8_t i, *buf_ptr;
  138. wmi_buf_t buf;
  139. uint32_t len;
  140. QDF_STATUS ret;
  141. /* Fixed Params */
  142. len = sizeof(*cmd);
  143. if (req->num_networks) {
  144. /* TLV place holder for array of structures
  145. * then each nlo_configured_parameters(nlo_list) TLV.
  146. */
  147. len += WMI_TLV_HDR_SIZE;
  148. len += (sizeof(nlo_configured_parameters)
  149. * QDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS));
  150. /* TLV for array of uint32 channel_list */
  151. len += WMI_TLV_HDR_SIZE;
  152. /* TLV for nlo_channel_prediction_cfg */
  153. len += WMI_TLV_HDR_SIZE;
  154. /* TLV for candidate score params */
  155. len += sizeof(enlo_candidate_score_params);
  156. }
  157. buf = wmi_buf_alloc(wmi_handle, len);
  158. if (!buf) {
  159. WMI_LOGE("%s: Failed allocate wmi buffer", __func__);
  160. return QDF_STATUS_E_NOMEM;
  161. }
  162. cmd = (wmi_nlo_config_cmd_fixed_param *) wmi_buf_data(buf);
  163. buf_ptr = (u_int8_t *) cmd;
  164. WMITLV_SET_HDR(&cmd->tlv_header,
  165. WMITLV_TAG_STRUC_wmi_nlo_config_cmd_fixed_param,
  166. WMITLV_GET_STRUCT_TLVLEN(
  167. wmi_nlo_config_cmd_fixed_param));
  168. cmd->vdev_id = req->vdev_id;
  169. /* set flag to reset if num of networks are 0 */
  170. cmd->flags = (req->num_networks == 0 ?
  171. WMI_NLO_CONFIG_ENLO_RESET : WMI_NLO_CONFIG_ENLO);
  172. buf_ptr += sizeof(wmi_nlo_config_cmd_fixed_param);
  173. cmd->no_of_ssids = QDF_MIN(req->num_networks, WMI_NLO_MAX_SSIDS);
  174. WMI_LOGD("SSID count: %d flags: %d",
  175. cmd->no_of_ssids, cmd->flags);
  176. /* Fill nlo_config only when num_networks are non zero */
  177. if (cmd->no_of_ssids) {
  178. /* Fill networks */
  179. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  180. cmd->no_of_ssids * sizeof(nlo_configured_parameters));
  181. buf_ptr += WMI_TLV_HDR_SIZE;
  182. nlo_list = (nlo_configured_parameters *) buf_ptr;
  183. for (i = 0; i < cmd->no_of_ssids; i++) {
  184. WMITLV_SET_HDR(&nlo_list[i].tlv_header,
  185. WMITLV_TAG_ARRAY_BYTE,
  186. WMITLV_GET_STRUCT_TLVLEN(
  187. nlo_configured_parameters));
  188. /* Copy ssid and it's length */
  189. nlo_list[i].ssid.valid = true;
  190. nlo_list[i].ssid.ssid.ssid_len =
  191. req->networks[i].ssid.length;
  192. qdf_mem_copy(nlo_list[i].ssid.ssid.ssid,
  193. req->networks[i].ssid.ssid,
  194. nlo_list[i].ssid.ssid.ssid_len);
  195. WMI_LOGD("index: %d ssid: %.*s len: %d", i,
  196. nlo_list[i].ssid.ssid.ssid_len,
  197. (char *) nlo_list[i].ssid.ssid.ssid,
  198. nlo_list[i].ssid.ssid.ssid_len);
  199. /* Copy pno flags */
  200. nlo_list[i].bcast_nw_type.valid = true;
  201. nlo_list[i].bcast_nw_type.bcast_nw_type =
  202. req->networks[i].flags;
  203. WMI_LOGD("PNO flags (%u)",
  204. nlo_list[i].bcast_nw_type.bcast_nw_type);
  205. /* Copy auth bit field */
  206. nlo_list[i].auth_type.valid = true;
  207. nlo_list[i].auth_type.auth_type =
  208. req->networks[i].auth_bit_field;
  209. WMI_LOGD("Auth bit field (%u)",
  210. nlo_list[i].auth_type.auth_type);
  211. }
  212. buf_ptr += cmd->no_of_ssids * sizeof(nlo_configured_parameters);
  213. /* Fill the channel list */
  214. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
  215. buf_ptr += WMI_TLV_HDR_SIZE;
  216. /* Fill prediction_param */
  217. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
  218. buf_ptr += WMI_TLV_HDR_SIZE;
  219. /* Fill epno candidate score params */
  220. cand_score_params = (enlo_candidate_score_params *) buf_ptr;
  221. WMITLV_SET_HDR(buf_ptr,
  222. WMITLV_TAG_STRUC_enlo_candidate_score_param,
  223. WMITLV_GET_STRUCT_TLVLEN(enlo_candidate_score_params));
  224. cand_score_params->min5GHz_rssi =
  225. req->min_5ghz_rssi;
  226. cand_score_params->min24GHz_rssi =
  227. req->min_24ghz_rssi;
  228. cand_score_params->initial_score_max =
  229. req->initial_score_max;
  230. cand_score_params->current_connection_bonus =
  231. req->current_connection_bonus;
  232. cand_score_params->same_network_bonus =
  233. req->same_network_bonus;
  234. cand_score_params->secure_bonus =
  235. req->secure_bonus;
  236. cand_score_params->band5GHz_bonus =
  237. req->band_5ghz_bonus;
  238. buf_ptr += sizeof(enlo_candidate_score_params);
  239. }
  240. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  241. WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
  242. if (QDF_IS_STATUS_ERROR(ret)) {
  243. WMI_LOGE("%s: Failed to send nlo wmi cmd", __func__);
  244. wmi_buf_free(buf);
  245. return QDF_STATUS_E_INVAL;
  246. }
  247. WMI_LOGD("set ePNO list request sent successfully for vdev %d",
  248. req->vdev_id);
  249. return ret;
  250. }
  251. /**
  252. * send_extscan_get_capabilities_cmd_tlv() - extscan get capabilities
  253. * @wmi_handle: wmi handle
  254. * @pgetcapab: get capabilities params
  255. *
  256. * This function send request to fw to get extscan capabilities.
  257. *
  258. * Return: CDF status
  259. */
  260. static QDF_STATUS send_extscan_get_capabilities_cmd_tlv(wmi_unified_t wmi_handle,
  261. struct extscan_capabilities_params *pgetcapab)
  262. {
  263. wmi_extscan_get_capabilities_cmd_fixed_param *cmd;
  264. wmi_buf_t wmi_buf;
  265. uint32_t len;
  266. uint8_t *buf_ptr;
  267. len = sizeof(*cmd);
  268. wmi_buf = wmi_buf_alloc(wmi_handle, len);
  269. if (!wmi_buf) {
  270. WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
  271. return QDF_STATUS_E_NOMEM;
  272. }
  273. buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
  274. cmd = (wmi_extscan_get_capabilities_cmd_fixed_param *) buf_ptr;
  275. WMITLV_SET_HDR(&cmd->tlv_header,
  276. WMITLV_TAG_STRUC_wmi_extscan_get_capabilities_cmd_fixed_param,
  277. WMITLV_GET_STRUCT_TLVLEN
  278. (wmi_extscan_get_capabilities_cmd_fixed_param));
  279. cmd->request_id = pgetcapab->request_id;
  280. if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
  281. WMI_EXTSCAN_GET_CAPABILITIES_CMDID)) {
  282. WMI_LOGE("%s: failed to command", __func__);
  283. wmi_buf_free(wmi_buf);
  284. return QDF_STATUS_E_FAILURE;
  285. }
  286. return QDF_STATUS_SUCCESS;
  287. }
  288. /**
  289. * send_extscan_get_cached_results_cmd_tlv() - extscan get cached results
  290. * @wmi_handle: wmi handle
  291. * @pcached_results: cached results parameters
  292. *
  293. * This function send request to fw to get cached results.
  294. *
  295. * Return: CDF status
  296. */
  297. static QDF_STATUS send_extscan_get_cached_results_cmd_tlv(wmi_unified_t wmi_handle,
  298. struct extscan_cached_result_params *pcached_results)
  299. {
  300. wmi_extscan_get_cached_results_cmd_fixed_param *cmd;
  301. wmi_buf_t wmi_buf;
  302. uint32_t len;
  303. uint8_t *buf_ptr;
  304. len = sizeof(*cmd);
  305. wmi_buf = wmi_buf_alloc(wmi_handle, len);
  306. if (!wmi_buf) {
  307. WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
  308. return QDF_STATUS_E_NOMEM;
  309. }
  310. buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
  311. cmd = (wmi_extscan_get_cached_results_cmd_fixed_param *) buf_ptr;
  312. WMITLV_SET_HDR(&cmd->tlv_header,
  313. WMITLV_TAG_STRUC_wmi_extscan_get_cached_results_cmd_fixed_param,
  314. WMITLV_GET_STRUCT_TLVLEN
  315. (wmi_extscan_get_cached_results_cmd_fixed_param));
  316. cmd->request_id = pcached_results->request_id;
  317. cmd->vdev_id = pcached_results->vdev_id;
  318. cmd->control_flags = pcached_results->flush;
  319. if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
  320. WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID)) {
  321. WMI_LOGE("%s: failed to command", __func__);
  322. wmi_buf_free(wmi_buf);
  323. return QDF_STATUS_E_FAILURE;
  324. }
  325. return QDF_STATUS_SUCCESS;
  326. }
  327. /**
  328. * send_extscan_stop_change_monitor_cmd_tlv() - send stop change monitor cmd
  329. * @wmi_handle: wmi handle
  330. * @reset_req: Reset change request params
  331. *
  332. * This function sends stop change monitor request to fw.
  333. *
  334. * Return: CDF status
  335. */
  336. static QDF_STATUS send_extscan_stop_change_monitor_cmd_tlv
  337. (wmi_unified_t wmi_handle,
  338. struct extscan_capabilities_reset_params *reset_req)
  339. {
  340. wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
  341. wmi_buf_t wmi_buf;
  342. uint32_t len;
  343. uint8_t *buf_ptr;
  344. int change_list = 0;
  345. len = sizeof(*cmd);
  346. /* reset significant change tlv is set to 0 */
  347. len += WMI_TLV_HDR_SIZE;
  348. len += change_list * sizeof(wmi_extscan_wlan_change_bssid_param);
  349. wmi_buf = wmi_buf_alloc(wmi_handle, len);
  350. if (!wmi_buf) {
  351. WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
  352. return QDF_STATUS_E_NOMEM;
  353. }
  354. buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
  355. cmd = (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
  356. buf_ptr;
  357. WMITLV_SET_HDR(&cmd->tlv_header,
  358. WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
  359. WMITLV_GET_STRUCT_TLVLEN
  360. (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
  361. cmd->request_id = reset_req->request_id;
  362. cmd->vdev_id = reset_req->vdev_id;
  363. cmd->mode = 0;
  364. buf_ptr += sizeof(*cmd);
  365. WMITLV_SET_HDR(buf_ptr,
  366. WMITLV_TAG_ARRAY_STRUC,
  367. change_list *
  368. sizeof(wmi_extscan_wlan_change_bssid_param));
  369. buf_ptr += WMI_TLV_HDR_SIZE + (change_list *
  370. sizeof
  371. (wmi_extscan_wlan_change_bssid_param));
  372. if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
  373. WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
  374. WMI_LOGE("%s: failed to command", __func__);
  375. wmi_buf_free(wmi_buf);
  376. return QDF_STATUS_E_FAILURE;
  377. }
  378. return QDF_STATUS_SUCCESS;
  379. }
  380. /**
  381. * wmi_get_buf_extscan_change_monitor_cmd() - fill change monitor request
  382. * @wmi_handle: wmi handle
  383. * @psigchange: change monitor request params
  384. * @buf: wmi buffer
  385. * @buf_len: buffer length
  386. *
  387. * This function fills elements of change monitor request buffer.
  388. *
  389. * Return: QDF status
  390. */
  391. static QDF_STATUS wmi_get_buf_extscan_change_monitor_cmd
  392. (wmi_unified_t wmi_handle,
  393. struct extscan_set_sig_changereq_params
  394. *psigchange, wmi_buf_t *buf, int *buf_len)
  395. {
  396. wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *cmd;
  397. wmi_extscan_wlan_change_bssid_param *dest_chglist;
  398. uint8_t *buf_ptr;
  399. int j;
  400. int len = sizeof(*cmd);
  401. uint32_t numap = psigchange->num_ap;
  402. struct ap_threshold_params *src_ap = psigchange->ap;
  403. if (!numap || (numap > WMI_WLAN_EXTSCAN_MAX_SIGNIFICANT_CHANGE_APS)) {
  404. WMI_LOGE("%s: Invalid number of bssid's", __func__);
  405. return QDF_STATUS_E_INVAL;
  406. }
  407. len += WMI_TLV_HDR_SIZE;
  408. len += numap * sizeof(wmi_extscan_wlan_change_bssid_param);
  409. *buf = wmi_buf_alloc(wmi_handle, len);
  410. if (!*buf) {
  411. WMI_LOGP("%s: failed to allocate memory for change monitor cmd",
  412. __func__);
  413. return QDF_STATUS_E_FAILURE;
  414. }
  415. buf_ptr = (uint8_t *) wmi_buf_data(*buf);
  416. cmd =
  417. (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param *)
  418. buf_ptr;
  419. WMITLV_SET_HDR(&cmd->tlv_header,
  420. WMITLV_TAG_STRUC_wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param,
  421. WMITLV_GET_STRUCT_TLVLEN
  422. (wmi_extscan_configure_wlan_change_monitor_cmd_fixed_param));
  423. cmd->request_id = psigchange->request_id;
  424. cmd->vdev_id = psigchange->vdev_id;
  425. cmd->total_entries = numap;
  426. cmd->mode = 1;
  427. cmd->num_entries_in_page = numap;
  428. cmd->lost_ap_scan_count = psigchange->lostap_sample_size;
  429. cmd->max_rssi_samples = psigchange->rssi_sample_size;
  430. cmd->rssi_averaging_samples = psigchange->rssi_sample_size;
  431. cmd->max_out_of_range_count = psigchange->min_breaching;
  432. buf_ptr += sizeof(*cmd);
  433. WMITLV_SET_HDR(buf_ptr,
  434. WMITLV_TAG_ARRAY_STRUC,
  435. numap * sizeof(wmi_extscan_wlan_change_bssid_param));
  436. dest_chglist = (wmi_extscan_wlan_change_bssid_param *)
  437. (buf_ptr + WMI_TLV_HDR_SIZE);
  438. for (j = 0; j < numap; j++) {
  439. WMITLV_SET_HDR(dest_chglist,
  440. WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
  441. WMITLV_GET_STRUCT_TLVLEN
  442. (wmi_extscan_wlan_change_bssid_param));
  443. dest_chglist->lower_rssi_limit = src_ap->low;
  444. dest_chglist->upper_rssi_limit = src_ap->high;
  445. WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
  446. &dest_chglist->bssid);
  447. WMI_LOGD("%s: min_rssi %d", __func__,
  448. dest_chglist->lower_rssi_limit);
  449. dest_chglist++;
  450. src_ap++;
  451. }
  452. buf_ptr += WMI_TLV_HDR_SIZE +
  453. (numap * sizeof(wmi_extscan_wlan_change_bssid_param));
  454. *buf_len = len;
  455. return QDF_STATUS_SUCCESS;
  456. }
  457. /**
  458. * send_extscan_start_change_monitor_cmd_tlv() - send start change monitor cmd
  459. * @wmi_handle: wmi handle
  460. * @psigchange: change monitor request params
  461. *
  462. * This function sends start change monitor request to fw.
  463. *
  464. * Return: CDF status
  465. */
  466. static QDF_STATUS send_extscan_start_change_monitor_cmd_tlv
  467. (wmi_unified_t wmi_handle,
  468. struct extscan_set_sig_changereq_params *
  469. psigchange)
  470. {
  471. QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
  472. wmi_buf_t buf;
  473. int len;
  474. qdf_status = wmi_get_buf_extscan_change_monitor_cmd(wmi_handle,
  475. psigchange, &buf,
  476. &len);
  477. if (qdf_status != QDF_STATUS_SUCCESS) {
  478. WMI_LOGE("%s: Failed to get buffer for change monitor cmd",
  479. __func__);
  480. return QDF_STATUS_E_FAILURE;
  481. }
  482. if (!buf) {
  483. WMI_LOGE("%s: Failed to get buffer", __func__);
  484. return QDF_STATUS_E_FAILURE;
  485. }
  486. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  487. WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID)) {
  488. WMI_LOGE("%s: failed to send command", __func__);
  489. wmi_buf_free(buf);
  490. return QDF_STATUS_E_FAILURE;
  491. }
  492. return QDF_STATUS_SUCCESS;
  493. }
  494. /**
  495. * send_extscan_stop_hotlist_monitor_cmd_tlv() - stop hotlist monitor
  496. * @wmi_handle: wmi handle
  497. * @photlist_reset: hotlist reset params
  498. *
  499. * This function configures hotlist monitor to stop in fw.
  500. *
  501. * Return: CDF status
  502. */
  503. static QDF_STATUS send_extscan_stop_hotlist_monitor_cmd_tlv
  504. (wmi_unified_t wmi_handle,
  505. struct extscan_bssid_hotlist_reset_params *photlist_reset)
  506. {
  507. wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd;
  508. wmi_buf_t wmi_buf;
  509. uint32_t len;
  510. uint8_t *buf_ptr;
  511. int hotlist_entries = 0;
  512. len = sizeof(*cmd);
  513. /* reset bssid hotlist with tlv set to 0 */
  514. len += WMI_TLV_HDR_SIZE;
  515. len += hotlist_entries * sizeof(wmi_extscan_hotlist_entry);
  516. wmi_buf = wmi_buf_alloc(wmi_handle, len);
  517. if (!wmi_buf) {
  518. WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
  519. return QDF_STATUS_E_NOMEM;
  520. }
  521. buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
  522. cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
  523. buf_ptr;
  524. WMITLV_SET_HDR(&cmd->tlv_header,
  525. WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
  526. WMITLV_GET_STRUCT_TLVLEN
  527. (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
  528. cmd->request_id = photlist_reset->request_id;
  529. cmd->vdev_id = photlist_reset->vdev_id;
  530. cmd->mode = 0;
  531. buf_ptr += sizeof(*cmd);
  532. WMITLV_SET_HDR(buf_ptr,
  533. WMITLV_TAG_ARRAY_STRUC,
  534. hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
  535. buf_ptr += WMI_TLV_HDR_SIZE +
  536. (hotlist_entries * sizeof(wmi_extscan_hotlist_entry));
  537. if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
  538. WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
  539. WMI_LOGE("%s: failed to command", __func__);
  540. wmi_buf_free(wmi_buf);
  541. return QDF_STATUS_E_FAILURE;
  542. }
  543. return QDF_STATUS_SUCCESS;
  544. }
  545. /**
  546. * send_stop_extscan_cmd_tlv() - stop extscan command to fw.
  547. * @wmi_handle: wmi handle
  548. * @pstopcmd: stop scan command request params
  549. *
  550. * This function sends stop extscan request to fw.
  551. *
  552. * Return: CDF Status.
  553. */
  554. static QDF_STATUS send_stop_extscan_cmd_tlv(wmi_unified_t wmi_handle,
  555. struct extscan_stop_req_params *pstopcmd)
  556. {
  557. wmi_extscan_stop_cmd_fixed_param *cmd;
  558. wmi_buf_t wmi_buf;
  559. uint32_t len;
  560. uint8_t *buf_ptr;
  561. len = sizeof(*cmd);
  562. wmi_buf = wmi_buf_alloc(wmi_handle, len);
  563. if (!wmi_buf) {
  564. WMI_LOGE("%s: wmi_buf_alloc failed", __func__);
  565. return QDF_STATUS_E_NOMEM;
  566. }
  567. buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
  568. cmd = (wmi_extscan_stop_cmd_fixed_param *) buf_ptr;
  569. WMITLV_SET_HDR(&cmd->tlv_header,
  570. WMITLV_TAG_STRUC_wmi_extscan_stop_cmd_fixed_param,
  571. WMITLV_GET_STRUCT_TLVLEN
  572. (wmi_extscan_stop_cmd_fixed_param));
  573. cmd->request_id = pstopcmd->request_id;
  574. cmd->vdev_id = pstopcmd->vdev_id;
  575. if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len,
  576. WMI_EXTSCAN_STOP_CMDID)) {
  577. WMI_LOGE("%s: failed to command", __func__);
  578. wmi_buf_free(wmi_buf);
  579. return QDF_STATUS_E_FAILURE;
  580. }
  581. return QDF_STATUS_SUCCESS;
  582. }
  583. /**
  584. * wmi_get_buf_extscan_start_cmd() - Fill extscan start request
  585. * @wmi_handle: wmi handle
  586. * @pstart: scan command request params
  587. * @buf: event buffer
  588. * @buf_len: length of buffer
  589. *
  590. * This function fills individual elements of extscan request and
  591. * TLV for buckets, channel list.
  592. *
  593. * Return: CDF Status.
  594. */
  595. static
  596. QDF_STATUS wmi_get_buf_extscan_start_cmd(wmi_unified_t wmi_handle,
  597. struct wifi_scan_cmd_req_params *pstart,
  598. wmi_buf_t *buf, int *buf_len)
  599. {
  600. wmi_extscan_start_cmd_fixed_param *cmd;
  601. wmi_extscan_bucket *dest_blist;
  602. wmi_extscan_bucket_channel *dest_clist;
  603. struct wifi_scan_bucket_params *src_bucket = pstart->buckets;
  604. struct wifi_scan_channelspec_params *src_channel = src_bucket->channels;
  605. struct wifi_scan_channelspec_params save_channel[WMI_WLAN_EXTSCAN_MAX_CHANNELS];
  606. uint8_t *buf_ptr;
  607. int i, k, count = 0;
  608. int len = sizeof(*cmd);
  609. int nbuckets = pstart->num_buckets;
  610. int nchannels = 0;
  611. /* These TLV's are are NULL by default */
  612. uint32_t ie_len_with_pad = 0;
  613. int num_ssid = 0;
  614. int num_bssid = 0;
  615. int ie_len = 0;
  616. uint32_t base_period = pstart->base_period;
  617. /* TLV placeholder for ssid_list (NULL) */
  618. len += WMI_TLV_HDR_SIZE;
  619. len += num_ssid * sizeof(wmi_ssid);
  620. /* TLV placeholder for bssid_list (NULL) */
  621. len += WMI_TLV_HDR_SIZE;
  622. len += num_bssid * sizeof(wmi_mac_addr);
  623. /* TLV placeholder for ie_data (NULL) */
  624. len += WMI_TLV_HDR_SIZE;
  625. len += ie_len * sizeof(uint32_t);
  626. /* TLV placeholder for bucket */
  627. len += WMI_TLV_HDR_SIZE;
  628. len += nbuckets * sizeof(wmi_extscan_bucket);
  629. /* TLV channel placeholder */
  630. len += WMI_TLV_HDR_SIZE;
  631. for (i = 0; i < nbuckets; i++) {
  632. nchannels += src_bucket->num_channels;
  633. src_bucket++;
  634. }
  635. WMI_LOGD("%s: Total buckets: %d total #of channels is %d",
  636. __func__, nbuckets, nchannels);
  637. len += nchannels * sizeof(wmi_extscan_bucket_channel);
  638. /* Allocate the memory */
  639. *buf = wmi_buf_alloc(wmi_handle, len);
  640. if (!*buf) {
  641. WMI_LOGP("%s: failed to allocate memory for start extscan cmd",
  642. __func__);
  643. return QDF_STATUS_E_NOMEM;
  644. }
  645. buf_ptr = (uint8_t *) wmi_buf_data(*buf);
  646. cmd = (wmi_extscan_start_cmd_fixed_param *) buf_ptr;
  647. WMITLV_SET_HDR(&cmd->tlv_header,
  648. WMITLV_TAG_STRUC_wmi_extscan_start_cmd_fixed_param,
  649. WMITLV_GET_STRUCT_TLVLEN
  650. (wmi_extscan_start_cmd_fixed_param));
  651. cmd->request_id = pstart->request_id;
  652. cmd->vdev_id = pstart->vdev_id;
  653. cmd->base_period = pstart->base_period;
  654. cmd->num_buckets = nbuckets;
  655. cmd->configuration_flags = 0;
  656. if (pstart->configuration_flags & WMI_EXTSCAN_LP_EXTENDED_BATCHING)
  657. cmd->configuration_flags |= WMI_EXTSCAN_EXTENDED_BATCHING_EN;
  658. WMI_LOGI("%s: configuration_flags: 0x%x", __func__,
  659. cmd->configuration_flags);
  660. #ifdef FEATURE_WLAN_EXTSCAN
  661. cmd->min_rest_time = WMI_EXTSCAN_REST_TIME;
  662. cmd->max_rest_time = WMI_EXTSCAN_REST_TIME;
  663. cmd->max_scan_time = WMI_EXTSCAN_MAX_SCAN_TIME;
  664. cmd->burst_duration = WMI_EXTSCAN_BURST_DURATION;
  665. #endif
  666. /* The max dwell time is retrieved from the first channel
  667. * of the first bucket and kept common for all channels.
  668. */
  669. cmd->min_dwell_time_active = pstart->min_dwell_time_active;
  670. cmd->max_dwell_time_active = pstart->max_dwell_time_active;
  671. cmd->min_dwell_time_passive = pstart->min_dwell_time_passive;
  672. cmd->max_dwell_time_passive = pstart->max_dwell_time_passive;
  673. cmd->max_bssids_per_scan_cycle = pstart->max_ap_per_scan;
  674. cmd->max_table_usage = pstart->report_threshold_percent;
  675. cmd->report_threshold_num_scans = pstart->report_threshold_num_scans;
  676. cmd->repeat_probe_time = cmd->max_dwell_time_active /
  677. WMI_SCAN_NPROBES_DEFAULT;
  678. cmd->probe_delay = 0;
  679. cmd->probe_spacing_time = 0;
  680. cmd->idle_time = 0;
  681. cmd->scan_ctrl_flags = WMI_SCAN_ADD_BCAST_PROBE_REQ |
  682. WMI_SCAN_ADD_CCK_RATES |
  683. WMI_SCAN_ADD_OFDM_RATES |
  684. WMI_SCAN_ADD_SPOOFED_MAC_IN_PROBE_REQ |
  685. WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ;
  686. WMI_SCAN_SET_DWELL_MODE(cmd->scan_ctrl_flags,
  687. pstart->extscan_adaptive_dwell_mode);
  688. cmd->scan_priority = WMI_SCAN_PRIORITY_VERY_LOW;
  689. cmd->num_ssids = 0;
  690. cmd->num_bssid = 0;
  691. cmd->ie_len = 0;
  692. cmd->n_probes = (cmd->repeat_probe_time > 0) ?
  693. cmd->max_dwell_time_active / cmd->repeat_probe_time : 0;
  694. buf_ptr += sizeof(*cmd);
  695. WMITLV_SET_HDR(buf_ptr,
  696. WMITLV_TAG_ARRAY_FIXED_STRUC,
  697. num_ssid * sizeof(wmi_ssid));
  698. buf_ptr += WMI_TLV_HDR_SIZE + (num_ssid * sizeof(wmi_ssid));
  699. WMITLV_SET_HDR(buf_ptr,
  700. WMITLV_TAG_ARRAY_FIXED_STRUC,
  701. num_bssid * sizeof(wmi_mac_addr));
  702. buf_ptr += WMI_TLV_HDR_SIZE + (num_bssid * sizeof(wmi_mac_addr));
  703. ie_len_with_pad = 0;
  704. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
  705. ie_len_with_pad);
  706. buf_ptr += WMI_TLV_HDR_SIZE + ie_len_with_pad;
  707. WMITLV_SET_HDR(buf_ptr,
  708. WMITLV_TAG_ARRAY_STRUC,
  709. nbuckets * sizeof(wmi_extscan_bucket));
  710. dest_blist = (wmi_extscan_bucket *)
  711. (buf_ptr + WMI_TLV_HDR_SIZE);
  712. src_bucket = pstart->buckets;
  713. /* Retrieve scanning information from each bucket and
  714. * channels and send it to the target
  715. */
  716. for (i = 0; i < nbuckets; i++) {
  717. WMITLV_SET_HDR(dest_blist,
  718. WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
  719. WMITLV_GET_STRUCT_TLVLEN(wmi_extscan_bucket));
  720. dest_blist->bucket_id = src_bucket->bucket;
  721. dest_blist->base_period_multiplier =
  722. src_bucket->period / base_period;
  723. dest_blist->min_period = src_bucket->period;
  724. dest_blist->max_period = src_bucket->max_period;
  725. dest_blist->exp_backoff = src_bucket->exponent;
  726. dest_blist->exp_max_step_count = src_bucket->step_count;
  727. dest_blist->channel_band = src_bucket->band;
  728. dest_blist->num_channels = src_bucket->num_channels;
  729. dest_blist->notify_extscan_events = 0;
  730. if (src_bucket->report_events &
  731. WMI_EXTSCAN_REPORT_EVENTS_EACH_SCAN)
  732. dest_blist->notify_extscan_events =
  733. WMI_EXTSCAN_CYCLE_COMPLETED_EVENT |
  734. WMI_EXTSCAN_CYCLE_STARTED_EVENT;
  735. if (src_bucket->report_events &
  736. WMI_EXTSCAN_REPORT_EVENTS_FULL_RESULTS) {
  737. dest_blist->forwarding_flags =
  738. WMI_EXTSCAN_FORWARD_FRAME_TO_HOST;
  739. dest_blist->notify_extscan_events |=
  740. WMI_EXTSCAN_BUCKET_COMPLETED_EVENT |
  741. WMI_EXTSCAN_CYCLE_STARTED_EVENT |
  742. WMI_EXTSCAN_CYCLE_COMPLETED_EVENT;
  743. } else {
  744. dest_blist->forwarding_flags =
  745. WMI_EXTSCAN_NO_FORWARDING;
  746. }
  747. if (src_bucket->report_events &
  748. WMI_EXTSCAN_REPORT_EVENTS_NO_BATCH)
  749. dest_blist->configuration_flags = 0;
  750. else
  751. dest_blist->configuration_flags =
  752. WMI_EXTSCAN_BUCKET_CACHE_RESULTS;
  753. WMI_LOGI("%s: ntfy_extscan_events:%u cfg_flags:%u fwd_flags:%u",
  754. __func__, dest_blist->notify_extscan_events,
  755. dest_blist->configuration_flags,
  756. dest_blist->forwarding_flags);
  757. dest_blist->min_dwell_time_active =
  758. src_bucket->min_dwell_time_active;
  759. dest_blist->max_dwell_time_active =
  760. src_bucket->max_dwell_time_active;
  761. dest_blist->min_dwell_time_passive =
  762. src_bucket->min_dwell_time_passive;
  763. dest_blist->max_dwell_time_passive =
  764. src_bucket->max_dwell_time_passive;
  765. src_channel = src_bucket->channels;
  766. /* save the channel info to later populate
  767. * the channel TLV
  768. */
  769. for (k = 0; k < src_bucket->num_channels; k++) {
  770. save_channel[count++].channel = src_channel->channel;
  771. src_channel++;
  772. }
  773. dest_blist++;
  774. src_bucket++;
  775. }
  776. buf_ptr += WMI_TLV_HDR_SIZE + (nbuckets * sizeof(wmi_extscan_bucket));
  777. WMITLV_SET_HDR(buf_ptr,
  778. WMITLV_TAG_ARRAY_STRUC,
  779. nchannels * sizeof(wmi_extscan_bucket_channel));
  780. dest_clist = (wmi_extscan_bucket_channel *)
  781. (buf_ptr + WMI_TLV_HDR_SIZE);
  782. /* Active or passive scan is based on the bucket dwell time
  783. * and channel specific active,passive scans are not
  784. * supported yet
  785. */
  786. for (i = 0; i < nchannels; i++) {
  787. WMITLV_SET_HDR(dest_clist,
  788. WMITLV_TAG_STRUC_wmi_extscan_bucket_channel_event_fixed_param,
  789. WMITLV_GET_STRUCT_TLVLEN
  790. (wmi_extscan_bucket_channel));
  791. dest_clist->channel = save_channel[i].channel;
  792. dest_clist++;
  793. }
  794. buf_ptr += WMI_TLV_HDR_SIZE +
  795. (nchannels * sizeof(wmi_extscan_bucket_channel));
  796. *buf_len = len;
  797. return QDF_STATUS_SUCCESS;
  798. }
  799. /**
  800. * send_start_extscan_cmd_tlv() - start extscan command to fw.
  801. * @wmi_handle: wmi handle
  802. * @pstart: scan command request params
  803. *
  804. * This function sends start extscan request to fw.
  805. *
  806. * Return: CDF Status.
  807. */
  808. static QDF_STATUS send_start_extscan_cmd_tlv(wmi_unified_t wmi_handle,
  809. struct wifi_scan_cmd_req_params *pstart)
  810. {
  811. QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
  812. wmi_buf_t buf;
  813. int len;
  814. /* Fill individual elements of extscan request and
  815. * TLV for buckets, channel list.
  816. */
  817. qdf_status = wmi_get_buf_extscan_start_cmd(wmi_handle,
  818. pstart, &buf, &len);
  819. if (qdf_status != QDF_STATUS_SUCCESS) {
  820. WMI_LOGE("%s: Failed to get buffer for ext scan cmd", __func__);
  821. return QDF_STATUS_E_FAILURE;
  822. }
  823. if (!buf) {
  824. WMI_LOGE("%s:Failed to get buffer for current extscan info",
  825. __func__);
  826. return QDF_STATUS_E_FAILURE;
  827. }
  828. if (wmi_unified_cmd_send(wmi_handle, buf,
  829. len, WMI_EXTSCAN_START_CMDID)) {
  830. WMI_LOGE("%s: failed to send command", __func__);
  831. wmi_buf_free(buf);
  832. return QDF_STATUS_E_FAILURE;
  833. }
  834. return QDF_STATUS_SUCCESS;
  835. }
  836. /** wmi_get_hotlist_entries_per_page() - hotlist entries per page
  837. * @wmi_handle: wmi handle.
  838. * @cmd: size of command structure.
  839. * @per_entry_size: per entry size.
  840. *
  841. * This utility function calculates how many hotlist entries can
  842. * fit in one page.
  843. *
  844. * Return: number of entries
  845. */
  846. static inline int wmi_get_hotlist_entries_per_page
  847. (wmi_unified_t wmi_handle,
  848. size_t cmd_size,
  849. size_t per_entry_size)
  850. {
  851. uint32_t avail_space = 0;
  852. int num_entries = 0;
  853. uint16_t max_msg_len = wmi_get_max_msg_len(wmi_handle);
  854. /* Calculate number of hotlist entries that can
  855. * be passed in wma message request.
  856. */
  857. avail_space = max_msg_len - cmd_size;
  858. num_entries = avail_space / per_entry_size;
  859. return num_entries;
  860. }
  861. /**
  862. * send_extscan_start_hotlist_monitor_cmd_tlv() - start hotlist monitor
  863. * @wmi_handle: wmi handle
  864. * @params: hotlist params
  865. *
  866. * This function configures hotlist monitor to start in fw.
  867. *
  868. * Return: QDF status
  869. */
  870. static QDF_STATUS send_extscan_start_hotlist_monitor_cmd_tlv
  871. (wmi_unified_t wmi_handle,
  872. struct extscan_bssid_hotlist_set_params *params)
  873. {
  874. wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *cmd = NULL;
  875. wmi_extscan_hotlist_entry *dest_hotlist;
  876. struct ap_threshold_params *src_ap = params->ap;
  877. wmi_buf_t buf;
  878. uint8_t *buf_ptr;
  879. int j, index = 0;
  880. int cmd_len = 0;
  881. int num_entries;
  882. int min_entries = 0;
  883. uint32_t numap = params->num_ap;
  884. int len = sizeof(*cmd);
  885. len += WMI_TLV_HDR_SIZE;
  886. cmd_len = len;
  887. num_entries = wmi_get_hotlist_entries_per_page(wmi_handle,
  888. cmd_len,
  889. sizeof(*dest_hotlist));
  890. /* setbssid hotlist expects the bssid list
  891. * to be non zero value
  892. */
  893. if (!numap || (numap > WMI_WLAN_EXTSCAN_MAX_HOTLIST_APS)) {
  894. WMI_LOGE("Invalid number of APs: %d", numap);
  895. return QDF_STATUS_E_INVAL;
  896. }
  897. /* Split the hot list entry pages and send multiple command
  898. * requests if the buffer reaches the maximum request size
  899. */
  900. while (index < numap) {
  901. min_entries = QDF_MIN(num_entries, numap);
  902. len += min_entries * sizeof(wmi_extscan_hotlist_entry);
  903. buf = wmi_buf_alloc(wmi_handle, len);
  904. if (!buf) {
  905. WMI_LOGP("%s: wmi_buf_alloc failed", __func__);
  906. return QDF_STATUS_E_FAILURE;
  907. }
  908. buf_ptr = (uint8_t *) wmi_buf_data(buf);
  909. cmd = (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param *)
  910. buf_ptr;
  911. WMITLV_SET_HDR(&cmd->tlv_header,
  912. WMITLV_TAG_STRUC_wmi_extscan_configure_hotlist_monitor_cmd_fixed_param,
  913. WMITLV_GET_STRUCT_TLVLEN
  914. (wmi_extscan_configure_hotlist_monitor_cmd_fixed_param));
  915. /* Multiple requests are sent until the num_entries_in_page
  916. * matches the total_entries
  917. */
  918. cmd->request_id = params->request_id;
  919. cmd->vdev_id = params->vdev_id;
  920. cmd->total_entries = numap;
  921. cmd->mode = 1;
  922. cmd->num_entries_in_page = min_entries;
  923. cmd->lost_ap_scan_count = params->lost_ap_sample_size;
  924. cmd->first_entry_index = index;
  925. WMI_LOGD("%s: vdev id:%d total_entries: %d num_entries: %d lost_ap_sample_size: %d",
  926. __func__, cmd->vdev_id, cmd->total_entries,
  927. cmd->num_entries_in_page,
  928. cmd->lost_ap_scan_count);
  929. buf_ptr += sizeof(*cmd);
  930. WMITLV_SET_HDR(buf_ptr,
  931. WMITLV_TAG_ARRAY_STRUC,
  932. min_entries * sizeof(wmi_extscan_hotlist_entry));
  933. dest_hotlist = (wmi_extscan_hotlist_entry *)
  934. (buf_ptr + WMI_TLV_HDR_SIZE);
  935. /* Populate bssid, channel info and rssi
  936. * for the bssid's that are sent as hotlists.
  937. */
  938. for (j = 0; j < min_entries; j++) {
  939. WMITLV_SET_HDR(dest_hotlist,
  940. WMITLV_TAG_STRUC_wmi_extscan_bucket_cmd_fixed_param,
  941. WMITLV_GET_STRUCT_TLVLEN
  942. (wmi_extscan_hotlist_entry));
  943. dest_hotlist->min_rssi = src_ap->low;
  944. WMI_CHAR_ARRAY_TO_MAC_ADDR(src_ap->bssid.bytes,
  945. &dest_hotlist->bssid);
  946. WMI_LOGD("%s:channel:%d min_rssi %d",
  947. __func__, dest_hotlist->channel,
  948. dest_hotlist->min_rssi);
  949. WMI_LOGD
  950. ("%s: bssid mac_addr31to0: 0x%x, mac_addr47to32: 0x%x",
  951. __func__, dest_hotlist->bssid.mac_addr31to0,
  952. dest_hotlist->bssid.mac_addr47to32);
  953. dest_hotlist++;
  954. src_ap++;
  955. }
  956. buf_ptr += WMI_TLV_HDR_SIZE +
  957. (min_entries * sizeof(wmi_extscan_hotlist_entry));
  958. if (wmi_unified_cmd_send(wmi_handle, buf, len,
  959. WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID)) {
  960. WMI_LOGE("%s: failed to send command", __func__);
  961. wmi_buf_free(buf);
  962. return QDF_STATUS_E_FAILURE;
  963. }
  964. index = index + min_entries;
  965. num_entries = numap - min_entries;
  966. len = cmd_len;
  967. }
  968. return QDF_STATUS_SUCCESS;
  969. }
  970. void wmi_extscan_attach_tlv(wmi_unified_t wmi_handle)
  971. {
  972. struct wmi_ops *ops = wmi_handle->ops;
  973. ops->send_reset_passpoint_network_list_cmd =
  974. send_reset_passpoint_network_list_cmd_tlv;
  975. ops->send_set_passpoint_network_list_cmd =
  976. send_set_passpoint_network_list_cmd_tlv;
  977. ops->send_set_epno_network_list_cmd =
  978. send_set_epno_network_list_cmd_tlv;
  979. ops->send_extscan_get_capabilities_cmd =
  980. send_extscan_get_capabilities_cmd_tlv;
  981. ops->send_extscan_get_cached_results_cmd =
  982. send_extscan_get_cached_results_cmd_tlv;
  983. ops->send_extscan_stop_change_monitor_cmd =
  984. send_extscan_stop_change_monitor_cmd_tlv;
  985. ops->send_extscan_start_change_monitor_cmd =
  986. send_extscan_start_change_monitor_cmd_tlv;
  987. ops->send_extscan_stop_hotlist_monitor_cmd =
  988. send_extscan_stop_hotlist_monitor_cmd_tlv;
  989. ops->send_extscan_start_hotlist_monitor_cmd =
  990. send_extscan_start_hotlist_monitor_cmd_tlv;
  991. ops->send_stop_extscan_cmd = send_stop_extscan_cmd_tlv;
  992. ops->send_start_extscan_cmd = send_start_extscan_cmd_tlv;
  993. }