mirror of https://github.com/ARMmbed/mbed-os.git
365 lines
10 KiB
C++
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;
|
|
}
|