• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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