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