mirror of
https://gitee.com/Vancouver2017/luban-lite.git
synced 2025-12-24 04:58:54 +00:00
1057 lines
32 KiB
C
1057 lines
32 KiB
C
/**************************************************************************************************************
|
|
* 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"
|
|
#if ATBM_SUPPORT_BRIDGE
|
|
#include "atbm_bridge.h"
|
|
#endif
|
|
|
|
atbm_void atbmwifi_mcast_timeout(atbm_void *data1,atbm_void *data2);
|
|
extern atbm_void atbmwifi_queued_timeout(atbm_void *data1,atbm_void *data2);
|
|
|
|
int _atbmwifi_unmap_link(struct atbmwifi_vif *priv, int link_id)
|
|
{
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
struct wsm_map_link maplink;
|
|
maplink.link_id = link_id;
|
|
maplink.unmap = ATBM_TRUE;
|
|
if (link_id)
|
|
atbm_memcpy(&maplink.mac_addr[0],
|
|
priv->link_id_db[link_id - 1].mac, ATBM_ETH_ALEN);
|
|
return wsm_map_link(hw_priv, &maplink, priv->if_id);
|
|
}
|
|
atbm_void atbmwifi_link_id_lmac(struct atbmwifi_vif *priv,int link_id )
|
|
{
|
|
ATBM_BOOL need_reset;
|
|
atbm_uint32 mask;
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
struct wsm_map_link map_link;
|
|
map_link.link_id = 0;
|
|
map_link.unmap = 0;
|
|
//int i=0;
|
|
if (priv->join_status != ATBMWIFI__JOIN_STATUS_AP)
|
|
return;
|
|
|
|
//wsm_lock_tx(hw_priv);
|
|
//for (i = 0; i < ATBMWIFI__MAX_STA_IN_AP_MODE; ++i) {
|
|
need_reset = ATBM_FALSE;
|
|
mask = BIT(link_id);
|
|
if(priv->link_id_db[link_id-1].status == ATBMWIFI__LINK_HARD) {
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
if (priv->link_id_map & mask) {
|
|
priv->sta_asleep_mask &= ~mask;
|
|
priv->pspoll_mask &= ~mask;
|
|
need_reset = ATBM_TRUE;
|
|
}
|
|
priv->link_id_map |= mask;
|
|
|
|
atbm_memcpy(map_link.mac_addr, priv->link_id_db[link_id-1].mac,ATBM_ETH_ALEN);
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
if (need_reset) {
|
|
_atbmwifi_unmap_link(priv, link_id);
|
|
}
|
|
map_link.link_id = link_id;
|
|
wsm_map_link(hw_priv, &map_link, priv->if_id);
|
|
}
|
|
}
|
|
|
|
int atbmwifi_alloc_link_id(struct atbmwifi_vif *priv, const atbm_uint8 *mac)
|
|
{
|
|
int i, ret = 0;
|
|
for (i = 0; i < ATBMWIFI__MAX_STA_IN_AP_MODE; ++i) {
|
|
if (!priv->link_id_db[i].status) {
|
|
ret = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
ATBM_WARN_ON_FUNC(ret>ATBMWIFI__MAX_STA_IN_AP_MODE);
|
|
ATBM_WARN_ON_FUNC(ret==0);
|
|
|
|
if (ret) {
|
|
struct atbmwifi_link_entry *entry = &priv->link_id_db[ret - 1];
|
|
wifi_printk(WIFI_ALWAYS,"[AP] STA added, link_id: %d\n",ret);
|
|
entry->status = ATBMWIFI__LINK_RESERVE;
|
|
atbm_memcpy(&entry->mac, mac, ATBM_ETH_ALEN);
|
|
atbm_memset(&entry->buffered, 0, ATBMWIFI__MAX_TID);
|
|
atbm_memcpy(entry->sta_priv.mac, mac, ATBM_ETH_ALEN);
|
|
entry->sta_priv.priv =priv ;
|
|
entry->sta_priv.link_id =ret ;
|
|
entry->sta_priv.flags =0 ;
|
|
entry->sta_priv.driver_buffered_tids =0 ;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*find hard connected link id ,get sta mac address, and copy together*/
|
|
int atbmwifi_get_hard_linked_macs(struct atbmwifi_vif *priv, atbm_uint8 *mac, atbm_uint32 maccnt)
|
|
{
|
|
int i;
|
|
atbm_uint8 *tmp = mac;
|
|
int mac_copyed_len = 0;
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
|
|
for (i = 0; i < ATBMWIFI__MAX_STA_IN_AP_MODE; ++i) {
|
|
if ((priv->link_id_db[i].status==ATBMWIFI__LINK_HARD)) {
|
|
|
|
atbm_memcpy(tmp, priv->link_id_db[i].mac, ATBM_ETH_ALEN);
|
|
mac_copyed_len++;
|
|
tmp += ATBM_ETH_ALEN;
|
|
if(mac_copyed_len >= maccnt)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
return mac_copyed_len;
|
|
}
|
|
/*find link id ,have alloc link id*/
|
|
int atbmwifi_find_link_id(struct atbmwifi_vif *priv, const atbm_uint8 *mac)
|
|
{
|
|
int i, ret = 0;
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
|
|
for (i = 0; i < ATBMWIFI__MAX_STA_IN_AP_MODE; ++i) {
|
|
if (!atbm_memcmp(mac, priv->link_id_db[i].mac, ATBM_ETH_ALEN) &&
|
|
priv->link_id_db[i].status) {
|
|
ret = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
return ret;
|
|
}
|
|
/*find link id ,have connect link id*/
|
|
int atbmwifi_find_hard_link_id(struct atbmwifi_vif *priv, const atbm_uint8 *mac)
|
|
{
|
|
int i, ret = 0;
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
|
|
for (i = 0; i < ATBMWIFI__MAX_STA_IN_AP_MODE; ++i) {
|
|
if (!atbm_memcmp(mac, priv->link_id_db[i].mac, ATBM_ETH_ALEN) &&
|
|
(priv->link_id_db[i].status==ATBMWIFI__LINK_HARD)) {
|
|
//priv->link_id_db[i].timestamp = atbm_GetOsTimeMs;
|
|
ret = i + 1;
|
|
break;
|
|
}
|
|
}
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int atbmwifi_sta_alloc(struct atbmwifi_vif *priv,
|
|
atbm_uint8 *sta_mac)
|
|
{
|
|
int link_id = 0;
|
|
if (!atbmwifi_is_ap_mode(priv->iftype))
|
|
return 0;
|
|
link_id = atbmwifi_find_link_id(priv, sta_mac);
|
|
if(link_id==0) {
|
|
link_id = atbmwifi_alloc_link_id(priv, sta_mac);
|
|
if(link_id ==0){
|
|
wifi_printk(WIFI_CONNECT,"%s %d Err1\n",__FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
}
|
|
else {
|
|
//if(priv->link_id_db[link_id-1].status != ATBMWIFI__LINK_RESERVE)
|
|
#if CONFIG_SAE
|
|
struct hostapd_data *hapd = (struct hostapd_data *)priv->appdata;
|
|
struct hostapd_sta_info *sta = ap_get_sta(hapd, sta_mac);
|
|
if(sta && ((sta->aid != link_id) || (sta->sae.state != SAE_COMMITTED)))
|
|
#endif
|
|
{
|
|
atbmwifi_sta_del(priv,sta_mac);
|
|
}
|
|
priv->link_id_db[link_id-1].status = ATBMWIFI__LINK_RESERVE;
|
|
atbm_memset(priv->link_id_db[link_id-1].buffered, 0, ATBMWIFI__MAX_TID);
|
|
}
|
|
|
|
return link_id;
|
|
}
|
|
int atbmwifi_sta_add(struct atbmwifi_vif *priv,
|
|
atbm_uint8 *sta_mac)
|
|
{
|
|
int link_id = 0;
|
|
struct atbmwifi_sta_priv *sta_priv = ATBM_NULL;
|
|
//struct atbmwifi_cfg *config = atbmwifi_get_config(priv);
|
|
|
|
if (!atbmwifi_is_ap_mode(priv->iftype))
|
|
return 0;
|
|
link_id = atbmwifi_find_hard_link_id(priv, sta_mac);
|
|
if(link_id !=0){
|
|
wifi_printk(WIFI_CONNECT,"sta_add again just drop \n");
|
|
return 0;
|
|
}
|
|
|
|
link_id = atbmwifi_find_link_id(priv, sta_mac);
|
|
if(link_id ==0){
|
|
wifi_printk(WIFI_CONNECT,"sta_add Error \n");
|
|
return -1;
|
|
}
|
|
|
|
priv->link_id_db[link_id-1].status = ATBMWIFI__LINK_HARD;
|
|
sta_priv = &priv->link_id_db[link_id-1].sta_priv;
|
|
sta_priv->link_id = link_id;
|
|
atbm_memset(&priv->link_id_db[link_id-1].sta_retry,0xff,sizeof(struct atbmwifi_filter_retry));
|
|
#if RATE_CONTROL_MODE
|
|
priv->link_id_db[link_id-1].sta_priv.sta_rc_priv = mac80211_ratectrl->alloc_sta();
|
|
mac80211_ratectrl->sta_rate_init(&sta_priv->rate,sta_priv->sta_rc_priv);
|
|
#endif
|
|
priv->sta_asleep_mask &= ~BIT(link_id);
|
|
priv->buffered_set_mask &= ~BIT(link_id);
|
|
atbmwifi_link_id_lmac(priv,link_id);
|
|
wifi_printk(WIFI_CONNECT,"[ap]:assoc OK %d\n",link_id);
|
|
#if ATBM_DRIVER_PROCESS_BA
|
|
if(priv->hw_priv->driver_setup_ba){
|
|
int i;
|
|
|
|
atbm_spin_lock_init(&sta_priv->lock);
|
|
if(!sta_priv->ampdu_mlme.init){
|
|
atbm_os_mutexLockInit(&sta_priv->ampdu_mlme.mtx);
|
|
sta_priv->ampdu_mlme.work = atbm_init_work(priv->hw_priv,
|
|
ieee80211_ba_session_work, sta_priv);
|
|
sta_priv->ampdu_mlme.init = 1;
|
|
}
|
|
sta_priv->priv = priv;
|
|
atbm_memcpy(sta_priv->mac, sta_mac, ATBM_ETH_ALEN);
|
|
sta_priv->link_id = link_id;
|
|
for (i = 0; i < STA_TID_NUM; i++) {
|
|
/*
|
|
* timer_to_tid must be initialized with identity mapping
|
|
* to enable session_timer's data differentiation. See
|
|
* sta_rx_agg_session_timer_expired for usage.
|
|
*/
|
|
sta_priv->timer_to_tid[i] = i;
|
|
sta_priv->rx_token[i] = -1;
|
|
sta_priv->ampdu_mlme.trylimit[i] = 0;
|
|
sta_priv->ampdu_mlme.timestamp[i] = atbm_GetOsTimeMs();
|
|
}
|
|
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
int atbmwifi_sta_del(struct atbmwifi_vif *priv,
|
|
atbm_uint8 * staMacAddr)
|
|
{
|
|
int link_id =0;
|
|
|
|
wifi_printk(WIFI_CONNECT,"[ap]:atbmwifi_sta_del \n");
|
|
|
|
if (!atbmwifi_is_ap_mode(priv->iftype))
|
|
return 0;
|
|
|
|
|
|
link_id = atbmwifi_find_link_id(priv, staMacAddr);
|
|
if((link_id > ATBMWIFI__MAX_STA_IN_AP_MODE) || ( link_id<=0)){
|
|
wifi_printk(WIFI_DBG_MSG,"[ap]:sta_del link_id 0 drop\n");
|
|
return -1;
|
|
}
|
|
//del hostapd sta priv
|
|
priv->link_id_db[link_id-1].sta_priv.reserved = ATBM_NULL;
|
|
atbmwifi_event_uplayer(priv,ATBM_WIFI_DEAUTH_EVENT,staMacAddr);
|
|
|
|
if((link_id <= ATBMWIFI__MAX_STA_IN_AP_MODE) && link_id>0){
|
|
#if ATBM_SUPPORT_BRIDGE
|
|
remove_item_from_brpool(link_id);
|
|
#endif
|
|
#if ATBM_DRIVER_PROCESS_BA
|
|
if(priv->hw_priv->driver_setup_ba){
|
|
if(priv->link_id_db[link_id-1].sta_priv.ampdu_mlme.init){
|
|
ieee80211_sta_tear_down_BA_sessions(&priv->link_id_db[link_id-1].sta_priv, ATBM_TRUE);
|
|
atbm_os_DeleteMutex(&priv->link_id_db[link_id-1].sta_priv.ampdu_mlme.mtx);
|
|
}
|
|
}
|
|
#endif
|
|
priv->link_id_db[link_id-1].status = ATBMWIFI__LINK_OFF;
|
|
__atbm_flush(priv->hw_priv, ATBM_FALSE, priv->if_id, BIT(link_id));
|
|
#if RATE_CONTROL_MODE
|
|
if(priv->link_id_db[link_id-1].sta_priv.sta_rc_priv){
|
|
mac80211_ratectrl->free_sta(priv->link_id_db[link_id-1].sta_priv.sta_rc_priv);
|
|
priv->link_id_db[link_id-1].sta_priv.sta_rc_priv = ATBM_NULL;
|
|
}
|
|
#endif
|
|
atbmwifi_del_key(priv,0, link_id);
|
|
#if ATBM_PKG_REORDER
|
|
atbm_reorder_func_reset(priv,link_id - 1);
|
|
#endif //ATBM_PKG_REORDER
|
|
_atbmwifi_unmap_link(priv, link_id);
|
|
priv->pspoll_mask &= ~BIT(link_id);
|
|
priv->sta_asleep_mask &= ~BIT(link_id);
|
|
priv->buffered_set_mask &= ~BIT(link_id);
|
|
atbm_memset(&priv->link_id_db[link_id-1].sta_retry,0xff,sizeof(struct atbmwifi_filter_retry));
|
|
wifi_printk(WIFI_DBG_ANY,"[ap]:sta_del link_id %d\n",link_id);
|
|
atbm_memset(&priv->link_id_db[link_id-1].sta_priv, 0, sizeof(struct atbmwifi_sta_priv));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct atbmwifi_sta_priv *atbmwifi_sta_find(struct atbmwifi_vif *priv,const atbm_uint8 *mac)
|
|
{
|
|
int i =0;
|
|
|
|
if (atbmwifi_is_sta_mode(priv->iftype))
|
|
return &priv->bss.sta_priv;
|
|
|
|
for (i = 0; i < ATBMWIFI__MAX_STA_IN_AP_MODE; ++i) {
|
|
if ((priv->link_id_db[i].status == ATBMWIFI__LINK_HARD) &&
|
|
!atbm_memcmp(mac, priv->link_id_db[i].mac, ATBM_ETH_ALEN)){
|
|
return &priv->link_id_db[i].sta_priv;
|
|
}
|
|
}
|
|
|
|
return ATBM_NULL;
|
|
}
|
|
|
|
struct atbmwifi_sta_priv *atbmwifi_sta_find_form_hard_linkid(struct atbmwifi_vif *priv,const atbm_uint8 linkid)
|
|
{
|
|
|
|
if (!atbmwifi_is_ap_mode(priv->iftype))
|
|
return ATBM_NULL;
|
|
|
|
if(linkid > ATBMWIFI__MAX_STA_IN_AP_MODE)
|
|
return ATBM_NULL;
|
|
if(linkid == 0)
|
|
return ATBM_NULL;
|
|
|
|
if(priv->link_id_db[linkid-1].status == ATBMWIFI__LINK_HARD)
|
|
return &priv->link_id_db[linkid-1].sta_priv;
|
|
else
|
|
return ATBM_NULL;
|
|
}
|
|
|
|
struct atbmwifi_sta_priv *atbmwifi_sta_find_form_linkid(struct atbmwifi_vif *priv,const atbm_uint8 linkid)
|
|
{
|
|
|
|
if (!atbmwifi_is_ap_mode(priv->iftype))
|
|
return ATBM_NULL;
|
|
|
|
if(linkid > ATBMWIFI__MAX_STA_IN_AP_MODE)
|
|
return ATBM_NULL;
|
|
if(linkid == 0)
|
|
return ATBM_NULL;
|
|
|
|
if(priv->link_id_db[linkid-1].status != ATBMWIFI__LINK_OFF)
|
|
return &priv->link_id_db[linkid-1].sta_priv;
|
|
else
|
|
return ATBM_NULL;
|
|
}
|
|
|
|
static atbm_void __atbm_sta_notify(struct atbmwifi_vif *priv,
|
|
enum sta_notify_cmd notify_cmd,
|
|
int link_id)
|
|
{
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
atbm_uint32 bit, prev;
|
|
|
|
/* Zero link id means "for all link IDs" */
|
|
if (link_id){
|
|
bit = BIT(link_id);
|
|
}
|
|
else if (ATBM_WARN_ON(notify_cmd != STA_NOTIFY_AWAKE)){
|
|
bit = 0;
|
|
}
|
|
else{
|
|
bit = priv->link_id_map;
|
|
}
|
|
prev = priv->sta_asleep_mask & bit;
|
|
switch (notify_cmd) {
|
|
case STA_NOTIFY_SLEEP:
|
|
if (!prev) {
|
|
if (priv->buffered_multicasts &&
|
|
!priv->sta_asleep_mask)
|
|
atbm_queue_work(priv->hw_priv, priv->set_tim_work);
|
|
priv->sta_asleep_mask |= bit;
|
|
wifi_printk(WIFI_PS,"STA_NOTIFY_SLEEP--->sta_asleep_mask %x\n",priv->sta_asleep_mask);
|
|
}
|
|
break;
|
|
case STA_NOTIFY_AWAKE:
|
|
if (prev) {
|
|
priv->sta_asleep_mask &= ~bit;
|
|
priv->pspoll_mask &= ~bit;
|
|
priv->link_id_uapsd_mask &= ~bit;
|
|
if (priv->tx_multicast && link_id &&
|
|
!priv->sta_asleep_mask)
|
|
atbm_queue_work(priv->hw_priv, priv->set_tim_work);
|
|
atbm_bh_wakeup(hw_priv);
|
|
wifi_printk(WIFI_PS,"STA_NOTIFY_AWAKE--->sta_asleep_mask %x\n",priv->sta_asleep_mask);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
atbm_void atbm_ps_notify(struct atbmwifi_vif *priv,
|
|
int link_id, ATBM_BOOL ps)
|
|
{
|
|
if (link_id > ATBMWIFI__MAX_STA_IN_AP_MODE)
|
|
return;
|
|
|
|
wifi_printk(WIFI_PS,"%s for LinkId: %d. STAs asleep: %.8X\n",
|
|
ps ? "Stop" : "Start",
|
|
link_id, priv->sta_asleep_mask);
|
|
|
|
/* TODO:COMBO: __atbm_sta_notify changed. */
|
|
__atbm_sta_notify(priv,
|
|
ps ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE, link_id);
|
|
}
|
|
|
|
int atbm_set_tim_impl(struct atbmwifi_vif *priv)
|
|
{
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
|
|
struct atbmwifi_cfg *config=atbmwifi_get_config(priv);
|
|
atbm_uint8 * tim_ie =ATBM_NULL;
|
|
atbm_uint8 * tim_ie_end=ATBM_NULL;
|
|
atbm_uint8 aid0_bit_set;
|
|
struct wsm_update_ie update_ie={0};
|
|
update_ie.what = WSM_UPDATE_IE_BEACON;
|
|
update_ie.count = 1;
|
|
update_ie.length = 0;
|
|
tim_ie = (atbm_uint8 *)atbm_kmalloc(sizeof(struct atbmwifi_ieee80211_tim_ie)+ ATBMWIFI__MAX_STA_IN_AP_MODE/8 + 4,GFP_KERNEL);
|
|
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
aid0_bit_set = priv->buffered_multicasts;
|
|
tim_ie_end = atbmwifi_add_tim(tim_ie,priv,priv->buffered_multicasts);
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
if(aid0_bit_set != priv->aid0_bit_set){
|
|
long tmo=0;
|
|
tmo=config->DTIMPeriod*(config->beaconInterval + 20);
|
|
atbmwifi_eloop_register_timeout(0,tmo,atbmwifi_mcast_timeout,(atbm_void *)priv,ATBM_NULL);
|
|
}
|
|
|
|
update_ie.ies = tim_ie;
|
|
update_ie.length = (atbm_uint32)tim_ie_end-(atbm_uint32)tim_ie;
|
|
ATBM_WARN_ON_FUNC(wsm_update_ie(hw_priv, &update_ie, priv->if_id));
|
|
priv->aid0_bit_set = aid0_bit_set;
|
|
|
|
atbm_kfree(tim_ie);
|
|
|
|
return 0;
|
|
}
|
|
|
|
atbm_void atbm_ap_set_tim_work(struct atbm_work_struct *work)
|
|
{
|
|
struct atbmwifi_vif *priv=(struct atbmwifi_vif *)work;
|
|
if(atbm_bh_is_term(priv->hw_priv)){
|
|
return;
|
|
}
|
|
atbm_set_tim_impl(priv);
|
|
}
|
|
|
|
int atbm_set_tim(struct atbmwifi_vif *priv, struct atbmwifi_sta_priv *sta_priv,ATBM_BOOL set)
|
|
{
|
|
if(atbm_bh_is_term(priv->hw_priv)){
|
|
return 0;
|
|
}
|
|
#ifdef P2P_MULTIVIF
|
|
ATBM_WARN_ON_FUNC(priv->if_id == ATBM_WIFI_GENERIC_IF_ID);
|
|
#endif
|
|
ATBM_WARN_ON_FUNC(!atbmwifi_is_ap_mode(priv->iftype));
|
|
if(atbmwifi_set_tim(priv,sta_priv->link_id,set)){
|
|
if(sta_priv->priv->sta_asleep_mask & BIT(sta_priv->link_id)){
|
|
atbm_queue_work(priv->hw_priv, priv->set_tim_work);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
/*if timeout ,must send mulcast frame*/
|
|
atbm_void atbmwifi_mcast_timeout(atbm_void *data1,atbm_void *data2)
|
|
{
|
|
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)data1;
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
priv->tx_multicast = priv->aid0_bit_set && priv->buffered_multicasts;
|
|
if (priv->tx_multicast){
|
|
// atbm_os_wakeup_event(&_atbmwifi_vifpriv_to_hwpriv(priv)->tx_bh_wq);
|
|
atbm_bh_schedule_tx(_atbmwifi_vifpriv_to_hwpriv(priv));
|
|
}
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* WSM callback LMACtoUMAC_SuspendResumeTxInd when tx DTIM */
|
|
atbm_void atbm_suspend_resume(struct atbmwifi_vif *priv,
|
|
struct wsm_suspend_resume *arg)
|
|
{
|
|
struct atbmwifi_common *hw_priv =
|
|
_atbmwifi_vifpriv_to_hwpriv(priv);
|
|
|
|
wifi_printk(WIFI_PS, "[AP] %s: %s\n",
|
|
arg->stop ? "stop" : "start",
|
|
arg->multicast ? "broadcast" : "unicast");
|
|
|
|
if (arg->multicast) {
|
|
ATBM_BOOL cancel_tmo = ATBM_FALSE;
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
if (arg->stop) {
|
|
priv->tx_multicast = ATBM_FALSE;
|
|
} else {
|
|
#if NEW_SUPPORT_PS
|
|
//atbm_uint32 ac,n_frames;
|
|
/* Firmware sends this indication every DTIM if there
|
|
* is a STA in powersave connected. There is no reason
|
|
* to suspend, following wakeup will consume much more
|
|
* power than it could be saved. */
|
|
|
|
priv->tx_multicast = (priv->aid0_bit_set &&priv->buffered_multicasts);
|
|
if(priv->tx_multicast)
|
|
{
|
|
cancel_tmo= ATBM_TRUE;
|
|
// wifi_printk(WIFI_PS,"--->muticast num n_frames =%d\n",n_frames);
|
|
atbm_bh_schedule_tx(priv->hw_priv);
|
|
}
|
|
|
|
|
|
#endif
|
|
}
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
if (cancel_tmo)
|
|
atbmwifi_eloop_cancel_timeout(atbmwifi_mcast_timeout, (atbm_void *)priv, ATBM_NULL);
|
|
} else {
|
|
/*lmac call here when p2p ps mode*/
|
|
atbm_spin_lock_bh(&priv->ps_state_lock);
|
|
atbm_ps_notify(priv, arg->link_id, arg->stop);
|
|
atbm_spin_unlock_bh(&priv->ps_state_lock);
|
|
if (!arg->stop)
|
|
atbm_bh_wakeup(hw_priv);
|
|
}
|
|
return;
|
|
}
|
|
int atbmwifi_ap_deauth(struct atbmwifi_vif *priv,atbm_uint8 *staMacAddr)
|
|
{
|
|
int link_id = atbmwifi_find_link_id(priv, staMacAddr);
|
|
//wifi_printk(WIFI_ALWAYS,"%s\n",__FUNCTION__);
|
|
if((link_id > ATBMWIFI__MAX_STA_IN_AP_MODE) || ( link_id<0)){
|
|
return -1;
|
|
}
|
|
atbmwifi_sta_del(priv,staMacAddr);
|
|
return 1;
|
|
}
|
|
|
|
int atbmwifi_ap_start_proberesp(struct atbmwifi_vif *priv)
|
|
{
|
|
int ret;
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
struct wsm_template_frame frame={0};
|
|
frame.frame_type = WSM_FRAME_TYPE_PROBE_RESPONSE;
|
|
frame.disable =0;
|
|
//frame.rate = test_config_txrx.Rate;
|
|
#if CONFIG_P2P
|
|
if(priv->p2p_ap)
|
|
frame.rate = RATE_INDEX_A_6M;
|
|
else
|
|
#endif
|
|
#if CONFIG_5G_SUPPORT
|
|
if(priv->bss.sta_priv.band == ATBM_IEEE80211_BAND_5GHZ)
|
|
frame.rate = RATE_INDEX_A_6M;
|
|
else
|
|
#endif
|
|
frame.rate = RATE_INDEX_B_1M;
|
|
frame.skb = atbmwifi_ieee80211_send_proberesp(priv,priv->extra_ie,priv->extra_ie_len);
|
|
if (ATBM_WARN_ON(!frame.skb))
|
|
return 0;
|
|
ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
|
|
atbm_dev_kfree_skb(frame.skb);
|
|
|
|
return ret;
|
|
}
|
|
int atbmwifi_ap_start_beacon(struct atbmwifi_vif *priv)
|
|
{
|
|
int ret = 0;
|
|
struct atbmwifi_common *hw_priv =_atbmwifi_vifpriv_to_hwpriv(priv);
|
|
struct wsm_template_frame frame={0};
|
|
frame.frame_type = WSM_FRAME_TYPE_BEACON;
|
|
frame.disable =0;
|
|
|
|
//frame.rate = test_config_txrx.Rate;
|
|
#if CONFIG_P2P
|
|
if(priv->p2p_ap)
|
|
frame.rate = RATE_INDEX_A_6M;
|
|
else
|
|
#endif
|
|
#if CONFIG_5G_SUPPORT
|
|
if(priv->bss.sta_priv.band == ATBM_IEEE80211_BAND_5GHZ)
|
|
frame.rate = RATE_INDEX_A_6M;
|
|
else
|
|
#endif
|
|
frame.rate = RATE_INDEX_B_1M;
|
|
frame.skb = atbmwifi_ieee80211_send_beacon(priv,priv->extra_ie,priv->extra_ie_len);
|
|
if (ATBM_WARN_ON(!frame.skb))
|
|
return 0;
|
|
|
|
ret = wsm_set_template_frame(hw_priv, &frame, priv->if_id);
|
|
if (!ret)
|
|
{
|
|
atbmwifi_ap_start_proberesp(priv);
|
|
}
|
|
|
|
atbm_dev_kfree_skb(frame.skb);
|
|
|
|
return ret;
|
|
}
|
|
int atbm_start_ap(struct atbmwifi_vif *priv)
|
|
{
|
|
int ret;
|
|
struct atbmwifi_cfg *config = atbmwifi_get_config(priv);
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
struct wsm_start start={0};
|
|
struct wsm_inactivity inactivity={0} ;
|
|
struct wsm_operational_mode mode={0};
|
|
start.mode = priv->config.mode;
|
|
start.band = priv->config.band;
|
|
start.channelNumber = config->channel_index;
|
|
start.beaconInterval = config->beaconInterval;
|
|
start.DTIMPeriod = config->DTIMPeriod;
|
|
start.preambleType = config->preambleType;
|
|
start.probeDelay = 100;
|
|
start.basicRateSet = config->basicRateSet;
|
|
// start.channel_type = hw_priv->channel_type;
|
|
start.channel_type = priv->bss.channel_type;
|
|
|
|
inactivity.min_inactivity = 39;
|
|
inactivity.max_inactivity = 1;
|
|
|
|
mode.power_mode = wsm_power_mode_active;
|
|
mode.disableMoreFlagUsage = ATBM_TRUE;
|
|
|
|
if (priv->if_id)
|
|
start.mode |= WSM_FLAG_MAC_INSTANCE_1;
|
|
else
|
|
start.mode &= ~WSM_FLAG_MAC_INSTANCE_1;
|
|
|
|
if(priv->hw_priv->channel_type == ATBM_NL80211_CHAN_HT40PLUS){
|
|
config->secondary_channel=1;//above bandwidth
|
|
}else{
|
|
config->secondary_channel=-1;//below bandwidth
|
|
}
|
|
atbmwifi_ap_start_beacon(priv);
|
|
|
|
priv->tx_multicast = ATBM_FALSE;
|
|
priv->aid0_bit_set = ATBM_FALSE;
|
|
priv->buffered_multicasts = ATBM_FALSE;
|
|
priv->pspoll_mask = 0;
|
|
priv->link_id_uapsd_mask=0;
|
|
//atbm_InitTimer(&priv->mcast_timeout,atbmwifi_mcast_timeout,(atbm_void*)priv);
|
|
|
|
start.ssidLength = priv->config.ssid_len;
|
|
atbm_memcpy(&start.ssid[0], priv->config.ssid, start.ssidLength);
|
|
atbm_memset(&priv->link_id_db[0], 0, sizeof(priv->link_id_db));
|
|
|
|
wifi_printk(WIFI_CONNECT, "[AP] ch: %d(%d), bcn: %d(%d), "
|
|
"brt: 0x%x, ssid: %s %d\n",
|
|
start.channelNumber, start.band,
|
|
start.beaconInterval, start.DTIMPeriod,
|
|
start.basicRateSet,
|
|
start.ssid,priv->if_id);
|
|
|
|
ret = wsm_start(hw_priv, &start, priv->if_id);
|
|
wsm_set_inactivity(hw_priv, &inactivity, priv->if_id);
|
|
if (!ret) {
|
|
priv->join_status = ATBMWIFI__JOIN_STATUS_AP;
|
|
atbmwifi_event_uplayer(priv,ATBM_WIFI_ENABLE_NET_EVENT,ATBM_NULL);
|
|
}
|
|
|
|
wsm_set_block_ack_policy(hw_priv,
|
|
hw_priv->ba_tid_tx_mask,
|
|
hw_priv->ba_tid_rx_mask,
|
|
priv->if_id);
|
|
wsm_set_operational_mode(hw_priv, &mode, priv->if_id);
|
|
return ret;
|
|
}
|
|
|
|
atbm_void atbmwifi_ap_deauth_sta(struct atbmwifi_vif *priv,atbm_uint8 link_id,int reason_code)
|
|
{
|
|
|
|
struct atbmwifi_sta_priv * sta_priv = atbmwifi_sta_find_form_linkid(priv,priv->connect_timer_linkid);
|
|
if(sta_priv){
|
|
wifi_printk(WIFI_ALWAYS,"atbmwifi_ap_deauth_sta\n");
|
|
atbmwifi_ieee80211_tx_mgmt_deauth(priv,sta_priv->mac,priv->bssid,reason_code);
|
|
if(atbmwifi_ap_deauth(priv,sta_priv->mac) < 0){
|
|
atbmwifi_event_uplayer(priv,ATBM_WIFI_DEAUTH_EVENT,sta_priv->mac);
|
|
}
|
|
}
|
|
}
|
|
atbm_void atbmwifi_ap_join_timeout(atbm_void *data1,atbm_void *data2)
|
|
{
|
|
//atbmwifi_autoconnect(priv);
|
|
struct atbmwifi_vif *priv=(struct atbmwifi_vif *)data1;
|
|
wifi_printk(WIFI_WPA,"atbm: atbmwifi_ap_join_timeout(), ms=%d\n", atbm_GetOsTimeMs());
|
|
atbmwifi_ap_deauth_sta(priv,priv->connect_timer_linkid,ATBM_WLAN_REASON_DISASSOC_STA_HAS_LEFT);
|
|
}
|
|
atbm_void atbmwifi_ap_deauth_all(struct atbmwifi_vif *priv)
|
|
{
|
|
//del group key
|
|
atbmwifi_del_key(priv,1,1);
|
|
if(priv->bss.information_elements){
|
|
atbm_kfree(priv->bss.information_elements);
|
|
priv->bss.information_elements = ATBM_NULL;
|
|
priv->bss.len_information_elements = 0;
|
|
}
|
|
#if ATBM_PKG_REORDER
|
|
atbm_reorder_func_reset(priv,0xff);
|
|
#endif
|
|
|
|
}
|
|
|
|
atbm_void atbmwifi_stop_ap(struct atbmwifi_vif *priv)
|
|
{
|
|
int i;
|
|
atbm_uint8 cnt = 0;
|
|
atbm_uint32 link_id_map = 0;
|
|
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
struct atbmwifi_cfg *config = atbmwifi_get_config(priv);
|
|
struct wsm_reset reset={0};
|
|
struct wsm_operational_mode mode={0};
|
|
{
|
|
reset.reset_statistics = ATBM_TRUE;
|
|
};
|
|
|
|
if(!priv->enabled){
|
|
wifi_printk(WIFI_ALWAYS,"atbmwifi_stop_ap drop\n");
|
|
goto ap_off;
|
|
}
|
|
wifi_printk(WIFI_ALWAYS,"%s\n",__FUNCTION__);
|
|
|
|
if(!atbmwifi_is_ap_mode(priv->iftype)){
|
|
goto ap_off;
|
|
}
|
|
|
|
atbm_cancel_work(hw_priv, priv->scan.ap_scan_work);
|
|
|
|
|
|
link_id_map = priv->link_id_map;
|
|
wifi_printk(WIFI_ALWAYS,"%s link_id_map=0x%x\n",__FUNCTION__, link_id_map);
|
|
for (i = 0; link_id_map; ++i) {
|
|
if (link_id_map & BIT(i)) {
|
|
if(i > 0){
|
|
while(cnt++ < 3){
|
|
atbmwifi_ieee80211_tx_mgmt_deauth(priv, priv->link_id_db[i-1].mac, priv->bssid, ATBM_WLAN_REASON_DISASSOC_AP_BUSY);
|
|
atbmwifi_ieee80211_send_deauth_disassoc(priv, priv->link_id_db[i-1].mac,priv->bssid,
|
|
ATBM_IEEE80211_STYPE_DISASSOC,
|
|
ATBM_WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
|
|
ATBM_NULL, ATBM_TRUE);
|
|
|
|
}
|
|
|
|
cnt = 0;
|
|
}
|
|
link_id_map &= ~BIT(i);
|
|
}
|
|
}
|
|
|
|
__atbm_flush(hw_priv, ATBM_FALSE, priv->if_id, BIT(0));
|
|
mode.power_mode = wsm_power_mode_quiescent;
|
|
mode.disableMoreFlagUsage = ATBM_TRUE;
|
|
|
|
for (i = 0; priv->link_id_map; ++i) {
|
|
if (priv->link_id_map & BIT(i)) {
|
|
if(i > 0){
|
|
atbmwifi_ap_deauth(priv, priv->link_id_db[i-1].mac);
|
|
}
|
|
priv->link_id_map &= ~BIT(i);
|
|
}
|
|
}
|
|
atbmwifi_ap_deauth_all(priv);
|
|
priv->enabled = 0;
|
|
atbm_memset(priv->link_id_db, 0,sizeof(priv->link_id_db));
|
|
priv->sta_asleep_mask = 0;
|
|
priv->buffered_set_mask = 0;
|
|
priv->enable_beacon = ATBM_FALSE;
|
|
priv->tx_multicast = ATBM_FALSE;
|
|
priv->aid0_bit_set = ATBM_FALSE;
|
|
priv->buffered_multicasts = ATBM_FALSE;
|
|
priv->pspoll_mask = 0;
|
|
reset.link_id = 0;
|
|
wsm_reset(priv->hw_priv, &reset, priv->if_id);
|
|
ATBM_WARN_ON_FUNC(wsm_set_operational_mode(priv->hw_priv, &mode, priv->if_id));
|
|
priv->connect.crypto_pairwise=0;
|
|
priv->connect.crypto_group=0;
|
|
priv->connect.encrype = 0;
|
|
priv->assoc_ok = 0;
|
|
priv->connect_ok = 0;
|
|
atbmwifi_eloop_cancel_timeout(atbmwifi_mcast_timeout, (atbm_void *)priv, ATBM_NULL);
|
|
atbmwifi_eloop_cancel_timeout(atbmwifi_ap_join_timeout, (atbm_void *)priv, ATBM_NULL);
|
|
atbmwifi_eloop_cancel_timeout(atbmwifi_queued_timeout,(atbm_void *)hw_priv->tx_queue,ATBM_NULL);
|
|
|
|
atbmwifi_event_uplayer(priv,ATBM_WIFI_DEAUTH_EVENT,atbm_broadcast_ether_addr);
|
|
atbmwifi_event_uplayer(priv,ATBM_WIFI_DISENABLE_NET_EVENT,ATBM_NULL);
|
|
priv->join_status = ATBMWIFI__JOIN_STATUS_PASSIVE;
|
|
atbm_memset(config,0,sizeof(struct atbmwifi_cfg));
|
|
atbm_clear_scan_req(priv);
|
|
|
|
if(priv->extra_ie){
|
|
atbm_kfree(priv->extra_ie);
|
|
priv->extra_ie = ATBM_NULL;
|
|
}
|
|
free_hostapd(priv);
|
|
priv->appdata = ATBM_NULL;
|
|
atbm_mdelay(100);
|
|
ap_off:
|
|
priv->iftype = ATBM_NUM_NL80211_IFTYPES;
|
|
}
|
|
atbm_void atbmwifi_start_hostapd(struct atbmwifi_vif *priv)
|
|
{
|
|
priv->appdata = init_hostapd(priv);
|
|
}
|
|
atbm_void atbmwifi_start_ap(struct atbmwifi_vif *priv)
|
|
{
|
|
struct atbmwifi_common * hw_priv = priv->hw_priv;
|
|
wifi_printk(WIFI_ALWAYS,"atbmwifi_start_ap++\n");
|
|
priv->config.mode = (priv->iftype == ATBM_NL80211_IFTYPE_P2P_GO) ? WSM_START_MODE_P2P_GO : WSM_START_MODE_AP;
|
|
|
|
#if CONFIG_P2P
|
|
priv->bss.sta_priv.wmm_used = 1;
|
|
priv->bss.sta_priv.uapsd_supported = 1;
|
|
priv->bss.sta_priv.ht = 1;
|
|
priv->bss.parameter_set_count=1;
|
|
priv->bss.channel_type = ATBM_NL80211_CHAN_HT20;
|
|
#endif
|
|
|
|
atbm_memcpy(priv->bssid ,priv->mac_addr,ATBM_ETH_ALEN);
|
|
atbm_memcpy(priv->config.bssid,priv->bssid,6);
|
|
priv->enabled = 1;
|
|
atbmwifi_start_hostapd(priv);
|
|
//atbm_InitTimer(&priv->connect_expire_timer,atbmwifi_ap_join_timeout,(atbm_void*)priv);
|
|
priv->scan.ap_scan_work = atbm_init_work(hw_priv, atbmwifi_ap_scan_start,priv);
|
|
}
|
|
|
|
int atbmwifi_ap_scan_start(struct atbm_work_struct *work)
|
|
{
|
|
struct atbmwifi_vif *priv=(struct atbmwifi_vif *)work;
|
|
|
|
if(priv->scan.ApScan_in_process){
|
|
return;
|
|
}
|
|
|
|
priv->scan.ApScan_in_process = 1;
|
|
|
|
atbmwifi_init_scan_req(priv, ATBM_SCAN_24G_ACTIVE);
|
|
#if CONFIG_5G_SUPPORT
|
|
atbmwifi_init_scan_req(priv, ATBM_SCAN_5G_PASSAVE);
|
|
#endif
|
|
atbm_req_scan_start(priv);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ap_scan(struct atbmwifi_vif *priv)
|
|
{
|
|
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
|
|
|
|
atbm_queue_work(hw_priv,priv->scan.ap_scan_work);
|
|
return 0;
|
|
}
|
|
|
|
int atbmwifi_ap_auto_process(struct atbmwifi_vif *priv)
|
|
{
|
|
wifi_printk(WIFI_ALWAYS,"%s ApScan_in_process=%d\n",__FUNCTION__,priv->scan.ApScan_in_process);
|
|
if(!priv->scan.ApScan_in_process){
|
|
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 -1;
|
|
}
|
|
}
|
|
priv->scan_ret.len = 0;
|
|
priv->scan.if_id = priv->if_id;
|
|
priv->scan_no_connect = 1;
|
|
return ap_scan(priv);
|
|
}
|
|
else {
|
|
wifi_printk(WIFI_ALWAYS,"scan busy!please try later!");
|
|
return -2;
|
|
}
|
|
}
|
|
static int WEIGHT(int x){
|
|
if((x)<=-75){
|
|
return 0;
|
|
}else if((x)<=-65){
|
|
return 1;
|
|
}else if((x)<=-50){
|
|
return 2;
|
|
}else if((x)>-50){
|
|
return 3;
|
|
}
|
|
return 3;
|
|
}
|
|
|
|
#define NUM_AP_CHNN 13
|
|
#define MIN(x,y) ((x)<(y)?(x):(y))
|
|
|
|
#define WAIT_CMP(x) \
|
|
while (x) { \
|
|
atbm_mdelay(3000); \
|
|
} \
|
|
|
|
static atbm_uint8 ReturnMin_InSort_1(atbm_uint8 * aCHList,atbm_uint8 *ChanArray,atbm_uint8 index,atbm_uint8 offset){
|
|
atbm_uint8 i,j;
|
|
atbm_uint8 minIndex;
|
|
minIndex=i=0;
|
|
for(j=i+1;j<index;++j){
|
|
if(aCHList[ChanArray[j]-offset]<aCHList[ChanArray[minIndex]-offset])
|
|
minIndex=j;
|
|
}
|
|
// if(minIndex!=i)
|
|
// AtbmSwap(&aCHList[ChanArray[i]-offset], &aCHList[ChanArray[minIndex]-offset]);
|
|
|
|
//wifi_printk(WIFI_ALWAYS,"Array[ChanArray[%d] %d\n",i,aCHList[ChanArray[i]-offset]);
|
|
//}
|
|
//wifi_printk(WIFI_ALWAYS,"ReturnMin_InSort_1 minIndex=%d: %d\n",minIndex,ChanArray[minIndex]);
|
|
return ChanArray[minIndex];
|
|
}
|
|
int atbm_autoChann_Select(struct atbmwifi_vif *priv,atbm_uint8 *SetChan)
|
|
{
|
|
atbm_uint8 chanNum,index=0,ssidNum=0;
|
|
atbm_uint8 aCHList[NUM_AP_CHNN]={0};
|
|
atbm_uint8 MinChanNum[14]={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
|
|
|
|
WLAN_SCAN_RESULT *AutoScanBuf=ATBM_NULL;
|
|
WLAN_BSS_INFO *bss_info;
|
|
struct atbmwifi_scan_result_info *info;
|
|
struct atbmwifi_common *hw_priv =priv->hw_priv;
|
|
/*For AP ScanEnd Flag */
|
|
hw_priv->ApScan_process_flag=1;
|
|
/*Do ap auto scan process*/
|
|
WAIT_CMP(!priv->enabled);
|
|
if(atbmwifi_ap_auto_process(priv)){
|
|
return -1;
|
|
}
|
|
/*Wait for scan cmp*/
|
|
WAIT_CMP(priv->scan.ApScan_in_process);
|
|
/*It means No ap in all channl,default channel 11*/
|
|
if(priv->scan_ret.len==0){
|
|
*SetChan=2;
|
|
}else{
|
|
AutoScanBuf=(WLAN_SCAN_RESULT*)atbm_kmalloc(priv->scan_ret.len*sizeof(WLAN_SCAN_RESULT),GFP_KERNEL);
|
|
bss_info = (WLAN_BSS_INFO *)(&AutoScanBuf->bss_info[0]);
|
|
for(ssidNum=0;ssidNum<priv->scan_ret.len;ssidNum++){
|
|
info = priv->scan_ret.info + ssidNum;
|
|
bss_info->chanspec = info->channel;
|
|
bss_info->RSSI = info->rssi;
|
|
/*Auto chann select process*/
|
|
switch(bss_info->chanspec){
|
|
case 1:
|
|
if(bss_info->chanspec+1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec+3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+3]+=WEIGHT(bss_info->RSSI-8);
|
|
break;
|
|
case 2:
|
|
if(bss_info->chanspec-1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec+3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+3]+=WEIGHT(bss_info->RSSI-8);
|
|
break;
|
|
case 3:
|
|
if(bss_info->chanspec-2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec-1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec+3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+3]+=WEIGHT(bss_info->RSSI-8);
|
|
break;
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
if(bss_info->chanspec-3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-3]+=WEIGHT(bss_info->RSSI-8);
|
|
if(bss_info->chanspec-2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec-1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec+3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+3]+=WEIGHT(bss_info->RSSI-8);
|
|
break;
|
|
case 11:
|
|
if(bss_info->chanspec-3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-3]+=WEIGHT(bss_info->RSSI-8);
|
|
if(bss_info->chanspec-2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec-1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+2]+=WEIGHT(bss_info->RSSI-4);
|
|
break;
|
|
case 12:
|
|
if(bss_info->chanspec-3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-3]+=WEIGHT(bss_info->RSSI-8);
|
|
if(bss_info->chanspec-2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec-1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-1]+=WEIGHT(bss_info->RSSI-2);
|
|
if(bss_info->chanspec+1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec+1]+=WEIGHT(bss_info->RSSI-2);
|
|
break;
|
|
case 13:
|
|
if(bss_info->chanspec-3 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-3]+=WEIGHT(bss_info->RSSI-8);
|
|
if(bss_info->chanspec-2 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-2]+=WEIGHT(bss_info->RSSI-4);
|
|
if(bss_info->chanspec+1 >= NUM_AP_CHNN) break;
|
|
aCHList[bss_info->chanspec-1]+=WEIGHT(bss_info->RSSI-2);
|
|
break;
|
|
default:
|
|
wifi_printk(WIFI_ALWAYS,"Channel Num > 13\n");
|
|
break;
|
|
}
|
|
aCHList[bss_info->chanspec]+=WEIGHT(bss_info->RSSI);
|
|
|
|
bss_info++;
|
|
}
|
|
|
|
for(chanNum=1;chanNum<NUM_AP_CHNN+1;chanNum++){
|
|
if(hw_priv->busy_ratio[chanNum]<110){
|
|
MinChanNum[index]=chanNum;
|
|
index++;
|
|
}
|
|
}
|
|
/*There is no busy_ratio<60 channl*/
|
|
if(index==0){
|
|
/*Do hw_priv->busy_ratio[chanNum] sort*/
|
|
//*SetChan=ReturnMin_InSort(&hw_priv->busy_ratio[0],0,chanNum);
|
|
*SetChan=ReturnMin_InSort_1(&hw_priv->busy_ratio[1],&MinChanNum[0],NUM_AP_CHNN,1);
|
|
}else{
|
|
/*Do MinChanNum[index] sort*/
|
|
//*SetChan=ReturnMin_InSort(&aCHList[MinChanNum[0]],MinChanNum[0],MinChanNum[index]);
|
|
*SetChan=ReturnMin_InSort_1(&aCHList[MinChanNum[0]],&MinChanNum[0],index,MinChanNum[0]);
|
|
}
|
|
}
|
|
atbm_kfree(AutoScanBuf);
|
|
wifi_printk(WIFI_ALWAYS,"SetChan =%d\n",*SetChan);
|
|
return 0;
|
|
}
|
|
|
|
|