wmi_unified_nan_tlv.c 39 KB

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