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