Files
luban-lite/bsp/peripheral/wireless/atbm603x/net/atbm_connect.c
刘可亮 8bca5e8332 v1.0.4
2024-04-03 16:40:57 +08:00

448 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**************************************************************************************************************
* altobeam RTOS wifi hmac source code
*
* Copyright (c) 2018, altobeam.inc All rights reserved.
*
* The source code contains proprietary information of AltoBeam, and shall not be distributed,
* copied, reproduced, or disclosed in whole or in part without prior written permission of AltoBeam.
*****************************************************************************************************************/
#include "atbm_hal.h"
extern atbm_void sta_scan_start_timer_func(atbm_void *data1,atbm_void *data2);
extern struct atbmwifi_common g_hw_prv;
#define MAX_SSID_LEN 32
#define MAX_PASSWORD_LEN 64
#define MAX_INTF_ID 2
#define ATBM_CHECK_AGRV_AVAILABLE(PARAM_1,PARAM_2) do{ \
atbm_uint8 ret;\
if(PARAM_1>MAX_SSID_LEN){ \
ret=-1; \
} \
if(PARAM_2>MAX_PASSWORD_LEN){\
ret= -2; \
} \
}while(0)
#define ATBM_CHECK_AGRV_AVAILABLE_POINTER(PARAM_1,PARAM_2) do{ \
atbm_uint8 ret;\
if(PARAM_1==ATBM_NULL){ \
ret=-1; \
goto EXIT;\
} \
if(PARAM_2==ATBM_NULL){\
ret= -2; \
goto EXIT;\
} \
}while(0)
atbm_int32 wifi_ConnectAP_vif(atbm_uint8 if_id,atbm_uint8 * ssid,int ssidlen,atbm_uint8 * password,int passwdlen,ATBM_SECURITY_TYPE key_mgmt)
{
atbm_int32 ret = 0;
struct atbmwifi_vif *priv;
ATBM_CHECK_AGRV_AVAILABLE(ssidlen,passwdlen);
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
if(priv == ATBM_NULL)
return -1;
atbm_memset(priv->config.ssid, 0, sizeof(priv->config.ssid));
atbm_memset(priv->config.password, 0, sizeof(priv->config.password));
atbm_memcpy(priv->config.ssid,ssid,ssidlen);
priv->config.ssid_len = priv->ssid_length= ssidlen;
atbm_memcpy(priv->ssid,priv->config.ssid,ssidlen);
if(passwdlen){
atbm_memcpy(priv->config.password,password,passwdlen);
}
if(ATBM_KEY_WEP_SHARE != key_mgmt){
priv->config.auth_alg = ATBM_WLAN_AUTH_OPEN;
}
else {
priv->config.auth_alg = ATBM_WLAN_AUTH_SHARED_KEY;
}
priv->config.password_len = passwdlen;
priv->config.privacy = passwdlen?1:0;
priv->config.key_mgmt = key_mgmt;
priv->config.key_id = 0;
priv->scan_expire = INITIAL_SCAN_EXPIRE;
priv->connect_expire=0;
//atbmwifi_autoconnect(priv);
#if CONFIG_IEEE80211W
if(priv->config.key_mgmt == ATBM_KEY_SAE)
priv->config.ieee80211w = 2;
else
priv->config.ieee80211w = 1;
#endif
wpa_connect_ap(priv);
return ret;
}
int wifi_SetAPConfig(struct atbmwifi_vif *priv,atbm_uint8 * ssid,int ssidlen,atbm_uint8 * password,int passwdlen,int channel,ATBM_SECURITY_TYPE key_mgmt,ATBM_BOOL ssidBcst){
if(ssidlen == 0 || ssidlen >32){
wifi_printk(WIFI_DBG_ERROR,"wifi_StartAP_vif ssid len is zero err\n");
return -1;
}
#if (CONFIG_5G_SUPPORT == 0)
if((channel > 14)){
wifi_printk(WIFI_DBG_ERROR,"wifi_StartAP_vif channel is zero err\n");
return -1;
}
#endif
if(passwdlen>64){
return -1;
}
atbm_memcpy(priv->config.ssid,ssid,ssidlen);
priv->config.ssid_len = priv->ssid_length= ssidlen;
atbm_memcpy(priv->ssid,priv->config.ssid,ssidlen);
if(passwdlen){
atbm_memcpy(priv->config.password,password,passwdlen);
priv->config.password_len = passwdlen;
priv->config.privacy = 1;
}else{
priv->config.privacy = 0;
}
priv->config.key_mgmt = key_mgmt;
priv->config.hide_ssid = ssidBcst;
/*Other Ap initial*/
priv->config.beaconInterval = TEST_BEACON_INTV;
priv->config.DTIMPeriod = TEST_DTIM_INTV;
priv->config.preambleType = TEST_SHORT_PREAMBLE;
priv->config.basicRateSet=TEST_BASIC_RATE;
///////////////////////////////////////////////////
/*If use the ap auto channel function,user need set channle 0*/
//channel=0;
channel = channel ? channel : atbmwifi_iee80211_peerif_channel(priv);
if(channel==0){
atbm_autoChann_Select(priv,&priv->config.channel_index);
}else{
priv->config.channel_index = channel;
#if BW_40M_SUPPORT
priv->bss.channel_type = atbmwifi_iee80211_peerif_channel_type(priv);
#else
priv->bss.channel_type = g_hw_prv.channel_type;
#endif
}
return 0;
}
atbm_void wifi_StartAP_vif(atbm_uint8 if_id,atbm_uint8 * ssid,int ssidlen,atbm_uint8 * password,int passwdlen,int channel,ATBM_SECURITY_TYPE key_mgmt,ATBM_BOOL ssidBcst)
{
struct atbmwifi_vif *priv;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,if_id);
wifi_printk(WIFI_ALWAYS,"%s @@@@ if_id=%d, scan.if_id=%d\n", __func__, priv->if_id, priv->scan.if_id);
if(wifi_SetAPConfig(priv, ssid, ssidlen, password, passwdlen, channel, key_mgmt, ssidBcst)){
return;
}
atbmwifi_wpa_event_queue((atbm_void*)priv,ATBM_NULL,ATBM_NULL,WPA_EVENT__HOSTAPD_START,ATBM_WPA_EVENT_ACK);
}
atbm_void atbmwifi_wpa_event_start_ap(struct atbmwifi_vif *priv)
{
struct atbmwifi_cfg *config = NULL;
if(priv == ATBM_NULL){
wifi_printk(WIFI_ALWAYS, "%s priv is null\n", __func__);
return;
}
config = atbmwifi_get_config(priv);
if(atbmwifi_iee80211_check_combination(priv,config->channel_index) == ATBM_FALSE){
wifi_printk(WIFI_ALWAYS, "%s AP(ch:%d) and STA is not work at same channel\n", __func__, config->channel_index);
return;
}
hostapd_start(priv);
}
/*
change wifi powersave mode
*/
atbm_void wifi_ChangePsMode(struct atbmwifi_vif *priv,atbm_uint8 enable,atbm_uint8 ds_timeout)
{
atbmwifi_set_pm(priv,enable,ds_timeout);
}
atbm_void AT_WDisConnect_vif(struct atbmwifi_vif *priv,char *pLine)
{
atbmwifi_ieee80211_send_deauth_disassoc(priv, priv->daddr,priv->bssid,
ATBM_IEEE80211_STYPE_DEAUTH,
ATBM_WLAN_REASON_DEAUTH_LEAVING,
ATBM_NULL, ATBM_TRUE);
if(!priv->enabled){
wifi_printk(WIFI_ALWAYS,"not support not enabled!\n");
return;
}
if(!atbmwifi_is_sta_mode(priv->iftype)) {
return;
}
sta_deauth(priv);
atbm_mdelay(100);
wpa_disconnect(priv);
atbm_mdelay(200);
}
atbm_void AT_WDisConnect(char *pLine)
{
struct atbmwifi_common *hw_priv;
struct atbmwifi_vif *priv;
hw_priv=&g_hw_prv;
priv= _atbmwifi_hwpriv_to_vifpriv(&g_hw_prv,0);
if(priv!=ATBM_NULL){
AT_WDisConnect_vif(priv,pLine);
}
}
/*
**************************************************************
*@breif <09><><EFBFBD>ӵ<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ap
*@params netdev:<3A><><EFBFBD><EFBFBD><EFBFBD>
* essid:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* key_mgmt:<3A><>Կ<EFBFBD><D4BF><EFBFBD>ܷ<EFBFBD>ʽ
*@retval none
**************************************************************
*/
extern int atbmwifi_sta_scan(struct atbmwifi_vif *priv);
int wpa_connect_ap(struct atbmwifi_vif *priv)
{
atbmwifi_wpa_event_queue((atbm_void*)priv,ATBM_NULL,
ATBM_NULL,WPA_EVENT__SUPPLICANT_START_CONNECT,ATBM_WPA_EVENT_NOACK);
return 0;
}
int atbmwifi_wpa_event_associte_ap(struct atbmwifi_vif *priv)
{
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata;
struct atbmwifi_cfg *config = atbmwifi_get_config(priv);
ATBM_CHECK_AGRV_AVAILABLE_POINTER(wpa_s,config);
priv->scan_no_connect_back = priv->scan_no_connect = 0;
if(priv->join_status == ATBMWIFI__JOIN_STATUS_STA){
wifi_printk(WIFI_ALWAYS,"atbmwifi_wpa_event_associte_ap() ---deauth\n");
sta_deauth(priv);
}
#if CONFIG_P2P
if(!priv->p2pdata)
#endif
priv->auto_connect_when_lost = 1;
#if (FAST_CONNECT_MODE == 0) && (FAST_CONNECT_NO_SCAN == 0)
config->psk_set=0;
#endif
wpa_s->wpa_state = ATBM_WPA_SCANNING;
wpa_comm_init_extra_ie(priv);
#if FAST_CONNECT_NO_SCAN
if(!priv->fast_conn_noscan){
if(!priv->scan.in_progress)
atbmwifi_sta_scan(priv);
}else{
atbm_queue_work(_atbmwifi_vifpriv_to_hwpriv(priv),priv->join_work);
}
#else
if(!priv->scan.in_progress){
atbmwifi_eloop_register_timeout(0,priv->scan_expire*1000,sta_scan_start_timer_func,(atbm_void *)priv,ATBM_NULL);
}
atbmwifi_sta_scan(priv);
#endif
atbm_kfree(priv->extra_ie);
priv->extra_ie = ATBM_NULL;
priv->extra_ie_len = 0;
EXIT:
return 0;
}
/****************************************************
Function Name: atbmwifi_scan_process
Return: scan status,0 success,other fail
******************************************************/
int atbmwifi_scan_process(struct atbmwifi_vif *priv)
{
if(!atbmwifi_is_sta_mode(priv->iftype)) {
wifi_printk(WIFI_ALWAYS,"not support scan in AP mode!\n");
return -1;
}
if(!priv->enabled){
wifi_printk(WIFI_ALWAYS,"not support not enabled!\n");
return -2;
}
if(priv->scan.scan_smartconfig){
wifi_printk(WIFI_ALWAYS,"scan_smartconfig now!please try later!\n");
return -3;
}
if((priv->assoc_ok==0) && ( priv->join_status == ATBMWIFI__JOIN_STATUS_STA)){
wifi_printk(WIFI_ALWAYS,"join now!please try later!\n");
return -6;
}
if(!priv->scan.in_progress){
if(priv->scan_ret.info==ATBM_NULL){
priv->scan_ret.info = (struct atbmwifi_scan_result_info *)atbm_kmalloc(sizeof(struct atbmwifi_scan_result_info) * MAX_SCAN_INFO_NUM,GFP_KERNEL);
if(priv->scan_ret.info ==ATBM_NULL){
wifi_printk(WIFI_ALWAYS,"scan malloc fail!");
return -4;
}
}
priv->scan_ret.len = 0;
priv->scan.if_id = priv->if_id;
priv->scan_expire = INITIAL_SCAN_EXPIRE;
priv->scan_no_connect_back = priv->scan_no_connect;
priv->scan_no_connect = 1;
return atbmwifi_sta_scan(priv);
}
else {
wifi_printk(WIFI_ALWAYS,"scan busy!please try later!");
return -5;
}
}
/*********************station interface**********************/
/****************************************************
Function Name: atbmwifi_scan
Return: NULL
******************************************************/
int atbmwifi_scan(struct atbmwifi_vif *priv)
{
atbmwifi_wpa_event_queue((atbm_void*)priv,ATBM_NULL,
ATBM_NULL,WPA_EVENT__SUPPLICANT_SCAN,ATBM_WPA_EVENT_ACK);
return 0;
}
atbm_void atbmwifi_event_handler(struct atbmwifi_vif *priv,atbm_uint32 eventId,atbm_uint32 eventData)
{
switch (eventId) {
case WSM_EVENT_ERROR:
/* I even don't know what is it about.. */
//STUB();
break;
case WSM_EVENT_BSS_LOST:
{
wifi_printk(WIFI_DBG_ERROR,"[CQM] BSS lost.\n");
atbmwifi_ieee80211_connection_loss(priv);
if(atbmwifi_is_sta_mode(priv->iftype))
{
wifi_printk(WIFI_ALWAYS,"atbmwifi_event_handler() ---deauth\n");
sta_deauth(priv);
}
else
{
//atbmwifi_ap_deauth(priv,StaMac);
}
break;
}
case WSM_EVENT_BSS_REGAINED:
{
//sta_printk(KERN_DEBUG "[CQM] BSS regained.\n");
//priv->delayed_link_loss = 0;
//atbm_spin_lock(&priv->bss_loss_lock);
//priv->bss_loss_status = ATBMWIFI__BSS_LOSS_NONE;
//atbm_spin_unlock(&priv->bss_loss_lock);
//cancel_delayed_work_sync(&priv->bss_loss_work);
//cancel_delayed_work_sync(&priv->connection_loss_work);
break;
}
case WSM_EVENT_RADAR_DETECTED:
//STUB();
break;
case WSM_EVENT_RCPI_RSSI:
{
break;
}
case WSM_EVENT_BT_INACTIVE:
//STUB();
break;
case WSM_EVENT_BT_ACTIVE:
//STUB();
break;
case WSM_EVENT_INACTIVITY://WSM_EVENT_IND_INACTIVITY
{
int link_id = atbm_ffs((atbm_uint32)eventData) - 1;
struct atbm_buff *skb;
struct atbmwifi_ieee80211_mgmt *deauth;
struct atbmwifi_link_entry *entry = ATBM_NULL;
wifi_printk(WIFI_DBG_ERROR, "Inactivity Event Rx "
"link_id %d\n", link_id);
_atbmwifi_unmap_link(priv, link_id);
skb = atbm_dev_alloc_skb(sizeof(struct atbmwifi_ieee80211_mgmt));
//atbm_skb_reserve(skb, 64);
deauth = (struct atbmwifi_ieee80211_mgmt *)atbm_skb_put(skb, sizeof(struct atbmwifi_ieee80211_mgmt));
ATBM_WARN_ON_FUNC(!deauth);
entry = &priv->link_id_db[link_id - 1];
deauth->duration = 0;
atbm_memcpy(deauth->da, priv->mac_addr, ATBM_ETH_ALEN);
atbm_memcpy(deauth->sa, entry->mac/*priv->link_id_db[i].mac*/, ATBM_ETH_ALEN);
atbm_memcpy(deauth->bssid,priv->mac_addr, ATBM_ETH_ALEN);
deauth->frame_control = atbm_cpu_to_le16(ATBM_IEEE80211_FTYPE_MGMT |
ATBM_IEEE80211_STYPE_DEAUTH |
ATBM_IEEE80211_FCTL_TODS);
deauth->u.deauth.reason_code = ATBM_WLAN_REASON_DEAUTH_LEAVING;
deauth->seq_ctrl = 0;
if(atbmwifi_ieee80211_rx_irqsafe(priv, skb) != 0){
atbm_dev_kfree_skb(skb);
}
atbm_set_tim_impl(priv);
break;
}
case WSM_EVENT_PS_MODE_ERROR:
{
}
}
}
int atbmwifi_disable_listening(struct atbmwifi_vif *priv)
{
int ret;
struct wsm_reset reset={0};
reset.reset_statistics = ATBM_TRUE;
#ifdef P2P_MULTIVIF
if(priv->if_id != 2) {
ATBM_WARN_ON_FUNC(priv->join_status > ATBMWIFI__JOIN_STATUS_MONITOR);
return 0;
}
#endif //change by wp
priv->join_status = ATBMWIFI__JOIN_STATUS_PASSIVE;
ATBM_WARN_ON_FUNC(priv->join_status > ATBMWIFI__JOIN_STATUS_MONITOR);
ret = wsm_reset(priv->hw_priv, &reset, ATBM_WIFI_GENERIC_IF_ID);
return ret;
}
atbm_void atbmwifi_stop(void)
{
struct atbmwifi_common * hw_priv;
int i = 0;
struct atbmwifi_vif *priv;
hw_priv = &g_hw_prv;
atbm_for_each_vif(hw_priv,priv,i){
switch (priv->join_status) {
case ATBMWIFI__JOIN_STATUS_STA:
atbmwifi_stop_sta(priv);
break;
case ATBMWIFI__JOIN_STATUS_AP:
atbmwifi_stop_ap(priv);
break;
case ATBMWIFI__JOIN_STATUS_MONITOR:
atbmwifi_disable_listening(priv);
break;
default:
break;
}
/* TODO:COMBO: May be reset of these variables "delayed_link_loss and
* join_status to default can be removed as dev_priv will be freed by
* mac80211 */
//priv->delayed_link_loss = 0;
priv->join_status = ATBMWIFI__JOIN_STATUS_PASSIVE;
wsm_unlock_tx(hw_priv);
priv->listening = ATBM_FALSE;
}
for (i = 0; i < 4; i++){
atbmwifi_queue_clear(&hw_priv->tx_queue[i], -1); //clear all queue
}
}