1 2 /* 3 * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <osdep.h> 21 #include <wmi.h> 22 #include <wmi_unified_priv.h> 23 #include <nan_public_structs.h> 24 #include <wmi_unified_nan_api.h> 25 26 static QDF_STATUS nan_ndp_initiator_req_tlv(wmi_unified_t wmi_handle, 27 struct nan_datapath_initiator_req *ndp_req) 28 { 29 uint16_t len; 30 wmi_buf_t buf; 31 uint8_t *tlv_ptr; 32 QDF_STATUS status; 33 wmi_channel *ch_tlv; 34 wmi_ndp_initiator_req_fixed_param *cmd; 35 uint32_t passphrase_len, service_name_len; 36 uint32_t ndp_cfg_len, ndp_app_info_len, pmk_len; 37 wmi_ndp_transport_ip_param *tcp_ip_param; 38 39 /* 40 * WMI command expects 4 byte alligned len: 41 * round up ndp_cfg_len and ndp_app_info_len to 4 bytes 42 */ 43 ndp_cfg_len = qdf_roundup(ndp_req->ndp_config.ndp_cfg_len, 4); 44 ndp_app_info_len = qdf_roundup(ndp_req->ndp_info.ndp_app_info_len, 4); 45 pmk_len = qdf_roundup(ndp_req->pmk.pmk_len, 4); 46 passphrase_len = qdf_roundup(ndp_req->passphrase.passphrase_len, 4); 47 service_name_len = 48 qdf_roundup(ndp_req->service_name.service_name_len, 4); 49 /* allocated memory for fixed params as well as variable size data */ 50 len = sizeof(*cmd) + sizeof(*ch_tlv) + (5 * WMI_TLV_HDR_SIZE) 51 + ndp_cfg_len + ndp_app_info_len + pmk_len 52 + passphrase_len + service_name_len; 53 54 if (ndp_req->is_ipv6_addr_present) 55 len += sizeof(*tcp_ip_param); 56 57 buf = wmi_buf_alloc(wmi_handle, len); 58 if (!buf) { 59 return QDF_STATUS_E_NOMEM; 60 } 61 62 cmd = (wmi_ndp_initiator_req_fixed_param *) wmi_buf_data(buf); 63 WMITLV_SET_HDR(&cmd->tlv_header, 64 WMITLV_TAG_STRUC_wmi_ndp_initiator_req_fixed_param, 65 WMITLV_GET_STRUCT_TLVLEN( 66 wmi_ndp_initiator_req_fixed_param)); 67 cmd->vdev_id = wlan_vdev_get_id(ndp_req->vdev); 68 cmd->transaction_id = ndp_req->transaction_id; 69 cmd->service_instance_id = ndp_req->service_instance_id; 70 WMI_CHAR_ARRAY_TO_MAC_ADDR(ndp_req->peer_discovery_mac_addr.bytes, 71 &cmd->peer_discovery_mac_addr); 72 73 cmd->ndp_cfg_len = ndp_req->ndp_config.ndp_cfg_len; 74 cmd->ndp_app_info_len = ndp_req->ndp_info.ndp_app_info_len; 75 cmd->ndp_channel_cfg = ndp_req->channel_cfg; 76 cmd->nan_pmk_len = ndp_req->pmk.pmk_len; 77 cmd->nan_csid = ndp_req->ncs_sk_type; 78 cmd->nan_passphrase_len = ndp_req->passphrase.passphrase_len; 79 cmd->nan_servicename_len = ndp_req->service_name.service_name_len; 80 81 ch_tlv = (wmi_channel *)&cmd[1]; 82 WMITLV_SET_HDR(ch_tlv, WMITLV_TAG_STRUC_wmi_channel, 83 WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); 84 ch_tlv->mhz = ndp_req->channel; 85 tlv_ptr = (uint8_t *)&ch_tlv[1]; 86 87 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len); 88 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], 89 ndp_req->ndp_config.ndp_cfg, cmd->ndp_cfg_len); 90 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len; 91 92 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len); 93 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], 94 ndp_req->ndp_info.ndp_app_info, cmd->ndp_app_info_len); 95 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len; 96 97 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len); 98 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], ndp_req->pmk.pmk, 99 cmd->nan_pmk_len); 100 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len; 101 102 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, passphrase_len); 103 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], ndp_req->passphrase.passphrase, 104 cmd->nan_passphrase_len); 105 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + passphrase_len; 106 107 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, service_name_len); 108 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], 109 ndp_req->service_name.service_name, 110 cmd->nan_servicename_len); 111 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + service_name_len; 112 113 if (ndp_req->is_ipv6_addr_present) { 114 tcp_ip_param = (wmi_ndp_transport_ip_param *)tlv_ptr; 115 WMITLV_SET_HDR(tcp_ip_param, 116 WMITLV_TAG_STRUC_wmi_ndp_transport_ip_param, 117 WMITLV_GET_STRUCT_TLVLEN( 118 wmi_ndp_transport_ip_param)); 119 tcp_ip_param->ipv6_addr_present = true; 120 qdf_mem_copy(tcp_ip_param->ipv6_intf_addr, 121 ndp_req->ipv6_addr, WMI_NDP_IPV6_INTF_ADDR_LEN); 122 } 123 WMI_LOGD(FL("IPv6 addr present: %d, addr: %pI6"), 124 ndp_req->is_ipv6_addr_present, ndp_req->ipv6_addr); 125 126 WMI_LOGD("vdev_id = %d, transaction_id: %d, service_instance_id: %d, ch: %d, ch_cfg: %d, csid: %d", 127 cmd->vdev_id, cmd->transaction_id, cmd->service_instance_id, 128 ch_tlv->mhz, cmd->ndp_channel_cfg, cmd->nan_csid); 129 WMI_LOGD("peer mac addr: mac_addr31to0: 0x%x, mac_addr47to32: 0x%x", 130 cmd->peer_discovery_mac_addr.mac_addr31to0, 131 cmd->peer_discovery_mac_addr.mac_addr47to32); 132 133 WMI_LOGD("ndp_config len: %d", cmd->ndp_cfg_len); 134 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 135 ndp_req->ndp_config.ndp_cfg, 136 ndp_req->ndp_config.ndp_cfg_len); 137 138 WMI_LOGD("ndp_app_info len: %d", cmd->ndp_app_info_len); 139 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 140 ndp_req->ndp_info.ndp_app_info, 141 ndp_req->ndp_info.ndp_app_info_len); 142 143 WMI_LOGD("pmk len: %d", cmd->nan_pmk_len); 144 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 145 ndp_req->pmk.pmk, cmd->nan_pmk_len); 146 147 WMI_LOGD("pass phrase len: %d", cmd->nan_passphrase_len); 148 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 149 ndp_req->passphrase.passphrase, 150 cmd->nan_passphrase_len); 151 152 WMI_LOGD("service name len: %d", cmd->nan_servicename_len); 153 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 154 ndp_req->service_name.service_name, 155 cmd->nan_servicename_len); 156 157 WMI_LOGD("sending WMI_NDP_INITIATOR_REQ_CMDID(0x%X)", 158 WMI_NDP_INITIATOR_REQ_CMDID); 159 160 wmi_mtrace(WMI_NDP_INITIATOR_REQ_CMDID, cmd->vdev_id, 0); 161 status = wmi_unified_cmd_send(wmi_handle, buf, len, 162 WMI_NDP_INITIATOR_REQ_CMDID); 163 if (QDF_IS_STATUS_ERROR(status)) { 164 WMI_LOGE("WMI_NDP_INITIATOR_REQ_CMDID failed, ret: %d", status); 165 wmi_buf_free(buf); 166 } 167 168 return status; 169 } 170 171 static QDF_STATUS nan_ndp_responder_req_tlv(wmi_unified_t wmi_handle, 172 struct nan_datapath_responder_req *req) 173 { 174 uint16_t len; 175 wmi_buf_t buf; 176 uint8_t *tlv_ptr; 177 QDF_STATUS status; 178 wmi_ndp_responder_req_fixed_param *cmd; 179 wmi_ndp_transport_ip_param *tcp_ip_param; 180 uint32_t passphrase_len, service_name_len; 181 uint32_t vdev_id = 0, ndp_cfg_len, ndp_app_info_len, pmk_len; 182 183 vdev_id = wlan_vdev_get_id(req->vdev); 184 WMI_LOGD("vdev_id: %d, transaction_id: %d, ndp_rsp %d, ndp_instance_id: %d, ndp_app_info_len: %d", 185 vdev_id, req->transaction_id, 186 req->ndp_rsp, 187 req->ndp_instance_id, 188 req->ndp_info.ndp_app_info_len); 189 190 /* 191 * WMI command expects 4 byte alligned len: 192 * round up ndp_cfg_len and ndp_app_info_len to 4 bytes 193 */ 194 ndp_cfg_len = qdf_roundup(req->ndp_config.ndp_cfg_len, 4); 195 ndp_app_info_len = qdf_roundup(req->ndp_info.ndp_app_info_len, 4); 196 pmk_len = qdf_roundup(req->pmk.pmk_len, 4); 197 passphrase_len = qdf_roundup(req->passphrase.passphrase_len, 4); 198 service_name_len = 199 qdf_roundup(req->service_name.service_name_len, 4); 200 201 /* allocated memory for fixed params as well as variable size data */ 202 len = sizeof(*cmd) + 5*WMI_TLV_HDR_SIZE + ndp_cfg_len + ndp_app_info_len 203 + pmk_len + passphrase_len + service_name_len; 204 205 if (req->is_ipv6_addr_present || req->is_port_present || 206 req->is_protocol_present) 207 len += sizeof(*tcp_ip_param); 208 209 buf = wmi_buf_alloc(wmi_handle, len); 210 if (!buf) { 211 return QDF_STATUS_E_NOMEM; 212 } 213 cmd = (wmi_ndp_responder_req_fixed_param *) wmi_buf_data(buf); 214 WMITLV_SET_HDR(&cmd->tlv_header, 215 WMITLV_TAG_STRUC_wmi_ndp_responder_req_fixed_param, 216 WMITLV_GET_STRUCT_TLVLEN( 217 wmi_ndp_responder_req_fixed_param)); 218 cmd->vdev_id = vdev_id; 219 cmd->transaction_id = req->transaction_id; 220 cmd->ndp_instance_id = req->ndp_instance_id; 221 cmd->rsp_code = req->ndp_rsp; 222 cmd->ndp_cfg_len = req->ndp_config.ndp_cfg_len; 223 cmd->ndp_app_info_len = req->ndp_info.ndp_app_info_len; 224 cmd->nan_pmk_len = req->pmk.pmk_len; 225 cmd->nan_csid = req->ncs_sk_type; 226 cmd->nan_passphrase_len = req->passphrase.passphrase_len; 227 cmd->nan_servicename_len = req->service_name.service_name_len; 228 229 tlv_ptr = (uint8_t *)&cmd[1]; 230 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len); 231 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], 232 req->ndp_config.ndp_cfg, cmd->ndp_cfg_len); 233 234 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len; 235 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len); 236 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], 237 req->ndp_info.ndp_app_info, 238 req->ndp_info.ndp_app_info_len); 239 240 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len; 241 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len); 242 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], req->pmk.pmk, 243 cmd->nan_pmk_len); 244 245 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len; 246 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, passphrase_len); 247 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], 248 req->passphrase.passphrase, 249 cmd->nan_passphrase_len); 250 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + passphrase_len; 251 252 WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, service_name_len); 253 qdf_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], 254 req->service_name.service_name, 255 cmd->nan_servicename_len); 256 257 tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + service_name_len; 258 259 if (req->is_ipv6_addr_present || req->is_port_present || 260 req->is_protocol_present) { 261 tcp_ip_param = (wmi_ndp_transport_ip_param *)tlv_ptr; 262 WMITLV_SET_HDR(tcp_ip_param, 263 WMITLV_TAG_STRUC_wmi_ndp_transport_ip_param, 264 WMITLV_GET_STRUCT_TLVLEN( 265 wmi_ndp_transport_ip_param)); 266 tcp_ip_param->ipv6_addr_present = req->is_ipv6_addr_present; 267 qdf_mem_copy(tcp_ip_param->ipv6_intf_addr, 268 req->ipv6_addr, WMI_NDP_IPV6_INTF_ADDR_LEN); 269 270 tcp_ip_param->trans_port_present = req->is_port_present; 271 tcp_ip_param->transport_port = req->port; 272 273 tcp_ip_param->trans_proto_present = req->is_protocol_present; 274 tcp_ip_param->transport_protocol = req->protocol; 275 } 276 WMI_LOGD(FL("IPv6 addr present: %d, addr: %pI6"), 277 req->is_ipv6_addr_present, req->ipv6_addr); 278 WMI_LOGD(FL("port: %d present: %d"), req->is_port_present, req->port); 279 WMI_LOGD(FL("protocol: %d present: %d"), 280 req->is_protocol_present, req->protocol); 281 282 WMI_LOGD("vdev_id = %d, transaction_id: %d, csid: %d", 283 cmd->vdev_id, cmd->transaction_id, cmd->nan_csid); 284 285 WMI_LOGD("ndp_config len: %d", 286 req->ndp_config.ndp_cfg_len); 287 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 288 req->ndp_config.ndp_cfg, 289 req->ndp_config.ndp_cfg_len); 290 291 WMI_LOGD("ndp_app_info len: %d", 292 req->ndp_info.ndp_app_info_len); 293 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 294 req->ndp_info.ndp_app_info, 295 req->ndp_info.ndp_app_info_len); 296 297 WMI_LOGD("pmk len: %d", cmd->nan_pmk_len); 298 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 299 req->pmk.pmk, cmd->nan_pmk_len); 300 301 WMI_LOGD("pass phrase len: %d", cmd->nan_passphrase_len); 302 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 303 req->passphrase.passphrase, 304 cmd->nan_passphrase_len); 305 306 WMI_LOGD("service name len: %d", cmd->nan_servicename_len); 307 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 308 req->service_name.service_name, 309 cmd->nan_servicename_len); 310 311 WMI_LOGD("sending WMI_NDP_RESPONDER_REQ_CMDID(0x%X)", 312 WMI_NDP_RESPONDER_REQ_CMDID); 313 wmi_mtrace(WMI_NDP_RESPONDER_REQ_CMDID, cmd->vdev_id, 0); 314 status = wmi_unified_cmd_send(wmi_handle, buf, len, 315 WMI_NDP_RESPONDER_REQ_CMDID); 316 if (QDF_IS_STATUS_ERROR(status)) { 317 WMI_LOGE("WMI_NDP_RESPONDER_REQ_CMDID failed, ret: %d", status); 318 wmi_buf_free(buf); 319 } 320 return status; 321 } 322 323 static QDF_STATUS nan_ndp_end_req_tlv(wmi_unified_t wmi_handle, 324 struct nan_datapath_end_req *req) 325 { 326 uint16_t len; 327 wmi_buf_t buf; 328 QDF_STATUS status; 329 uint32_t ndp_end_req_len, i; 330 wmi_ndp_end_req *ndp_end_req_lst; 331 wmi_ndp_end_req_fixed_param *cmd; 332 333 /* len of tlv following fixed param */ 334 ndp_end_req_len = sizeof(wmi_ndp_end_req) * req->num_ndp_instances; 335 /* above comes out to 4 byte alligned already, no need of padding */ 336 len = sizeof(*cmd) + ndp_end_req_len + WMI_TLV_HDR_SIZE; 337 buf = wmi_buf_alloc(wmi_handle, len); 338 if (!buf) { 339 return QDF_STATUS_E_NOMEM; 340 } 341 342 cmd = (wmi_ndp_end_req_fixed_param *) wmi_buf_data(buf); 343 WMITLV_SET_HDR(&cmd->tlv_header, 344 WMITLV_TAG_STRUC_wmi_ndp_end_req_fixed_param, 345 WMITLV_GET_STRUCT_TLVLEN(wmi_ndp_end_req_fixed_param)); 346 347 cmd->transaction_id = req->transaction_id; 348 349 /* set tlv pointer to end of fixed param */ 350 WMITLV_SET_HDR((uint8_t *)&cmd[1], WMITLV_TAG_ARRAY_STRUC, 351 ndp_end_req_len); 352 353 ndp_end_req_lst = (wmi_ndp_end_req *)((uint8_t *)&cmd[1] + 354 WMI_TLV_HDR_SIZE); 355 for (i = 0; i < req->num_ndp_instances; i++) { 356 WMITLV_SET_HDR(&ndp_end_req_lst[i], 357 WMITLV_TAG_ARRAY_FIXED_STRUC, 358 (sizeof(*ndp_end_req_lst) - WMI_TLV_HDR_SIZE)); 359 360 ndp_end_req_lst[i].ndp_instance_id = req->ndp_ids[i]; 361 } 362 363 WMI_LOGD("Sending WMI_NDP_END_REQ_CMDID to FW"); 364 wmi_mtrace(WMI_NDP_END_REQ_CMDID, NO_SESSION, 0); 365 status = wmi_unified_cmd_send(wmi_handle, buf, len, 366 WMI_NDP_END_REQ_CMDID); 367 if (QDF_IS_STATUS_ERROR(status)) { 368 WMI_LOGE("WMI_NDP_END_REQ_CMDID failed, ret: %d", status); 369 wmi_buf_free(buf); 370 } 371 372 return status; 373 } 374 375 static QDF_STATUS extract_ndp_initiator_rsp_tlv(wmi_unified_t wmi_handle, 376 uint8_t *data, struct nan_datapath_initiator_rsp *rsp) 377 { 378 WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *event; 379 wmi_ndp_initiator_rsp_event_fixed_param *fixed_params; 380 381 event = (WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *)data; 382 fixed_params = event->fixed_param; 383 384 rsp->vdev = 385 wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc, 386 fixed_params->vdev_id, 387 WLAN_NAN_ID); 388 if (!rsp->vdev) { 389 WMI_LOGE("vdev is null"); 390 return QDF_STATUS_E_INVAL; 391 } 392 393 rsp->transaction_id = fixed_params->transaction_id; 394 rsp->ndp_instance_id = fixed_params->ndp_instance_id; 395 rsp->status = fixed_params->rsp_status; 396 rsp->reason = fixed_params->reason_code; 397 398 return QDF_STATUS_SUCCESS; 399 } 400 401 static QDF_STATUS extract_ndp_ind_tlv(wmi_unified_t wmi_handle, 402 uint8_t *data, struct nan_datapath_indication_event *rsp) 403 { 404 WMI_NDP_INDICATION_EVENTID_param_tlvs *event; 405 wmi_ndp_indication_event_fixed_param *fixed_params; 406 size_t total_array_len; 407 408 event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)data; 409 fixed_params = 410 (wmi_ndp_indication_event_fixed_param *)event->fixed_param; 411 412 if (fixed_params->ndp_cfg_len > event->num_ndp_cfg) { 413 WMI_LOGE("FW message ndp cfg length %d larger than TLV hdr %d", 414 fixed_params->ndp_cfg_len, event->num_ndp_cfg); 415 return QDF_STATUS_E_INVAL; 416 } 417 418 if (fixed_params->ndp_app_info_len > event->num_ndp_app_info) { 419 WMI_LOGE("FW message ndp app info length %d more than TLV hdr %d", 420 fixed_params->ndp_app_info_len, 421 event->num_ndp_app_info); 422 return QDF_STATUS_E_INVAL; 423 } 424 425 if (fixed_params->ndp_cfg_len > 426 (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) { 427 WMI_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", 428 __func__, fixed_params->ndp_cfg_len); 429 return QDF_STATUS_E_INVAL; 430 } 431 432 total_array_len = fixed_params->ndp_cfg_len + 433 sizeof(*fixed_params); 434 435 if (fixed_params->ndp_app_info_len > 436 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) { 437 WMI_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", 438 __func__, fixed_params->ndp_app_info_len); 439 return QDF_STATUS_E_INVAL; 440 } 441 total_array_len += fixed_params->ndp_app_info_len; 442 443 if (fixed_params->nan_scid_len > 444 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) { 445 WMI_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", 446 __func__, fixed_params->nan_scid_len); 447 return QDF_STATUS_E_INVAL; 448 } 449 450 rsp->vdev = 451 wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc, 452 fixed_params->vdev_id, 453 WLAN_NAN_ID); 454 if (!rsp->vdev) { 455 WMI_LOGE("vdev is null"); 456 return QDF_STATUS_E_INVAL; 457 } 458 rsp->service_instance_id = fixed_params->service_instance_id; 459 rsp->ndp_instance_id = fixed_params->ndp_instance_id; 460 rsp->role = fixed_params->self_ndp_role; 461 rsp->policy = fixed_params->accept_policy; 462 463 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, 464 rsp->peer_mac_addr.bytes); 465 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_discovery_mac_addr, 466 rsp->peer_discovery_mac_addr.bytes); 467 468 WMI_LOGD("WMI_NDP_INDICATION_EVENTID(0x%X) received. vdev %d,\n" 469 "service_instance %d, ndp_instance %d, role %d, policy %d,\n" 470 "csid: %d, scid_len: %d, peer_addr: %pM, peer_disc_addr: %pM", 471 WMI_NDP_INDICATION_EVENTID, fixed_params->vdev_id, 472 fixed_params->service_instance_id, 473 fixed_params->ndp_instance_id, fixed_params->self_ndp_role, 474 fixed_params->accept_policy, 475 fixed_params->nan_csid, fixed_params->nan_scid_len, 476 rsp->peer_mac_addr.bytes, 477 rsp->peer_discovery_mac_addr.bytes); 478 479 WMI_LOGD("ndp_cfg - %d bytes", fixed_params->ndp_cfg_len); 480 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 481 &event->ndp_cfg, fixed_params->ndp_cfg_len); 482 483 WMI_LOGD("ndp_app_info - %d bytes", 484 fixed_params->ndp_app_info_len); 485 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 486 &event->ndp_app_info, fixed_params->ndp_app_info_len); 487 488 rsp->ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len; 489 rsp->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len; 490 rsp->ncs_sk_type = fixed_params->nan_csid; 491 rsp->scid.scid_len = fixed_params->nan_scid_len; 492 493 if (rsp->ndp_config.ndp_cfg_len > NDP_QOS_INFO_LEN) 494 rsp->ndp_config.ndp_cfg_len = NDP_QOS_INFO_LEN; 495 qdf_mem_copy(rsp->ndp_config.ndp_cfg, event->ndp_cfg, 496 rsp->ndp_config.ndp_cfg_len); 497 498 if (rsp->ndp_info.ndp_app_info_len > NDP_APP_INFO_LEN) 499 rsp->ndp_info.ndp_app_info_len = NDP_APP_INFO_LEN; 500 qdf_mem_copy(rsp->ndp_info.ndp_app_info, event->ndp_app_info, 501 rsp->ndp_info.ndp_app_info_len); 502 503 if (rsp->scid.scid_len > NDP_SCID_BUF_LEN) 504 rsp->scid.scid_len = NDP_SCID_BUF_LEN; 505 qdf_mem_copy(rsp->scid.scid, event->ndp_scid, rsp->scid.scid_len); 506 507 if (event->ndp_transport_ip_param && 508 event->num_ndp_transport_ip_param) { 509 if (event->ndp_transport_ip_param->ipv6_addr_present) { 510 rsp->is_ipv6_addr_present = true; 511 qdf_mem_copy(rsp->ipv6_addr, 512 event->ndp_transport_ip_param->ipv6_intf_addr, 513 WMI_NDP_IPV6_INTF_ADDR_LEN); 514 } 515 } 516 WMI_LOGD(FL("IPv6 addr present: %d, addr: %pI6"), 517 rsp->is_ipv6_addr_present, rsp->ipv6_addr); 518 519 WMI_LOGD("scid hex dump:"); 520 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 521 rsp->scid.scid, rsp->scid.scid_len); 522 523 return QDF_STATUS_SUCCESS; 524 } 525 526 static QDF_STATUS extract_ndp_confirm_tlv(wmi_unified_t wmi_handle, 527 uint8_t *data, struct nan_datapath_confirm_event *rsp) 528 { 529 uint8_t i; 530 WMI_HOST_WLAN_PHY_MODE ch_mode; 531 WMI_NDP_CONFIRM_EVENTID_param_tlvs *event; 532 wmi_ndp_confirm_event_fixed_param *fixed_params; 533 size_t total_array_len; 534 535 event = (WMI_NDP_CONFIRM_EVENTID_param_tlvs *) data; 536 fixed_params = (wmi_ndp_confirm_event_fixed_param *)event->fixed_param; 537 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", 538 WMI_NDP_CONFIRM_EVENTID, fixed_params->vdev_id, 539 fixed_params->ndp_instance_id, fixed_params->rsp_code, 540 fixed_params->reason_code, 541 fixed_params->num_active_ndps_on_peer); 542 WMI_LOGE("num_ch: %d", fixed_params->num_ndp_channels); 543 544 if (fixed_params->ndp_cfg_len > event->num_ndp_cfg) { 545 WMI_LOGE("FW message ndp cfg length %d larger than TLV hdr %d", 546 fixed_params->ndp_cfg_len, event->num_ndp_cfg); 547 return QDF_STATUS_E_INVAL; 548 } 549 550 WMI_LOGD("ndp_cfg - %d bytes", fixed_params->ndp_cfg_len); 551 552 if (fixed_params->ndp_app_info_len > event->num_ndp_app_info) { 553 WMI_LOGE("FW message ndp app info length %d more than TLV hdr %d", 554 fixed_params->ndp_app_info_len, 555 event->num_ndp_app_info); 556 return QDF_STATUS_E_INVAL; 557 } 558 559 WMI_LOGD("ndp_app_info - %d bytes", 560 fixed_params->ndp_app_info_len); 561 562 if (fixed_params->ndp_cfg_len > 563 (WMI_SVC_MSG_MAX_SIZE - sizeof(*fixed_params))) { 564 WMI_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", 565 __func__, fixed_params->ndp_cfg_len); 566 return QDF_STATUS_E_INVAL; 567 } 568 569 total_array_len = fixed_params->ndp_cfg_len + 570 sizeof(*fixed_params); 571 572 if (fixed_params->ndp_app_info_len > 573 (WMI_SVC_MSG_MAX_SIZE - total_array_len)) { 574 WMI_LOGE("%s: excess wmi buffer: ndp_cfg_len %d", 575 __func__, fixed_params->ndp_app_info_len); 576 return QDF_STATUS_E_INVAL; 577 } 578 579 if (fixed_params->num_ndp_channels > event->num_ndp_channel_list || 580 fixed_params->num_ndp_channels > event->num_nss_list) { 581 WMI_LOGE(FL("NDP Ch count %d greater than NDP Ch TLV len (%d) or NSS TLV len (%d)"), 582 fixed_params->num_ndp_channels, 583 event->num_ndp_channel_list, 584 event->num_nss_list); 585 return QDF_STATUS_E_INVAL; 586 } 587 588 rsp->vdev = 589 wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc, 590 fixed_params->vdev_id, 591 WLAN_NAN_ID); 592 if (!rsp->vdev) { 593 WMI_LOGE("vdev is null"); 594 return QDF_STATUS_E_INVAL; 595 } 596 rsp->ndp_instance_id = fixed_params->ndp_instance_id; 597 rsp->rsp_code = fixed_params->rsp_code; 598 rsp->reason_code = fixed_params->reason_code; 599 rsp->num_active_ndps_on_peer = fixed_params->num_active_ndps_on_peer; 600 rsp->num_channels = fixed_params->num_ndp_channels; 601 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, 602 rsp->peer_ndi_mac_addr.bytes); 603 rsp->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len; 604 qdf_mem_copy(rsp->ndp_info.ndp_app_info, event->ndp_app_info, 605 rsp->ndp_info.ndp_app_info_len); 606 607 if (rsp->num_channels > NAN_CH_INFO_MAX_CHANNELS) { 608 WMI_LOGE(FL("too many channels")); 609 rsp->num_channels = NAN_CH_INFO_MAX_CHANNELS; 610 } 611 612 for (i = 0; i < rsp->num_channels; i++) { 613 rsp->ch[i].channel = event->ndp_channel_list[i].mhz; 614 rsp->ch[i].nss = event->nss_list[i]; 615 ch_mode = WMI_GET_CHANNEL_MODE(&event->ndp_channel_list[i]); 616 rsp->ch[i].ch_width = wmi_get_ch_width_from_phy_mode(wmi_handle, 617 ch_mode); 618 WMI_LOGD(FL("ch: %d, ch_mode: %d, nss: %d"), 619 rsp->ch[i].channel, 620 rsp->ch[i].ch_width, 621 rsp->ch[i].nss); 622 } 623 624 if (event->ndp_transport_ip_param && 625 event->num_ndp_transport_ip_param) { 626 if (event->ndp_transport_ip_param->ipv6_addr_present) { 627 rsp->is_ipv6_addr_present = true; 628 qdf_mem_copy(rsp->ipv6_addr, 629 event->ndp_transport_ip_param->ipv6_intf_addr, 630 WMI_NDP_IPV6_INTF_ADDR_LEN); 631 } 632 633 if (event->ndp_transport_ip_param->trans_port_present) { 634 rsp->is_port_present = true; 635 rsp->port = 636 event->ndp_transport_ip_param->transport_port; 637 } 638 639 if (event->ndp_transport_ip_param->trans_proto_present) { 640 rsp->is_protocol_present = true; 641 rsp->protocol = 642 event->ndp_transport_ip_param->transport_protocol; 643 } 644 } 645 WMI_LOGD(FL("IPv6 addr present: %d, addr: %pI6"), 646 rsp->is_ipv6_addr_present, rsp->ipv6_addr); 647 WMI_LOGD(FL("port: %d present: %d"), rsp->port, rsp->is_port_present); 648 WMI_LOGD(FL("protocol: %d present: %d"), 649 rsp->protocol, rsp->is_protocol_present); 650 651 return QDF_STATUS_SUCCESS; 652 } 653 654 static QDF_STATUS extract_ndp_responder_rsp_tlv(wmi_unified_t wmi_handle, 655 uint8_t *data, struct nan_datapath_responder_rsp *rsp) 656 { 657 WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *event; 658 wmi_ndp_responder_rsp_event_fixed_param *fixed_params; 659 660 event = (WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *)data; 661 fixed_params = event->fixed_param; 662 663 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", 664 WMI_NDP_RESPONDER_RSP_EVENTID, fixed_params->vdev_id, 665 rsp->peer_mac_addr.bytes, rsp->transaction_id, 666 rsp->status, rsp->reason, rsp->create_peer); 667 668 rsp->vdev = 669 wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc, 670 fixed_params->vdev_id, 671 WLAN_NAN_ID); 672 if (!rsp->vdev) { 673 WMI_LOGE("vdev is null"); 674 return QDF_STATUS_E_INVAL; 675 } 676 rsp->transaction_id = fixed_params->transaction_id; 677 rsp->reason = fixed_params->reason_code; 678 rsp->status = fixed_params->rsp_status; 679 rsp->create_peer = fixed_params->create_peer; 680 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, 681 rsp->peer_mac_addr.bytes); 682 683 return QDF_STATUS_SUCCESS; 684 } 685 686 static QDF_STATUS extract_ndp_end_rsp_tlv(wmi_unified_t wmi_handle, 687 uint8_t *data, struct nan_datapath_end_rsp_event *rsp) 688 { 689 WMI_NDP_END_RSP_EVENTID_param_tlvs *event; 690 wmi_ndp_end_rsp_event_fixed_param *fixed_params = NULL; 691 692 event = (WMI_NDP_END_RSP_EVENTID_param_tlvs *) data; 693 fixed_params = (wmi_ndp_end_rsp_event_fixed_param *)event->fixed_param; 694 WMI_LOGD("WMI_NDP_END_RSP_EVENTID(0x%X) received. transaction_id: %d, rsp_status: %d, reason_code: %d", 695 WMI_NDP_END_RSP_EVENTID, fixed_params->transaction_id, 696 fixed_params->rsp_status, fixed_params->reason_code); 697 698 rsp->vdev = wlan_objmgr_get_vdev_by_opmode_from_psoc( 699 wmi_handle->soc->wmi_psoc, QDF_NDI_MODE, WLAN_NAN_ID); 700 if (!rsp->vdev) { 701 WMI_LOGE("vdev is null"); 702 return QDF_STATUS_E_INVAL; 703 } 704 rsp->transaction_id = fixed_params->transaction_id; 705 rsp->reason = fixed_params->reason_code; 706 rsp->status = fixed_params->rsp_status; 707 708 return QDF_STATUS_SUCCESS; 709 } 710 711 static QDF_STATUS extract_ndp_end_ind_tlv(wmi_unified_t wmi_handle, 712 uint8_t *data, struct nan_datapath_end_indication_event **rsp) 713 { 714 uint32_t i, buf_size; 715 wmi_ndp_end_indication *ind; 716 struct qdf_mac_addr peer_addr; 717 WMI_NDP_END_INDICATION_EVENTID_param_tlvs *event; 718 719 event = (WMI_NDP_END_INDICATION_EVENTID_param_tlvs *) data; 720 ind = event->ndp_end_indication_list; 721 722 if (event->num_ndp_end_indication_list == 0) { 723 WMI_LOGE("Error: Event ignored, 0 ndp instances"); 724 return QDF_STATUS_E_INVAL; 725 } 726 727 WMI_LOGD("number of ndp instances = %d", 728 event->num_ndp_end_indication_list); 729 730 if (event->num_ndp_end_indication_list > ((UINT_MAX - sizeof(**rsp))/ 731 sizeof((*rsp)->ndp_map[0]))) { 732 WMI_LOGE("num_ndp_end_ind_list %d too large", 733 event->num_ndp_end_indication_list); 734 return QDF_STATUS_E_INVAL; 735 } 736 737 buf_size = sizeof(**rsp) + event->num_ndp_end_indication_list * 738 sizeof((*rsp)->ndp_map[0]); 739 *rsp = qdf_mem_malloc(buf_size); 740 if (!(*rsp)) { 741 WMI_LOGE("Failed to allocate memory"); 742 return QDF_STATUS_E_NOMEM; 743 } 744 745 (*rsp)->num_ndp_ids = event->num_ndp_end_indication_list; 746 for (i = 0; i < (*rsp)->num_ndp_ids; i++) { 747 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ind[i].peer_ndi_mac_addr, 748 peer_addr.bytes); 749 WMI_LOGD("ind[%d]: type %d, reason_code %d, instance_id %d num_active %d ", 750 i, ind[i].type, ind[i].reason_code, 751 ind[i].ndp_instance_id, 752 ind[i].num_active_ndps_on_peer); 753 /* Add each instance entry to the list */ 754 (*rsp)->ndp_map[i].ndp_instance_id = ind[i].ndp_instance_id; 755 (*rsp)->ndp_map[i].vdev_id = ind[i].vdev_id; 756 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ind[i].peer_ndi_mac_addr, 757 (*rsp)->ndp_map[i].peer_ndi_mac_addr.bytes); 758 (*rsp)->ndp_map[i].num_active_ndp_sessions = 759 ind[i].num_active_ndps_on_peer; 760 (*rsp)->ndp_map[i].type = ind[i].type; 761 (*rsp)->ndp_map[i].reason_code = ind[i].reason_code; 762 } 763 764 return QDF_STATUS_SUCCESS; 765 } 766 767 static QDF_STATUS extract_ndp_sch_update_tlv(wmi_unified_t wmi_handle, 768 uint8_t *data, struct nan_datapath_sch_update_event *ind) 769 { 770 uint8_t i; 771 WMI_HOST_WLAN_PHY_MODE ch_mode; 772 WMI_NDL_SCHEDULE_UPDATE_EVENTID_param_tlvs *event; 773 wmi_ndl_schedule_update_fixed_param *fixed_params; 774 775 event = (WMI_NDL_SCHEDULE_UPDATE_EVENTID_param_tlvs *)data; 776 fixed_params = event->fixed_param; 777 778 WMI_LOGD(FL("flags: %d, num_ch: %d, num_ndp_instances: %d"), 779 fixed_params->flags, fixed_params->num_channels, 780 fixed_params->num_ndp_instances); 781 782 if (fixed_params->num_channels > event->num_ndl_channel_list || 783 fixed_params->num_channels > event->num_nss_list) { 784 WMI_LOGE(FL("Channel count %d greater than NDP Ch list TLV len (%d) or NSS list TLV len (%d)"), 785 fixed_params->num_channels, 786 event->num_ndl_channel_list, 787 event->num_nss_list); 788 return QDF_STATUS_E_INVAL; 789 } 790 if (fixed_params->num_ndp_instances > event->num_ndp_instance_list) { 791 WMI_LOGE(FL("NDP Instance count %d greater than NDP Instancei TLV len %d"), 792 fixed_params->num_ndp_instances, 793 event->num_ndp_instance_list); 794 return QDF_STATUS_E_INVAL; 795 } 796 797 ind->vdev = 798 wlan_objmgr_get_vdev_by_id_from_psoc(wmi_handle->soc->wmi_psoc, 799 fixed_params->vdev_id, 800 WLAN_NAN_ID); 801 if (!ind->vdev) { 802 WMI_LOGE("vdev is null"); 803 return QDF_STATUS_E_INVAL; 804 } 805 806 ind->flags = fixed_params->flags; 807 ind->num_channels = fixed_params->num_channels; 808 ind->num_ndp_instances = fixed_params->num_ndp_instances; 809 WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_macaddr, 810 ind->peer_addr.bytes); 811 812 if (ind->num_ndp_instances > NDP_NUM_INSTANCE_ID) { 813 WMI_LOGE(FL("uint32 overflow")); 814 wlan_objmgr_vdev_release_ref(ind->vdev, WLAN_NAN_ID); 815 return QDF_STATUS_E_INVAL; 816 } 817 818 qdf_mem_copy(ind->ndp_instances, event->ndp_instance_list, 819 sizeof(uint32_t) * ind->num_ndp_instances); 820 821 if (ind->num_channels > NAN_CH_INFO_MAX_CHANNELS) { 822 WMI_LOGE(FL("too many channels")); 823 ind->num_channels = NAN_CH_INFO_MAX_CHANNELS; 824 } 825 826 for (i = 0; i < ind->num_channels; i++) { 827 ind->ch[i].channel = event->ndl_channel_list[i].mhz; 828 ind->ch[i].nss = event->nss_list[i]; 829 ch_mode = WMI_GET_CHANNEL_MODE(&event->ndl_channel_list[i]); 830 ind->ch[i].ch_width = wmi_get_ch_width_from_phy_mode(wmi_handle, 831 ch_mode); 832 WMI_LOGD(FL("ch: %d, ch_mode: %d, nss: %d"), 833 ind->ch[i].channel, 834 ind->ch[i].ch_width, 835 ind->ch[i].nss); 836 } 837 838 for (i = 0; i < fixed_params->num_ndp_instances; i++) 839 WMI_LOGD(FL("instance_id[%d]: %d"), 840 i, event->ndp_instance_list[i]); 841 842 return QDF_STATUS_SUCCESS; 843 } 844 845 void wmi_nan_attach_tlv(wmi_unified_t wmi_handle) 846 { 847 struct wmi_ops *ops = wmi_handle->ops; 848 849 ops->send_ndp_initiator_req_cmd = nan_ndp_initiator_req_tlv; 850 ops->send_ndp_responder_req_cmd = nan_ndp_responder_req_tlv; 851 ops->send_ndp_end_req_cmd = nan_ndp_end_req_tlv; 852 ops->extract_ndp_initiator_rsp = extract_ndp_initiator_rsp_tlv; 853 ops->extract_ndp_ind = extract_ndp_ind_tlv; 854 ops->extract_ndp_confirm = extract_ndp_confirm_tlv; 855 ops->extract_ndp_responder_rsp = extract_ndp_responder_rsp_tlv; 856 ops->extract_ndp_end_rsp = extract_ndp_end_rsp_tlv; 857 ops->extract_ndp_end_ind = extract_ndp_end_ind_tlv; 858 ops->extract_ndp_sch_update = extract_ndp_sch_update_tlv; 859 } 860