mbed-os/features/netsocket/emac-drivers/TARGET_RDA_EMAC/RdaWiFiInterface.cpp

365 lines
10 KiB
C++

/* Copyright (c) 2019 Unisoc Communications Inc.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "WiFiInterface.h"
#include "RdaWiFiInterface.h"
#include "rda5991h_wland.h"
#include "nsapi_types.h"
#include "wland_types.h"
#include "rda_sys_wrapper.h"
typedef enum {
WIFI_CONNECTED,
WIFI_DISCONNECTED,
}WIFI_STATE;
static WIFI_STATE wifi_state = WIFI_DISCONNECTED;
void daemon(void *para)
{
void *main_msgQ = NULL;
rda_msg msg;
int ret;
RDAWiFiInterface *wifi = (RDAWiFiInterface *)para;
main_msgQ = rda_mail_create(10, sizeof(unsigned int)*4);
wifi->set_msg_queue(main_msgQ);
while(1){
rda_mail_get(main_msgQ, (void*)&msg, osWaitForever);
switch(msg.type)
{
case MAIN_RECONNECT:
printf("wifi disconnect!\r\n");
ret = wifi->disconnect();
if(ret != 0){
printf("disconnect failed!\r\n");
break;
}
ret = wifi->reconnect();
while(ret != 0){
osDelay(5*1000);
ret = wifi->reconnect();
};
break;
default:
printf("unknown msg\r\n");
break;
}
}
}
nsapi_error_t RDAWiFiInterface::set_channel(uint8_t channel)
{
int ret= 0;
init();
if (channel > 13)
return NSAPI_ERROR_PARAMETER;
if (channel == 0) {
_channel = 0;
return NSAPI_ERROR_OK;
}
ret = rda5981_set_channel(channel);
if (ret == 0) {
_channel = channel;
return NSAPI_ERROR_OK;
} else {
return NSAPI_ERROR_TIMEOUT;
}
}
int8_t RDAWiFiInterface::get_rssi()
{
return rda5981_get_rssi();
}
nsapi_error_t RDAWiFiInterface::init()
{
if (!_interface) {
if (!_emac.power_up()) {
LWIP_DEBUGF(NETIF_DEBUG,("power up failed!\n"));
}
nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface);
if (err != NSAPI_ERROR_OK) {
_interface = NULL;
return err;
}
_interface->attach(_connection_status_cb);
//rda_thread_new("daemon", daemon, this, DEFAULT_THREAD_STACKSIZE*4, osPriorityNormal);
}
return NSAPI_ERROR_OK;
}
nsapi_error_t RDAWiFiInterface::set_credentials(const char *ssid, const char *pass,
nsapi_security_t security)
{
if (ssid == 0 || strlen(ssid) == 0) {
return NSAPI_ERROR_PARAMETER;
}
if (security != NSAPI_SECURITY_NONE && (pass == 0 || strlen(pass) == 0)) {
return NSAPI_ERROR_PARAMETER;
}
if (strlen(ssid) > 32 || strlen(pass) > 63) {
return NSAPI_ERROR_PARAMETER;
}
memcpy((void*)_ssid, (void*)ssid, strlen(ssid));
_ssid[strlen(ssid)] = '\0';
memcpy((void*)_pass, (void*)pass, strlen(pass));
_pass[strlen(pass)] = '\0';
_security = security;
return NSAPI_ERROR_OK;
}
nsapi_error_t RDAWiFiInterface::connect(const char *ssid, const char *pass,
nsapi_security_t security, uint8_t channel)
{
rda_msg msg;
bool find = false;
int i = 0;
rda5981_scan_result bss;
int ret = 0;
if(wifi_state == WIFI_CONNECTED) {
return NSAPI_ERROR_IS_CONNECTED;
}
if (ssid == NULL || ssid[0] == 0) {
return NSAPI_ERROR_PARAMETER;
}
set_credentials(ssid, pass, security);
set_channel(channel);
init();
//reset all scan result to avoid any previous stored SSID/PW/CHANNEL
rda5981_del_scan_all_result();
rda5981_scan(NULL,0,0);
if(rda5981_check_scan_result_name(ssid) != 0) {
for (i = 0; i< 5; i++) {
rda5981_scan(NULL, 0, 0);
if(rda5981_check_scan_result_name(ssid) == 0) {
find = true;
break;
}
}
} else {
find = true;
}
if (find == false) {
LWIP_DEBUGF(NETIF_DEBUG,("can not find the ap.\r\n"));
return NSAPI_ERROR_NO_SSID;
}
bss.channel = 15;
rda5981_get_scan_result_name(&bss, ssid);
if ((channel !=0) && (bss.channel != channel)) {
LWIP_DEBUGF(NETIF_DEBUG, ("invalid channel\r\n"));
return NSAPI_ERROR_CONNECTION_TIMEOUT;
}
memcpy(gssid, ssid, strlen(ssid));
if (pass[0] != 0) {
memcpy(gpass, pass, strlen(pass));
}
memset(gbssid, 0, NSAPI_MAC_BYTES);
gssid[strlen(ssid)] = gpass[strlen(pass)] = '\0';
msg.type = WLAND_CONNECT;
rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever);
ret = rda_sem_wait(wifi_auth_sem, 10000);
if (ret) {
return NSAPI_ERROR_CONNECTION_TIMEOUT;
}
wifi_state = WIFI_CONNECTED;
ret = _interface->bringup(_dhcp,
_ip_address[0] ? _ip_address : 0,
_netmask[0] ? _netmask : 0,
_gateway[0] ? _gateway : 0,
DEFAULT_STACK,
_blocking);
LWIP_DEBUGF(NETIF_DEBUG,("Interface bringup up status:%d\r\n",ret));
if( ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED ) {
ret = NSAPI_ERROR_OK;
}
else if( ret == NSAPI_ERROR_DHCP_FAILURE) {
disconnect();
}
return ret;
}
nsapi_error_t RDAWiFiInterface::connect()
{
return connect(_ssid, _pass, _security, _channel);
}
nsapi_error_t RDAWiFiInterface::disconnect()
{
rda_msg msg;
if(wifi_state == WIFI_DISCONNECTED) {
return NSAPI_ERROR_NO_CONNECTION;
}
wifi_state = WIFI_DISCONNECTED;
void* wifi_disconnect_sem = rda_sem_create(0);
msg.type = WLAND_DISCONNECT;
msg.arg1 = (unsigned int)wifi_disconnect_sem;
rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever);
rda_sem_wait(wifi_disconnect_sem, osWaitForever);
rda_sem_delete(wifi_disconnect_sem);
if (_interface) {
return _interface->bringdown();
}
return NSAPI_ERROR_NO_CONNECTION;
}
nsapi_error_t RDAWiFiInterface::reconnect()
{
rda_msg msg;
bool find = false;
int i = 0;
rda5981_scan_result bss;
int ret = 0;
if (_ssid == NULL || _ssid[0] == 0) {
return NSAPI_ERROR_PARAMETER;
}
rda5981_del_scan_all_result();
if(rda5981_check_scan_result_name(_ssid) != 0) {
for (i = 0; i< 5; i++) {
rda5981_scan(NULL, 0, 0);
if(rda5981_check_scan_result_name(_ssid) == 0) {
find = true;
break;
}
}
} else {
find = true;
}
if (find == false) {
LWIP_DEBUGF(NETIF_DEBUG,"can not find the ap.\r\n");
return NSAPI_ERROR_CONNECTION_TIMEOUT;
}
bss.channel = 15;
rda5981_get_scan_result_name(&bss, _ssid);
if ((_channel !=0) && (bss.channel != _channel)) {
LWIP_DEBUGF(NETIF_DEBUG, "invalid channel\r\n");
return NSAPI_ERROR_CONNECTION_TIMEOUT;
}
memcpy(gssid, _ssid, strlen(_ssid));
if (_pass[0] != 0) {
memcpy(gpass, _pass, strlen(_pass));
}
memset(gbssid, 0, NSAPI_MAC_BYTES);
gssid[strlen(_ssid)] = gpass[strlen(_pass)] = '\0';
msg.type = WLAND_CONNECT;
rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever);
ret = rda_sem_wait(wifi_auth_sem, 10000);
if (ret) {
return NSAPI_ERROR_CONNECTION_TIMEOUT;
}
if(_dhcp) {
memset(_ip_address, 0, sizeof(_ip_address));
memset(_netmask, 0, sizeof(_netmask));
memset(_gateway, 0, sizeof(_gateway));
}
ret = _interface->bringup(_dhcp,
_ip_address[0] ? _ip_address : 0,
_netmask[0] ? _netmask : 0,
_gateway[0] ? _gateway : 0,
DEFAULT_STACK,
_blocking);
LWIP_DEBUGF(NETIF_DEBUG,("Interface bringup up status:%d\r\n",ret));
if( ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED ) {
ret = NSAPI_ERROR_OK;
wifi_state = WIFI_CONNECTED;
}
else if( ret == NSAPI_ERROR_DHCP_FAILURE) {
disconnect();
}
return ret;
}
nsapi_size_or_error_t RDAWiFiInterface::scan(WiFiAccessPoint *res, nsapi_size_t count)
{
int bss_num = 0, i;
rda5981_scan_result *bss;
nsapi_wifi_ap_t ap;
init();
rda5981_scan(NULL, 0, 0);
bss_num = rda5981_get_scan_num();
if (count != 0) {
bss_num = (bss_num < count) ? bss_num : count;
}
if (res) {
bss = (rda5981_scan_result *)malloc(bss_num * sizeof(rda5981_scan_result));
rda5981_get_scan_result(bss, bss_num);
for (i=0; i<bss_num; i++) {
memset(&ap, 0, sizeof(nsapi_wifi_ap_t));
memcpy(ap.bssid, bss[i].BSSID, 6);
memcpy(ap.ssid, bss[i].SSID, bss[i].SSID_len);
ap.channel = bss[i].channel;
ap.rssi = bss[i].RSSI;
if (bss[i].secure_type == ENCRYPT_NONE) {
ap.security = NSAPI_SECURITY_NONE;
} else if(bss[i].secure_type & ENCRYPT_WEP) {
ap.security = NSAPI_SECURITY_WEP;
} else if((bss[i].secure_type & (ENCRYPT_WPA_TKIP | ENCRYPT_WPA_CCMP)) && \
(bss[i].secure_type & (ENCRYPT_WPA2_TKIP | ENCRYPT_WPA2_CCMP))) {
ap.security = NSAPI_SECURITY_WPA_WPA2;
} else if((bss[i].secure_type & (ENCRYPT_WPA_TKIP | ENCRYPT_WPA_CCMP))) {
ap.security = NSAPI_SECURITY_WPA;
} else {
ap.security = NSAPI_SECURITY_WPA2;
}
WiFiAccessPoint ap_temp(ap);
memcpy(&res[i], &ap_temp, sizeof(WiFiAccessPoint));
}
free(bss);
}
return bss_num;
}
WiFiInterface *WiFiInterface::get_default_instance() {
static RDAWiFiInterface wifinet;
return &wifinet;
}
nsapi_size_or_error_t RDAWiFiInterface::set_msg_queue(void *queue)
{
//TO_DO: No need for 1st stage since application already control the logic.
//rda5981_set_main_queue(queue);
return 0;
}