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