1 /* 2 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: Implements CM UTF 20 */ 21 22 #ifdef FEATURE_CM_UTF_ENABLE 23 #include <wlan_cm_utf.h> 24 #include <wlan_cm_api.h> 25 #include <qdf_str.h> 26 #include <wlan_cm_ucfg_api.h> 27 #include <include/wlan_mlme_cmn.h> 28 29 #define CM_UTF_LIST_SIZE 1 30 31 qdf_list_t wlan_cm_utf_list; 32 33 static const char *cm_utf_test_names[] = { 34 "CONNECT_SUCCESS", 35 "DISCONNECT_SUCCESS", 36 "PEER_CREATE_FAILURE", 37 "PEER_CREATE_TIMEOUT", 38 "PEER_DELETE_TIMEOUT", 39 "AUTH_FAILURE", 40 "AUTH_TIMEOUT", 41 "ASSOC_FAILURE", 42 "ASSOC_TIMEOUT", 43 "CONNECT_SCAN_FAILURE", 44 "CONNECT_SER_TIMEOUT", 45 "DISCONNECT_SER_TIMEOUT", 46 "CONNECT_SER_FAILED", 47 "DISCONNECT_SER_FAIL", 48 }; 49 50 /* Structure to maintain debug information */ 51 struct cm_utf_debugfs_info { 52 const char *name; 53 const struct file_operations *ops; 54 }; 55 56 #define DEBUG_FOO(func_base) { .name = #func_base, \ 57 .ops = &wlan_cm_utf_##func_base##_ops } 58 59 /* 60 * wlan_cm_utf_##func_base##_open() - Open debugfs entry for respective command 61 * and event buffer. 62 * @inode: node for debug dir entry 63 * @file: file handler 64 * 65 * Return: open status 66 */ 67 #define GENERATE_DEBUG_STRUCTS(func_base) \ 68 static int wlan_cm_utf_##func_base##_open(struct inode *inode, \ 69 struct file *file) \ 70 { \ 71 return single_open(file, wlan_cm_utf_##func_base##_show, \ 72 inode->i_private); \ 73 } \ 74 \ 75 static const struct file_operations wlan_cm_utf_##func_base##_ops = { \ 76 .open = wlan_cm_utf_##func_base##_open, \ 77 .read = seq_read, \ 78 .llseek = seq_lseek, \ 79 .write = wlan_cm_utf_##func_base##_write, \ 80 .release = single_release, \ 81 }; 82 83 GENERATE_DEBUG_STRUCTS(scan_db_update); 84 GENERATE_DEBUG_STRUCTS(cm_test_id); 85 86 struct cm_utf_debugfs_info cm_utf_debugfs_infos[NUM_UTF_DEBUGFS_INFOS] = { 87 DEBUG_FOO(scan_db_update), 88 DEBUG_FOO(cm_test_id), 89 }; 90 91 /** 92 * wlan_cm_utf_debugfs_create() - Create debugfs entry for cm db 93 * @cm_utf: CM UTF object 94 * 95 * Return: QDF_STATUS 96 */ 97 static QDF_STATUS wlan_cm_utf_debugfs_create(struct wlan_cm_utf *cm_utf) 98 { 99 struct wlan_objmgr_vdev *vdev = cm_utf->vdev; 100 struct wlan_objmgr_pdev *pdev; 101 uint8_t pdev_id; 102 uint8_t vdev_id; 103 char name[32]; 104 105 if (cm_utf->debugfs_de[0] || cm_utf->debugfs_de[1]) { 106 mlme_info("CM UTF debugfs file already exist"); 107 return QDF_STATUS_SUCCESS; 108 } 109 110 pdev = wlan_vdev_get_pdev(vdev); 111 if (!pdev) { 112 mlme_err("Pdev is Null"); 113 return QDF_STATUS_E_FAILURE; 114 } 115 116 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 117 vdev_id = wlan_vdev_get_id(vdev); 118 119 snprintf(name, sizeof(name), "CM_UTF_PDEV%u_VDEV%u_SCAN", 120 pdev_id, vdev_id); 121 cm_utf->debugfs_de[0] = debugfs_create_file( 122 name, 0644, qdf_debugfs_get_root(), 123 cm_utf, cm_utf_debugfs_infos[0].ops); 124 125 if (!cm_utf->debugfs_de[0]) { 126 mlme_err("Failed to create debugfs entry"); 127 return QDF_STATUS_E_FAILURE; 128 } 129 130 snprintf(name, sizeof(name), "CM_UTF_PDEV%u_VDEV%u_UTF", 131 pdev_id, vdev_id); 132 cm_utf->debugfs_de[1] = debugfs_create_file( 133 name, 0644, qdf_debugfs_get_root(), 134 cm_utf, cm_utf_debugfs_infos[1].ops); 135 136 if (!cm_utf->debugfs_de[1]) { 137 mlme_err("Failed to create debugfs entry"); 138 debugfs_remove(cm_utf->debugfs_de[0]); 139 cm_utf->debugfs_de[0] = NULL; 140 return QDF_STATUS_E_FAILURE; 141 } 142 143 return QDF_STATUS_SUCCESS; 144 } 145 146 /** 147 * wlan_cm_utf_debugfs_remove: Remove connection manager UTF debugfs entries 148 * @cm_utf: Connection Manager UTF object 149 * 150 * Return: None 151 */ 152 static void wlan_cm_utf_debugfs_remove(struct wlan_cm_utf *cm_utf) 153 { 154 if (cm_utf->debugfs_de[0]) { 155 qdf_debugfs_remove_file(cm_utf->debugfs_de[0]); 156 cm_utf->debugfs_de[0] = NULL; 157 } 158 159 if (cm_utf->debugfs_de[1]) { 160 qdf_debugfs_remove_file(cm_utf->debugfs_de[1]); 161 cm_utf->debugfs_de[1] = NULL; 162 } 163 } 164 165 /** 166 * wlan_cm_utf_bss_peer_create_rsp: Connection manager UTF bss peer 167 * create response 168 * @cm_utf: Connection Manager UTF object 169 * 170 * Return: None 171 */ 172 static void wlan_cm_utf_bss_peer_create_rsp(struct wlan_cm_utf *cm_utf) 173 { 174 struct qdf_mac_addr *peer_mac; 175 QDF_STATUS status; 176 177 peer_mac = cm_utf->utf_node.peer_mac; 178 switch (cm_utf->test_id) { 179 case CM_UTF_ID_PEER_CREATE_FAILURE: 180 status = QDF_STATUS_E_FAILURE; 181 break; 182 default: 183 status = QDF_STATUS_SUCCESS; 184 break; 185 } 186 wlan_cm_bss_peer_create_rsp(cm_utf->vdev, status, peer_mac); 187 } 188 189 /** 190 * wlan_cm_utf_bss_peer_delete_rsp: Connection manager UTF bss peer 191 * delete response 192 * @cm_utf: Connection Manager UTF object 193 * 194 * Return: None 195 */ 196 static void wlan_cm_utf_bss_peer_delete_rsp(struct wlan_cm_utf *cm_utf) 197 { 198 wlan_cm_bss_peer_delete_rsp(cm_utf->vdev, QDF_STATUS_SUCCESS); 199 } 200 201 /** 202 * wlan_cm_utf_connect_rsp: Connection manager UTF connect response 203 * @cm_utf: Connection Manager UTF object 204 * 205 * Return: None 206 */ 207 static void wlan_cm_utf_connect_rsp(struct wlan_cm_utf *cm_utf) 208 { 209 struct wlan_cm_connect_resp *cm_conn_rsp; 210 struct wlan_cm_vdev_connect_req conn_req = cm_utf->utf_node.conn_req; 211 212 cm_conn_rsp = qdf_mem_malloc(sizeof(struct wlan_cm_connect_resp)); 213 if (!cm_conn_rsp) { 214 mlme_err("failed ta allocate memory"); 215 return; 216 } 217 qdf_mem_zero(cm_conn_rsp, sizeof(struct wlan_cm_connect_resp)); 218 219 cm_conn_rsp->vdev_id = conn_req.vdev_id; 220 cm_conn_rsp->cm_id = conn_req.cm_id; 221 cm_conn_rsp->aid = 1; 222 cm_conn_rsp->connect_status = QDF_STATUS_E_FAILURE; 223 cm_conn_rsp->status_code = 0; 224 cm_conn_rsp->freq = conn_req.bss->entry->channel.chan_freq; 225 cm_conn_rsp->connect_ies.bcn_probe_rsp.ptr = 226 conn_req.bss->entry->raw_frame.ptr; 227 cm_conn_rsp->connect_ies.bcn_probe_rsp.len = 228 conn_req.bss->entry->raw_frame.len; 229 cm_conn_rsp->bssid = conn_req.bss->entry->bssid; 230 cm_conn_rsp->ssid = conn_req.bss->entry->ssid; 231 232 switch (cm_utf->test_id) { 233 case CM_UTF_ID_AUTH_FAILURE: 234 cm_conn_rsp->reason = CM_AUTH_FAILED; 235 break; 236 case CM_UTF_ID_AUTH_TIMEOUT: 237 cm_conn_rsp->reason = CM_AUTH_TIMEOUT; 238 break; 239 case CM_UTF_ID_ASSOC_FAILURE: 240 cm_conn_rsp->reason = CM_ASSOC_FAILED; 241 break; 242 case CM_UTF_ID_ASSOC_TIMEOUT: 243 cm_conn_rsp->reason = CM_ASSOC_TIMEOUT; 244 break; 245 default: 246 cm_conn_rsp->connect_status = QDF_STATUS_SUCCESS; 247 break; 248 } 249 wlan_cm_connect_rsp(cm_utf->vdev, cm_conn_rsp); 250 qdf_mem_free(cm_conn_rsp); 251 } 252 253 /** 254 * wlan_cm_utf_disconnect_rsp: Connection manager UTF disconnect response 255 * @cm_utf: Connection Manager UTF object 256 * 257 * Return: None 258 */ 259 static void wlan_cm_utf_disconnect_rsp(struct wlan_cm_utf *cm_utf) 260 { 261 struct wlan_cm_discon_rsp *cm_discon_rsp; 262 263 cm_discon_rsp = qdf_mem_malloc(sizeof(struct wlan_cm_discon_rsp)); 264 if (!cm_discon_rsp) { 265 mlme_err("failed ta allocate memory"); 266 return; 267 } 268 cm_discon_rsp->req = cm_utf->utf_node.disconn_req; 269 270 wlan_cm_disconnect_rsp(cm_utf->vdev, cm_discon_rsp); 271 qdf_mem_free(cm_discon_rsp); 272 } 273 274 /** 275 * wlan_cm_utf_peer_del_ind: Connection manager UTF peer delete indication 276 * @cm_utf: Connection Manager UTF object 277 * 278 * Return: None 279 */ 280 static void wlan_cm_utf_peer_del_ind(struct wlan_cm_utf *cm_utf) 281 { 282 struct qdf_mac_addr peer_mac; 283 284 peer_mac.bytes[0] = 0x1; 285 peer_mac.bytes[1] = 0x2; 286 peer_mac.bytes[2] = 0x3; 287 peer_mac.bytes[3] = 0x4; 288 peer_mac.bytes[4] = 0x5; 289 peer_mac.bytes[5] = 0x6; 290 291 wlan_cm_bss_peer_delete_ind(cm_utf->vdev, &peer_mac); 292 } 293 294 static void wlan_cm_utf_stop_test(void *arg) 295 { 296 struct wlan_cm_utf *cm_utf = (struct wlan_cm_utf *)arg; 297 298 mlme_err("No Response from CM"); 299 cm_utf->test_id = CM_UTF_ID_MAX; 300 } 301 302 static void wlan_cm_utf_deliver_event(void *arg) 303 { 304 struct wlan_cm_utf *cm_utf = (struct wlan_cm_utf *)arg; 305 306 qdf_sched_work(NULL, &cm_utf->cm_utf_work); 307 } 308 309 /** 310 * wlan_cm_utf_default_connect_param: Update default connect req params 311 * for connection manager UTF 312 * @cm_utf: Connection Manager UTF object 313 * 314 * Return: None 315 */ 316 static QDF_STATUS 317 wlan_cm_utf_default_connect_param(struct wlan_cm_utf *cm_utf) 318 { 319 cm_utf->req.vdev_id = wlan_vdev_get_id(cm_utf->vdev); 320 cm_utf->req.source = CM_OSIF_CONNECT; 321 cm_utf->req.bssid.bytes[0] = 0x1; 322 cm_utf->req.bssid.bytes[1] = 0x2; 323 cm_utf->req.bssid.bytes[2] = 0x3; 324 cm_utf->req.bssid.bytes[3] = 0x4; 325 cm_utf->req.bssid.bytes[4] = 0x5; 326 cm_utf->req.bssid.bytes[5] = 0x6; 327 cm_utf->req.ssid.length = 6; 328 qdf_str_lcopy(cm_utf->req.ssid.ssid, "CM_STA", cm_utf->req.ssid.length); 329 cm_utf->req.chan_freq = 5200; 330 cm_utf->req.crypto.wep_keys.key_len = 0; 331 return QDF_STATUS_SUCCESS; 332 } 333 334 static void wlan_cm_utf_work_cb(void *arg) 335 { 336 struct wlan_cm_utf *cm_utf = (struct wlan_cm_utf *)arg; 337 enum wlan_cm_utf_evt event_id = cm_utf->utf_node.evt_id; 338 339 switch (event_id) { 340 case CM_UTF_BSS_PEER_CREATE_RESP: 341 wlan_cm_utf_bss_peer_create_rsp(cm_utf); 342 break; 343 case CM_UTF_BSS_PEER_DELETE_RESP: 344 wlan_cm_utf_bss_peer_delete_rsp(cm_utf); 345 break; 346 case CM_UTF_CONNECT_RESP: 347 wlan_cm_utf_connect_rsp(cm_utf); 348 break; 349 case CM_UTF_DISCONNECT_RESP: 350 wlan_cm_utf_disconnect_rsp(cm_utf); 351 break; 352 case CM_UTF_PEER_DELETE_IND: 353 wlan_cm_utf_peer_del_ind(cm_utf); 354 break; 355 default: 356 break; 357 } 358 } 359 360 QDF_STATUS wlan_cm_utf_attach(struct wlan_objmgr_vdev *vdev) 361 { 362 struct wlan_cm_utf *cm_utf; 363 QDF_STATUS status; 364 365 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) { 366 mlme_err("Vdev is not a STA vdev"); 367 return QDF_STATUS_E_FAILURE; 368 } 369 370 if (qdf_list_size(&wlan_cm_utf_list) == CM_UTF_LIST_SIZE) { 371 mlme_err("List is at max size"); 372 return QDF_STATUS_E_FAILURE; 373 } 374 375 if (!qdf_list_size(&wlan_cm_utf_list)) 376 qdf_list_create(&wlan_cm_utf_list, CM_UTF_LIST_SIZE); 377 378 cm_utf = (struct wlan_cm_utf *) 379 qdf_mem_malloc(sizeof(struct wlan_cm_utf)); 380 381 if (!cm_utf) { 382 mlme_err("Failed to allocate CM utf context"); 383 qdf_list_destroy(&wlan_cm_utf_list); 384 return QDF_STATUS_E_NOMEM; 385 } 386 387 cm_utf->vdev = vdev; 388 cm_utf->test_id = CM_UTF_ID_MAX; 389 wlan_cm_utf_default_connect_param(cm_utf); 390 status = wlan_cm_utf_debugfs_create(cm_utf); 391 if (QDF_IS_STATUS_ERROR(status)) { 392 qdf_mem_free(cm_utf); 393 qdf_list_destroy(&wlan_cm_utf_list); 394 return status; 395 } 396 397 qdf_timer_init(NULL, &cm_utf->cm_utf_timer, 398 wlan_cm_utf_deliver_event, (void *)cm_utf, 399 QDF_TIMER_TYPE_WAKE_APPS); 400 401 qdf_timer_init(NULL, &cm_utf->cm_utf_test_timer, 402 wlan_cm_utf_stop_test, (void *)cm_utf, 403 QDF_TIMER_TYPE_WAKE_APPS); 404 405 qdf_create_work(NULL, &cm_utf->cm_utf_work, 406 wlan_cm_utf_work_cb, cm_utf); 407 408 qdf_list_insert_back(&wlan_cm_utf_list, &cm_utf->cm_utf_node); 409 mlme_err("CM UTF attach Success"); 410 return QDF_STATUS_SUCCESS; 411 } 412 413 static struct wlan_cm_utf *wlan_cm_get_utf(struct wlan_objmgr_vdev *vdev) 414 { 415 struct wlan_cm_utf *cm_utf; 416 qdf_list_node_t *node; 417 qdf_list_node_t *next_node; 418 419 if (!qdf_list_size(&wlan_cm_utf_list)) { 420 mlme_err("UTF list is empty"); 421 return NULL; 422 } 423 424 if (qdf_list_peek_front(&wlan_cm_utf_list, &next_node) 425 != QDF_STATUS_SUCCESS) { 426 mlme_err("UTF list is empty"); 427 return NULL; 428 } 429 430 do { 431 node = next_node; 432 cm_utf = qdf_container_of(node, struct wlan_cm_utf, 433 cm_utf_node); 434 if (cm_utf->vdev == vdev) 435 return cm_utf; 436 } while (qdf_list_peek_next(&wlan_cm_utf_list, node, &next_node) 437 == QDF_STATUS_SUCCESS); 438 439 return NULL; 440 } 441 442 void wlan_cm_utf_detach(struct wlan_objmgr_vdev *vdev) 443 { 444 struct wlan_cm_utf *cm_utf; 445 QDF_STATUS status; 446 447 cm_utf = wlan_cm_get_utf(vdev); 448 if (!cm_utf) { 449 mlme_err("UTF not initialized for the vdev %d", 450 wlan_vdev_get_id(vdev)); 451 return; 452 } 453 454 status = qdf_list_remove_node(&wlan_cm_utf_list, 455 &cm_utf->cm_utf_node); 456 if (QDF_IS_STATUS_SUCCESS(status)) { 457 qdf_timer_free(&cm_utf->cm_utf_timer); 458 qdf_timer_free(&cm_utf->cm_utf_test_timer); 459 460 if (cm_utf->req.assoc_ie.ptr) { 461 qdf_mem_free(cm_utf->req.assoc_ie.ptr); 462 cm_utf->req.assoc_ie.ptr = NULL; 463 } 464 465 if (cm_utf->req.crypto.wep_keys.key) { 466 qdf_mem_free(cm_utf->req.crypto.wep_keys.key); 467 cm_utf->req.crypto.wep_keys.key = NULL; 468 } 469 470 qdf_disable_work(&cm_utf->cm_utf_work); 471 wlan_cm_utf_debugfs_remove(cm_utf); 472 qdf_mem_free(cm_utf); 473 mlme_err("CM UTF Deinit Success"); 474 return; 475 } 476 477 mlme_err("Failed to remove UTF node"); 478 } 479 480 QDF_STATUS wlan_cm_utf_bss_peer_create_req(struct wlan_objmgr_vdev *vdev, 481 struct qdf_mac_addr *peer_mac) 482 { 483 struct wlan_cm_utf *cm_utf; 484 485 cm_utf = wlan_cm_get_utf(vdev); 486 if (!cm_utf) { 487 mlme_err("cm_utf is Null"); 488 return QDF_STATUS_E_FAILURE; 489 } 490 491 switch (cm_utf->test_id) { 492 case CM_UTF_ID_PEER_CREATE_TIMEOUT: 493 break; 494 default: 495 cm_utf->utf_node.peer_mac = peer_mac; 496 cm_utf->utf_node.evt_id = CM_UTF_BSS_PEER_CREATE_RESP; 497 qdf_timer_start(&cm_utf->cm_utf_timer, 100); 498 break; 499 } 500 return QDF_STATUS_SUCCESS; 501 } 502 503 QDF_STATUS wlan_cm_utf_connect_req_active( 504 struct wlan_objmgr_vdev *vdev, 505 struct wlan_cm_vdev_connect_req *vdev_connect_req) 506 { 507 //Resp API to be added 508 return QDF_STATUS_SUCCESS; 509 } 510 511 QDF_STATUS wlan_cm_utf_connect_req( 512 struct wlan_objmgr_vdev *vdev, 513 struct wlan_cm_vdev_connect_req *vdev_connect_req) 514 { 515 struct wlan_cm_utf *cm_utf; 516 517 cm_utf = wlan_cm_get_utf(vdev); 518 if (!cm_utf) { 519 mlme_err("cm_utf is Null"); 520 return QDF_STATUS_E_FAILURE; 521 } 522 523 switch (cm_utf->test_id) { 524 case CM_UTF_ID_CONNECT_SER_TIMEOUT: 525 break; 526 default: 527 qdf_mem_copy(&cm_utf->utf_node.conn_req, vdev_connect_req, 528 sizeof(struct wlan_cm_vdev_connect_req)); 529 cm_utf->utf_node.evt_id = CM_UTF_CONNECT_RESP; 530 qdf_timer_start(&cm_utf->cm_utf_timer, 100); 531 break; 532 } 533 return QDF_STATUS_SUCCESS; 534 } 535 536 QDF_STATUS wlan_cm_utf_disconnect_req( 537 struct wlan_objmgr_vdev *vdev, 538 struct wlan_cm_vdev_discon_req *vdev_disconnect_req) 539 { 540 struct wlan_cm_utf *cm_utf; 541 542 cm_utf = wlan_cm_get_utf(vdev); 543 if (!cm_utf) { 544 mlme_err("cm_utf is Null"); 545 return QDF_STATUS_E_FAILURE; 546 } 547 548 switch (cm_utf->test_id) { 549 case CM_UTF_ID_DISCONNECT_SER_TIMEOUT: 550 break; 551 default: 552 qdf_mem_copy(&cm_utf->utf_node.disconn_req, vdev_disconnect_req, 553 sizeof(struct wlan_cm_vdev_discon_req)); 554 cm_utf->utf_node.evt_id = CM_UTF_PEER_DELETE_IND; 555 qdf_timer_start(&cm_utf->cm_utf_timer, 100); 556 break; 557 } 558 return QDF_STATUS_SUCCESS; 559 } 560 561 QDF_STATUS wlan_cm_utf_bss_peer_delete_req(struct wlan_objmgr_vdev *vdev) 562 { 563 struct wlan_cm_utf *cm_utf; 564 565 cm_utf = wlan_cm_get_utf(vdev); 566 if (!cm_utf) { 567 mlme_err("cm_utf is Null"); 568 return QDF_STATUS_E_FAILURE; 569 } 570 571 switch (cm_utf->test_id) { 572 case CM_UTF_ID_PEER_DELETE_TIMEOUT: 573 break; 574 default: 575 cm_utf->utf_node.evt_id = CM_UTF_BSS_PEER_DELETE_RESP; 576 qdf_timer_start(&cm_utf->cm_utf_timer, 100); 577 break; 578 } 579 return QDF_STATUS_SUCCESS; 580 } 581 582 QDF_STATUS wlan_cm_utf_vdev_down(struct wlan_objmgr_vdev *vdev) 583 { 584 struct wlan_cm_utf *cm_utf; 585 586 cm_utf = wlan_cm_get_utf(vdev); 587 if (!cm_utf) { 588 mlme_err("cm_utf is Null"); 589 return QDF_STATUS_E_FAILURE; 590 } 591 592 switch (cm_utf->test_id) { 593 default: 594 cm_utf->utf_node.evt_id = CM_UTF_DISCONNECT_RESP; 595 qdf_timer_start(&cm_utf->cm_utf_timer, 100); 596 break; 597 } 598 return QDF_STATUS_SUCCESS; 599 } 600 601 static 602 QDF_STATUS wlan_cm_utf_validate_test(struct wlan_cm_utf *cm_utf, 603 struct wlan_cm_connect_resp *cm_conn_rsp) 604 { 605 QDF_STATUS status = QDF_STATUS_E_FAILURE; 606 607 switch (cm_utf->test_id) { 608 case CM_UTF_ID_PEER_CREATE_FAILURE: 609 case CM_UTF_ID_PEER_CREATE_TIMEOUT: 610 if (cm_conn_rsp->reason == CM_PEER_CREATE_FAILED) { 611 // check (CM state to be valid as per test in all cases) 612 status = QDF_STATUS_SUCCESS; 613 } 614 break; 615 case CM_UTF_ID_CONNECT_SER_TIMEOUT: 616 case CM_UTF_ID_CONNECT_SER_FAILED: 617 if (cm_conn_rsp->reason == CM_SER_FAILURE) 618 status = QDF_STATUS_SUCCESS; 619 break; 620 case CM_UTF_ID_CONNECT_SCAN_FAILURE: 621 if (cm_conn_rsp->reason == CM_NO_CANDIDATE_FOUND) 622 status = QDF_STATUS_SUCCESS; 623 break; 624 case CM_UTF_ID_AUTH_FAILURE: 625 if (cm_conn_rsp->reason == CM_AUTH_FAILED) 626 status = QDF_STATUS_SUCCESS; 627 break; 628 case CM_UTF_ID_AUTH_TIMEOUT: 629 if (cm_conn_rsp->reason == CM_AUTH_TIMEOUT) 630 status = QDF_STATUS_SUCCESS; 631 break; 632 case CM_UTF_ID_ASSOC_FAILURE: 633 if (cm_conn_rsp->reason == CM_ASSOC_FAILED) 634 status = QDF_STATUS_SUCCESS; 635 break; 636 case CM_UTF_ID_ASSOC_TIMEOUT: 637 if (cm_conn_rsp->reason == CM_ASSOC_TIMEOUT) 638 status = QDF_STATUS_SUCCESS; 639 break; 640 default: 641 if (cm_conn_rsp->connect_status == QDF_STATUS_SUCCESS) 642 status = QDF_STATUS_SUCCESS; 643 break; 644 } 645 646 return status; 647 } 648 649 /** 650 * wlan_cm_utf_osif_connect_cb: Connection manager UTF 651 * connect callback handler 652 * @vdev: VDEV object 653 * @cm_conn_rsp: Connect Response 654 * 655 * Return: None 656 */ 657 static QDF_STATUS 658 wlan_cm_utf_osif_connect_cb(struct wlan_objmgr_vdev *vdev, 659 struct wlan_cm_connect_resp *cm_conn_rsp) 660 { 661 struct wlan_cm_utf *cm_utf; 662 QDF_STATUS status = QDF_STATUS_E_FAILURE; 663 664 cm_utf = wlan_cm_get_utf(vdev); 665 if (!cm_utf) { 666 mlme_err("cm_utf is Null"); 667 return QDF_STATUS_E_FAILURE; 668 } 669 670 if (cm_conn_rsp->cm_id != cm_utf->last_cmd_id || 671 cm_utf->last_cmd_source != CM_OSIF_CONNECT) { 672 mlme_err("Incorrect cmd id/source"); 673 return QDF_STATUS_E_FAILURE; 674 } 675 676 status = wlan_cm_utf_validate_test(cm_utf, cm_conn_rsp); 677 if (status == QDF_STATUS_SUCCESS) 678 mlme_err("Test case Success for Test: %s", 679 cm_utf_test_names[cm_utf->test_id]); 680 else 681 mlme_err("Test case Failed for Test: %s", 682 cm_utf_test_names[cm_utf->test_id]); 683 684 qdf_timer_stop(&cm_utf->cm_utf_test_timer); 685 cm_utf->test_id = CM_UTF_ID_MAX; 686 687 return status; 688 } 689 690 /** 691 * wlan_cm_utf_osif_disconnect_cb: Connection manager UTF 692 * disconnect callback handler 693 * @vdev: VDEV object 694 * @cm_disconn_rsp: Disconnect Response 695 * 696 * Return: None 697 */ 698 static QDF_STATUS wlan_cm_utf_osif_disconnect_cb( 699 struct wlan_objmgr_vdev *vdev, 700 struct wlan_cm_discon_rsp *cm_disconn_rsp) 701 { 702 struct wlan_cm_utf *cm_utf; 703 704 cm_utf = wlan_cm_get_utf(vdev); 705 if (!cm_utf) { 706 mlme_err("cm_utf is Null"); 707 return QDF_STATUS_E_FAILURE; 708 } 709 710 if (cm_disconn_rsp->req.cm_id != cm_utf->last_cmd_id || 711 cm_disconn_rsp->req.req.source != cm_utf->last_cmd_source) { 712 mlme_err("Incorrect cmd id/source"); 713 return QDF_STATUS_E_FAILURE; 714 } 715 716 mlme_err("Test case Success for Test: %s", 717 cm_utf_test_names[cm_utf->test_id]); 718 qdf_timer_stop(&cm_utf->cm_utf_test_timer); 719 cm_utf->test_id = CM_UTF_ID_MAX; 720 721 return QDF_STATUS_SUCCESS; 722 } 723 724 /** 725 * wlan_cm_utf_update_conn_id_and_src_cb: Connection manager UTF 726 * callback to update connect id and source of the connect request 727 * @vdev: VDEV object 728 * @source: connect source 729 * @cm_id: connect id 730 * 731 * Return: None 732 */ 733 static QDF_STATUS wlan_cm_utf_update_conn_id_and_src_cb( 734 struct wlan_objmgr_vdev *vdev, 735 enum wlan_cm_source source, wlan_cm_id cm_id) 736 { 737 struct wlan_cm_utf *cm_utf; 738 739 cm_utf = wlan_cm_get_utf(vdev); 740 if (!cm_utf) { 741 mlme_err("cm_utf is Null"); 742 return QDF_STATUS_E_FAILURE; 743 } 744 745 cm_utf->last_cmd_id = cm_id; 746 cm_utf->last_cmd_source = source; 747 748 return QDF_STATUS_SUCCESS; 749 } 750 751 static struct mlme_cm_ops cm_ops = { 752 .mlme_cm_connect_complete_cb = wlan_cm_utf_osif_connect_cb, 753 .mlme_cm_failed_candidate_cb = NULL, 754 .mlme_cm_update_id_and_src_cb = 755 wlan_cm_utf_update_conn_id_and_src_cb, 756 .mlme_cm_disconnect_complete_cb = wlan_cm_utf_osif_disconnect_cb, 757 .mlme_cm_disconnect_start_cb = NULL, 758 }; 759 760 static struct mlme_cm_ops *osif_cm_get_global_ops(void) 761 { 762 return &cm_ops; 763 } 764 765 QDF_STATUS osif_cm_utf_register_cb(void) 766 { 767 mlme_set_osif_cm_cb(osif_cm_get_global_ops); 768 return QDF_STATUS_SUCCESS; 769 } 770 771 /** 772 * wlan_cm_utf_update_connect_param: API to update connect req params 773 * @cm_utf: CM UTF object 774 * @buffer: user input buffer 775 * 776 * Return: None 777 * 778 */ 779 static void 780 wlan_cm_utf_update_connect_param(struct wlan_cm_utf *cm_utf, char *buffer) 781 { 782 char *token; 783 uint8_t idx = 0; 784 785 token = qdf_str_sep(&buffer, "\n"); 786 787 if (!token) { 788 mlme_err("Invalid Parameters"); 789 return; 790 } 791 792 if (cm_utf->req.assoc_ie.ptr) { 793 qdf_mem_free(cm_utf->req.assoc_ie.ptr); 794 cm_utf->req.assoc_ie.ptr = NULL; 795 } 796 797 if (cm_utf->req.crypto.wep_keys.key) { 798 qdf_mem_free(cm_utf->req.crypto.wep_keys.key); 799 cm_utf->req.crypto.wep_keys.key = NULL; 800 } 801 802 qdf_mem_zero(cm_utf->req.ssid.ssid, WLAN_SSID_MAX_LEN); 803 if (sscanf(token, "%2x:%2x:%2x:%2x:%2x:%2x ,%2x:%2x:%2x:%2x:%2x:%2x " 804 ",%2x:%2x:%2x:%2x:%2x:%2x ,%u ,%u ,%u ,%u ,%u ,%u ,%u ,%u " 805 ",%u ,%u ,%u ,%u ,%u ,%s", 806 (unsigned int *)&cm_utf->req.bssid.bytes[0], 807 (unsigned int *)&cm_utf->req.bssid.bytes[1], 808 (unsigned int *)&cm_utf->req.bssid.bytes[2], 809 (unsigned int *)&cm_utf->req.bssid.bytes[3], 810 (unsigned int *)&cm_utf->req.bssid.bytes[4], 811 (unsigned int *)&cm_utf->req.bssid.bytes[5], 812 (unsigned int *)&cm_utf->req.prev_bssid.bytes[0], 813 (unsigned int *)&cm_utf->req.prev_bssid.bytes[1], 814 (unsigned int *)&cm_utf->req.prev_bssid.bytes[2], 815 (unsigned int *)&cm_utf->req.prev_bssid.bytes[3], 816 (unsigned int *)&cm_utf->req.prev_bssid.bytes[4], 817 (unsigned int *)&cm_utf->req.prev_bssid.bytes[5], 818 (unsigned int *)&cm_utf->req.bssid_hint.bytes[0], 819 (unsigned int *)&cm_utf->req.bssid_hint.bytes[1], 820 (unsigned int *)&cm_utf->req.bssid_hint.bytes[2], 821 (unsigned int *)&cm_utf->req.bssid_hint.bytes[3], 822 (unsigned int *)&cm_utf->req.bssid_hint.bytes[4], 823 (unsigned int *)&cm_utf->req.bssid_hint.bytes[5], 824 &cm_utf->req.chan_freq, 825 &cm_utf->req.crypto.wpa_versions, 826 &cm_utf->req.crypto.auth_type, 827 &cm_utf->req.crypto.group_cipher, 828 &cm_utf->req.crypto.ciphers_pairwise, 829 &cm_utf->req.crypto.akm_suites, 830 (unsigned int *)&cm_utf->req.crypto.rsn_caps, 831 &cm_utf->req.crypto.mgmt_ciphers, 832 (unsigned int *)&cm_utf->req.ht_caps, 833 (unsigned int *)&cm_utf->req.ht_caps_mask, 834 &cm_utf->req.vht_caps, 835 &cm_utf->req.vht_caps_mask, 836 (unsigned int *)&cm_utf->req.ssid.length, 837 cm_utf->req.ssid.ssid) != 32) { 838 mlme_err("Invalid connect req params"); 839 return; 840 } 841 842 qdf_err("Updated connect params %s", buffer); 843 while ((token = qdf_str_sep(&buffer, ",")) != NULL) { 844 switch (idx) { 845 case 0: 846 if (sscanf(token, "%u", &cm_utf->req.assoc_ie.len) != 1) 847 return; 848 if (!cm_utf->req.assoc_ie.len) { 849 idx += 2; 850 break; 851 } 852 idx++; 853 break; 854 case 1: 855 cm_utf->req.assoc_ie.ptr = 856 (uint8_t *)qdf_mem_malloc(cm_utf->req.assoc_ie.len); 857 if (!cm_utf->req.assoc_ie.ptr) { 858 mlme_err("Failed to alloc memory"); 859 return; 860 } 861 qdf_mem_copy(cm_utf->req.assoc_ie.ptr, token, 862 cm_utf->req.assoc_ie.len); 863 idx++; 864 break; 865 case 2: 866 if (sscanf(token, "%u", 867 (unsigned int *)&cm_utf->req.crypto.wep_keys.key_len) != 1) 868 return; 869 if (!cm_utf->req.crypto.wep_keys.key_len) 870 return; 871 idx++; 872 break; 873 case 3: 874 cm_utf->req.crypto.wep_keys.key = 875 (uint8_t *)qdf_mem_malloc(cm_utf->req.crypto.wep_keys.key_len); 876 if (!cm_utf->req.crypto.wep_keys.key) { 877 mlme_err("Failed to alloc memory"); 878 return; 879 } 880 qdf_mem_copy(cm_utf->req.crypto.wep_keys.key, token, 881 cm_utf->req.crypto.wep_keys.key_len); 882 break; 883 default: 884 break; 885 } 886 } 887 } 888 889 /** 890 * wlan_cm_utf_start_test: Connection manager UTF entry function 891 * @cm_utf: Connection Manager UTF object 892 * @buffer: test command buffer 893 * 894 */ 895 static void wlan_cm_utf_start_test(struct wlan_cm_utf *cm_utf, void *buffer) 896 { 897 int reason = 0, ret; 898 uint8_t i = 0; 899 char *token; 900 char *token2; 901 char *buff = (char *)buffer; 902 struct wlan_cm_disconnect_req req; 903 904 if (cm_utf->test_id != CM_UTF_ID_MAX) { 905 mlme_err("Test Already in progress"); 906 return; 907 } 908 909 token = qdf_str_sep(&buff, " "); 910 if (token) { 911 if (!qdf_str_cmp(token, "CONNECT_REQ")) { 912 mlme_err("Update Connect Params"); 913 wlan_cm_utf_update_connect_param(cm_utf, buff); 914 return; 915 } 916 917 token2 = qdf_str_sep(&token, "\n"); 918 for (i = 0; i < CM_UTF_ID_MAX; i++) { 919 if (!qdf_str_cmp(token2, cm_utf_test_names[i])) { 920 cm_utf->test_id = i; 921 break; 922 } 923 } 924 } 925 926 if (cm_utf->test_id == CM_UTF_ID_MAX) { 927 mlme_err("Invalid Test Case"); 928 return; 929 } 930 931 mlme_err("Test ID: %d", cm_utf->test_id); 932 switch (cm_utf->test_id) { 933 case CM_UTF_ID_CONNECT_SUCCESS: 934 case CM_UTF_ID_PEER_CREATE_FAILURE: 935 case CM_UTF_ID_PEER_CREATE_TIMEOUT: 936 case CM_UTF_ID_AUTH_FAILURE: 937 case CM_UTF_ID_AUTH_TIMEOUT: 938 case CM_UTF_ID_ASSOC_FAILURE: 939 case CM_UTF_ID_ASSOC_TIMEOUT: 940 case CM_UTF_ID_CONNECT_SCAN_FAILURE: 941 case CM_UTF_ID_CONNECT_SER_TIMEOUT: 942 case CM_UTF_ID_CONNECT_SER_FAILED: 943 cm_utf->req.vdev_id = wlan_vdev_get_id(cm_utf->vdev); 944 cm_utf->req.source = CM_OSIF_CONNECT; 945 ucfg_cm_start_connect(cm_utf->vdev, &cm_utf->req); 946 break; 947 case CM_UTF_ID_DISCONNECT_SUCCESS: 948 case CM_UTF_ID_DISCONNECT_SER_TIMEOUT: 949 case CM_UTF_ID_DISCONNECT_SER_FAILED: 950 case CM_UTF_ID_PEER_DELETE_TIMEOUT: 951 token = qdf_str_sep(&buff, " "); 952 if (!token) { 953 mlme_err("Provide reason code for disconnect"); 954 cm_utf->test_id = CM_UTF_ID_MAX; 955 return; 956 } else { 957 ret = qdf_kstrtoint(token, 0, &reason); 958 if (ret) { 959 mlme_err("Invalid disconnect reason"); 960 cm_utf->test_id = CM_UTF_ID_MAX; 961 return; 962 } 963 } 964 mlme_err("Disconnect reason %d", reason); 965 req.vdev_id = wlan_vdev_get_id(cm_utf->vdev); 966 req.source = CM_OSIF_DISCONNECT; 967 req.reason_code = reason; 968 ucfg_cm_start_disconnect(cm_utf->vdev, &req); 969 break; 970 default: 971 mlme_err("Invalid test ID"); 972 cm_utf->test_id = CM_UTF_ID_MAX; 973 qdf_timer_stop(&cm_utf->cm_utf_test_timer); 974 break; 975 } 976 977 if (cm_utf->test_id == CM_UTF_ID_PEER_DELETE_TIMEOUT || 978 cm_utf->test_id == CM_UTF_ID_PEER_CREATE_TIMEOUT || 979 cm_utf->test_id == CM_UTF_ID_DISCONNECT_SER_TIMEOUT || 980 cm_utf->test_id == CM_UTF_ID_CONNECT_SER_TIMEOUT) 981 qdf_timer_start(&cm_utf->cm_utf_test_timer, 70000); 982 else 983 qdf_timer_start(&cm_utf->cm_utf_test_timer, 10000); 984 } 985 986 int wlan_cm_utf_cm_test_id_show(qdf_debugfs_file_t m, void *v) 987 { 988 uint8_t i; 989 990 mlme_nofl_err("Usage:"); 991 for (i = 0; i < CM_UTF_ID_MAX; i++) { 992 switch (i) { 993 case CM_UTF_ID_DISCONNECT_SUCCESS: 994 case CM_UTF_ID_DISCONNECT_SER_TIMEOUT: 995 case CM_UTF_ID_DISCONNECT_SER_FAILED: 996 case CM_UTF_ID_PEER_DELETE_TIMEOUT: 997 mlme_nofl_err("%22s <reason>", cm_utf_test_names[i]); 998 break; 999 default: 1000 mlme_nofl_err("%22s", cm_utf_test_names[i]); 1001 break; 1002 } 1003 } 1004 return 0; 1005 } 1006 1007 ssize_t wlan_cm_utf_cm_test_id_write(struct file *file, 1008 const char __user *buf, 1009 size_t count, loff_t *ppos) 1010 { 1011 struct wlan_cm_utf *cm_utf = 1012 ((struct seq_file *)file->private_data)->private; 1013 char *locbuf; 1014 1015 if ((!buf) || (count <= 0)) 1016 return -EFAULT; 1017 1018 locbuf = (char *)qdf_mem_malloc(count + 1); 1019 1020 if (!locbuf) 1021 return -EFAULT; 1022 1023 qdf_mem_zero(locbuf, count + 1); 1024 1025 if (copy_from_user(locbuf, buf, count)) 1026 return -EFAULT; 1027 1028 mlme_err("CM Start Test"); 1029 wlan_cm_utf_start_test(cm_utf, locbuf); 1030 qdf_mem_free(locbuf); 1031 1032 return count; 1033 } 1034 #endif 1035