1 /*
2  * Copyright (c) 2018 Intel Corporation
3  * Copyright 2024 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /** @file
9  * @brief WiFi shell module
10  */
11 
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF);
14 
15 #include <zephyr/kernel.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <strings.h>
20 #include <zephyr/shell/shell.h>
21 #include <zephyr/sys/printk.h>
22 #include <zephyr/init.h>
23 
24 #include <zephyr/net/net_if.h>
25 #include <zephyr/net/net_event.h>
26 #include <zephyr/net/wifi_mgmt.h>
27 #include <zephyr/net/wifi_utils.h>
28 #include <zephyr/posix/unistd.h>
29 #include <zephyr/sys/slist.h>
30 
31 #include "net_shell_private.h"
32 #include <math.h>
33 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
34 static const char ca_cert_test[] = {
35 	#include <wifi_enterprise_test_certs/ca.pem.inc>
36 	'\0'
37 };
38 
39 static const char client_cert_test[] = {
40 	#include <wifi_enterprise_test_certs/client.pem.inc>
41 	'\0'
42 };
43 
44 static const char client_key_test[] = {
45 	#include <wifi_enterprise_test_certs/client-key.pem.inc>
46 	'\0'
47 };
48 
49 static const char ca_cert2_test[] = {
50 	#include <wifi_enterprise_test_certs/ca2.pem.inc>
51 	'\0'};
52 
53 static const char client_cert2_test[] = {
54 	#include <wifi_enterprise_test_certs/client2.pem.inc>
55 	'\0'};
56 
57 static const char client_key2_test[] = {
58 	#include <wifi_enterprise_test_certs/client-key2.pem.inc>
59 	'\0'};
60 
61 static const char server_cert_test[] = {
62 	#include <wifi_enterprise_test_certs/server.pem.inc>
63 	'\0'
64 };
65 
66 static const char server_key_test[] = {
67 	#include <wifi_enterprise_test_certs/server-key.pem.inc>
68 	'\0'
69 };
70 #endif
71 
72 #define WIFI_SHELL_MODULE "wifi"
73 
74 #define WIFI_SHELL_MGMT_EVENTS_COMMON (NET_EVENT_WIFI_SCAN_DONE   |\
75 				NET_EVENT_WIFI_CONNECT_RESULT     |\
76 				NET_EVENT_WIFI_DISCONNECT_RESULT  |\
77 				NET_EVENT_WIFI_TWT                |\
78 				NET_EVENT_WIFI_RAW_SCAN_RESULT    |\
79 				NET_EVENT_WIFI_AP_ENABLE_RESULT   |\
80 				NET_EVENT_WIFI_AP_DISABLE_RESULT  |\
81 				NET_EVENT_WIFI_AP_STA_CONNECTED   |\
82 				NET_EVENT_WIFI_AP_STA_DISCONNECTED)
83 
84 #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY
85 #define WIFI_SHELL_MGMT_EVENTS (WIFI_SHELL_MGMT_EVENTS_COMMON)
86 #else
87 #define WIFI_SHELL_MGMT_EVENTS (WIFI_SHELL_MGMT_EVENTS_COMMON |\
88 				NET_EVENT_WIFI_SCAN_RESULT)
89 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS_ONLY */
90 
91 #define MAX_BANDS_STR_LEN 64
92 
93 static struct {
94 	const struct shell *sh;
95 	uint32_t scan_result;
96 
97 	union {
98 		struct {
99 			uint8_t connecting: 1;
100 			uint8_t disconnecting: 1;
101 			uint8_t _unused: 6;
102 		};
103 		uint8_t all;
104 	};
105 } context;
106 
107 static struct net_mgmt_event_callback wifi_shell_mgmt_cb;
108 static struct wifi_reg_chan_info chan_info[MAX_REG_CHAN_NUM];
109 
110 static K_MUTEX_DEFINE(wifi_ap_sta_list_lock);
111 struct wifi_ap_sta_node {
112 	bool valid;
113 	struct wifi_ap_sta_info sta_info;
114 };
115 static struct wifi_ap_sta_node sta_list[CONFIG_WIFI_SHELL_MAX_AP_STA];
116 
117 
118 #if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \
119 	defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE
cmd_wifi_set_enterprise_creds(const struct shell * sh,struct net_if * iface)120 static int cmd_wifi_set_enterprise_creds(const struct shell *sh, struct net_if *iface)
121 {
122 	struct wifi_enterprise_creds_params params = {0};
123 
124 	params.ca_cert = (uint8_t *)ca_cert_test;
125 	params.ca_cert_len = ARRAY_SIZE(ca_cert_test);
126 	params.client_cert = (uint8_t *)client_cert_test;
127 	params.client_cert_len = ARRAY_SIZE(client_cert_test);
128 	params.client_key = (uint8_t *)client_key_test;
129 	params.client_key_len = ARRAY_SIZE(client_key_test);
130 	params.ca_cert2 = (uint8_t *)ca_cert2_test;
131 	params.ca_cert2_len = ARRAY_SIZE(ca_cert2_test);
132 	params.client_cert2 = (uint8_t *)client_cert2_test;
133 	params.client_cert2_len = ARRAY_SIZE(client_cert2_test);
134 	params.client_key2 = (uint8_t *)client_key2_test;
135 	params.client_key2_len = ARRAY_SIZE(client_key2_test);
136 	params.server_cert = (uint8_t *)server_cert_test;
137 	params.server_cert_len = ARRAY_SIZE(server_cert_test);
138 	params.server_key = (uint8_t *)server_key_test;
139 	params.server_key_len = ARRAY_SIZE(server_key_test);
140 
141 	if (net_mgmt(NET_REQUEST_WIFI_ENTERPRISE_CREDS, iface, &params, sizeof(params))) {
142 		PR_WARNING("Set enterprise credentials failed\n");
143 		return -1;
144 	}
145 
146 	return 0;
147 }
148 #endif
149 
parse_number(const struct shell * sh,long * param,char * str,char * pname,long min,long max)150 static bool parse_number(const struct shell *sh, long *param, char *str,
151 			 char *pname, long min, long max)
152 {
153 	char *endptr;
154 	char *str_tmp = str;
155 	long num;
156 
157 	if ((str_tmp[0] == '0') && (str_tmp[1] == 'x')) {
158 		/* Hexadecimal numbers take base 0 in strtol */
159 		num = strtol(str_tmp, &endptr, 0);
160 	} else {
161 		num = strtol(str_tmp, &endptr, 10);
162 	}
163 
164 	if (*endptr != '\0') {
165 		PR_ERROR("Invalid number: %s\n", str_tmp);
166 		return false;
167 	}
168 
169 	if ((num) < (min) || (num) > (max)) {
170 		if (pname) {
171 			PR_WARNING("%s value out of range: %s, (%ld-%ld)\n",
172 				   pname, str_tmp, min, max);
173 		} else {
174 			PR_WARNING("Value out of range: %s, (%ld-%ld)\n",
175 				   str_tmp, min, max);
176 		}
177 		return false;
178 	}
179 	*param = num;
180 	return true;
181 }
182 
handle_wifi_scan_result(struct net_mgmt_event_callback * cb)183 static void handle_wifi_scan_result(struct net_mgmt_event_callback *cb)
184 {
185 	const struct wifi_scan_result *entry =
186 		(const struct wifi_scan_result *)cb->info;
187 	uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
188 	const struct shell *sh = context.sh;
189 	uint8_t ssid_print[WIFI_SSID_MAX_LEN + 1];
190 
191 	context.scan_result++;
192 
193 	if (context.scan_result == 1U) {
194 		PR("\n%-4s | %-32s %-5s | %-13s | %-4s | %-15s | %-17s | %-8s\n",
195 		   "Num", "SSID", "(len)", "Chan (Band)", "RSSI", "Security", "BSSID", "MFP");
196 	}
197 
198 	strncpy(ssid_print, entry->ssid, sizeof(ssid_print) - 1);
199 	ssid_print[sizeof(ssid_print) - 1] = '\0';
200 
201 	PR("%-4d | %-32s %-5u | %-4u (%-6s) | %-4d | %-15s | %-17s | %-8s\n",
202 	   context.scan_result, ssid_print, entry->ssid_length, entry->channel,
203 	   wifi_band_txt(entry->band),
204 	   entry->rssi,
205 	   wifi_security_txt(entry->security),
206 	   ((entry->mac_length) ?
207 		   net_sprint_ll_addr_buf(entry->mac, WIFI_MAC_ADDR_LEN,
208 					  mac_string_buf,
209 					  sizeof(mac_string_buf)) : ""),
210 	   wifi_mfp_txt(entry->mfp));
211 }
212 
wifi_freq_to_channel(int frequency)213 static int wifi_freq_to_channel(int frequency)
214 {
215 	int channel;
216 
217 	if (frequency == 2484) { /* channel 14 */
218 		channel = 14;
219 	} else if ((frequency <= 2472) && (frequency >= 2412)) {
220 		channel = ((frequency - 2412) / 5) + 1;
221 	} else if ((frequency <= 5320) && (frequency >= 5180)) {
222 		channel = ((frequency - 5180) / 5) + 36;
223 	} else if ((frequency <= 5720) && (frequency >= 5500)) {
224 		channel = ((frequency - 5500) / 5) + 100;
225 	} else if ((frequency <= 5895) && (frequency >= 5745)) {
226 		channel = ((frequency - 5745) / 5) + 149;
227 	} else {
228 		channel = frequency;
229 	}
230 
231 	return channel;
232 }
233 
234 #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
wifi_freq_to_band(int frequency)235 static enum wifi_frequency_bands wifi_freq_to_band(int frequency)
236 {
237 	enum wifi_frequency_bands band = WIFI_FREQ_BAND_2_4_GHZ;
238 
239 	if ((frequency >= 2401) && (frequency <= 2495)) {
240 		band = WIFI_FREQ_BAND_2_4_GHZ;
241 	} else if ((frequency >= 5170) && (frequency <= 5895)) {
242 		band = WIFI_FREQ_BAND_5_GHZ;
243 	} else {
244 		band = WIFI_FREQ_BAND_6_GHZ;
245 	}
246 
247 	return band;
248 }
249 
handle_wifi_raw_scan_result(struct net_mgmt_event_callback * cb)250 static void handle_wifi_raw_scan_result(struct net_mgmt_event_callback *cb)
251 {
252 	struct wifi_raw_scan_result *raw =
253 		(struct wifi_raw_scan_result *)cb->info;
254 	int channel;
255 	int band;
256 	int rssi;
257 	uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
258 	const struct shell *sh = context.sh;
259 
260 	context.scan_result++;
261 
262 	if (context.scan_result == 1U) {
263 		PR("\n%-4s | %-13s | %-4s |  %-15s | %-15s | %-32s\n",
264 		   "Num", "Channel (Band)", "RSSI", "BSSID", "Frame length", "Frame Body");
265 	}
266 
267 	rssi = raw->rssi;
268 	channel = wifi_freq_to_channel(raw->frequency);
269 	band = wifi_freq_to_band(raw->frequency);
270 
271 	PR("%-4d | %-4u (%-6s) | %-4d | %s |      %-4d        ",
272 	   context.scan_result,
273 	   channel,
274 	   wifi_band_txt(band),
275 	   rssi,
276 	   net_sprint_ll_addr_buf(raw->data + 10, WIFI_MAC_ADDR_LEN, mac_string_buf,
277 				  sizeof(mac_string_buf)), raw->frame_length);
278 
279 	for (int i = 0; i < 32; i++) {
280 		PR("%02X ", *(raw->data + i));
281 	}
282 
283 	PR("\n");
284 }
285 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
286 
handle_wifi_scan_done(struct net_mgmt_event_callback * cb)287 static void handle_wifi_scan_done(struct net_mgmt_event_callback *cb)
288 {
289 	const struct wifi_status *status =
290 		(const struct wifi_status *)cb->info;
291 	const struct shell *sh = context.sh;
292 
293 	if (status->status) {
294 		PR_WARNING("Scan request failed (%d)\n", status->status);
295 	} else {
296 		PR("Scan request done\n");
297 	}
298 
299 	context.scan_result = 0U;
300 }
301 
handle_wifi_connect_result(struct net_mgmt_event_callback * cb)302 static void handle_wifi_connect_result(struct net_mgmt_event_callback *cb)
303 {
304 	const struct wifi_status *status =
305 		(const struct wifi_status *) cb->info;
306 	const struct shell *sh = context.sh;
307 
308 	if (status->status) {
309 		PR_WARNING("Connection request failed (%d)\n", status->status);
310 	} else {
311 		PR("Connected\n");
312 	}
313 
314 	context.connecting = false;
315 }
316 
handle_wifi_disconnect_result(struct net_mgmt_event_callback * cb)317 static void handle_wifi_disconnect_result(struct net_mgmt_event_callback *cb)
318 {
319 	const struct wifi_status *status =
320 		(const struct wifi_status *) cb->info;
321 	const struct shell *sh = context.sh;
322 
323 	if (context.disconnecting) {
324 		if (status->status) {
325 			PR_WARNING("Disconnection request failed (%d)\n", status->status);
326 		} else {
327 			PR("Disconnection request done (%d)\n", status->status);
328 		}
329 		context.disconnecting = false;
330 	} else {
331 		PR("Disconnected\n");
332 	}
333 }
334 
print_twt_params(uint8_t dialog_token,uint8_t flow_id,enum wifi_twt_negotiation_type negotiation_type,bool responder,bool implicit,bool announce,bool trigger,uint32_t twt_wake_interval,uint64_t twt_interval)335 static void print_twt_params(uint8_t dialog_token, uint8_t flow_id,
336 			     enum wifi_twt_negotiation_type negotiation_type,
337 			     bool responder, bool implicit, bool announce,
338 			     bool trigger, uint32_t twt_wake_interval,
339 			     uint64_t twt_interval)
340 {
341 	const struct shell *sh = context.sh;
342 
343 	PR("TWT Dialog token: %d\n",
344 	      dialog_token);
345 	PR("TWT flow ID: %d\n",
346 	      flow_id);
347 	PR("TWT negotiation type: %s\n",
348 	      wifi_twt_negotiation_type_txt(negotiation_type));
349 	PR("TWT responder: %s\n",
350 	       responder ? "true" : "false");
351 	PR("TWT implicit: %s\n",
352 	      implicit ? "true" : "false");
353 	PR("TWT announce: %s\n",
354 	      announce ? "true" : "false");
355 	PR("TWT trigger: %s\n",
356 	      trigger ? "true" : "false");
357 	PR("TWT wake interval: %d us\n",
358 	      twt_wake_interval);
359 	PR("TWT interval: %lld us\n",
360 	      twt_interval);
361 	PR("========================\n");
362 }
363 
handle_wifi_twt_event(struct net_mgmt_event_callback * cb)364 static void handle_wifi_twt_event(struct net_mgmt_event_callback *cb)
365 {
366 	const struct wifi_twt_params *resp =
367 		(const struct wifi_twt_params *)cb->info;
368 	const struct shell *sh = context.sh;
369 
370 	if (resp->operation == WIFI_TWT_TEARDOWN) {
371 		if (resp->teardown_status == WIFI_TWT_TEARDOWN_SUCCESS) {
372 			PR("TWT teardown succeeded for flow ID %d\n",
373 			      resp->flow_id);
374 		} else {
375 			PR("TWT teardown failed for flow ID %d\n",
376 			      resp->flow_id);
377 		}
378 		return;
379 	}
380 
381 	if (resp->resp_status == WIFI_TWT_RESP_RECEIVED) {
382 		PR("TWT response: %s\n",
383 		      wifi_twt_setup_cmd_txt(resp->setup_cmd));
384 		PR("== TWT negotiated parameters ==\n");
385 		print_twt_params(resp->dialog_token,
386 				 resp->flow_id,
387 				 resp->negotiation_type,
388 				 resp->setup.responder,
389 				 resp->setup.implicit,
390 				 resp->setup.announce,
391 				 resp->setup.trigger,
392 				 resp->setup.twt_wake_interval,
393 				 resp->setup.twt_interval);
394 	} else {
395 		PR("TWT response timed out\n");
396 	}
397 }
398 
handle_wifi_ap_enable_result(struct net_mgmt_event_callback * cb)399 static void handle_wifi_ap_enable_result(struct net_mgmt_event_callback *cb)
400 {
401 	const struct wifi_status *status =
402 		(const struct wifi_status *)cb->info;
403 	const struct shell *sh = context.sh;
404 
405 	if (status->status) {
406 		PR_WARNING("AP enable request failed (%d)\n", status->status);
407 	} else {
408 		PR("AP enabled\n");
409 	}
410 }
411 
handle_wifi_ap_disable_result(struct net_mgmt_event_callback * cb)412 static void handle_wifi_ap_disable_result(struct net_mgmt_event_callback *cb)
413 {
414 	const struct wifi_status *status =
415 		(const struct wifi_status *)cb->info;
416 	const struct shell *sh = context.sh;
417 
418 	if (status->status) {
419 		PR_WARNING("AP disable request failed (%d)\n", status->status);
420 	} else {
421 		PR("AP disabled\n");
422 	}
423 
424 	k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER);
425 	memset(&sta_list, 0, sizeof(sta_list));
426 	k_mutex_unlock(&wifi_ap_sta_list_lock);
427 }
428 
handle_wifi_ap_sta_connected(struct net_mgmt_event_callback * cb)429 static void handle_wifi_ap_sta_connected(struct net_mgmt_event_callback *cb)
430 {
431 	const struct wifi_ap_sta_info *sta_info =
432 		(const struct wifi_ap_sta_info *)cb->info;
433 	const struct shell *sh = context.sh;
434 	uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
435 	int i;
436 
437 	PR("Station connected: %s\n",
438 	   net_sprint_ll_addr_buf(sta_info->mac, WIFI_MAC_ADDR_LEN,
439 				  mac_string_buf, sizeof(mac_string_buf)));
440 
441 	k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER);
442 	for (i = 0; i < CONFIG_WIFI_SHELL_MAX_AP_STA; i++) {
443 		if (!sta_list[i].valid) {
444 			sta_list[i].sta_info = *sta_info;
445 			sta_list[i].valid = true;
446 			break;
447 		}
448 	}
449 	if (i == CONFIG_WIFI_SHELL_MAX_AP_STA) {
450 		PR_WARNING("No space to store station info: "
451 			   "Increase CONFIG_WIFI_SHELL_MAX_AP_STA\n");
452 	}
453 	k_mutex_unlock(&wifi_ap_sta_list_lock);
454 }
455 
handle_wifi_ap_sta_disconnected(struct net_mgmt_event_callback * cb)456 static void handle_wifi_ap_sta_disconnected(struct net_mgmt_event_callback *cb)
457 {
458 	const struct wifi_ap_sta_info *sta_info =
459 		(const struct wifi_ap_sta_info *)cb->info;
460 	const struct shell *sh = context.sh;
461 	uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
462 
463 	PR("Station disconnected: %s\n",
464 	   net_sprint_ll_addr_buf(sta_info->mac, WIFI_MAC_ADDR_LEN,
465 				  mac_string_buf, sizeof(mac_string_buf)));
466 
467 	k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER);
468 	for (int i = 0; i < CONFIG_WIFI_SHELL_MAX_AP_STA; i++) {
469 		if (!sta_list[i].valid) {
470 			continue;
471 		}
472 
473 		if (!memcmp(sta_list[i].sta_info.mac, sta_info->mac,
474 			    WIFI_MAC_ADDR_LEN)) {
475 			sta_list[i].valid = false;
476 			break;
477 		}
478 	}
479 	k_mutex_unlock(&wifi_ap_sta_list_lock);
480 }
481 
482 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
handle_wifi_signal_change(struct net_mgmt_event_callback * cb)483 static void handle_wifi_signal_change(struct net_mgmt_event_callback *cb)
484 {
485 	struct net_if *iface = net_if_get_wifi_sta();
486 	const struct shell *sh = context.sh;
487 	int ret;
488 
489 	ret = net_mgmt(NET_REQUEST_WIFI_START_ROAMING, iface, NULL, 0);
490 	if (ret) {
491 		PR_WARNING("Start roaming failed\n");
492 		return;
493 	}
494 
495 	PR("Start roaming requested\n");
496 }
497 
handle_wifi_neighbor_rep_complete(struct net_mgmt_event_callback * cb)498 static void handle_wifi_neighbor_rep_complete(struct net_mgmt_event_callback *cb)
499 {
500 	struct net_if *iface = net_if_get_wifi_sta();
501 	const struct shell *sh = context.sh;
502 	int ret;
503 
504 	ret = net_mgmt(NET_REQUEST_WIFI_NEIGHBOR_REP_COMPLETE, iface, NULL, 0);
505 	if (ret) {
506 		PR_WARNING("Neighbor report complete failed\n");
507 		return;
508 	}
509 
510 	PR("Neighbor report complete requested\n");
511 }
512 #endif
513 
wifi_mgmt_event_handler(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)514 static void wifi_mgmt_event_handler(struct net_mgmt_event_callback *cb,
515 				    uint32_t mgmt_event, struct net_if *iface)
516 {
517 	switch (mgmt_event) {
518 	case NET_EVENT_WIFI_SCAN_RESULT:
519 		handle_wifi_scan_result(cb);
520 		break;
521 	case NET_EVENT_WIFI_SCAN_DONE:
522 		handle_wifi_scan_done(cb);
523 		break;
524 	case NET_EVENT_WIFI_CONNECT_RESULT:
525 		handle_wifi_connect_result(cb);
526 		break;
527 	case NET_EVENT_WIFI_DISCONNECT_RESULT:
528 		handle_wifi_disconnect_result(cb);
529 		break;
530 	case NET_EVENT_WIFI_TWT:
531 		handle_wifi_twt_event(cb);
532 		break;
533 #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
534 	case NET_EVENT_WIFI_RAW_SCAN_RESULT:
535 		handle_wifi_raw_scan_result(cb);
536 		break;
537 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
538 	case NET_EVENT_WIFI_AP_ENABLE_RESULT:
539 		handle_wifi_ap_enable_result(cb);
540 		break;
541 	case NET_EVENT_WIFI_AP_DISABLE_RESULT:
542 		handle_wifi_ap_disable_result(cb);
543 		break;
544 	case NET_EVENT_WIFI_AP_STA_CONNECTED:
545 		handle_wifi_ap_sta_connected(cb);
546 		break;
547 	case NET_EVENT_WIFI_AP_STA_DISCONNECTED:
548 		handle_wifi_ap_sta_disconnected(cb);
549 		break;
550 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_ROAMING
551 	case NET_EVENT_WIFI_SIGNAL_CHANGE:
552 		handle_wifi_signal_change(cb);
553 		break;
554 	case NET_EVENT_WIFI_NEIGHBOR_REP_COMP:
555 		handle_wifi_neighbor_rep_complete(cb);
556 		break;
557 #endif
558 	default:
559 		break;
560 	}
561 }
562 
__wifi_args_to_params(const struct shell * sh,size_t argc,char * argv[],struct wifi_connect_req_params * params,enum wifi_iface_mode iface_mode)563 static int __wifi_args_to_params(const struct shell *sh, size_t argc, char *argv[],
564 				 struct wifi_connect_req_params *params,
565 				 enum wifi_iface_mode iface_mode)
566 {
567 	int opt;
568 	int opt_index = 0;
569 	struct getopt_state *state;
570 	static const struct option long_options[] = {
571 		{"ssid", required_argument, 0, 's'},
572 		{"passphrase", required_argument, 0, 'p'},
573 		{"key-mgmt", required_argument, 0, 'k'},
574 		{"ieee-80211w", required_argument, 0, 'w'},
575 		{"bssid", required_argument, 0, 'm'},
576 		{"band", required_argument, 0, 'b'},
577 		{"channel", required_argument, 0, 'c'},
578 		{"timeout", required_argument, 0, 't'},
579 		{"anon-id", required_argument, 0, 'a'},
580 		{"bandwidth", required_argument, 0, 'B'},
581 		{"key1-pwd", required_argument, 0, 'K'},
582 		{"key2-pwd", required_argument, 0, 'K'},
583 		{"suiteb-type", required_argument, 0, 'S'},
584 		{"TLS-cipher", required_argument, 0, 'T'},
585 		{"eap-version", required_argument, 0, 'V'},
586 		{"eap-id1", required_argument, 0, 'I'},
587 		{"eap-id2", required_argument, 0, 'I'},
588 		{"eap-id3", required_argument, 0, 'I'},
589 		{"eap-id4", required_argument, 0, 'I'},
590 		{"eap-id5", required_argument, 0, 'I'},
591 		{"eap-id6", required_argument, 0, 'I'},
592 		{"eap-id7", required_argument, 0, 'I'},
593 		{"eap-id8", required_argument, 0, 'I'},
594 		{"eap-pwd1", required_argument, 0, 'P'},
595 		{"eap-pwd2", required_argument, 0, 'P'},
596 		{"eap-pwd3", required_argument, 0, 'P'},
597 		{"eap-pwd4", required_argument, 0, 'P'},
598 		{"eap-pwd5", required_argument, 0, 'P'},
599 		{"eap-pwd6", required_argument, 0, 'P'},
600 		{"eap-pwd7", required_argument, 0, 'P'},
601 		{"eap-pwd8", required_argument, 0, 'P'},
602 		{"ignore-broadcast-ssid", required_argument, 0, 'i'},
603 		{"ieee-80211r", no_argument, 0, 'R'},
604 		{"help", no_argument, 0, 'h'},
605 		{0, 0, 0, 0}};
606 	char *endptr;
607 	int idx = 1;
608 	bool secure_connection = false;
609 	uint8_t band;
610 	const uint8_t all_bands[] = {
611 		WIFI_FREQ_BAND_2_4_GHZ,
612 		WIFI_FREQ_BAND_5_GHZ,
613 		WIFI_FREQ_BAND_6_GHZ
614 	};
615 	bool found = false;
616 	char bands_str[MAX_BANDS_STR_LEN] = {0};
617 	size_t offset = 0;
618 	long channel;
619 	int key_passwd_cnt = 0;
620 	int ret = 0;
621 
622 	/* Defaults */
623 	params->band = WIFI_FREQ_BAND_UNKNOWN;
624 	params->channel = WIFI_CHANNEL_ANY;
625 	params->security = WIFI_SECURITY_TYPE_NONE;
626 	params->mfp = WIFI_MFP_OPTIONAL;
627 	params->eap_ver = 1;
628 	params->ignore_broadcast_ssid = 0;
629 	params->bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
630 
631 	while ((opt = getopt_long(argc, argv, "s:p:k:e:w:b:c:m:t:a:B:K:S:T:V:I:P:i:Rh",
632 				  long_options, &opt_index)) != -1) {
633 		state = getopt_state_get();
634 		switch (opt) {
635 		case 's':
636 			params->ssid = state->optarg;
637 			params->ssid_length = strlen(params->ssid);
638 			if (params->ssid_length > WIFI_SSID_MAX_LEN) {
639 				PR_WARNING("SSID too long (max %d characters)\n",
640 					   WIFI_SSID_MAX_LEN);
641 				return -EINVAL;
642 			}
643 			break;
644 		case 'k':
645 			params->security = atoi(state->optarg);
646 			if (params->security) {
647 				secure_connection = true;
648 			}
649 			break;
650 		case 'p':
651 			params->psk = state->optarg;
652 			params->psk_length = strlen(params->psk);
653 			break;
654 		case 'c':
655 			channel = strtol(state->optarg, &endptr, 10);
656 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
657 			if (iface_mode == WIFI_MODE_AP && channel == 0) {
658 				params->channel = channel;
659 				break;
660 			}
661 #endif
662 			for (band = 0; band < ARRAY_SIZE(all_bands); band++) {
663 				offset += snprintf(bands_str + offset,
664 						   sizeof(bands_str) - offset,
665 						   "%s%s",
666 						   band ? "," : "",
667 						   wifi_band_txt(all_bands[band]));
668 				if (offset >= sizeof(bands_str)) {
669 					PR_ERROR("Failed to parse channel: %s: "
670 						 "band string too long\n",
671 						 argv[idx]);
672 					return -EINVAL;
673 				}
674 
675 				if (wifi_utils_validate_chan(all_bands[band],
676 							     channel)) {
677 					found = true;
678 					break;
679 				}
680 			}
681 
682 			if (!found) {
683 				PR_ERROR("Invalid channel: %ld, checked bands: %s\n",
684 					 channel,
685 					 bands_str);
686 				return -EINVAL;
687 			}
688 
689 			params->channel = channel;
690 			break;
691 		case 'b':
692 			if (iface_mode == WIFI_MODE_INFRA ||
693 				iface_mode == WIFI_MODE_AP) {
694 				switch (atoi(state->optarg)) {
695 				case 2:
696 					params->band = WIFI_FREQ_BAND_2_4_GHZ;
697 					break;
698 				case 5:
699 					params->band = WIFI_FREQ_BAND_5_GHZ;
700 					break;
701 				case 6:
702 					params->band = WIFI_FREQ_BAND_6_GHZ;
703 					break;
704 				default:
705 					PR_ERROR("Invalid band: %d\n", atoi(state->optarg));
706 					return -EINVAL;
707 				}
708 			}
709 			break;
710 		case 'w':
711 			if (params->security == WIFI_SECURITY_TYPE_NONE ||
712 			    params->security == WIFI_SECURITY_TYPE_WPA_PSK) {
713 				PR_ERROR("MFP not supported for security type %s\n",
714 					 wifi_security_txt(params->security));
715 				return -EINVAL;
716 			}
717 			params->mfp = atoi(state->optarg);
718 			break;
719 		case 'm':
720 			if (net_bytes_from_str(params->bssid, sizeof(params->bssid),
721 					       state->optarg) < 0) {
722 				PR_WARNING("Invalid MAC address\n");
723 				return -EINVAL;
724 			}
725 			break;
726 		case 't':
727 			if (iface_mode == WIFI_MODE_INFRA) {
728 				params->timeout = strtol(state->optarg, &endptr, 10);
729 				if (*endptr != '\0') {
730 					PR_ERROR("Invalid timeout: %s\n", state->optarg);
731 					return -EINVAL;
732 				}
733 			}
734 			break;
735 		case 'a':
736 			params->anon_id = state->optarg;
737 			params->aid_length = strlen(params->anon_id);
738 			if (params->aid_length > WIFI_ENT_IDENTITY_MAX_LEN) {
739 				PR_WARNING("anon_id too long (max %d characters)\n",
740 					    WIFI_ENT_IDENTITY_MAX_LEN);
741 				return -EINVAL;
742 			}
743 			break;
744 		case 'B':
745 			if (iface_mode == WIFI_MODE_AP) {
746 				switch (atoi(state->optarg)) {
747 				case 1:
748 					params->bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
749 					break;
750 				case 2:
751 					params->bandwidth = WIFI_FREQ_BANDWIDTH_40MHZ;
752 					break;
753 				case 3:
754 					params->bandwidth = WIFI_FREQ_BANDWIDTH_80MHZ;
755 					break;
756 				default:
757 					PR_ERROR("Invalid bandwidth: %d\n", atoi(state->optarg));
758 					return -EINVAL;
759 				}
760 			}
761 			break;
762 		case 'K':
763 			if (key_passwd_cnt >= 2) {
764 				PR_WARNING("too many key_passwd (max 2 key_passwd)\n");
765 				return -EINVAL;
766 			}
767 
768 			if (key_passwd_cnt == 0) {
769 				params->key_passwd = state->optarg;
770 				params->key_passwd_length = strlen(params->key_passwd);
771 				if (params->key_passwd_length > WIFI_ENT_PSWD_MAX_LEN) {
772 					PR_WARNING("key_passwd too long (max %d characters)\n",
773 							WIFI_ENT_PSWD_MAX_LEN);
774 					return -EINVAL;
775 				}
776 			} else if (key_passwd_cnt == 1) {
777 				params->key2_passwd = state->optarg;
778 				params->key2_passwd_length = strlen(params->key2_passwd);
779 				if (params->key2_passwd_length > WIFI_ENT_PSWD_MAX_LEN) {
780 					PR_WARNING("key2_passwd too long (max %d characters)\n",
781 							WIFI_ENT_PSWD_MAX_LEN);
782 					return -EINVAL;
783 				}
784 			}
785 			key_passwd_cnt++;
786 			break;
787 		case 'S':
788 			params->suiteb_type = atoi(state->optarg);
789 			break;
790 		case 'T':
791 			params->TLS_cipher = atoi(state->optarg);
792 			break;
793 		case 'V':
794 			params->eap_ver = atoi(state->optarg);
795 			if (params->eap_ver != 0U && params->eap_ver != 1U) {
796 				PR_WARNING("eap_ver error %d\n", params->eap_ver);
797 				return -EINVAL;
798 			}
799 			break;
800 		case 'I':
801 			if (params->nusers >= WIFI_ENT_IDENTITY_MAX_USERS) {
802 				PR_WARNING("too many eap identities (max %d identities)\n",
803 					    WIFI_ENT_IDENTITY_MAX_USERS);
804 				return -EINVAL;
805 			}
806 
807 			params->eap_identity = state->optarg;
808 			params->eap_id_length = strlen(params->eap_identity);
809 
810 			params->identities[params->nusers] = state->optarg;
811 			params->nusers++;
812 			if (params->eap_id_length > WIFI_ENT_IDENTITY_MAX_LEN) {
813 				PR_WARNING("eap identity too long (max %d characters)\n",
814 					    WIFI_ENT_IDENTITY_MAX_LEN);
815 				return -EINVAL;
816 			}
817 			break;
818 		case 'P':
819 			if (params->passwds >= WIFI_ENT_IDENTITY_MAX_USERS) {
820 				PR_WARNING("too many eap passwds (max %d passwds)\n",
821 					    WIFI_ENT_IDENTITY_MAX_USERS);
822 				return -EINVAL;
823 			}
824 
825 			params->eap_password = state->optarg;
826 			params->eap_passwd_length = strlen(params->eap_password);
827 
828 			params->passwords[params->passwds] = state->optarg;
829 			params->passwds++;
830 			if (params->eap_passwd_length > WIFI_ENT_PSWD_MAX_LEN) {
831 				PR_WARNING("eap password length too long (max %d characters)\n",
832 					    WIFI_ENT_PSWD_MAX_LEN);
833 				return -EINVAL;
834 			}
835 			break;
836 		case 'R':
837 			params->ft_used = true;
838 			break;
839 		case 'i':
840 			params->ignore_broadcast_ssid = shell_strtol(state->optarg, 10, &ret);
841 			break;
842 		case 'h':
843 			return -ENOEXEC;
844 		default:
845 			PR_ERROR("Invalid option %c\n", state->optopt);
846 			return -EINVAL;
847 		}
848 
849 		if (ret) {
850 			PR_ERROR("Invalid argument %d ret %d\n", opt_index, ret);
851 			return -EINVAL;
852 		}
853 	}
854 
855 	if (params->psk && !secure_connection) {
856 		PR_WARNING("Passphrase provided without security configuration\n");
857 	}
858 
859 	if (!params->ssid) {
860 		PR_ERROR("SSID not provided\n");
861 		return -EINVAL;
862 	}
863 
864 	if (iface_mode == WIFI_MODE_AP && params->channel == WIFI_CHANNEL_ANY) {
865 		PR_ERROR("Channel not provided\n");
866 		return -EINVAL;
867 	}
868 
869 #ifdef CONFIG_WIFI_NM_HOSTAPD_AP
870 	if (iface_mode == WIFI_MODE_AP) {
871 		if (params->channel == 0 && params->band == WIFI_FREQ_BAND_UNKNOWN) {
872 			PR_ERROR("Band not provided when channel is 0\n");
873 			return -EINVAL;
874 		}
875 
876 		if (params->channel > 0 && params->channel <= 14 &&
877 		    (params->band != WIFI_FREQ_BAND_2_4_GHZ &&
878 		     params->band != WIFI_FREQ_BAND_UNKNOWN)) {
879 			PR_ERROR("Band and channel mismatch\n");
880 			return -EINVAL;
881 		}
882 
883 		if (params->channel >= 36 &&
884 		    (params->band != WIFI_FREQ_BAND_5_GHZ &&
885 		     params->band != WIFI_FREQ_BAND_UNKNOWN)) {
886 			PR_ERROR("Band and channel mismatch\n");
887 			return -EINVAL;
888 		}
889 	}
890 #endif
891 	if (params->ignore_broadcast_ssid > 2) {
892 		PR_ERROR("Invalid ignore_broadcast_ssid value\n");
893 		return -EINVAL;
894 	}
895 
896 	return 0;
897 }
898 
cmd_wifi_connect(const struct shell * sh,size_t argc,char * argv[])899 static int cmd_wifi_connect(const struct shell *sh, size_t argc,
900 			    char *argv[])
901 {
902 	struct net_if *iface = net_if_get_wifi_sta();
903 	struct wifi_connect_req_params cnx_params = { 0 };
904 	int ret;
905 
906 	context.sh = sh;
907 	if (__wifi_args_to_params(sh, argc, argv, &cnx_params, WIFI_MODE_INFRA)) {
908 		shell_help(sh);
909 		return -ENOEXEC;
910 	}
911 
912 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
913 	/* Load the enterprise credentials if needed */
914 	if (cnx_params.security == WIFI_SECURITY_TYPE_EAP_TLS ||
915 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
916 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
917 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
918 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS ||
919 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_TLS_SHA256) {
920 		cmd_wifi_set_enterprise_creds(sh, iface);
921 	}
922 #endif
923 
924 	context.connecting = true;
925 	ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, iface,
926 		       &cnx_params, sizeof(struct wifi_connect_req_params));
927 	if (ret) {
928 		printk("Connection request failed with error: %d\n", ret);
929 		context.connecting = false;
930 		return -ENOEXEC;
931 	}
932 
933 	PR("Connection requested\n");
934 
935 	return 0;
936 }
937 
cmd_wifi_disconnect(const struct shell * sh,size_t argc,char * argv[])938 static int cmd_wifi_disconnect(const struct shell *sh, size_t argc,
939 			       char *argv[])
940 {
941 	struct net_if *iface = net_if_get_wifi_sta();
942 	int status;
943 
944 	context.disconnecting = true;
945 	context.sh = sh;
946 
947 	status = net_mgmt(NET_REQUEST_WIFI_DISCONNECT, iface, NULL, 0);
948 
949 	if (status) {
950 		context.disconnecting = false;
951 
952 		if (status == -EALREADY) {
953 			PR_INFO("Already disconnected\n");
954 		} else {
955 			PR_WARNING("Disconnect request failed: %d\n", status);
956 			return -ENOEXEC;
957 		}
958 	} else {
959 		PR("Disconnect requested\n");
960 	}
961 
962 	return 0;
963 }
964 
wifi_scan_args_to_params(const struct shell * sh,size_t argc,char * argv[],struct wifi_scan_params * params,bool * do_scan)965 static int wifi_scan_args_to_params(const struct shell *sh,
966 				    size_t argc,
967 				    char *argv[],
968 				    struct wifi_scan_params *params,
969 				    bool *do_scan)
970 {
971 	int opt;
972 	int opt_index = 0;
973 	struct getopt_state *state;
974 	static const struct option long_options[] = {
975 		{"type", required_argument, 0, 't'},
976 		{"bands", required_argument, 0, 'b'},
977 		{"dwell_time_active", required_argument, 0, 'a'},
978 		{"dwell_time_passive", required_argument, 0, 'p'},
979 		{"ssid", required_argument, 0, 's'},
980 		{"max_bss", required_argument, 0, 'm'},
981 		{"chans", required_argument, 0, 'c'},
982 		{"help", no_argument, 0, 'h'},
983 		{0, 0, 0, 0}};
984 	int val;
985 	int opt_num = 0;
986 
987 	*do_scan = true;
988 
989 	while ((opt = getopt_long(argc, argv, "t:b:a:p:s:m:c:h",
990 				  long_options, &opt_index)) != -1) {
991 		state = getopt_state_get();
992 		switch (opt) {
993 		case 't':
994 			if (!strncasecmp(state->optarg, "passive", 7)) {
995 				params->scan_type = WIFI_SCAN_TYPE_PASSIVE;
996 			} else if (!strncasecmp(state->optarg, "active", 6)) {
997 				params->scan_type = WIFI_SCAN_TYPE_ACTIVE;
998 			} else {
999 				PR_ERROR("Invalid scan type %s\n", state->optarg);
1000 				return -ENOEXEC;
1001 			}
1002 
1003 			opt_num++;
1004 			break;
1005 		case 'b':
1006 			if (wifi_utils_parse_scan_bands(state->optarg, &params->bands)) {
1007 				PR_ERROR("Invalid band value(s)\n");
1008 				return -ENOEXEC;
1009 			}
1010 
1011 			opt_num++;
1012 			break;
1013 		case 'a':
1014 			val = atoi(state->optarg);
1015 
1016 			if (val < 0) {
1017 				PR_ERROR("Invalid dwell_time_active val\n");
1018 				return -ENOEXEC;
1019 			}
1020 
1021 			params->dwell_time_active = val;
1022 			opt_num++;
1023 			break;
1024 		case 'p':
1025 			val = atoi(state->optarg);
1026 
1027 			if (val < 0) {
1028 				PR_ERROR("Invalid dwell_time_passive val\n");
1029 				return -ENOEXEC;
1030 			}
1031 
1032 			params->dwell_time_passive = val;
1033 			opt_num++;
1034 			break;
1035 		case 's':
1036 			if (wifi_utils_parse_scan_ssids(state->optarg,
1037 							params->ssids,
1038 							ARRAY_SIZE(params->ssids))) {
1039 				PR_ERROR("Invalid SSID(s)\n");
1040 				return -ENOEXEC;
1041 			}
1042 
1043 			opt_num++;
1044 			break;
1045 		case 'm':
1046 			val = atoi(state->optarg);
1047 
1048 			if ((val < 0) || (val > WIFI_MGMT_SCAN_MAX_BSS_CNT)) {
1049 				PR_ERROR("Invalid max_bss val\n");
1050 				return -ENOEXEC;
1051 			}
1052 
1053 			params->max_bss_cnt = val;
1054 			opt_num++;
1055 			break;
1056 		case 'c':
1057 			if (wifi_utils_parse_scan_chan(state->optarg,
1058 						       params->band_chan,
1059 						       ARRAY_SIZE(params->band_chan))) {
1060 				PR_ERROR("Invalid band or channel value(s)\n");
1061 				return -ENOEXEC;
1062 			}
1063 
1064 			opt_num++;
1065 			break;
1066 		case 'h':
1067 			shell_help(sh);
1068 			*do_scan = false;
1069 			opt_num++;
1070 			break;
1071 		case '?':
1072 		default:
1073 			PR_ERROR("Invalid option or option usage: %s\n",
1074 				 argv[opt_index + 1]);
1075 			return -ENOEXEC;
1076 		}
1077 	}
1078 
1079 	return opt_num;
1080 }
1081 
cmd_wifi_scan(const struct shell * sh,size_t argc,char * argv[])1082 static int cmd_wifi_scan(const struct shell *sh, size_t argc, char *argv[])
1083 {
1084 	struct net_if *iface = net_if_get_wifi_sta();
1085 	struct wifi_scan_params params = { 0 };
1086 	bool do_scan = true;
1087 	int opt_num;
1088 
1089 	context.sh = sh;
1090 
1091 	if (argc > 1) {
1092 		opt_num = wifi_scan_args_to_params(sh, argc, argv, &params, &do_scan);
1093 
1094 		if (opt_num < 0) {
1095 			shell_help(sh);
1096 			return -ENOEXEC;
1097 		} else if (!opt_num) {
1098 			PR_WARNING("No valid option(s) found\n");
1099 			do_scan = false;
1100 		}
1101 	}
1102 
1103 	if (do_scan) {
1104 		if (net_mgmt(NET_REQUEST_WIFI_SCAN, iface, &params, sizeof(params))) {
1105 			PR_WARNING("Scan request failed\n");
1106 			return -ENOEXEC;
1107 		}
1108 
1109 		PR("Scan requested\n");
1110 
1111 		return 0;
1112 	}
1113 
1114 	PR_WARNING("Scan not initiated\n");
1115 	return -ENOEXEC;
1116 }
1117 
cmd_wifi_status(const struct shell * sh,size_t argc,char * argv[])1118 static int cmd_wifi_status(const struct shell *sh, size_t argc, char *argv[])
1119 {
1120 	struct net_if *iface = net_if_get_wifi_sta();
1121 	struct wifi_iface_status status = { 0 };
1122 
1123 	context.sh = sh;
1124 
1125 	if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status,
1126 		     sizeof(struct wifi_iface_status))) {
1127 		PR_WARNING("Status request failed\n");
1128 
1129 		return -ENOEXEC;
1130 	}
1131 
1132 	PR("Status: successful\n");
1133 	PR("==================\n");
1134 	PR("State: %s\n", wifi_state_txt(status.state));
1135 
1136 	if (status.state >= WIFI_STATE_ASSOCIATED) {
1137 		uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
1138 
1139 		PR("Interface Mode: %s\n", wifi_mode_txt(status.iface_mode));
1140 		PR("Link Mode: %s\n", wifi_link_mode_txt(status.link_mode));
1141 		PR("SSID: %.32s\n", status.ssid);
1142 		PR("BSSID: %s\n",
1143 		   net_sprint_ll_addr_buf(status.bssid,
1144 					  WIFI_MAC_ADDR_LEN, mac_string_buf,
1145 					  sizeof(mac_string_buf)));
1146 		PR("Band: %s\n", wifi_band_txt(status.band));
1147 		PR("Channel: %d\n", status.channel);
1148 		PR("Security: %s\n", wifi_security_txt(status.security));
1149 		PR("MFP: %s\n", wifi_mfp_txt(status.mfp));
1150 		if (status.iface_mode == WIFI_MODE_INFRA) {
1151 			PR("RSSI: %d\n", status.rssi);
1152 		}
1153 		PR("Beacon Interval: %d\n", status.beacon_interval);
1154 		PR("DTIM: %d\n", status.dtim_period);
1155 		PR("TWT: %s\n",
1156 		   status.twt_capable ? "Supported" : "Not supported");
1157 		PR("Current PHY TX rate (Mbps) : %d\n", status.current_phy_tx_rate);
1158 	}
1159 
1160 	return 0;
1161 }
1162 
cmd_wifi_ap_status(const struct shell * sh,size_t argc,char * argv[])1163 static int cmd_wifi_ap_status(const struct shell *sh, size_t argc, char *argv[])
1164 {
1165 	struct net_if *iface = net_if_get_wifi_sap();
1166 	struct wifi_iface_status status = {0};
1167 	uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
1168 
1169 	context.sh = sh;
1170 
1171 	if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, iface, &status,
1172 		     sizeof(struct wifi_iface_status))) {
1173 		PR_WARNING("Status request failed\n");
1174 
1175 		return -ENOEXEC;
1176 	}
1177 
1178 	switch (status.state) {
1179 	case WIFI_SAP_IFACE_UNINITIALIZED:
1180 		PR("State: %s\n", "UNINITIALIZED");
1181 		return 0;
1182 	case WIFI_SAP_IFACE_DISABLED:
1183 		PR("State: %s\n", "DISABLED");
1184 		return 0;
1185 	case WIFI_SAP_IFACE_COUNTRY_UPDATE:
1186 		PR("State: %s\n", "COUNTRY_UPDATE");
1187 		return 0;
1188 	case WIFI_SAP_IFACE_ACS:
1189 		PR("State: %s\n", "ACS");
1190 		return 0;
1191 	case WIFI_SAP_IFACE_HT_SCAN:
1192 		PR("State: %s\n", "HT_SCAN");
1193 		return 0;
1194 	case WIFI_SAP_IFACE_DFS:
1195 		PR("State: %s\n", "DFS");
1196 		break;
1197 	case WIFI_SAP_IFACE_NO_IR:
1198 		PR("State: %s\n", "NO_IR");
1199 		break;
1200 	case WIFI_SAP_IFACE_ENABLED:
1201 		PR("State: %s\n", "ENABLED");
1202 		break;
1203 	default:
1204 		return 0;
1205 	}
1206 
1207 	PR("Interface Mode: %s\n", wifi_mode_txt(status.iface_mode));
1208 	PR("Link Mode: %s\n", wifi_link_mode_txt(status.link_mode));
1209 	PR("SSID: %.32s\n", status.ssid);
1210 	PR("BSSID: %s\n", net_sprint_ll_addr_buf(status.bssid, WIFI_MAC_ADDR_LEN, mac_string_buf,
1211 						 sizeof(mac_string_buf)));
1212 	PR("Band: %s\n", wifi_band_txt(status.band));
1213 	PR("Channel: %d\n", status.channel);
1214 	PR("Security: %s\n", wifi_security_txt(status.security));
1215 	PR("MFP: %s\n", wifi_mfp_txt(status.mfp));
1216 	if (status.iface_mode == WIFI_MODE_INFRA) {
1217 		PR("RSSI: %d\n", status.rssi);
1218 	}
1219 	PR("Beacon Interval: %d\n", status.beacon_interval);
1220 	PR("DTIM: %d\n", status.dtim_period);
1221 	PR("TWT: %s\n", status.twt_capable ? "Supported" : "Not supported");
1222 
1223 	return 0;
1224 }
1225 
1226 #if defined(CONFIG_NET_STATISTICS_WIFI) && \
1227 					defined(CONFIG_NET_STATISTICS_USER_API)
print_wifi_stats(struct net_if * iface,struct net_stats_wifi * data,const struct shell * sh)1228 static void print_wifi_stats(struct net_if *iface, struct net_stats_wifi *data,
1229 			     const struct shell *sh)
1230 {
1231 	PR("Statistics for Wi-Fi interface %p [%d]\n", iface,
1232 	   net_if_get_by_iface(iface));
1233 
1234 	PR("Bytes received   : %u\n", data->bytes.received);
1235 	PR("Bytes sent       : %u\n", data->bytes.sent);
1236 	PR("Packets received : %u\n", data->pkts.rx);
1237 	PR("Packets sent     : %u\n", data->pkts.tx);
1238 	PR("Receive errors   : %u\n", data->errors.rx);
1239 	PR("Send errors      : %u\n", data->errors.tx);
1240 	PR("Bcast received   : %u\n", data->broadcast.rx);
1241 	PR("Bcast sent       : %u\n", data->broadcast.tx);
1242 	PR("Mcast received   : %u\n", data->multicast.rx);
1243 	PR("Mcast sent       : %u\n", data->multicast.tx);
1244 	PR("Beacons received : %u\n", data->sta_mgmt.beacons_rx);
1245 	PR("Beacons missed   : %u\n", data->sta_mgmt.beacons_miss);
1246 	PR("Unicast received : %u\n", data->unicast.rx);
1247 	PR("Unicast sent     : %u\n", data->unicast.tx);
1248 	PR("Overrun count    : %u\n", data->overrun_count);
1249 }
1250 #endif /* CONFIG_NET_STATISTICS_WIFI && CONFIG_NET_STATISTICS_USER_API */
1251 
cmd_wifi_stats(const struct shell * sh,size_t argc,char * argv[])1252 static int cmd_wifi_stats(const struct shell *sh, size_t argc, char *argv[])
1253 {
1254 #if defined(CONFIG_NET_STATISTICS_WIFI) && \
1255 					defined(CONFIG_NET_STATISTICS_USER_API)
1256 	struct net_if *iface = net_if_get_wifi_sta();
1257 	struct net_stats_wifi stats = { 0 };
1258 	int ret;
1259 
1260 	context.sh = sh;
1261 
1262 	if (argc == 1) {
1263 		ret = net_mgmt(NET_REQUEST_STATS_GET_WIFI, iface,
1264 			&stats, sizeof(stats));
1265 		if (!ret) {
1266 			print_wifi_stats(iface, &stats, sh);
1267 		}
1268 	}
1269 
1270 	if (argc > 1) {
1271 		if (!strncasecmp(argv[1], "reset", 5)) {
1272 			ret = net_mgmt(NET_REQUEST_STATS_RESET_WIFI, iface,
1273 					&stats, sizeof(stats));
1274 			if (!ret) {
1275 				PR("Wi-Fi interface statistics have been reset.\n");
1276 			}
1277 		} else if (!strncasecmp(argv[1], "help", 4)) {
1278 			shell_help(sh);
1279 		} else {
1280 			PR_WARNING("Invalid argument\n");
1281 			shell_help(sh);
1282 			return -ENOEXEC;
1283 		}
1284 	}
1285 #else
1286 	ARG_UNUSED(argc);
1287 	ARG_UNUSED(argv);
1288 
1289 	PR_INFO("Set %s to enable %s support.\n",
1290 		"CONFIG_NET_STATISTICS_WIFI and CONFIG_NET_STATISTICS_USER_API",
1291 		"statistics");
1292 #endif /* CONFIG_NET_STATISTICS_WIFI && CONFIG_NET_STATISTICS_USER_API */
1293 
1294 	return 0;
1295 }
1296 
cmd_wifi_11k(const struct shell * sh,size_t argc,char * argv[])1297 static int cmd_wifi_11k(const struct shell *sh, size_t argc, char *argv[])
1298 {
1299 	struct net_if *iface = net_if_get_wifi_sta();
1300 	struct wifi_11k_params params = { 0 };
1301 
1302 	context.sh = sh;
1303 
1304 	if (argc > 2) {
1305 		PR_WARNING("Invalid number of arguments\n");
1306 		return -ENOEXEC;
1307 	}
1308 
1309 	if (argc == 1) {
1310 		params.oper = WIFI_MGMT_GET;
1311 	} else {
1312 		params.oper = WIFI_MGMT_SET;
1313 		if (!strncasecmp(argv[1], "enable", 2)) {
1314 			params.enable_11k = true;
1315 		} else if (!strncasecmp(argv[1], "disable", 3)) {
1316 			params.enable_11k = false;
1317 		} else {
1318 			PR_WARNING("Invalid argument\n");
1319 			return -ENOEXEC;
1320 		}
1321 	}
1322 
1323 	if (net_mgmt(NET_REQUEST_WIFI_11K_CONFIG, iface, &params, sizeof(params))) {
1324 		PR_WARNING("11k enable/disable failed\n");
1325 		return -ENOEXEC;
1326 	}
1327 
1328 	if (params.oper == WIFI_MGMT_GET) {
1329 		PR("11k is %s\n", params.enable_11k ? "enabled" : "disabled");
1330 	} else {
1331 		PR("%s %s requested\n", argv[0], argv[1]);
1332 	}
1333 
1334 	return 0;
1335 }
1336 
1337 
cmd_wifi_11k_neighbor_request(const struct shell * sh,size_t argc,char * argv[])1338 static int cmd_wifi_11k_neighbor_request(const struct shell *sh, size_t argc, char *argv[])
1339 {
1340 	struct net_if *iface = net_if_get_wifi_sta();
1341 	struct wifi_11k_params params = { 0 };
1342 
1343 	context.sh = sh;
1344 
1345 	if ((argc != 1 && argc != 3) || (argc == 3 && !strncasecmp("ssid", argv[1], 4))) {
1346 		PR_WARNING("Invalid input arguments\n");
1347 		PR_WARNING("Usage: %s\n", argv[0]);
1348 		PR_WARNING("or	 %s ssid <ssid>\n", argv[0]);
1349 		return -ENOEXEC;
1350 	}
1351 
1352 	if (argc == 3) {
1353 		if (strlen(argv[2]) > (sizeof(params.ssid) - 1)) {
1354 			PR_WARNING("Error: ssid too long\n");
1355 			return -ENOEXEC;
1356 		}
1357 		(void)memcpy((void *)params.ssid, (const void *)argv[2],
1358 			     (size_t)strlen(argv[2]));
1359 	}
1360 
1361 	if (net_mgmt(NET_REQUEST_WIFI_11K_NEIGHBOR_REQUEST, iface, &params, sizeof(params))) {
1362 		PR_WARNING("11k neighbor request failed\n");
1363 		return -ENOEXEC;
1364 	}
1365 
1366 	if (argc == 3) {
1367 		PR("%s %s %s requested\n", argv[0], argv[1], argv[2]);
1368 	} else {
1369 		PR("%s requested\n", argv[0]);
1370 	}
1371 
1372 	return 0;
1373 }
1374 
cmd_wifi_ps(const struct shell * sh,size_t argc,char * argv[])1375 static int cmd_wifi_ps(const struct shell *sh, size_t argc, char *argv[])
1376 {
1377 	struct net_if *iface = net_if_get_wifi_sta();
1378 	struct wifi_ps_params params = { 0 };
1379 
1380 	context.sh = sh;
1381 
1382 	if (argc > 2) {
1383 		PR_WARNING("Invalid number of arguments\n");
1384 		return -ENOEXEC;
1385 	}
1386 
1387 	if (argc == 1) {
1388 		struct wifi_ps_config config = { 0 };
1389 
1390 		if (net_mgmt(NET_REQUEST_WIFI_PS_CONFIG, iface,
1391 				&config, sizeof(config))) {
1392 			PR_WARNING("Failed to get PS config\n");
1393 			return -ENOEXEC;
1394 		}
1395 
1396 		PR("PS status: %s\n",
1397 		   wifi_ps_txt(config.ps_params.enabled));
1398 		if (config.ps_params.enabled) {
1399 			PR("PS mode: %s\n",
1400 			   wifi_ps_mode_txt(config.ps_params.mode));
1401 		}
1402 
1403 		PR("PS listen_interval: %d\n",
1404 		   config.ps_params.listen_interval);
1405 
1406 		PR("PS wake up mode: %s\n",
1407 		   config.ps_params.wakeup_mode ? "Listen interval" : "DTIM");
1408 
1409 		if (config.ps_params.timeout_ms) {
1410 			PR("PS timeout: %d ms\n",
1411 			   config.ps_params.timeout_ms);
1412 		} else {
1413 			PR("PS timeout: disabled\n");
1414 		}
1415 
1416 		shell_fprintf(sh, SHELL_NORMAL, "PS exit strategy: %s\n",
1417 				wifi_ps_exit_strategy_txt(config.ps_params.exit_strategy));
1418 
1419 		if (config.num_twt_flows == 0) {
1420 			PR("No TWT flows\n");
1421 		} else {
1422 			for (int i = 0; i < config.num_twt_flows; i++) {
1423 				print_twt_params(
1424 					config.twt_flows[i].dialog_token,
1425 					config.twt_flows[i].flow_id,
1426 					config.twt_flows[i].negotiation_type,
1427 					config.twt_flows[i].responder,
1428 					config.twt_flows[i].implicit,
1429 					config.twt_flows[i].announce,
1430 					config.twt_flows[i].trigger,
1431 					config.twt_flows[i].twt_wake_interval,
1432 					config.twt_flows[i].twt_interval);
1433 				PR("TWT Wake ahead duration : %d us\n",
1434 				   config.twt_flows[i].twt_wake_ahead_duration);
1435 			}
1436 		}
1437 		return 0;
1438 	}
1439 
1440 	if (!strncasecmp(argv[1], "on", 2)) {
1441 		params.enabled = WIFI_PS_ENABLED;
1442 	} else if (!strncasecmp(argv[1], "off", 3)) {
1443 		params.enabled = WIFI_PS_DISABLED;
1444 	} else {
1445 		PR_WARNING("Invalid argument\n");
1446 		return -ENOEXEC;
1447 	}
1448 
1449 	params.type = WIFI_PS_PARAM_STATE;
1450 
1451 	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
1452 		PR_WARNING("PS %s failed. Reason: %s\n",
1453 			   params.enabled ? "enable" : "disable",
1454 			   wifi_ps_get_config_err_code_str(params.fail_reason));
1455 		return -ENOEXEC;
1456 	}
1457 
1458 	PR("%s\n", wifi_ps_txt(params.enabled));
1459 
1460 	return 0;
1461 }
1462 
cmd_wifi_ps_mode(const struct shell * sh,size_t argc,char * argv[])1463 static int cmd_wifi_ps_mode(const struct shell *sh, size_t argc, char *argv[])
1464 {
1465 	struct net_if *iface = net_if_get_wifi_sta();
1466 	struct wifi_ps_params params = { 0 };
1467 
1468 	context.sh = sh;
1469 
1470 	if (!strncasecmp(argv[1], "legacy", 6)) {
1471 		params.mode = WIFI_PS_MODE_LEGACY;
1472 	} else if (!strncasecmp(argv[1], "WMM", 3)) {
1473 		params.mode = WIFI_PS_MODE_WMM;
1474 	} else {
1475 		PR_WARNING("Invalid PS mode\n");
1476 		return -ENOEXEC;
1477 	}
1478 
1479 	params.type = WIFI_PS_PARAM_MODE;
1480 
1481 	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
1482 		PR_WARNING("%s failed Reason : %s\n",
1483 			   wifi_ps_mode_txt(params.mode),
1484 			   wifi_ps_get_config_err_code_str(params.fail_reason));
1485 		return -ENOEXEC;
1486 	}
1487 
1488 	PR("%s\n", wifi_ps_mode_txt(params.mode));
1489 
1490 	return 0;
1491 }
1492 
cmd_wifi_ps_timeout(const struct shell * sh,size_t argc,char * argv[])1493 static int cmd_wifi_ps_timeout(const struct shell *sh, size_t argc, char *argv[])
1494 {
1495 	struct net_if *iface = net_if_get_wifi_sta();
1496 	struct wifi_ps_params params = { 0 };
1497 	long timeout_ms = 0;
1498 	int err = 0;
1499 
1500 	context.sh = sh;
1501 
1502 	timeout_ms = shell_strtol(argv[1], 10, &err);
1503 
1504 	if (err) {
1505 		shell_error(sh, "Unable to parse input (err %d)", err);
1506 		return err;
1507 	}
1508 
1509 	params.timeout_ms = timeout_ms;
1510 	params.type = WIFI_PS_PARAM_TIMEOUT;
1511 
1512 	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
1513 		PR_WARNING("Setting PS timeout failed. Reason : %s\n",
1514 			   wifi_ps_get_config_err_code_str(params.fail_reason));
1515 		return -ENOEXEC;
1516 	}
1517 
1518 	if (params.timeout_ms) {
1519 		PR("PS timeout: %d ms\n", params.timeout_ms);
1520 	} else {
1521 		PR("PS timeout: disabled\n");
1522 	}
1523 
1524 	return 0;
1525 }
1526 
cmd_wifi_twt_setup_quick(const struct shell * sh,size_t argc,char * argv[])1527 static int cmd_wifi_twt_setup_quick(const struct shell *sh, size_t argc,
1528 				    char *argv[])
1529 {
1530 	struct net_if *iface = net_if_get_wifi_sta();
1531 	struct wifi_twt_params params = { 0 };
1532 	int idx = 1;
1533 	long value;
1534 	double twt_mantissa_scale = 0.0;
1535 	double twt_interval_scale = 0.0;
1536 	uint16_t scale = 1000;
1537 	int exponent = 0;
1538 
1539 	context.sh = sh;
1540 
1541 	/* Sensible defaults */
1542 	params.operation = WIFI_TWT_SETUP;
1543 	params.negotiation_type = WIFI_TWT_INDIVIDUAL;
1544 	params.setup_cmd = WIFI_TWT_SETUP_CMD_REQUEST;
1545 	params.dialog_token = 1;
1546 	params.flow_id = 0;
1547 	params.setup.responder = 0;
1548 	params.setup.implicit = 1;
1549 	params.setup.trigger = 0;
1550 	params.setup.announce = 0;
1551 
1552 	if (!parse_number(sh, &value, argv[idx++], NULL, 1, WIFI_MAX_TWT_WAKE_INTERVAL_US)) {
1553 		return -EINVAL;
1554 	}
1555 	params.setup.twt_wake_interval = (uint32_t)value;
1556 
1557 	if (!parse_number(sh, &value, argv[idx++], NULL, 1, WIFI_MAX_TWT_INTERVAL_US)) {
1558 		return -EINVAL;
1559 	}
1560 	params.setup.twt_interval = (uint64_t)value;
1561 
1562 	/* control the region of mantissa filed */
1563 	twt_interval_scale = (double)(params.setup.twt_interval / scale);
1564 	/* derive mantissa and exponent from interval */
1565 	twt_mantissa_scale = frexp(twt_interval_scale, &exponent);
1566 	params.setup.twt_mantissa = ceil(twt_mantissa_scale * scale);
1567 	params.setup.twt_exponent = exponent;
1568 
1569 	if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, &params, sizeof(params))) {
1570 		PR_WARNING("%s with %s failed, reason : %s\n",
1571 			   wifi_twt_operation_txt(params.operation),
1572 			   wifi_twt_negotiation_type_txt(params.negotiation_type),
1573 			   wifi_twt_get_err_code_str(params.fail_reason));
1574 
1575 		return -ENOEXEC;
1576 	}
1577 
1578 	PR("TWT operation %s with dg: %d, flow_id: %d requested\n",
1579 	   wifi_twt_operation_txt(params.operation),
1580 	   params.dialog_token, params.flow_id);
1581 
1582 	return 0;
1583 }
1584 
cmd_wifi_btwt_setup(const struct shell * sh,size_t argc,char * argv[])1585 static int cmd_wifi_btwt_setup(const struct shell *sh, size_t argc, char *argv[])
1586 {
1587 	struct net_if *iface = net_if_get_wifi_sap();
1588 	struct wifi_twt_params params = {0};
1589 	int idx = 1;
1590 	long value;
1591 	int ret = 0;
1592 
1593 	context.sh = sh;
1594 
1595 	params.btwt.sub_id = (uint16_t)shell_strtol(argv[idx++], 10, &ret);
1596 	params.btwt.nominal_wake = (uint8_t)shell_strtol(argv[idx++], 10, &ret);
1597 	params.btwt.max_sta_support = (uint8_t)shell_strtol(argv[idx++], 10, &ret);
1598 
1599 	if (!parse_number(sh, &value, argv[idx++], NULL, 1, 0xFFFF)) {
1600 		return -EINVAL;
1601 	}
1602 	params.btwt.twt_mantissa = (uint16_t)value;
1603 
1604 	params.btwt.twt_offset = (uint16_t)shell_strtol(argv[idx++], 10, &ret);
1605 
1606 	if (!parse_number(sh, &value, argv[idx++], NULL, 0, WIFI_MAX_TWT_EXPONENT)) {
1607 		return -EINVAL;
1608 	}
1609 	params.btwt.twt_exponent = (uint8_t)value;
1610 
1611 	params.btwt.sp_gap = (uint8_t)shell_strtol(argv[idx++], 10, &ret);
1612 
1613 	if (ret) {
1614 		PR_ERROR("Invalid argument (ret %d)\n", ret);
1615 		return -EINVAL;
1616 	}
1617 
1618 	if (net_mgmt(NET_REQUEST_WIFI_BTWT, iface, &params, sizeof(params))) {
1619 		PR_WARNING("Failed reason : %s\n",
1620 			   wifi_twt_get_err_code_str(params.fail_reason));
1621 
1622 		return -ENOEXEC;
1623 	}
1624 
1625 	PR("BTWT setup\n");
1626 
1627 	return 0;
1628 }
1629 
twt_args_to_params(const struct shell * sh,size_t argc,char * argv[],struct wifi_twt_params * params)1630 static int twt_args_to_params(const struct shell *sh, size_t argc, char *argv[],
1631 				 struct wifi_twt_params *params)
1632 {
1633 	int opt;
1634 	int opt_index = 0;
1635 	struct getopt_state *state;
1636 	long value;
1637 	double twt_mantissa_scale = 0.0;
1638 	double twt_interval_scale = 0.0;
1639 	uint16_t scale = 1000;
1640 	int exponent = 0;
1641 	static const struct option long_options[] = {
1642 		{"negotiation-type", required_argument, 0, 'n'},
1643 		{"setup-cmd", required_argument, 0, 'c'},
1644 		{"dialog-token", required_argument, 0, 't'},
1645 		{"flow-id", required_argument, 0, 'f'},
1646 		{"responder", required_argument, 0, 'r'},
1647 		{"trigger", required_argument, 0, 'T'},
1648 		{"implicit", required_argument, 0, 'I'},
1649 		{"announce", required_argument, 0, 'a'},
1650 		{"wake-interval", required_argument, 0, 'w'},
1651 		{"interval", required_argument, 0, 'i'},
1652 		{"wake-ahead-duration", required_argument, 0, 'D'},
1653 		{"info-disable", required_argument, 0, 'd'},
1654 		{"exponent", required_argument, 0, 'e'},
1655 		{"mantissa", required_argument, 0, 'm'},
1656 		{"help", no_argument, 0, 'h'},
1657 		{0, 0, 0, 0}};
1658 
1659 	params->operation = WIFI_TWT_SETUP;
1660 
1661 	while ((opt = getopt_long(argc, argv, "n:c:t:f:r:T:I:a:t:w:i:D:d:e:m:h",
1662 				  long_options, &opt_index)) != -1) {
1663 		state = getopt_state_get();
1664 		switch (opt) {
1665 		case 'n':
1666 			if (!parse_number(sh, &value, state->optarg, NULL,
1667 					  WIFI_TWT_INDIVIDUAL,
1668 					  WIFI_TWT_WAKE_TBTT)) {
1669 				return -EINVAL;
1670 			}
1671 			params->negotiation_type = (enum wifi_twt_negotiation_type)value;
1672 			break;
1673 
1674 		case 'c':
1675 			if (!parse_number(sh, &value, state->optarg, NULL,
1676 					  WIFI_TWT_SETUP_CMD_REQUEST,
1677 					  WIFI_TWT_SETUP_CMD_DEMAND)) {
1678 				return -EINVAL;
1679 			}
1680 			params->setup_cmd = (enum wifi_twt_setup_cmd)value;
1681 			break;
1682 
1683 		case 't':
1684 			if (!parse_number(sh, &value, state->optarg, NULL, 1, 255)) {
1685 				return -EINVAL;
1686 			}
1687 			params->dialog_token = (uint8_t)value;
1688 			break;
1689 
1690 		case 'f':
1691 			if (!parse_number(sh, &value, state->optarg, NULL, 0,
1692 					  (WIFI_MAX_TWT_FLOWS - 1))) {
1693 				return -EINVAL;
1694 			}
1695 			params->flow_id = (uint8_t)value;
1696 			break;
1697 
1698 		case 'r':
1699 			if (!parse_number(sh, &value, state->optarg, NULL, 0, 1)) {
1700 				return -EINVAL;
1701 			}
1702 			params->setup.responder = (bool)value;
1703 			break;
1704 
1705 		case 'T':
1706 			if (!parse_number(sh, &value, state->optarg, NULL, 0, 1)) {
1707 				return -EINVAL;
1708 			}
1709 			params->setup.trigger = (bool)value;
1710 			break;
1711 
1712 		case 'I':
1713 			if (!parse_number(sh, &value, state->optarg, NULL, 0, 1)) {
1714 				return -EINVAL;
1715 			}
1716 			params->setup.implicit = (bool)value;
1717 			break;
1718 
1719 		case 'a':
1720 			if (!parse_number(sh, &value, state->optarg, NULL, 0, 1)) {
1721 				return -EINVAL;
1722 			}
1723 			params->setup.announce = (bool)value;
1724 			break;
1725 
1726 		case 'w':
1727 			if (!parse_number(sh, &value, state->optarg, NULL, 1,
1728 					  WIFI_MAX_TWT_WAKE_INTERVAL_US)) {
1729 				return -EINVAL;
1730 			}
1731 			params->setup.twt_wake_interval = (uint32_t)value;
1732 			break;
1733 
1734 		case 'i':
1735 			if (!parse_number(sh, &value, state->optarg, NULL, 1,
1736 					  WIFI_MAX_TWT_INTERVAL_US)) {
1737 				return -EINVAL;
1738 			}
1739 			params->setup.twt_interval = (uint64_t)value;
1740 			break;
1741 
1742 		case 'D':
1743 			if (!parse_number(sh, &value, state->optarg, NULL, 0,
1744 					  WIFI_MAX_TWT_WAKE_AHEAD_DURATION_US)) {
1745 				return -EINVAL;
1746 			}
1747 			params->setup.twt_wake_ahead_duration = (uint32_t)value;
1748 			break;
1749 
1750 		case 'd':
1751 			if (!parse_number(sh, &value, state->optarg, NULL, 0, 1)) {
1752 				return -EINVAL;
1753 			}
1754 			params->setup.twt_info_disable = (bool)value;
1755 			break;
1756 
1757 		case 'e':
1758 			if (!parse_number(sh, &value, state->optarg, NULL, 0,
1759 					  WIFI_MAX_TWT_EXPONENT)) {
1760 				return -EINVAL;
1761 			}
1762 			params->setup.twt_exponent = (uint8_t)value;
1763 			break;
1764 
1765 		case 'm':
1766 			if (!parse_number(sh, &value, state->optarg, NULL, 0, 0xFFFF)) {
1767 				return -EINVAL;
1768 			}
1769 			params->setup.twt_mantissa = (uint16_t)value;
1770 			break;
1771 
1772 		case 'h':
1773 			return -ENOEXEC;
1774 		}
1775 	}
1776 
1777 	if ((params->setup.twt_interval != 0) &&
1778 	   ((params->setup.twt_exponent != 0) ||
1779 	   (params->setup.twt_mantissa != 0))) {
1780 		PR_ERROR("Only one of TWT internal or (mantissa, exponent) should be used\n");
1781 		return -EINVAL;
1782 	}
1783 
1784 	if (params->setup.twt_interval) {
1785 		/* control the region of mantissa filed */
1786 		twt_interval_scale = (double)(params->setup.twt_interval / scale);
1787 		/* derive mantissa and exponent from interval */
1788 		twt_mantissa_scale = frexp(twt_interval_scale, &exponent);
1789 		params->setup.twt_mantissa = ceil(twt_mantissa_scale * scale);
1790 		params->setup.twt_exponent = exponent;
1791 	} else if ((params->setup.twt_exponent != 0) ||
1792 		   (params->setup.twt_mantissa != 0)) {
1793 		params->setup.twt_interval = floor(ldexp(params->setup.twt_mantissa,
1794 							 params->setup.twt_exponent));
1795 	} else {
1796 		PR_ERROR("Either TWT interval or (mantissa, exponent) is needed\n");
1797 		return -EINVAL;
1798 	}
1799 
1800 	return 0;
1801 }
1802 
cmd_wifi_twt_setup(const struct shell * sh,size_t argc,char * argv[])1803 static int cmd_wifi_twt_setup(const struct shell *sh, size_t argc,
1804 			      char *argv[])
1805 {
1806 	struct net_if *iface = net_if_get_wifi_sta();
1807 	struct wifi_twt_params params = { 0 };
1808 
1809 	context.sh = sh;
1810 
1811 	if (twt_args_to_params(sh, argc, argv, &params)) {
1812 		shell_help(sh);
1813 		return -ENOEXEC;
1814 	}
1815 
1816 	if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, &params, sizeof(params))) {
1817 		PR_WARNING("%s with %s failed. reason : %s\n",
1818 			   wifi_twt_operation_txt(params.operation),
1819 			   wifi_twt_negotiation_type_txt(params.negotiation_type),
1820 			   wifi_twt_get_err_code_str(params.fail_reason));
1821 
1822 		return -ENOEXEC;
1823 	}
1824 
1825 	PR("TWT operation %s with dg: %d, flow_id: %d requested\n",
1826 	   wifi_twt_operation_txt(params.operation),
1827 	   params.dialog_token, params.flow_id);
1828 
1829 	return 0;
1830 }
1831 
cmd_wifi_twt_teardown(const struct shell * sh,size_t argc,char * argv[])1832 static int cmd_wifi_twt_teardown(const struct shell *sh, size_t argc,
1833 				 char *argv[])
1834 {
1835 	struct net_if *iface = net_if_get_wifi_sta();
1836 	struct wifi_twt_params params = { 0 };
1837 	long value;
1838 
1839 	context.sh = sh;
1840 	int idx = 1;
1841 
1842 	params.operation = WIFI_TWT_TEARDOWN;
1843 
1844 	if (!parse_number(sh, &value, argv[idx++], NULL, WIFI_TWT_INDIVIDUAL,
1845 			  WIFI_TWT_WAKE_TBTT)) {
1846 		return -EINVAL;
1847 	}
1848 	params.negotiation_type = (enum wifi_twt_negotiation_type)value;
1849 
1850 	if (!parse_number(sh, &value, argv[idx++], NULL, WIFI_TWT_SETUP_CMD_REQUEST,
1851 			  WIFI_TWT_SETUP_CMD_DEMAND)) {
1852 		return -EINVAL;
1853 	}
1854 	params.setup_cmd = (enum wifi_twt_setup_cmd)value;
1855 
1856 	if (!parse_number(sh, &value, argv[idx++], NULL, 1, 255)) {
1857 		return -EINVAL;
1858 	}
1859 	params.dialog_token = (uint8_t)value;
1860 
1861 	if (!parse_number(sh, &value, argv[idx++], NULL, 0, (WIFI_MAX_TWT_FLOWS - 1))) {
1862 		return -EINVAL;
1863 	}
1864 	params.flow_id = (uint8_t)value;
1865 
1866 	if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, &params, sizeof(params))) {
1867 		PR_WARNING("%s with %s failed, reason : %s\n",
1868 			   wifi_twt_operation_txt(params.operation),
1869 			   wifi_twt_negotiation_type_txt(params.negotiation_type),
1870 			   wifi_twt_get_err_code_str(params.fail_reason));
1871 
1872 		return -ENOEXEC;
1873 	}
1874 
1875 	PR("TWT operation %s with dg: %d, flow_id: %d success\n",
1876 	   wifi_twt_operation_txt(params.operation),
1877 	   params.dialog_token, params.flow_id);
1878 
1879 	return 0;
1880 }
1881 
cmd_wifi_twt_teardown_all(const struct shell * sh,size_t argc,char * argv[])1882 static int cmd_wifi_twt_teardown_all(const struct shell *sh, size_t argc,
1883 				     char *argv[])
1884 {
1885 	struct net_if *iface = net_if_get_wifi_sta();
1886 	struct wifi_twt_params params = { 0 };
1887 
1888 	context.sh = sh;
1889 
1890 	params.operation = WIFI_TWT_TEARDOWN;
1891 	params.teardown.teardown_all = 1;
1892 
1893 	if (net_mgmt(NET_REQUEST_WIFI_TWT, iface, &params, sizeof(params))) {
1894 		PR_WARNING("%s with %s failed, reason : %s\n",
1895 			   wifi_twt_operation_txt(params.operation),
1896 			   wifi_twt_negotiation_type_txt(params.negotiation_type),
1897 			   wifi_twt_get_err_code_str(params.fail_reason));
1898 
1899 		return -ENOEXEC;
1900 	}
1901 
1902 	PR("TWT operation %s all flows success\n",
1903 	   wifi_twt_operation_txt(params.operation));
1904 
1905 	return 0;
1906 }
1907 
cmd_wifi_ap_enable(const struct shell * sh,size_t argc,char * argv[])1908 static int cmd_wifi_ap_enable(const struct shell *sh, size_t argc,
1909 			      char *argv[])
1910 {
1911 	struct net_if *iface = net_if_get_wifi_sap();
1912 	struct wifi_connect_req_params cnx_params = {0};
1913 	int ret;
1914 
1915 	context.sh = sh;
1916 	if (__wifi_args_to_params(sh, argc, &argv[0], &cnx_params, WIFI_MODE_AP)) {
1917 		shell_help(sh);
1918 		return -ENOEXEC;
1919 	}
1920 
1921 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE
1922 	/* Load the enterprise credentials if needed */
1923 	if (cnx_params.security == WIFI_SECURITY_TYPE_EAP_TLS ||
1924 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_MSCHAPV2 ||
1925 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC ||
1926 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 ||
1927 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS ||
1928 	    cnx_params.security == WIFI_SECURITY_TYPE_EAP_TLS_SHA256) {
1929 		cmd_wifi_set_enterprise_creds(sh, iface);
1930 	}
1931 #endif
1932 
1933 	k_mutex_init(&wifi_ap_sta_list_lock);
1934 
1935 	ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, iface, &cnx_params,
1936 		       sizeof(struct wifi_connect_req_params));
1937 	if (ret) {
1938 		PR_WARNING("AP mode enable failed: %s\n", strerror(-ret));
1939 		return -ENOEXEC;
1940 	}
1941 
1942 	PR("AP mode enable requested\n");
1943 
1944 	return 0;
1945 }
1946 
cmd_wifi_ap_disable(const struct shell * sh,size_t argc,char * argv[])1947 static int cmd_wifi_ap_disable(const struct shell *sh, size_t argc,
1948 			       char *argv[])
1949 {
1950 	struct net_if *iface = net_if_get_wifi_sap();
1951 	int ret;
1952 
1953 	ret = net_mgmt(NET_REQUEST_WIFI_AP_DISABLE, iface, NULL, 0);
1954 	if (ret) {
1955 		PR_WARNING("AP mode disable failed: %s\n", strerror(-ret));
1956 		return -ENOEXEC;
1957 	}
1958 
1959 	PR("AP mode disable requested\n");
1960 	return 0;
1961 }
1962 
cmd_wifi_ap_stations(const struct shell * sh,size_t argc,char * argv[])1963 static int cmd_wifi_ap_stations(const struct shell *sh, size_t argc,
1964 				char *argv[])
1965 {
1966 	size_t id = 1;
1967 
1968 	ARG_UNUSED(argv);
1969 	ARG_UNUSED(argc);
1970 
1971 	PR("AP stations:\n");
1972 	PR("============\n");
1973 
1974 	k_mutex_lock(&wifi_ap_sta_list_lock, K_FOREVER);
1975 	for (int i = 0; i < CONFIG_WIFI_SHELL_MAX_AP_STA; i++) {
1976 		struct wifi_ap_sta_info *sta;
1977 		uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
1978 
1979 		if (!sta_list[i].valid) {
1980 			continue;
1981 		}
1982 
1983 		sta = &sta_list[i].sta_info;
1984 
1985 		PR("Station %zu:\n", id++);
1986 		PR("==========\n");
1987 		PR("MAC: %s\n",
1988 		   net_sprint_ll_addr_buf(sta->mac,
1989 					  WIFI_MAC_ADDR_LEN,
1990 					  mac_string_buf,
1991 					  sizeof(mac_string_buf)));
1992 		PR("Link mode: %s\n",
1993 		   wifi_link_mode_txt(sta->link_mode));
1994 		PR("TWT: %s\n",
1995 		   sta->twt_capable ? "Supported" : "Not supported");
1996 	}
1997 
1998 	if (id == 1) {
1999 		PR("No stations connected\n");
2000 	}
2001 	k_mutex_unlock(&wifi_ap_sta_list_lock);
2002 
2003 	return 0;
2004 }
2005 
cmd_wifi_ap_sta_disconnect(const struct shell * sh,size_t argc,char * argv[])2006 static int cmd_wifi_ap_sta_disconnect(const struct shell *sh, size_t argc,
2007 				      char *argv[])
2008 {
2009 	struct net_if *iface = net_if_get_wifi_sap();
2010 	uint8_t mac[6];
2011 	int ret;
2012 
2013 	if (net_bytes_from_str(mac, sizeof(mac), argv[1]) < 0) {
2014 		PR_WARNING("Invalid MAC address\n");
2015 		return -ENOEXEC;
2016 	}
2017 
2018 	ret = net_mgmt(NET_REQUEST_WIFI_AP_STA_DISCONNECT, iface, mac, sizeof(mac));
2019 	if (ret) {
2020 		PR_WARNING("AP station disconnect failed: %s\n",
2021 			   strerror(-ret));
2022 		return -ENOEXEC;
2023 	}
2024 
2025 	PR("AP station disconnect requested\n");
2026 	return 0;
2027 }
2028 
wifi_ap_config_args_to_params(const struct shell * sh,size_t argc,char * argv[],struct wifi_ap_config_params * params)2029 static int wifi_ap_config_args_to_params(const struct shell *sh, size_t argc, char *argv[],
2030 					 struct wifi_ap_config_params *params)
2031 {
2032 	int opt;
2033 	int opt_index = 0;
2034 	struct getopt_state *state;
2035 	static const struct option long_options[] = {
2036 		{"max_inactivity", required_argument, 0, 'i'},
2037 		{"max_num_sta", required_argument, 0, 's'},
2038 #if defined(CONFIG_WIFI_NM_HOSTAPD_AP)
2039 		{"ht_capab", required_argument, 0, 'n'},
2040 		{"vht_capab", required_argument, 0, 'c'},
2041 #endif
2042 		{"help", no_argument, 0, 'h'},
2043 		{0, 0, 0, 0}};
2044 	long val;
2045 
2046 	while ((opt = getopt_long(argc, argv, "i:s:n:c:h",
2047 				  long_options, &opt_index)) != -1) {
2048 		state = getopt_state_get();
2049 		switch (opt) {
2050 		case 'i':
2051 			if (!parse_number(sh, &val, state->optarg, "max_inactivity",
2052 					  0, WIFI_AP_STA_MAX_INACTIVITY)) {
2053 				return -EINVAL;
2054 			}
2055 			params->max_inactivity = (uint32_t)val;
2056 			params->type |= WIFI_AP_CONFIG_PARAM_MAX_INACTIVITY;
2057 			break;
2058 		case 's':
2059 			if (!parse_number(sh, &val, state->optarg, "max_num_sta",
2060 					  0, CONFIG_WIFI_MGMT_AP_MAX_NUM_STA)) {
2061 				return -EINVAL;
2062 			}
2063 			params->max_num_sta = (uint32_t)val;
2064 			params->type |= WIFI_AP_CONFIG_PARAM_MAX_NUM_STA;
2065 			break;
2066 #if defined(CONFIG_WIFI_NM_HOSTAPD_AP)
2067 		case 'n':
2068 			strncpy(params->ht_capab, state->optarg, WIFI_AP_IEEE_80211_CAPAB_MAX_LEN);
2069 			params->type |= WIFI_AP_CONFIG_PARAM_HT_CAPAB;
2070 			break;
2071 		case 'c':
2072 			strncpy(params->vht_capab, state->optarg, WIFI_AP_IEEE_80211_CAPAB_MAX_LEN);
2073 			params->type |= WIFI_AP_CONFIG_PARAM_VHT_CAPAB;
2074 			break;
2075 #endif
2076 		case 'h':
2077 			shell_help(sh);
2078 			return SHELL_CMD_HELP_PRINTED;
2079 		default:
2080 			PR_ERROR("Invalid option %c\n", state->optopt);
2081 			shell_help(sh);
2082 			return SHELL_CMD_HELP_PRINTED;
2083 		}
2084 	}
2085 
2086 	return 0;
2087 }
2088 
cmd_wifi_ap_config_params(const struct shell * sh,size_t argc,char * argv[])2089 static int cmd_wifi_ap_config_params(const struct shell *sh, size_t argc,
2090 				     char *argv[])
2091 {
2092 	struct net_if *iface = net_if_get_wifi_sap();
2093 	struct wifi_ap_config_params ap_config_params = { 0 };
2094 	int ret = -1;
2095 
2096 	context.sh = sh;
2097 
2098 	if (wifi_ap_config_args_to_params(sh, argc, argv, &ap_config_params)) {
2099 		return -ENOEXEC;
2100 	}
2101 
2102 	ret = net_mgmt(NET_REQUEST_WIFI_AP_CONFIG_PARAM, iface,
2103 		       &ap_config_params, sizeof(struct wifi_ap_config_params));
2104 	if (ret) {
2105 		PR_WARNING("Setting AP parameter failed: %s\n",
2106 			   strerror(-ret));
2107 		return -ENOEXEC;
2108 	}
2109 
2110 	return 0;
2111 }
2112 
cmd_wifi_ap_set_rts_threshold(const struct shell * sh,size_t argc,char * argv[])2113 static int cmd_wifi_ap_set_rts_threshold(const struct shell *sh, size_t argc, char *argv[])
2114 {
2115 	struct net_if *iface = net_if_get_wifi_sap();
2116 	unsigned int rts_threshold = -1; /* Default value if user supplies "off" argument */
2117 	int err = 0;
2118 
2119 	context.sh = sh;
2120 
2121 	if (strcmp(argv[1], "off") != 0) {
2122 		long rts_val = shell_strtol(argv[1], 10, &err);
2123 
2124 		if (err) {
2125 			shell_error(sh, "Unable to parse input (err %d)", err);
2126 			return err;
2127 		}
2128 
2129 		rts_threshold = (unsigned int)rts_val;
2130 	}
2131 
2132 	if (net_mgmt(NET_REQUEST_WIFI_AP_RTS_THRESHOLD, iface,
2133 		     &rts_threshold, sizeof(rts_threshold))) {
2134 		shell_fprintf(sh, SHELL_WARNING,
2135 			      "Setting RTS threshold failed.\n");
2136 		return -ENOEXEC;
2137 	}
2138 
2139 	if ((int)rts_threshold >= 0)
2140 		shell_fprintf(sh, SHELL_NORMAL, "RTS threshold: %d\n", rts_threshold);
2141 	else
2142 		shell_fprintf(sh, SHELL_NORMAL, "RTS threshold is off\n");
2143 
2144 	return 0;
2145 }
2146 
cmd_wifi_reg_domain(const struct shell * sh,size_t argc,char * argv[])2147 static int cmd_wifi_reg_domain(const struct shell *sh, size_t argc,
2148 			       char *argv[])
2149 {
2150 	struct net_if *iface = net_if_get_wifi_sta();
2151 	struct wifi_reg_domain regd = {0};
2152 	int ret, chan_idx = 0;
2153 	int opt;
2154 	bool force = false;
2155 	bool verbose = false;
2156 	int opt_index = 0;
2157 	static const struct option long_options[] = {
2158 		{"force", no_argument, 0, 'f'},
2159 		{"verbose", no_argument, 0, 'v'},
2160 		{NULL, 0, NULL, 0}
2161 	};
2162 
2163 	while ((opt = getopt_long(argc, argv, "fv", long_options, &opt_index)) != -1) {
2164 		switch (opt) {
2165 		case 'f':
2166 			force = true;
2167 			break;
2168 		case 'v':
2169 			verbose = true;
2170 			break;
2171 		default:
2172 			return -ENOEXEC;
2173 		}
2174 	}
2175 
2176 	if (optind == argc) {
2177 		regd.chan_info = &chan_info[0];
2178 		regd.oper = WIFI_MGMT_GET;
2179 	} else if (optind == argc - 1) {
2180 		if (strlen(argv[optind]) != 2) {
2181 			PR_WARNING("Invalid reg domain: Length should be two letters/digits\n");
2182 			return -ENOEXEC;
2183 		}
2184 
2185 		/* Two letter country code with special case of 00 for WORLD */
2186 		if (((argv[optind][0] < 'A' || argv[optind][0] > 'Z') ||
2187 			(argv[optind][1] < 'A' || argv[optind][1] > 'Z')) &&
2188 			(argv[optind][0] != '0' || argv[optind][1] != '0')) {
2189 			PR_WARNING("Invalid reg domain %c%c\n", argv[optind][0], argv[optind][1]);
2190 			return -ENOEXEC;
2191 		}
2192 		regd.country_code[0] = argv[optind][0];
2193 		regd.country_code[1] = argv[optind][1];
2194 		regd.force = force;
2195 		regd.oper = WIFI_MGMT_SET;
2196 	} else {
2197 		return -ENOEXEC;
2198 	}
2199 
2200 	ret = net_mgmt(NET_REQUEST_WIFI_REG_DOMAIN, iface,
2201 		       &regd, sizeof(regd));
2202 	if (ret) {
2203 		PR_WARNING("Cannot %s Regulatory domain: %d\n",
2204 			   regd.oper == WIFI_MGMT_GET ? "get" : "set", ret);
2205 		return -ENOEXEC;
2206 	}
2207 
2208 	if (regd.oper == WIFI_MGMT_GET) {
2209 		PR("Wi-Fi Regulatory domain is: %c%c\n",
2210 		   regd.country_code[0], regd.country_code[1]);
2211 		if (!verbose) {
2212 			return 0;
2213 		}
2214 		PR("<channel>\t<center frequency>\t<supported(y/n)>\t"
2215 		   "<max power(dBm)>\t<passive transmission only(y/n)>\t<DFS supported(y/n)>\n");
2216 		for (chan_idx = 0; chan_idx < regd.num_channels; chan_idx++) {
2217 			PR("  %d\t\t\t%d\t\t\t%s\t\t\t%d\t\t\t%s\t\t\t\t%s\n",
2218 			   wifi_freq_to_channel(chan_info[chan_idx].center_frequency),
2219 			   chan_info[chan_idx].center_frequency,
2220 			   chan_info[chan_idx].supported ? "y" : "n",
2221 			   chan_info[chan_idx].max_power,
2222 			   chan_info[chan_idx].passive_only ? "y" : "n",
2223 			   chan_info[chan_idx].dfs ? "y" : "n");
2224 		}
2225 	} else {
2226 		PR("Wi-Fi Regulatory domain set to: %c%c\n",
2227 		   regd.country_code[0], regd.country_code[1]);
2228 	}
2229 
2230 	return 0;
2231 }
2232 
cmd_wifi_listen_interval(const struct shell * sh,size_t argc,char * argv[])2233 static int cmd_wifi_listen_interval(const struct shell *sh, size_t argc, char *argv[])
2234 {
2235 	struct net_if *iface = net_if_get_wifi_sta();
2236 	struct wifi_ps_params params = { 0 };
2237 	long interval;
2238 
2239 	context.sh = sh;
2240 
2241 	if (!parse_number(sh, &interval, argv[1], NULL,
2242 			  WIFI_LISTEN_INTERVAL_MIN,
2243 			  WIFI_LISTEN_INTERVAL_MAX)) {
2244 		return -EINVAL;
2245 	}
2246 
2247 	params.listen_interval = interval;
2248 	params.type = WIFI_PS_PARAM_LISTEN_INTERVAL;
2249 
2250 	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
2251 		if (params.fail_reason ==
2252 		    WIFI_PS_PARAM_LISTEN_INTERVAL_RANGE_INVALID) {
2253 			PR_WARNING("Setting listen interval failed. Reason :%s\n",
2254 				   wifi_ps_get_config_err_code_str(params.fail_reason));
2255 		} else {
2256 			PR_WARNING("Setting listen interval failed. Reason :%s\n",
2257 				   wifi_ps_get_config_err_code_str(params.fail_reason));
2258 		}
2259 		return -ENOEXEC;
2260 	}
2261 
2262 	PR("Listen interval %hu\n", params.listen_interval);
2263 
2264 	return 0;
2265 }
2266 
2267 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
cmd_wifi_btm_query(const struct shell * sh,size_t argc,char * argv[])2268 static int cmd_wifi_btm_query(const struct shell *sh, size_t argc, char *argv[])
2269 {
2270 	struct net_if *iface = net_if_get_wifi_sta();
2271 	uint8_t query_reason = 0;
2272 	long tmp = 0;
2273 
2274 	context.sh = sh;
2275 
2276 	if (!parse_number(sh, &tmp, argv[1], NULL,
2277 			  WIFI_BTM_QUERY_REASON_UNSPECIFIED, WIFI_BTM_QUERY_REASON_LEAVING_ESS)) {
2278 		return -EINVAL;
2279 	}
2280 
2281 	query_reason = tmp;
2282 
2283 	if (net_mgmt(NET_REQUEST_WIFI_BTM_QUERY, iface, &query_reason, sizeof(query_reason))) {
2284 		PR_WARNING("Setting BTM query Reason failed. Reason : %d\n", query_reason);
2285 		return -ENOEXEC;
2286 	}
2287 
2288 	PR("Query reason %d\n", query_reason);
2289 
2290 	return 0;
2291 }
2292 #endif
2293 
cmd_wifi_wps_pbc(const struct shell * sh,size_t argc,char * argv[])2294 static int cmd_wifi_wps_pbc(const struct shell *sh, size_t argc, char *argv[])
2295 {
2296 	struct net_if *iface = net_if_get_wifi_sta();
2297 	struct wifi_wps_config_params params = {0};
2298 
2299 	context.sh = sh;
2300 
2301 	if (argc == 1) {
2302 		params.oper = WIFI_WPS_PBC;
2303 	} else {
2304 		shell_help(sh);
2305 		return -ENOEXEC;
2306 	}
2307 
2308 	if (net_mgmt(NET_REQUEST_WIFI_WPS_CONFIG, iface, &params, sizeof(params))) {
2309 		PR_WARNING("Start wps pbc connection failed\n");
2310 		return -ENOEXEC;
2311 	}
2312 
2313 	return 0;
2314 }
2315 
cmd_wifi_wps_pin(const struct shell * sh,size_t argc,char * argv[])2316 static int cmd_wifi_wps_pin(const struct shell *sh, size_t argc, char *argv[])
2317 {
2318 	struct net_if *iface = net_if_get_wifi_sta();
2319 	struct wifi_wps_config_params params = {0};
2320 
2321 	context.sh = sh;
2322 
2323 	if (argc == 1) {
2324 		params.oper = WIFI_WPS_PIN_GET;
2325 	} else if (argc == 2) {
2326 		params.oper = WIFI_WPS_PIN_SET;
2327 		strncpy(params.pin, argv[1], WIFI_WPS_PIN_MAX_LEN);
2328 	} else {
2329 		shell_help(sh);
2330 		return -ENOEXEC;
2331 	}
2332 
2333 	if (net_mgmt(NET_REQUEST_WIFI_WPS_CONFIG, iface, &params, sizeof(params))) {
2334 		PR_WARNING("Start wps pin connection failed\n");
2335 		return -ENOEXEC;
2336 	}
2337 
2338 	if (params.oper == WIFI_WPS_PIN_GET) {
2339 		PR("WPS PIN is: %s\n", params.pin);
2340 	}
2341 
2342 	return 0;
2343 }
2344 
cmd_wifi_ap_wps_pbc(const struct shell * sh,size_t argc,char * argv[])2345 static int cmd_wifi_ap_wps_pbc(const struct shell *sh, size_t argc, char *argv[])
2346 {
2347 	struct net_if *iface = net_if_get_wifi_sap();
2348 	struct wifi_wps_config_params params = {0};
2349 
2350 	context.sh = sh;
2351 
2352 	if (argc == 1) {
2353 		params.oper = WIFI_WPS_PBC;
2354 	} else {
2355 		shell_help(sh);
2356 		return -ENOEXEC;
2357 	}
2358 
2359 	if (net_mgmt(NET_REQUEST_WIFI_WPS_CONFIG, iface, &params, sizeof(params))) {
2360 		PR_WARNING("Start AP WPS PBC failed\n");
2361 		return -ENOEXEC;
2362 	}
2363 
2364 	return 0;
2365 }
2366 
cmd_wifi_ap_wps_pin(const struct shell * sh,size_t argc,char * argv[])2367 static int cmd_wifi_ap_wps_pin(const struct shell *sh, size_t argc, char *argv[])
2368 {
2369 	struct net_if *iface = net_if_get_wifi_sap();
2370 	struct wifi_wps_config_params params = {0};
2371 
2372 	context.sh = sh;
2373 
2374 	if (argc == 1) {
2375 		params.oper = WIFI_WPS_PIN_GET;
2376 	} else if (argc == 2) {
2377 		params.oper = WIFI_WPS_PIN_SET;
2378 		strncpy(params.pin, argv[1], WIFI_WPS_PIN_MAX_LEN);
2379 	} else {
2380 		shell_help(sh);
2381 		return -ENOEXEC;
2382 	}
2383 
2384 	if (net_mgmt(NET_REQUEST_WIFI_WPS_CONFIG, iface, &params, sizeof(params))) {
2385 		PR_WARNING("Start AP WPS PIN failed\n");
2386 		return -ENOEXEC;
2387 	}
2388 
2389 	if (params.oper == WIFI_WPS_PIN_GET) {
2390 		PR("WPS PIN is: %s\n", params.pin);
2391 	}
2392 
2393 	return 0;
2394 }
2395 
cmd_wifi_ps_wakeup_mode(const struct shell * sh,size_t argc,char * argv[])2396 static int cmd_wifi_ps_wakeup_mode(const struct shell *sh, size_t argc, char *argv[])
2397 {
2398 	struct net_if *iface = net_if_get_wifi_sta();
2399 	struct wifi_ps_params params = { 0 };
2400 
2401 	context.sh = sh;
2402 
2403 	if (!strncasecmp(argv[1], "dtim", 4)) {
2404 		params.wakeup_mode = WIFI_PS_WAKEUP_MODE_DTIM;
2405 	} else if (!strncasecmp(argv[1], "listen_interval", 15)) {
2406 		params.wakeup_mode = WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL;
2407 	} else {
2408 		PR_WARNING("Invalid argument\n");
2409 		PR_INFO("Valid argument : <dtim> / <listen_interval>\n");
2410 		return -ENOEXEC;
2411 	}
2412 
2413 	params.type = WIFI_PS_PARAM_WAKEUP_MODE;
2414 
2415 	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
2416 		PR_WARNING("Setting PS wake up mode to %s failed..Reason :%s\n",
2417 			   params.wakeup_mode ? "Listen interval" : "DTIM interval",
2418 			   wifi_ps_get_config_err_code_str(params.fail_reason));
2419 		return -ENOEXEC;
2420 	}
2421 
2422 	PR("%s\n", wifi_ps_wakeup_mode_txt(params.wakeup_mode));
2423 
2424 	return 0;
2425 }
2426 
cmd_wifi_set_rts_threshold(const struct shell * sh,size_t argc,char * argv[])2427 static int cmd_wifi_set_rts_threshold(const struct shell *sh, size_t argc, char *argv[])
2428 {
2429 	struct net_if *iface = net_if_get_wifi_sta();
2430 	unsigned int rts_threshold = -1; /* Default value if user supplies "off" argument */
2431 	int err = 0;
2432 
2433 	context.sh = sh;
2434 
2435 	if (argc > 2) {
2436 		PR_WARNING("Invalid number of arguments\n");
2437 		return -ENOEXEC;
2438 	}
2439 
2440 	if (argc == 1) {
2441 		if (net_mgmt(NET_REQUEST_WIFI_RTS_THRESHOLD_CONFIG, iface,
2442 			     &rts_threshold, sizeof(rts_threshold))) {
2443 			PR_WARNING("Failed to get rts_threshold\n");
2444 			return -ENOEXEC;
2445 		}
2446 
2447 		if ((int)rts_threshold < 0) {
2448 			PR("RTS threshold is off\n");
2449 		} else {
2450 			PR("RTS threshold: %d\n", rts_threshold);
2451 		}
2452 	}
2453 
2454 	if (argc == 2) {
2455 		if (strcmp(argv[1], "off") != 0) {
2456 			long rts_val = shell_strtol(argv[1], 10, &err);
2457 
2458 			if (err) {
2459 				shell_error(sh, "Unable to parse input (err %d)", err);
2460 				return err;
2461 			}
2462 
2463 			rts_threshold = (unsigned int)rts_val;
2464 		}
2465 
2466 		if (net_mgmt(NET_REQUEST_WIFI_RTS_THRESHOLD, iface,
2467 			     &rts_threshold, sizeof(rts_threshold))) {
2468 			shell_fprintf(sh, SHELL_WARNING,
2469 					"Setting RTS threshold failed.\n");
2470 			return -ENOEXEC;
2471 		}
2472 
2473 		if ((int)rts_threshold >= 0) {
2474 			shell_fprintf(sh, SHELL_NORMAL, "RTS threshold: %d\n", rts_threshold);
2475 		} else {
2476 			shell_fprintf(sh, SHELL_NORMAL, "RTS threshold is off\n");
2477 		}
2478 	}
2479 
2480 	return 0;
2481 }
2482 
cmd_wifi_ps_exit_strategy(const struct shell * sh,size_t argc,char * argv[])2483 static int cmd_wifi_ps_exit_strategy(const struct shell *sh, size_t argc,
2484 			    char *argv[])
2485 {
2486 	struct net_if *iface = net_if_get_wifi_sta();
2487 	struct wifi_ps_params params = { 0 };
2488 
2489 	context.sh = sh;
2490 
2491 	if (!strncmp(argv[1], "tim", 3)) {
2492 		params.exit_strategy = WIFI_PS_EXIT_EVERY_TIM;
2493 	} else if (!strncmp(argv[1], "custom", 6)) {
2494 		params.exit_strategy = WIFI_PS_EXIT_CUSTOM_ALGO;
2495 	} else {
2496 		shell_fprintf(sh, SHELL_WARNING, "Invalid argument\n");
2497 		shell_fprintf(sh, SHELL_INFO, "Valid argument : <tim> / <custom>\n");
2498 		return -ENOEXEC;
2499 	}
2500 
2501 	params.type = WIFI_PS_PARAM_EXIT_STRATEGY;
2502 
2503 	if (net_mgmt(NET_REQUEST_WIFI_PS, iface, &params, sizeof(params))) {
2504 		shell_fprintf(sh, SHELL_WARNING,
2505 			      "Setting PS exit strategy to %s failed..Reason :%s\n",
2506 			      wifi_ps_exit_strategy_txt(params.exit_strategy),
2507 			      wifi_ps_get_config_err_code_str(params.fail_reason));
2508 		return -ENOEXEC;
2509 	}
2510 
2511 	shell_fprintf(sh, SHELL_NORMAL, "%s\n",
2512 		      wifi_ps_exit_strategy_txt(params.exit_strategy));
2513 
2514 	return 0;
2515 }
2516 
parse_mode_args_to_params(const struct shell * sh,int argc,char * argv[],struct wifi_mode_info * mode,bool * do_mode_oper)2517 void parse_mode_args_to_params(const struct shell *sh, int argc,
2518 			       char *argv[], struct wifi_mode_info *mode,
2519 			       bool *do_mode_oper)
2520 {
2521 	int opt;
2522 	int opt_index = 0;
2523 	struct getopt_state *state;
2524 	static const struct option long_options[] = {
2525 		{"if-index", optional_argument, 0, 'i'},
2526 		{"sta", no_argument, 0, 's'},
2527 		{"monitor", no_argument, 0, 'm'},
2528 		{"ap", no_argument, 0, 'a'},
2529 		{"softap", no_argument, 0, 'k'},
2530 		{"get", no_argument, 0, 'g'},
2531 		{"help", no_argument, 0, 'h'},
2532 		{0, 0, 0, 0}};
2533 
2534 	while ((opt = getopt_long(argc, argv, "i:smtpakgh",
2535 				  long_options, &opt_index)) != -1) {
2536 		state = getopt_state_get();
2537 		switch (opt) {
2538 		case 's':
2539 			mode->mode |= WIFI_STA_MODE;
2540 			break;
2541 		case 'm':
2542 			mode->mode |= WIFI_MONITOR_MODE;
2543 			break;
2544 		case 'a':
2545 			mode->mode |= WIFI_AP_MODE;
2546 			break;
2547 		case 'k':
2548 			mode->mode |= WIFI_SOFTAP_MODE;
2549 			break;
2550 		case 'g':
2551 			mode->oper = WIFI_MGMT_GET;
2552 			break;
2553 		case 'i':
2554 			mode->if_index = (uint8_t)atoi(state->optarg);
2555 			break;
2556 		case 'h':
2557 			shell_help(sh);
2558 			*do_mode_oper = false;
2559 			break;
2560 		case '?':
2561 		default:
2562 			break;
2563 		}
2564 	}
2565 }
2566 
cmd_wifi_mode(const struct shell * sh,size_t argc,char * argv[])2567 static int cmd_wifi_mode(const struct shell *sh, size_t argc, char *argv[])
2568 {
2569 	struct net_if *iface;
2570 	struct wifi_mode_info mode_info = {0};
2571 	int ret;
2572 	bool do_mode_oper = true;
2573 
2574 	if (argc > 1) {
2575 		mode_info.oper = WIFI_MGMT_SET;
2576 		parse_mode_args_to_params(sh, argc, argv, &mode_info, &do_mode_oper);
2577 	} else {
2578 		PR_ERROR("Invalid number of arguments\n");
2579 		return -EINVAL;
2580 	}
2581 
2582 	if (do_mode_oper) {
2583 		/* Check interface index value. Mode validation must be performed by
2584 		 * lower layer
2585 		 */
2586 		if (mode_info.if_index == 0) {
2587 			iface = net_if_get_wifi_sta();
2588 			if (iface == NULL) {
2589 				PR_ERROR("Cannot find the default wifi interface\n");
2590 				return -ENOEXEC;
2591 			}
2592 			mode_info.if_index = net_if_get_by_iface(iface);
2593 		} else {
2594 			iface = net_if_get_by_index(mode_info.if_index);
2595 			if (iface == NULL) {
2596 				PR_ERROR("Cannot find interface for if_index %d\n",
2597 					 mode_info.if_index);
2598 				return -ENOEXEC;
2599 			}
2600 		}
2601 
2602 		ret = net_mgmt(NET_REQUEST_WIFI_MODE, iface, &mode_info, sizeof(mode_info));
2603 
2604 		if (ret) {
2605 			PR_ERROR("mode %s operation failed with reason %d\n",
2606 				 mode_info.oper == WIFI_MGMT_GET ? "get" : "set", ret);
2607 			return -ENOEXEC;
2608 		}
2609 
2610 		if (mode_info.oper == WIFI_MGMT_GET) {
2611 			PR("Wi-Fi current mode is %x\n", mode_info.mode);
2612 		} else {
2613 			PR("Wi-Fi mode set to %x\n", mode_info.mode);
2614 		}
2615 	}
2616 	return 0;
2617 }
2618 
parse_channel_args_to_params(const struct shell * sh,int argc,char * argv[],struct wifi_channel_info * channel,bool * do_channel_oper)2619 void parse_channel_args_to_params(const struct shell *sh, int argc,
2620 				  char *argv[], struct wifi_channel_info *channel,
2621 				  bool *do_channel_oper)
2622 {
2623 	int opt;
2624 	int opt_index = 0;
2625 	struct getopt_state *state;
2626 	static const struct option long_options[] = {
2627 		{"if-index", optional_argument, 0, 'i'},
2628 		{"channel", required_argument, 0, 'c'},
2629 		{"get", no_argument, 0, 'g'},
2630 		{"help", no_argument, 0, 'h'},
2631 		{0, 0, 0, 0}};
2632 
2633 	while ((opt = getopt_long(argc, argv, "i:c:gh",
2634 				  long_options, &opt_index)) != -1) {
2635 		state = getopt_state_get();
2636 		switch (opt) {
2637 		case 'c':
2638 			channel->channel = (uint16_t)atoi(state->optarg);
2639 			break;
2640 		case 'i':
2641 			channel->if_index = (uint8_t)atoi(state->optarg);
2642 			break;
2643 		case 'g':
2644 			channel->oper = WIFI_MGMT_GET;
2645 			break;
2646 		case 'h':
2647 			shell_help(sh);
2648 			*do_channel_oper = false;
2649 			break;
2650 		case '?':
2651 		default:
2652 			break;
2653 		}
2654 	}
2655 }
2656 
cmd_wifi_channel(const struct shell * sh,size_t argc,char * argv[])2657 static int cmd_wifi_channel(const struct shell *sh, size_t argc, char *argv[])
2658 {
2659 	struct net_if *iface;
2660 	struct wifi_channel_info channel_info = {0};
2661 	int ret;
2662 	bool do_channel_oper = true;
2663 
2664 	channel_info.oper = WIFI_MGMT_SET;
2665 	parse_channel_args_to_params(sh, argc, argv, &channel_info, &do_channel_oper);
2666 
2667 	if (do_channel_oper) {
2668 		/*
2669 		 * Validate parameters before sending to lower layer.
2670 		 * Do it here instead of parse_channel_args_to_params
2671 		 * as this is right before sending the parameters to
2672 		 * the lower layer.
2673 		 */
2674 
2675 		if (channel_info.if_index == 0) {
2676 			iface = net_if_get_wifi_sta();
2677 			if (iface == NULL) {
2678 				PR_ERROR("Cannot find the default wifi interface\n");
2679 				return -ENOEXEC;
2680 			}
2681 			channel_info.if_index = net_if_get_by_iface(iface);
2682 		} else {
2683 			iface = net_if_get_by_index(channel_info.if_index);
2684 			if (iface == NULL) {
2685 				PR_ERROR("Cannot find interface for if_index %d\n",
2686 					 channel_info.if_index);
2687 				return -ENOEXEC;
2688 			}
2689 		}
2690 
2691 		if (channel_info.oper == WIFI_MGMT_SET) {
2692 			if ((channel_info.channel < WIFI_CHANNEL_MIN) ||
2693 			    (channel_info.channel > WIFI_CHANNEL_MAX)) {
2694 				PR_ERROR("Invalid channel number. Range is (1-233)\n");
2695 				return -ENOEXEC;
2696 			}
2697 		}
2698 
2699 		ret = net_mgmt(NET_REQUEST_WIFI_CHANNEL, iface, &channel_info,
2700 			       sizeof(channel_info));
2701 
2702 		if (ret) {
2703 			PR_ERROR("channel %s operation failed with reason %d\n",
2704 				 channel_info.oper == WIFI_MGMT_GET ? "get" : "set", ret);
2705 			return -ENOEXEC;
2706 		}
2707 
2708 		if (channel_info.oper == WIFI_MGMT_GET) {
2709 			PR("Wi-Fi current channel is: %d\n", channel_info.channel);
2710 		} else {
2711 			PR("Wi-Fi channel set to %d\n", channel_info.channel);
2712 		}
2713 	}
2714 	return 0;
2715 }
2716 
parse_filter_args_to_params(const struct shell * sh,int argc,char * argv[],struct wifi_filter_info * filter,bool * do_filter_oper)2717 void parse_filter_args_to_params(const struct shell *sh, int argc,
2718 				 char *argv[], struct wifi_filter_info *filter,
2719 				 bool *do_filter_oper)
2720 {
2721 	int opt;
2722 	int opt_index = 0;
2723 	struct getopt_state *state;
2724 	static const struct option long_options[] = {
2725 		{"if-index", optional_argument, 0, 'i'},
2726 		{"capture-len", optional_argument, 0, 'b'},
2727 		{"all", no_argument, 0, 'a'},
2728 		{"mgmt", no_argument, 0, 'm'},
2729 		{"ctrl", no_argument, 0, 'c'},
2730 		{"data", no_argument, 0, 'd'},
2731 		{"get", no_argument, 0, 'g'},
2732 		{"help", no_argument, 0, 'h'},
2733 		{0, 0, 0, 0}};
2734 
2735 	while ((opt = getopt_long(argc, argv, "i:b:amcdgh",
2736 				  long_options, &opt_index)) != -1) {
2737 		state = getopt_state_get();
2738 		switch (opt) {
2739 		case 'a':
2740 			filter->filter |= WIFI_PACKET_FILTER_ALL;
2741 			break;
2742 		case 'm':
2743 			filter->filter |= WIFI_PACKET_FILTER_MGMT;
2744 			break;
2745 		case 'c':
2746 			filter->filter |= WIFI_PACKET_FILTER_CTRL;
2747 			break;
2748 		case 'd':
2749 			filter->filter |= WIFI_PACKET_FILTER_DATA;
2750 			break;
2751 		case 'i':
2752 			filter->if_index = (uint8_t)atoi(state->optarg);
2753 			break;
2754 		case 'b':
2755 			filter->buffer_size = (uint16_t)atoi(state->optarg);
2756 			break;
2757 		case 'h':
2758 			shell_help(sh);
2759 			*do_filter_oper = false;
2760 			break;
2761 		case 'g':
2762 			filter->oper = WIFI_MGMT_GET;
2763 			break;
2764 		case '?':
2765 		default:
2766 			break;
2767 		}
2768 	}
2769 }
2770 
cmd_wifi_packet_filter(const struct shell * sh,size_t argc,char * argv[])2771 static int cmd_wifi_packet_filter(const struct shell *sh, size_t argc, char *argv[])
2772 {
2773 	struct net_if *iface;
2774 	struct wifi_filter_info packet_filter = {0};
2775 	int ret;
2776 	bool do_filter_oper = true;
2777 
2778 	packet_filter.oper = WIFI_MGMT_SET;
2779 	parse_filter_args_to_params(sh, argc, argv, &packet_filter, &do_filter_oper);
2780 
2781 	if (do_filter_oper) {
2782 		/*
2783 		 * Validate parameters before sending to lower layer.
2784 		 * Do it here instead of parse_filter_args_to_params
2785 		 * as this is right before sending the parameters to
2786 		 * the lower layer. filter and packet capture length
2787 		 * value to be verified by the lower layer.
2788 		 */
2789 		if (packet_filter.if_index == 0) {
2790 			iface = net_if_get_wifi_sta();
2791 			if (iface == NULL) {
2792 				PR_ERROR("Cannot find the default wifi interface\n");
2793 				return -ENOEXEC;
2794 			}
2795 			packet_filter.if_index = net_if_get_by_iface(iface);
2796 		} else {
2797 			iface = net_if_get_by_index(packet_filter.if_index);
2798 			if (iface == NULL) {
2799 				PR_ERROR("Cannot find interface for if_index %d\n",
2800 					 packet_filter.if_index);
2801 				return -ENOEXEC;
2802 			}
2803 		}
2804 
2805 		ret = net_mgmt(NET_REQUEST_WIFI_PACKET_FILTER, iface, &packet_filter,
2806 			       sizeof(packet_filter));
2807 
2808 		if (ret) {
2809 			PR_ERROR("Wi-Fi packet filter %s operation failed with reason %d\n",
2810 				 packet_filter.oper == WIFI_MGMT_GET ? "get" : "set", ret);
2811 			return -ENOEXEC;
2812 		}
2813 
2814 		if (packet_filter.oper == WIFI_MGMT_GET) {
2815 			PR("Wi-Fi current mode packet filter is %d\n",
2816 			   packet_filter.filter);
2817 		} else {
2818 			PR("Wi-Fi mode packet filter set to %d\n",
2819 			   packet_filter.filter);
2820 		}
2821 	}
2822 	return 0;
2823 }
2824 
cmd_wifi_version(const struct shell * sh,size_t argc,char * argv[])2825 static int cmd_wifi_version(const struct shell *sh, size_t argc, char *argv[])
2826 {
2827 	struct net_if *iface = net_if_get_wifi_sta();
2828 	struct wifi_version version = {0};
2829 
2830 	if (argc > 1) {
2831 		PR_WARNING("Invalid number of arguments\n");
2832 		return -ENOEXEC;
2833 	}
2834 
2835 	if (net_mgmt(NET_REQUEST_WIFI_VERSION, iface, &version, sizeof(version))) {
2836 		PR_WARNING("Failed to get Wi-Fi versions\n");
2837 		return -ENOEXEC;
2838 	}
2839 
2840 	PR("Wi-Fi Driver Version: %s\n", version.drv_version);
2841 	PR("Wi-Fi Firmware Version: %s\n", version.fw_version);
2842 
2843 	return 0;
2844 }
2845 
2846 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
parse_dpp_args_auth_init(const struct shell * sh,size_t argc,char * argv[],struct wifi_dpp_params * params)2847 static int parse_dpp_args_auth_init(const struct shell *sh, size_t argc, char *argv[],
2848 				    struct wifi_dpp_params *params)
2849 {
2850 	int opt;
2851 	int opt_index = 0;
2852 	struct getopt_state *state;
2853 	static const struct option long_options[] = {
2854 		{"peer", required_argument, 0, 'p'},
2855 		{"role", required_argument, 0, 'r'},
2856 		{"configurator", required_argument, 0, 'c'},
2857 		{"mode", required_argument, 0, 'm'},
2858 		{"ssid", required_argument, 0, 's'},
2859 		{0, 0, 0, 0}};
2860 	int ret = 0;
2861 
2862 	while ((opt = getopt_long(argc, argv, "p:r:c:m:s:",
2863 				  long_options, &opt_index)) != -1) {
2864 		state = getopt_state_get();
2865 		switch (opt) {
2866 		case 'p':
2867 			params->auth_init.peer = shell_strtol(state->optarg, 10, &ret);
2868 			break;
2869 		case 'r':
2870 			params->auth_init.role = shell_strtol(state->optarg, 10, &ret);
2871 			break;
2872 		case 'c':
2873 			params->auth_init.configurator = shell_strtol(state->optarg, 10, &ret);
2874 			break;
2875 		case 'm':
2876 			params->auth_init.conf = shell_strtol(state->optarg, 10, &ret);
2877 			break;
2878 		case 's':
2879 			strncpy(params->auth_init.ssid, state->optarg, WIFI_SSID_MAX_LEN);
2880 			break;
2881 		default:
2882 			PR_ERROR("Invalid option %c\n", state->optopt);
2883 			return -EINVAL;
2884 		}
2885 
2886 		if (ret) {
2887 			PR_ERROR("Invalid argument %d ret %d\n", opt_index, ret);
2888 			return -EINVAL;
2889 		}
2890 	}
2891 
2892 	return 0;
2893 }
2894 
parse_dpp_args_chirp(const struct shell * sh,size_t argc,char * argv[],struct wifi_dpp_params * params)2895 static int parse_dpp_args_chirp(const struct shell *sh, size_t argc, char *argv[],
2896 				struct wifi_dpp_params *params)
2897 {
2898 	int opt;
2899 	int opt_index = 0;
2900 	struct getopt_state *state;
2901 	static const struct option long_options[] = {
2902 		{"own", required_argument, 0, 'i'},
2903 		{"freq", required_argument, 0, 'f'},
2904 		{0, 0, 0, 0}};
2905 	int ret = 0;
2906 
2907 	while ((opt = getopt_long(argc, argv, "i:f:",
2908 				  long_options, &opt_index)) != -1) {
2909 		state = getopt_state_get();
2910 		switch (opt) {
2911 		case 'i':
2912 			params->chirp.id = shell_strtol(state->optarg, 10, &ret);
2913 			break;
2914 		case 'f':
2915 			params->chirp.freq = shell_strtol(state->optarg, 10, &ret);
2916 			break;
2917 		default:
2918 			PR_ERROR("Invalid option %c\n", state->optopt);
2919 			return -EINVAL;
2920 		}
2921 
2922 		if (ret) {
2923 			PR_ERROR("Invalid argument %d ret %d\n", opt_index, ret);
2924 			return -EINVAL;
2925 		}
2926 	}
2927 
2928 	return 0;
2929 }
2930 
parse_dpp_args_listen(const struct shell * sh,size_t argc,char * argv[],struct wifi_dpp_params * params)2931 static int parse_dpp_args_listen(const struct shell *sh, size_t argc, char *argv[],
2932 				 struct wifi_dpp_params *params)
2933 {
2934 	int opt;
2935 	int opt_index = 0;
2936 	struct getopt_state *state;
2937 	static const struct option long_options[] = {
2938 		{"role", required_argument, 0, 'r'},
2939 		{"freq", required_argument, 0, 'f'},
2940 		{0, 0, 0, 0}};
2941 	int ret = 0;
2942 
2943 	while ((opt = getopt_long(argc, argv, "r:f:",
2944 				  long_options, &opt_index)) != -1) {
2945 		state = getopt_state_get();
2946 		switch (opt) {
2947 		case 'r':
2948 			params->listen.role = shell_strtol(state->optarg, 10, &ret);
2949 			break;
2950 		case 'f':
2951 			params->listen.freq = shell_strtol(state->optarg, 10, &ret);
2952 			break;
2953 		default:
2954 			PR_ERROR("Invalid option %c\n", state->optopt);
2955 			return -EINVAL;
2956 		}
2957 
2958 		if (ret) {
2959 			PR_ERROR("Invalid argument %d ret %d\n", opt_index, ret);
2960 			return -EINVAL;
2961 		}
2962 	}
2963 
2964 	return 0;
2965 }
2966 
parse_dpp_args_btstrap_gen(const struct shell * sh,size_t argc,char * argv[],struct wifi_dpp_params * params)2967 static int parse_dpp_args_btstrap_gen(const struct shell *sh, size_t argc, char *argv[],
2968 				      struct wifi_dpp_params *params)
2969 {
2970 	int opt;
2971 	int opt_index = 0;
2972 	struct getopt_state *state;
2973 	static const struct option long_options[] = {
2974 		{"type", required_argument, 0, 't'},
2975 		{"opclass", required_argument, 0, 'o'},
2976 		{"channel", required_argument, 0, 'h'},
2977 		{"mac", required_argument, 0, 'a'},
2978 		{0, 0, 0, 0}};
2979 	int ret = 0;
2980 
2981 	while ((opt = getopt_long(argc, argv, "t:o:h:a:",
2982 				  long_options, &opt_index)) != -1) {
2983 		state = getopt_state_get();
2984 		switch (opt) {
2985 		case 't':
2986 			params->bootstrap_gen.type = shell_strtol(state->optarg, 10, &ret);
2987 			break;
2988 		case 'o':
2989 			params->bootstrap_gen.op_class = shell_strtol(state->optarg, 10, &ret);
2990 			break;
2991 		case 'h':
2992 			params->bootstrap_gen.chan = shell_strtol(state->optarg, 10, &ret);
2993 			break;
2994 		case 'a':
2995 			ret = net_bytes_from_str(params->bootstrap_gen.mac,
2996 						 WIFI_MAC_ADDR_LEN, state->optarg);
2997 			break;
2998 		default:
2999 			PR_ERROR("Invalid option %c\n", state->optopt);
3000 			return -EINVAL;
3001 		}
3002 
3003 		if (ret) {
3004 			PR_ERROR("Invalid argument %d ret %d\n", opt_index, ret);
3005 			return -EINVAL;
3006 		}
3007 	}
3008 
3009 	/* DPP bootstrap type currently only support qr_code */
3010 	if (params->bootstrap_gen.type == 0) {
3011 		params->bootstrap_gen.type = WIFI_DPP_BOOTSTRAP_TYPE_QRCODE;
3012 	}
3013 
3014 	if (params->bootstrap_gen.type != WIFI_DPP_BOOTSTRAP_TYPE_QRCODE) {
3015 		PR_ERROR("DPP bootstrap type currently only support qr_code\n");
3016 		return -ENOTSUP;
3017 	}
3018 
3019 	/* operating class should be set alongside with channel */
3020 	if ((params->bootstrap_gen.op_class && !params->bootstrap_gen.chan) ||
3021 	    (!params->bootstrap_gen.op_class && params->bootstrap_gen.chan)) {
3022 		PR_ERROR("Operating class should be set alongside with channel\n");
3023 		return -EINVAL;
3024 	}
3025 
3026 	return 0;
3027 }
3028 
parse_dpp_args_set_config_param(const struct shell * sh,size_t argc,char * argv[],struct wifi_dpp_params * params)3029 static int parse_dpp_args_set_config_param(const struct shell *sh, size_t argc, char *argv[],
3030 					   struct wifi_dpp_params *params)
3031 {
3032 	int opt;
3033 	int opt_index = 0;
3034 	struct getopt_state *state;
3035 	static const struct option long_options[] = {
3036 		{"configurator", required_argument, 0, 'c'},
3037 		{"mode", required_argument, 0, 'm'},
3038 		{"ssid", required_argument, 0, 's'},
3039 		{0, 0, 0, 0}};
3040 	int ret = 0;
3041 
3042 	while ((opt = getopt_long(argc, argv, "p:r:c:m:s:",
3043 				  long_options, &opt_index)) != -1) {
3044 		state = getopt_state_get();
3045 		switch (opt) {
3046 		case 'c':
3047 			params->configurator_set.configurator =
3048 				shell_strtol(state->optarg, 10, &ret);
3049 			break;
3050 		case 'm':
3051 			params->configurator_set.conf = shell_strtol(state->optarg, 10, &ret);
3052 			break;
3053 		case 's':
3054 			strncpy(params->configurator_set.ssid, state->optarg, WIFI_SSID_MAX_LEN);
3055 			break;
3056 		default:
3057 			PR_ERROR("Invalid option %c\n", state->optopt);
3058 			return -EINVAL;
3059 		}
3060 
3061 		if (ret) {
3062 			PR_ERROR("Invalid argument %d ret %d\n", opt_index, ret);
3063 			return -EINVAL;
3064 		}
3065 	}
3066 
3067 	return 0;
3068 }
3069 
cmd_wifi_dpp_configurator_add(const struct shell * sh,size_t argc,char * argv[])3070 static int cmd_wifi_dpp_configurator_add(const struct shell *sh, size_t argc, char *argv[])
3071 {
3072 	struct net_if *iface = net_if_get_wifi_sta();
3073 	struct wifi_dpp_params params = {0};
3074 
3075 	params.action = WIFI_DPP_CONFIGURATOR_ADD;
3076 
3077 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3078 		PR_WARNING("Failed to request DPP action\n");
3079 		return -ENOEXEC;
3080 	}
3081 	return 0;
3082 }
3083 
cmd_wifi_dpp_auth_init(const struct shell * sh,size_t argc,char * argv[])3084 static int cmd_wifi_dpp_auth_init(const struct shell *sh, size_t argc, char *argv[])
3085 {
3086 	int ret;
3087 	struct net_if *iface = net_if_get_wifi_sta();
3088 	struct wifi_dpp_params params = {0};
3089 
3090 	params.action = WIFI_DPP_AUTH_INIT;
3091 
3092 	ret = parse_dpp_args_auth_init(sh, argc, argv, &params);
3093 	if (ret) {
3094 		PR_ERROR("parse DPP args fail\n");
3095 		return -EINVAL;
3096 	}
3097 
3098 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3099 		PR_WARNING("Failed to request DPP action\n");
3100 		return -ENOEXEC;
3101 	}
3102 	return 0;
3103 }
3104 
cmd_wifi_dpp_qr_code(const struct shell * sh,size_t argc,char * argv[])3105 static int cmd_wifi_dpp_qr_code(const struct shell *sh, size_t argc, char *argv[])
3106 {
3107 	struct net_if *iface = net_if_get_wifi_sta();
3108 	struct wifi_dpp_params params = {0};
3109 
3110 	params.action = WIFI_DPP_QR_CODE;
3111 
3112 	if (argc >= 2) {
3113 		strncpy(params.dpp_qr_code, argv[1], WIFI_DPP_QRCODE_MAX_LEN);
3114 	}
3115 
3116 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3117 		PR_WARNING("Failed to request DPP action\n");
3118 		return -ENOEXEC;
3119 	}
3120 	return 0;
3121 }
3122 
cmd_wifi_dpp_chirp(const struct shell * sh,size_t argc,char * argv[])3123 static int cmd_wifi_dpp_chirp(const struct shell *sh, size_t argc, char *argv[])
3124 {
3125 	int ret;
3126 	struct net_if *iface = net_if_get_wifi_sta();
3127 	struct wifi_dpp_params params = {0};
3128 
3129 	params.action = WIFI_DPP_CHIRP;
3130 
3131 	ret = parse_dpp_args_chirp(sh, argc, argv, &params);
3132 	if (ret) {
3133 		PR_ERROR("parse DPP args fail\n");
3134 		return -EINVAL;
3135 	}
3136 
3137 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3138 		PR_WARNING("Failed to request DPP action\n");
3139 		return -ENOEXEC;
3140 	}
3141 	return 0;
3142 }
3143 
cmd_wifi_dpp_listen(const struct shell * sh,size_t argc,char * argv[])3144 static int cmd_wifi_dpp_listen(const struct shell *sh, size_t argc, char *argv[])
3145 {
3146 	int ret;
3147 	struct net_if *iface = net_if_get_wifi_sta();
3148 	struct wifi_dpp_params params = {0};
3149 
3150 	params.action = WIFI_DPP_LISTEN;
3151 
3152 	ret = parse_dpp_args_listen(sh, argc, argv, &params);
3153 	if (ret) {
3154 		PR_ERROR("parse DPP args fail\n");
3155 		return -EINVAL;
3156 	}
3157 
3158 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3159 		PR_WARNING("Failed to request DPP action\n");
3160 		return -ENOEXEC;
3161 	}
3162 	return 0;
3163 }
3164 
cmd_wifi_dpp_btstrap_gen(const struct shell * sh,size_t argc,char * argv[])3165 static int cmd_wifi_dpp_btstrap_gen(const struct shell *sh, size_t argc, char *argv[])
3166 {
3167 	int ret;
3168 	struct net_if *iface = net_if_get_wifi_sta();
3169 	struct wifi_dpp_params params = {0};
3170 
3171 	params.action = WIFI_DPP_BOOTSTRAP_GEN;
3172 
3173 	ret = parse_dpp_args_btstrap_gen(sh, argc, argv, &params);
3174 	if (ret) {
3175 		PR_ERROR("parse DPP args fail\n");
3176 		return -EINVAL;
3177 	}
3178 
3179 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3180 		PR_WARNING("Failed to request DPP action\n");
3181 		return -ENOEXEC;
3182 	}
3183 	return 0;
3184 }
3185 
cmd_wifi_dpp_btstrap_get_uri(const struct shell * sh,size_t argc,char * argv[])3186 static int cmd_wifi_dpp_btstrap_get_uri(const struct shell *sh, size_t argc, char *argv[])
3187 {
3188 	int ret = 0;
3189 	struct net_if *iface = net_if_get_wifi_sta();
3190 	struct wifi_dpp_params params = {0};
3191 
3192 	params.action = WIFI_DPP_BOOTSTRAP_GET_URI;
3193 
3194 	if (argc >= 2) {
3195 		params.id = shell_strtol(argv[1], 10, &ret);
3196 	}
3197 
3198 	if (ret) {
3199 		PR_ERROR("parse DPP args fail\n");
3200 		return -EINVAL;
3201 	}
3202 
3203 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3204 		PR_WARNING("Failed to request DPP action\n");
3205 		return -ENOEXEC;
3206 	}
3207 	return 0;
3208 }
3209 
cmd_wifi_dpp_configurator_set(const struct shell * sh,size_t argc,char * argv[])3210 static int cmd_wifi_dpp_configurator_set(const struct shell *sh, size_t argc, char *argv[])
3211 {
3212 	int ret;
3213 	struct net_if *iface = net_if_get_wifi_sta();
3214 	struct wifi_dpp_params params = {0};
3215 
3216 	params.action = WIFI_DPP_SET_CONF_PARAM;
3217 
3218 	ret = parse_dpp_args_set_config_param(sh, argc, argv, &params);
3219 	if (ret) {
3220 		PR_ERROR("parse DPP args fail\n");
3221 		return -EINVAL;
3222 	}
3223 
3224 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3225 		PR_WARNING("Failed to request DPP action\n");
3226 		return -ENOEXEC;
3227 	}
3228 	return 0;
3229 }
3230 
cmd_wifi_dpp_resp_timeout_set(const struct shell * sh,size_t argc,char * argv[])3231 static int cmd_wifi_dpp_resp_timeout_set(const struct shell *sh, size_t argc, char *argv[])
3232 {
3233 	int ret = 0;
3234 	struct net_if *iface = net_if_get_wifi_sta();
3235 	struct wifi_dpp_params params = {0};
3236 
3237 	params.action = WIFI_DPP_SET_WAIT_RESP_TIME;
3238 
3239 	if (argc >= 2) {
3240 		params.dpp_resp_wait_time = shell_strtol(argv[1], 10, &ret);
3241 	}
3242 
3243 	if (ret) {
3244 		PR_ERROR("parse DPP args fail");
3245 		return -EINVAL;
3246 	}
3247 
3248 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3249 		PR_WARNING("Failed to request DPP action\n");
3250 		return -ENOEXEC;
3251 	}
3252 	return 0;
3253 }
3254 
cmd_wifi_dpp_ap_btstrap_gen(const struct shell * sh,size_t argc,char * argv[])3255 static int cmd_wifi_dpp_ap_btstrap_gen(const struct shell *sh, size_t argc, char *argv[])
3256 {
3257 	int ret;
3258 	struct net_if *iface = net_if_get_wifi_sap();
3259 	struct wifi_dpp_params params = {0};
3260 
3261 	params.action = WIFI_DPP_BOOTSTRAP_GEN;
3262 
3263 	ret = parse_dpp_args_btstrap_gen(sh, argc, argv, &params);
3264 	if (ret) {
3265 		PR_ERROR("parse DPP args fail\n");
3266 		return -EINVAL;
3267 	}
3268 
3269 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3270 		PR_WARNING("Failed to request DPP action\n");
3271 		return -ENOEXEC;
3272 	}
3273 	return 0;
3274 }
3275 
cmd_wifi_dpp_ap_btstrap_get_uri(const struct shell * sh,size_t argc,char * argv[])3276 static int cmd_wifi_dpp_ap_btstrap_get_uri(const struct shell *sh, size_t argc, char *argv[])
3277 {
3278 	int ret = 0;
3279 	struct net_if *iface = net_if_get_wifi_sap();
3280 	struct wifi_dpp_params params = {0};
3281 
3282 	params.action = WIFI_DPP_BOOTSTRAP_GET_URI;
3283 
3284 	if (argc >= 2) {
3285 		params.id = shell_strtol(argv[1], 10, &ret);
3286 	}
3287 
3288 	if (ret) {
3289 		PR_ERROR("parse DPP args fail\n");
3290 		return -EINVAL;
3291 	}
3292 
3293 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3294 		PR_WARNING("Failed to request DPP action\n");
3295 		return -ENOEXEC;
3296 	}
3297 	return 0;
3298 }
3299 
cmd_wifi_dpp_ap_qr_code(const struct shell * sh,size_t argc,char * argv[])3300 static int cmd_wifi_dpp_ap_qr_code(const struct shell *sh, size_t argc, char *argv[])
3301 {
3302 	struct net_if *iface = net_if_get_wifi_sap();
3303 	struct wifi_dpp_params params = {0};
3304 
3305 	params.action = WIFI_DPP_QR_CODE;
3306 
3307 	if (argc >= 2) {
3308 		strncpy(params.dpp_qr_code, argv[1], WIFI_DPP_QRCODE_MAX_LEN);
3309 	}
3310 
3311 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3312 		PR_WARNING("Failed to request DPP action\n");
3313 		return -ENOEXEC;
3314 	}
3315 	return 0;
3316 }
3317 
cmd_wifi_dpp_ap_auth_init(const struct shell * sh,size_t argc,char * argv[])3318 static int cmd_wifi_dpp_ap_auth_init(const struct shell *sh, size_t argc, char *argv[])
3319 {
3320 	int opt;
3321 	int opt_index = 0;
3322 	struct getopt_state *state;
3323 	static const struct option long_options[] = {
3324 		{"peer", required_argument, 0, 'p'},
3325 		{0, 0, 0, 0}};
3326 	int ret = 0;
3327 	struct net_if *iface = net_if_get_wifi_sap();
3328 	struct wifi_dpp_params params = {0};
3329 
3330 	params.action = WIFI_DPP_AUTH_INIT;
3331 
3332 	while ((opt = getopt_long(argc, argv, "p:",
3333 				  long_options, &opt_index)) != -1) {
3334 		state = getopt_state_get();
3335 		switch (opt) {
3336 		case 'p':
3337 			params.auth_init.peer = shell_strtol(state->optarg, 10, &ret);
3338 			break;
3339 		default:
3340 			PR_ERROR("Invalid option %c\n", state->optopt);
3341 			return -EINVAL;
3342 		}
3343 
3344 		if (ret) {
3345 			PR_ERROR("Invalid argument %d ret %d\n", opt_index, ret);
3346 			return -EINVAL;
3347 		}
3348 	}
3349 
3350 	/* AP DPP auth only act as enrollee */
3351 	params.auth_init.role = WIFI_DPP_ROLE_ENROLLEE;
3352 
3353 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3354 		PR_WARNING("Failed to request DPP action\n");
3355 		return -ENOEXEC;
3356 	}
3357 	return 0;
3358 }
3359 
cmd_wifi_dpp_reconfig(const struct shell * sh,size_t argc,char * argv[])3360 static int cmd_wifi_dpp_reconfig(const struct shell *sh, size_t argc, char *argv[])
3361 {
3362 	int ret = 0;
3363 	struct net_if *iface = net_if_get_wifi_sta();
3364 	struct wifi_dpp_params params = {0};
3365 
3366 	params.action = WIFI_DPP_RECONFIG;
3367 
3368 	if (argc >= 2) {
3369 		params.network_id = shell_strtol(argv[1], 10, &ret);
3370 	}
3371 
3372 	if (ret) {
3373 		PR_ERROR("parse DPP args fail\n");
3374 		return -EINVAL;
3375 	}
3376 
3377 	if (net_mgmt(NET_REQUEST_WIFI_DPP, iface, &params, sizeof(params))) {
3378 		PR_WARNING("Failed to request DPP action\n");
3379 		return -ENOEXEC;
3380 	}
3381 	return 0;
3382 }
3383 
3384 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
cmd_wifi_pmksa_flush(const struct shell * sh,size_t argc,char * argv[])3385 static int cmd_wifi_pmksa_flush(const struct shell *sh, size_t argc, char *argv[])
3386 {
3387 	struct net_if *iface = net_if_get_wifi_sta();
3388 
3389 	context.sh = sh;
3390 
3391 	if (net_mgmt(NET_REQUEST_WIFI_PMKSA_FLUSH, iface, NULL, 0)) {
3392 		PR_WARNING("Flush PMKSA cache entries failed\n");
3393 		return -ENOEXEC;
3394 	}
3395 
3396 	return 0;
3397 }
3398 
3399 SHELL_STATIC_SUBCMD_SET_CREATE(
3400 	wifi_cmd_ap,
3401 	SHELL_CMD_ARG(disable, NULL, "Disable Access Point mode.\n", cmd_wifi_ap_disable, 1, 0),
3402 	SHELL_CMD_ARG(enable, NULL,
3403 		      "-s --ssid=<SSID>\n"
3404 		      "-c --channel=<channel number>\n"
3405 		      "-p --passphrase=<PSK> (valid only for secure SSIDs)\n"
3406 		      "-k --key-mgmt=<Security type> (valid only for secure SSIDs)\n"
3407 		      "0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE-HNP, 4:SAE-H2E, 5:SAE-AUTO, 6:WAPI,"
3408 		      "7:EAP-TLS, 8:WEP, 9: WPA-PSK, 10: WPA-Auto-Personal, 11: DPP\n"
3409 		      "12: EAP-PEAP-MSCHAPv2, 13: EAP-PEAP-GTC, 14: EAP-TTLS-MSCHAPv2,\n"
3410 		      "15: EAP-PEAP-TLS, 16:EAP_TLS_SHA256\n"
3411 		      "-w --ieee-80211w=<MFP> (optional: needs security type to be specified)\n"
3412 		      "0:Disable, 1:Optional, 2:Required\n"
3413 		      "-b --band=<band> (2 -2.6GHz, 5 - 5Ghz, 6 - 6GHz)\n"
3414 		      "-m --bssid=<BSSID>\n"
3415 		      "-i --ignore-broadcast-ssid=<type>. Hide SSID in AP mode.\n"
3416 		      "0: disabled (default)\n"
3417 		      "1: send empty (length=0) SSID in beacon and ignore probe request for "
3418 		      "broadcast SSID.\n"
3419 		      "2: clear SSID (ASCII 0), but keep the original length and ignore "
3420 		      "probe requests for broadcast SSID.\n"
3421 		      "[-B, --bandwidth=<bandwidth>]: 1:20MHz, 2:40MHz, 3:80MHz\n"
3422 		      "[-K, --key1-pwd for eap phase1 or --key2-pwd for eap phase2]:\n"
3423 		      "Private key passwd for enterprise mode. Default no password for private key.\n"
3424 		      "[-S, --suiteb-type]: 1:suiteb, 2:suiteb-192. Default 0: not suiteb mode.\n"
3425 		      "[-V, --eap-version]: 0 or 1. Default 1: eap version 1.\n"
3426 		      "[-I, --eap-id1...--eap-id8]: Client Identity. Default no eap identity.\n"
3427 		      "[-P, --eap-pwd1...--eap-pwd8]: Client Password.\n"
3428 		      "Default no password for eap user.\n"
3429 		      "-h --help (prints help)",
3430 		      cmd_wifi_ap_enable, 2, 45),
3431 	SHELL_CMD_ARG(stations, NULL, "List stations connected to the AP", cmd_wifi_ap_stations, 1,
3432 		      0),
3433 	SHELL_CMD_ARG(disconnect, NULL,
3434 		      "Disconnect a station from the AP\n"
3435 		      "<MAC address of the station>\n",
3436 		      cmd_wifi_ap_sta_disconnect, 2, 0),
3437 	SHELL_CMD_ARG(config, NULL,
3438 		      "Configure AP parameters.\n"
3439 		      "-i --max_inactivity=<time duration (in seconds)>\n"
3440 		      "-s --max_num_sta=<maximum number of stations>\n"
3441 #if defined(CONFIG_WIFI_NM_HOSTAPD_AP)
3442 		      "Please refer to hostapd.conf to set the following options,\n"
3443 		      "============ IEEE 802.11 related configuration ============\n"
3444 		      "-n --ht_capab=<HT capabilities (string)>\n"
3445 		      "(e.g. \"ht_capab=[HT40+]\" is that \"-n [HT40+]\")\n"
3446 		      "-c --vht_capab=<VHT capabilities (string)>\n"
3447 		      "(e.g. \"vht_capab=[SU-BEAMFORMEE][BF-ANTENNA-4]\" is that\n"
3448 		      "\"-c [SU-BEAMFORMEE][BF-ANTENNA-4]\")\n"
3449 		      "===========================================================\n"
3450 #endif
3451 		      "-h --help (prints help)",
3452 		      cmd_wifi_ap_config_params, 2, 10),
3453 	SHELL_CMD_ARG(wps_pbc, NULL,
3454 		      "Start AP WPS PBC session.\n",
3455 		      cmd_wifi_ap_wps_pbc, 1, 0),
3456 	SHELL_CMD_ARG(wps_pin, NULL,
3457 		      "Get or Set AP WPS PIN.\n"
3458 		      "[pin] Only applicable for set.\n",
3459 		      cmd_wifi_ap_wps_pin, 1, 1),
3460 	SHELL_CMD_ARG(status, NULL, "Status of Wi-Fi SAP\n", cmd_wifi_ap_status, 1, 0),
3461 	SHELL_CMD_ARG(rts_threshold,
3462 		  NULL,
3463 		  "<rts_threshold: rts threshold/off>.\n",
3464 		  cmd_wifi_ap_set_rts_threshold,
3465 		  2,
3466 		  0),
3467 	SHELL_SUBCMD_SET_END);
3468 
3469 SHELL_SUBCMD_ADD((wifi), ap, &wifi_cmd_ap,
3470 		 "Access Point mode commands.",
3471 		 NULL,
3472 		 0, 0);
3473 
3474 SHELL_STATIC_SUBCMD_SET_CREATE(wifi_twt_ops,
3475 	SHELL_CMD_ARG(quick_setup, NULL, " Start a TWT flow with defaults:\n"
3476 		"<twt_wake_interval: 1-262144us> <twt_interval: 1us-2^31us>.\n",
3477 		cmd_wifi_twt_setup_quick,
3478 		3, 0),
3479 	SHELL_CMD_ARG(setup, NULL, " Start a TWT flow:\n"
3480 		"<-n --negotiation-type>: 0: Individual, 1: Broadcast, 2: Wake TBTT\n"
3481 		"<-c --setup-cmd>: 0: Request, 1: Suggest, 2: Demand\n"
3482 		"<-t --dialog-token>: 1-255\n"
3483 		"<-f --flow-id>: 0-7\n"
3484 		"<-r --responder>: 0/1\n"
3485 		"<-T --trigger>: 0/1\n"
3486 		"<-I --implicit>:0/1\n"
3487 		"<-a --announce>: 0/1\n"
3488 		"<-w --wake-interval>: 1-262144us\n"
3489 		"<-i --interval>: 1us-2^31us\n"
3490 		"<-D --wake-ahead-duration>: 0us-2^31us\n"
3491 		"<-d --info-disable>: 0/1\n"
3492 		"<-e --exponent>: 0-31\n"
3493 		"<-m --mantissa>: 1-2^16\n"
3494 		"[-h, --help]: Print out command usage.\n",
3495 		cmd_wifi_twt_setup,
3496 		25, 5),
3497 	SHELL_CMD_ARG(
3498 		btwt_setup, NULL,
3499 		" Start a BTWT flow:\n"
3500 		"<sub_id: Broadcast TWT AP config> <nominal_wake: 64-255> <max_sta_support>"
3501 		"<twt_mantissa:0-sizeof(UINT16)> <twt_offset> <twt_exponent: 0-31> <sp_gap>.\n",
3502 		cmd_wifi_btwt_setup,
3503 		8, 0),
3504 	SHELL_CMD_ARG(teardown, NULL, " Teardown a TWT flow:\n"
3505 		"<negotiation_type, 0: Individual, 1: Broadcast, 2: Wake TBTT>\n"
3506 		"<setup_cmd: 0: Request, 1: Suggest, 2: Demand>\n"
3507 		"<dialog_token: 1-255> <flow_id: 0-7>.\n",
3508 		cmd_wifi_twt_teardown,
3509 		5, 0),
3510 	SHELL_CMD_ARG(teardown_all, NULL, " Teardown all TWT flows.\n",
3511 		cmd_wifi_twt_teardown_all,
3512 		1, 0),
3513 	SHELL_SUBCMD_SET_END
3514 );
3515 
3516 SHELL_SUBCMD_ADD((wifi), twt, &wifi_twt_ops,
3517 		 "Manage TWT flows.",
3518 		 NULL,
3519 		 0, 0);
3520 
3521 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP
3522 SHELL_STATIC_SUBCMD_SET_CREATE(
3523 	wifi_cmd_dpp,
3524 	SHELL_CMD_ARG(configurator_add, NULL,
3525 		      " Add DPP configurator\n",
3526 		      cmd_wifi_dpp_configurator_add, 1, 0),
3527 	SHELL_CMD_ARG(auth_init, NULL,
3528 		      "DPP start auth request:\n"
3529 		      "-p --peer <peer_bootstrap_id>\n"
3530 		      "[-r --role <1/2>]: DPP role default 1. 1: configurator, 2: enrollee\n"
3531 		      "Optional args for configurator:\n"
3532 		      "[-c --configurator <configurator_id>]\n"
3533 		      "[-m --mode <1/2>]: Peer mode. 1: STA, 2: AP\n"
3534 		      "[-s --ssid <SSID>]: SSID\n",
3535 		      cmd_wifi_dpp_auth_init, 3, 8),
3536 	SHELL_CMD_ARG(qr_code, NULL,
3537 		      " Input QR code:\n"
3538 		      "<qr_code_string>\n",
3539 		      cmd_wifi_dpp_qr_code, 2, 0),
3540 	SHELL_CMD_ARG(chirp, NULL,
3541 		      " DPP chirp:\n"
3542 		      "-i --own <own_bootstrap_id>\n"
3543 		      "-f --freq <listen_freq>\n",
3544 		      cmd_wifi_dpp_chirp, 5, 0),
3545 	SHELL_CMD_ARG(listen, NULL,
3546 		      " DPP listen:\n"
3547 		      "-f --freq <listen_freq>\n"
3548 		      "-r --role <1/2>: DPP role. 1: configurator, 2: enrollee\n",
3549 		      cmd_wifi_dpp_listen, 5, 0),
3550 	SHELL_CMD_ARG(btstrap_gen, NULL,
3551 		      " DPP bootstrap generate:\n"
3552 		      "[-t --type <1/2/3>]: Bootstrap type. 1: qr_code, 2: pkex, 3: nfc."
3553 		      " Currently only support qr_code\n"
3554 		      "[-o --opclass <operating_class>]\n"
3555 		      "[-h --channel <channel>]\n"
3556 		      "[-a --mac <mac_addr>]\n",
3557 		      cmd_wifi_dpp_btstrap_gen, 1, 8),
3558 	SHELL_CMD_ARG(btstrap_get_uri, NULL,
3559 		      " Get DPP bootstrap uri by id:\n"
3560 		      "<bootstrap_id>\n",
3561 		      cmd_wifi_dpp_btstrap_get_uri, 2, 0),
3562 	SHELL_CMD_ARG(configurator_set, NULL,
3563 		      " Set DPP configurator parameters:\n"
3564 		      "-c --configurator <configurator_id>\n"
3565 		      "[-m --mode <1/2>]: Peer mode. 1: STA, 2: AP\n"
3566 		      "[-s --ssid <SSID>]: SSID\n",
3567 		      cmd_wifi_dpp_configurator_set, 3, 4),
3568 	SHELL_CMD_ARG(resp_timeout_set, NULL,
3569 		      " Set DPP RX response wait timeout ms:\n"
3570 		      "<timeout_ms>\n",
3571 		      cmd_wifi_dpp_resp_timeout_set, 2, 0),
3572 	SHELL_CMD_ARG(ap_btstrap_gen, NULL,
3573 		      " AP DPP bootstrap generate:\n"
3574 		      "[-t --type <1/2/3>]: Bootstrap type. 1: qr_code, 2: pkex, 3: nfc."
3575 		      " Currently only support qr_code\n"
3576 		      "[-o --opclass <operating_class>]\n"
3577 		      "[-h --channel <channel>]\n"
3578 		      "[-a --mac <mac_addr>]\n",
3579 		      cmd_wifi_dpp_ap_btstrap_gen, 1, 8),
3580 	SHELL_CMD_ARG(ap_btstrap_get_uri, NULL,
3581 		      " AP get DPP bootstrap uri by id:\n"
3582 		      "<bootstrap_id>\n",
3583 		      cmd_wifi_dpp_ap_btstrap_get_uri, 2, 0),
3584 	SHELL_CMD_ARG(ap_qr_code, NULL,
3585 		      " AP Input QR code:\n"
3586 		      "<qr_code_string>\n",
3587 		      cmd_wifi_dpp_ap_qr_code, 2, 0),
3588 	SHELL_CMD_ARG(ap_auth_init, NULL,
3589 		      "AP DPP start auth request as enrollee:\n"
3590 		      "-p --peer <peer_bootstrap_id>\n",
3591 		      cmd_wifi_dpp_ap_auth_init, 3, 0),
3592 	SHELL_CMD_ARG(reconfig, NULL,
3593 		      " reconfig network by id:\n"
3594 		      "<network_id>\n",
3595 		      cmd_wifi_dpp_reconfig, 2, 0),
3596 	SHELL_SUBCMD_SET_END
3597 );
3598 
3599 SHELL_SUBCMD_ADD((wifi), dpp, &wifi_cmd_dpp,
3600 		 "DPP actions.",
3601 		 NULL,
3602 		 0, 0);
3603 #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP */
3604 
3605 SHELL_SUBCMD_SET_CREATE(wifi_commands, (wifi));
3606 
3607 SHELL_SUBCMD_ADD((wifi), 11k, NULL,
3608 		 "Configure 11k or get 11k status.\n"
3609 		 "[enable/disable]\n",
3610 		 cmd_wifi_11k,
3611 		 1, 1);
3612 
3613 SHELL_SUBCMD_ADD((wifi), 11k_neighbor_request, NULL,
3614 		 "Send Neighbor Report Request frame.\n"
3615 		 "[ssid <ssid>]\n",
3616 		 cmd_wifi_11k_neighbor_request,
3617 		 1, 2);
3618 
3619 #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
3620 SHELL_SUBCMD_ADD((wifi), 11v_btm_query, NULL,
3621 		 "<query_reason: The reason code for a BSS transition management query>.\n",
3622 		 cmd_wifi_btm_query,
3623 		 2, 0);
3624 #endif
3625 
3626 SHELL_SUBCMD_ADD((wifi), channel, NULL,
3627 		 "wifi channel setting\n"
3628 		 "This command is used to set the channel when\n"
3629 		 "monitor or TX-Injection mode is enabled\n"
3630 		 "Currently 20 MHz is only supported and no BW parameter is provided\n"
3631 		 "[-i, --if-index <idx>] : Interface index\n"
3632 		 "[-c, --channel <chan>] : Set a specific channel number to the lower layer\n"
3633 		 "[-g, --get] : Get current set channel number from the lower layer\n"
3634 		 "[-h, --help] : Help\n"
3635 		 "Usage: Get operation example for interface index 1\n"
3636 		 "wifi channel -g -i1\n"
3637 		 "Set operation example for interface index 1 (setting channel 5)\n"
3638 		 "wifi -i1 -c5.\n",
3639 		 cmd_wifi_channel,
3640 		 2, 4);
3641 
3642 SHELL_SUBCMD_ADD((wifi), connect, NULL,
3643 		  "Connect to a Wi-Fi AP\n"
3644 		  "<-s --ssid \"<SSID>\">: SSID.\n"
3645 		  "[-c --channel]: Channel that needs to be scanned for connection. "
3646 		 "0:any channel.\n"
3647 		  "[-b, --band] 0: any band (2:2.4GHz, 5:5GHz, 6:6GHz]\n"
3648 		  "[-p, --psk]: Passphrase (valid only for secure SSIDs)\n"
3649 		  "[-k, --key-mgmt]: Key Management type (valid only for secure SSIDs)\n"
3650 		  "0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE-HNP, 4:SAE-H2E, 5:SAE-AUTO, 6:WAPI,"
3651 		  "7:EAP-TLS, 8:WEP, 9: WPA-PSK, 10: WPA-Auto-Personal, 11: DPP\n"
3652 		  "12: EAP-PEAP-MSCHAPv2, 13: EAP-PEAP-GTC, 14: EAP-TTLS-MSCHAPv2,\n"
3653 		  "15: EAP-PEAP-TLS, 16:EAP_TLS_SHA256\n"
3654 		  "[-w, --ieee-80211w]: MFP (optional: needs security type to be specified)\n"
3655 		  ": 0:Disable, 1:Optional, 2:Required.\n"
3656 		  "[-m, --bssid]: MAC address of the AP (BSSID).\n"
3657 		  "[-t, --timeout]: Timeout for the connection attempt (in seconds).\n"
3658 		  "[-a, --anon-id]: Anonymous identity for enterprise mode.\n"
3659 		  "[-K, --key1-pwd for eap phase1 or --key2-pwd for eap phase2]:\n"
3660 		  "Private key passwd for enterprise mode. Default no password for private key.\n"
3661 		  "[-S, --suiteb-type]: 1:suiteb, 2:suiteb-192. Default 0: not suiteb mode.\n"
3662 		  "[-T, --TLS-cipher]: 0:TLS-NONE, 1:TLS-ECC-P384, 2:TLS-RSA-3K.\n"
3663 		  "[-V, --eap-version]: 0 or 1. Default 1: eap version 1.\n"
3664 		  "[-I, --eap-id1]: Client Identity. Default no eap identity.\n"
3665 		  "[-P, --eap-pwd1]: Client Password.\n"
3666 		  "Default no password for eap user.\n"
3667 		  "[-R, --ieee-80211r]: Use IEEE80211R fast BSS transition connect."
3668 		  "[-h, --help]: Print out the help for the connect command.\n",
3669 		  cmd_wifi_connect,
3670 		 2, 19);
3671 
3672 SHELL_SUBCMD_ADD((wifi), disconnect, NULL,
3673 		 "Disconnect from the Wi-Fi AP.\n",
3674 		 cmd_wifi_disconnect,
3675 		 1, 0);
3676 
3677 SHELL_SUBCMD_ADD((wifi), mode, NULL,
3678 		 "mode operational setting\n"
3679 		 "This command may be used to set the Wi-Fi device into a specific "
3680 		 "mode of operation\n"
3681 		 "[-i, --if-index <idx>] : Interface index\n"
3682 		 "[-s, --sta] : Station mode\n"
3683 		 "[-m, --monitor] : Monitor mode\n"
3684 		 "[-a, --ap] : AP mode\n"
3685 		 "[-k, --softap] : Softap mode\n"
3686 		 "[-h, --help] : Help\n"
3687 		 "[-g, --get] : Get current mode for a specific interface index\n"
3688 		 "Usage: Get operation example for interface index 1\n"
3689 		 "wifi mode -g -i1\n"
3690 		 "Set operation example for interface index 1 - set station+promiscuous\n"
3691 		 "wifi mode -i1 -sp.\n",
3692 		 cmd_wifi_mode,
3693 		 1, 9);
3694 
3695 SHELL_SUBCMD_ADD((wifi), packet_filter, NULL,
3696 		 "mode filter setting\n"
3697 		 "This command is used to set packet filter setting when\n"
3698 		 "monitor, TX-Injection and promiscuous mode is enabled\n"
3699 		 "The different packet filter modes are control, management, "
3700 		 "data and enable all filters\n"
3701 		 "[-i, --if-index <idx>] : Interface index\n"
3702 		 "[-a, --all] : Enable all packet filter modes\n"
3703 		 "[-m, --mgmt] : Enable management packets to allowed up the stack\n"
3704 		 "[-c, --ctrl] : Enable control packets to be allowed up the stack\n"
3705 		 "[-d, --data] : Enable Data packets to be allowed up the stack\n"
3706 		 "[-g, --get] : Get current filter settings for a specific interface index\n"
3707 		 "[-b, --capture-len <len>] : Capture length buffer size for each packet "
3708 		 "to be captured\n"
3709 		 "[-h, --help] : Help\n"
3710 		 "Usage: Get operation example for interface index 1\n"
3711 		 "wifi packet_filter -g -i1\n"
3712 		 "Set operation example for interface index 1 - set data+management frame filter\n"
3713 		 "wifi packet_filter -i1 -md.\n",
3714 		 cmd_wifi_packet_filter,
3715 		 2, 8);
3716 
3717 SHELL_SUBCMD_ADD((wifi), pmksa_flush, NULL,
3718 		 "Flush PMKSA cache entries.\n",
3719 		 cmd_wifi_pmksa_flush,
3720 		 1, 0);
3721 
3722 SHELL_SUBCMD_ADD((wifi), ps, NULL,
3723 		 "Configure or display Wi-Fi power save state.\n[on/off]\n",
3724 		 cmd_wifi_ps,
3725 		 1, 1);
3726 
3727 SHELL_SUBCMD_ADD((wifi), ps_listen_interval, NULL,
3728 		 "<val> - Listen interval in the range of <0-65535>.\n",
3729 		 cmd_wifi_listen_interval,
3730 		 2, 0);
3731 
3732 SHELL_SUBCMD_ADD((wifi), ps_mode, NULL,
3733 		 "<mode: legacy/WMM>.\n",
3734 		 cmd_wifi_ps_mode,
3735 		 2, 0);
3736 
3737 SHELL_SUBCMD_ADD((wifi), ps_timeout, NULL,
3738 		 "<val> - PS inactivity timer(in ms).\n",
3739 		 cmd_wifi_ps_timeout,
3740 		 2, 0);
3741 
3742 SHELL_SUBCMD_ADD((wifi), ps_wakeup_mode, NULL,
3743 		 "<wakeup_mode: DTIM/Listen Interval>.\n",
3744 		 cmd_wifi_ps_wakeup_mode,
3745 		 2, 0);
3746 
3747 SHELL_SUBCMD_ADD((wifi), reg_domain, NULL,
3748 		 "Set or Get Wi-Fi regulatory domain\n"
3749 		 "[ISO/IEC 3166-1 alpha2]: Regulatory domain\n"
3750 		 "[-f]: Force to use this regulatory hint over any other regulatory hints\n"
3751 		 "Note1: The behavior of this command is dependent on the Wi-Fi driver/chipset implementation\n"
3752 		 "Note2: This may cause regulatory compliance issues, use it at your own risk.\n"
3753 		 "[-v]: Verbose, display the per-channel regulatory information\n",
3754 		 cmd_wifi_reg_domain,
3755 		 1, 3);
3756 
3757 SHELL_SUBCMD_ADD((wifi), rts_threshold, NULL,
3758 		 "<rts_threshold: rts threshold/off>.\n",
3759 		 cmd_wifi_set_rts_threshold,
3760 		 1, 1);
3761 
3762 SHELL_SUBCMD_ADD((wifi), scan, NULL,
3763 		 "Scan for Wi-Fi APs\n"
3764 		 "[-t, --type <active/passive>] : Preferred mode of scan. "
3765 		 "The actual mode of scan can depend on factors such as the Wi-Fi chip "
3766 		 "implementation, regulatory domain restrictions. Default type is active\n"
3767 		 "[-b, --bands <Comma separated list of band values (2/5/6)>] : "
3768 		 "Bands to be scanned where 2: 2.4 GHz, 5: 5 GHz, 6: 6 GHz\n"
3769 		 "[-a, --dwell_time_active <val_in_ms>] : "
3770 		 "Active scan dwell time (in ms) on a channel. Range 5 ms to 1000 ms\n"
3771 		 "[-p, --dwell_time_passive <val_in_ms>] : "
3772 		 "Passive scan dwell time (in ms) on a channel. Range 10 ms to 1000 ms\n"
3773 		 "[-s, --ssid] : SSID to scan for. Can be provided multiple times\n"
3774 		 "[-m, --max_bss <val>] : Maximum BSSes to scan for. Range 1 - 65535\n"
3775 		 "[-c, --chans <Comma separated list of channel ranges>] : "
3776 		 "Channels to be scanned. The channels must be specified in the form "
3777 		 "band1:chan1,chan2_band2:chan3,..etc. band1, band2 must be valid band "
3778 		 "values and chan1, chan2, chan3 must be specified as a list of comma "
3779 		 "separated values where each value is either a single channel or a "
3780 		 "channel range specified as chan_start-chan_end. Each band channel "
3781 		 "set has to be separated by a _. For example, a valid channel "
3782 		 "specification can be 2:1,6_5:36 or 2:1,6-11,14_5:36,163-177,52. "
3783 		 "Care should be taken to ensure that configured channels don't exceed "
3784 		 "CONFIG_WIFI_MGMT_SCAN_CHAN_MAX_MANUAL\n"
3785 		 "[-h, --help] : Print out the help for the scan command.\n",
3786 		 cmd_wifi_scan,
3787 		 1, 8);
3788 
3789 SHELL_SUBCMD_ADD((wifi), statistics, NULL,
3790 		 "Wi-Fi interface statistics.\n"
3791 		 "[reset] : Reset Wi-Fi interface statistics\n"
3792 		 "[help] :  Print out the help for the statistics command.",
3793 		 cmd_wifi_stats,
3794 		 1, 1);
3795 
3796 SHELL_SUBCMD_ADD((wifi), status, NULL,
3797 		 "Status of the Wi-Fi interface.\n",
3798 		 cmd_wifi_status,
3799 		 1, 0);
3800 
3801 SHELL_SUBCMD_ADD((wifi), version, NULL,
3802 		 "Print Wi-Fi Driver and Firmware versions\n",
3803 		 cmd_wifi_version,
3804 		 1, 0);
3805 
3806 SHELL_SUBCMD_ADD((wifi), wps_pbc, NULL,
3807 		 "Start a WPS PBC connection.\n",
3808 		 cmd_wifi_wps_pbc,
3809 		 1, 0);
3810 
3811 SHELL_SUBCMD_ADD((wifi), wps_pin, NULL,
3812 		 "Set and get WPS pin.\n"
3813 		 "[pin] Only applicable for set.\n",
3814 		 cmd_wifi_wps_pin,
3815 		 1, 1);
3816 
3817 SHELL_SUBCMD_ADD((wifi), ps_exit_strategy, NULL,
3818 		 "<tim> : Set PS exit strategy to Every TIM\n"
3819 		 "<custom> : Set PS exit strategy to Custom",
3820 		 cmd_wifi_ps_exit_strategy,
3821 		 2, 0);
3822 
3823 SHELL_CMD_REGISTER(wifi, &wifi_commands, "Wi-Fi commands", NULL);
3824 
wifi_shell_init(void)3825 static int wifi_shell_init(void)
3826 {
3827 
3828 	context.sh = NULL;
3829 	context.all = 0U;
3830 	context.scan_result = 0U;
3831 
3832 	net_mgmt_init_event_callback(&wifi_shell_mgmt_cb,
3833 				     wifi_mgmt_event_handler,
3834 				     WIFI_SHELL_MGMT_EVENTS);
3835 
3836 	net_mgmt_add_event_callback(&wifi_shell_mgmt_cb);
3837 
3838 	return 0;
3839 }
3840 
3841 SYS_INIT(wifi_shell_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
3842