1 /*
2 * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 /*
16 * INCLUDE FILES
17 ****************************************************************************************
18 */
19 #include <stdlib.h>
20 #include <strings.h>
21 #include "al_rtos.h"
22 #include "wifi_mac.h"
23 #include "wifi_host.h"
24 #include "wifi_host_wpa.h"
25 #include "wifi_host_cntrl.h"
26 #include "wifi_host_config.h"
27 #include "wifi_host_iperf.h"
28 #include "wifi_host_ping.h"
29 #include "dbg_assert.h"
30 #include "rwnx_utils.h"
31 #include "wifi_nx_msg_tx.h"
32 #include "porting_net_al.h"
33 #include "console.h"
34 #include "wlan_if.h"
35 #include "command.h"
36 #include "wifi_host_tx.h"
37 #include "wifi_host_smartconf.h"
38 #include "fhost_command_common.h"
39 #include "flash_api.h"
40
41 uint8_t fhost_vif_idx = 0;
42
43 #ifdef CFG_SOFTAP
44 int ps_sta_connected = 0;
45 #endif
46 uint8_t is_ap = 0;
47 #define PW_LEN 64
48
fhost_nw_upper(char * str,char * stop)49 static void fhost_nw_upper(char *str, char *stop)
50 {
51 char *ptr = str;
52 char c;
53
54 if (stop)
55 {
56 c = *stop;
57 *stop = 0;
58 }
59 while (*ptr)
60 {
61 if ((*ptr >= 'a') && (*ptr <= 'z'))
62 *ptr -= 'a' - 'A';
63 ptr++;
64 }
65
66 if (stop)
67 *stop = c;
68 }
69
do_restore(int argc,char * argv[])70 int do_restore(int argc, char *argv[]){
71 flash_wifi_info_remove_all();
72
73 return ERR_NONE;
74 }
75
76 // int do_show_heap(int argc, char *argv[])
77 // {
78 // int total, used, free, max_used;
79
80 // rtos_heap_info(&total, &free, &max_used);
81 // used = total - free;
82 // max_used = total - max_used;
83 // dbg("RTOS HEAP: free=%d used=%d max_used=%d/%d\n",
84 // free, used, max_used, total);
85
86 // return ERR_NONE;
87 // }
88
do_set_power(int argc,char * argv[])89 int do_set_power(int argc, char *argv[])
90 {
91 unsigned int fvif_idx;
92 unsigned int tx_pwr_lvl;
93 char power_pol;
94
95 if (argc != 3) {
96 dbg("Usage:\n AT+TXPWR=idx power_level\n");
97 return ERR_WRONG_ARGS;
98 }
99
100 fvif_idx = console_cmd_strtoul(argv[1], NULL, 10);
101 if (fvif_idx >= NX_VIRT_DEV_MAX) {
102 dbg("invalid fvif index\n");
103 return ERR_WRONG_ARGS;
104 }
105 power_pol = *(argv[2]);
106 if(power_pol == '-') {
107 argv[2] = argv[2] + 1;
108 tx_pwr_lvl = console_cmd_strtoul(argv[2], NULL, 10);
109 if(tx_pwr_lvl > 0x7F) {
110 dbg("invalid tx power\n");
111 return ERR_WRONG_ARGS;
112 }
113 tx_pwr_lvl = 0xFF &(~(tx_pwr_lvl - 1));
114 }
115 else {
116 tx_pwr_lvl = console_cmd_strtoul(argv[2], NULL, 10);
117 if(tx_pwr_lvl > 0x7F) {
118 dbg("invalid tx power\n");
119 return ERR_WRONG_ARGS;
120 }
121 }
122 fhost_cntrl_cfgrwnx_set_tx_power(fvif_idx,tx_pwr_lvl);
123
124 return ERR_NONE;
125 }
126
do_mac(int argc,char * argv[])127 int do_mac(int argc, char *argv[])
128 {
129 uint8_t *mdata, mac[12];
130
131 if(*argv[1] == '?') {
132 #if (!PLF_HW_PXP)
133 if (flash_wifi_sta_macaddr_read(mac) == INFO_READ_DONE) {
134 set_mac_address(mac);
135 }
136 #endif
137 mdata = get_mac_address();
138 dbg("%02x:%02x:%02x:%02x:%02x:%02x\r\n",
139 mdata[0], mdata[1], mdata[2], mdata[3], mdata[4], mdata[5]);
140 return ERR_NONE;
141 }
142
143 if(1 == wlan_connected) {
144 return ERR_CMD_ABORT;
145 }
146
147 if(strlen(argv[1]) != 12) {
148 return ERR_WRONG_ARGS;
149 }
150
151 mdata = (uint8_t *)argv[1];
152 for(uint8_t i = 0; i < 12; i++){
153 if(mdata[i] >= 0x41 && mdata[i] <= 0x46)// switch 'A' to 'a'
154 mdata[i] += 0x20;
155 if(mdata[i] >= 0x61 && mdata[i] <= 0x66)//switch "ab" to 0xab
156 mac[i] = mdata[i] - 0x57;
157 if(mdata[i] >= 0x30 && mdata[i] <= 0x39)
158 mac[i] = mdata[i] - 0x30;
159 if(i%2 == 1)
160 mac[i/2] = mac[i-1] << 4 | mac[i];
161 }
162 if((!MAC_ADDR_VALID(mac)) && (!MAC_ADDR_GROUP(mac))) {
163 return ERR_WRONG_ARGS;
164 }
165 set_mac_address(mac);
166 #if (!PLF_HW_PXP)
167 flash_wifi_sta_macaddr_write(mac);
168 #endif
169
170 return ERR_NONE;
171 }
172
173 #ifdef CFG_WPS
do_wps_pbc(int argc,char * argv[])174 int do_wps_pbc (int argc, char *argv[])
175 {
176 wlan_start_wps();
177
178 return ERR_NONE;
179 }
180 #endif /* CFG_WPS */
181
do_auto_connect(int argc,char * argv[])182 int do_auto_connect (int argc, char *argv[])
183 {
184 if (argc != 3) {
185 dbg("Usage:\n AT+WAUTOCNCT=mode <frcd_ap/auto_cnct>\n");
186 return ERR_WRONG_ARGS;
187 }
188
189 if (strncasecmp(argv[1], "AP", 2) == 0) {
190 unsigned int ap_config;
191 unsigned int forced_ap_mode;
192 if (flash_wifi_ap_config_read(&ap_config)) {
193 dbg("flash read err\n");
194 return ERR_CMD_FAIL;
195 }
196 forced_ap_mode = console_cmd_strtoul(argv[2],NULL,10);
197 if (forced_ap_mode) {
198 ap_config |= WIFI_AP_CONFIG_FORCED_AP_MODE_EN;
199 } else {
200 ap_config &= ~WIFI_AP_CONFIG_FORCED_AP_MODE_EN;
201 }
202 flash_wifi_ap_config_write(&ap_config);
203 } else if (strncasecmp(argv[1], "STA", 3) == 0) {
204 unsigned int sta_config;
205 unsigned int auto_connect;
206 if (flash_wifi_sta_config_read(&sta_config)) {
207 dbg("flash read err\n");
208 return ERR_CMD_FAIL;
209 }
210 auto_connect = console_cmd_strtoul(argv[2],NULL,10);
211 if (auto_connect > 1) {
212 dbg("invalid auto_cnct parameter\n");
213 return ERR_WRONG_ARGS;
214 }
215 if (auto_connect) {
216 sta_config |= WIFI_STA_CONFIG_STA_AUTO_CONNECT_EN;
217 } else {
218 sta_config &= ~WIFI_STA_CONFIG_STA_AUTO_CONNECT_EN;
219 }
220 flash_wifi_sta_config_write(&sta_config);
221 } else {
222 dbg("invalid mode\n");
223 return ERR_WRONG_ARGS;
224 }
225
226 return ERR_NONE;
227 }
228
do_connect(int argc,char * argv[])229 int do_connect (int argc, char *argv[])
230 {
231 uint8_t *ssid = NULL, *pw = NULL;
232 uint8_t len = 0;
233 int flash_ssid_rd_flag = 0;
234 int flash_wr_flag = 0;
235 unsigned char macaddr_flash[MAC_ADDR_LEN];
236
237 if (argc == 1) {
238 flash_ssid_rd_flag = 1;
239 } else if (argc >= 3) {
240 if (strlen(argv[1]) == 1) {
241 flash_wr_flag = argv[1][0] - '0';
242 } else {
243 flash_wr_flag = 2;
244 }
245 }
246 if ((argc == 2) || (flash_wr_flag & ~0x01UL)) {
247 dbg("Usage:\n connect 0/1 ssid <pwd>\n");
248 return ERR_WRONG_ARGS;
249 }
250 #if (!PLF_HW_PXP)
251 if (flash_wifi_sta_macaddr_read(macaddr_flash) == INFO_READ_DONE) {
252 // MAC Address
253 set_mac_address(macaddr_flash);
254 } else if (flash_ssid_rd_flag) {
255 dbg("Wifi flash macaddr read err\n");
256 return ERR_CMD_FAIL;
257 }
258 #endif
259 is_ap = 0;
260 // SSID
261 ssid = rtos_malloc(MAC_SSID_LEN+1);
262 if(!ssid)
263 return ERR_CMD_FAIL;
264 pw = rtos_malloc(PW_LEN+1);
265 if(!pw) {
266 rtos_free(ssid);
267 ssid = NULL;
268 return ERR_CMD_FAIL;
269 }
270 if (flash_ssid_rd_flag) {
271 if(flash_wifi_sta_ssidpw_read((char *)ssid, (char *)pw) != INFO_READ_DONE) {
272 rtos_free(ssid);
273 ssid = NULL;
274 rtos_free(pw);
275 pw = NULL;
276 return ERR_CMD_FAIL;
277 }
278 } else {
279 len = ((strlen(argv[2]) + 1) > MAC_SSID_LEN) ? MAC_SSID_LEN : (strlen(argv[2]) + 1);
280 memcpy(ssid, argv[2], len);
281 if (argc > 3) { // <Password>
282 len = ((strlen(argv[3]) + 1) > PW_LEN) ? PW_LEN : (strlen(argv[3]) + 1);
283 memcpy(pw, argv[3], len);
284 } else {
285 pw[0] = '\0';
286 }
287 }
288
289 if(wlan_connected) {
290 dbg("wlan already connected.\r\n");
291 return ERR_CMD_ABORT;
292 }
293
294 if (0 == wlan_start_sta(ssid, pw, 0)) {
295 wlan_connected = 1;
296 }
297
298 if (flash_wr_flag == 1) {
299 #if (!PLF_HW_PXP)
300 flash_wifi_sta_ssidpw_write((char *)ssid, (char *)pw);
301 #endif
302 }
303
304 rtos_free(ssid);
305 ssid = NULL;
306 rtos_free(pw);
307 pw = NULL;
308
309 return ERR_NONE;
310 }
do_connect_wep(int argc,char * argv[])311 int do_connect_wep (int argc, char *argv[])
312 {
313 uint8_t *ssid = NULL, *pw = NULL;
314 uint8_t len = 0;
315 int flash_ssid_rd_flag = 0;
316 int flash_wr_flag = 0;
317 unsigned char macaddr_flash[MAC_ADDR_LEN];
318
319 if (argc == 1) {
320 flash_ssid_rd_flag = 1;
321 } else if (argc >= 3) {
322 if (strlen(argv[1]) == 1) {
323 flash_wr_flag = argv[1][0] - '0';
324 } else {
325 flash_wr_flag = 2;
326 }
327 }
328 if ((argc == 2) || (flash_wr_flag & ~0x01UL)) {
329 dbg("Usage:\n connect 0/1 ssid <pwd>\n");
330 return ERR_WRONG_ARGS;
331 }
332 #if (!PLF_HW_PXP)
333 if (flash_wifi_sta_macaddr_read(macaddr_flash) == INFO_READ_DONE) {
334 // MAC Address
335 set_mac_address(macaddr_flash);
336 } else if (flash_ssid_rd_flag) {
337 dbg("Wifi flash macaddr read err\n");
338 return ERR_CMD_FAIL;
339 }
340 #endif
341 is_ap = 0;
342 // SSID
343 ssid = rtos_malloc(MAC_SSID_LEN+1);
344 if(!ssid)
345 return ERR_CMD_FAIL;
346 pw = rtos_malloc(PW_LEN+1);
347 if(!pw) {
348 rtos_free(ssid);
349 ssid = NULL;
350 return ERR_CMD_FAIL;
351 }
352 if (flash_ssid_rd_flag) {
353 if(flash_wifi_sta_ssidpw_read((char *)ssid, (char *)pw) != INFO_READ_DONE) {
354 rtos_free(ssid);
355 ssid = NULL;
356 rtos_free(pw);
357 pw = NULL;
358 return ERR_CMD_FAIL;
359 }
360 } else {
361 len = ((strlen(argv[2]) + 1) > MAC_SSID_LEN) ? MAC_SSID_LEN : (strlen(argv[2]) + 1);
362 memcpy(ssid, argv[2], len);
363 if (argc > 3) { // <Password>
364 len = ((strlen(argv[3]) + 1) > PW_LEN) ? PW_LEN : (strlen(argv[3]) + 1);
365 memcpy(pw, argv[3], len);
366 } else {
367 pw[0] = '\0';
368 }
369 }
370
371 if(wlan_connected) {
372 dbg("wlan already connected.\r\n");
373 return ERR_CMD_ABORT;
374 }
375
376 if (0 == wlan_start_sta(ssid, pw, 1)) {
377 wlan_connected = 1;
378 }
379
380 if (flash_wr_flag == 1) {
381 #if (!PLF_HW_PXP)
382 flash_wifi_sta_ssidpw_write((char *)ssid, (char *)pw);
383 #endif
384 }
385
386 rtos_free(ssid);
387 ssid = NULL;
388 rtos_free(pw);
389 pw = NULL;
390
391 return ERR_NONE;
392 }
393
do_disconnect(int argc,char * argv[])394 int do_disconnect (int argc, char *argv[])
395 {
396 wlan_disconnect_sta(fhost_vif_idx);
397
398 return ERR_NONE;
399 }
400
401 #ifdef CFG_SOFTAP
do_start_ap(int argc,char * argv[])402 int do_start_ap (int argc, char *argv[])
403 {
404 uint8_t *ssid = NULL, *pw = NULL;
405 uint8_t len = 0, band = 0;
406
407 if (argc < 3) {
408 dbg("Usage:\n startap band ssid <pwd>\n");
409 return ERR_WRONG_ARGS;
410 }
411
412 is_ap = 1;
413
414 // band
415 band = console_cmd_strtoul(argv[1], NULL, 10);
416
417 // SSID
418 ssid = rtos_malloc(MAC_SSID_LEN+1);
419 if(!ssid)
420 return ERR_CMD_FAIL;
421 memset(ssid, 0, MAC_SSID_LEN+1);
422 len = (strlen(argv[2]) > MAC_SSID_LEN) ? MAC_SSID_LEN : strlen(argv[2]);
423 memcpy(ssid, argv[2], len);
424
425 //<Password>
426 if(argc > 3)
427 {
428 pw = rtos_malloc(PW_LEN+1);
429 if(!pw) {
430 rtos_free(ssid);
431 ssid = NULL;
432 return ERR_CMD_FAIL;
433 }
434 memset(pw, 0, PW_LEN+1);
435 len = (strlen(argv[3]) > PW_LEN) ? PW_LEN : strlen(argv[3]);
436 memcpy(pw, argv[3], len);
437 }
438
439 wlan_start_ap(band, ssid, pw);
440
441 rtos_free(ssid);
442 ssid = NULL;
443 rtos_free(pw);
444 pw = NULL;
445
446 return ERR_NONE;
447 }
448
do_stop_ap(int argc,char * argv[])449 int do_stop_ap (int argc, char *argv[])
450 {
451 wlan_stop_ap();
452
453 return ERR_NONE;
454 }
455 #endif /* CFG_SOFTAP */
456
457 #ifdef CFG_SOFTAP
458 #if NX_BEACONING
459 static struct fhost_cntrl_link *ap_link;
460 #include "dhcps.h"
461 #endif
462 /**
463 ****************************************************************************************
464 * @brief Process function for 'ap' command
465 *
466 * Start an AP
467 * @verbatim
468 ap [-i <itf>] -s <SSID> -f <freq>[+-@] [-a <akm>[,<akm 2>]] [-k <key>]
469 [-b bcn_int[,dtim_period]] [-u <unicast cipher>[,<unicast cipher 2>]]
470 [-g <group cipher>] [-m <mfp: 0|1|2>]
471 @endverbatim
472 * The '+/-' after the frequency allow to configure a 40MHz channel with the secondary
473 * channel being the upper/lower one. The '@' allow to configure a 80 MHz channel, this
474 * is only allowed for valid primary channel and center freq is automatically computed.
475 *
476 * @param[in] params Connection parameters
477 * @return 0 on success and !=0 if error occurred
478 ****************************************************************************************
479 */
do_create_ap(int argc,char * argv[])480 int do_create_ap (int argc, char *argv[])
481 {
482 #if NX_BEACONING
483 struct fhost_vif_ap_cfg cfg;
484 int fhost_vif_idx = 0;//fhost_search_first_valid_itf();
485 char option;
486 char *cfg_val;
487 uint32_t cipher;
488
489 if ((argc < 5) || (argc > 9)) {
490 dbg("Usage:\n AT+WCAP ssid pwd center_frequency cipher_suite hidden_ssid <group cipher_type> <mfp_feature> <dtim> <beacon_interval>\n");
491 return ERR_WRONG_ARGS;
492 }
493
494 memset(&cfg, 0, sizeof(cfg));
495 //cfg ssid
496 size_t ssid_len = strlen(argv[1]);
497 if (ssid_len > sizeof(cfg.ssid.array))
498 {
499 dbg("Invalid SSID\r\n");
500 return ERR_CMD_FAIL;
501 }
502 memcpy(cfg.ssid.array, argv[1], ssid_len);
503 cfg.ssid.length = ssid_len;
504 //cfg key
505 size_t key_len = strlen(argv[2]);
506 if ((key_len + 1) > sizeof(cfg.key))
507 {
508 dbg("Invalid Key\r\n");
509 return ERR_CMD_FAIL;
510 }
511 strcpy(cfg.key, argv[2]);
512 //cfg freq_feature
513 int len = strlen(argv[3]) - 1;
514 char freq_feature = *(argv[3] + len);
515
516 struct mac_chan_def *chan = NULL;
517 int offset = 0;
518 if (freq_feature == '+')
519 {
520 offset = 10;
521 cfg.chan.type = PHY_CHNL_BW_40;
522 }
523 else if (freq_feature == '-')
524 {
525 offset = -10;
526 cfg.chan.type = PHY_CHNL_BW_40;
527 }
528 else if (freq_feature == '@')
529 {
530 cfg.chan.type = PHY_CHNL_BW_80;
531 }
532 else
533 {
534 cfg.chan.type = PHY_CHNL_BW_20;
535 }
536
537 cfg.chan.prim20_freq = atoi(argv[3]);
538 chan = fhost_chan_get(cfg.chan.prim20_freq);
539 if (!chan)
540 {
541 dbg("Invalid channel\n");
542 return ERR_CMD_FAIL;
543 }
544
545 if (cfg.chan.prim20_freq >= PHY_FREQ_5G)
546 cfg.chan.band = PHY_BAND_5G;
547 else
548 cfg.chan.band = PHY_BAND_2G4;
549
550 if (cfg.chan.type == PHY_CHNL_BW_80)
551 {
552 if ((cfg.chan.prim20_freq < 5180) ||
553 (cfg.chan.prim20_freq > 5805))
554 {
555 dbg("Invalid primary for 80MHz channel\n");
556 return ERR_CMD_FAIL;
557 }
558 offset = (cfg.chan.prim20_freq - 5180) % 80;
559 if (offset < 20)
560 offset = 30;
561 else if (offset < 40)
562 offset = 10;
563 else if (offset < 60)
564 offset = -10;
565 else
566 offset = -30;
567 }
568 cfg.chan.center1_freq = cfg.chan.prim20_freq + offset;
569 //cfg cipher suite
570 fhost_nw_upper(argv[4], NULL);
571 if (strncmp(argv[4], "OPEN", 4) == 0)
572 {
573 cfg.akm |= CO_BIT(MAC_AKM_NONE);
574 }
575 else if (strncmp(argv[4], "WEP", 4) == 0)
576 {
577 cfg.akm |= CO_BIT(MAC_AKM_PRE_RSN);
578 }
579 else if (strncmp(argv[4], "WPA", 3) == 0)
580 {
581 cfg.akm |= CO_BIT(MAC_AKM_PRE_RSN) | CO_BIT(MAC_AKM_PSK);
582 }
583 else if (strncmp(argv[4], "RSN", 3) == 0)
584 {
585 cfg.akm |= CO_BIT(MAC_AKM_PSK);
586 }
587 else if (strncmp(argv[4], "SAE", 3) == 0)
588 {
589 cfg.akm |= CO_BIT(MAC_AKM_SAE);
590 }
591 else
592 {
593 dbg("The following AKM are supported [%s]:\n"
594 "OPEN: For open AP\n"
595 "WEP: For AP with WEP security\n"
596 "WPA: For AP with WPA/PSK security (pre WPA2)\n"
597 "RSN: For AP with WPA2/PSK security\n"
598 "SAE: For AP with WPA3/PSK security\n", argv[4]);
599 return ERR_CMD_FAIL;
600 }
601 //cfg unicast_cipher_suite group_cipher_suite or bcn_interval or mpf_feature
602 if(argc >= 6){
603 option = *(argv[5]);
604 cfg_val = (char *)(argv[5] + 1);
605 if(option == 'g')
606 {
607 cipher = 0;
608 if(((cfg.akm & CO_BIT(MAC_AKM_PRE_RSN)) == 0) && ((cfg.akm & CO_BIT(MAC_AKM_PSK)) != 0))
609 {
610 fhost_nw_upper(cfg_val,NULL);
611 dbg("cipher type %s\n",cfg_val);
612 if (strncmp(cfg_val, "CCMP", 4) == 0)
613 {
614 cipher |= CO_BIT(MAC_CIPHER_CCMP);
615 }
616 else if (strncmp(cfg_val, "TKIP", 4) == 0)
617 {
618 cipher |= CO_BIT(MAC_CIPHER_TKIP);
619 }
620 else
621 {
622 dbg("The following cipher are supported [%s]:\n"
623 "CCMP, TKIP", cfg_val);
624 return ERR_CMD_FAIL;
625 }
626 cfg.group_cipher = cipher;
627 }
628 else
629 {
630 dbg("akm %s cannot cfg groupkey",argv[4]);
631 return ERR_CMD_FAIL;
632 }
633 }
634 else if(option == 'm')
635 {
636 cfg.mfp = atoi(cfg_val);
637 }
638 else if(option == 'b')
639 {
640 cfg.bcn_interval = atoi(cfg_val);
641 }
642 else if(option == 'd')
643 {
644 cfg.dtim_period = atoi(cfg_val);
645 }
646 else
647 {
648 dbg("Invalid additional feature: %s\n",argv[5]);
649 return ERR_CMD_FAIL;
650 }
651 }
652
653 if(argc >= 7){
654 option = *(argv[6]);
655 cfg_val = (char *)(argv[6] + 1);
656 if(option == 'm')
657 {
658 cfg.mfp = atoi(cfg_val);
659 }
660 else if(option == 'b')
661 {
662 cfg.bcn_interval = atoi(cfg_val);
663 }
664 else if(option == 'd')
665 {
666 cfg.dtim_period = atoi(cfg_val);
667 }
668 else
669 {
670 dbg("Invalid additional feature: %s\n",argv[6]);
671 return ERR_CMD_FAIL;
672 }
673 }
674
675 if(argc >= 8){
676 option = *(argv[7]);
677 cfg_val = (char *)(argv[7] + 1);
678 if(option == 'b')
679 {
680 cfg.bcn_interval = atoi(cfg_val);
681 }
682 else if(option == 'd')
683 {
684 cfg.dtim_period = atoi(cfg_val);
685 }
686 else
687 {
688 dbg("Invalid additional feature: %s\n",argv[7]);
689 return ERR_CMD_FAIL;
690 }
691 }
692 if(argc == 9){
693 option = *(argv[8]);
694 cfg_val = (char *)(argv[8] + 1);
695 if(option == 'd')
696 {
697 cfg.dtim_period = atoi(cfg_val);
698 }
699 else
700 {
701 dbg("Invalid additional feature: %s\n",argv[8]);
702 return ERR_CMD_FAIL;
703 }
704 }
705
706 if (fhost_vif_idx < 0)
707 return ERR_CMD_FAIL;
708
709 if ((cfg.ssid.length == 0) || (cfg.chan.prim20_freq == 0))
710 return ERR_WRONG_ARGS;
711
712 // try to select the best AKM if not set
713 if (cfg.akm == 0)
714 {
715 if (strlen(cfg.key) == 0)
716 cfg.akm = CO_BIT(MAC_AKM_NONE);
717 else if (strlen(cfg.key) == 5)
718 cfg.akm = CO_BIT(MAC_AKM_PRE_RSN);
719 else
720 cfg.akm = CO_BIT(MAC_AKM_PSK);
721 }
722 ipc_host_cntrl_start();
723
724 struct fhost_vif_tag *fhost_vif;
725
726 ap_link = fhost_cntrl_cfgrwnx_link_open();
727 if (ap_link == NULL) {
728 dbg(D_ERR "Failed to open link with control task\n");
729 ASSERT_ERR(0);
730 }
731
732 // (Re)Set interface type to AP
733 if (fhost_set_vif_type(ap_link, fhost_vif_idx, VIF_UNKNOWN, false) ||
734 fhost_set_vif_type(ap_link, fhost_vif_idx, VIF_AP, false))
735 return ERR_CMD_FAIL;
736 fhost_cntrl_cfgrwnx_link_close(ap_link);
737
738 fhost_vif = &fhost_env.vif[fhost_vif_idx];
739 MAC_ADDR_CPY(&(vif_info_tab[fhost_vif_idx].mac_addr), &(fhost_vif->mac_addr));
740
741 if (fhost_ap_cfg(fhost_vif_idx, &cfg))
742 {
743 dbg("Failed to start AP, check your configuration");
744 return ERR_CMD_FAIL;
745 }
746
747 net_if_t *net_if = fhost_to_net_if(fhost_vif_idx);
748 if (net_if == NULL) {
749 dbg("[CS] net_if_find_from_wifi_idx fail\r\n");
750 return 1;
751 }
752 uint32_t ip_mask = 0x00FFFFFF;
753 uint32_t ip_addr = get_ap_ip_addr();
754 net_if_set_ip(net_if, ip_addr, ip_mask, 0);
755
756 //set up DHCP server
757 dhcpServerStart(net_if);
758
759 // Now that we got an IP address use this interface as default
760 net_if_set_default(net_if);
761
762 fhost_tx_task_init();
763
764 dbg("DHCPS init: ip=%d.%d.%d.%d\r\n",
765 (ip_addr)&0xFF, (ip_addr>>8)&0xFF, (ip_addr>>16)&0xFF, (ip_addr>>24)&0xFF);
766
767 #endif // NX_BEACONING
768
769 is_ap = 1;
770
771 return ERR_NONE;
772 }
773 #endif /* CFG_SOFTAP */
774
775 #if NX_SMARTCONFIG
776 extern uint8_t disconnected_by_user;
777 /**
778 ****************************************************************************************
779 * @brief Process function for 'smartconf' command
780 *
781 * smartconf command allows to set the SSID and password and associate automatically
782 * to an AP .
783 * Wi-Fi enabled device such as a smartphone sends to the Wi-Fi Access Point(AP) the SSID
784 * and password encoded into the Length field of a sequence UDP packets, then the smartconf
785 * can reach packets, decode the ssid & pwd and connect to the AP
786
787 * @return 0 on success and !=0 if error occurred
788 ****************************************************************************************
789 */
do_smartconf(int argc,char * argv[])790 int do_smartconf(int argc, char *argv[])
791 {
792 fhost_vif_idx = 0;
793
794 if(!disconnected_by_user) {
795 set_mac_address(NULL);
796 ipc_host_cntrl_start();
797 }
798
799 if (fhost_smartconf_start(fhost_vif_idx, NULL))
800 {
801 dbg("Fhost smartconf init failed\n");
802 return ERR_CMD_ABORT;
803 }
804
805 return ERR_NONE;
806 }
807
do_stop_smartconf(int argc,char * argv[])808 int do_stop_smartconf(int argc, char *argv[])
809 {
810 if(fhost_smartconf_stop()) {
811 return ERR_CMD_ABORT;
812 }
813 return ERR_NONE;
814 }
815 #endif /* NX_SMARTCONFIG */
816
817 #if PLF_PING
818 /// Handle of the ping task
819 static rtos_task_handle ping_task_handle;
820 #endif /* PLF_PING */
821 /**
822 ****************************************************************************************
823 * @brief Convert string containing ip address
824 *
825 * The string may should be of the form a.b.c.d/e (/e being optional)
826 *
827 * @param[in] str String to parse
828 * @parse[out] ip Updated with the numerical value of the ip address
829 * @parse[out] mask Updated with the numerical value of the network mask
830 * (or 32 if not present)
831 * @return 0 if string contained what looks like a valid ip address and -1 otherwise
832 ****************************************************************************************
833 */
fhost_nw_parse_ip4(char * str,uint32_t * ip,uint32_t * mask)834 int fhost_nw_parse_ip4(char *str, uint32_t *ip, uint32_t *mask)
835 {
836 char *token;
837 uint32_t a, i, j;
838
839 #define check_is_num(_str) for (j = 0 ; j < strlen(_str); j++) { \
840 if (_str[j] < '0' || _str[j] > '9') \
841 return -1; \
842 }
843
844 // Check if mask is present
845 token = strchr(str, '/');
846 if (token && mask) {
847 *token++ = '\0';
848 check_is_num(token);
849 a = atoi(token);
850 if (a == 0 || a > 32)
851 return -1;
852 *mask = (1<<a) - 1;
853 }
854 else if (mask)
855 {
856 *mask = 0xffffffff;
857 }
858
859 // parse the ip part
860 *ip = 0;
861 for (i = 0; i < 4; i ++)
862 {
863 if (i < 3)
864 {
865 token = strchr(str, '.');
866 if (!token)
867 return -1;
868 *token++ = '\0';
869 }
870 check_is_num(str);
871 a = atoi(str);
872 if (a > 255)
873 return -1;
874 str = token;
875 *ip += (a << (i * 8));
876 }
877
878 return 0;
879 }
880
881 /**
882 ****************************************************************************************
883 * @brief Extract token from parameter list
884 *
885 * Extract the first parameter of the string. Parameters are separatd with space unless
886 * it starts with " (or ') in which case it extract the token until " (or ') is reached.
887 * " (or ') are then removed from the token.
888 *
889 * @param[in, out] params Pointer to parameters string to parse. Updated with remaining
890 * parameters to parse.
891 * @return pointer on first parameter
892 ****************************************************************************************
893 */
fhost_nw_next_token(char ** params)894 char *fhost_nw_next_token(char **params)
895 {
896 char *ptr = *params, *next;
897 char sep = ' ';
898
899 if (!ptr)
900 return NULL;
901
902 if ((ptr[0] == '"') || (ptr[0] == '\''))
903 {
904 sep = ptr[0];
905 ptr++;
906 }
907
908 next = strchr(ptr, sep);
909 if (next)
910 {
911 *next++ = '\0';
912 while (*next == ' ')
913 next++;
914 if (*next == '\0')
915 next = NULL;
916 }
917 *params = next;
918 return ptr;
919 }
920
921 #if PLF_PING
922 /**
923 ****************************************************************************************
924 * @brief Process function for 'ping' command
925 *
926 * Ping command can be used to test the reachability of a host on an IP network.
927 *
928 * ping <dst_ip> [-s pksize] [-r rate] [-d duration] [-Q tos]
929 * ping stop <id1> [<id2> ... <id8>]
930 *
931 * Note that -s, -r, -d, -t are options for ping command. We could choose any of them to
932 * configure. If not configured, it will set the default values at layer @ref net_tg_al.
933 *
934 * @param[in] params ping command above
935 *
936 * @return 0 on success and !=0 if error occurred
937 ****************************************************************************************
938 */
fhost_console_ping(char * params)939 int fhost_console_ping(char *params)
940 {
941 char *token, *next = params;
942 uint32_t rip = 0;
943 token = fhost_nw_next_token(&next);
944 u32_t rate = 0, pksize = 0, duration = 0, tos = 0;
945 //struct fhost_task_msg_id *task_hdl_msg_ptr;
946 bool background = false;
947 struct fhost_ping_task_args args;
948
949 if (!strcmp("stop", token))
950 {
951 u32_t stream_id;
952 struct fhost_ping_stream* ping_stream;
953 int ret = FHOST_NW_SUCCESS;
954
955 token = fhost_nw_next_token(&next);
956 if (!token)
957 {
958 dbg("No ping id\n");
959 return FHOST_NW_ERROR;
960 }
961
962 stream_id = atoi(token);
963 ping_stream = fhost_ping_find_stream_profile(stream_id);
964
965 if (ping_stream)
966 {
967 if (ping_stream->background)
968 {
969 //task_hdl_msg_ptr = fhost_search_task_hdl_msg(ping_stream->ping_handle);
970 //task_hdl_msg_ptr->msg_id = ipc_msg.id;
971 ret = FHOST_NW_NO_RESP;
972 }
973 fhost_ping_stop(ping_stream);
974 }
975 else
976 {
977 dbg("Invalid stream_id %d, no stream associated\r\n", stream_id);
978 ret = FHOST_NW_ERROR;
979 }
980
981 return ret;
982 }
983 else
984 {
985 do
986 {
987 // Handle all options of ping command
988 if (token[0] == '-')
989 {
990 switch(token[1])
991 {
992 case ('s'):
993 token = fhost_nw_next_token(&next);
994 if (!token)
995 {
996 dbg("No packet size\n");
997 return FHOST_NW_ERROR;
998 }
999 pksize = atoi(token);
1000 break;
1001 case ('r'):
1002 token = fhost_nw_next_token(&next);
1003 if (!token)
1004 {
1005 dbg("No rate\n");
1006 return FHOST_NW_ERROR;
1007 }
1008 rate = atoi(token);
1009 break;
1010 case ('d'):
1011 token = fhost_nw_next_token(&next);
1012 if (!token)
1013 {
1014 dbg("No duration\n");
1015 return FHOST_NW_ERROR;
1016 }
1017 duration = atoi(token);
1018 break;
1019 case ('Q'):
1020 token = fhost_nw_next_token(&next);
1021 if (!token)
1022 {
1023 dbg("No ToS\n");
1024 return FHOST_NW_ERROR;
1025 }
1026 tos = atoi(token);
1027 break;
1028 case ('G'):
1029 background = true;
1030 break;
1031 default:
1032 dbg("Argument -%c not supported\n", token[1]);
1033 return FHOST_NW_ERROR;
1034 }
1035 }
1036 // If it's neither options, nor IP address, then the input is wrong
1037 else if (fhost_nw_parse_ip4(token, &rip, NULL))
1038 {
1039 dbg("Invalid input of ping %s\n", token);
1040 return FHOST_NW_ERROR;
1041 }
1042 } while ((token = fhost_nw_next_token(&next)));
1043
1044 // IP destination should be set by the command
1045 if (rip == 0)
1046 {
1047 dbg("No IP address, %s\n", token);
1048 return FHOST_NW_ERROR;
1049 }
1050 args.rip = rip;
1051 args.rate = rate;
1052 args.pksize = pksize;
1053 args.duration = duration;
1054 args.tos = tos;
1055 args.background = background;
1056 if ((ping_task_handle = fhost_ping_start(&args)))
1057 {
1058 //task_hdl_msg_ptr->msg_id = ipc_msg.id;
1059 }
1060 else
1061 {
1062 dbg("Send ping error\n");
1063 return FHOST_NW_ERROR;
1064 }
1065
1066 if (background)
1067 return FHOST_NW_SUCCESS;
1068 else
1069 return FHOST_NW_NO_RESP;
1070 }
1071 }
1072 #endif /* PLF_PING */
1073 #if PLF_IPERF
1074 rtos_task_handle iperf_task_handle;
1075 uint8_t remote_address[16] = {0};
1076 /*
1077 * IPERF FUNCTION
1078 ****************************************************************************************
1079 */
1080 /**
1081 ****************************************************************************************
1082 * @brief Process function for 'iperf' command
1083 *
1084 * Start an iperf server on the specified port.
1085 *
1086 * @param[in] params Port number
1087 * @return 0 on success and !=0 if error occurred
1088 ****************************************************************************************
1089 */
fhost_console_iperf(char * params)1090 int fhost_console_iperf(char *params)
1091 {
1092 char conv, *token, *substr, *next = params;
1093 struct fhost_iperf_settings iperf_settings;
1094 bool client_server_set = 0;
1095
1096 fhost_iperf_settings_init(&iperf_settings);
1097
1098 while ((token = fhost_nw_next_token(&next)))
1099 {
1100 if (token[0] != '-')
1101 {
1102 dbg("iperf: invalid option %s\n", token);
1103 return FHOST_NW_ERROR;
1104 }
1105
1106 //TODO[AAL]: Add support long options
1107
1108 switch(token[1])
1109 {
1110 case ('b'): // UDP bandwidth
1111 {
1112 if (!(token = fhost_nw_next_token(&next)))
1113 {
1114 dbg("iperf: missing bandwidth\n");
1115 return FHOST_NW_ERROR;
1116 }
1117
1118 iperf_settings.udprate = atoi (token);
1119 conv = token[strlen(token) - 1];
1120
1121 /* convert according to [Gg Mm Kk] */
1122 switch (conv)
1123 {
1124 case 'G':
1125 case 'g':
1126 iperf_settings.udprate *= 1000;
1127 case 'M':
1128 case 'm':
1129 iperf_settings.udprate *= 1000;
1130 case 'K':
1131 case 'k':
1132 iperf_settings.udprate *= 1000;
1133 default: break;
1134 }
1135
1136 iperf_settings.flags.is_udp = true;
1137 iperf_settings.flags.is_bw_set = true;
1138 // if -l has already been processed, is_buf_len_set is true so don't overwrite that value.
1139 if (!iperf_settings.flags.is_buf_len_set)
1140 {
1141 iperf_settings.buf_len = FHOST_IPERF_DEFAULT_UDPBUFLEN;
1142 }
1143 break;
1144 }
1145 case ('c'): // Client mode with server host to connect to
1146 {
1147 if (client_server_set)
1148 {
1149 dbg("iperf: Client/Server mode already set\n");
1150 return FHOST_NW_ERROR;
1151 }
1152 iperf_settings.flags.is_server = 0;
1153 client_server_set = true;
1154
1155 if (!(token = fhost_nw_next_token(&next)))
1156 {
1157 dbg("iperf: missing host\n");
1158 return FHOST_NW_ERROR;
1159 }
1160
1161 memcpy(remote_address, token, strlen(token));
1162
1163 if (fhost_nw_parse_ip4(token, &iperf_settings.host_ip, NULL))
1164 {
1165 dbg("iperf: invalid host IP\n");
1166 return FHOST_NW_ERROR;
1167 }
1168 break;
1169 }
1170 case ('f'): // format to print in
1171 {
1172 if (!(token = fhost_nw_next_token(&next)))
1173 {
1174 dbg("iperf: missing format\n");
1175 return FHOST_NW_ERROR;
1176 }
1177 iperf_settings.format = token[0];
1178 break;
1179 }
1180 case ('i'): // Interval between periodic reports
1181 {
1182 uint32_t interval = 0;
1183 if (!(token = fhost_nw_next_token(&next)))
1184 {
1185 dbg("iperf: missing interval\n");
1186 return FHOST_NW_ERROR;
1187 }
1188
1189 substr = strchr(token, '.');
1190
1191 if (substr)
1192 {
1193 *substr++ = '\0';
1194 interval += atoi(substr);
1195 }
1196
1197 interval += atoi(token) * 10;
1198 #if (PLF_HW_PXP != 1)
1199 if (interval < 5)
1200 {
1201 dbg("iperf: interval must be greater than or equal to 0.5. Interval set to 0.5\n");
1202 interval = 5;
1203 }
1204 #endif /* !PLF_HW_PXP */
1205
1206 iperf_settings.interval.sec = interval / 10;
1207 iperf_settings.interval.usec = 100000 * (interval - (iperf_settings.interval.sec * 10));
1208 break;
1209 }
1210 case ('l'): //Length of each buffer
1211 {
1212 if (!(token = fhost_nw_next_token(&next)))
1213 {
1214 dbg("iperf: missing buffer length\n");
1215 return FHOST_NW_ERROR;
1216 }
1217
1218 iperf_settings.buf_len = atoi( token );
1219 iperf_settings.flags.is_buf_len_set = true;
1220 if (iperf_settings.flags.is_udp && iperf_settings.buf_len < (int) sizeof( struct iperf_UDP_datagram ))
1221 {
1222 iperf_settings.buf_len = sizeof( struct iperf_UDP_datagram );
1223 dbg("iperf: buffer length must be greater than or equal to %d in UDP\n",
1224 sizeof(struct iperf_UDP_datagram));
1225 }
1226 break;
1227 }
1228 case ('n'): // amount mode (instead of time mode)
1229 {
1230 iperf_settings.flags.is_time_mode = false;
1231 if (!(token = fhost_nw_next_token(&next)))
1232 {
1233 dbg("iperf: missing amount (-n)\n");
1234 return FHOST_NW_ERROR;
1235 }
1236 iperf_settings.amount = atoi( token );
1237 break;
1238 }
1239 case ('p'): //server port
1240 {
1241 if (!(token = fhost_nw_next_token(&next)))
1242 {
1243 dbg("iperf: missing server port\n");
1244 return FHOST_NW_ERROR;
1245 }
1246 iperf_settings.port = atoi( token );
1247 break;
1248 }
1249 case ('s'): // server mode
1250 {
1251 if (client_server_set)
1252 {
1253 dbg("iperf: Client/Server already set\n");
1254 return FHOST_NW_ERROR;
1255 }
1256 iperf_settings.flags.is_server = 1;
1257 client_server_set = true;
1258 break;
1259 }
1260 case ('t'): // time mode (instead of amount mode)
1261 {
1262 iperf_settings.flags.is_time_mode = true;
1263 if (!(token = fhost_nw_next_token(&next)))
1264 {
1265 dbg("iperf: missing time\n");
1266 return FHOST_NW_ERROR;
1267 }
1268 iperf_settings.amount = 0;
1269 substr = strchr(token, '.');
1270 if (substr)
1271 {
1272 *substr++ = '\0';
1273 iperf_settings.amount += atoi(substr);
1274 }
1275
1276 iperf_settings.amount += atoi(token) * 10;
1277 break;
1278 }
1279 case ('u'): // UDP instead of TCP
1280 {
1281 // if -b has already been processed, UDP rate will be non-zero, so don't overwrite that value
1282 if (!iperf_settings.flags.is_udp)
1283 {
1284 iperf_settings.flags.is_udp = true;
1285 iperf_settings.udprate = FHOST_IPERF_DEFAULT_UDPRATE;
1286 }
1287
1288 // if -l has already been processed, is_buf_len_set is true, so don't overwrite that value.
1289 if (!iperf_settings.flags.is_buf_len_set)
1290 {
1291 iperf_settings.buf_len = FHOST_IPERF_DEFAULT_UDPBUFLEN;
1292 }
1293 break;
1294 }
1295 case ('S'): // IP type-of-service
1296 {
1297 if (!(token = fhost_nw_next_token(&next)))
1298 {
1299 dbg("iperf: missing TOS\n");
1300 return FHOST_NW_ERROR;
1301 }
1302 // the zero base allows the user to specify
1303 // hexadecimals: "0x#"
1304 // octals: "0#"
1305 // decimal numbers: "#"
1306 iperf_settings.tos = strtol( token, NULL, 0 );
1307 break;
1308 }
1309 case ('T'): // TTL
1310 {
1311 if (!(token = fhost_nw_next_token(&next)))
1312 {
1313 dbg("iperf: missing TTL\n");
1314 return FHOST_NW_ERROR;
1315 }
1316 iperf_settings.ttl = atoi(token);
1317 break;
1318 }
1319 case ('X'): // Peer version detect
1320 {
1321 iperf_settings.flags.is_peer_ver = true;
1322 break;
1323 }
1324 case ('h'): // Long Help
1325 {
1326 uart_puts(iperf_long_help);
1327 return FHOST_NW_SUCCESS;
1328 }
1329 default: // Short Help
1330 {
1331 dbg(iperf_short_help);
1332 return FHOST_NW_SUCCESS;
1333 }
1334 }
1335 };
1336
1337 if (!client_server_set)
1338 {
1339 dbg("iperf: missing option -s or -c\n");
1340 dbg(iperf_short_help);
1341 return FHOST_NW_ERROR;
1342 }
1343 fhost_iperf_start(&iperf_settings, &iperf_task_handle);
1344 return FHOST_NW_SUCCESS;
1345 }
1346 #endif /* PLF_IPERF */
1347
sta_auto_connect(void)1348 int sta_auto_connect(void)
1349 {
1350 uint8_t *ssid = NULL, *pw = NULL;
1351 unsigned int ap_config, sta_config;
1352 int ret;
1353
1354 ret = flash_wifi_ap_config_read(&ap_config);
1355 if (ret < 0) {
1356 dbg("Wifi ap_config read err: %d\n", ret);
1357 return -1;
1358 } else if (ret > 0) {
1359 // flag never set
1360 ap_config = 0;
1361 }
1362 ret = flash_wifi_sta_config_read(&sta_config);
1363 if (ret < 0) {
1364 dbg("Wifi sta_config read err: %d\n", ret);
1365 return -1;
1366 } else if (ret > 0) {
1367 // flag never set
1368 sta_config = 0;
1369 }
1370 if (((ap_config & WIFI_AP_CONFIG_FORCED_AP_MODE_EN) == 0) && (sta_config & WIFI_STA_CONFIG_STA_AUTO_CONNECT_EN)) {
1371 // SSID
1372 ssid = rtos_malloc(MAC_SSID_LEN+1);
1373 if(!ssid)
1374 return -1;
1375 //<Password>
1376 pw = rtos_malloc(PW_LEN+1);
1377 if(!pw) {
1378 rtos_free(ssid);
1379 ssid = NULL;
1380 return -1;
1381 }
1382 ret = flash_wifi_sta_ssidpw_read((char *)ssid, (char *)pw);
1383 if (ret) {
1384 dbg("WiFi sta_ssid_pw read err: %d\n", ret);
1385 return -1;
1386 }
1387 if (0 == wlan_start_sta(ssid, pw, 0)) {
1388 wlan_connected = 1;
1389 }
1390 rtos_free(ssid);
1391 ssid = NULL;
1392 rtos_free(pw);
1393 pw = NULL;
1394 }
1395 return 0;
1396 }
1397
1398