wmi_unified_nan_tlv.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209
  1. /*
  2. * Copyright (c) 2013-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. #include <nan_public_structs.h>
  22. #include <wmi_unified_nan_api.h>
  23. #include <wlan_nan_msg_common_v2.h>
  24. static QDF_STATUS
  25. extract_nan_event_rsp_tlv(wmi_unified_t wmi_handle, void *evt_buf,
  26. struct nan_event_params *evt_params,
  27. uint8_t **msg_buf)
  28. {
  29. WMI_NAN_EVENTID_param_tlvs *event;
  30. wmi_nan_event_hdr *nan_rsp_event_hdr;
  31. nan_msg_header_t *nan_msg_hdr;
  32. wmi_nan_event_info *nan_evt_info;
  33. /*
  34. * This is how received evt looks like
  35. *
  36. * <-------------------- evt_buf ----------------------------------->
  37. *
  38. * <--wmi_nan_event_hdr--><---WMI_TLV_HDR_SIZE---><----- data -------->
  39. *
  40. * +-----------+---------+-----------------------+--------------------+-
  41. * | tlv_header| data_len| WMITLV_TAG_ARRAY_BYTE | nan_rsp_event_data |
  42. * +-----------+---------+-----------------------+--------------------+-
  43. *
  44. * (Only for NAN Enable Resp)
  45. * <--wmi_nan_event_info-->
  46. * +-----------+-----------+
  47. * | tlv_header| event_info|
  48. * +-----------+-----------+
  49. *
  50. */
  51. event = (WMI_NAN_EVENTID_param_tlvs *)evt_buf;
  52. nan_rsp_event_hdr = event->fixed_param;
  53. /* Actual data may include some padding, so data_len <= num_data */
  54. if (nan_rsp_event_hdr->data_len > event->num_data) {
  55. wmi_err("Provided NAN event length(%d) exceeding actual length(%d)!",
  56. nan_rsp_event_hdr->data_len,
  57. event->num_data);
  58. return QDF_STATUS_E_INVAL;
  59. }
  60. evt_params->buf_len = nan_rsp_event_hdr->data_len;
  61. *msg_buf = event->data;
  62. if (nan_rsp_event_hdr->data_len < sizeof(nan_msg_header_t) ||
  63. nan_rsp_event_hdr->data_len > (WMI_SVC_MSG_MAX_SIZE -
  64. WMI_TLV_HDR_SIZE)) {
  65. wmi_err("Invalid NAN event data length(%d)!",
  66. nan_rsp_event_hdr->data_len);
  67. return QDF_STATUS_E_INVAL;
  68. }
  69. nan_msg_hdr = (nan_msg_header_t *)event->data;
  70. if (!wmi_service_enabled(wmi_handle, wmi_service_nan_dbs_support) &&
  71. !wmi_service_enabled(wmi_handle, wmi_service_nan_disable_support)) {
  72. evt_params->evt_type = nan_event_id_generic_rsp;
  73. return QDF_STATUS_SUCCESS;
  74. }
  75. switch (nan_msg_hdr->msg_id) {
  76. case NAN_MSG_ID_ENABLE_RSP:
  77. nan_evt_info = event->event_info;
  78. if (!nan_evt_info) {
  79. wmi_err("Fail: NAN enable rsp event info Null");
  80. return QDF_STATUS_E_INVAL;
  81. }
  82. evt_params->evt_type = nan_event_id_enable_rsp;
  83. evt_params->mac_id = nan_evt_info->mac_id;
  84. evt_params->is_nan_enable_success = (nan_evt_info->status == 0);
  85. evt_params->vdev_id = nan_evt_info->vdev_id;
  86. break;
  87. case NAN_MSG_ID_DISABLE_IND:
  88. evt_params->evt_type = nan_event_id_disable_ind;
  89. break;
  90. case NAN_MSG_ID_ERROR_RSP:
  91. evt_params->evt_type = nan_event_id_error_rsp;
  92. break;
  93. default:
  94. evt_params->evt_type = nan_event_id_generic_rsp;
  95. break;
  96. }
  97. return QDF_STATUS_SUCCESS;
  98. }
  99. /**
  100. * send_nan_disable_req_cmd_tlv() - to send nan disable request to target
  101. * @wmi_handle: wmi handle
  102. * @nan_msg: request data which will be non-null
  103. *
  104. * Return: CDF status
  105. */
  106. static QDF_STATUS send_nan_disable_req_cmd_tlv(wmi_unified_t wmi_handle,
  107. struct nan_disable_req *nan_msg)
  108. {
  109. QDF_STATUS ret;
  110. wmi_nan_cmd_param *cmd;
  111. wmi_nan_host_config_param *cfg;
  112. wmi_buf_t buf;
  113. /* Initialize with minimum length required, which is Scenario 2*/
  114. uint16_t len = sizeof(*cmd) + sizeof(*cfg) + 2 * WMI_TLV_HDR_SIZE;
  115. uint16_t nan_data_len, nan_data_len_aligned = 0;
  116. uint8_t *buf_ptr;
  117. /*
  118. * Scenario 1: NAN Disable with NAN msg data from upper layers
  119. *
  120. * <-----nan cmd param-----><-- WMI_TLV_HDR_SIZE --><--- data ---->
  121. * +------------+----------+-----------------------+--------------+
  122. * | tlv_header | data_len | WMITLV_TAG_ARRAY_BYTE | nan_msg_data |
  123. * +------------+----------+-----------------------+--------------+
  124. *
  125. * <-- WMI_TLV_HDR_SIZE --><------nan host config params----->
  126. * -+-----------------------+---------------------------------+
  127. * | WMITLV_TAG_ARRAY_STRUC| tlv_header | 2g/5g disable flags|
  128. * -+-----------------------+---------------------------------+
  129. *
  130. * Scenario 2: NAN Disable without any NAN msg data from upper layers
  131. *
  132. * <------nan cmd param------><--WMI_TLV_HDR_SIZE--><--WMI_TLV_HDR_SI
  133. * +------------+------------+----------------------+----------------
  134. * | tlv_header | data_len=0 | WMITLV_TAG_ARRAY_BYTE| WMITLV_TAG_ARRA
  135. * +------------+------------+----------------------+----------------
  136. *
  137. * ZE----><------nan host config params----->
  138. * -------+---------------------------------+
  139. * Y_STRUC| tlv_header | 2g/5g disable flags|
  140. * -------+---------------------------------+
  141. */
  142. if (!nan_msg) {
  143. wmi_err("nan req is not valid");
  144. return QDF_STATUS_E_FAILURE;
  145. }
  146. nan_data_len = nan_msg->params.request_data_len;
  147. if (nan_data_len) {
  148. nan_data_len_aligned = roundup(nan_data_len, sizeof(uint32_t));
  149. if (nan_data_len_aligned < nan_data_len) {
  150. wmi_err("Int overflow while rounding up data_len");
  151. return QDF_STATUS_E_FAILURE;
  152. }
  153. if (nan_data_len_aligned > WMI_SVC_MSG_MAX_SIZE
  154. - WMI_TLV_HDR_SIZE) {
  155. wmi_err("nan_data_len exceeding wmi_max_msg_size");
  156. return QDF_STATUS_E_FAILURE;
  157. }
  158. len += nan_data_len_aligned;
  159. }
  160. buf = wmi_buf_alloc(wmi_handle, len);
  161. if (!buf)
  162. return QDF_STATUS_E_NOMEM;
  163. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  164. cmd = (wmi_nan_cmd_param *)buf_ptr;
  165. WMITLV_SET_HDR(&cmd->tlv_header,
  166. WMITLV_TAG_STRUC_wmi_nan_cmd_param,
  167. WMITLV_GET_STRUCT_TLVLEN(wmi_nan_cmd_param));
  168. cmd->data_len = nan_data_len;
  169. WMI_LOGD("%s: nan data len value is %u", __func__, nan_data_len);
  170. buf_ptr += sizeof(wmi_nan_cmd_param);
  171. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, nan_data_len_aligned);
  172. buf_ptr += WMI_TLV_HDR_SIZE;
  173. if (nan_data_len) {
  174. qdf_mem_copy(buf_ptr, nan_msg->params.request_data,
  175. cmd->data_len);
  176. buf_ptr += nan_data_len_aligned;
  177. }
  178. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  179. sizeof(wmi_nan_host_config_param));
  180. buf_ptr += WMI_TLV_HDR_SIZE;
  181. cfg = (wmi_nan_host_config_param *)buf_ptr;
  182. WMITLV_SET_HDR(&cfg->tlv_header,
  183. WMITLV_TAG_STRUC_wmi_nan_host_config_param,
  184. WMITLV_GET_STRUCT_TLVLEN(wmi_nan_host_config_param));
  185. cfg->nan_2g_disc_disable = nan_msg->disable_2g_discovery;
  186. cfg->nan_5g_disc_disable = nan_msg->disable_5g_discovery;
  187. wmi_mtrace(WMI_NAN_CMDID, NO_SESSION, 0);
  188. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  189. WMI_NAN_CMDID);
  190. if (QDF_IS_STATUS_ERROR(ret)) {
  191. wmi_err("Failed to send set param command ret = %d", ret);
  192. wmi_buf_free(buf);
  193. }
  194. return ret;
  195. }
  196. /**
  197. * send_nan_req_cmd_tlv() - to send nan request to target
  198. * @wmi_handle: wmi handle
  199. * @nan_msg: request data which will be non-null
  200. *
  201. * Return: CDF status
  202. */
  203. static QDF_STATUS send_nan_req_cmd_tlv(wmi_unified_t wmi_handle,
  204. struct nan_msg_params *nan_msg)
  205. {
  206. QDF_STATUS ret;
  207. wmi_nan_cmd_param *cmd;
  208. wmi_buf_t buf;
  209. wmi_nan_host_config_param *cfg;
  210. uint16_t len = sizeof(*cmd) + sizeof(*cfg) + 2 * WMI_TLV_HDR_SIZE;
  211. uint16_t nan_data_len, nan_data_len_aligned;
  212. uint8_t *buf_ptr;
  213. /*
  214. * <----- cmd ------------><-- WMI_TLV_HDR_SIZE --><--- data ---->
  215. * +------------+----------+-----------------------+--------------+
  216. * | tlv_header | data_len | WMITLV_TAG_ARRAY_BYTE | nan_msg_data |
  217. * +------------+----------+-----------------------+--------------+
  218. *
  219. * <-- WMI_TLV_HDR_SIZE --><------nan host config params-------->
  220. * +-----------------------+------------------------------------+
  221. * | WMITLV_TAG_ARRAY_STRUC| tlv_header | disable flags | flags |
  222. * +-----------------------+------------------------------------+
  223. */
  224. if (!nan_msg) {
  225. wmi_err("nan req is not valid");
  226. return QDF_STATUS_E_FAILURE;
  227. }
  228. nan_data_len = nan_msg->request_data_len;
  229. nan_data_len_aligned = roundup(nan_msg->request_data_len,
  230. sizeof(uint32_t));
  231. if (nan_data_len_aligned < nan_msg->request_data_len) {
  232. wmi_err("integer overflow while rounding up data_len");
  233. return QDF_STATUS_E_FAILURE;
  234. }
  235. if (nan_data_len_aligned > WMI_SVC_MSG_MAX_SIZE - WMI_TLV_HDR_SIZE) {
  236. wmi_err("wmi_max_msg_size overflow for given datalen");
  237. return QDF_STATUS_E_FAILURE;
  238. }
  239. len += nan_data_len_aligned;
  240. buf = wmi_buf_alloc(wmi_handle, len);
  241. if (!buf)
  242. return QDF_STATUS_E_NOMEM;
  243. buf_ptr = (uint8_t *)wmi_buf_data(buf);
  244. cmd = (wmi_nan_cmd_param *)buf_ptr;
  245. WMITLV_SET_HDR(&cmd->tlv_header,
  246. WMITLV_TAG_STRUC_wmi_nan_cmd_param,
  247. WMITLV_GET_STRUCT_TLVLEN(wmi_nan_cmd_param));
  248. cmd->data_len = nan_msg->request_data_len;
  249. buf_ptr += sizeof(wmi_nan_cmd_param);
  250. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, nan_data_len_aligned);
  251. buf_ptr += WMI_TLV_HDR_SIZE;
  252. qdf_mem_copy(buf_ptr, nan_msg->request_data, cmd->data_len);
  253. buf_ptr += nan_data_len_aligned;
  254. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  255. sizeof(wmi_nan_host_config_param));
  256. buf_ptr += WMI_TLV_HDR_SIZE;
  257. cfg = (wmi_nan_host_config_param *)buf_ptr;
  258. WMITLV_SET_HDR(&cfg->tlv_header,
  259. WMITLV_TAG_STRUC_wmi_nan_host_config_param,
  260. WMITLV_GET_STRUCT_TLVLEN(wmi_nan_host_config_param));
  261. WMI_NAN_SET_RANGING_INITIATOR_ROLE(cfg->flags, !!(nan_msg->rtt_cap &
  262. WMI_FW_NAN_RTT_INITR));
  263. WMI_NAN_SET_RANGING_RESPONDER_ROLE(cfg->flags, !!(nan_msg->rtt_cap &
  264. WMI_FW_NAN_RTT_RESPR));
  265. wmi_mtrace(WMI_NAN_CMDID, NO_SESSION, 0);
  266. ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_NAN_CMDID);
  267. if (QDF_IS_STATUS_ERROR(ret)) {
  268. wmi_err("Failed to send NAN req command ret = %d", ret);
  269. wmi_buf_free(buf);
  270. }
  271. return ret;
  272. }
  273. /**
  274. * send_terminate_all_ndps_cmd_tlv() - send NDP Terminate for all NDP's
  275. * associated with the given vdev id
  276. * @wmi_handle: wmi handle
  277. * @vdev_id: vdev id
  278. *
  279. * Return: QDF status
  280. */
  281. static QDF_STATUS send_terminate_all_ndps_cmd_tlv(wmi_unified_t wmi_handle,
  282. uint32_t vdev_id)
  283. {
  284. wmi_ndp_cmd_param *cmd;
  285. wmi_buf_t wmi_buf;
  286. uint32_t len;
  287. QDF_STATUS status;
  288. WMI_LOGD(FL("Enter"));
  289. len = sizeof(*cmd);
  290. wmi_buf = wmi_buf_alloc(wmi_handle, len);
  291. if (!wmi_buf)
  292. return QDF_STATUS_E_NOMEM;
  293. cmd = (wmi_ndp_cmd_param *)wmi_buf_data(wmi_buf);
  294. WMITLV_SET_HDR(&cmd->tlv_header, WMITLV_TAG_STRUC_wmi_ndp_cmd_param,
  295. WMITLV_GET_STRUCT_TLVLEN(wmi_ndp_cmd_param));
  296. cmd->vdev_id = vdev_id;
  297. cmd->ndp_disable = 1;
  298. wmi_mtrace(WMI_NDP_CMDID, NO_SESSION, 0);
  299. status = wmi_unified_cmd_send(wmi_handle, wmi_buf, len, WMI_NDP_CMDID);
  300. if (QDF_IS_STATUS_ERROR(status)) {
  301. wmi_err("Failed to send NDP Terminate cmd: %d", status);
  302. wmi_buf_free(wmi_buf);
  303. }
  304. return status;
  305. }
  306. static QDF_STATUS nan_ndp_initiator_req_tlv(wmi_unified_t wmi_handle,
  307. struct nan_datapath_initiator_req *ndp_req)
  308. {
  309. uint16_t len;
  310. wmi_buf_t buf;
  311. uint8_t *tlv_ptr;
  312. QDF_STATUS status;
  313. wmi_channel *ch_tlv;
  314. wmi_ndp_initiator_req_fixed_param *cmd;
  315. uint32_t passphrase_len, service_name_len;
  316. uint32_t ndp_cfg_len, ndp_app_info_len, pmk_len;
  317. wmi_ndp_transport_ip_param *tcp_ip_param;
  318. /*
  319. * WMI command expects 4 byte alligned len:
  320. * round up ndp_cfg_len and ndp_app_info_len to 4 bytes
  321. */
  322. ndp_cfg_len = qdf_roundup(ndp_req->ndp_config.ndp_cfg_len, 4);
  323. ndp_app_info_len = qdf_roundup(ndp_req->ndp_info.ndp_app_info_len, 4);
  324. pmk_len = qdf_roundup(ndp_req->pmk.pmk_len, 4);
  325. passphrase_len = qdf_roundup(ndp_req->passphrase.passphrase_len, 4);
  326. service_name_len =
  327. qdf_roundup(ndp_req->service_name.service_name_len, 4);
  328. /* allocated memory for fixed params as well as variable size data */
  329. len = sizeof(*cmd) + sizeof(*ch_tlv) + (5 * WMI_TLV_HDR_SIZE)
  330. + ndp_cfg_len + ndp_app_info_len + pmk_len
  331. + passphrase_len + service_name_len;
  332. if (ndp_req->is_ipv6_addr_present)
  333. len += sizeof(*tcp_ip_param);
  334. buf = wmi_buf_alloc(wmi_handle, len);
  335. if (!buf) {
  336. return QDF_STATUS_E_NOMEM;
  337. }
  338. cmd = (wmi_ndp_initiator_req_fixed_param *) wmi_buf_data(buf);
  339. WMITLV_SET_HDR(&cmd->tlv_header,
  340. WMITLV_TAG_STRUC_wmi_ndp_initiator_req_fixed_param,
  341. WMITLV_GET_STRUCT_TLVLEN(
  342. wmi_ndp_initiator_req_fixed_param));
  343. cmd->vdev_id = wlan_vdev_get_id(ndp_req->vdev);
  344. cmd->transaction_id = ndp_req->transaction_id;
  345. cmd->service_instance_id = ndp_req->service_instance_id;
  346. WMI_CHAR_ARRAY_TO_MAC_ADDR(ndp_req->peer_discovery_mac_addr.bytes,
  347. &cmd->peer_discovery_mac_addr);
  348. cmd->ndp_cfg_len = ndp_req->ndp_config.ndp_cfg_len;
  349. cmd->ndp_app_info_len = ndp_req->ndp_info.ndp_app_info_len;
  350. cmd->ndp_channel_cfg = ndp_req->channel_cfg;
  351. cmd->nan_pmk_len = ndp_req->pmk.pmk_len;
  352. cmd->nan_csid = ndp_req->ncs_sk_type;
  353. cmd->nan_passphrase_len = ndp_req->passphrase.passphrase_len;
  354. cmd->nan_servicename_len = ndp_req->service_name.service_name_len;
  355. ch_tlv = (wmi_channel *)&cmd[1];
  356. WMITLV_SET_HDR(ch_tlv, WMITLV_TAG_STRUC_wmi_channel,
  357. WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
  358. ch_tlv->mhz = ndp_req->channel;
  359. tlv_ptr = (uint8_t *)&ch_tlv[1];
  360. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len);
  361. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  362. ndp_req->ndp_config.ndp_cfg, cmd->ndp_cfg_len);
  363. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len;
  364. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len);
  365. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  366. ndp_req->ndp_info.ndp_app_info, cmd->ndp_app_info_len);
  367. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len;
  368. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len);
  369. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], ndp_req->pmk.pmk,
  370. cmd->nan_pmk_len);
  371. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len;
  372. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, passphrase_len);
  373. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], ndp_req->passphrase.passphrase,
  374. cmd->nan_passphrase_len);
  375. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + passphrase_len;
  376. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, service_name_len);
  377. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  378. ndp_req->service_name.service_name,
  379. cmd->nan_servicename_len);
  380. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + service_name_len;
  381. if (ndp_req->is_ipv6_addr_present) {
  382. tcp_ip_param = (wmi_ndp_transport_ip_param *)tlv_ptr;
  383. WMITLV_SET_HDR(tcp_ip_param,
  384. WMITLV_TAG_STRUC_wmi_ndp_transport_ip_param,
  385. WMITLV_GET_STRUCT_TLVLEN(
  386. wmi_ndp_transport_ip_param));
  387. tcp_ip_param->ipv6_addr_present = true;
  388. qdf_mem_copy(tcp_ip_param->ipv6_intf_addr,
  389. ndp_req->ipv6_addr, WMI_NDP_IPV6_INTF_ADDR_LEN);
  390. }
  391. WMI_LOGD("IPv6 addr present: %d, addr: %pI6",
  392. ndp_req->is_ipv6_addr_present, ndp_req->ipv6_addr);
  393. WMI_LOGD("vdev_id = %d, transaction_id: %d, service_instance_id: %d, ch: %d, ch_cfg: %d, csid: %d peer mac addr: mac_addr31to0: 0x%x, mac_addr47to32: 0x%x",
  394. cmd->vdev_id, cmd->transaction_id, cmd->service_instance_id,
  395. ch_tlv->mhz, cmd->ndp_channel_cfg, cmd->nan_csid,
  396. cmd->peer_discovery_mac_addr.mac_addr31to0,
  397. cmd->peer_discovery_mac_addr.mac_addr47to32);
  398. WMI_LOGD("ndp_config len: %d ndp_app_info len: %d pmk len: %d pass phrase len: %d service name len: %d",
  399. cmd->ndp_cfg_len, cmd->ndp_app_info_len, cmd->nan_pmk_len,
  400. cmd->nan_passphrase_len, cmd->nan_servicename_len);
  401. wmi_mtrace(WMI_NDP_INITIATOR_REQ_CMDID, cmd->vdev_id, 0);
  402. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  403. WMI_NDP_INITIATOR_REQ_CMDID);
  404. if (QDF_IS_STATUS_ERROR(status)) {
  405. wmi_err("WMI_NDP_INITIATOR_REQ_CMDID failed, ret: %d", status);
  406. wmi_buf_free(buf);
  407. }
  408. return status;
  409. }
  410. static QDF_STATUS nan_ndp_responder_req_tlv(wmi_unified_t wmi_handle,
  411. struct nan_datapath_responder_req *req)
  412. {
  413. uint16_t len;
  414. wmi_buf_t buf;
  415. uint8_t *tlv_ptr;
  416. QDF_STATUS status;
  417. wmi_ndp_responder_req_fixed_param *cmd;
  418. wmi_ndp_transport_ip_param *tcp_ip_param;
  419. uint32_t passphrase_len, service_name_len;
  420. uint32_t vdev_id = 0, ndp_cfg_len, ndp_app_info_len, pmk_len;
  421. vdev_id = wlan_vdev_get_id(req->vdev);
  422. WMI_LOGD("vdev_id: %d, transaction_id: %d, ndp_rsp %d, ndp_instance_id: %d, ndp_app_info_len: %d",
  423. vdev_id, req->transaction_id,
  424. req->ndp_rsp,
  425. req->ndp_instance_id,
  426. req->ndp_info.ndp_app_info_len);
  427. /*
  428. * WMI command expects 4 byte alligned len:
  429. * round up ndp_cfg_len and ndp_app_info_len to 4 bytes
  430. */
  431. ndp_cfg_len = qdf_roundup(req->ndp_config.ndp_cfg_len, 4);
  432. ndp_app_info_len = qdf_roundup(req->ndp_info.ndp_app_info_len, 4);
  433. pmk_len = qdf_roundup(req->pmk.pmk_len, 4);
  434. passphrase_len = qdf_roundup(req->passphrase.passphrase_len, 4);
  435. service_name_len =
  436. qdf_roundup(req->service_name.service_name_len, 4);
  437. /* allocated memory for fixed params as well as variable size data */
  438. len = sizeof(*cmd) + 5*WMI_TLV_HDR_SIZE + ndp_cfg_len + ndp_app_info_len
  439. + pmk_len + passphrase_len + service_name_len;
  440. if (req->is_ipv6_addr_present || req->is_port_present ||
  441. req->is_protocol_present)
  442. len += sizeof(*tcp_ip_param);
  443. buf = wmi_buf_alloc(wmi_handle, len);
  444. if (!buf) {
  445. return QDF_STATUS_E_NOMEM;
  446. }
  447. cmd = (wmi_ndp_responder_req_fixed_param *) wmi_buf_data(buf);
  448. WMITLV_SET_HDR(&cmd->tlv_header,
  449. WMITLV_TAG_STRUC_wmi_ndp_responder_req_fixed_param,
  450. WMITLV_GET_STRUCT_TLVLEN(
  451. wmi_ndp_responder_req_fixed_param));
  452. cmd->vdev_id = vdev_id;
  453. cmd->transaction_id = req->transaction_id;
  454. cmd->ndp_instance_id = req->ndp_instance_id;
  455. cmd->rsp_code = req->ndp_rsp;
  456. cmd->ndp_cfg_len = req->ndp_config.ndp_cfg_len;
  457. cmd->ndp_app_info_len = req->ndp_info.ndp_app_info_len;
  458. cmd->nan_pmk_len = req->pmk.pmk_len;
  459. cmd->nan_csid = req->ncs_sk_type;
  460. cmd->nan_passphrase_len = req->passphrase.passphrase_len;
  461. cmd->nan_servicename_len = req->service_name.service_name_len;
  462. tlv_ptr = (uint8_t *)&cmd[1];
  463. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len);
  464. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  465. req->ndp_config.ndp_cfg, cmd->ndp_cfg_len);
  466. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len;
  467. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len);
  468. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  469. req->ndp_info.ndp_app_info,
  470. req->ndp_info.ndp_app_info_len);
  471. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len;
  472. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len);
  473. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], req->pmk.pmk,
  474. cmd->nan_pmk_len);
  475. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len;
  476. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, passphrase_len);
  477. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  478. req->passphrase.passphrase,
  479. cmd->nan_passphrase_len);
  480. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + passphrase_len;
  481. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, service_name_len);
  482. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  483. req->service_name.service_name,
  484. cmd->nan_servicename_len);
  485. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + service_name_len;
  486. if (req->is_ipv6_addr_present || req->is_port_present ||
  487. req->is_protocol_present) {
  488. tcp_ip_param = (wmi_ndp_transport_ip_param *)tlv_ptr;
  489. WMITLV_SET_HDR(tcp_ip_param,
  490. WMITLV_TAG_STRUC_wmi_ndp_transport_ip_param,
  491. WMITLV_GET_STRUCT_TLVLEN(
  492. wmi_ndp_transport_ip_param));
  493. tcp_ip_param->ipv6_addr_present = req->is_ipv6_addr_present;
  494. qdf_mem_copy(tcp_ip_param->ipv6_intf_addr,
  495. req->ipv6_addr, WMI_NDP_IPV6_INTF_ADDR_LEN);
  496. tcp_ip_param->trans_port_present = req->is_port_present;
  497. tcp_ip_param->transport_port = req->port;
  498. tcp_ip_param->trans_proto_present = req->is_protocol_present;
  499. tcp_ip_param->transport_protocol = req->protocol;
  500. }
  501. WMI_LOGD("ndp_config len: %d ndp_app_info len: %d pmk len: %d pass phrase len: %d service name len: %d",
  502. req->ndp_config.ndp_cfg_len, req->ndp_info.ndp_app_info_len,
  503. cmd->nan_pmk_len, cmd->nan_passphrase_len,
  504. cmd->nan_servicename_len);
  505. wmi_mtrace(WMI_NDP_RESPONDER_REQ_CMDID, cmd->vdev_id, 0);
  506. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  507. WMI_NDP_RESPONDER_REQ_CMDID);
  508. if (QDF_IS_STATUS_ERROR(status)) {
  509. wmi_err("WMI_NDP_RESPONDER_REQ_CMDID failed, ret: %d", status);
  510. wmi_buf_free(buf);
  511. }
  512. return status;
  513. }
  514. static QDF_STATUS nan_ndp_end_req_tlv(wmi_unified_t wmi_handle,
  515. struct nan_datapath_end_req *req)
  516. {
  517. uint16_t len;
  518. wmi_buf_t buf;
  519. QDF_STATUS status;
  520. uint32_t ndp_end_req_len, i;
  521. wmi_ndp_end_req *ndp_end_req_lst;
  522. wmi_ndp_end_req_fixed_param *cmd;
  523. /* len of tlv following fixed param */
  524. ndp_end_req_len = sizeof(wmi_ndp_end_req) * req->num_ndp_instances;
  525. /* above comes out to 4 byte alligned already, no need of padding */
  526. len = sizeof(*cmd) + ndp_end_req_len + WMI_TLV_HDR_SIZE;
  527. buf = wmi_buf_alloc(wmi_handle, len);
  528. if (!buf) {
  529. return QDF_STATUS_E_NOMEM;
  530. }
  531. cmd = (wmi_ndp_end_req_fixed_param *) wmi_buf_data(buf);
  532. WMITLV_SET_HDR(&cmd->tlv_header,
  533. WMITLV_TAG_STRUC_wmi_ndp_end_req_fixed_param,
  534. WMITLV_GET_STRUCT_TLVLEN(wmi_ndp_end_req_fixed_param));
  535. cmd->transaction_id = req->transaction_id;
  536. /* set tlv pointer to end of fixed param */
  537. WMITLV_SET_HDR((uint8_t *)&cmd[1], WMITLV_TAG_ARRAY_STRUC,
  538. ndp_end_req_len);
  539. ndp_end_req_lst = (wmi_ndp_end_req *)((uint8_t *)&cmd[1] +
  540. WMI_TLV_HDR_SIZE);
  541. for (i = 0; i < req->num_ndp_instances; i++) {
  542. WMITLV_SET_HDR(&ndp_end_req_lst[i],
  543. WMITLV_TAG_ARRAY_FIXED_STRUC,
  544. (sizeof(*ndp_end_req_lst) - WMI_TLV_HDR_SIZE));
  545. ndp_end_req_lst[i].ndp_instance_id = req->ndp_ids[i];
  546. }
  547. wmi_mtrace(WMI_NDP_END_REQ_CMDID, NO_SESSION, 0);
  548. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  549. WMI_NDP_END_REQ_CMDID);
  550. if (QDF_IS_STATUS_ERROR(status)) {
  551. wmi_err("WMI_NDP_END_REQ_CMDID failed, ret: %d", status);
  552. wmi_buf_free(buf);
  553. }
  554. return status;
  555. }
  556. static QDF_STATUS
  557. extract_ndp_host_event_tlv(wmi_unified_t wmi_handle, uint8_t *data,
  558. struct nan_datapath_host_event *evt)
  559. {
  560. WMI_NDP_EVENTID_param_tlvs *event;
  561. wmi_ndp_event_param *fixed_params;
  562. event = (WMI_NDP_EVENTID_param_tlvs *)data;
  563. fixed_params = event->fixed_param;
  564. evt->vdev =
  565. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  566. fixed_params->vdev_id,
  567. WLAN_NAN_ID);
  568. if (!evt->vdev) {
  569. wmi_err("vdev is null");
  570. return QDF_STATUS_E_INVAL;
  571. }
  572. evt->ndp_termination_in_progress =
  573. fixed_params->ndp_termination_in_progress ? true : false;
  574. return QDF_STATUS_SUCCESS;
  575. }
  576. static QDF_STATUS extract_ndp_initiator_rsp_tlv(wmi_unified_t wmi_handle,
  577. uint8_t *data, struct nan_datapath_initiator_rsp *rsp)
  578. {
  579. WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *event;
  580. wmi_ndp_initiator_rsp_event_fixed_param *fixed_params;
  581. event = (WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *)data;
  582. fixed_params = event->fixed_param;
  583. rsp->vdev =
  584. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  585. fixed_params->vdev_id,
  586. WLAN_NAN_ID);
  587. if (!rsp->vdev) {
  588. wmi_err("vdev is null");
  589. return QDF_STATUS_E_INVAL;
  590. }
  591. rsp->transaction_id = fixed_params->transaction_id;
  592. rsp->ndp_instance_id = fixed_params->ndp_instance_id;
  593. rsp->status = fixed_params->rsp_status;
  594. rsp->reason = fixed_params->reason_code;
  595. return QDF_STATUS_SUCCESS;
  596. }
  597. #define MAX_NAN_MSG_LEN 200
  598. static QDF_STATUS extract_nan_msg_tlv(uint8_t *data,
  599. struct nan_dump_msg *msg)
  600. {
  601. WMI_NAN_DMESG_EVENTID_param_tlvs *event;
  602. wmi_nan_dmesg_event_fixed_param *fixed_params;
  603. event = (WMI_NAN_DMESG_EVENTID_param_tlvs *)data;
  604. fixed_params = (wmi_nan_dmesg_event_fixed_param *)event->fixed_param;
  605. if (!fixed_params->msg_len ||
  606. fixed_params->msg_len > MAX_NAN_MSG_LEN ||
  607. fixed_params->msg_len > event->num_msg)
  608. return QDF_STATUS_E_FAILURE;
  609. msg->data_len = fixed_params->msg_len;
  610. msg->msg = event->msg;
  611. msg->msg[fixed_params->msg_len - 1] = (uint8_t)'\0';
  612. return QDF_STATUS_SUCCESS;
  613. }
  614. static QDF_STATUS extract_ndp_ind_tlv(wmi_unified_t wmi_handle,
  615. uint8_t *data, struct nan_datapath_indication_event *rsp)
  616. {
  617. WMI_NDP_INDICATION_EVENTID_param_tlvs *event;
  618. wmi_ndp_indication_event_fixed_param *fixed_params;
  619. size_t total_array_len;
  620. event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)data;
  621. fixed_params =
  622. (wmi_ndp_indication_event_fixed_param *)event->fixed_param;
  623. if (fixed_params->ndp_cfg_len > event->num_ndp_cfg) {
  624. wmi_err("FW message ndp cfg length %d larger than TLV hdr %d",
  625. fixed_params->ndp_cfg_len, event->num_ndp_cfg);
  626. return QDF_STATUS_E_INVAL;
  627. }
  628. if (fixed_params->ndp_app_info_len > event->num_ndp_app_info) {
  629. wmi_err("FW message ndp app info length %d more than TLV hdr %d",
  630. fixed_params->ndp_app_info_len,
  631. event->num_ndp_app_info);
  632. return QDF_STATUS_E_INVAL;
  633. }
  634. if (fixed_params->nan_scid_len > event->num_ndp_scid) {
  635. wmi_err("FW msg ndp scid info len %d more than TLV hdr %d",
  636. fixed_params->nan_scid_len,
  637. event->num_ndp_scid);
  638. return QDF_STATUS_E_INVAL;
  639. }
  640. if (fixed_params->ndp_cfg_len >
  641. (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) {
  642. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  643. fixed_params->ndp_cfg_len);
  644. return QDF_STATUS_E_INVAL;
  645. }
  646. total_array_len = fixed_params->ndp_cfg_len +
  647. sizeof(*fixed_params);
  648. if (fixed_params->ndp_app_info_len >
  649. (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
  650. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  651. fixed_params->ndp_app_info_len);
  652. return QDF_STATUS_E_INVAL;
  653. }
  654. total_array_len += fixed_params->ndp_app_info_len;
  655. if (fixed_params->nan_scid_len >
  656. (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
  657. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  658. fixed_params->nan_scid_len);
  659. return QDF_STATUS_E_INVAL;
  660. }
  661. rsp->vdev =
  662. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  663. fixed_params->vdev_id,
  664. WLAN_NAN_ID);
  665. if (!rsp->vdev) {
  666. wmi_err("vdev is null");
  667. return QDF_STATUS_E_INVAL;
  668. }
  669. rsp->service_instance_id = fixed_params->service_instance_id;
  670. rsp->ndp_instance_id = fixed_params->ndp_instance_id;
  671. rsp->role = fixed_params->self_ndp_role;
  672. rsp->policy = fixed_params->accept_policy;
  673. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
  674. rsp->peer_mac_addr.bytes);
  675. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_discovery_mac_addr,
  676. rsp->peer_discovery_mac_addr.bytes);
  677. WMI_LOGD("WMI_NDP_INDICATION_EVENTID(0x%X) received. vdev %d service_instance %d, ndp_instance %d, role %d, policy %d csid: %d, scid_len: %d, peer_addr: "QDF_MAC_ADDR_FMT", peer_disc_addr: "QDF_MAC_ADDR_FMT" ndp_cfg - %d bytes ndp_app_info - %d bytes",
  678. WMI_NDP_INDICATION_EVENTID, fixed_params->vdev_id,
  679. fixed_params->service_instance_id,
  680. fixed_params->ndp_instance_id, fixed_params->self_ndp_role,
  681. fixed_params->accept_policy, fixed_params->nan_csid,
  682. fixed_params->nan_scid_len,
  683. QDF_MAC_ADDR_REF(rsp->peer_mac_addr.bytes),
  684. QDF_MAC_ADDR_REF(rsp->peer_discovery_mac_addr.bytes),
  685. fixed_params->ndp_cfg_len,
  686. fixed_params->ndp_app_info_len);
  687. rsp->ncs_sk_type = fixed_params->nan_csid;
  688. if (event->ndp_cfg) {
  689. rsp->ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len;
  690. if (rsp->ndp_config.ndp_cfg_len > NDP_QOS_INFO_LEN)
  691. rsp->ndp_config.ndp_cfg_len = NDP_QOS_INFO_LEN;
  692. qdf_mem_copy(rsp->ndp_config.ndp_cfg, event->ndp_cfg,
  693. rsp->ndp_config.ndp_cfg_len);
  694. }
  695. if (event->ndp_app_info) {
  696. rsp->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len;
  697. if (rsp->ndp_info.ndp_app_info_len > NDP_APP_INFO_LEN)
  698. rsp->ndp_info.ndp_app_info_len = NDP_APP_INFO_LEN;
  699. qdf_mem_copy(rsp->ndp_info.ndp_app_info, event->ndp_app_info,
  700. rsp->ndp_info.ndp_app_info_len);
  701. }
  702. if (event->ndp_scid) {
  703. rsp->scid.scid_len = fixed_params->nan_scid_len;
  704. if (rsp->scid.scid_len > NDP_SCID_BUF_LEN)
  705. rsp->scid.scid_len = NDP_SCID_BUF_LEN;
  706. qdf_mem_copy(rsp->scid.scid, event->ndp_scid,
  707. rsp->scid.scid_len);
  708. }
  709. if (event->ndp_transport_ip_param &&
  710. event->num_ndp_transport_ip_param) {
  711. if (event->ndp_transport_ip_param->ipv6_addr_present) {
  712. rsp->is_ipv6_addr_present = true;
  713. qdf_mem_copy(rsp->ipv6_addr,
  714. event->ndp_transport_ip_param->ipv6_intf_addr,
  715. WMI_NDP_IPV6_INTF_ADDR_LEN);
  716. }
  717. }
  718. WMI_LOGD(FL("IPv6 addr present: %d, addr: %pI6"),
  719. rsp->is_ipv6_addr_present, rsp->ipv6_addr);
  720. return QDF_STATUS_SUCCESS;
  721. }
  722. static QDF_STATUS extract_ndp_confirm_tlv(wmi_unified_t wmi_handle,
  723. uint8_t *data, struct nan_datapath_confirm_event *rsp)
  724. {
  725. uint8_t i;
  726. WMI_HOST_WLAN_PHY_MODE ch_mode;
  727. WMI_NDP_CONFIRM_EVENTID_param_tlvs *event;
  728. wmi_ndp_confirm_event_fixed_param *fixed_params;
  729. size_t total_array_len;
  730. bool ndi_dbs = wmi_service_enabled(wmi_handle,
  731. wmi_service_ndi_dbs_support);
  732. event = (WMI_NDP_CONFIRM_EVENTID_param_tlvs *) data;
  733. fixed_params = (wmi_ndp_confirm_event_fixed_param *)event->fixed_param;
  734. WMI_LOGD("WMI_NDP_CONFIRM_EVENTID(0x%X) received. vdev %d, ndp_instance %d, rsp_code %d, reason_code: %d, num_active_ndps_on_peer: %d num_ch: %d",
  735. WMI_NDP_CONFIRM_EVENTID, fixed_params->vdev_id,
  736. fixed_params->ndp_instance_id, fixed_params->rsp_code,
  737. fixed_params->reason_code,
  738. fixed_params->num_active_ndps_on_peer,
  739. fixed_params->num_ndp_channels);
  740. if (fixed_params->ndp_cfg_len > event->num_ndp_cfg) {
  741. wmi_err("FW message ndp cfg length %d larger than TLV hdr %d",
  742. fixed_params->ndp_cfg_len, event->num_ndp_cfg);
  743. return QDF_STATUS_E_INVAL;
  744. }
  745. if (fixed_params->ndp_app_info_len > event->num_ndp_app_info) {
  746. wmi_err("FW message ndp app info length %d more than TLV hdr %d",
  747. fixed_params->ndp_app_info_len,
  748. event->num_ndp_app_info);
  749. return QDF_STATUS_E_INVAL;
  750. }
  751. WMI_LOGD("ndp_cfg - %d bytes, ndp_app_info - %d bytes",
  752. fixed_params->ndp_cfg_len, fixed_params->ndp_app_info_len);
  753. if (fixed_params->ndp_cfg_len >
  754. (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) {
  755. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  756. fixed_params->ndp_cfg_len);
  757. return QDF_STATUS_E_INVAL;
  758. }
  759. total_array_len = fixed_params->ndp_cfg_len +
  760. sizeof(*fixed_params);
  761. if (fixed_params->ndp_app_info_len >
  762. (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
  763. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  764. fixed_params->ndp_app_info_len);
  765. return QDF_STATUS_E_INVAL;
  766. }
  767. if (fixed_params->num_ndp_channels > event->num_ndp_channel_list ||
  768. fixed_params->num_ndp_channels > event->num_nss_list) {
  769. wmi_err("NDP Ch count %d greater than NDP Ch TLV len(%d) or NSS TLV len(%d)",
  770. fixed_params->num_ndp_channels,
  771. event->num_ndp_channel_list,
  772. event->num_nss_list);
  773. return QDF_STATUS_E_INVAL;
  774. }
  775. if (ndi_dbs &&
  776. fixed_params->num_ndp_channels > event->num_ndp_channel_info) {
  777. wmi_err("NDP Ch count %d greater than NDP Ch info(%d)",
  778. fixed_params->num_ndp_channels,
  779. event->num_ndp_channel_info);
  780. return QDF_STATUS_E_INVAL;
  781. }
  782. rsp->vdev =
  783. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  784. fixed_params->vdev_id,
  785. WLAN_NAN_ID);
  786. if (!rsp->vdev) {
  787. wmi_err("vdev is null");
  788. return QDF_STATUS_E_INVAL;
  789. }
  790. rsp->ndp_instance_id = fixed_params->ndp_instance_id;
  791. rsp->rsp_code = fixed_params->rsp_code;
  792. rsp->reason_code = fixed_params->reason_code;
  793. rsp->num_active_ndps_on_peer = fixed_params->num_active_ndps_on_peer;
  794. rsp->num_channels = fixed_params->num_ndp_channels;
  795. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
  796. rsp->peer_ndi_mac_addr.bytes);
  797. rsp->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len;
  798. qdf_mem_copy(rsp->ndp_info.ndp_app_info, event->ndp_app_info,
  799. rsp->ndp_info.ndp_app_info_len);
  800. if (rsp->num_channels > NAN_CH_INFO_MAX_CHANNELS) {
  801. wmi_err("too many channels");
  802. rsp->num_channels = NAN_CH_INFO_MAX_CHANNELS;
  803. }
  804. for (i = 0; i < rsp->num_channels; i++) {
  805. rsp->ch[i].freq = event->ndp_channel_list[i].mhz;
  806. rsp->ch[i].nss = event->nss_list[i];
  807. ch_mode = WMI_GET_CHANNEL_MODE(&event->ndp_channel_list[i]);
  808. rsp->ch[i].ch_width = wmi_get_ch_width_from_phy_mode(wmi_handle,
  809. ch_mode);
  810. if (ndi_dbs) {
  811. rsp->ch[i].mac_id = event->ndp_channel_info[i].mac_id;
  812. WMI_LOGD("Freq: %d, ch_mode: %d, nss: %d mac_id: %d",
  813. rsp->ch[i].freq, rsp->ch[i].ch_width,
  814. rsp->ch[i].nss, rsp->ch[i].mac_id);
  815. } else {
  816. WMI_LOGD("Freq: %d, ch_mode: %d, nss: %d",
  817. rsp->ch[i].freq, rsp->ch[i].ch_width,
  818. rsp->ch[i].nss);
  819. }
  820. }
  821. if (event->ndp_transport_ip_param &&
  822. event->num_ndp_transport_ip_param) {
  823. if (event->ndp_transport_ip_param->ipv6_addr_present) {
  824. rsp->is_ipv6_addr_present = true;
  825. qdf_mem_copy(rsp->ipv6_addr,
  826. event->ndp_transport_ip_param->ipv6_intf_addr,
  827. WMI_NDP_IPV6_INTF_ADDR_LEN);
  828. }
  829. if (event->ndp_transport_ip_param->trans_port_present) {
  830. rsp->is_port_present = true;
  831. rsp->port =
  832. event->ndp_transport_ip_param->transport_port;
  833. }
  834. if (event->ndp_transport_ip_param->trans_proto_present) {
  835. rsp->is_protocol_present = true;
  836. rsp->protocol =
  837. event->ndp_transport_ip_param->transport_protocol;
  838. }
  839. }
  840. WMI_LOGD("IPv6 addr present: %d, addr: %pI6 port: %d present: %d protocol: %d present: %d",
  841. rsp->is_ipv6_addr_present, rsp->ipv6_addr, rsp->port,
  842. rsp->is_port_present, rsp->protocol, rsp->is_protocol_present);
  843. return QDF_STATUS_SUCCESS;
  844. }
  845. static QDF_STATUS extract_ndp_responder_rsp_tlv(wmi_unified_t wmi_handle,
  846. uint8_t *data, struct nan_datapath_responder_rsp *rsp)
  847. {
  848. WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *event;
  849. wmi_ndp_responder_rsp_event_fixed_param *fixed_params;
  850. event = (WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *)data;
  851. fixed_params = event->fixed_param;
  852. rsp->vdev =
  853. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  854. fixed_params->vdev_id,
  855. WLAN_NAN_ID);
  856. if (!rsp->vdev) {
  857. wmi_err("vdev is null");
  858. return QDF_STATUS_E_INVAL;
  859. }
  860. rsp->transaction_id = fixed_params->transaction_id;
  861. rsp->reason = fixed_params->reason_code;
  862. rsp->status = fixed_params->rsp_status;
  863. rsp->create_peer = fixed_params->create_peer;
  864. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
  865. rsp->peer_mac_addr.bytes);
  866. WMI_LOGD("WMI_NDP_RESPONDER_RSP_EVENTID(0x%X) received. vdev_id: %d, peer_mac_addr: "QDF_MAC_ADDR_FMT",transaction_id: %d, status_code %d, reason_code: %d, create_peer: %d",
  867. WMI_NDP_RESPONDER_RSP_EVENTID, fixed_params->vdev_id,
  868. QDF_MAC_ADDR_REF(rsp->peer_mac_addr.bytes),
  869. rsp->transaction_id,
  870. rsp->status, rsp->reason, rsp->create_peer);
  871. return QDF_STATUS_SUCCESS;
  872. }
  873. static QDF_STATUS extract_ndp_end_rsp_tlv(wmi_unified_t wmi_handle,
  874. uint8_t *data, struct nan_datapath_end_rsp_event *rsp)
  875. {
  876. WMI_NDP_END_RSP_EVENTID_param_tlvs *event;
  877. wmi_ndp_end_rsp_event_fixed_param *fixed_params = NULL;
  878. event = (WMI_NDP_END_RSP_EVENTID_param_tlvs *) data;
  879. fixed_params = (wmi_ndp_end_rsp_event_fixed_param *)event->fixed_param;
  880. WMI_LOGD("WMI_NDP_END_RSP_EVENTID(0x%X) received. transaction_id: %d, rsp_status: %d, reason_code: %d",
  881. WMI_NDP_END_RSP_EVENTID, fixed_params->transaction_id,
  882. fixed_params->rsp_status, fixed_params->reason_code);
  883. rsp->vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(
  884. wmi_handle->soc->wmi_psoc, QDF_NDI_MODE, WLAN_NAN_ID);
  885. if (!rsp->vdev) {
  886. wmi_err("vdev is null");
  887. return QDF_STATUS_E_INVAL;
  888. }
  889. rsp->transaction_id = fixed_params->transaction_id;
  890. rsp->reason = fixed_params->reason_code;
  891. rsp->status = fixed_params->rsp_status;
  892. return QDF_STATUS_SUCCESS;
  893. }
  894. static QDF_STATUS extract_ndp_end_ind_tlv(wmi_unified_t wmi_handle,
  895. uint8_t *data, struct nan_datapath_end_indication_event **rsp)
  896. {
  897. uint32_t i, buf_size;
  898. wmi_ndp_end_indication *ind;
  899. struct qdf_mac_addr peer_addr;
  900. WMI_NDP_END_INDICATION_EVENTID_param_tlvs *event;
  901. event = (WMI_NDP_END_INDICATION_EVENTID_param_tlvs *) data;
  902. ind = event->ndp_end_indication_list;
  903. if (event->num_ndp_end_indication_list == 0) {
  904. wmi_err("Error: Event ignored, 0 ndp instances");
  905. return QDF_STATUS_E_INVAL;
  906. }
  907. WMI_LOGD("number of ndp instances = %d",
  908. event->num_ndp_end_indication_list);
  909. if (event->num_ndp_end_indication_list > ((UINT_MAX - sizeof(**rsp))/
  910. sizeof((*rsp)->ndp_map[0]))) {
  911. wmi_err("num_ndp_end_ind_list %d too large",
  912. event->num_ndp_end_indication_list);
  913. return QDF_STATUS_E_INVAL;
  914. }
  915. buf_size = sizeof(**rsp) + event->num_ndp_end_indication_list *
  916. sizeof((*rsp)->ndp_map[0]);
  917. *rsp = qdf_mem_malloc(buf_size);
  918. if (!(*rsp))
  919. return QDF_STATUS_E_NOMEM;
  920. (*rsp)->num_ndp_ids = event->num_ndp_end_indication_list;
  921. for (i = 0; i < (*rsp)->num_ndp_ids; i++) {
  922. WMI_MAC_ADDR_TO_CHAR_ARRAY(&ind[i].peer_ndi_mac_addr,
  923. peer_addr.bytes);
  924. WMI_LOGD("ind[%d]: type %d, reason_code %d, instance_id %d num_active %d ",
  925. i, ind[i].type, ind[i].reason_code,
  926. ind[i].ndp_instance_id,
  927. ind[i].num_active_ndps_on_peer);
  928. /* Add each instance entry to the list */
  929. (*rsp)->ndp_map[i].ndp_instance_id = ind[i].ndp_instance_id;
  930. (*rsp)->ndp_map[i].vdev_id = ind[i].vdev_id;
  931. WMI_MAC_ADDR_TO_CHAR_ARRAY(&ind[i].peer_ndi_mac_addr,
  932. (*rsp)->ndp_map[i].peer_ndi_mac_addr.bytes);
  933. (*rsp)->ndp_map[i].num_active_ndp_sessions =
  934. ind[i].num_active_ndps_on_peer;
  935. (*rsp)->ndp_map[i].type = ind[i].type;
  936. (*rsp)->ndp_map[i].reason_code = ind[i].reason_code;
  937. }
  938. return QDF_STATUS_SUCCESS;
  939. }
  940. static QDF_STATUS extract_ndp_sch_update_tlv(wmi_unified_t wmi_handle,
  941. uint8_t *data, struct nan_datapath_sch_update_event *ind)
  942. {
  943. uint8_t i;
  944. WMI_HOST_WLAN_PHY_MODE ch_mode;
  945. WMI_NDL_SCHEDULE_UPDATE_EVENTID_param_tlvs *event;
  946. wmi_ndl_schedule_update_fixed_param *fixed_params;
  947. bool ndi_dbs = wmi_service_enabled(wmi_handle,
  948. wmi_service_ndi_dbs_support);
  949. event = (WMI_NDL_SCHEDULE_UPDATE_EVENTID_param_tlvs *)data;
  950. fixed_params = event->fixed_param;
  951. WMI_LOGD(FL("flags: %d, num_ch: %d, num_ndp_instances: %d"),
  952. fixed_params->flags, fixed_params->num_channels,
  953. fixed_params->num_ndp_instances);
  954. if (fixed_params->num_channels > event->num_ndl_channel_list ||
  955. fixed_params->num_channels > event->num_nss_list) {
  956. wmi_err("Channel count %d greater than NDP Ch list TLV len(%d) or NSS list TLV len(%d)",
  957. fixed_params->num_channels,
  958. event->num_ndl_channel_list,
  959. event->num_nss_list);
  960. return QDF_STATUS_E_INVAL;
  961. }
  962. if (ndi_dbs &&
  963. fixed_params->num_channels > event->num_ndp_channel_info) {
  964. wmi_err("Channel count %d greater than NDP Ch info(%d)",
  965. fixed_params->num_channels,
  966. event->num_ndp_channel_info);
  967. return QDF_STATUS_E_INVAL;
  968. }
  969. if (fixed_params->num_ndp_instances > event->num_ndp_instance_list) {
  970. wmi_err("NDP Instance count %d greater than NDP Instancei TLV len %d",
  971. fixed_params->num_ndp_instances,
  972. event->num_ndp_instance_list);
  973. return QDF_STATUS_E_INVAL;
  974. }
  975. ind->vdev =
  976. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  977. fixed_params->vdev_id,
  978. WLAN_NAN_ID);
  979. if (!ind->vdev) {
  980. wmi_err("vdev is null");
  981. return QDF_STATUS_E_INVAL;
  982. }
  983. ind->flags = fixed_params->flags;
  984. ind->num_channels = fixed_params->num_channels;
  985. ind->num_ndp_instances = fixed_params->num_ndp_instances;
  986. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_macaddr,
  987. ind->peer_addr.bytes);
  988. if (ind->num_ndp_instances > NDP_NUM_INSTANCE_ID) {
  989. wmi_err("uint32 overflow");
  990. wlan_objmgr_vdev_release_ref(ind->vdev, WLAN_NAN_ID);
  991. return QDF_STATUS_E_INVAL;
  992. }
  993. qdf_mem_copy(ind->ndp_instances, event->ndp_instance_list,
  994. sizeof(uint32_t) * ind->num_ndp_instances);
  995. if (ind->num_channels > NAN_CH_INFO_MAX_CHANNELS) {
  996. wmi_err("too many channels");
  997. ind->num_channels = NAN_CH_INFO_MAX_CHANNELS;
  998. }
  999. for (i = 0; i < ind->num_channels; i++) {
  1000. ind->ch[i].freq = event->ndl_channel_list[i].mhz;
  1001. ind->ch[i].nss = event->nss_list[i];
  1002. ch_mode = WMI_GET_CHANNEL_MODE(&event->ndl_channel_list[i]);
  1003. ind->ch[i].ch_width = wmi_get_ch_width_from_phy_mode(wmi_handle,
  1004. ch_mode);
  1005. if (ndi_dbs) {
  1006. ind->ch[i].mac_id = event->ndp_channel_info[i].mac_id;
  1007. WMI_LOGD(FL("Freq: %d, ch_mode: %d, nss: %d mac_id: %d"),
  1008. ind->ch[i].freq, ind->ch[i].ch_width,
  1009. ind->ch[i].nss, ind->ch[i].mac_id);
  1010. } else {
  1011. WMI_LOGD(FL("Freq: %d, ch_mode: %d, nss: %d"),
  1012. ind->ch[i].freq, ind->ch[i].ch_width,
  1013. ind->ch[i].nss);
  1014. }
  1015. }
  1016. for (i = 0; i < fixed_params->num_ndp_instances; i++)
  1017. WMI_LOGD(FL("instance_id[%d]: %d"),
  1018. i, event->ndp_instance_list[i]);
  1019. return QDF_STATUS_SUCCESS;
  1020. }
  1021. void wmi_nan_attach_tlv(wmi_unified_t wmi_handle)
  1022. {
  1023. struct wmi_ops *ops = wmi_handle->ops;
  1024. ops->send_nan_req_cmd = send_nan_req_cmd_tlv;
  1025. ops->send_nan_disable_req_cmd = send_nan_disable_req_cmd_tlv;
  1026. ops->extract_nan_event_rsp = extract_nan_event_rsp_tlv;
  1027. ops->send_terminate_all_ndps_req_cmd = send_terminate_all_ndps_cmd_tlv;
  1028. ops->send_ndp_initiator_req_cmd = nan_ndp_initiator_req_tlv;
  1029. ops->send_ndp_responder_req_cmd = nan_ndp_responder_req_tlv;
  1030. ops->send_ndp_end_req_cmd = nan_ndp_end_req_tlv;
  1031. ops->extract_ndp_initiator_rsp = extract_ndp_initiator_rsp_tlv;
  1032. ops->extract_ndp_ind = extract_ndp_ind_tlv;
  1033. ops->extract_nan_msg = extract_nan_msg_tlv,
  1034. ops->extract_ndp_confirm = extract_ndp_confirm_tlv;
  1035. ops->extract_ndp_responder_rsp = extract_ndp_responder_rsp_tlv;
  1036. ops->extract_ndp_end_rsp = extract_ndp_end_rsp_tlv;
  1037. ops->extract_ndp_end_ind = extract_ndp_end_ind_tlv;
  1038. ops->extract_ndp_sch_update = extract_ndp_sch_update_tlv;
  1039. ops->extract_ndp_host_event = extract_ndp_host_event_tlv;
  1040. }