/* * Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved. * * 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 XRADIO TECHNOLOGY CO., LTD. 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 * OWNER 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. */ #include #include #include "net/wlan/wlan.h" #include "net/wlan/wlan_defs.h" #include "common/framework/net_ctrl.h" #include "common/framework/platform_init.h" #include "common/framework/sysinfo.h" #include "common/cmd/cmd.h" #include "lwip/inet.h" #include "sys/fdcm.h" #include "sys/xr_debug.h" #include "util/time_logger.h" extern uint64_t HAL_RTC_GetFreeRunTime(void); extern void stdout_enable(uint8_t en); extern void dns_setserver(u8_t numdns, ip_addr_t *dnsserver); #define FC_DEBUG_EN 0 #if FC_DEBUG_EN #define FC_DEBUG(fmt, arg...) printf(fmt, ##arg) #else #define FC_DEBUG(fmt, arg...) #endif static uint8_t g_ap_connected; void net_msg_receiver(uint32_t event, uint32_t data, void *arg) { uint16_t type = EVENT_SUBTYPE(event); switch (type) { case NET_CTRL_MSG_WLAN_CONNECTED: break; case NET_CTRL_MSG_WLAN_DISCONNECTED: g_ap_connected = 0; wlan_sta_bss_flush(0); break; case NET_CTRL_MSG_WLAN_SCAN_SUCCESS: case NET_CTRL_MSG_WLAN_SCAN_FAILED: break; case NET_CTRL_MSG_WLAN_4WAY_HANDSHAKE_FAILED: case NET_CTRL_MSG_WLAN_CONNECT_FAILED: case NET_CTRL_MSG_WLAN_CONNECTION_LOSS: g_ap_connected = 0; break; case NET_CTRL_MSG_NETWORK_UP: g_ap_connected = 1; break; case NET_CTRL_MSG_NETWORK_DOWN: g_ap_connected = 0; break; default: printf("unknown msg (%u, %u)\n", type, data); break; } } int net_msg_rcv_init(void) { observer_base *ob = sys_callback_observer_create(CTRL_MSG_TYPE_NETWORK, NET_CTRL_MSG_ALL, net_msg_receiver, NULL); if (ob == NULL) return -1; if (sys_ctrl_attach(ob) != 0) return -1; return 0; } #define BSS_FLASH_NUM (0) #define BSS_FLASH_ADDR ((1024 + 128) * 1024) #define BSS_FLASH_SIZE (8*1024) #define FLAGS_BSS_USING_WPA3 HAL_BIT(0) typedef struct bss_info { uint8_t ssid[32]; uint8_t psk[32]; uint32_t bss_size; uint8_t bss[800]; uint8_t psk_ph[100]; uint32_t flags; } bss_info_t; bss_info_t g_bss_info; char sta_ssid[100]; char sta_psk[100]; void connect_ap(void) { printf("Wait for link up...\n"); printf("use this cmd to connect your ap with your own ssid and password:\n" "\t\"net fc config your_ssid your_password\"\n\t\"net fc enable\"\n"); while (!g_ap_connected) { OS_MSleep(10); } save_time((uint32_t)HAL_RTC_GetFreeRunTime(), 2); printf("Connect AP success!\n"); struct sysinfo *sysinfo = sysinfo_get(); if (sysinfo == NULL) { printf("sysinfo %p\n", sysinfo); return; } //Save IP info to flash struct netif *nif = wlan_netif_get(WLAN_MODE_NONE); sysinfo->sta_use_dhcp = 0; memcpy(&sysinfo->netif_sta_param.ip_addr, &nif->ip_addr, sizeof(ip_addr_t)); memcpy(&sysinfo->netif_sta_param.gateway, &nif->gw, sizeof(ip_addr_t)); memcpy(&sysinfo->netif_sta_param.net_mask, &nif->netmask, sizeof(ip_addr_t)); sysinfo_save(); } int save_bss_to_flash(bss_info_t *pbss_info) { int ret = 0; uint32_t size; wlan_sta_bss_info_t bss_get; wlan_sta_ap_t ap_info; fdcm_handle_t *bss_fdcm_hdl; if (!g_ap_connected) { printf("Please connect AP first!\n"); ret = -1; return ret; } //Try to get current bss info size ret = wlan_sta_get_bss_size(&size); if (ret != 0) { printf("Get current bss info size failed!\n"); return ret; } bss_get.size = size; bss_get.bss = malloc(size); //Try to get current bss info ret = wlan_sta_get_bss(&bss_get); if (ret != 0) { printf("Get current bss info failed!\n"); return ret; } //Gererate 32 bytes HEX psk, so that we don't need to calcute next time wlan_gen_psk_param_t param; if (strlen(sta_psk) == 64) { hex2bin(param.psk, sta_psk, 32); } else if (sta_psk[0] == '\0') { memset(param.psk, 0, sizeof(param.psk)); } else { param.ssid_len = strlen(sta_ssid); memcpy(param.ssid, sta_ssid, param.ssid_len); strlcpy(param.passphrase, sta_psk, sizeof(param.passphrase)); ret = wlan_sta_gen_psk(¶m); if (ret != 0) { printf("fail to generate psk\n"); ret = -1; return ret; } } //Try to get connected ap info ret = wlan_sta_ap_info(&ap_info); if (ret != 0) { printf("Get ap info failed!\n"); return ret; } FC_DEBUG("(%s)(%d)get ap_info flags: 0x%x\n", __func__, __LINE__, ap_info.status); //Save current bss info to flash memset(pbss_info, 0, sizeof(bss_info_t)); if (ap_info.status & WLAN_STA_AP_STATUS_USE_WPA3) pbss_info->flags |= FLAGS_BSS_USING_WPA3; else pbss_info->flags &= ~FLAGS_BSS_USING_WPA3; memcpy(pbss_info->ssid, sta_ssid, strlen(sta_ssid)); memcpy(pbss_info->psk, param.psk, 32); memcpy(pbss_info->psk_ph, sta_psk, 100); pbss_info->bss_size = size; memcpy(pbss_info->bss, bss_get.bss, size); bss_fdcm_hdl = fdcm_open(BSS_FLASH_NUM, BSS_FLASH_ADDR, BSS_FLASH_SIZE); if (bss_fdcm_hdl == NULL) { printf("fdcm open failed, hdl %p\n", bss_fdcm_hdl); ret = -1; return ret; } fdcm_write(bss_fdcm_hdl, pbss_info, sizeof(bss_info_t)); fdcm_close(bss_fdcm_hdl); free(bss_get.bss); printf("Save bss info done!\n"); return ret; } int clear_bss_in_flash(void) { int ret = 0; fdcm_handle_t *bss_fdcm_hdl; printf("Clear bss info in flash!\n"); memset(&g_bss_info, 0, sizeof(bss_info_t)); bss_fdcm_hdl = fdcm_open(BSS_FLASH_NUM, BSS_FLASH_ADDR, BSS_FLASH_SIZE); if (bss_fdcm_hdl == NULL) { printf("fdcm open failed, hdl %p\n", bss_fdcm_hdl); ret = -1; return ret; } fdcm_write(bss_fdcm_hdl, &g_bss_info, sizeof(bss_info_t)); fdcm_close(bss_fdcm_hdl); struct sysinfo *sysinfo = sysinfo_get(); if (sysinfo == NULL) { printf("sysinfo %p\n", sysinfo); ret = -1; return ret; } printf("Clear IP info inflash!\n"); sysinfo->sta_use_dhcp = 1; sysinfo_save(); return ret; } void connect_ap_normal(void) { connect_ap(); //Save new bss info to flash save_bss_to_flash(&g_bss_info); } void connect_ap_fast(bss_info_t *pbss_info) { char psk_buf[64]; char *p; int i; p = psk_buf; FC_DEBUG("Set old bss info!\n"); if (pbss_info->flags & FLAGS_BSS_USING_WPA3) { wlan_sta_config((uint8_t *)pbss_info->ssid, strlen((char *)pbss_info->ssid), (uint8_t *)pbss_info->psk_ph, WLAN_STA_CONF_FLAG_WPA3); } else if (pbss_info->psk_ph[0] == '\0') { /* for open AP */ wlan_sta_config((uint8_t *)pbss_info->ssid, strlen((char *)pbss_info->ssid), pbss_info->psk_ph, 0); } else { /* for wpa/wpa2 fast connect */ for (i = 0; i < 32; i++) { sprintf(p, "%02x", pbss_info->psk[i]); p += 2; } wlan_sta_config((uint8_t *)pbss_info->ssid, strlen((char *)pbss_info->ssid), (uint8_t *)psk_buf, 0); } FC_DEBUG("Try to connect AP\n"); wlan_sta_enable(); FC_DEBUG("Wait for link up...\n"); while (!g_ap_connected) { OS_MSleep(10); } save_time((uint32_t)HAL_RTC_GetFreeRunTime(), 2); //Fast connect AP success } int get_bss_from_flash(bss_info_t *pbss_info) { int ret; uint32_t size; wlan_sta_bss_info_t bss_set; fdcm_handle_t *bss_fdcm_hdl; bss_fdcm_hdl = fdcm_open(BSS_FLASH_NUM, BSS_FLASH_ADDR, BSS_FLASH_SIZE); if (bss_fdcm_hdl == NULL) { printf("fdcm open failed, hdl %p\n", bss_fdcm_hdl); ret = -1; return ret; } size = fdcm_read(bss_fdcm_hdl, pbss_info, sizeof(bss_info_t)); fdcm_close(bss_fdcm_hdl); if (size != sizeof(bss_info_t)) { printf("fdcm read failed, size %d\n", size); ret = -1; return ret; } if (pbss_info->bss_size == 0) { printf("empty bss info\n"); ret = -1; return ret; } FC_DEBUG("SSID:%s\n", pbss_info->ssid); FC_DEBUG("FLAGS:0x%x\n", pbss_info->flags); FC_DEBUG("PSK_PHRASE:%s\n", pbss_info->psk_ph); FC_DEBUG("PSK:"); for (int i = 1; i < 33; ++i) FC_DEBUG("%02x", pbss_info->psk[i-1]); FC_DEBUG("\n"); FC_DEBUG("BSS size:%d\n", pbss_info->bss_size); FC_DEBUG("Set current bss info!\n"); bss_set.size = pbss_info->bss_size; bss_set.bss = malloc(bss_set.size); memcpy(bss_set.bss, pbss_info->bss, bss_set.size); ret = wlan_sta_set_bss(&bss_set); free(bss_set.bss); return ret; } void fast_connect_example(void) { FC_DEBUG("Init wlan message receiver\n"); net_msg_rcv_init(); FC_DEBUG("Begin fast connect example\n"); FC_DEBUG("Try to get old bss info in flash...\n"); if (get_bss_from_flash(&g_bss_info)) { #if !FC_DEBUG_EN stdout_enable(1); #endif printf("Get old bss failed!\n"); printf("Begin normal connection\n"); connect_ap_normal(); printf("The first connection is complete, please reboot to run fast connection!\n"); } else { FC_DEBUG("Get old bss info success!\n"); FC_DEBUG("Begin fast connection\n"); connect_ap_fast(&g_bss_info); #if !FC_DEBUG_EN stdout_enable(1); #endif } } #if defined(CONFIG_LWIP_VER_2_0_3) static inline void _ip_addr_set_ip4_u32(ip_addr_t *ipaddr, uint32_t value) { ip_addr_set_ip4_u32(ipaddr, value); } #endif int main(void) { uint32_t time_eob, time_eop; time_eob = (uint32_t)HAL_RTC_GetFreeRunTime(); #if !FC_DEBUG_EN stdout_enable(0); #endif platform_init(); time_eop = (uint32_t)HAL_RTC_GetFreeRunTime(); save_time(time_eob, 0); save_time(time_eop, 1); fast_connect_example(); get_time(); ip_addr_t dnsserver; #if defined(CONFIG_LWIP_VER_1_4_1) ip4_addr_set_u32(&dnsserver, ipaddr_addr("180.76.76.76")); #elif defined(CONFIG_LWIP_VER_2_0_3) _ip_addr_set_ip4_u32(&dnsserver, ipaddr_addr("180.76.76.76")); #else ip_addr_set_ip4_u32_val(dnsserver, ipaddr_addr("180.76.76.76")); #endif dns_setserver(0, &dnsserver); printf("Try to ping www.baidu.com\n"); cmd_ping_exec("www.baidu.com"); return 0; }