wmi_unified_extscan_tlv.c 33 KB

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