/*! \file cmd_shell.c \brief Command shell for GD32W51x WiFi SDK \version 2021-10-30, V1.0.0, firmware for GD32W51x */ /* Copyright (c) 2021, GigaDevice Semiconductor Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*============================ INCLUDES ======================================*/ #include #include #include "app_cfg.h" #include "app_type.h" #include "bsp_inc.h" #include "osal_types.h" #include "wlan_debug.h" #include "wrapper_os.h" #include "debug_print.h" #include "malloc.h" #include "lwip/netifapi.h" #include "lwip/dhcp.h" #include "lwip/ip_addr.h" #include "lwip/inet.h" #include "lwip/stats.h" #include "wifi_netlink.h" #include "dhcpd.h" #include "cmd_shell.h" #include "wifi_netif.h" #include "wifi_management.h" #include "uart.h" #include "console.h" #include "flash_api.h" #include #ifdef CONFIG_TELNET_SERVER #include "telnet_main.h" #endif #ifdef CONFIG_ALICLOUD_SUPPORT #include "alicloud_entry.h" #endif #if defined(CONFIG_CONSOLE_ENABLE) #ifdef CONFIG_RF_TEST_SUPPORT #include "cmd_rf_test.h" #endif #ifdef CONFIG_INTERNAL_DEBUG #include "cmd_inner_wifi.c" #include "cmd_inner_misc.c" #endif #ifdef CONFIG_ATCMD #include "atcmd.c" #endif #ifdef CONFIG_FATFS_SUPPORT #include "fatfs.h" #endif /*============================ MACROS ========================================*/ /*============================ MACRO FUNCTIONS ===============================*/ /*============================ TYPES =========================================*/ /*============================ GLOBAL VARIABLES ==============================*/ /*============================ LOCAL VARIABLES ===============================*/ static uint8_t exit_cmd_mode = 0; #ifndef CONFIG_WIFI_MANAGEMENT_TASK static uint8_t ap_dhcpd_started = 0; #endif /*============================ PROTOTYPES ====================================*/ extern void cmd_ping(int argc, char **argv); extern void cmd_tcp(int argc, char **argv); extern void cmd_udp(int argc, char **argv); extern err_t igmp_joingroup(const ip4_addr_t *ifaddr, const ip4_addr_t *groupaddr); #ifdef CONFIG_IPERF_TEST extern void cmd_iperf3(int argc, char **argv); #endif #ifdef CONFIG_SSL_TEST extern void cmd_ssl_client(int argc, char **argv); extern void cmd_ssl_selftest(int argc, char **argv); #endif static void cmd_help(int argc, char **argv); extern void dump_mem_block_list(void); /*============================ IMPLEMENTATION ================================*/ /*! \brief open wifi \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_open(int argc, char **argv) { if (!p_wifi_netlink->device_opened) { wifi_pmu_config(); wifi_rcu_config(); wifi_setting_config(); wifi_netlink_dev_open(); } else { DEBUGPRINT("wifi device had been opened!\r\n"); } #ifdef CONFIG_WIFI_MANAGEMENT_TASK if (eloop_event_send(ELOOP_EVENT_WAKEUP) != OS_OK) { wifi_management_start(); } #endif } /*! \brief close wifi \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_close(int argc, char **argv) { #ifdef CONFIG_WIFI_MANAGEMENT_TASK wifi_management_stop(); #endif if (p_wifi_netlink->device_opened) { wifi_netlink_dev_close(); /* wlan related clock disable */ wifi_clock_gate(); /* set PMU to power off wlan */ wifi_power_state_set(PMU_WIFI_SLEEP); } else { DEBUGPRINT("wifi device had been closed!\r\n"); } } /*! \brief show wifi scan information \param[in] scan_item: the pointer of WiFi scan information used in getting scan result \param[out] none \retval none */ static void scan_info_print(struct wifi_scan_info *scan_item) { DEBUGPRINT("----------------------------------------------------\r\n"); DEBUGPRINT("SSID: %s\r\n", &scan_item->ssid.ssid); DEBUGPRINT("Channel: %d\r\n", scan_item->channel); switch (scan_item->encryp_protocol) { case WIFI_ENCRYPT_PROTOCOL_OPENSYS: DEBUGPRINT("Security: Open\r\n"); break; case WIFI_ENCRYPT_PROTOCOL_WEP: DEBUGPRINT("Security: WEP\r\n"); break; case WIFI_ENCRYPT_PROTOCOL_WPA: DEBUGPRINT("Security: WPA\r\n"); break; case WIFI_ENCRYPT_PROTOCOL_WPA2: DEBUGPRINT("Security: WPA2\r\n"); break; case WIFI_ENCRYPT_PROTOCOL_WPA3_TRANSITION: DEBUGPRINT("Security: WPA2/WPA3\r\n"); break; case WIFI_ENCRYPT_PROTOCOL_WPA3_ONLY: DEBUGPRINT("Security: WPA3\r\n"); break; default: DEBUGPRINT("Security: Unknown\r\n"); break; } if (scan_item->network_mode == WIFI_NETWORK_MODE_INFRA) { DEBUGPRINT("Network: Infrastructure\r\n"); } else if (scan_item->network_mode == WIFI_NETWORK_MODE_ADHOC) { DEBUGPRINT("Network: Adhoc\r\n"); } else { DEBUGPRINT("Network: Unknown\r\n"); } // bitrate_print(scan_item->rate); DEBUGPRINT("Rate: %d Mbps\r\n", scan_item->rate); DEBUGPRINT("RSSI: %d dbm\r\n", scan_item->rssi); DEBUGPRINT("BSSID: "MAC_FMT"\r\n", MAC_ARG(scan_item->bssid_info.bssid)); DEBUGPRINT("\r\n"); } #ifdef CONFIG_WIFI_MANAGEMENT_TASK /*! \brief callback function after scan done \param[in] eloop_data: the pointer of related data after the loop has stopped \param[in] user_ctx: the pointer of user parameter \param[out] none \retval none */ void cmd_cb_scan_done(void *eloop_data, void *user_ctx) { DEBUGPRINT("[Scanned AP list]\r\n"); wifi_netlink_scan_list_get(scan_info_print); eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); } /*! \brief callback function after scan failed \param[in] eloop_data: the pointer of related data after the loop has stopped \param[in] user_ctx: the pointer of user parameter \param[out] none \retval none */ void cmd_cb_scan_fail(void *eloop_data, void *user_ctx) { DEBUGPRINT("WIFI_SCAN: failed\r\n"); eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); } #endif /*! \brief start wifi scan and show scan result \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_scan(int argc, char **argv) { #ifdef CONFIG_WIFI_MANAGEMENT_TASK eloop_event_register(WIFI_MGMT_EVENT_SCAN_DONE, cmd_cb_scan_done, NULL, NULL); eloop_event_register(WIFI_MGMT_EVENT_SCAN_FAIL, cmd_cb_scan_fail, NULL, NULL); if (wifi_management_scan(FALSE) != 0) { eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_DONE); eloop_event_unregister(WIFI_MGMT_EVENT_SCAN_FAIL); DEBUGPRINT("start wifi_scan failed\r\n"); } #else WIFI_MESSAGE_TYPE_E msg_type; int result = 0; sys_task_msg_flush(NULL); if (wifi_netlink_scan_set() != 1) { DEBUGPRINT("\rWIFI_SCAN: failed!\r\n"); return; } do { result = sys_task_wait(WIFI_SCAN_WAITING_TIME, &msg_type); if (result == OS_OK) { if (msg_type == WIFI_MESSAGE_NOTIFY_SCAN_RESULT_SUCC) { DEBUGPRINT("[Scanned AP list]\r\n"); wifi_netlink_scan_list_get(scan_info_print); break; } else if (msg_type == WIFI_MESSAGE_NOTIFY_SCAN_RESULT_FAIL) { break; } else { /* shell command or other messages, do nothing */ } } else { /* Waiting timeout */ break; } } while (1); #endif /* CONFIG_WIFI_MANAGEMENT_TASK */ } /*! \brief set wifi ip address \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_ip_set(int argc, char **argv) { ip4_addr_t ip, netmask, gw; if (argc > 4 || argc < 2) { DEBUGPRINT("wifi_set_ip: invalid input \r\n"); goto usage; } if (argc == 2) { if (strcmp(argv[1], "dhcp") == 0) { wifi_netif_set_ip_mode(IP_MODE_DHCP); return; } else { goto usage; } } else if (argc == 4) { ip4addr_aton((const char *)argv[1], &ip); ip4addr_aton((const char *)argv[2], &gw); ip4addr_aton((const char *)argv[3], &netmask); DEBUGPRINT("wifi_set_ip: set ip addr:%s, gate_way:%s, net_mask:%s \r\n", (char *)argv[1], (char *)argv[2],(char *)argv[3]); wifi_netif_set_ip(&ip, &netmask, &gw); wifi_netif_set_ip_mode(IP_MODE_STATIC); return; } else { goto usage; } usage: DEBUGPRINT("Usage: wifi_set_ip dhcp | \r\n"); DEBUGPRINT("\tdhcp: get ip from dhcp\r\n"); DEBUGPRINT("\tip_addr: ipv4 addr needded to set. eg: 192.168.0.123\r\n"); DEBUGPRINT("\tgate_way: eg: 192.168.0.1\r\n"); DEBUGPRINT("\tnet_mask: eg: 255.255.255.0\r\n"); } /*! \brief wifi connect to ap \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_connect(int argc, char **argv) { int status = 0; uint8_t *ssid; uint8_t *password; #ifndef CONFIG_WIFI_MANAGEMENT_TASK WIFI_MESSAGE_TYPE_E msg_type; #endif if(argc == 2) { ssid = (uint8_t *)argv[1]; password = NULL; } else if(argc == 3) { ssid = (uint8_t *)argv[1]; password = (uint8_t *)argv[2]; } else { DEBUGPRINT("\rUsage: wifi_connect SSID [PASSWORD]\r\n"); return; } #ifdef CONFIG_WIFI_MANAGEMENT_TASK status = wifi_management_connect(ssid, password, FALSE); if (status != 0) DEBUGPRINT("start wifi_connect failed\r\n"); #else if ((wifi_netlink_link_state_get() >= WIFI_NETLINK_STATUS_LINKED) || (wifi_netlink_link_state_get() == WIFI_NETLINK_STATUS_ROAMING)) { wifi_netlink_disconnect_req(); wifi_netif_stop_dhcp(); } if (ap_dhcpd_started) { stop_dhcpd_daemon(); ap_dhcpd_started = 0; } //connect req sys_task_msg_flush(NULL); status = wifi_netlink_connect_req(ssid, password); if (status != 0) return; do{ if (sys_task_wait(WIFI_CONNECT_WAITING_TIME, &msg_type) == OS_OK) { switch (msg_type) { case WIFI_MESSAGE_INDICATE_CONN_SUCCESS: wifi_netif_start_dhcp(); if (TRUE == wifi_netif_polling_dhcp()) { wifi_netlink_ipaddr_set((uint8_t *)wifi_netif_get_ip()); DEBUGPRINT("WIFI_CONNECT: ip configured, IP: %s\r\n", ip_ntoa(wifi_netif_get_ip())); } else { DEBUGPRINT("WIFI_CONNECT: get ip timeout!\r\n"); wifi_netif_stop_dhcp(); wifi_netlink_disconnect_req(); } status = 1; break; case WIFI_MESSAGE_INDICATE_CONN_NO_AP: case WIFI_MESSAGE_INDICATE_CONN_ASSOC_FAIL: case WIFI_MESSAGE_INDICATE_CONN_HANDSHAKE_FAIL: case WIFI_MESSAGE_INDICATE_CONN_FAIL: DEBUGPRINT("WIFI_CONNECT: connect failed, msg_type is %d!\r\n", msg_type); status = 1; break; case WIFI_MESSAGE_INDICATE_DISCON_RECV_DEAUTH: DEBUGPRINT("WIFI_CONNECT: connect failed, receive Deauth or Disassoc.\r\n"); status = 1; break; case WIFI_MESSAGE_INDICATE_DISCON_AP_CHANGED: DEBUGPRINT("WIFI_CONNECT: connect failed, AP has changed, please scan again!\r\n"); status = 1; break; case WIFI_MESSAGE_SHELL_COMMAND: default: break; } }else{ DEBUGPRINT("WIFI_CONNECT: connect timeout or error\r\n"); break; } } while(!status); #endif } /*! \brief wifi disconnect from ap \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_disconnect(int argc, char **argv) { #ifdef CONFIG_WIFI_MANAGEMENT_TASK if (wifi_management_disconnect() != 0) DEBUGPRINT("start wifi_disconnect failed\r\n"); #else //disconnect req wifi_netlink_disconnect_req(); wifi_netif_stop_dhcp(); #endif } /*! \brief show wifi status \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_status(int argc, char **argv) { uint8_t *mac = wifi_netif_get_hwaddr(); uint8_t *ip = (uint8_t *)wifi_netif_get_ip(); uint8_t *gw = (uint8_t *)wifi_netif_get_gw(); wifi_netlink_status_get(); DEBUGPRINT("\rNetwork Interface Status\r\n"); DEBUGPRINT("==============================\r\n"); DEBUGPRINT("\rMAC: [%02x:%02x:%02x:%02x:%02x:%02x]\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); DEBUGPRINT("\rIP: [%d.%d.%d.%d]\r\n", ip[0], ip[1], ip[2], ip[3]); DEBUGPRINT("\rGW: [%d.%d.%d.%d]\r\n", gw[0], gw[1], gw[2], gw[3]); #ifdef CONFIG_IPV6_SUPPORT if (!p_wifi_netlink->ap_started) { ip6_addr_t *ip6_local = (ip6_addr_t *)wifi_netif_get_ip6(0); ip6_addr_t *ip6_uniqe = (ip6_addr_t *)wifi_netif_get_ip6(1); DEBUGPRINT("\rIP6_local: [%s]\r\n", ip6addr_ntoa(ip6_local)); DEBUGPRINT("\rIP6_uniqe: [%s]\r\n", ip6addr_ntoa(ip6_uniqe)); } #endif } /*! \brief show wifi signal strength \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_rssi(int argc, char **argv) { int rssi; rssi = wifi_netlink_bss_rssi_get(); if (rssi < 0) { DEBUGPRINT("wifi rssi: current AP RSSI is %d dbm\r\n", rssi); } else { DEBUGPRINT("wifi rssi: wifi is not connected!\r\n"); } } /*! \brief set wifi channel \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_channel_set(int argc, char **argv) { char *endptr = NULL; uint32_t channel = 0; uint32_t bandwidth = CHANNEL_WIDTH_20; uint32_t ch_offset = HT_SEC_CHNL_OFFSET_NONE; if (!p_wifi_netlink->device_opened) { DEBUGPRINT("wifi device is closed! please use 'wifi_open' to open device\r\n"); return; } if (argc >= 4) { ch_offset = (uint32_t)strtoul((const char *)argv[3], &endptr, 10); if (*endptr != '\0' || !((ch_offset == HT_SEC_CHNL_OFFSET_ABOVE) || (ch_offset == HT_SEC_CHNL_OFFSET_BELOW))) { DEBUGPRINT("wifi_set_channel: invalid channel offset\r\n"); goto usage; } } if (argc >= 3) { bandwidth = (uint32_t)strtoul((const char *)argv[2], &endptr, 10); if (*endptr != '\0') { DEBUGPRINT("wifi_set_channel: invalid channel bandwidth\r\n"); goto usage; } } if (argc >= 2) { channel = (uint32_t)strtoul((const char *)argv[1], &endptr, 10); if (*endptr == '\0') { if (bandwidth == 1) { if ((channel <= 4 && ch_offset == HT_SEC_CHNL_OFFSET_BELOW) || (channel <= 14 && channel >= 11 && ch_offset == HT_SEC_CHNL_OFFSET_ABOVE)) { DEBUGPRINT("wifi_set_channel: channel 1-4 can't set 2nd channel below, channel 11-14 can't set 2nd channel above\r\n"); goto usage; } } wifi_netlink_channel_set(channel, bandwidth, ch_offset); return; } else { DEBUGPRINT("wifi_set_channel: invalid channel\r\n"); } } usage: DEBUGPRINT("Usage: wifi_set_channel [bandwidth] [offset]\r\n"); DEBUGPRINT("\tchannel: 1 - 14\r\n"); DEBUGPRINT("\tbandwidth: 0: 20M, 1: 40M, default 0\r\n"); DEBUGPRINT("\toffset: 1: 2nd channel above, 3: 2nd channel below (only use for 40M, 20M will ignore)\r\n"); } /*! \brief set wifi mac address \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_mac_addr(int argc, char **argv) { uint8_t macaddr[9]; /* reserve 3 more bytes to buffer the overflow */ uint32_t num; if (argc < 2) { DEBUGPRINT("Device MAC address: "MAC_FMT"\r\n", MAC_ARG(wifi_netif_get_hwaddr())); return; } num = sscanf(argv[1], "%02x:%02x:%02x:%02x:%02x:%02x", (uint32_t *)&macaddr[0], (uint32_t *)&macaddr[1], (uint32_t *)&macaddr[2], (uint32_t *)&macaddr[3], (uint32_t *)&macaddr[4], (uint32_t *)&macaddr[5]); if (num == 6) { if (wifi_netif_set_hwaddr(macaddr)) { DEBUGPRINT("Set device MAC address: "MAC_FMT"\r\n", MAC_ARG(macaddr)); } } else { DEBUGPRINT("Usage: wifi_mac_addr \r\n"); DEBUGPRINT("\tMAC address should be like 11:22:33:aa:bb:cc\r\n"); } } /*! \brief configure wifi power save mode \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_ps(int argc, char **argv) { char *endptr = NULL; uint32_t ps_enable = 1; if (argc >= 2) { ps_enable = (uint32_t)strtoul((const char *)argv[1], &endptr, 0); if (*endptr != '\0' || ps_enable > 2) { goto usage; } } else { DEBUGPRINT("Current ps mode: %d\r\n", wifi_netlink_ps_get()); goto usage; } wifi_netlink_ps_set(ps_enable); if (ps_enable) { DEBUGPRINT("wifi_ps: power save enabled!\r\n"); } else { DEBUGPRINT("wifi_ps: power save disabled!\r\n"); } return; usage: DEBUGPRINT("Usage: wifi_ps <0, 1 or 2>\r\n"); DEBUGPRINT("\t0: Wifi not sleep and CPU not sleep\r\n"); DEBUGPRINT("\t1: WiFi in sleep and CPU not sleep\r\n"); DEBUGPRINT("\t2: WiFi in sleep and CPU in deep sleep\r\n"); } /*! \brief configure wifi as AP \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_ap(int argc, char **argv) { #ifndef CONFIG_WIFI_MANAGEMENT_TASK ip_addr_t ipaddr; ip_addr_t netmask; ip_addr_t gw; #endif char *ssid = NULL; char *passwd = NULL; uint8_t channel = 0; if (!p_wifi_netlink->device_opened) { DEBUGPRINT("wifi device is closed! please use 'wifi_open' to open device\r\n"); return; } if (argc == 4) { ssid = argv[1]; passwd = argv[2]; if (strlen(ssid) > WIFI_SSID_MAX_LEN || strlen(passwd) > WPA_MAX_PSK_LEN || strlen(passwd) < WPA_MIN_PSK_LEN) goto usage; channel = atoi(argv[3]) & 0xFF; if (channel > 13 || channel < 1) goto usage; } else { goto usage; } #ifdef CONFIG_WIFI_MANAGEMENT_TASK wifi_management_ap_start(ssid, passwd, channel, 0); #else wifi_netif_stop_dhcp(); wifi_netlink_ap_start(ssid, passwd, channel, 0); CONFIG_IP4_ADDR(&ipaddr); CONFIG_IP4_ADDR_NM(&netmask); CONFIG_IP4_ADDR_GW(&gw); wifi_netif_set_addr(&ipaddr, &netmask, &gw); if (!ap_dhcpd_started) { dhcpd_daemon(); ap_dhcpd_started = 1; } wifi_netif_set_up(); #endif return; usage: DEBUGPRINT("Usage: wifi_ap \r\n"); DEBUGPRINT(": The length should be less than 32.\r\n"); DEBUGPRINT(": The length should be between 8 and 63.\r\n"); DEBUGPRINT(": 1~13.\r\n"); } /*! \brief advanced settings for WiFi in AP mode \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_ap_adv(int argc, char **argv) { char *ssid = NULL; char *passwd = NULL; #ifndef CONFIG_WIFI_MANAGEMENT_TASK ip_addr_t ipaddr; ip_addr_t netmask; ip_addr_t gw; int ssid_len = 0, psk_len = 0; #endif uint8_t channel = 1, is_hidden = 0; if (!p_wifi_netlink->device_opened) { DEBUGPRINT("wifi device is closed! please use 'wifi_open' to open device\r\n"); return; } if (argc == 2) { ssid = argv[1]; if (strlen(ssid) > WIFI_SSID_MAX_LEN) goto usage; } else if (argc == 3) { ssid = argv[1]; passwd = argv[2]; if (strlen(ssid) > WIFI_SSID_MAX_LEN || strlen(passwd) > WPA_MAX_PSK_LEN || strlen(passwd) < WPA_MIN_PSK_LEN) goto usage; } else if (argc == 4) { ssid = argv[1]; passwd = argv[2]; channel = atoi(argv[3]); if (strlen(ssid) > WIFI_SSID_MAX_LEN || strlen(passwd) > WPA_MAX_PSK_LEN || strlen(passwd) < WPA_MIN_PSK_LEN || channel > 13 || channel < 1) goto usage; } else if (argc == 5) { ssid = argv[1]; passwd = argv[2]; channel = atoi(argv[3]); is_hidden = atoi(argv[4]); if (strlen(ssid) > WIFI_SSID_MAX_LEN || strlen(passwd) > WPA_MAX_PSK_LEN || strlen(passwd) < WPA_MIN_PSK_LEN || channel > 13 || channel < 1 || (1 != is_hidden && 0 != is_hidden)) goto usage; } else { goto usage; } #ifdef CONFIG_WIFI_MANAGEMENT_TASK wifi_management_ap_start(ssid, passwd, channel, is_hidden); #else wifi_netif_stop_dhcp(); wifi_netlink_ap_start(ssid, passwd, channel, is_hidden); CONFIG_IP4_ADDR(&ipaddr); CONFIG_IP4_ADDR_NM(&netmask); CONFIG_IP4_ADDR_GW(&gw); wifi_netif_set_addr(&ipaddr, &netmask, &gw); if (!ap_dhcpd_started) { dhcpd_daemon(); ap_dhcpd_started = 1; } wifi_netif_set_up(); #endif return; usage: DEBUGPRINT("Usage: wifi_ap_adv [PASSWORD] [CHANNEL] [HIDDEN]\r\n"); DEBUGPRINT(": len <= 32\r\n"); DEBUGPRINT("[PASSWORD]: len >= 8 && len <= 63\r\n"); DEBUGPRINT("[CHANNEL]: 1~13\r\n"); DEBUGPRINT("[HIDDEN]: 0 or 1\r\n"); } /*! \brief stop wifi ap mode \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_wifi_ap_stop(int argc, char **argv) { #ifdef CONFIG_WIFI_MANAGEMENT_TASK wifi_management_sta_start(); #else if (p_wifi_netlink->ap_started){ /* Stop DHCPD */ if (ap_dhcpd_started) { stop_dhcpd_daemon(); ap_dhcpd_started = 0; } wifi_netlink_dev_close(); wifi_netlink_dev_open(); } #endif } /*! \brief show memory usage \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ void cmd_mem_status(int argc, char **argv) { uint8_t i; DEBUGPRINT("\rHeap Information\r\n"); DEBUGPRINT("==================================\r\n"); DEBUGPRINT("\rheap status: total free heap size = %d\r\n", sys_free_heap_size()); DEBUGPRINT("\rheap status: total min free heap size = %d\r\n", sys_min_free_heap_size()); DEBUGPRINT("Task Stack Information\r\n"); DEBUGPRINT("==================================\r\n"); DEBUGPRINT("\ros idle task: free stack = %d\r\n", sys_stack_free_get(sys_idle_task_handle_get())); DEBUGPRINT("\ros timer task: free stack = %d\r\n", sys_stack_free_get(sys_timer_task_handle_get())); DEBUGPRINT("\rconsole task: free stack = %d\r\n", sys_stack_free_get(&console_task_tcb)); for (i = 0; i < LWIP_TASK_MAX; i++) { DEBUGPRINT("\rlwip task %d: free stack = %d\r\n", i, sys_stack_free_get(&lwip_task_tcb[i])); } wifi_netlink_task_stack_get(); #ifdef CONFIG_GAGENT_TEST DEBUGPRINT("\rgagent test task: free stack = %d\r\n", sys_stack_free_get(&gagent_task_tcb)); #endif DEBUGPRINT("\r\n"); DEBUGPRINT("\r\n\rMemory List\r\n"); DEBUGPRINT("==================================\r\n"); dump_mem_block_list(); } #ifdef CONFIG_JOIN_GROUP_SUPPORT static void join_group_task_func(void *param) { ip4_addr_t group_ip; char *ip_addr = (char *)param; if (inet_aton(ip_addr, (struct in_addr*)&group_ip) == 0) { DEBUGPRINT("\rCan not join group because of group IP error\r\n"); goto exit; } if (wifi_netif_is_ip_got()) { igmp_joingroup((const ip4_addr_t *)wifi_netif_get_ip(), (const ip4_addr_t *)&group_ip); } else { DEBUGPRINT("\rCan not join group because DHCP IP not got\r\n"); } exit: sys_task_delete(NULL); } /*! \brief join group \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_group_join(int argc, char **argv) { void *handle; if (argc == 2) { handle = sys_task_create(NULL, (const uint8_t *)"join_group_task", NULL, JOIN_GROUP_STACK_SIZE, 0, JOIN_GROUP_TASK_PRIO, (task_func_t)join_group_task_func, (void *)argv[1]); if (handle == NULL) { DEBUGPRINT("ERROR: create join group task failed.\r\n"); return; } } else { DEBUGPRINT("\rUsage: join_group MulticastIP\r\n"); } } #endif /*! \brief restart system \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_reboot(int argc, char **argv) { if (p_wifi_netlink->device_opened) { /* clock: wlan disable, wlan run disable */ wifi_clock_gate(); /* set PMU to power off wlan */ wifi_power_state_set(PMU_WIFI_SLEEP); } NVIC_SystemReset(); } /*! \brief iperf2 test \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_iperf2(int argc, char **argv) { int i; if(argc >= 2){ if (strcmp(argv[1], "-h") == 0) { goto Usage; } } else { goto Exit; } for (i = 2; i < argc; i++) { if (strcmp(argv[i], "-u") == 0) { cmd_udp(argc, argv); return; } } cmd_tcp(argc, argv); return; Exit: DEBUGPRINT("\r\nIperf2: command format error!\r\n"); Usage: DEBUGPRINT("\rUsage:\r\n"); DEBUGPRINT(" iperf <-s|-c hostip|exit|-h> [options]\r\n"); DEBUGPRINT("\rClient/Server:\r\n"); DEBUGPRINT(" -u # use UDP rather than TCP\r\n"); DEBUGPRINT(" -i # seconds between periodic bandwidth reports\r\n"); DEBUGPRINT(" -l # length of buffer to read or write (default 1460 Bytes)\r\n"); DEBUGPRINT(" -p # server port to listen on/connect to (default 5001)\r\n"); //DEBUGPRINT(" -N set TCP no delay, disabling Nagle's Algorithm\r\n"); DEBUGPRINT("\rServer specific:\r\n"); DEBUGPRINT(" -s run in server mode\r\n"); DEBUGPRINT("\rClient specific:\r\n"); DEBUGPRINT(" -b # bandwidth to send at in bits/sec (default 1 Mbit/sec, implies -u)\r\n"); DEBUGPRINT(" -S # set the IP 'type of service'\r\n"); DEBUGPRINT(" -c run in client mode, connecting to \r\n"); //DEBUGPRINT(" -d Do a bidirectional test simultaneously\r\n"); //DEBUGPRINT(" -n # number of bytes to transmit for (default not use)\r\n"); DEBUGPRINT(" -t # time in seconds to transmit for (default 10 secs)\r\n"); } /*! \brief exit command test mode \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_exit(int argc, char **argv) { DEBUGPRINT("\rLEAVE COMMAND TEST MODE\r\n"); exit_cmd_mode = 1; } #ifdef CONFIG_FATFS_SUPPORT /*! \brief fatfs related operation \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ void cmd_fatfs (int argc, char **argv) { if(argc >= 2 && argc <= 4){ if (cmd_fatfs_exec(argc, argv) == 0) return; } DEBUGPRINT("\r\nUsage:\r\n"); DEBUGPRINT(" fatfs create (path should end with \\ or /)\r\n"); DEBUGPRINT(" fatfs append \r\n"); DEBUGPRINT(" fatfs read [length]\r\n"); DEBUGPRINT(" fatfs delete \r\n"); DEBUGPRINT(" fatfs show [dir]\r\n"); DEBUGPRINT(" Example: fatfs creat a/b/c/d/ | fatfs creat a/b/c/d.txt\r\n"); } #endif /*! \brief set bw to support 20MHz only or 20/40MHz \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_bw_set(int argc, char **argv) { char *endptr = NULL; uint32_t cmd_bw = CHANNEL_WIDTH_20, cur_bw = 0, connected_bw = 0; int status = 0; if (!p_wifi_netlink->device_opened) { DEBUGPRINT("wifi device is closed! please use 'wifi_open' to open device\r\n"); return; } if (argc >= 3) { DEBUGPRINT("wifi_set_bw: command format error!\r\n"); goto Usage; } // get current supported bw status = wifi_netlink_bw_get(&cur_bw); if (status != 0) { DEBUGPRINT("ERROR: get current supported bandwidth failed\r\n"); goto Usage; } if(argc == 2) { cmd_bw = (uint32_t)strtoul((const char *)argv[1], &endptr, 10); if (*endptr != '\0' || (cmd_bw != CHANNEL_WIDTH_20 && cmd_bw != CHANNEL_WIDTH_40)) { DEBUGPRINT("wifi_set_bw: invalid bandwidth\r\n"); goto Usage; } if (cmd_bw == cur_bw) { DEBUGPRINT("No need to modify the supported bandwidth.\r\n"); return; } if (wifi_netlink_link_state_get() >= WIFI_NETLINK_STATUS_LINKED) { connected_bw = p_wifi_netlink->connected_ap_info.bw; if ((cmd_bw == connected_bw) && (connected_bw != cur_bw)) { status = wifi_netlink_bw_set(cmd_bw); if (status != 0) DEBUGPRINT("ERROR: wifi_set_bw failed\r\n"); return; } // reconnect wifi_management_disconnect(); status = wifi_netlink_bw_set(cmd_bw); if (status != 0) { DEBUGPRINT("ERROR: wifi_set_bw failed\r\n"); return; } if (WIFI_ENCRYPT_PROTOCOL_OPENSYS == p_wifi_netlink->connect_info.encryp_protocol) { status = wifi_management_connect(p_wifi_netlink->connect_info.ssid.ssid, NULL, FALSE); } else { status = wifi_management_connect(p_wifi_netlink->connect_info.ssid.ssid, p_wifi_netlink->connect_info.passwd, FALSE); } if (status != 0) DEBUGPRINT("start wifi_connect failed\r\n"); } else { status = wifi_netlink_bw_set(cmd_bw); if (status != 0) DEBUGPRINT("ERROR: wifi_set_bw failed\r\n"); } return; } else { switch (cur_bw) { case CHANNEL_WIDTH_20: DEBUGPRINT("\rBW: 20M\r\n"); break; case CHANNEL_WIDTH_40: DEBUGPRINT("\rBW: 40M\r\n"); break; case CHANNEL_WIDTH_80: DEBUGPRINT("\rBW: 80M\r\n"); break; case CHANNEL_WIDTH_160: DEBUGPRINT("\rBW: 160M\r\n"); break; case CHANNEL_WIDTH_80_80: DEBUGPRINT("\rBW: 80+80M\r\n"); break; default: DEBUGPRINT("\rBW: UnKnown\r\n"); break; } } Usage: DEBUGPRINT("\rUsage:\r\n"); DEBUGPRINT(" wifi_set_bw [0/1]\r\n"); DEBUGPRINT(" 0 # support 20MHz only\r\n"); DEBUGPRINT(" 1 # support 20/40MHz\r\n"); } typedef void (*img_fptr_t) (void); #define IMAGE_HEADER_SIZE 0 /*! \brief set bw to support 20MHz only or 20/40MHz \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_boot(int argc, char **argv) { static img_fptr_t img_reset; uint32_t arm_vector[2] = {0}; uint32_t boot_idx = 0, image_offset = 0, version; bRadioGoStandby(); if (argc > 2) { DEBUGPRINT("jump_bml: command format error!\r\n"); goto Usage; } /* Read the MSP and Reset_Handler of the main image */ flash_read((image_offset + IMAGE_HEADER_SIZE), arm_vector, 8); if (!is_valid_flash_addr(arm_vector[1])) { DEBUGPRINT("Error, image vector reset is invalid (%08x).\r\n", arm_vector[1]); goto BootFailed; } for (int i = 0; i < sizeof(NVIC->ICER) / 4; i++) NVIC->ICER[i] = ~(0UL); /* Jump to main image */ img_reset = (img_fptr_t)arm_vector[1]; #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) /* Restore the Main Stack Pointer Limit register's reset value * before passing execution to runtime firmware to make the * bootloader transparent to it. */ __set_MSPLIM(0); #endif __set_MSP(arm_vector[0]); __DSB(); __ISB(); img_reset(); BootFailed: DEBUGPRINT("\r[%s|%u] Jump to MBL failed.\r\n", __FUNCTION__, __LINE__); while(1); Usage: DEBUGPRINT("\rUsage:\r\n"); DEBUGPRINT(" jm [0/1]\r\n"); DEBUGPRINT(" 0 # dry run.\r\n"); DEBUGPRINT(" 1 # show the verbosity of messages.\r\n"); } static const cmd_entry cmd_table[] = { #ifdef CONFIG_BASECMD {"wifi_open", cmd_wifi_open}, {"wifi_close", cmd_wifi_close}, {"wifi_scan", cmd_wifi_scan}, {"wifi_set_ip", cmd_wifi_ip_set}, {"wifi_connect", cmd_wifi_connect}, {"wifi_disconnect", cmd_wifi_disconnect}, {"wifi_status", cmd_wifi_status}, {"wifi_rssi", cmd_wifi_rssi}, {"wifi_set_channel", cmd_wifi_channel_set}, {"wifi_mac_addr", cmd_wifi_mac_addr}, {"wifi_ps", cmd_wifi_ps}, {"wifi_ap", cmd_wifi_ap}, {"wifi_ap_adv", cmd_wifi_ap_adv}, {"wifi_stop_ap", cmd_wifi_ap_stop}, {"mem_status", cmd_mem_status}, {"ping", cmd_ping}, #ifdef CONFIG_JOIN_GROUP_SUPPORT {"join_group", cmd_group_join}, #endif #ifdef CONFIG_TELNET_SERVER {"telnet", cmd_telnet_server}, #endif #ifdef CONFIG_IPERF_TEST {"iperf", cmd_iperf2}, {"iperf3", cmd_iperf3}, #endif #ifdef CONFIG_SSL_TEST {"ssl_client", cmd_ssl_client}, {"ssl_selftest", cmd_ssl_selftest}, #endif #ifdef CONFIG_ALICLOUD_SUPPORT {"ali_cloud", cmd_alicloud_linkkit}, #endif {"exit", cmd_exit}, #if defined(CONFIG_ATCMD) {"AT", at_entry}, #endif #ifdef CONFIG_FATFS_SUPPORT {"fatfs", cmd_fatfs}, #endif {"wifi_set_bw", cmd_bw_set}, #endif {"reboot", cmd_reboot}, {"bootm", cmd_boot}, {"help", cmd_help} }; /*! \brief show help command list \param[in] argc: number of parameters \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval none */ static void cmd_help(int argc, char **argv) { int i; DEBUGPRINT("\rCOMMAND LIST:\r\n"); DEBUGPRINT("==============================\r\n"); for (i = 0; i < ARRAY_SIZE(cmd_table); i++) DEBUGPRINT(" %s\r\n", cmd_table[i].command); #ifdef CONFIG_RF_TEST_SUPPORT mp_cmd_help(); #endif #ifdef CONFIG_INTERNAL_DEBUG inner_cmd_help(); #endif } /*! \brief parse command \param[in] buf: the pointer to the buffer that holds commands \param[in] argv: the pointer to the array that holds the parameters \param[out] none \retval number of commands */ static int cmd_parse(char *buf, char **argv) { int argc = 0; while((argc < MAX_ARGC) && (*buf != '\0')) { argv[argc] = buf; argc ++; buf ++; while((*buf != ' ') && (*buf != '\0')) buf ++; while(*buf == ' ') { *buf = '\0'; buf ++; } // Don't replace space if(argc == 1){ if(strcmp(argv[0], "iwpriv") == 0){ if(*buf != '\0'){ argv[1] = buf; argc ++; } break; } } } return argc; } /*! \brief command handler \param[in] none \param[out] none \retval none */ void command_handler(void) { int i, argc; char *argv[MAX_ARGC]; extern char uart_buf[]; char local_uart_buf[UART_BUFFER_SIZE]; WIFI_MESSAGE_TYPE_E msg_type; exit_cmd_mode = 0; while (1) { while (1) { if (sys_task_wait(0, &msg_type) == OS_OK) { if (msg_type == WIFI_MESSAGE_SHELL_COMMAND) { sys_memcpy(local_uart_buf, uart_buf, UART_BUFFER_SIZE); uart_buf[0] = '\0'; DEBUGPRINT("\r\n"); break; } } else { DEBUGPRINT("command_handler: sys_task_wait error\n"); } } #ifdef CONFIG_ATCMD if (atcmd_mode_get()) { if ((argc = atcmd_parse(local_uart_buf, argv)) > 0) { int found = 0; for (i = 0; i < ARRAY_SIZE(atcmd_table); i++) { if ((strlen(argv[0]) == strlen(atcmd_table[i].command) || strlen(argv[0]) == (strlen(atcmd_table[i].command) + 1)) && (strncmp(argv[0], atcmd_table[i].command, strlen(atcmd_table[i].command)) == 0)) { atcmd_table[i].function(argc, argv); found = 1; break; } } if (!found) at_rsp_error(); } } else #endif { if ((argc = cmd_parse(local_uart_buf, argv)) > 0) { int found = 0; for (i = 0; i < ARRAY_SIZE(cmd_table); i++) { if (strcmp(argv[0], cmd_table[i].command) == 0) { cmd_table[i].function(argc, argv); found = 1; break; } } #ifdef CONFIG_RF_TEST_SUPPORT if (!found) { found = mp_cmd_handler(argc, argv); } #endif #ifdef CONFIG_INTERNAL_DEBUG if (!found) { found = inner_cmd_handler(argc, argv); } #endif if (!found) DEBUGPRINT("Unknown command '%s'\r\n", argv[0]); } DEBUGPRINT("# "); } if (exit_cmd_mode == 1) { break; } } } #endif /* defined(CONFIG_CONSOLE_ENABLE) */ #ifdef CONFIG_TELNET_SERVER void cmd_telnet_server(int argc, char **argv) { if (argc != 2) { goto exit; } if (strcmp(argv[1], "start") == 0) { telnet_server_start(); } else if (strcmp(argv[1], "stop") == 0) { telnet_server_stop(); } else { goto exit; } return; exit: DEBUGPRINT("Usage: telnet \r\n"); DEBUGPRINT("\tYou can use 'tenlet start' to start task or use 'tenlet stop' to stop task\r\n"); return; } #endif