wmi_unified_nan_tlv.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214
  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_debug("nan data len value is %u", 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_NAN_SET_NAN_6G_DISABLE(cfg->flags, nan_msg->disable_6g_nan);
  266. wmi_mtrace(WMI_NAN_CMDID, NO_SESSION, 0);
  267. ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_NAN_CMDID);
  268. if (QDF_IS_STATUS_ERROR(ret)) {
  269. wmi_err("Failed to send NAN req command ret = %d", ret);
  270. wmi_buf_free(buf);
  271. }
  272. return ret;
  273. }
  274. /**
  275. * send_terminate_all_ndps_cmd_tlv() - send NDP Terminate for all NDP's
  276. * associated with the given vdev id
  277. * @wmi_handle: wmi handle
  278. * @vdev_id: vdev id
  279. *
  280. * Return: QDF status
  281. */
  282. static QDF_STATUS send_terminate_all_ndps_cmd_tlv(wmi_unified_t wmi_handle,
  283. uint32_t vdev_id)
  284. {
  285. wmi_ndp_cmd_param *cmd;
  286. wmi_buf_t wmi_buf;
  287. uint32_t len;
  288. QDF_STATUS status;
  289. wmi_debug("Enter");
  290. len = sizeof(*cmd);
  291. wmi_buf = wmi_buf_alloc(wmi_handle, len);
  292. if (!wmi_buf)
  293. return QDF_STATUS_E_NOMEM;
  294. cmd = (wmi_ndp_cmd_param *)wmi_buf_data(wmi_buf);
  295. WMITLV_SET_HDR(&cmd->tlv_header, WMITLV_TAG_STRUC_wmi_ndp_cmd_param,
  296. WMITLV_GET_STRUCT_TLVLEN(wmi_ndp_cmd_param));
  297. cmd->vdev_id = vdev_id;
  298. cmd->ndp_disable = 1;
  299. wmi_mtrace(WMI_NDP_CMDID, NO_SESSION, 0);
  300. status = wmi_unified_cmd_send(wmi_handle, wmi_buf, len, WMI_NDP_CMDID);
  301. if (QDF_IS_STATUS_ERROR(status)) {
  302. wmi_err("Failed to send NDP Terminate cmd: %d", status);
  303. wmi_buf_free(wmi_buf);
  304. }
  305. return status;
  306. }
  307. static QDF_STATUS nan_ndp_initiator_req_tlv(wmi_unified_t wmi_handle,
  308. struct nan_datapath_initiator_req *ndp_req)
  309. {
  310. uint16_t len;
  311. wmi_buf_t buf;
  312. uint8_t *tlv_ptr;
  313. QDF_STATUS status;
  314. wmi_channel *ch_tlv;
  315. wmi_ndp_initiator_req_fixed_param *cmd;
  316. uint32_t passphrase_len, service_name_len;
  317. uint32_t ndp_cfg_len, ndp_app_info_len, pmk_len;
  318. wmi_ndp_transport_ip_param *tcp_ip_param;
  319. /*
  320. * WMI command expects 4 byte alligned len:
  321. * round up ndp_cfg_len and ndp_app_info_len to 4 bytes
  322. */
  323. ndp_cfg_len = qdf_roundup(ndp_req->ndp_config.ndp_cfg_len, 4);
  324. ndp_app_info_len = qdf_roundup(ndp_req->ndp_info.ndp_app_info_len, 4);
  325. pmk_len = qdf_roundup(ndp_req->pmk.pmk_len, 4);
  326. passphrase_len = qdf_roundup(ndp_req->passphrase.passphrase_len, 4);
  327. service_name_len =
  328. qdf_roundup(ndp_req->service_name.service_name_len, 4);
  329. /* allocated memory for fixed params as well as variable size data */
  330. len = sizeof(*cmd) + sizeof(*ch_tlv) + (5 * WMI_TLV_HDR_SIZE)
  331. + ndp_cfg_len + ndp_app_info_len + pmk_len
  332. + passphrase_len + service_name_len;
  333. if (ndp_req->is_ipv6_addr_present)
  334. len += sizeof(*tcp_ip_param);
  335. buf = wmi_buf_alloc(wmi_handle, len);
  336. if (!buf) {
  337. return QDF_STATUS_E_NOMEM;
  338. }
  339. cmd = (wmi_ndp_initiator_req_fixed_param *) wmi_buf_data(buf);
  340. WMITLV_SET_HDR(&cmd->tlv_header,
  341. WMITLV_TAG_STRUC_wmi_ndp_initiator_req_fixed_param,
  342. WMITLV_GET_STRUCT_TLVLEN(
  343. wmi_ndp_initiator_req_fixed_param));
  344. cmd->vdev_id = wlan_vdev_get_id(ndp_req->vdev);
  345. cmd->transaction_id = ndp_req->transaction_id;
  346. cmd->service_instance_id = ndp_req->service_instance_id;
  347. WMI_CHAR_ARRAY_TO_MAC_ADDR(ndp_req->peer_discovery_mac_addr.bytes,
  348. &cmd->peer_discovery_mac_addr);
  349. cmd->ndp_cfg_len = ndp_req->ndp_config.ndp_cfg_len;
  350. cmd->ndp_app_info_len = ndp_req->ndp_info.ndp_app_info_len;
  351. cmd->ndp_channel_cfg = ndp_req->channel_cfg;
  352. cmd->nan_pmk_len = ndp_req->pmk.pmk_len;
  353. cmd->nan_csid = ndp_req->ncs_sk_type;
  354. cmd->nan_passphrase_len = ndp_req->passphrase.passphrase_len;
  355. cmd->nan_servicename_len = ndp_req->service_name.service_name_len;
  356. ch_tlv = (wmi_channel *)&cmd[1];
  357. WMITLV_SET_HDR(ch_tlv, WMITLV_TAG_STRUC_wmi_channel,
  358. WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
  359. ch_tlv->mhz = ndp_req->channel;
  360. tlv_ptr = (uint8_t *)&ch_tlv[1];
  361. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len);
  362. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  363. ndp_req->ndp_config.ndp_cfg, cmd->ndp_cfg_len);
  364. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len;
  365. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len);
  366. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  367. ndp_req->ndp_info.ndp_app_info, cmd->ndp_app_info_len);
  368. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len;
  369. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len);
  370. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], ndp_req->pmk.pmk,
  371. cmd->nan_pmk_len);
  372. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len;
  373. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, passphrase_len);
  374. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], ndp_req->passphrase.passphrase,
  375. cmd->nan_passphrase_len);
  376. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + passphrase_len;
  377. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, service_name_len);
  378. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  379. ndp_req->service_name.service_name,
  380. cmd->nan_servicename_len);
  381. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + service_name_len;
  382. if (ndp_req->is_ipv6_addr_present) {
  383. tcp_ip_param = (wmi_ndp_transport_ip_param *)tlv_ptr;
  384. WMITLV_SET_HDR(tcp_ip_param,
  385. WMITLV_TAG_STRUC_wmi_ndp_transport_ip_param,
  386. WMITLV_GET_STRUCT_TLVLEN(
  387. wmi_ndp_transport_ip_param));
  388. tcp_ip_param->ipv6_addr_present = true;
  389. qdf_mem_copy(tcp_ip_param->ipv6_intf_addr,
  390. ndp_req->ipv6_addr, WMI_NDP_IPV6_INTF_ADDR_LEN);
  391. }
  392. wmi_debug("IPv6 addr present: %d, addr: %pI6",
  393. ndp_req->is_ipv6_addr_present, ndp_req->ipv6_addr);
  394. wmi_debug("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",
  395. cmd->vdev_id, cmd->transaction_id, cmd->service_instance_id,
  396. ch_tlv->mhz, cmd->ndp_channel_cfg, cmd->nan_csid,
  397. cmd->peer_discovery_mac_addr.mac_addr31to0,
  398. cmd->peer_discovery_mac_addr.mac_addr47to32);
  399. wmi_debug("ndp_config len: %d ndp_app_info len: %d pmk len: %d pass phrase len: %d service name len: %d",
  400. cmd->ndp_cfg_len, cmd->ndp_app_info_len, cmd->nan_pmk_len,
  401. cmd->nan_passphrase_len, cmd->nan_servicename_len);
  402. wmi_mtrace(WMI_NDP_INITIATOR_REQ_CMDID, cmd->vdev_id, 0);
  403. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  404. WMI_NDP_INITIATOR_REQ_CMDID);
  405. if (QDF_IS_STATUS_ERROR(status)) {
  406. wmi_err("WMI_NDP_INITIATOR_REQ_CMDID failed, ret: %d", status);
  407. wmi_buf_free(buf);
  408. }
  409. return status;
  410. }
  411. static QDF_STATUS nan_ndp_responder_req_tlv(wmi_unified_t wmi_handle,
  412. struct nan_datapath_responder_req *req)
  413. {
  414. uint16_t len;
  415. wmi_buf_t buf;
  416. uint8_t *tlv_ptr;
  417. QDF_STATUS status;
  418. wmi_ndp_responder_req_fixed_param *cmd;
  419. wmi_ndp_transport_ip_param *tcp_ip_param;
  420. uint32_t passphrase_len, service_name_len;
  421. uint32_t vdev_id = 0, ndp_cfg_len, ndp_app_info_len, pmk_len;
  422. vdev_id = wlan_vdev_get_id(req->vdev);
  423. wmi_debug("vdev_id: %d, transaction_id: %d, ndp_rsp %d, ndp_instance_id: %d, ndp_app_info_len: %d",
  424. vdev_id, req->transaction_id,
  425. req->ndp_rsp,
  426. req->ndp_instance_id,
  427. req->ndp_info.ndp_app_info_len);
  428. /*
  429. * WMI command expects 4 byte alligned len:
  430. * round up ndp_cfg_len and ndp_app_info_len to 4 bytes
  431. */
  432. ndp_cfg_len = qdf_roundup(req->ndp_config.ndp_cfg_len, 4);
  433. ndp_app_info_len = qdf_roundup(req->ndp_info.ndp_app_info_len, 4);
  434. pmk_len = qdf_roundup(req->pmk.pmk_len, 4);
  435. passphrase_len = qdf_roundup(req->passphrase.passphrase_len, 4);
  436. service_name_len =
  437. qdf_roundup(req->service_name.service_name_len, 4);
  438. /* allocated memory for fixed params as well as variable size data */
  439. len = sizeof(*cmd) + 5*WMI_TLV_HDR_SIZE + ndp_cfg_len + ndp_app_info_len
  440. + pmk_len + passphrase_len + service_name_len;
  441. if (req->is_ipv6_addr_present || req->is_port_present ||
  442. req->is_protocol_present)
  443. len += sizeof(*tcp_ip_param);
  444. buf = wmi_buf_alloc(wmi_handle, len);
  445. if (!buf) {
  446. return QDF_STATUS_E_NOMEM;
  447. }
  448. cmd = (wmi_ndp_responder_req_fixed_param *) wmi_buf_data(buf);
  449. WMITLV_SET_HDR(&cmd->tlv_header,
  450. WMITLV_TAG_STRUC_wmi_ndp_responder_req_fixed_param,
  451. WMITLV_GET_STRUCT_TLVLEN(
  452. wmi_ndp_responder_req_fixed_param));
  453. cmd->vdev_id = vdev_id;
  454. cmd->transaction_id = req->transaction_id;
  455. cmd->ndp_instance_id = req->ndp_instance_id;
  456. cmd->rsp_code = req->ndp_rsp;
  457. cmd->ndp_cfg_len = req->ndp_config.ndp_cfg_len;
  458. cmd->ndp_app_info_len = req->ndp_info.ndp_app_info_len;
  459. cmd->nan_pmk_len = req->pmk.pmk_len;
  460. cmd->nan_csid = req->ncs_sk_type;
  461. cmd->nan_passphrase_len = req->passphrase.passphrase_len;
  462. cmd->nan_servicename_len = req->service_name.service_name_len;
  463. tlv_ptr = (uint8_t *)&cmd[1];
  464. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len);
  465. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  466. req->ndp_config.ndp_cfg, cmd->ndp_cfg_len);
  467. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len;
  468. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len);
  469. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  470. req->ndp_info.ndp_app_info,
  471. req->ndp_info.ndp_app_info_len);
  472. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len;
  473. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len);
  474. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], req->pmk.pmk,
  475. cmd->nan_pmk_len);
  476. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len;
  477. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, passphrase_len);
  478. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  479. req->passphrase.passphrase,
  480. cmd->nan_passphrase_len);
  481. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + passphrase_len;
  482. WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, service_name_len);
  483. qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE],
  484. req->service_name.service_name,
  485. cmd->nan_servicename_len);
  486. tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + service_name_len;
  487. if (req->is_ipv6_addr_present || req->is_port_present ||
  488. req->is_protocol_present) {
  489. tcp_ip_param = (wmi_ndp_transport_ip_param *)tlv_ptr;
  490. WMITLV_SET_HDR(tcp_ip_param,
  491. WMITLV_TAG_STRUC_wmi_ndp_transport_ip_param,
  492. WMITLV_GET_STRUCT_TLVLEN(
  493. wmi_ndp_transport_ip_param));
  494. tcp_ip_param->ipv6_addr_present = req->is_ipv6_addr_present;
  495. qdf_mem_copy(tcp_ip_param->ipv6_intf_addr,
  496. req->ipv6_addr, WMI_NDP_IPV6_INTF_ADDR_LEN);
  497. tcp_ip_param->trans_port_present = req->is_port_present;
  498. tcp_ip_param->transport_port = req->port;
  499. tcp_ip_param->trans_proto_present = req->is_protocol_present;
  500. tcp_ip_param->transport_protocol = req->protocol;
  501. }
  502. wmi_debug("ndp_config len: %d ndp_app_info len: %d pmk len: %d pass phrase len: %d service name len: %d",
  503. req->ndp_config.ndp_cfg_len, req->ndp_info.ndp_app_info_len,
  504. cmd->nan_pmk_len, cmd->nan_passphrase_len,
  505. cmd->nan_servicename_len);
  506. wmi_mtrace(WMI_NDP_RESPONDER_REQ_CMDID, cmd->vdev_id, 0);
  507. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  508. WMI_NDP_RESPONDER_REQ_CMDID);
  509. if (QDF_IS_STATUS_ERROR(status)) {
  510. wmi_err("WMI_NDP_RESPONDER_REQ_CMDID failed, ret: %d", status);
  511. wmi_buf_free(buf);
  512. }
  513. return status;
  514. }
  515. static QDF_STATUS nan_ndp_end_req_tlv(wmi_unified_t wmi_handle,
  516. struct nan_datapath_end_req *req)
  517. {
  518. uint16_t len;
  519. wmi_buf_t buf;
  520. QDF_STATUS status;
  521. uint32_t ndp_end_req_len, i;
  522. wmi_ndp_end_req *ndp_end_req_lst;
  523. wmi_ndp_end_req_fixed_param *cmd;
  524. /* len of tlv following fixed param */
  525. ndp_end_req_len = sizeof(wmi_ndp_end_req) * req->num_ndp_instances;
  526. /* above comes out to 4 byte alligned already, no need of padding */
  527. len = sizeof(*cmd) + ndp_end_req_len + WMI_TLV_HDR_SIZE;
  528. buf = wmi_buf_alloc(wmi_handle, len);
  529. if (!buf) {
  530. return QDF_STATUS_E_NOMEM;
  531. }
  532. cmd = (wmi_ndp_end_req_fixed_param *) wmi_buf_data(buf);
  533. WMITLV_SET_HDR(&cmd->tlv_header,
  534. WMITLV_TAG_STRUC_wmi_ndp_end_req_fixed_param,
  535. WMITLV_GET_STRUCT_TLVLEN(wmi_ndp_end_req_fixed_param));
  536. cmd->transaction_id = req->transaction_id;
  537. /* set tlv pointer to end of fixed param */
  538. WMITLV_SET_HDR((uint8_t *)&cmd[1], WMITLV_TAG_ARRAY_STRUC,
  539. ndp_end_req_len);
  540. ndp_end_req_lst = (wmi_ndp_end_req *)((uint8_t *)&cmd[1] +
  541. WMI_TLV_HDR_SIZE);
  542. for (i = 0; i < req->num_ndp_instances; i++) {
  543. WMITLV_SET_HDR(&ndp_end_req_lst[i],
  544. WMITLV_TAG_ARRAY_FIXED_STRUC,
  545. (sizeof(*ndp_end_req_lst) - WMI_TLV_HDR_SIZE));
  546. ndp_end_req_lst[i].ndp_instance_id = req->ndp_ids[i];
  547. }
  548. wmi_mtrace(WMI_NDP_END_REQ_CMDID, NO_SESSION, 0);
  549. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  550. WMI_NDP_END_REQ_CMDID);
  551. if (QDF_IS_STATUS_ERROR(status)) {
  552. wmi_err("WMI_NDP_END_REQ_CMDID failed, ret: %d", status);
  553. wmi_buf_free(buf);
  554. }
  555. return status;
  556. }
  557. static QDF_STATUS
  558. extract_ndp_host_event_tlv(wmi_unified_t wmi_handle, uint8_t *data,
  559. struct nan_datapath_host_event *evt)
  560. {
  561. WMI_NDP_EVENTID_param_tlvs *event;
  562. wmi_ndp_event_param *fixed_params;
  563. event = (WMI_NDP_EVENTID_param_tlvs *)data;
  564. fixed_params = event->fixed_param;
  565. evt->vdev =
  566. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  567. fixed_params->vdev_id,
  568. WLAN_NAN_ID);
  569. if (!evt->vdev) {
  570. wmi_err("vdev is null");
  571. return QDF_STATUS_E_INVAL;
  572. }
  573. evt->ndp_termination_in_progress =
  574. fixed_params->ndp_termination_in_progress ? true : false;
  575. return QDF_STATUS_SUCCESS;
  576. }
  577. static QDF_STATUS extract_ndp_initiator_rsp_tlv(wmi_unified_t wmi_handle,
  578. uint8_t *data, struct nan_datapath_initiator_rsp *rsp)
  579. {
  580. WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *event;
  581. wmi_ndp_initiator_rsp_event_fixed_param *fixed_params;
  582. event = (WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *)data;
  583. fixed_params = event->fixed_param;
  584. rsp->vdev =
  585. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  586. fixed_params->vdev_id,
  587. WLAN_NAN_ID);
  588. if (!rsp->vdev) {
  589. wmi_err("vdev is null");
  590. return QDF_STATUS_E_INVAL;
  591. }
  592. rsp->transaction_id = fixed_params->transaction_id;
  593. rsp->ndp_instance_id = fixed_params->ndp_instance_id;
  594. rsp->status = fixed_params->rsp_status;
  595. rsp->reason = fixed_params->reason_code;
  596. return QDF_STATUS_SUCCESS;
  597. }
  598. #define MAX_NAN_MSG_LEN 200
  599. static QDF_STATUS extract_nan_msg_tlv(uint8_t *data,
  600. struct nan_dump_msg *msg)
  601. {
  602. WMI_NAN_DMESG_EVENTID_param_tlvs *event;
  603. wmi_nan_dmesg_event_fixed_param *fixed_params;
  604. event = (WMI_NAN_DMESG_EVENTID_param_tlvs *)data;
  605. fixed_params = (wmi_nan_dmesg_event_fixed_param *)event->fixed_param;
  606. if (!fixed_params->msg_len ||
  607. fixed_params->msg_len > MAX_NAN_MSG_LEN ||
  608. fixed_params->msg_len > event->num_msg)
  609. return QDF_STATUS_E_FAILURE;
  610. msg->data_len = fixed_params->msg_len;
  611. msg->msg = event->msg;
  612. msg->msg[fixed_params->msg_len - 1] = (uint8_t)'\0';
  613. return QDF_STATUS_SUCCESS;
  614. }
  615. static QDF_STATUS extract_ndp_ind_tlv(wmi_unified_t wmi_handle,
  616. uint8_t *data, struct nan_datapath_indication_event *rsp)
  617. {
  618. WMI_NDP_INDICATION_EVENTID_param_tlvs *event;
  619. wmi_ndp_indication_event_fixed_param *fixed_params;
  620. size_t total_array_len;
  621. event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)data;
  622. fixed_params =
  623. (wmi_ndp_indication_event_fixed_param *)event->fixed_param;
  624. if (fixed_params->ndp_cfg_len > event->num_ndp_cfg) {
  625. wmi_err("FW message ndp cfg length %d larger than TLV hdr %d",
  626. fixed_params->ndp_cfg_len, event->num_ndp_cfg);
  627. return QDF_STATUS_E_INVAL;
  628. }
  629. if (fixed_params->ndp_app_info_len > event->num_ndp_app_info) {
  630. wmi_err("FW message ndp app info length %d more than TLV hdr %d",
  631. fixed_params->ndp_app_info_len,
  632. event->num_ndp_app_info);
  633. return QDF_STATUS_E_INVAL;
  634. }
  635. if (fixed_params->nan_scid_len > event->num_ndp_scid) {
  636. wmi_err("FW msg ndp scid info len %d more than TLV hdr %d",
  637. fixed_params->nan_scid_len,
  638. event->num_ndp_scid);
  639. return QDF_STATUS_E_INVAL;
  640. }
  641. if (fixed_params->ndp_cfg_len >
  642. (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) {
  643. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  644. fixed_params->ndp_cfg_len);
  645. return QDF_STATUS_E_INVAL;
  646. }
  647. total_array_len = fixed_params->ndp_cfg_len +
  648. sizeof(*fixed_params);
  649. if (fixed_params->ndp_app_info_len >
  650. (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
  651. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  652. fixed_params->ndp_app_info_len);
  653. return QDF_STATUS_E_INVAL;
  654. }
  655. total_array_len += fixed_params->ndp_app_info_len;
  656. if (fixed_params->nan_scid_len >
  657. (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
  658. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  659. fixed_params->nan_scid_len);
  660. return QDF_STATUS_E_INVAL;
  661. }
  662. rsp->vdev =
  663. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  664. fixed_params->vdev_id,
  665. WLAN_NAN_ID);
  666. if (!rsp->vdev) {
  667. wmi_err("vdev is null");
  668. return QDF_STATUS_E_INVAL;
  669. }
  670. rsp->service_instance_id = fixed_params->service_instance_id;
  671. rsp->ndp_instance_id = fixed_params->ndp_instance_id;
  672. rsp->role = fixed_params->self_ndp_role;
  673. rsp->policy = fixed_params->accept_policy;
  674. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
  675. rsp->peer_mac_addr.bytes);
  676. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_discovery_mac_addr,
  677. rsp->peer_discovery_mac_addr.bytes);
  678. wmi_debug("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",
  679. WMI_NDP_INDICATION_EVENTID, fixed_params->vdev_id,
  680. fixed_params->service_instance_id,
  681. fixed_params->ndp_instance_id, fixed_params->self_ndp_role,
  682. fixed_params->accept_policy, fixed_params->nan_csid,
  683. fixed_params->nan_scid_len,
  684. QDF_MAC_ADDR_REF(rsp->peer_mac_addr.bytes),
  685. QDF_MAC_ADDR_REF(rsp->peer_discovery_mac_addr.bytes),
  686. fixed_params->ndp_cfg_len,
  687. fixed_params->ndp_app_info_len);
  688. rsp->ncs_sk_type = fixed_params->nan_csid;
  689. if (event->ndp_cfg) {
  690. rsp->ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len;
  691. if (rsp->ndp_config.ndp_cfg_len > NDP_QOS_INFO_LEN)
  692. rsp->ndp_config.ndp_cfg_len = NDP_QOS_INFO_LEN;
  693. qdf_mem_copy(rsp->ndp_config.ndp_cfg, event->ndp_cfg,
  694. rsp->ndp_config.ndp_cfg_len);
  695. }
  696. if (event->ndp_app_info) {
  697. rsp->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len;
  698. if (rsp->ndp_info.ndp_app_info_len > NDP_APP_INFO_LEN)
  699. rsp->ndp_info.ndp_app_info_len = NDP_APP_INFO_LEN;
  700. qdf_mem_copy(rsp->ndp_info.ndp_app_info, event->ndp_app_info,
  701. rsp->ndp_info.ndp_app_info_len);
  702. }
  703. if (event->ndp_scid) {
  704. rsp->scid.scid_len = fixed_params->nan_scid_len;
  705. if (rsp->scid.scid_len > NDP_SCID_BUF_LEN)
  706. rsp->scid.scid_len = NDP_SCID_BUF_LEN;
  707. qdf_mem_copy(rsp->scid.scid, event->ndp_scid,
  708. rsp->scid.scid_len);
  709. }
  710. if (event->ndp_transport_ip_param &&
  711. event->num_ndp_transport_ip_param) {
  712. if (event->ndp_transport_ip_param->ipv6_addr_present) {
  713. rsp->is_ipv6_addr_present = true;
  714. qdf_mem_copy(rsp->ipv6_addr,
  715. event->ndp_transport_ip_param->ipv6_intf_addr,
  716. WMI_NDP_IPV6_INTF_ADDR_LEN);
  717. }
  718. }
  719. wmi_debug("IPv6 addr present: %d, addr: %pI6",
  720. rsp->is_ipv6_addr_present, rsp->ipv6_addr);
  721. return QDF_STATUS_SUCCESS;
  722. }
  723. static QDF_STATUS extract_ndp_confirm_tlv(wmi_unified_t wmi_handle,
  724. uint8_t *data, struct nan_datapath_confirm_event *rsp)
  725. {
  726. uint8_t i;
  727. WMI_HOST_WLAN_PHY_MODE ch_mode;
  728. WMI_NDP_CONFIRM_EVENTID_param_tlvs *event;
  729. wmi_ndp_confirm_event_fixed_param *fixed_params;
  730. size_t total_array_len;
  731. bool ndi_dbs = wmi_service_enabled(wmi_handle,
  732. wmi_service_ndi_dbs_support);
  733. event = (WMI_NDP_CONFIRM_EVENTID_param_tlvs *) data;
  734. fixed_params = (wmi_ndp_confirm_event_fixed_param *)event->fixed_param;
  735. wmi_debug("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",
  736. WMI_NDP_CONFIRM_EVENTID, fixed_params->vdev_id,
  737. fixed_params->ndp_instance_id, fixed_params->rsp_code,
  738. fixed_params->reason_code,
  739. fixed_params->num_active_ndps_on_peer,
  740. fixed_params->num_ndp_channels);
  741. if (fixed_params->ndp_cfg_len > event->num_ndp_cfg) {
  742. wmi_err("FW message ndp cfg length %d larger than TLV hdr %d",
  743. fixed_params->ndp_cfg_len, event->num_ndp_cfg);
  744. return QDF_STATUS_E_INVAL;
  745. }
  746. if (fixed_params->ndp_app_info_len > event->num_ndp_app_info) {
  747. wmi_err("FW message ndp app info length %d more than TLV hdr %d",
  748. fixed_params->ndp_app_info_len,
  749. event->num_ndp_app_info);
  750. return QDF_STATUS_E_INVAL;
  751. }
  752. wmi_debug("ndp_cfg - %d bytes, ndp_app_info - %d bytes",
  753. fixed_params->ndp_cfg_len, fixed_params->ndp_app_info_len);
  754. if (fixed_params->ndp_cfg_len >
  755. (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) {
  756. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  757. fixed_params->ndp_cfg_len);
  758. return QDF_STATUS_E_INVAL;
  759. }
  760. total_array_len = fixed_params->ndp_cfg_len +
  761. sizeof(*fixed_params);
  762. if (fixed_params->ndp_app_info_len >
  763. (WMI_SVC_MSG_MAX_SIZE - total_array_len)) {
  764. wmi_err("excess wmi buffer: ndp_cfg_len %d",
  765. fixed_params->ndp_app_info_len);
  766. return QDF_STATUS_E_INVAL;
  767. }
  768. if (fixed_params->num_ndp_channels > event->num_ndp_channel_list ||
  769. fixed_params->num_ndp_channels > event->num_nss_list) {
  770. wmi_err("NDP Ch count %d greater than NDP Ch TLV len(%d) or NSS TLV len(%d)",
  771. fixed_params->num_ndp_channels,
  772. event->num_ndp_channel_list,
  773. event->num_nss_list);
  774. return QDF_STATUS_E_INVAL;
  775. }
  776. if (ndi_dbs &&
  777. fixed_params->num_ndp_channels > event->num_ndp_channel_info) {
  778. wmi_err("NDP Ch count %d greater than NDP Ch info(%d)",
  779. fixed_params->num_ndp_channels,
  780. event->num_ndp_channel_info);
  781. return QDF_STATUS_E_INVAL;
  782. }
  783. rsp->vdev =
  784. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  785. fixed_params->vdev_id,
  786. WLAN_NAN_ID);
  787. if (!rsp->vdev) {
  788. wmi_err("vdev is null");
  789. return QDF_STATUS_E_INVAL;
  790. }
  791. rsp->ndp_instance_id = fixed_params->ndp_instance_id;
  792. rsp->rsp_code = fixed_params->rsp_code;
  793. rsp->reason_code = fixed_params->reason_code;
  794. rsp->num_active_ndps_on_peer = fixed_params->num_active_ndps_on_peer;
  795. rsp->num_channels = fixed_params->num_ndp_channels;
  796. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
  797. rsp->peer_ndi_mac_addr.bytes);
  798. rsp->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len;
  799. if (rsp->ndp_info.ndp_app_info_len > NDP_APP_INFO_LEN)
  800. rsp->ndp_info.ndp_app_info_len = NDP_APP_INFO_LEN;
  801. qdf_mem_copy(rsp->ndp_info.ndp_app_info, event->ndp_app_info,
  802. rsp->ndp_info.ndp_app_info_len);
  803. if (rsp->num_channels > NAN_CH_INFO_MAX_CHANNELS) {
  804. wmi_err("too many channels");
  805. rsp->num_channels = NAN_CH_INFO_MAX_CHANNELS;
  806. }
  807. for (i = 0; i < rsp->num_channels; i++) {
  808. rsp->ch[i].freq = event->ndp_channel_list[i].mhz;
  809. rsp->ch[i].nss = event->nss_list[i];
  810. ch_mode = WMI_GET_CHANNEL_MODE(&event->ndp_channel_list[i]);
  811. rsp->ch[i].ch_width = wmi_get_ch_width_from_phy_mode(wmi_handle,
  812. ch_mode);
  813. if (ndi_dbs) {
  814. rsp->ch[i].mac_id = event->ndp_channel_info[i].mac_id;
  815. wmi_debug("Freq: %d, ch_mode: %d, nss: %d mac_id: %d",
  816. rsp->ch[i].freq, rsp->ch[i].ch_width,
  817. rsp->ch[i].nss, rsp->ch[i].mac_id);
  818. } else {
  819. wmi_debug("Freq: %d, ch_mode: %d, nss: %d",
  820. rsp->ch[i].freq, rsp->ch[i].ch_width,
  821. rsp->ch[i].nss);
  822. }
  823. }
  824. if (event->ndp_transport_ip_param &&
  825. event->num_ndp_transport_ip_param) {
  826. if (event->ndp_transport_ip_param->ipv6_addr_present) {
  827. rsp->is_ipv6_addr_present = true;
  828. qdf_mem_copy(rsp->ipv6_addr,
  829. event->ndp_transport_ip_param->ipv6_intf_addr,
  830. WMI_NDP_IPV6_INTF_ADDR_LEN);
  831. }
  832. if (event->ndp_transport_ip_param->trans_port_present) {
  833. rsp->is_port_present = true;
  834. rsp->port =
  835. event->ndp_transport_ip_param->transport_port;
  836. }
  837. if (event->ndp_transport_ip_param->trans_proto_present) {
  838. rsp->is_protocol_present = true;
  839. rsp->protocol =
  840. event->ndp_transport_ip_param->transport_protocol;
  841. }
  842. }
  843. wmi_debug("IPv6 addr present: %d, addr: %pI6 port: %d present: %d protocol: %d present: %d",
  844. rsp->is_ipv6_addr_present, rsp->ipv6_addr, rsp->port,
  845. rsp->is_port_present, rsp->protocol, rsp->is_protocol_present);
  846. return QDF_STATUS_SUCCESS;
  847. }
  848. static QDF_STATUS extract_ndp_responder_rsp_tlv(wmi_unified_t wmi_handle,
  849. uint8_t *data, struct nan_datapath_responder_rsp *rsp)
  850. {
  851. WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *event;
  852. wmi_ndp_responder_rsp_event_fixed_param *fixed_params;
  853. event = (WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *)data;
  854. fixed_params = event->fixed_param;
  855. rsp->vdev =
  856. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  857. fixed_params->vdev_id,
  858. WLAN_NAN_ID);
  859. if (!rsp->vdev) {
  860. wmi_err("vdev is null");
  861. return QDF_STATUS_E_INVAL;
  862. }
  863. rsp->transaction_id = fixed_params->transaction_id;
  864. rsp->reason = fixed_params->reason_code;
  865. rsp->status = fixed_params->rsp_status;
  866. rsp->create_peer = fixed_params->create_peer;
  867. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr,
  868. rsp->peer_mac_addr.bytes);
  869. wmi_debug("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",
  870. WMI_NDP_RESPONDER_RSP_EVENTID, fixed_params->vdev_id,
  871. QDF_MAC_ADDR_REF(rsp->peer_mac_addr.bytes),
  872. rsp->transaction_id,
  873. rsp->status, rsp->reason, rsp->create_peer);
  874. return QDF_STATUS_SUCCESS;
  875. }
  876. static QDF_STATUS extract_ndp_end_rsp_tlv(wmi_unified_t wmi_handle,
  877. uint8_t *data, struct nan_datapath_end_rsp_event *rsp)
  878. {
  879. WMI_NDP_END_RSP_EVENTID_param_tlvs *event;
  880. wmi_ndp_end_rsp_event_fixed_param *fixed_params = NULL;
  881. event = (WMI_NDP_END_RSP_EVENTID_param_tlvs *) data;
  882. fixed_params = (wmi_ndp_end_rsp_event_fixed_param *)event->fixed_param;
  883. wmi_debug("WMI_NDP_END_RSP_EVENTID(0x%X) received. transaction_id: %d, rsp_status: %d, reason_code: %d",
  884. WMI_NDP_END_RSP_EVENTID, fixed_params->transaction_id,
  885. fixed_params->rsp_status, fixed_params->reason_code);
  886. rsp->vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc(
  887. wmi_handle->soc->wmi_psoc, QDF_NDI_MODE, WLAN_NAN_ID);
  888. if (!rsp->vdev) {
  889. wmi_err("vdev is null");
  890. return QDF_STATUS_E_INVAL;
  891. }
  892. rsp->transaction_id = fixed_params->transaction_id;
  893. rsp->reason = fixed_params->reason_code;
  894. rsp->status = fixed_params->rsp_status;
  895. return QDF_STATUS_SUCCESS;
  896. }
  897. static QDF_STATUS extract_ndp_end_ind_tlv(wmi_unified_t wmi_handle,
  898. uint8_t *data, struct nan_datapath_end_indication_event **rsp)
  899. {
  900. uint32_t i, buf_size;
  901. wmi_ndp_end_indication *ind;
  902. struct qdf_mac_addr peer_addr;
  903. WMI_NDP_END_INDICATION_EVENTID_param_tlvs *event;
  904. event = (WMI_NDP_END_INDICATION_EVENTID_param_tlvs *) data;
  905. ind = event->ndp_end_indication_list;
  906. if (event->num_ndp_end_indication_list == 0) {
  907. wmi_err("Error: Event ignored, 0 ndp instances");
  908. return QDF_STATUS_E_INVAL;
  909. }
  910. wmi_debug("number of ndp instances = %d",
  911. event->num_ndp_end_indication_list);
  912. if (event->num_ndp_end_indication_list > ((UINT_MAX - sizeof(**rsp))/
  913. sizeof((*rsp)->ndp_map[0]))) {
  914. wmi_err("num_ndp_end_ind_list %d too large",
  915. event->num_ndp_end_indication_list);
  916. return QDF_STATUS_E_INVAL;
  917. }
  918. buf_size = sizeof(**rsp) + event->num_ndp_end_indication_list *
  919. sizeof((*rsp)->ndp_map[0]);
  920. *rsp = qdf_mem_malloc(buf_size);
  921. if (!(*rsp))
  922. return QDF_STATUS_E_NOMEM;
  923. (*rsp)->num_ndp_ids = event->num_ndp_end_indication_list;
  924. for (i = 0; i < (*rsp)->num_ndp_ids; i++) {
  925. WMI_MAC_ADDR_TO_CHAR_ARRAY(&ind[i].peer_ndi_mac_addr,
  926. peer_addr.bytes);
  927. wmi_debug("ind[%d]: type %d, reason_code %d, instance_id %d num_active %d ",
  928. i, ind[i].type, ind[i].reason_code,
  929. ind[i].ndp_instance_id,
  930. ind[i].num_active_ndps_on_peer);
  931. /* Add each instance entry to the list */
  932. (*rsp)->ndp_map[i].ndp_instance_id = ind[i].ndp_instance_id;
  933. (*rsp)->ndp_map[i].vdev_id = ind[i].vdev_id;
  934. WMI_MAC_ADDR_TO_CHAR_ARRAY(&ind[i].peer_ndi_mac_addr,
  935. (*rsp)->ndp_map[i].peer_ndi_mac_addr.bytes);
  936. (*rsp)->ndp_map[i].num_active_ndp_sessions =
  937. ind[i].num_active_ndps_on_peer;
  938. (*rsp)->ndp_map[i].type = ind[i].type;
  939. (*rsp)->ndp_map[i].reason_code = ind[i].reason_code;
  940. }
  941. return QDF_STATUS_SUCCESS;
  942. }
  943. static QDF_STATUS extract_ndp_sch_update_tlv(wmi_unified_t wmi_handle,
  944. uint8_t *data, struct nan_datapath_sch_update_event *ind)
  945. {
  946. uint8_t i;
  947. WMI_HOST_WLAN_PHY_MODE ch_mode;
  948. WMI_NDL_SCHEDULE_UPDATE_EVENTID_param_tlvs *event;
  949. wmi_ndl_schedule_update_fixed_param *fixed_params;
  950. bool ndi_dbs = wmi_service_enabled(wmi_handle,
  951. wmi_service_ndi_dbs_support);
  952. event = (WMI_NDL_SCHEDULE_UPDATE_EVENTID_param_tlvs *)data;
  953. fixed_params = event->fixed_param;
  954. wmi_debug("flags: %d, num_ch: %d, num_ndp_instances: %d",
  955. fixed_params->flags, fixed_params->num_channels,
  956. fixed_params->num_ndp_instances);
  957. if (fixed_params->num_channels > event->num_ndl_channel_list ||
  958. fixed_params->num_channels > event->num_nss_list) {
  959. wmi_err("Channel count %d greater than NDP Ch list TLV len(%d) or NSS list TLV len(%d)",
  960. fixed_params->num_channels,
  961. event->num_ndl_channel_list,
  962. event->num_nss_list);
  963. return QDF_STATUS_E_INVAL;
  964. }
  965. if (ndi_dbs &&
  966. fixed_params->num_channels > event->num_ndp_channel_info) {
  967. wmi_err("Channel count %d greater than NDP Ch info(%d)",
  968. fixed_params->num_channels,
  969. event->num_ndp_channel_info);
  970. return QDF_STATUS_E_INVAL;
  971. }
  972. if (fixed_params->num_ndp_instances > event->num_ndp_instance_list) {
  973. wmi_err("NDP Instance count %d greater than NDP Instancei TLV len %d",
  974. fixed_params->num_ndp_instances,
  975. event->num_ndp_instance_list);
  976. return QDF_STATUS_E_INVAL;
  977. }
  978. ind->vdev =
  979. wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc,
  980. fixed_params->vdev_id,
  981. WLAN_NAN_ID);
  982. if (!ind->vdev) {
  983. wmi_err("vdev is null");
  984. return QDF_STATUS_E_INVAL;
  985. }
  986. ind->flags = fixed_params->flags;
  987. ind->num_channels = fixed_params->num_channels;
  988. ind->num_ndp_instances = fixed_params->num_ndp_instances;
  989. WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_macaddr,
  990. ind->peer_addr.bytes);
  991. if (ind->num_ndp_instances > NDP_NUM_INSTANCE_ID) {
  992. wmi_err("uint32 overflow");
  993. wlan_objmgr_vdev_release_ref(ind->vdev, WLAN_NAN_ID);
  994. return QDF_STATUS_E_INVAL;
  995. }
  996. qdf_mem_copy(ind->ndp_instances, event->ndp_instance_list,
  997. sizeof(uint32_t) * ind->num_ndp_instances);
  998. if (ind->num_channels > NAN_CH_INFO_MAX_CHANNELS) {
  999. wmi_err("too many channels");
  1000. ind->num_channels = NAN_CH_INFO_MAX_CHANNELS;
  1001. }
  1002. for (i = 0; i < ind->num_channels; i++) {
  1003. ind->ch[i].freq = event->ndl_channel_list[i].mhz;
  1004. ind->ch[i].nss = event->nss_list[i];
  1005. ch_mode = WMI_GET_CHANNEL_MODE(&event->ndl_channel_list[i]);
  1006. ind->ch[i].ch_width = wmi_get_ch_width_from_phy_mode(wmi_handle,
  1007. ch_mode);
  1008. if (ndi_dbs) {
  1009. ind->ch[i].mac_id = event->ndp_channel_info[i].mac_id;
  1010. wmi_debug("Freq: %d, ch_mode: %d, nss: %d mac_id: %d",
  1011. ind->ch[i].freq, ind->ch[i].ch_width,
  1012. ind->ch[i].nss, ind->ch[i].mac_id);
  1013. } else {
  1014. wmi_debug("Freq: %d, ch_mode: %d, nss: %d",
  1015. ind->ch[i].freq, ind->ch[i].ch_width,
  1016. ind->ch[i].nss);
  1017. }
  1018. }
  1019. for (i = 0; i < fixed_params->num_ndp_instances; i++)
  1020. wmi_debug("instance_id[%d]: %d",
  1021. i, event->ndp_instance_list[i]);
  1022. return QDF_STATUS_SUCCESS;
  1023. }
  1024. void wmi_nan_attach_tlv(wmi_unified_t wmi_handle)
  1025. {
  1026. struct wmi_ops *ops = wmi_handle->ops;
  1027. ops->send_nan_req_cmd = send_nan_req_cmd_tlv;
  1028. ops->send_nan_disable_req_cmd = send_nan_disable_req_cmd_tlv;
  1029. ops->extract_nan_event_rsp = extract_nan_event_rsp_tlv;
  1030. ops->send_terminate_all_ndps_req_cmd = send_terminate_all_ndps_cmd_tlv;
  1031. ops->send_ndp_initiator_req_cmd = nan_ndp_initiator_req_tlv;
  1032. ops->send_ndp_responder_req_cmd = nan_ndp_responder_req_tlv;
  1033. ops->send_ndp_end_req_cmd = nan_ndp_end_req_tlv;
  1034. ops->extract_ndp_initiator_rsp = extract_ndp_initiator_rsp_tlv;
  1035. ops->extract_ndp_ind = extract_ndp_ind_tlv;
  1036. ops->extract_nan_msg = extract_nan_msg_tlv,
  1037. ops->extract_ndp_confirm = extract_ndp_confirm_tlv;
  1038. ops->extract_ndp_responder_rsp = extract_ndp_responder_rsp_tlv;
  1039. ops->extract_ndp_end_rsp = extract_ndp_end_rsp_tlv;
  1040. ops->extract_ndp_end_ind = extract_ndp_end_ind_tlv;
  1041. ops->extract_ndp_sch_update = extract_ndp_sch_update_tlv;
  1042. ops->extract_ndp_host_event = extract_ndp_host_event_tlv;
  1043. }