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 */
wlan_cm_utf_debugfs_create(struct wlan_cm_utf * cm_utf)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 */
wlan_cm_utf_debugfs_remove(struct wlan_cm_utf * cm_utf)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 */
wlan_cm_utf_bss_peer_create_rsp(struct wlan_cm_utf * cm_utf)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 */
wlan_cm_utf_bss_peer_delete_rsp(struct wlan_cm_utf * cm_utf)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 */
wlan_cm_utf_connect_rsp(struct wlan_cm_utf * cm_utf)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 */
wlan_cm_utf_disconnect_rsp(struct wlan_cm_utf * cm_utf)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 */
wlan_cm_utf_peer_del_ind(struct wlan_cm_utf * cm_utf)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
wlan_cm_utf_stop_test(void * arg)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
wlan_cm_utf_deliver_event(void * arg)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
wlan_cm_utf_default_connect_param(struct wlan_cm_utf * cm_utf)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
wlan_cm_utf_work_cb(void * arg)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
wlan_cm_utf_attach(struct wlan_objmgr_vdev * vdev)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
wlan_cm_get_utf(struct wlan_objmgr_vdev * vdev)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
wlan_cm_utf_detach(struct wlan_objmgr_vdev * vdev)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
wlan_cm_utf_bss_peer_create_req(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * peer_mac)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
wlan_cm_utf_connect_req_active(struct wlan_objmgr_vdev * vdev,struct wlan_cm_vdev_connect_req * vdev_connect_req)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
wlan_cm_utf_connect_req(struct wlan_objmgr_vdev * vdev,struct wlan_cm_vdev_connect_req * vdev_connect_req)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
wlan_cm_utf_disconnect_req(struct wlan_objmgr_vdev * vdev,struct wlan_cm_vdev_discon_req * vdev_disconnect_req)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
wlan_cm_utf_bss_peer_delete_req(struct wlan_objmgr_vdev * vdev)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
wlan_cm_utf_vdev_down(struct wlan_objmgr_vdev * vdev)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
wlan_cm_utf_validate_test(struct wlan_cm_utf * cm_utf,struct wlan_cm_connect_resp * cm_conn_rsp)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
wlan_cm_utf_osif_connect_cb(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_resp * cm_conn_rsp)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 */
wlan_cm_utf_osif_disconnect_cb(struct wlan_objmgr_vdev * vdev,struct wlan_cm_discon_rsp * cm_disconn_rsp)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 */
wlan_cm_utf_update_conn_id_and_src_cb(struct wlan_objmgr_vdev * vdev,enum wlan_cm_source source,wlan_cm_id cm_id)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
osif_cm_get_global_ops(void)760 static struct mlme_cm_ops *osif_cm_get_global_ops(void)
761 {
762 return &cm_ops;
763 }
764
osif_cm_utf_register_cb(void)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
wlan_cm_utf_update_connect_param(struct wlan_cm_utf * cm_utf,char * buffer)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 */
wlan_cm_utf_start_test(struct wlan_cm_utf * cm_utf,void * buffer)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
wlan_cm_utf_cm_test_id_show(qdf_debugfs_file_t m,void * v)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
wlan_cm_utf_cm_test_id_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)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