10a7ce71fSopenharmony_ci/*
20a7ce71fSopenharmony_ci * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
30a7ce71fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
40a7ce71fSopenharmony_ci * you may not use this file except in compliance with the License.
50a7ce71fSopenharmony_ci * You may obtain a copy of the License at
60a7ce71fSopenharmony_ci *
70a7ce71fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
80a7ce71fSopenharmony_ci *
90a7ce71fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
100a7ce71fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
110a7ce71fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120a7ce71fSopenharmony_ci * See the License for the specific language governing permissions and
130a7ce71fSopenharmony_ci * limitations under the License.
140a7ce71fSopenharmony_ci */
150a7ce71fSopenharmony_ci
160a7ce71fSopenharmony_ci// < this demo make the wifi to connect to the specified AP
170a7ce71fSopenharmony_ci#include <unistd.h>
180a7ce71fSopenharmony_ci#include <hi_wifi_api.h>
190a7ce71fSopenharmony_ci#include <lwip/ip_addr.h>
200a7ce71fSopenharmony_ci#include <lwip/netifapi.h>
210a7ce71fSopenharmony_ci#include <hi_types_base.h>
220a7ce71fSopenharmony_ci#include <hi_task.h>
230a7ce71fSopenharmony_ci#include <hi_mem.h>
240a7ce71fSopenharmony_ci#include "iot_config.h"
250a7ce71fSopenharmony_ci#include "iot_log.h"
260a7ce71fSopenharmony_ci#include "wifi_device.h"
270a7ce71fSopenharmony_ci#include "cmsis_os2.h"
280a7ce71fSopenharmony_ci#include "wifi_device_config.h"
290a7ce71fSopenharmony_ci#include "lwip/api_shell.h"
300a7ce71fSopenharmony_ci
310a7ce71fSopenharmony_ci#define APP_INIT_VAP_NUM    2
320a7ce71fSopenharmony_ci#define APP_INIT_USR_NUM    2
330a7ce71fSopenharmony_ci
340a7ce71fSopenharmony_cistatic struct netif *gLwipNetif = NULL;
350a7ce71fSopenharmony_cistatic hi_bool  gScanDone = HI_FALSE;
360a7ce71fSopenharmony_ciunsigned char wifiStatus = 0;
370a7ce71fSopenharmony_ci
380a7ce71fSopenharmony_ciunsigned char wifiFirstConnecting = 0;
390a7ce71fSopenharmony_ciunsigned char wifiSecondConnecting = 0;
400a7ce71fSopenharmony_ciunsigned char wifiSecondConnected = 0;
410a7ce71fSopenharmony_cistatic struct netif* g_iface = NULL;
420a7ce71fSopenharmony_civoid WifiStopSta(int netId);
430a7ce71fSopenharmony_cistatic int WifiStartSta(void);
440a7ce71fSopenharmony_ciint cnetId = -1;
450a7ce71fSopenharmony_ciint g_connected = 0;
460a7ce71fSopenharmony_ci
470a7ce71fSopenharmony_ci#define WIFI_CONNECT_STATUS ((unsigned char)0x02)
480a7ce71fSopenharmony_ci
490a7ce71fSopenharmony_civoid wifiReconnected(int netId)
500a7ce71fSopenharmony_ci{
510a7ce71fSopenharmony_ci    int recnetId = netId;
520a7ce71fSopenharmony_ci    if (wifiFirstConnecting == WIFI_CONNECT_STATUS) {
530a7ce71fSopenharmony_ci        wifiSecondConnecting = HI_TRUE;
540a7ce71fSopenharmony_ci        wifiFirstConnecting = HI_FALSE;
550a7ce71fSopenharmony_ci        WifiStopSta(recnetId);
560a7ce71fSopenharmony_ci        ip4_addr_t ipAddr;
570a7ce71fSopenharmony_ci        ip4_addr_t ipAny;
580a7ce71fSopenharmony_ci        IP4_ADDR(&ipAny, 0, 0, 0, 0);
590a7ce71fSopenharmony_ci        IP4_ADDR(&ipAddr, 0, 0, 0, 0);
600a7ce71fSopenharmony_ci        recnetId = WifiStartSta();
610a7ce71fSopenharmony_ci        netifapi_dhcp_start(gLwipNetif);
620a7ce71fSopenharmony_ci        while (0 == memcmp(&ipAddr, &ipAny, sizeof(ip4_addr_t))) {
630a7ce71fSopenharmony_ci            IOT_LOG_DEBUG("<Wifi reconnecting>:Wait the DHCP READY");
640a7ce71fSopenharmony_ci            netifapi_netif_get_addr(gLwipNetif, &ipAddr, NULL, NULL);
650a7ce71fSopenharmony_ci            hi_sleep(1000); /* 1000: cpu sleep 1000 ms */
660a7ce71fSopenharmony_ci        }
670a7ce71fSopenharmony_ci        wifiSecondConnected = HI_FALSE;
680a7ce71fSopenharmony_ci        wifiFirstConnecting = WIFI_CONNECT_STATUS;
690a7ce71fSopenharmony_ci        wifiStatus = HI_WIFI_EVT_CONNECTED;
700a7ce71fSopenharmony_ci    }
710a7ce71fSopenharmony_ci}
720a7ce71fSopenharmony_ci/* clear netif's ip, gateway and netmask */
730a7ce71fSopenharmony_cistatic void StaResetAddr(struct netif *lwipNetif)
740a7ce71fSopenharmony_ci{
750a7ce71fSopenharmony_ci    ip4_addr_t st_gw;
760a7ce71fSopenharmony_ci    ip4_addr_t st_ipaddr;
770a7ce71fSopenharmony_ci    ip4_addr_t st_netmask;
780a7ce71fSopenharmony_ci
790a7ce71fSopenharmony_ci    if (lwipNetif == NULL) {
800a7ce71fSopenharmony_ci        IOT_LOG_ERROR("hisi_reset_addr::Null param of netdev");
810a7ce71fSopenharmony_ci        return;
820a7ce71fSopenharmony_ci    }
830a7ce71fSopenharmony_ci
840a7ce71fSopenharmony_ci    IP4_ADDR(&st_gw, 0, 0, 0, 0);
850a7ce71fSopenharmony_ci    IP4_ADDR(&st_ipaddr, 0, 0, 0, 0);
860a7ce71fSopenharmony_ci    IP4_ADDR(&st_netmask, 0, 0, 0, 0);
870a7ce71fSopenharmony_ci
880a7ce71fSopenharmony_ci    netifapi_netif_set_addr(lwipNetif, &st_ipaddr, &st_netmask, &st_gw);
890a7ce71fSopenharmony_ci}
900a7ce71fSopenharmony_ci
910a7ce71fSopenharmony_cistatic void WpaEventCB(const hi_wifi_event *hisiEvent)
920a7ce71fSopenharmony_ci{
930a7ce71fSopenharmony_ci    if (hisiEvent == NULL)
940a7ce71fSopenharmony_ci        return;
950a7ce71fSopenharmony_ci    IOT_LOG_DEBUG("EVENT_TYPE:%d", hisiEvent->event);
960a7ce71fSopenharmony_ci    switch (hisiEvent->event) {
970a7ce71fSopenharmony_ci        case HI_WIFI_EVT_SCAN_DONE:
980a7ce71fSopenharmony_ci            IOT_LOG_DEBUG("WiFi: Scan results available");
990a7ce71fSopenharmony_ci            gScanDone = HI_TRUE;
1000a7ce71fSopenharmony_ci            break;
1010a7ce71fSopenharmony_ci        case HI_WIFI_EVT_CONNECTED:
1020a7ce71fSopenharmony_ci            IOT_LOG_DEBUG("WiFi: Connected");
1030a7ce71fSopenharmony_ci            netifapi_dhcp_start(gLwipNetif);
1040a7ce71fSopenharmony_ci            wifiStatus = HI_WIFI_EVT_CONNECTED;
1050a7ce71fSopenharmony_ci            if (wifiSecondConnected) {
1060a7ce71fSopenharmony_ci                wifiSecondConnected = HI_FALSE;
1070a7ce71fSopenharmony_ci                wifiFirstConnecting = WIFI_CONNECT_STATUS;
1080a7ce71fSopenharmony_ci            }
1090a7ce71fSopenharmony_ci            break;
1100a7ce71fSopenharmony_ci        case HI_WIFI_EVT_DISCONNECTED:
1110a7ce71fSopenharmony_ci            IOT_LOG_DEBUG("WiFi: Disconnected");
1120a7ce71fSopenharmony_ci            netifapi_dhcp_stop(gLwipNetif);
1130a7ce71fSopenharmony_ci            StaResetAddr(gLwipNetif);
1140a7ce71fSopenharmony_ci            wifiStatus = HI_WIFI_EVT_DISCONNECTED;
1150a7ce71fSopenharmony_ci            wifiReconnected(cnetId);
1160a7ce71fSopenharmony_ci            break;
1170a7ce71fSopenharmony_ci        case HI_WIFI_EVT_WPS_TIMEOUT:
1180a7ce71fSopenharmony_ci            IOT_LOG_DEBUG("WiFi: wps is timeout");
1190a7ce71fSopenharmony_ci            wifiStatus = HI_WIFI_EVT_WPS_TIMEOUT;
1200a7ce71fSopenharmony_ci            break;
1210a7ce71fSopenharmony_ci        default:
1220a7ce71fSopenharmony_ci            break;
1230a7ce71fSopenharmony_ci    }
1240a7ce71fSopenharmony_ci}
1250a7ce71fSopenharmony_ci
1260a7ce71fSopenharmony_cistatic int StaStartConnect(void)
1270a7ce71fSopenharmony_ci{
1280a7ce71fSopenharmony_ci    int ret;
1290a7ce71fSopenharmony_ci    errno_t rc;
1300a7ce71fSopenharmony_ci    hi_wifi_assoc_request assoc_req = {0};
1310a7ce71fSopenharmony_ci
1320a7ce71fSopenharmony_ci    /* copy SSID to assoc_req */
1330a7ce71fSopenharmony_ci    rc = memcpy_s(assoc_req.ssid, HI_WIFI_MAX_SSID_LEN + 1, CONFIG_AP_SSID, strlen(CONFIG_AP_SSID));
1340a7ce71fSopenharmony_ci    if (rc != EOK) {
1350a7ce71fSopenharmony_ci        return -1;
1360a7ce71fSopenharmony_ci    }
1370a7ce71fSopenharmony_ci
1380a7ce71fSopenharmony_ci    /*
1390a7ce71fSopenharmony_ci     * OPEN mode
1400a7ce71fSopenharmony_ci     * for WPA2-PSK mode:
1410a7ce71fSopenharmony_ci     * set assoc_req.auth as HI_WIFI_SECURITY_WPA2PSK,
1420a7ce71fSopenharmony_ci     * then memcpy(assoc_req.key, "12345678", 8).
1430a7ce71fSopenharmony_ci     */
1440a7ce71fSopenharmony_ci    assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK;
1450a7ce71fSopenharmony_ci    rc = memcpy_s(assoc_req.key, HI_WIFI_MAX_KEY_LEN + 1, CONFIG_AP_PWD, strlen(CONFIG_AP_PWD));
1460a7ce71fSopenharmony_ci    if (rc != EOK) {
1470a7ce71fSopenharmony_ci        return -1;
1480a7ce71fSopenharmony_ci    }
1490a7ce71fSopenharmony_ci
1500a7ce71fSopenharmony_ci    ret = hi_wifi_sta_connect(&assoc_req);
1510a7ce71fSopenharmony_ci    if (ret != HISI_OK) {
1520a7ce71fSopenharmony_ci        return -1;
1530a7ce71fSopenharmony_ci    }
1540a7ce71fSopenharmony_ci
1550a7ce71fSopenharmony_ci    return 0;
1560a7ce71fSopenharmony_ci}
1570a7ce71fSopenharmony_ci
1580a7ce71fSopenharmony_cistatic void PrintLinkedInfo(WifiLinkedInfo* info)
1590a7ce71fSopenharmony_ci{
1600a7ce71fSopenharmony_ci    int ret = 0;
1610a7ce71fSopenharmony_ci    if (!info) {
1620a7ce71fSopenharmony_ci        return;
1630a7ce71fSopenharmony_ci    }
1640a7ce71fSopenharmony_ci
1650a7ce71fSopenharmony_ci    static char macAddress[32] = {0};
1660a7ce71fSopenharmony_ci    unsigned char* mac = info->bssid;
1670a7ce71fSopenharmony_ci    if (snprintf_s(macAddress, sizeof(macAddress) + 1, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
1680a7ce71fSopenharmony_ci        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]) < 0) { /* mac地址从0,1,2,3,4,5位 */
1690a7ce71fSopenharmony_ci            return;
1700a7ce71fSopenharmony_ci    }
1710a7ce71fSopenharmony_ci}
1720a7ce71fSopenharmony_ci
1730a7ce71fSopenharmony_cistatic void OnWifiConnectionChanged(int state, WifiLinkedInfo* info)
1740a7ce71fSopenharmony_ci{
1750a7ce71fSopenharmony_ci    if (!info) {
1760a7ce71fSopenharmony_ci        return;
1770a7ce71fSopenharmony_ci    }
1780a7ce71fSopenharmony_ci
1790a7ce71fSopenharmony_ci    printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state);
1800a7ce71fSopenharmony_ci    PrintLinkedInfo(info);
1810a7ce71fSopenharmony_ci
1820a7ce71fSopenharmony_ci    if (state == WIFI_STATE_AVAILABLE) {
1830a7ce71fSopenharmony_ci        g_connected = 1;
1840a7ce71fSopenharmony_ci    } else {
1850a7ce71fSopenharmony_ci        g_connected = 0;
1860a7ce71fSopenharmony_ci    }
1870a7ce71fSopenharmony_ci}
1880a7ce71fSopenharmony_ci
1890a7ce71fSopenharmony_cistatic void OnWifiScanStateChanged(int state, int size)
1900a7ce71fSopenharmony_ci{
1910a7ce71fSopenharmony_ci    printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size);
1920a7ce71fSopenharmony_ci}
1930a7ce71fSopenharmony_ci
1940a7ce71fSopenharmony_cistatic WifiEvent g_defaultWifiEventListener = {
1950a7ce71fSopenharmony_ci    .OnWifiConnectionChanged = OnWifiConnectionChanged,
1960a7ce71fSopenharmony_ci    .OnWifiScanStateChanged = OnWifiScanStateChanged
1970a7ce71fSopenharmony_ci};
1980a7ce71fSopenharmony_ci
1990a7ce71fSopenharmony_cistatic int WifiStartSta(void)
2000a7ce71fSopenharmony_ci{
2010a7ce71fSopenharmony_ci    WifiDeviceConfig apConfig = {0};
2020a7ce71fSopenharmony_ci    strcpy_s(apConfig.ssid, sizeof(CONFIG_AP_SSID), CONFIG_AP_SSID);
2030a7ce71fSopenharmony_ci    strcpy_s(apConfig.preSharedKey, sizeof(CONFIG_AP_PWD), CONFIG_AP_PWD);
2040a7ce71fSopenharmony_ci    apConfig.securityType = WIFI_SEC_TYPE_PSK;
2050a7ce71fSopenharmony_ci
2060a7ce71fSopenharmony_ci    WifiErrorCode errCode;
2070a7ce71fSopenharmony_ci    int netId = -1;
2080a7ce71fSopenharmony_ci
2090a7ce71fSopenharmony_ci    errCode = RegisterWifiEvent(&g_defaultWifiEventListener);
2100a7ce71fSopenharmony_ci    printf("RegisterWifiEvent: %d\r\n", errCode);
2110a7ce71fSopenharmony_ci
2120a7ce71fSopenharmony_ci    errCode = EnableWifi();
2130a7ce71fSopenharmony_ci    printf("EnableWifi: %d\r\n", errCode);
2140a7ce71fSopenharmony_ci
2150a7ce71fSopenharmony_ci    errCode = AddDeviceConfig(&apConfig, &netId);
2160a7ce71fSopenharmony_ci    printf("AddDeviceConfig: %d\r\n", errCode);
2170a7ce71fSopenharmony_ci
2180a7ce71fSopenharmony_ci    g_connected = 0;
2190a7ce71fSopenharmony_ci    errCode = ConnectTo(netId);
2200a7ce71fSopenharmony_ci    printf("ConnectTo(%d): %d\r\n", netId, errCode);
2210a7ce71fSopenharmony_ci
2220a7ce71fSopenharmony_ci    while (!g_connected) { // wait until connect to AP
2230a7ce71fSopenharmony_ci        osDelay(10); /* 10: os sleep 10ms */
2240a7ce71fSopenharmony_ci    }
2250a7ce71fSopenharmony_ci    printf("g_connected: %d\r\n", g_connected);
2260a7ce71fSopenharmony_ci
2270a7ce71fSopenharmony_ci    g_iface = netifapi_netif_find("wlan0");
2280a7ce71fSopenharmony_ci    if (g_iface) {
2290a7ce71fSopenharmony_ci        err_t ret = netifapi_dhcp_start(g_iface);
2300a7ce71fSopenharmony_ci        printf("netifapi_dhcp_start: %d\r\n", ret);
2310a7ce71fSopenharmony_ci
2320a7ce71fSopenharmony_ci        osDelay(100); // 100: os sleep 100ms wait DHCP server give me IP
2330a7ce71fSopenharmony_ci        ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL);
2340a7ce71fSopenharmony_ci        printf("netifapi_netif_common: %d\r\n", ret);
2350a7ce71fSopenharmony_ci    }
2360a7ce71fSopenharmony_ci    return netId;
2370a7ce71fSopenharmony_ci}
2380a7ce71fSopenharmony_ci
2390a7ce71fSopenharmony_civoid WifiStopSta(int netId)
2400a7ce71fSopenharmony_ci{
2410a7ce71fSopenharmony_ci    int stopNetId = netId;
2420a7ce71fSopenharmony_ci
2430a7ce71fSopenharmony_ci    if (g_iface) {
2440a7ce71fSopenharmony_ci        err_t ret = netifapi_dhcp_stop(g_iface);
2450a7ce71fSopenharmony_ci        printf("netifapi_dhcp_stop: %d\r\n", ret);
2460a7ce71fSopenharmony_ci    }
2470a7ce71fSopenharmony_ci
2480a7ce71fSopenharmony_ci    WifiErrorCode errCode = Disconnect(); // disconnect with your AP
2490a7ce71fSopenharmony_ci    printf("Disconnect: %d\r\n", errCode);
2500a7ce71fSopenharmony_ci
2510a7ce71fSopenharmony_ci    errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener);
2520a7ce71fSopenharmony_ci    printf("UnRegisterWifiEvent: %d\r\n", errCode);
2530a7ce71fSopenharmony_ci
2540a7ce71fSopenharmony_ci    RemoveDevice(stopNetId); // remove AP config
2550a7ce71fSopenharmony_ci    printf("RemoveDevice: %d\r\n", errCode);
2560a7ce71fSopenharmony_ci
2570a7ce71fSopenharmony_ci    errCode = DisableWifi();
2580a7ce71fSopenharmony_ci    printf("DisableWifi: %d\r\n", errCode);
2590a7ce71fSopenharmony_ci}
2600a7ce71fSopenharmony_ci
2610a7ce71fSopenharmony_civoid WifiStaReadyWait(void)
2620a7ce71fSopenharmony_ci{
2630a7ce71fSopenharmony_ci    ip4_addr_t ipAddr;
2640a7ce71fSopenharmony_ci    ip4_addr_t ipAny;
2650a7ce71fSopenharmony_ci    IP4_ADDR(&ipAny, 0, 0, 0, 0);
2660a7ce71fSopenharmony_ci    IP4_ADDR(&ipAddr, 0, 0, 0, 0);
2670a7ce71fSopenharmony_ci    cnetId = WifiStartSta();
2680a7ce71fSopenharmony_ci    IOT_LOG_DEBUG("wifi sta dhcp done");
2690a7ce71fSopenharmony_ci}