1 /* 2 * Copyright (c) 2012-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 19 /** 20 * DOC: wifi_pos_main.c 21 * This file defines the important functions pertinent to 22 * wifi positioning to initialize and de-initialize the component. 23 */ 24 #include "target_if_wifi_pos.h" 25 #include "wifi_pos_oem_interface_i.h" 26 #include "wifi_pos_utils_i.h" 27 #include "wifi_pos_api.h" 28 #include "wifi_pos_main_i.h" 29 #include "wifi_pos_ucfg_i.h" 30 #include "wlan_objmgr_cmn.h" 31 #include "wlan_objmgr_global_obj.h" 32 #include "wlan_objmgr_psoc_obj.h" 33 #include "wlan_objmgr_pdev_obj.h" 34 #include "wlan_objmgr_vdev_obj.h" 35 #include "wlan_ptt_sock_svc.h" 36 37 #include "wlan_reg_services_api.h" 38 /* forward declartion */ 39 struct regulatory_channel; 40 41 #define REG_SET_CHANNEL_REG_POWER(reg_info_1, val) do { \ 42 reg_info_1 &= 0xff00ffff; \ 43 reg_info_1 |= ((val & 0xff) << 16); \ 44 } while (0) 45 46 /* max tx power is in 1 dBm units */ 47 #define REG_SET_CHANNEL_MAX_TX_POWER(reg_info_2, val) do { \ 48 reg_info_2 &= 0xffff00ff; \ 49 reg_info_2 |= ((val & 0xff) << 8); \ 50 } while (0) 51 52 /* channel info consists of 6 bits of channel mode */ 53 54 #define REG_SET_CHANNEL_MODE(reg_channel, val) do { \ 55 (reg_channel)->info &= 0xffffffc0; \ 56 (reg_channel)->info |= (val); \ 57 } while (0) 58 59 /* 60 * obj mgr api to iterate over vdevs does not provide a direct array or vdevs, 61 * rather takes a callback that is called for every vdev. wifi pos needs to 62 * store device mode and vdev id of all active vdevs and provide this info to 63 * user space as part of APP registration response. due to this, vdev_idx is 64 * used to identify how many vdevs have been populated by obj manager API. 65 */ 66 static uint32_t vdev_idx; 67 68 /** 69 * wifi_pos_get_tlv_support: indicates if firmware supports TLV wifi pos msg 70 * @psoc: psoc object 71 * 72 * Return: status of operation 73 */ 74 static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc) 75 { 76 /* this is TBD */ 77 return true; 78 } 79 80 static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc, 81 struct wifi_pos_req_msg *req) 82 { 83 uint8_t idx; 84 uint32_t sub_type = 0; 85 uint32_t channel_mhz = 0; 86 void *pdev_id = NULL; 87 uint32_t offset; 88 struct oem_data_req data_req; 89 struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops; 90 91 wifi_pos_debug("Received data req pid(%d), len(%d)", 92 req->pid, req->buf_len); 93 94 /* look for fields */ 95 if (req->field_info_buf) 96 for (idx = 0; idx < req->field_info_buf->count; idx++) { 97 offset = req->field_info_buf->fields[idx].offset; 98 /* 99 * replace following reads with read_api based on 100 * length 101 */ 102 if (req->field_info_buf->fields[idx].id == 103 WMIRTT_FIELD_ID_oem_data_sub_type) { 104 sub_type = *((uint32_t *)&req->buf[offset]); 105 continue; 106 } 107 108 if (req->field_info_buf->fields[idx].id == 109 WMIRTT_FIELD_ID_channel_mhz) { 110 channel_mhz = *((uint32_t *)&req->buf[offset]); 111 continue; 112 } 113 114 if (req->field_info_buf->fields[idx].id == 115 WMIRTT_FIELD_ID_pdev) { 116 pdev_id = &req->buf[offset]; 117 continue; 118 } 119 } 120 121 switch (sub_type) { 122 case TARGET_OEM_CAPABILITY_REQ: 123 /* TBD */ 124 break; 125 case TARGET_OEM_CONFIGURE_LCR: 126 /* TBD */ 127 break; 128 case TARGET_OEM_CONFIGURE_LCI: 129 /* TBD */ 130 break; 131 case TARGET_OEM_MEASUREMENT_REQ: 132 /* TBD */ 133 break; 134 case TARGET_OEM_CONFIGURE_FTMRR: 135 /* TBD */ 136 break; 137 case TARGET_OEM_CONFIGURE_WRU: 138 /* TBD */ 139 break; 140 default: 141 wifi_pos_debug("invalid sub type or not passed"); 142 /* 143 * this is legacy MCL operation. pass whole msg to firmware as 144 * it is. 145 */ 146 tx_ops = target_if_wifi_pos_get_txops(psoc); 147 if (!tx_ops) { 148 wifi_pos_err("tx ops null"); 149 return QDF_STATUS_E_INVAL; 150 } 151 data_req.data_len = req->buf_len; 152 data_req.data = req->buf; 153 tx_ops->data_req_tx(psoc, &data_req); 154 break; 155 } 156 157 return QDF_STATUS_SUCCESS; 158 } 159 160 static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc, 161 struct wifi_pos_req_msg *req) 162 { 163 int error_code; 164 struct wifi_pos_psoc_priv_obj *wifi_pos_obj = 165 wifi_pos_get_psoc_priv_obj(psoc); 166 struct wifi_pos_user_defined_caps *caps = 167 (struct wifi_pos_user_defined_caps *)req->buf; 168 169 wifi_pos_debug("Received set cap req pid(%d), len(%d)", 170 req->pid, req->buf_len); 171 172 wifi_pos_obj->ftm_rr = caps->ftm_rr; 173 wifi_pos_obj->lci_capability = caps->lci_capability; 174 error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS); 175 wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, 176 ANI_MSG_SET_OEM_CAP_RSP, 177 sizeof(error_code), 178 (uint8_t *)&error_code); 179 180 return QDF_STATUS_SUCCESS; 181 } 182 183 static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc, 184 struct wifi_pos_req_msg *req) 185 { 186 struct wifi_pos_oem_get_cap_rsp cap_rsp = { { {0} } }; 187 struct wifi_pos_psoc_priv_obj *wifi_pos_obj = 188 wifi_pos_get_psoc_priv_obj(psoc); 189 190 wifi_pos_debug("Received get cap req pid(%d), len(%d)", 191 req->pid, req->buf_len); 192 193 wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap); 194 cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr; 195 cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability; 196 wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, 197 ANI_MSG_GET_OEM_CAP_RSP, 198 sizeof(cap_rsp), 199 (uint8_t *)&cap_rsp); 200 201 return QDF_STATUS_SUCCESS; 202 } 203 204 static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc, 205 struct wlan_objmgr_pdev *pdev, 206 uint16_t chan, 207 struct wifi_pos_ch_info_rsp *chan_info) 208 { 209 struct ch_params ch_params = {0}; 210 uint16_t sec_ch_2g = 0; 211 struct wifi_pos_psoc_priv_obj *wifi_pos_psoc = 212 wifi_pos_get_psoc_priv_obj(psoc); 213 uint32_t phy_mode; 214 215 if (!wifi_pos_psoc) { 216 wifi_pos_err("wifi_pos priv obj is null"); 217 return; 218 } 219 220 /* Passing CH_WIDTH_MAX will give the max bandwidth supported */ 221 ch_params.ch_width = CH_WIDTH_MAX; 222 223 wlan_reg_set_channel_params(pdev, chan, sec_ch_2g, &ch_params); 224 if (ch_params.center_freq_seg0) 225 chan_info->band_center_freq1 = 226 wlan_reg_get_channel_freq(pdev, 227 ch_params.center_freq_seg0); 228 229 wifi_pos_psoc->wifi_pos_get_phy_mode(chan, ch_params.ch_width, 230 &phy_mode); 231 232 REG_SET_CHANNEL_MODE(chan_info, phy_mode); 233 } 234 235 static void wifi_pos_get_reg_info(struct wlan_objmgr_pdev *pdev, 236 uint32_t chan_num, uint32_t *reg_info_1, 237 uint32_t *reg_info_2) 238 { 239 uint32_t reg_power = wlan_reg_get_channel_reg_power(pdev, chan_num); 240 241 *reg_info_1 = 0; 242 *reg_info_2 = 0; 243 244 REG_SET_CHANNEL_REG_POWER(*reg_info_1, reg_power); 245 REG_SET_CHANNEL_MAX_TX_POWER(*reg_info_2, reg_power); 246 } 247 248 /** 249 * wifi_pos_get_valid_channels: Get the list of valid channels from the 250 * given channel list 251 * @channels: Channel list to be validated 252 * @num_ch: NUmber of channels in the channel list to be validated 253 * @valid_channel_list: Pointer to valid channel list 254 * 255 * Return: Number of valid channels in the given list 256 */ 257 258 static uint32_t wifi_pos_get_valid_channels(uint8_t *channels, uint32_t num_ch, 259 uint8_t *valid_channel_list) { 260 uint32_t i, num_valid_channels = 0; 261 262 for (i = 0; i < num_ch; i++) { 263 if (INVALID_CHANNEL == reg_get_chan_enum(channels[i])) 264 continue; 265 valid_channel_list[num_valid_channels++] = channels[i]; 266 } 267 return num_valid_channels; 268 } 269 270 static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc, 271 struct wifi_pos_req_msg *req) 272 { 273 uint8_t idx; 274 uint8_t *buf; 275 uint32_t len; 276 uint32_t reg_info_1; 277 uint32_t reg_info_2; 278 uint8_t *channels = req->buf; 279 struct wlan_objmgr_pdev *pdev; 280 uint32_t num_ch = req->buf_len; 281 uint8_t valid_channel_list[NUM_CHANNELS]; 282 uint32_t num_valid_channels; 283 struct wifi_pos_ch_info_rsp *ch_info; 284 struct wifi_pos_psoc_priv_obj *wifi_pos_obj = 285 wifi_pos_get_psoc_priv_obj(psoc); 286 287 wifi_pos_debug("Received ch info req pid(%d), len(%d)", 288 req->pid, req->buf_len); 289 290 /* get first pdev since we need that only for freq and dfs state */ 291 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_WIFI_POS_CORE_ID); 292 if (!pdev) { 293 wifi_pos_err("pdev get API failed"); 294 return QDF_STATUS_E_INVAL; 295 } 296 if (num_ch > NUM_CHANNELS) { 297 wifi_pos_err("Invalid number of channels"); 298 return QDF_STATUS_E_INVAL; 299 } 300 num_valid_channels = wifi_pos_get_valid_channels(channels, num_ch, 301 valid_channel_list); 302 303 len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) * 304 num_valid_channels; 305 buf = qdf_mem_malloc(len); 306 if (!buf) { 307 wifi_pos_alert("malloc failed"); 308 wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID); 309 return QDF_STATUS_E_NOMEM; 310 } 311 312 qdf_mem_zero(buf, len); 313 314 /* First byte of message body will have num of channels */ 315 buf[0] = num_valid_channels; 316 ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1]; 317 for (idx = 0; idx < num_valid_channels; idx++) { 318 ch_info[idx].chan_id = valid_channel_list[idx]; 319 wifi_pos_get_reg_info(pdev, ch_info[idx].chan_id, 320 ®_info_1, ®_info_2); 321 ch_info[idx].reserved0 = 0; 322 ch_info[idx].mhz = wlan_reg_get_channel_freq( 323 pdev, 324 valid_channel_list[idx]); 325 ch_info[idx].band_center_freq1 = ch_info[idx].mhz; 326 ch_info[idx].band_center_freq2 = 0; 327 ch_info[idx].info = 0; 328 if (wlan_reg_is_dfs_ch(pdev, valid_channel_list[idx])) 329 WIFI_POS_SET_DFS(ch_info[idx].info); 330 331 wifi_update_channel_bw_info(psoc, pdev, 332 ch_info[idx].chan_id, 333 &ch_info[idx]); 334 335 ch_info[idx].reg_info_1 = reg_info_1; 336 ch_info[idx].reg_info_2 = reg_info_2; 337 } 338 339 wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid, 340 ANI_MSG_CHANNEL_INFO_RSP, 341 len, buf); 342 qdf_mem_free(buf); 343 wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID); 344 345 return QDF_STATUS_SUCCESS; 346 } 347 348 static void wifi_pos_vdev_iterator(struct wlan_objmgr_psoc *psoc, 349 void *vdev, void *arg) 350 { 351 struct app_reg_rsp_vdev_info *vdev_info = arg; 352 353 vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev); 354 vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev); 355 vdev_idx++; 356 } 357 358 static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc, 359 struct wifi_pos_req_msg *req) 360 { 361 QDF_STATUS ret = QDF_STATUS_SUCCESS; 362 uint8_t err = 0; 363 uint32_t rsp_len; 364 char *sign_str = NULL; 365 struct wifi_app_reg_rsp *app_reg_rsp; 366 struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS] 367 = { { 0 } }; 368 struct wifi_pos_psoc_priv_obj *wifi_pos_obj = 369 wifi_pos_get_psoc_priv_obj(psoc); 370 371 wifi_pos_err("Received App Req Req pid(%d), len(%d)", 372 req->pid, req->buf_len); 373 374 sign_str = (char *)req->buf; 375 /* Registration request is only allowed for QTI Application */ 376 if ((OEM_APP_SIGNATURE_LEN != req->buf_len) || 377 (strncmp(sign_str, OEM_APP_SIGNATURE_STR, 378 OEM_APP_SIGNATURE_LEN))) { 379 wifi_pos_err("Invalid signature pid(%d)", req->pid); 380 ret = QDF_STATUS_E_PERM; 381 err = OEM_ERR_INVALID_SIGNATURE; 382 goto app_reg_failed; 383 } 384 385 wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid); 386 wifi_pos_obj->is_app_registered = true; 387 wifi_pos_obj->app_pid = req->pid; 388 389 vdev_idx = 0; 390 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 391 wifi_pos_vdev_iterator, 392 vdevs_info, true, WLAN_WIFI_POS_CORE_ID); 393 rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx) 394 + sizeof(uint8_t); 395 app_reg_rsp = qdf_mem_malloc(rsp_len); 396 if (!app_reg_rsp) { 397 wifi_pos_alert("malloc failed"); 398 ret = QDF_STATUS_E_NOMEM; 399 err = OEM_ERR_NULL_CONTEXT; 400 goto app_reg_failed; 401 } 402 403 app_reg_rsp->num_inf = vdev_idx; 404 qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info, 405 sizeof(struct app_reg_rsp_vdev_info) * vdev_idx); 406 if (!vdev_idx) 407 wifi_pos_debug("no active vdev"); 408 409 vdev_idx = 0; 410 wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_APP_REG_RSP, 411 rsp_len, (uint8_t *)app_reg_rsp); 412 413 qdf_mem_free(app_reg_rsp); 414 return ret; 415 416 app_reg_failed: 417 418 wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_OEM_ERROR, 419 sizeof(err), &err); 420 return ret; 421 } 422 423 /** 424 * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req 425 * @wmi_msg: wmi type request msg 426 * 427 * Return: status of operation 428 */ 429 static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc, 430 struct wifi_pos_req_msg *req) 431 { 432 wifi_pos_debug("enter: msg_type: %d", req->msg_type); 433 switch (req->msg_type) { 434 case ANI_MSG_APP_REG_REQ: 435 return wifi_pos_process_app_reg_req(psoc, req); 436 case ANI_MSG_OEM_DATA_REQ: 437 return wifi_pos_process_data_req(psoc, req); 438 case ANI_MSG_CHANNEL_INFO_REQ: 439 return wifi_pos_process_ch_info_req(psoc, req); 440 case ANI_MSG_SET_OEM_CAP_REQ: 441 return wifi_pos_process_set_cap_req(psoc, req); 442 case ANI_MSG_GET_OEM_CAP_REQ: 443 return wifi_pos_process_get_cap_req(psoc, req); 444 default: 445 wifi_pos_err("invalid request type"); 446 break; 447 } 448 return 0; 449 } 450 451 /** 452 * wifi_pos_non_tlv_callback: wifi pos msg handler registered for non-TLV 453 * type req 454 * @wmi_msg: wmi type request msg 455 * 456 * Return: status of operation 457 */ 458 static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc, 459 struct wifi_pos_req_msg *req) 460 { 461 return QDF_STATUS_SUCCESS; 462 } 463 464 QDF_STATUS wifi_pos_psoc_obj_created_notification( 465 struct wlan_objmgr_psoc *psoc, void *arg_list) 466 { 467 QDF_STATUS status; 468 struct wifi_pos_psoc_priv_obj *wifi_pos_obj; 469 470 /* 471 * this is for WIN, if they have multiple psoc, we dont want to create 472 * multiple priv object. Since there is just one LOWI app registered to 473 * one driver, avoid 2nd private object with another psoc. 474 */ 475 if (wifi_pos_get_psoc()) { 476 wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object"); 477 return QDF_STATUS_SUCCESS; 478 } else { 479 wifi_pos_debug("setting global pos object"); 480 wifi_pos_set_psoc(psoc); 481 } 482 483 /* initialize wifi-pos psoc priv object */ 484 wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj)); 485 if (!wifi_pos_obj) { 486 wifi_pos_alert("Mem alloc failed for wifi pos psoc priv obj"); 487 wifi_pos_clear_psoc(); 488 return QDF_STATUS_E_NOMEM; 489 } 490 491 qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock); 492 /* Register TLV or non-TLV callbacks depending on target fw version */ 493 if (wifi_pos_get_tlv_support(psoc)) 494 wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback; 495 else 496 wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback; 497 498 /* 499 * MGMT Rx is not handled in this phase since wifi pos only uses few 500 * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are 501 * used for 80211k. That part is not yet converged and still follows 502 * legacy MGMT Rx to work. Action frame in new TXRX can be registered 503 * at per ACTION Frame type granularity only. 504 */ 505 506 status = wlan_objmgr_psoc_component_obj_attach(psoc, 507 WLAN_UMAC_COMP_WIFI_POS, 508 wifi_pos_obj, 509 QDF_STATUS_SUCCESS); 510 511 if (QDF_IS_STATUS_ERROR(status)) { 512 wifi_pos_err("obj attach with psoc failed with status: %d", 513 status); 514 qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock); 515 qdf_mem_free(wifi_pos_obj); 516 wifi_pos_clear_psoc(); 517 } 518 519 return status; 520 } 521 522 QDF_STATUS wifi_pos_psoc_obj_destroyed_notification( 523 struct wlan_objmgr_psoc *psoc, void *arg_list) 524 { 525 QDF_STATUS status; 526 struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL; 527 528 if (wifi_pos_get_psoc() == psoc) { 529 wifi_pos_debug("deregistering wifi_pos_psoc object"); 530 wifi_pos_clear_psoc(); 531 } else { 532 wifi_pos_warn("un-related PSOC closed. do nothing"); 533 return QDF_STATUS_SUCCESS; 534 } 535 536 wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc); 537 if (!wifi_pos_obj) { 538 wifi_pos_err("wifi_pos_obj is NULL"); 539 return QDF_STATUS_E_FAULT; 540 } 541 542 target_if_wifi_pos_deinit_dma_rings(psoc); 543 544 status = wlan_objmgr_psoc_component_obj_detach(psoc, 545 WLAN_UMAC_COMP_WIFI_POS, 546 wifi_pos_obj); 547 if (status != QDF_STATUS_SUCCESS) 548 wifi_pos_err("wifi_pos_obj detach failed"); 549 550 wifi_pos_debug("wifi_pos_obj deleted with status %d", status); 551 qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock); 552 qdf_mem_free(wifi_pos_obj); 553 554 return status; 555 } 556 557 int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc, 558 struct oem_data_rsp *oem_rsp) 559 { 560 uint32_t len; 561 uint8_t *data; 562 uint32_t app_pid; 563 struct wifi_pos_psoc_priv_obj *priv = 564 wifi_pos_get_psoc_priv_obj(psoc); 565 void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *); 566 567 if (!priv) { 568 wifi_pos_err("private object is NULL"); 569 return -EINVAL; 570 } 571 572 qdf_spin_lock_bh(&priv->wifi_pos_lock); 573 app_pid = priv->app_pid; 574 wifi_pos_send_rsp = priv->wifi_pos_send_rsp; 575 qdf_spin_unlock_bh(&priv->wifi_pos_lock); 576 577 len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len; 578 if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE || 579 oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) { 580 wifi_pos_err("invalid length of Oem Data response"); 581 return -EINVAL; 582 } 583 584 wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid); 585 586 if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) { 587 /* stitch togther the msg data_1 + CIR/CFR + data_2 */ 588 data = qdf_mem_malloc(len); 589 if (!data) { 590 wifi_pos_err("malloc failed"); 591 return -ENOMEM; 592 } 593 qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1); 594 qdf_mem_copy(&data[oem_rsp->rsp_len_1], 595 oem_rsp->vaddr, oem_rsp->dma_len); 596 qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len], 597 oem_rsp->data_2, oem_rsp->rsp_len_2); 598 599 wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, len, data); 600 qdf_mem_free(data); 601 } else { 602 wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, 603 oem_rsp->rsp_len_1, oem_rsp->data_1); 604 } 605 606 return 0; 607 } 608 609 static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc, 610 void *obj, void *arg) 611 { 612 uint32_t i; 613 QDF_STATUS status; 614 struct wlan_objmgr_pdev *pdev = obj; 615 struct regulatory_channel *psoc_ch_lst = arg; 616 struct regulatory_channel pdev_ch_lst[NUM_CHANNELS]; 617 618 status = wlan_reg_get_current_chan_list(pdev, pdev_ch_lst); 619 if (QDF_IS_STATUS_ERROR(status)) { 620 wifi_pos_err("wlan_reg_get_current_chan_list_by_range failed"); 621 return; 622 } 623 624 for (i = 0; i < NUM_CHANNELS; i++) { 625 if (pdev_ch_lst[i].state != CHANNEL_STATE_DISABLE && 626 pdev_ch_lst[i].state != CHANNEL_STATE_INVALID) 627 psoc_ch_lst[i] = pdev_ch_lst[i]; 628 } 629 } 630 631 static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc, 632 struct wifi_pos_driver_caps *caps) 633 { 634 uint32_t i, num_ch = 0; 635 struct regulatory_channel ch_lst[NUM_CHANNELS] = {{0}}; 636 637 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 638 wifi_pos_pdev_iterator, 639 ch_lst, true, WLAN_WIFI_POS_CORE_ID); 640 641 for (i = 0; i < NUM_CHANNELS && num_ch < OEM_CAP_MAX_NUM_CHANNELS; 642 i++) { 643 if (ch_lst[i].state != CHANNEL_STATE_DISABLE && 644 ch_lst[i].state != CHANNEL_STATE_INVALID) { 645 num_ch++; 646 caps->channel_list[i] = ch_lst[i].chan_num; 647 } 648 } 649 650 caps->num_channels = num_ch; 651 wifi_pos_err("num channels: %d", num_ch); 652 } 653 654 QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc, 655 struct wifi_pos_driver_caps *caps) 656 { 657 struct wifi_pos_psoc_priv_obj *wifi_pos_obj = 658 wifi_pos_get_psoc_priv_obj(psoc); 659 660 wifi_pos_debug("Enter"); 661 if (!wifi_pos_obj) { 662 wifi_pos_err("wifi_pos_obj is null"); 663 return QDF_STATUS_E_NULL_VALUE; 664 } 665 666 strlcpy(caps->oem_target_signature, 667 OEM_TARGET_SIGNATURE, 668 OEM_TARGET_SIGNATURE_LEN); 669 caps->oem_target_type = wifi_pos_obj->oem_target_type; 670 caps->oem_fw_version = wifi_pos_obj->oem_fw_version; 671 caps->driver_version.major = wifi_pos_obj->driver_version.major; 672 caps->driver_version.minor = wifi_pos_obj->driver_version.minor; 673 caps->driver_version.patch = wifi_pos_obj->driver_version.patch; 674 caps->driver_version.build = wifi_pos_obj->driver_version.build; 675 caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min; 676 caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max; 677 caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min; 678 caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max; 679 caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc); 680 wifi_pos_get_ch_info(psoc, caps); 681 return QDF_STATUS_SUCCESS; 682 } 683