Files
luban-lite/bsp/peripheral/wireless/atbm603x/net/atbm_connect.c

448 lines
13 KiB
C
Raw Normal View History

2024-04-03 16:40:57 +08:00
/**************************************************************************************************************
* 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 <EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ap
*@params netdev:<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* essid:<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* key_mgmt:<EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><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
}
}