rt-thread/bsp/amebaz/drivers/wlan/drv_wlan.c

367 lines
8.4 KiB
C
Raw Normal View History

/*
* File : drv_wlan.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2017, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2018-7-10 tyx the first version
*/
#include "wifi_structures.h"
#include "wifi_constants.h"
#include <wifi/wifi_util.h>
#include <wifi/wifi_conf.h>
#include "board.h"
#include "drv_wlan.h"
// #define SCAN_WAIT_TIME (10000)
struct scan_user_data
{
struct rt_completion done;
scan_callback_fn fun;
void *data;
};
extern rthw_mode_t wifi_mode;
rthw_mode_t rthw_wifi_mode_get(void)
{
return wifi_mode;
}
int rthw_wifi_stop(void)
{
return wifi_off();
}
int rthw_wifi_start(rthw_mode_t mode)
{
if(wifi_on(mode) < 0)
{
rt_kprintf("ERROR: wifi_on failed\n");
return -1;
}
return 0;
}
int rthw_wifi_connect(char *ssid, int ssid_len, char *password, int pass_len, rthw_security_t security_type)
{
int mode;
rtw_wifi_setting_t setting;
mode = rthw_wifi_mode_get();
if ((mode != RTHW_MODE_STA) && (mode != RTHW_MODE_STA_AP))
{
return -1;
}
if(wext_get_mode(WLAN0_NAME, &mode) < 0)
{
rt_kprintf("L:%d wifi get mode err\n", __LINE__);
return -1;
}
if(wifi_connect(ssid, security_type, password, ssid_len, pass_len, -1, NULL) != RTW_SUCCESS)
{
rt_kprintf("wifi connect fail\n");
return -1;
}
rt_kprintf("wifi connect success\n");
rt_kprintf("Show Wi-Fi information\n");
wifi_get_setting(WLAN0_NAME,&setting);
wifi_show_setting(WLAN0_NAME,&setting);
return 0;
}
int rthw_wifi_connect_bssid(char *bssid, char *ssid, int ssid_len, char *password, int pass_len, rthw_security_t security_type)
{
int mode;
rtw_wifi_setting_t setting;
mode = rthw_wifi_mode_get();
if ((mode != RTHW_MODE_STA) && (mode != RTHW_MODE_STA_AP))
{
return -1;
}
if(wext_get_mode(WLAN0_NAME, &mode) < 0)
{
rt_kprintf("L:%d wifi get mode err\n", __LINE__);
return -1;
}
if(wifi_connect_bssid(bssid, ssid, security_type, password, 6, ssid_len, pass_len, -1, NULL) != RTW_SUCCESS)
{
rt_kprintf("wifi connect fail\n");
return -1;
}
rt_kprintf("wifi connect success\n");
rt_kprintf("Show Wi-Fi information\n");
wifi_get_setting(WLAN0_NAME,&setting);
wifi_show_setting(WLAN0_NAME,&setting);
return 0;
}
int rthw_wifi_ap_start(char *ssid, char *password, int channel)
{
int mode = 0, timeout = 20;
rtw_security_t security_type = RTW_SECURITY_WPA2_AES_PSK;
char *name = RT_NULL;
mode = rthw_wifi_mode_get();
if (mode == RTHW_MODE_AP)
{
name = WLAN0_NAME;
}
else if (mode == RTHW_MODE_STA_AP)
{
name = WLAN1_NAME;
}
else
{
return -1;
}
if(wext_get_mode(name, &mode) < 0)
{
rt_kprintf("L:%d wifi get mode err\n", __LINE__);
return -1;
}
if (password == RT_NULL)
{
security_type = RTW_SECURITY_OPEN;
}
if(wifi_start_ap(ssid, security_type, password, rt_strlen(ssid), rt_strlen(password), 6) != 0)
{
rt_kprintf("ERROR: wifi_start_ap failed\n");
return -1;
}
while(1)
{
char essid[33];
if(wext_get_ssid(name, (unsigned char *) essid) > 0)
{
if(strcmp((const char *) essid, (const char *)ssid) == 0)
{
rt_kprintf("%s started\n", ssid);
break;
}
}
if(timeout == 0)
{
rt_kprintf("Start AP timeout\n");
return -1;
}
rt_thread_delay(1 * RT_TICK_PER_SECOND);
timeout --;
}
return 0;
}
static int rthw_wifi_disconnect(char *name)
{
char essid[33];
int timeout = 20;
const rt_uint8_t null_bssid[ETH_ALEN + 2] = {0, 0, 0, 0, 0, 1, 0, 0};
if (name == RT_NULL)
return -1;
if (wext_get_ssid(name, (unsigned char *) essid) < 0)
{
rt_kprintf("\nWIFI disconnected!\n");
return -1;
}
if (wext_set_bssid(name, null_bssid) < 0)
{
rt_kprintf("Failed to set bogus BSSID to disconnect");
return -1;
}
while (1)
{
if(wext_get_ssid(name, (unsigned char *) essid) < 0)
{
rt_kprintf("WIFI disconnected!\n");
break;
}
if(timeout == 0)
{
rt_kprintf("ERROR: Deassoc timeout!\n");
return -1;
}
rt_thread_delay(10);
timeout --;
}
return 0;
}
int rthw_wifi_sta_disconnect(void)
{
int mode = 0;
char *name = RT_NULL;
mode = rthw_wifi_mode_get();
if (mode == RTHW_MODE_STA)
{
name = WLAN0_NAME;
}
else if (mode == RTHW_MODE_STA_AP)
{
name = WLAN0_NAME;
}
else
{
return -1;
}
return rthw_wifi_disconnect(name);
}
int rthw_wifi_ap_disconnect(void)
{
int mode = 0;
char *name = RT_NULL;
mode = rthw_wifi_mode_get();
if (mode == RTHW_MODE_AP)
{
name = WLAN0_NAME;
}
else if (mode == RTHW_MODE_STA_AP)
{
name = WLAN1_NAME;
}
else
{
return -1;
}
return rthw_wifi_disconnect(name);
}
int rthw_wifi_rssi_get(void)
{
int rssi = 0;
wifi_get_rssi(&rssi);
return rssi;
}
void rthw_wifi_channel_set(int channel)
{
wifi_set_channel(channel);
}
int rthw_wifi_channel_get(void)
{
int channel;
wifi_get_channel(&channel);
return channel;
}
static rtw_result_t rthw_wifi_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result)
{
struct scan_user_data* user_data = malloced_scan_result->user_data;
struct rthw_wlan_info info = { 0 };
if (malloced_scan_result->scan_complete != RTW_TRUE)
{
rtw_scan_result_t* record = &malloced_scan_result->ap_details;
if (user_data->fun != RT_NULL)
{
record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
info.ssid = record->SSID.val;
info.bssid = record->BSSID.octet;
info.band = record->band;
info.datarate = 0;
info.channel = record->channel;
info.rssi = record->signal_strength;
info.security = record->security;
user_data->fun(&info, user_data->data);
}
}
else
{
user_data->fun(RT_NULL, user_data->data);
rt_free(user_data);
rt_kprintf("scan ap down\n");
}
return RTW_SUCCESS;
}
int rthw_wifi_scan(scan_callback_fn fun, void *data)
{
struct scan_user_data *user_data;
if (fun == RT_NULL)
{
rt_kprintf("scan callback fun is null\n");
return -1;
}
user_data = rt_malloc(sizeof(struct scan_user_data));
if (user_data == RT_NULL)
{
rt_kprintf("wifi scan malloc fail\n");
return -1;
}
user_data->fun = fun;
user_data->data = data;
if (wifi_scan_networks(rthw_wifi_scan_result_handler, user_data) != RTW_SUCCESS)
{
rt_kprintf("ERROR: wifi scan failed\n\r");
return -1;
}
return 0;
}
static rthw_wlan_monitor_callback_t monitor_callback;
static void rthw_wifi_promisc_callback(unsigned char *buf, unsigned int len, void* userdata)
{
if (monitor_callback)
{
monitor_callback(userdata, len, RT_NULL);
}
}
void rthw_wifi_monitor_callback_set(rthw_wlan_monitor_callback_t callback)
{
monitor_callback = callback;
}
void rthw_wifi_monitor_enable(int enable)
{
if (enable)
{
wifi_enter_promisc_mode();
wifi_set_promisc(RTW_PROMISC_ENABLE, rthw_wifi_promisc_callback, 1);
rt_kprintf("%s run \n", __FUNCTION__);
}
else
{
wifi_set_promisc(RTW_PROMISC_DISABLE, RT_NULL, 0);
rthw_wifi_stop();
}
}