diff options
Diffstat (limited to 'drivers/net/wireless/rtl8723as/core')
24 files changed, 16428 insertions, 13705 deletions
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_ap.c b/drivers/net/wireless/rtl8723as/core/rtw_ap.c index 4213f3bdf1b4..adebe11f32c7 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_ap.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_ap.c @@ -1,2936 +1,2939 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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, USA - * - * - ******************************************************************************/ -#define _RTW_AP_C_ - -#include <drv_conf.h> -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> - - -#ifdef CONFIG_AP_MODE - -extern unsigned char RTW_WPA_OUI[]; -extern unsigned char WMM_OUI[]; -extern unsigned char WPS_OUI[]; -extern unsigned char P2P_OUI[]; -extern unsigned char WFD_OUI[]; - -void init_mlme_ap_info(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - - _rtw_spinlock_init(&pmlmepriv->bcn_update_lock); - - //for ACL - _rtw_init_queue(&pacl_list->acl_node_q); - - //pmlmeext->bstart_bss = _FALSE; - - start_ap_mode(padapter); -} - -void free_mlme_ap_info(_adapter *padapter) -{ - _irqL irqL; - struct sta_info *psta=NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - //stop_ap_mode(padapter); - - pmlmepriv->update_bcn = _FALSE; - pmlmeext->bstart_bss = _FALSE; - - rtw_sta_flush(padapter); - - pmlmeinfo->state = _HW_STATE_NOLINK_; - - //free_assoc_sta_resources - rtw_free_all_stainfo(padapter); - - //free bc/mc sta_info - psta = rtw_get_bcmc_stainfo(padapter); - _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - rtw_free_stainfo(padapter, psta); - _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - - - _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); - -} - -static void update_BCNTIM(_adapter *padapter) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network); - unsigned char *pie = pnetwork_mlmeext->IEs; - - //DBG_871X("%s\n", __FUNCTION__); - - //update TIM IE - //if(pstapriv->tim_bitmap) - if(_TRUE) - { - u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL; - u16 tim_bitmap_le; - uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - - tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap); - - p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_); - if (p != NULL && tim_ielen>0) - { - tim_ielen += 2; - - premainder_ie = p+tim_ielen; - - tim_ie_offset = (sint)(p -pie); - - remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen; - - //append TIM IE from dst_ie offset - dst_ie = p; - } - else - { - tim_ielen = 0; - - //calucate head_len - offset = _FIXED_IE_LENGTH_; - - /* get ssid_ie len */ - p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)); - if (p != NULL) - offset += tmp_len+2; - - // get supported rates len - p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_)); - if (p != NULL) - { - offset += tmp_len+2; - } - - //DS Parameter Set IE, len=3 - offset += 3; - - premainder_ie = pie + offset; - - remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen; - - //append TIM IE from offset - dst_ie = pie + offset; - - } - - - if(remainder_ielen>0) - { - pbackup_remainder_ie = rtw_malloc(remainder_ielen); - if(pbackup_remainder_ie && premainder_ie) - _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - *dst_ie++=_TIM_IE_; - - if((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc)) - tim_ielen = 5; - else - tim_ielen = 4; - - *dst_ie++= tim_ielen; - - *dst_ie++=0;//DTIM count - *dst_ie++=1;//DTIM peroid - - if(pstapriv->tim_bitmap&BIT(0))//for bc/mc frames - *dst_ie++ = BIT(0);//bitmap ctrl - else - *dst_ie++ = 0; - - if(tim_ielen==4) - { - *dst_ie++ = *(u8*)&tim_bitmap_le; - } - else if(tim_ielen==5) - { - _rtw_memcpy(dst_ie, &tim_bitmap_le, 2); - dst_ie+=2; - } - - //copy remainder IE - if(pbackup_remainder_ie) - { - _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - - rtw_mfree(pbackup_remainder_ie, remainder_ielen); - } - - offset = (uint)(dst_ie - pie); - pnetwork_mlmeext->IELength = offset + remainder_ielen; - - } - -#ifndef CONFIG_INTERRUPT_BASED_TXBCN -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) - set_tx_beacon_cmd(padapter); -#endif -#endif //!CONFIG_INTERRUPT_BASED_TXBCN - - -} - -void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len) -{ - PNDIS_802_11_VARIABLE_IEs pIE; - u8 bmatch = _FALSE; - u8 *pie = pnetwork->IEs; - u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL; - u32 i, offset, ielen, ie_offset, remainder_ielen = 0; - - for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;) - { - pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i); - - if (pIE->ElementID > index) - { - break; - } - else if(pIE->ElementID == index) // already exist the same IE - { - p = (u8 *)pIE; - ielen = pIE->Length; - bmatch = _TRUE; - break; - } - - p = (u8 *)pIE; - ielen = pIE->Length; - i += (pIE->Length + 2); - } - - if (p != NULL && ielen>0) - { - ielen += 2; - - premainder_ie = p+ielen; - - ie_offset = (sint)(p -pie); - - remainder_ielen = pnetwork->IELength - ie_offset - ielen; - - if(bmatch) - dst_ie = p; - else - dst_ie = (p+ielen); - } - - if(remainder_ielen>0) - { - pbackup_remainder_ie = rtw_malloc(remainder_ielen); - if(pbackup_remainder_ie && premainder_ie) - _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - *dst_ie++=index; - *dst_ie++=len; - - _rtw_memcpy(dst_ie, data, len); - dst_ie+=len; - - //copy remainder IE - if(pbackup_remainder_ie) - { - _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - - rtw_mfree(pbackup_remainder_ie, remainder_ielen); - } - - offset = (uint)(dst_ie - pie); - pnetwork->IELength = offset + remainder_ielen; -} - -void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index) -{ - u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL; - uint offset, ielen, ie_offset, remainder_ielen = 0; - u8 *pie = pnetwork->IEs; - - p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_); - if (p != NULL && ielen>0) - { - ielen += 2; - - premainder_ie = p+ielen; - - ie_offset = (sint)(p -pie); - - remainder_ielen = pnetwork->IELength - ie_offset - ielen; - - dst_ie = p; - } - - if(remainder_ielen>0) - { - pbackup_remainder_ie = rtw_malloc(remainder_ielen); - if(pbackup_remainder_ie && premainder_ie) - _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - //copy remainder IE - if(pbackup_remainder_ie) - { - _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); - - rtw_mfree(pbackup_remainder_ie, remainder_ielen); - } - - offset = (uint)(dst_ie - pie); - pnetwork->IELength = offset + remainder_ielen; -} - - -u8 chk_sta_is_alive(struct sta_info *psta); -u8 chk_sta_is_alive(struct sta_info *psta) -{ - u8 ret = _FALSE; - #ifdef DBG_EXPIRATION_CHK - DBG_871X("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n" - , MAC_ARG(psta->hwaddr) - , psta->rssi_stat.UndecoratedSmoothedPWDB - //, STA_RX_PKTS_ARG(psta) - , STA_RX_PKTS_DIFF_ARG(psta) - , psta->expire_to - , psta->state&WIFI_SLEEP_STATE?"PS, ":"" - , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":"" - , psta->sleepq_len - ); - #endif - - //if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta)) - if((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) - { - #if 0 - if(psta->state&WIFI_SLEEP_STATE) - ret = _TRUE; - #endif - } - else - { - ret = _TRUE; - } - - sta_update_last_rx_pkts(psta); - - return ret; -} - -void expire_timeout_chk(_adapter *padapter) -{ - _irqL irqL; - _list *phead, *plist; - u8 updated; - struct sta_info *psta=NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 chk_alive_num = 0; - char chk_alive_list[NUM_STA]; - int i; - - _enter_critical_bh(&pstapriv->auth_list_lock, &irqL); - - phead = &pstapriv->auth_list; - plist = get_next(phead); - - //check auth_queue - #ifdef DBG_EXPIRATION_CHK - if (rtw_end_of_queue_search(phead, plist) == _FALSE) { - DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n" - , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt); - } - #endif - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) - { - psta = LIST_CONTAINOR(plist, struct sta_info, auth_list); - plist = get_next(plist); - - if(psta->expire_to>0) - { - psta->expire_to--; - if (psta->expire_to == 0) - { - rtw_list_delete(&psta->auth_list); - pstapriv->auth_list_cnt--; - - DBG_871X("auth expire %02X%02X%02X%02X%02X%02X\n", - psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]); - - _exit_critical_bh(&pstapriv->auth_list_lock, &irqL); - - _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - rtw_free_stainfo(padapter, psta); - _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - - _enter_critical_bh(&pstapriv->auth_list_lock, &irqL); - } - } - - } - - _exit_critical_bh(&pstapriv->auth_list_lock, &irqL); - - psta = NULL; - - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - phead = &pstapriv->asoc_list; - plist = get_next(phead); - - //check asoc_queue - #ifdef DBG_EXPIRATION_CHK - if (rtw_end_of_queue_search(phead, plist) == _FALSE) { - DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n" - , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt); - } - #endif - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) - { - psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - plist = get_next(plist); - - if (chk_sta_is_alive(psta) || !psta->expire_to) { - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - #ifdef CONFIG_TX_MCAST2UNI - psta->under_exist_checking = 0; - #endif // CONFIG_TX_MCAST2UNI - } else { - psta->expire_to--; - } - -#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK -#ifdef CONFIG_TX_MCAST2UNI -#ifdef CONFIG_80211N_HT - if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) { - // check sta by delba(addba) for 11n STA - // ToDo: use CCX report to check for all STAs - //DBG_871X("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->htpriv.agg_enable_bitmap, psta->under_exist_checking); - - if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) { - DBG_871X("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2); - psta->under_exist_checking = 0; - psta->expire_to = 0; - } else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) { - DBG_871X("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2); - psta->under_exist_checking = 1; - //tear down TX AMPDU - send_delba(padapter, 1, psta->hwaddr);// // originator - psta->htpriv.agg_enable_bitmap = 0x0;//reset - psta->htpriv.candidate_tid_bitmap = 0x0;//reset - } - } -#endif //CONFIG_80211N_HT -#endif // CONFIG_TX_MCAST2UNI -#endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK - - if (psta->expire_to <= 0) - { - #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (padapter->registrypriv.wifi_spec == 1) - { - psta->expire_to = pstapriv->expire_to; - continue; - } - - if (psta->state & WIFI_SLEEP_STATE) { - if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - //to check if alive by another methods if staion is at ps mode. - psta->expire_to = pstapriv->expire_to; - psta->state |= WIFI_STA_ALIVE_CHK_STATE; - - //DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr)); - - //to update bcn with tim_bitmap for this station - pstapriv->tim_bitmap |= BIT(psta->aid); - update_beacon(padapter, _TIM_IE_, NULL, _FALSE); - - if(!pmlmeext->active_keep_alive_check) - continue; - } - } - - if (pmlmeext->active_keep_alive_check) { - int stainfo_offset; - - stainfo_offset = rtw_stainfo_offset(pstapriv, psta); - if (stainfo_offset_valid(stainfo_offset)) { - chk_alive_list[chk_alive_num++] = stainfo_offset; - } - - continue; - } - #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ - - rtw_list_delete(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state); - updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING); - } - else - { - /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */ - if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt) - && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2) - ){ - DBG_871X("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__ - , MAC_ARG(psta->hwaddr) - , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt); - wakeup_sta_to_xmit(padapter, psta); - } - } - } - - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - -#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK -if (chk_alive_num) { - - u8 backup_oper_channel=0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - /* switch to correct channel of current network before issue keep-alive frames */ - if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) { - backup_oper_channel = rtw_get_oper_ch(padapter); - SelectChannel(padapter, pmlmeext->cur_channel); - } - - /* issue null data to check sta alive*/ - for (i = 0; i < chk_alive_num; i++) { - - int ret = _FAIL; - - psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); - if(!(psta->state &_FW_LINKED)) - continue; - - if (psta->state & WIFI_SLEEP_STATE) - ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50); - else - ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50); - - psta->keep_alive_trycnt++; - if (ret == _SUCCESS) - { - DBG_871X("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr)); - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - continue; - } - else if (psta->keep_alive_trycnt <= 3) - { - DBG_871X("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt); - psta->expire_to = 1; - continue; - } - - psta->keep_alive_trycnt = 0; - - DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state); - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) { - rtw_list_delete(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING); - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - } - - if (backup_oper_channel>0) /* back to the original operation channel */ - SelectChannel(padapter, backup_oper_channel); -} -#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ - - associated_clients_update(padapter, updated); -} - -void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level) -{ - int i; - u8 rf_type; - u32 init_rate=0; - unsigned char sta_band = 0, raid, shortGIrate = _FALSE; - unsigned char limit; - unsigned int tx_ra_bitmap=0; - struct ht_priv *psta_ht = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; - -#ifdef CONFIG_80211N_HT - if(psta) - psta_ht = &psta->htpriv; - else - return; -#endif //CONFIG_80211N_HT - - if(!(psta->state & _FW_LINKED)) - return; - - //b/g mode ra_bitmap - for (i=0; i<sizeof(psta->bssrateset); i++) - { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f); - } -#ifdef CONFIG_80211N_HT - //n mode ra_bitmap - if(psta_ht->ht_option) - { - rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - if(rf_type == RF_2T2R) - limit=16;// 2R - else - limit=8;// 1R - - for (i=0; i<limit; i++) { - if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8)) - tx_ra_bitmap |= BIT(i+12); - } - - //max short GI rate - shortGIrate = psta_ht->sgi; - } -#endif //CONFIG_80211N_HT - -#if 0//gtest - if(get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R) - { - //is this a 2r STA? - if((pstat->tx_ra_bitmap & 0x0ff00000) != 0 && !(priv->pshare->has_2r_sta & BIT(pstat->aid))) - { - priv->pshare->has_2r_sta |= BIT(pstat->aid); - if(rtw_read16(padapter, 0x102501f6) != 0xffff) - { - rtw_write16(padapter, 0x102501f6, 0xffff); - reset_1r_sta_RA(priv, 0xffff); - Switch_1SS_Antenna(priv, 3); - } - } - else// bg or 1R STA? - { - if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && priv->pshare->has_2r_sta == 0) - { - if(rtw_read16(padapter, 0x102501f6) != 0x7777) - { // MCS7 SGI - rtw_write16(padapter, 0x102501f6,0x7777); - reset_1r_sta_RA(priv, 0x7777); - Switch_1SS_Antenna(priv, 2); - } - } - } - - } - - if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) - { - if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper) - pstat->rssi_level = 1; - else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) || - ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) && - (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) && - (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_)))) - pstat->rssi_level = 2; - else - pstat->rssi_level = 3; - } - - // rate adaptive by rssi - if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len) - { - if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R)) - { - switch (pstat->rssi_level) { - case 1: - pstat->tx_ra_bitmap &= 0x100f0000; - break; - case 2: - pstat->tx_ra_bitmap &= 0x100ff000; - break; - case 3: - if (priv->pshare->is_40m_bw) - pstat->tx_ra_bitmap &= 0x100ff005; - else - pstat->tx_ra_bitmap &= 0x100ff001; - - break; - } - } - else - { - switch (pstat->rssi_level) { - case 1: - pstat->tx_ra_bitmap &= 0x1f0f0000; - break; - case 2: - pstat->tx_ra_bitmap &= 0x1f0ff000; - break; - case 3: - if (priv->pshare->is_40m_bw) - pstat->tx_ra_bitmap &= 0x000ff005; - else - pstat->tx_ra_bitmap &= 0x000ff001; - - break; - } - - // Don't need to mask high rates due to new rate adaptive parameters - //if (pstat->is_broadcom_sta) // use MCS12 as the highest rate vs. Broadcom sta - // pstat->tx_ra_bitmap &= 0x81ffffff; - - // NIC driver will report not supporting MCS15 and MCS14 in asoc req - //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta) - // pstat->tx_ra_bitmap &= 0x83ffffff; // if Realtek 1x2 sta, don't use MCS15 and MCS14 - } - } - else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat)) - { - switch (pstat->rssi_level) { - case 1: - pstat->tx_ra_bitmap &= 0x00000f00; - break; - case 2: - pstat->tx_ra_bitmap &= 0x00000ff0; - break; - case 3: - pstat->tx_ra_bitmap &= 0x00000ff5; - break; - } - } - else - { - pstat->tx_ra_bitmap &= 0x0000000d; - } - - // disable tx short GI when station cannot rx MCS15(AP is 2T2R) - // disable tx short GI when station cannot rx MCS7 (AP is 1T2R or 1T1R) - // if there is only 1r STA and we are 2T2R, DO NOT mask SGI rate - if ((!(pstat->tx_ra_bitmap & 0x8000000) && (priv->pshare->has_2r_sta > 0) && (get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)) || - (!(pstat->tx_ra_bitmap & 0x80000) && (get_rf_mimo_mode(padapter) != RTL8712_RF_2T2R))) - { - pstat->tx_ra_bitmap &= ~BIT(28); - } -#endif - - if ( pcur_network->Configuration.DSConfig > 14 ) { - // 5G band - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N | WIRELESS_11A; - else - sta_band |= WIRELESS_11A; - } else { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B; - else if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11G |WIRELESS_11B; - else - sta_band |= WIRELESS_11B; - } - - psta->wireless_mode = sta_band; - - raid = networktype_to_raid(sta_band); - init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f; - - if (psta->aid < NUM_STA) - { - u8 arg = 0; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7);//support entry 2~31 - - if (shortGIrate==_TRUE) - arg |= BIT(5); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_871X("%s=> mac_id:%d , raid:%d , bitmap=0x%x, arg=0x%x\n", - __FUNCTION__ , psta->mac_id, raid ,tx_ra_bitmap, arg); - - //bitmap[0:27] = tx_rate_bitmap - //bitmap[28:31]= Rate Adaptive id - //arg[0:4] = macid - //arg[5] = Short GI - rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level); - - - if (shortGIrate==_TRUE) - init_rate |= BIT(6); - - //set ra_id, init_rate - psta->raid = raid; - psta->init_rate = init_rate; - - } - else - { - DBG_871X("station aid %d exceed the max number\n", psta->aid); - } - -} - -static void update_bmc_sta(_adapter *padapter) -{ - _irqL irqL; - u32 init_rate=0; - unsigned char network_type, raid; - int i, supportRateNum = 0; - unsigned int tx_ra_bitmap=0; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; - struct sta_info *psta = rtw_get_bcmc_stainfo(padapter); - - if(psta) - { - psta->aid = 0;//default set to 0 - //psta->mac_id = psta->aid+4; - psta->mac_id = psta->aid + 1; - - psta->qos_option = 0; -#ifdef CONFIG_80211N_HT - psta->htpriv.ht_option = _FALSE; -#endif //CONFIG_80211N_HT - - psta->ieee8021x_blocked = 0; - - _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - //psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this. - - - - //prepare for add_RATid - supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates); - network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, 1); - - _rtw_memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum); - psta->bssratelen = supportRateNum; - - //b/g mode ra_bitmap - for (i=0; i<supportRateNum; i++) - { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f); - } - - if ( pcur_network->Configuration.DSConfig > 14 ) { - //force to A mode. 5G doesn't support CCK rates - network_type = WIRELESS_11A; - tx_ra_bitmap = 0x150; // 6, 12, 24 Mbps - } else { - //force to b mode - network_type = WIRELESS_11B; - tx_ra_bitmap = 0xf; - } - - //tx_ra_bitmap = update_basic_rate(pcur_network->SupportedRates, supportRateNum); - - raid = networktype_to_raid(network_type); - init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f; - - //DBG_871X("Add id %d val %08x to ratr for bmc sta\n", psta->aid, tx_ra_bitmap); - //ap mode - rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE); - - //if(pHalData->fw_ractrl == _TRUE) - { - u8 arg = 0; - - arg = psta->mac_id&0x1f; - - arg |= BIT(7); - - //if (shortGIrate==_TRUE) - // arg |= BIT(5); - - tx_ra_bitmap |= ((raid<<28)&0xf0000000); - - DBG_871X("update_bmc_sta, mask=0x%x, arg=0x%x\n", tx_ra_bitmap, arg); - - //bitmap[0:27] = tx_rate_bitmap - //bitmap[28:31]= Rate Adaptive id - //arg[0:4] = macid - //arg[5] = Short GI - rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0); - - } - - //set ra_id, init_rate - psta->raid = raid; - psta->init_rate = init_rate; - - rtw_stassoc_hw_rpt(padapter, psta); - - _enter_critical_bh(&psta->lock, &irqL); - psta->state = _FW_LINKED; - _exit_critical_bh(&psta->lock, &irqL); - - } - else - { - DBG_871X("add_RATid_bmc_sta error!\n"); - } - -} - -//notes: -//AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode -//MAC_ID = AID+1 for sta in ap/adhoc mode -//MAC_ID = 1 for bc/mc for sta/ap/adhoc -//MAC_ID = 0 for bssid for sta/ap/adhoc -//CAM_ID = //0~3 for default key, cmd_id=macid + 3, macid=aid+1; - -void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta) -{ - _irqL irqL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); -#ifdef CONFIG_80211N_HT - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - struct ht_priv *phtpriv_sta = &psta->htpriv; -#endif //CONFIG_80211N_HT - //set intf_tag to if1 - //psta->intf_tag = 0; - - //psta->mac_id = psta->aid+4; - psta->mac_id = psta->aid+1; - DBG_871X("%s\n",__FUNCTION__); - - //ap mode - rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE); - - if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X) - psta->ieee8021x_blocked = _TRUE; - else - psta->ieee8021x_blocked = _FALSE; - - - //update sta's cap - - //ERP - VCS_update(padapter, psta); -#ifdef CONFIG_80211N_HT - //HT related cap - if(phtpriv_sta->ht_option) - { - //check if sta supports rx ampdu - phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; - - //check if sta support s Short GI - if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) - { - phtpriv_sta->sgi = _TRUE; - } - - // bwmode - if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) - { - //phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; - phtpriv_sta->bwmode = pmlmeext->cur_bwmode; - phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; - - } - - psta->qos_option = _TRUE; - - } - else - { - phtpriv_sta->ampdu_enable = _FALSE; - - phtpriv_sta->sgi = _FALSE; - phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - //Rx AMPDU - send_delba(padapter, 0, psta->hwaddr);// recipient - - //TX AMPDU - send_delba(padapter, 1, psta->hwaddr);// // originator - phtpriv_sta->agg_enable_bitmap = 0x0;//reset - phtpriv_sta->candidate_tid_bitmap = 0x0;//reset -#endif //CONFIG_80211N_HT - - //todo: init other variables - - _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - - //add ratid - //add_RATid(padapter, psta);//move to ap_sta_info_defer_update() - - - _enter_critical_bh(&psta->lock, &irqL); - psta->state |= _FW_LINKED; - _exit_critical_bh(&psta->lock, &irqL); - - -} - -static void update_hw_ht_param(_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - DBG_871X("%s\n", __FUNCTION__); - - - //handle A-MPDU parameter field - /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing - */ - max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; - - min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; - - rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing)); - - rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len)); - - // - // Config SM Power Save setting - // - pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2; - if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) - { - /*u8 i; - //update the MCS rates - for (i = 0; i < 16; i++) - { - pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i]; - }*/ - DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__); - } - - // - // Config current HT Protection mode. - // - //pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; - -} - -static void start_bss_network(_adapter *padapter, u8 *pbuf) -{ - u8 *p; - u8 val8, cur_channel, cur_bwmode, cur_ch_offset; - u16 bcn_interval; - u32 acparm; - int ie_len; - struct registry_priv *pregpriv = &padapter->registrypriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct security_priv* psecuritypriv=&(padapter->securitypriv); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network); - struct HT_info_element *pht_info=NULL; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif //CONFIG_P2P - - //DBG_871X("%s\n", __FUNCTION__); - - bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod; - cur_channel = pnetwork->Configuration.DSConfig; - cur_bwmode = HT_CHANNEL_WIDTH_20;; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - - //check if there is wps ie, - //if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, - //and at first time the security ie ( RSN/WPA IE) will not include in beacon. - if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL)) - { - pmlmeext->bstart_bss = _TRUE; - } - - //todo: update wmm, ht cap - //pmlmeinfo->WMM_enable; - //pmlmeinfo->HT_enable; - if(pmlmepriv->qospriv.qos_option) - pmlmeinfo->WMM_enable = _TRUE; -#ifdef CONFIG_80211N_HT - if(pmlmepriv->htpriv.ht_option) - { - pmlmeinfo->WMM_enable = _TRUE; - pmlmeinfo->HT_enable = _TRUE; - //pmlmeinfo->HT_info_enable = _TRUE; - //pmlmeinfo->HT_caps_enable = _TRUE; - - update_hw_ht_param(padapter); - } -#endif //#CONFIG_80211N_HT - - - if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at first time - { - //WEP Key will be set before this function, do not clear CAM. - if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)) - flush_all_cam_entry(padapter); //clear CAM - } - - //set MSR to AP_Mode - Set_MSR(padapter, _HW_STATE_AP_); - - //Set BSSID REG - rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress); - - //Set EDCA param reg -#ifdef CONFIG_CONCURRENT_MODE - acparm = 0x005ea42b; -#else - acparm = 0x002F3217; // VO -#endif - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm)); - acparm = 0x005E4317; // VI - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm)); - //acparm = 0x00105320; // BE - acparm = 0x005ea42b; - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm)); - acparm = 0x0000A444; // BK - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm)); - - //Set Security - val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf; - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); - - //Beacon Control related register - rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval)); - - - UpdateBrateTbl(padapter, pnetwork->SupportedRates); - rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); - - if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at first time - { - //u32 initialgain; - - //initialgain = 0x1e; - - - //disable dynamic functions, such as high power, DIG - //Save_DM_Func_Flag(padapter); - //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE); - -#ifdef CONFIG_CONCURRENT_MODE - if(padapter->adapter_type > PRIMARY_ADAPTER) - { - if(rtw_buddy_adapter_up(padapter)) - { - _adapter *pbuddy_adapter = padapter->pbuddy_adapter; - - //turn on all dynamic functions on PRIMARY_ADAPTER, dynamic functions only runs at PRIMARY_ADAPTER - Switch_DM_Func(pbuddy_adapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE); - - //rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); - } - } - else -#endif - { - //turn on all dynamic functions - Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE); - - //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); - } - - } -#ifdef CONFIG_80211N_HT - //set channel, bwmode - p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs))); - if( p && ie_len) - { - pht_info = (struct HT_info_element *)(p+2); - - if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) - { - //switch to the 40M Hz mode - //pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; - cur_bwmode = HT_CHANNEL_WIDTH_40; - switch (pht_info->infos[0] & 0x3) - { - case 1: - //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - - case 3: - //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - - default: - //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - - } - - } -#endif //CONFIG_80211N_HT -#ifdef CONFIG_DUALMAC_CONCURRENT - dc_set_ap_channel_bandwidth(padapter, cur_channel, cur_ch_offset, cur_bwmode); -#else - //TODO: need to judge the phy parameters on concurrent mode for single phy - //set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); -#ifdef CONFIG_CONCURRENT_MODE - if(!check_buddy_fwstate(padapter, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY)) - { - set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); - } - else if(check_buddy_fwstate(padapter, _FW_LINKED)==_TRUE)//only second adapter can enter AP Mode - { - _adapter *pbuddy_adapter = padapter->pbuddy_adapter; - struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; - - //To sync cur_channel/cur_bwmode/cur_ch_offset with primary adapter - DBG_871X("primary iface is at linked state, sync cur_channel/cur_bwmode/cur_ch_offset\n"); - DBG_871X("primary adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset); - DBG_871X("second adapter, CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset); - - cur_channel = pbuddy_mlmeext->cur_channel; - if(cur_bwmode == HT_CHANNEL_WIDTH_40) - { - if(pht_info) - pht_info->infos[0] &= ~(BIT(0)|BIT(1)); - - if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) - { - cur_ch_offset = pbuddy_mlmeext->cur_ch_offset; - - //to update cur_ch_offset value in beacon - if(pht_info) - { - switch(cur_ch_offset) - { - case HAL_PRIME_CHNL_OFFSET_LOWER: - pht_info->infos[0] |= 0x1; - break; - case HAL_PRIME_CHNL_OFFSET_UPPER: - pht_info->infos[0] |= 0x3; - break; - case HAL_PRIME_CHNL_OFFSET_DONT_CARE: - default: - break; - } - } - - } - else if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20) - { - cur_bwmode = HT_CHANNEL_WIDTH_20; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - if(cur_channel>0 && cur_channel<5) - { - if(pht_info) - pht_info->infos[0] |= 0x1; - - cur_bwmode = HT_CHANNEL_WIDTH_40; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; - } - - if(cur_channel>7 && cur_channel<(14+1)) - { - if(pht_info) - pht_info->infos[0] |= 0x3; - - cur_bwmode = HT_CHANNEL_WIDTH_40; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; - } - - set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); - } - - } - - // to update channel value in beacon - pnetwork->Configuration.DSConfig = cur_channel; - p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs))); - if(p && ie_len>0) - *(p + 2) = cur_channel; - - if(pht_info) - pht_info->primary_channel = cur_channel; - } -#else - set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); -#endif //CONFIG_CONCURRENT_MODE - - DBG_871X("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset); - - // - pmlmeext->cur_channel = cur_channel; - pmlmeext->cur_bwmode = cur_bwmode; - pmlmeext->cur_ch_offset = cur_ch_offset; -#endif //CONFIG_DUALMAC_CONCURRENT - pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type; - - //update cur_wireless_mode - update_wireless_mode(padapter); - - //udpate capability after cur_wireless_mode updated - update_capinfo(padapter, rtw_get_capability((WLAN_BSSID_EX *)pnetwork)); - - //let pnetwork_mlmeext == pnetwork_mlme. - _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); - -#ifdef CONFIG_P2P - _rtw_memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength); - pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength; -#endif //CONFIG_P2P - - if(_TRUE == pmlmeext->bstart_bss) - { - update_beacon(padapter, _TIM_IE_, NULL, _FALSE); - -#ifndef CONFIG_INTERRUPT_BASED_TXBCN //other case will tx beacon when bcn interrupt coming in. -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) - //issue beacon frame - if(send_beacon(padapter)==_FAIL) - { - DBG_871X("issue_beacon, fail!\n"); - } -#endif -#endif //!CONFIG_INTERRUPT_BASED_TXBCN - - } - - - //update bc/mc sta_info - update_bmc_sta(padapter); - - //pmlmeext->bstart_bss = _TRUE; - -} - -int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len) -{ - int ret=_SUCCESS; - u8 *p; - u8 *pHT_caps_ie=NULL; - u8 *pHT_info_ie=NULL; - struct sta_info *psta = NULL; - u16 cap, ht_cap=_FALSE; - uint ie_len = 0; - int group_cipher, pairwise_cipher; - u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; - int supportRateNum = 0; - u8 OUI1[] = {0x00, 0x50, 0xf2,0x01}; - u8 wps_oui[4]={0x0,0x50,0xf2,0x04}; - u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *ie = pbss_network->IEs; - - - /* SSID */ - /* Supported rates */ - /* DS Params */ - /* WLAN_EID_COUNTRY */ - /* ERP Information element */ - /* Extended supported rates */ - /* WPA/WPA2 */ - /* Wi-Fi Wireless Multimedia Extensions */ - /* ht_capab, ht_oper */ - /* WPS IE */ - - DBG_871X("%s, len=%d\n", __FUNCTION__, len); - - if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE) - return _FAIL; - - - if(len>MAX_IE_SZ) - return _FAIL; - - pbss_network->IELength = len; - - _rtw_memset(ie, 0, MAX_IE_SZ); - - _rtw_memcpy(ie, pbuf, pbss_network->IELength); - - - if(pbss_network->InfrastructureMode!=Ndis802_11APMode) - return _FAIL; - - pbss_network->Rssi = 0; - - _rtw_memcpy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)), ETH_ALEN); - - //beacon interval - p = rtw_get_beacon_interval_from_ie(ie);//ie + 8; // 8: TimeStamp, 2: Beacon Interval 2:Capability - //pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); - pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p); - - //capability - //cap = *(unsigned short *)rtw_get_capability_from_ie(ie); - //cap = le16_to_cpu(cap); - cap = RTW_GET_LE16(ie); - - //SSID - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_)); - if(p && ie_len>0) - { - _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID)); - _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len); - pbss_network->Ssid.SsidLength = ie_len; - } - - //chnnel - channel = 0; - pbss_network->Configuration.Length = 0; - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if(p && ie_len>0) - channel = *(p + 2); - - pbss_network->Configuration.DSConfig = channel; - - - _rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); - // get supported rates - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if (p != NULL) - { - _rtw_memcpy(supportRate, p+2, ie_len); - supportRateNum = ie_len; - } - - //get ext_supported rates - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_); - if (p != NULL) - { - _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len); - supportRateNum += ie_len; - - } - - network_type = rtw_check_network_type(supportRate, supportRateNum, channel); - - rtw_set_supported_rate(pbss_network->SupportedRates, network_type); - - - //parsing ERP_IE - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if(p && ie_len>0) - { - ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p); - } - - //update privacy/security - if (cap & BIT(4)) - pbss_network->Privacy = 1; - else - pbss_network->Privacy = 0; - - psecuritypriv->wpa_psk = 0; - - //wpa2 - group_cipher = 0; pairwise_cipher = 0; - psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; - psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if(p && ie_len>0) - { - if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) - { - psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X; - - psecuritypriv->dot8021xalg = 1;//psk, todo:802.1x - psecuritypriv->wpa_psk |= BIT(1); - - psecuritypriv->wpa2_group_cipher = group_cipher; - psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; -#if 0 - switch(group_cipher) - { - case WPA_CIPHER_NONE: - psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; - break; - case WPA_CIPHER_WEP40: - psecuritypriv->wpa2_group_cipher = _WEP40_; - break; - case WPA_CIPHER_TKIP: - psecuritypriv->wpa2_group_cipher = _TKIP_; - break; - case WPA_CIPHER_CCMP: - psecuritypriv->wpa2_group_cipher = _AES_; - break; - case WPA_CIPHER_WEP104: - psecuritypriv->wpa2_group_cipher = _WEP104_; - break; - } - - switch(pairwise_cipher) - { - case WPA_CIPHER_NONE: - psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; - break; - case WPA_CIPHER_WEP40: - psecuritypriv->wpa2_pairwise_cipher = _WEP40_; - break; - case WPA_CIPHER_TKIP: - psecuritypriv->wpa2_pairwise_cipher = _TKIP_; - break; - case WPA_CIPHER_CCMP: - psecuritypriv->wpa2_pairwise_cipher = _AES_; - break; - case WPA_CIPHER_WEP104: - psecuritypriv->wpa2_pairwise_cipher = _WEP104_; - break; - } -#endif - } - - } - - //wpa - ie_len = 0; - group_cipher = 0; pairwise_cipher = 0; - psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; - psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; - for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) - { - p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if ((p) && (_rtw_memcmp(p+2, OUI1, 4))) - { - if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) - { - psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X; - - psecuritypriv->dot8021xalg = 1;//psk, todo:802.1x - - psecuritypriv->wpa_psk |= BIT(0); - - psecuritypriv->wpa_group_cipher = group_cipher; - psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; - -#if 0 - switch(group_cipher) - { - case WPA_CIPHER_NONE: - psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; - break; - case WPA_CIPHER_WEP40: - psecuritypriv->wpa_group_cipher = _WEP40_; - break; - case WPA_CIPHER_TKIP: - psecuritypriv->wpa_group_cipher = _TKIP_; - break; - case WPA_CIPHER_CCMP: - psecuritypriv->wpa_group_cipher = _AES_; - break; - case WPA_CIPHER_WEP104: - psecuritypriv->wpa_group_cipher = _WEP104_; - break; - } - - switch(pairwise_cipher) - { - case WPA_CIPHER_NONE: - psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; - break; - case WPA_CIPHER_WEP40: - psecuritypriv->wpa_pairwise_cipher = _WEP40_; - break; - case WPA_CIPHER_TKIP: - psecuritypriv->wpa_pairwise_cipher = _TKIP_; - break; - case WPA_CIPHER_CCMP: - psecuritypriv->wpa_pairwise_cipher = _AES_; - break; - case WPA_CIPHER_WEP104: - psecuritypriv->wpa_pairwise_cipher = _WEP104_; - break; - } -#endif - } - - break; - - } - - if ((p == NULL) || (ie_len == 0)) - { - break; - } - - } - - //wmm - ie_len = 0; - pmlmepriv->qospriv.qos_option = 0; - if(pregistrypriv->wmm_enable) - { - for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2)) - { - p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6)) - { - pmlmepriv->qospriv.qos_option = 1; - - *(p+8) |= BIT(7);//QoS Info, support U-APSD - - /* disable all ACM bits since the WMM admission control is not supported */ - *(p + 10) &= ~BIT(4); /* BE */ - *(p + 14) &= ~BIT(4); /* BK */ - *(p + 18) &= ~BIT(4); /* VI */ - *(p + 22) &= ~BIT(4); /* VO */ - - break; - } - - if ((p == NULL) || (ie_len == 0)) - { - break; - } - } - } -#ifdef CONFIG_80211N_HT - //parsing HT_CAP_IE - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if(p && ie_len>0) - { - u8 rf_type; - - struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2); - - pHT_caps_ie=p; - - - ht_cap = _TRUE; - network_type |= WIRELESS_11_24N; - - - rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - - if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || - (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) - { - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2)); - } - else - { - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00); - } - - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); //set Max Rx AMPDU size to 64K - - if(rf_type == RF_1T1R) - { - pht_cap->supp_mcs_set[0] = 0xff; - pht_cap->supp_mcs_set[1] = 0x0; - } - - _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); - - } - - //parsing HT_INFO_IE - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if(p && ie_len>0) - { - pHT_info_ie=p; - } -#endif //CONFIG_80211N_HT - switch(network_type) - { - case WIRELESS_11B: - pbss_network->NetworkTypeInUse = Ndis802_11DS; - break; - case WIRELESS_11G: - case WIRELESS_11BG: - case WIRELESS_11G_24N: - case WIRELESS_11BG_24N: - pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; - break; - case WIRELESS_11A: - pbss_network->NetworkTypeInUse = Ndis802_11OFDM5; - break; - default : - pbss_network->NetworkTypeInUse = Ndis802_11OFDM24; - break; - } - - pmlmepriv->cur_network.network_type = network_type; - -#ifdef CONFIG_80211N_HT - pmlmepriv->htpriv.ht_option = _FALSE; - - if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || - (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP)) - { - //todo: - //ht_cap = _FALSE; - } - - //ht_cap - if(pregistrypriv->ht_enable && ht_cap==_TRUE) - { - pmlmepriv->htpriv.ht_option = _TRUE; - pmlmepriv->qospriv.qos_option = 1; - - if(pregistrypriv->ampdu_enable==1) - { - pmlmepriv->htpriv.ampdu_enable = _TRUE; - } - - HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie); - - HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie); - } -#endif - - - pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network); - - //issue beacon to start bss network - start_bss_network(padapter, (u8*)pbss_network); - - - //alloc sta_info for ap itself - psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress); - if(!psta) - { - psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress); - if (psta == NULL) - { - return _FAIL; - } - } - psta->state |= WIFI_AP_STATE; //Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 - rtw_indicate_connect( padapter); - - pmlmepriv->cur_network.join_res = _TRUE;//for check if already set beacon - - //update bc/mc sta_info - //update_bmc_sta(padapter); - - return ret; - -} - -void rtw_set_macaddr_acl(_adapter *padapter, int mode) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - DBG_871X("%s, mode=%d\n", __func__, mode); - - pacl_list->mode = mode; -} - -int rtw_acl_add_sta(_adapter *padapter, u8 *addr) -{ - _irqL irqL; - _list *plist, *phead; - u8 added = _FALSE; - int i, ret=0; - struct rtw_wlan_acl_node *paclnode; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - _queue *pacl_node_q =&pacl_list->acl_node_q; - - DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr)); - - if((NUM_ACL-1) < pacl_list->num) - return (-1); - - - _enter_critical_bh(&(pacl_node_q->lock), &irqL); - - phead = get_list_head(pacl_node_q); - plist = get_next(phead); - - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) - { - paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list); - plist = get_next(plist); - - if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN)) - { - if(paclnode->valid == _TRUE) - { - added = _TRUE; - DBG_871X("%s, sta has been added\n", __func__); - break; - } - } - } - - _exit_critical_bh(&(pacl_node_q->lock), &irqL); - - - if(added == _TRUE) - return ret; - - - _enter_critical_bh(&(pacl_node_q->lock), &irqL); - - for(i=0; i< NUM_ACL; i++) - { - paclnode = &pacl_list->aclnode[i]; - - if(paclnode->valid == _FALSE) - { - _rtw_init_listhead(&paclnode->list); - - _rtw_memcpy(paclnode->addr, addr, ETH_ALEN); - - paclnode->valid = _TRUE; - - rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q)); - - pacl_list->num++; - - break; - } - } - - DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num); - - _exit_critical_bh(&(pacl_node_q->lock), &irqL); - - return ret; -} - -int rtw_acl_remove_sta(_adapter *padapter, u8 *addr) -{ - _irqL irqL; - _list *plist, *phead; - int i, ret=0; - struct rtw_wlan_acl_node *paclnode; - struct sta_priv *pstapriv = &padapter->stapriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - _queue *pacl_node_q =&pacl_list->acl_node_q; - - DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr)); - - _enter_critical_bh(&(pacl_node_q->lock), &irqL); - - phead = get_list_head(pacl_node_q); - plist = get_next(phead); - - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) - { - paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list); - plist = get_next(plist); - - if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN)) - { - if(paclnode->valid == _TRUE) - { - paclnode->valid = _FALSE; - - rtw_list_delete(&paclnode->list); - - pacl_list->num--; - } - } - } - - _exit_critical_bh(&(pacl_node_q->lock), &irqL); - - DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num); - - return ret; - -} - -#ifdef CONFIG_NATIVEAP_MLME - -static void update_bcn_fixed_ie(_adapter *padapter) -{ - DBG_871X("%s\n", __FUNCTION__); - -} - -static void update_bcn_erpinfo_ie(_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network); - unsigned char *p, *ie = pnetwork->IEs; - u32 len = 0; - - DBG_871X("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable); - - if(!pmlmeinfo->ERP_enable) - return; - - //parsing ERP_IE - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if(p && len>0) - { - PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p; - - if (pmlmepriv->num_sta_non_erp == 1) - pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION; - else - pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION); - - if(pmlmepriv->num_sta_no_short_preamble > 0) - pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE; - else - pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE); - - ERP_IE_handler(padapter, pIE); - } - -} - -static void update_bcn_htcap_ie(_adapter *padapter) -{ - DBG_871X("%s\n", __FUNCTION__); - -} - -static void update_bcn_htinfo_ie(_adapter *padapter) -{ - DBG_871X("%s\n", __FUNCTION__); - -} - -static void update_bcn_rsn_ie(_adapter *padapter) -{ - DBG_871X("%s\n", __FUNCTION__); - -} - -static void update_bcn_wpa_ie(_adapter *padapter) -{ - DBG_871X("%s\n", __FUNCTION__); - -} - -static void update_bcn_wmm_ie(_adapter *padapter) -{ - DBG_871X("%s\n", __FUNCTION__); - -} - -static void update_bcn_wps_ie(_adapter *padapter) -{ - u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL; - uint wps_ielen=0, wps_offset, remainder_ielen; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network); - unsigned char *ie = pnetwork->IEs; - u32 ielen = pnetwork->IELength; - - - DBG_871X("%s\n", __FUNCTION__); - - pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen); - - if(pwps_ie==NULL || wps_ielen==0) - return; - - wps_offset = (uint)(pwps_ie-ie); - - premainder_ie = pwps_ie + wps_ielen; - - remainder_ielen = ielen - wps_offset - wps_ielen; - - if(remainder_ielen>0) - { - pbackup_remainder_ie = rtw_malloc(remainder_ielen); - if(pbackup_remainder_ie) - _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); - } - - - pwps_ie_src = pmlmepriv->wps_beacon_ie; - if(pwps_ie_src == NULL) - return; - - - wps_ielen = (uint)pwps_ie_src[1];//to get ie data len - if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ) - { - _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen+2); - pwps_ie += (wps_ielen+2); - - if(pbackup_remainder_ie) - _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); - - //update IELength - pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen; - } - - if(pbackup_remainder_ie) - rtw_mfree(pbackup_remainder_ie, remainder_ielen); - -} - -static void update_bcn_p2p_ie(_adapter *padapter) -{ - -} - -static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui) -{ - DBG_871X("%s\n", __FUNCTION__); - - if(_rtw_memcmp(RTW_WPA_OUI, oui, 4)) - { - update_bcn_wpa_ie(padapter); - } - else if(_rtw_memcmp(WMM_OUI, oui, 4)) - { - update_bcn_wmm_ie(padapter); - } - else if(_rtw_memcmp(WPS_OUI, oui, 4)) - { - update_bcn_wps_ie(padapter); - } - else if(_rtw_memcmp(P2P_OUI, oui, 4)) - { - update_bcn_p2p_ie(padapter); - } - else - { - DBG_871X("unknown OUI type!\n"); - } - - -} - -void update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx) -{ - _irqL irqL; - struct mlme_priv *pmlmepriv; - struct mlme_ext_priv *pmlmeext; - //struct mlme_ext_info *pmlmeinfo; - - //DBG_871X("%s\n", __FUNCTION__); - - if(!padapter) - return; - - pmlmepriv = &(padapter->mlmepriv); - pmlmeext = &(padapter->mlmeextpriv); - //pmlmeinfo = &(pmlmeext->mlmext_info); - - if(_FALSE == pmlmeext->bstart_bss) - return; - - _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL); - - switch(ie_id) - { - case 0xFF: - - update_bcn_fixed_ie(padapter);//8: TimeStamp, 2: Beacon Interval 2:Capability - - break; - - case _TIM_IE_: - - update_BCNTIM(padapter); - - break; - - case _ERPINFO_IE_: - - update_bcn_erpinfo_ie(padapter); - - break; - - case _HT_CAPABILITY_IE_: - - update_bcn_htcap_ie(padapter); - - break; - - case _RSN_IE_2_: - - update_bcn_rsn_ie(padapter); - - break; - - case _HT_ADD_INFO_IE_: - - update_bcn_htinfo_ie(padapter); - - break; - - case _VENDOR_SPECIFIC_IE_: - - update_bcn_vendor_spec_ie(padapter, oui); - - break; - - default: - break; - } - - pmlmepriv->update_bcn = _TRUE; - - _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL); - -#ifndef CONFIG_INTERRUPT_BASED_TXBCN -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) - if(tx) - { - //send_beacon(padapter);//send_beacon must execute on TSR level - set_tx_beacon_cmd(padapter); - } -#else - { - //PCI will issue beacon when BCN interrupt occurs. - } -#endif -#endif //!CONFIG_INTERRUPT_BASED_TXBCN - -} - -#ifdef CONFIG_80211N_HT - -/* -op_mode -Set to 0 (HT pure) under the followign conditions - - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - - all STAs in the BSS are 20 MHz HT in 20 MHz BSS -Set to 1 (HT non-member protection) if there may be non-HT STAs - in both the primary and the secondary channel -Set to 2 if only HT STAs are associated in BSS, - however and at least one 20 MHz HT STA is associated -Set to 3 (HT mixed mode) when one or more non-HT STAs are associated - (currently non-GF HT station is considered as non-HT STA also) -*/ -static int rtw_ht_operation_update(_adapter *padapter) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - - if(pmlmepriv->htpriv.ht_option == _TRUE) - return 0; - - //if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) - // return 0; - - DBG_871X("%s current operation mode=0x%X\n", - __FUNCTION__, pmlmepriv->ht_op_mode); - - if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) - && pmlmepriv->num_sta_ht_no_gf) { - pmlmepriv->ht_op_mode |= - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && - pmlmepriv->num_sta_ht_no_gf == 0) { - pmlmepriv->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } - - if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } else if ((pmlmepriv->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) { - pmlmepriv->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } - - /* Note: currently we switch to the MIXED op mode if HT non-greenfield - * station is associated. Probably it's a theoretical case, since - * it looks like all known HT STAs support greenfield. - */ - new_op_mode = 0; - if (pmlmepriv->num_sta_no_ht || - (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) - new_op_mode = OP_MODE_MIXED; - else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH) - && pmlmepriv->num_sta_ht_20mhz) - new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; - else if (pmlmepriv->olbc_ht) - new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS; - else - new_op_mode = OP_MODE_PURE; - - cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; - if (cur_op_mode != new_op_mode) { - pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; - pmlmepriv->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - DBG_871X("%s new operation mode=0x%X changes=%d\n", - __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes); - - return op_mode_changes; - -} - -#endif /* CONFIG_80211N_HT */ - -void associated_clients_update(_adapter *padapter, u8 updated) -{ - //update associcated stations cap. - if(updated == _TRUE) - { - _irqL irqL; - _list *phead, *plist; - struct sta_info *psta=NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - phead = &pstapriv->asoc_list; - plist = get_next(phead); - - //check asoc_queue - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) - { - psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - - plist = get_next(plist); - - VCS_update(padapter, psta); - } - - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - } - -} - -/* called > TSR LEVEL for USB or SDIO Interface*/ -void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = _FALSE; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - - -#if 0 - if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && - !psta->no_short_preamble_set) { - psta->no_short_preamble_set = 1; - pmlmepriv->num_sta_no_short_preamble++; - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 1)) - ieee802_11_set_beacons(hapd->iface); - } -#endif - - - if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) - { - if(!psta->no_short_preamble_set) - { - psta->no_short_preamble_set = 1; - - pmlmepriv->num_sta_no_short_preamble++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 1)) - { - beacon_updated = _TRUE; - update_beacon(padapter, 0xFF, NULL, _TRUE); - } - - } - } - else - { - if(psta->no_short_preamble_set) - { - psta->no_short_preamble_set = 0; - - pmlmepriv->num_sta_no_short_preamble--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_preamble == 0)) - { - beacon_updated = _TRUE; - update_beacon(padapter, 0xFF, NULL, _TRUE); - } - - } - } - -#if 0 - if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) { - psta->nonerp_set = 1; - pmlmepriv->num_sta_non_erp++; - if (pmlmepriv->num_sta_non_erp == 1) - ieee802_11_set_beacons(hapd->iface); - } -#endif - - if(psta->flags & WLAN_STA_NONERP) - { - if(!psta->nonerp_set) - { - psta->nonerp_set = 1; - - pmlmepriv->num_sta_non_erp++; - - if (pmlmepriv->num_sta_non_erp == 1) - { - beacon_updated = _TRUE; - update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE); - } - } - - } - else - { - if(psta->nonerp_set) - { - psta->nonerp_set = 0; - - pmlmepriv->num_sta_non_erp--; - - if (pmlmepriv->num_sta_non_erp == 0) - { - beacon_updated = _TRUE; - update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE); - } - } - - } - - -#if 0 - if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) && - !psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 1; - pmlmepriv->num_sta_no_short_slot_time++; - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 1)) - ieee802_11_set_beacons(hapd->iface); - } -#endif - - if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) - { - if(!psta->no_short_slot_time_set) - { - psta->no_short_slot_time_set = 1; - - pmlmepriv->num_sta_no_short_slot_time++; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 1)) - { - beacon_updated = _TRUE; - update_beacon(padapter, 0xFF, NULL, _TRUE); - } - - } - } - else - { - if(psta->no_short_slot_time_set) - { - psta->no_short_slot_time_set = 0; - - pmlmepriv->num_sta_no_short_slot_time--; - - if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && - (pmlmepriv->num_sta_no_short_slot_time == 0)) - { - beacon_updated = _TRUE; - update_beacon(padapter, 0xFF, NULL, _TRUE); - } - } - } - -#ifdef CONFIG_80211N_HT - - if (psta->flags & WLAN_STA_HT) - { - u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); - - DBG_871X("HT: STA " MAC_FMT " HT Capabilities " - "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab); - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { - if (!psta->no_ht_gf_set) { - psta->no_ht_gf_set = 1; - pmlmepriv->num_sta_ht_no_gf++; - } - DBG_871X("%s STA " MAC_FMT " - no " - "greenfield, num of non-gf stations %d\n", - __FUNCTION__, MAC_ARG(psta->hwaddr), - pmlmepriv->num_sta_ht_no_gf); - } - - if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) { - if (!psta->ht_20mhz_set) { - psta->ht_20mhz_set = 1; - pmlmepriv->num_sta_ht_20mhz++; - } - DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, " - "num of 20MHz HT STAs %d\n", - __FUNCTION__, MAC_ARG(psta->hwaddr), - pmlmepriv->num_sta_ht_20mhz); - } - - } - else - { - if (!psta->no_ht_set) { - psta->no_ht_set = 1; - pmlmepriv->num_sta_no_ht++; - } - if(pmlmepriv->htpriv.ht_option == _TRUE) { - DBG_871X("%s STA " MAC_FMT - " - no HT, num of non-HT stations %d\n", - __FUNCTION__, MAC_ARG(psta->hwaddr), - pmlmepriv->num_sta_no_ht); - } - } - - if (rtw_ht_operation_update(padapter) > 0) - { - update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE); - update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE); - } - -#endif /* CONFIG_80211N_HT */ - - //update associcated stations cap. - associated_clients_update(padapter, beacon_updated); - - DBG_871X("%s, updated=%d\n", __func__, beacon_updated); - -} - -u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta) -{ - u8 beacon_updated = _FALSE; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - - if(!psta) - return beacon_updated; - - if (psta->no_short_preamble_set) { - psta->no_short_preamble_set = 0; - pmlmepriv->num_sta_no_short_preamble--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_preamble == 0) - { - beacon_updated = _TRUE; - update_beacon(padapter, 0xFF, NULL, _TRUE); - } - } - - if (psta->nonerp_set) { - psta->nonerp_set = 0; - pmlmepriv->num_sta_non_erp--; - if (pmlmepriv->num_sta_non_erp == 0) - { - beacon_updated = _TRUE; - update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE); - } - } - - if (psta->no_short_slot_time_set) { - psta->no_short_slot_time_set = 0; - pmlmepriv->num_sta_no_short_slot_time--; - if (pmlmeext->cur_wireless_mode > WIRELESS_11B - && pmlmepriv->num_sta_no_short_slot_time == 0) - { - beacon_updated = _TRUE; - update_beacon(padapter, 0xFF, NULL, _TRUE); - } - } - -#ifdef CONFIG_80211N_HT - - if (psta->no_ht_gf_set) { - psta->no_ht_gf_set = 0; - pmlmepriv->num_sta_ht_no_gf--; - } - - if (psta->no_ht_set) { - psta->no_ht_set = 0; - pmlmepriv->num_sta_no_ht--; - } - - if (psta->ht_20mhz_set) { - psta->ht_20mhz_set = 0; - pmlmepriv->num_sta_ht_20mhz--; - } - - if (rtw_ht_operation_update(padapter) > 0) - { - update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE); - update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE); - } - -#endif /* CONFIG_80211N_HT */ - - //update associcated stations cap. - //associated_clients_update(padapter, beacon_updated); //move it to avoid deadlock - - DBG_871X("%s, updated=%d\n", __func__, beacon_updated); - - return beacon_updated; - -} - -u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason) -{ - _irqL irqL; - u8 beacon_updated = _FALSE; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct sta_priv *pstapriv = &padapter->stapriv; - - if(!psta) - return beacon_updated; - - if (active == _TRUE) - { -#ifdef CONFIG_80211N_HT - //tear down Rx AMPDU - send_delba(padapter, 0, psta->hwaddr);// recipient - - //tear down TX AMPDU - send_delba(padapter, 1, psta->hwaddr);// // originator - -#endif //CONFIG_80211N_HT - - issue_deauth(padapter, psta->hwaddr, reason); - } - - psta->htpriv.agg_enable_bitmap = 0x0;//reset - psta->htpriv.candidate_tid_bitmap = 0x0;//reset - - - //report_del_sta_event(padapter, psta->hwaddr, reason); - - //clear cam entry / key - //clear_cam_entry(padapter, (psta->mac_id + 3)); - rtw_clearstakey_cmd(padapter, (u8*)psta, (u8)(psta->mac_id + 3), _TRUE); - - - _enter_critical_bh(&psta->lock, &irqL); - psta->state &= ~_FW_LINKED; - _exit_critical_bh(&psta->lock, &irqL); - - #ifdef CONFIG_IOCTL_CFG80211 - if (1) { - #ifdef COMPAT_KERNEL_RELEASE - rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason); - #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) - rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason); - #else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) - /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */ - #endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) - } else - #endif //CONFIG_IOCTL_CFG80211 - { - rtw_indicate_sta_disassoc_event(padapter, psta); - } - - report_del_sta_event(padapter, psta->hwaddr, reason); - - beacon_updated = bss_cap_update_on_sta_leave(padapter, psta); - - _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - rtw_free_stainfo(padapter, psta); - _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - - - return beacon_updated; - -} - -int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset) -{ - _irqL irqL; - _list *phead, *plist; - int ret=0; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; - - if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) - return ret; - - DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset); - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - phead = &pstapriv->asoc_list; - plist = get_next(phead); - - /* for each sta in asoc_queue */ - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) - { - psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - plist = get_next(plist); - - issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset); - psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2); - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset); - - return ret; -} - -int rtw_sta_flush(_adapter *padapter) -{ - _irqL irqL; - _list *phead, *plist; - int ret=0; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff}; - u8 chk_alive_num = 0; - char chk_alive_list[NUM_STA]; - int i; - - DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - - if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) - return ret; - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - phead = &pstapriv->asoc_list; - plist = get_next(phead); - - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { - int stainfo_offset; - - psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - plist = get_next(plist); - - /* Remove sta from asoc_list */ - rtw_list_delete(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - - /* Keep sta for ap_free_sta() beyond this asoc_list loop */ - stainfo_offset = rtw_stainfo_offset(pstapriv, psta); - if (stainfo_offset_valid(stainfo_offset)) { - chk_alive_list[chk_alive_num++] = stainfo_offset; - } - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - - /* For each sta in chk_alive_list, call ap_free_sta */ - for (i = 0; i < chk_alive_num; i++) { - psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); - ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING); - } - - issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); - - associated_clients_update(padapter, _TRUE); - - return ret; - -} - -/* called > TSR LEVEL for USB or SDIO Interface*/ -void sta_info_update(_adapter *padapter, struct sta_info *psta) -{ - int flags = psta->flags; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - - //update wmm cap. - if(WLAN_STA_WME&flags) - psta->qos_option = 1; - else - psta->qos_option = 0; - - if(pmlmepriv->qospriv.qos_option == 0) - psta->qos_option = 0; - - -#ifdef CONFIG_80211N_HT - //update 802.11n ht cap. - if(WLAN_STA_HT&flags) - { - psta->htpriv.ht_option = _TRUE; - psta->qos_option = 1; - } - else - { - psta->htpriv.ht_option = _FALSE; - } - - if(pmlmepriv->htpriv.ht_option == _FALSE) - psta->htpriv.ht_option = _FALSE; -#endif - - - update_sta_info_apmode(padapter, psta); - - -} - -/* called >= TSR LEVEL for USB or SDIO Interface*/ -void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta) -{ - if(psta->state & _FW_LINKED) - { - //add ratid - add_RATid(padapter, psta, 0);//DM_RATR_STA_INIT - } -} - -/* restore hw setting from sw data structures */ -void rtw_ap_restore_network(_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct sta_priv * pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct security_priv* psecuritypriv=&(padapter->securitypriv); - _irqL irqL; - _list *phead, *plist; - u8 chk_alive_num = 0; - char chk_alive_list[NUM_STA]; - int i; - - rtw_setopmode_cmd(padapter, Ndis802_11APMode); - - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network); - - if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) || - (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) - { - /* restore group key, WEP keys is restored in ips_leave() */ - rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0); - } - - /* per sta pairwise key and settings */ - if((padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_) && - (padapter->securitypriv.dot11PrivacyAlgrthm != _AES_)) { - return; - } - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - phead = &pstapriv->asoc_list; - plist = get_next(phead); - - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { - int stainfo_offset; - - psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - plist = get_next(plist); - - stainfo_offset = rtw_stainfo_offset(pstapriv, psta); - if (stainfo_offset_valid(stainfo_offset)) { - chk_alive_list[chk_alive_num++] = stainfo_offset; - } - } - - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - for (i = 0; i < chk_alive_num; i++) { - psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); - - if (psta == NULL) { - DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter)); - } - else if(psta->state &_FW_LINKED) - { - Update_RA_Entry(padapter, psta); - //pairwise key - rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE); - } - } - -} - -void start_ap_mode(_adapter *padapter) -{ - int i; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - - pmlmepriv->update_bcn = _FALSE; - - //init_mlme_ap_info(padapter); - pmlmeext->bstart_bss = _FALSE; - - pmlmepriv->num_sta_non_erp = 0; - - pmlmepriv->num_sta_no_short_slot_time = 0; - - pmlmepriv->num_sta_no_short_preamble = 0; - - pmlmepriv->num_sta_ht_no_gf = 0; -#ifdef CONFIG_80211N_HT - pmlmepriv->num_sta_no_ht = 0; -#endif //CONFIG_80211N_HT - pmlmepriv->num_sta_ht_20mhz = 0; - - pmlmepriv->olbc = _FALSE; - - pmlmepriv->olbc_ht = _FALSE; - -#ifdef CONFIG_80211N_HT - pmlmepriv->ht_op_mode = 0; -#endif - - for(i=0; i<NUM_STA; i++) - pstapriv->sta_aid[i] = NULL; - - pmlmepriv->wps_beacon_ie = NULL; - pmlmepriv->wps_probe_resp_ie = NULL; - pmlmepriv->wps_assoc_resp_ie = NULL; - - pmlmepriv->p2p_beacon_ie = NULL; - pmlmepriv->p2p_probe_resp_ie = NULL; - - - //for ACL - _rtw_init_listhead(&(pacl_list->acl_node_q.queue)); - pacl_list->num = 0; - pacl_list->mode = 0; - for(i = 0; i < NUM_ACL; i++) - { - _rtw_init_listhead(&pacl_list->aclnode[i].list); - pacl_list->aclnode[i].valid = _FALSE; - } - -} - -void stop_ap_mode(_adapter *padapter) -{ - _irqL irqL; - _list *phead, *plist; - struct rtw_wlan_acl_node *paclnode; - struct sta_info *psta=NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; - _queue *pacl_node_q =&pacl_list->acl_node_q; - - pmlmepriv->update_bcn = _FALSE; - pmlmeext->bstart_bss = _FALSE; - //_rtw_spinlock_free(&pmlmepriv->bcn_update_lock); - - //reset and init security priv , this can refine with rtw_reset_securitypriv - _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv)); - padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; - padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; - - //for ACL - _enter_critical_bh(&(pacl_node_q->lock), &irqL); - phead = get_list_head(pacl_node_q); - plist = get_next(phead); - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) - { - paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list); - plist = get_next(plist); - - if(paclnode->valid == _TRUE) - { - paclnode->valid = _FALSE; - - rtw_list_delete(&paclnode->list); - - pacl_list->num--; - } - } - _exit_critical_bh(&(pacl_node_q->lock), &irqL); - - DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num); - - rtw_sta_flush(padapter); - - //free_assoc_sta_resources - rtw_free_all_stainfo(padapter); - - psta = rtw_get_bcmc_stainfo(padapter); - _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - rtw_free_stainfo(padapter, psta); - _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - - rtw_init_bcmc_stainfo(padapter); - - rtw_free_mlme_priv_ie_data(pmlmepriv); - -} - -#endif //CONFIG_NATIVEAP_MLME -#endif //CONFIG_AP_MODE - +/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_AP_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+#include <wifi.h>
+
+
+#ifdef CONFIG_AP_MODE
+
+extern unsigned char RTW_WPA_OUI[];
+extern unsigned char WMM_OUI[];
+extern unsigned char WPS_OUI[];
+extern unsigned char P2P_OUI[];
+extern unsigned char WFD_OUI[];
+
+void init_mlme_ap_info(_adapter *padapter)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+
+
+ _rtw_spinlock_init(&pmlmepriv->bcn_update_lock);
+
+ //for ACL
+ _rtw_init_queue(&pacl_list->acl_node_q);
+
+ //pmlmeext->bstart_bss = _FALSE;
+
+ start_ap_mode(padapter);
+}
+
+void free_mlme_ap_info(_adapter *padapter)
+{
+ _irqL irqL;
+ struct sta_info *psta=NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ //stop_ap_mode(padapter);
+
+ pmlmepriv->update_bcn = _FALSE;
+ pmlmeext->bstart_bss = _FALSE;
+
+ rtw_sta_flush(padapter);
+
+ pmlmeinfo->state = _HW_STATE_NOLINK_;
+
+ //free_assoc_sta_resources
+ rtw_free_all_stainfo(padapter);
+
+ //free bc/mc sta_info
+ psta = rtw_get_bcmc_stainfo(padapter);
+ _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ rtw_free_stainfo(padapter, psta);
+ _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ _rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
+
+}
+
+static void update_BCNTIM(_adapter *padapter)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
+ unsigned char *pie = pnetwork_mlmeext->IEs;
+
+ //DBG_871X("%s\n", __FUNCTION__);
+
+ //update TIM IE
+ //if(pstapriv->tim_bitmap)
+ if(_TRUE)
+ {
+ u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
+ u16 tim_bitmap_le;
+ uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
+
+ tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
+
+ p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
+ if (p != NULL && tim_ielen>0)
+ {
+ tim_ielen += 2;
+
+ premainder_ie = p+tim_ielen;
+
+ tim_ie_offset = (sint)(p -pie);
+
+ remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
+
+ //append TIM IE from dst_ie offset
+ dst_ie = p;
+ }
+ else
+ {
+ tim_ielen = 0;
+
+ //calucate head_len
+ offset = _FIXED_IE_LENGTH_;
+
+ /* get ssid_ie len */
+ p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
+ if (p != NULL)
+ offset += tmp_len+2;
+
+ // get supported rates len
+ p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
+ if (p != NULL)
+ {
+ offset += tmp_len+2;
+ }
+
+ //DS Parameter Set IE, len=3
+ offset += 3;
+
+ premainder_ie = pie + offset;
+
+ remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
+
+ //append TIM IE from offset
+ dst_ie = pie + offset;
+
+ }
+
+
+ if(remainder_ielen>0)
+ {
+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+ if(pbackup_remainder_ie && premainder_ie)
+ _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+ }
+
+ *dst_ie++=_TIM_IE_;
+
+ if((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc))
+ tim_ielen = 5;
+ else
+ tim_ielen = 4;
+
+ *dst_ie++= tim_ielen;
+
+ *dst_ie++=0;//DTIM count
+ *dst_ie++=1;//DTIM peroid
+
+ if(pstapriv->tim_bitmap&BIT(0))//for bc/mc frames
+ *dst_ie++ = BIT(0);//bitmap ctrl
+ else
+ *dst_ie++ = 0;
+
+ if(tim_ielen==4)
+ {
+ *dst_ie++ = *(u8*)&tim_bitmap_le;
+ }
+ else if(tim_ielen==5)
+ {
+ _rtw_memcpy(dst_ie, &tim_bitmap_le, 2);
+ dst_ie+=2;
+ }
+
+ //copy remainder IE
+ if(pbackup_remainder_ie)
+ {
+ _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+ rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+ }
+
+ offset = (uint)(dst_ie - pie);
+ pnetwork_mlmeext->IELength = offset + remainder_ielen;
+
+ }
+
+#ifndef CONFIG_INTERRUPT_BASED_TXBCN
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+ set_tx_beacon_cmd(padapter);
+#endif
+#endif //!CONFIG_INTERRUPT_BASED_TXBCN
+
+
+}
+
+void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)
+{
+ PNDIS_802_11_VARIABLE_IEs pIE;
+ u8 bmatch = _FALSE;
+ u8 *pie = pnetwork->IEs;
+ u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
+ u32 i, offset, ielen, ie_offset, remainder_ielen = 0;
+
+ for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)
+ {
+ pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
+
+ if (pIE->ElementID > index)
+ {
+ break;
+ }
+ else if(pIE->ElementID == index) // already exist the same IE
+ {
+ p = (u8 *)pIE;
+ ielen = pIE->Length;
+ bmatch = _TRUE;
+ break;
+ }
+
+ p = (u8 *)pIE;
+ ielen = pIE->Length;
+ i += (pIE->Length + 2);
+ }
+
+ if (p != NULL && ielen>0)
+ {
+ ielen += 2;
+
+ premainder_ie = p+ielen;
+
+ ie_offset = (sint)(p -pie);
+
+ remainder_ielen = pnetwork->IELength - ie_offset - ielen;
+
+ if(bmatch)
+ dst_ie = p;
+ else
+ dst_ie = (p+ielen);
+ }
+
+ if(remainder_ielen>0)
+ {
+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+ if(pbackup_remainder_ie && premainder_ie)
+ _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+ }
+
+ *dst_ie++=index;
+ *dst_ie++=len;
+
+ _rtw_memcpy(dst_ie, data, len);
+ dst_ie+=len;
+
+ //copy remainder IE
+ if(pbackup_remainder_ie)
+ {
+ _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+ rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+ }
+
+ offset = (uint)(dst_ie - pie);
+ pnetwork->IELength = offset + remainder_ielen;
+}
+
+void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)
+{
+ u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
+ uint offset, ielen, ie_offset, remainder_ielen = 0;
+ u8 *pie = pnetwork->IEs;
+
+ p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);
+ if (p != NULL && ielen>0)
+ {
+ ielen += 2;
+
+ premainder_ie = p+ielen;
+
+ ie_offset = (sint)(p -pie);
+
+ remainder_ielen = pnetwork->IELength - ie_offset - ielen;
+
+ dst_ie = p;
+ }
+ else {
+ return;
+ }
+
+ if(remainder_ielen>0)
+ {
+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+ if(pbackup_remainder_ie && premainder_ie)
+ _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+ }
+
+ //copy remainder IE
+ if(pbackup_remainder_ie)
+ {
+ _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+ rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+ }
+
+ offset = (uint)(dst_ie - pie);
+ pnetwork->IELength = offset + remainder_ielen;
+}
+
+
+u8 chk_sta_is_alive(struct sta_info *psta);
+u8 chk_sta_is_alive(struct sta_info *psta)
+{
+ u8 ret = _FALSE;
+ #ifdef DBG_EXPIRATION_CHK
+ DBG_871X("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"
+ , MAC_ARG(psta->hwaddr)
+ , psta->rssi_stat.UndecoratedSmoothedPWDB
+ //, STA_RX_PKTS_ARG(psta)
+ , STA_RX_PKTS_DIFF_ARG(psta)
+ , psta->expire_to
+ , psta->state&WIFI_SLEEP_STATE?"PS, ":""
+ , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""
+ , psta->sleepq_len
+ );
+ #endif
+
+ //if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta))
+ if((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts))
+ {
+ #if 0
+ if(psta->state&WIFI_SLEEP_STATE)
+ ret = _TRUE;
+ #endif
+ }
+ else
+ {
+ ret = _TRUE;
+ }
+
+ sta_update_last_rx_pkts(psta);
+
+ return ret;
+}
+
+void expire_timeout_chk(_adapter *padapter)
+{
+ _irqL irqL;
+ _list *phead, *plist;
+ u8 updated;
+ struct sta_info *psta=NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 chk_alive_num = 0;
+ char chk_alive_list[NUM_STA];
+ int i;
+
+ _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+
+ phead = &pstapriv->auth_list;
+ plist = get_next(phead);
+
+ //check auth_queue
+ #ifdef DBG_EXPIRATION_CHK
+ if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+ DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"
+ , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);
+ }
+ #endif
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
+ plist = get_next(plist);
+
+ if(psta->expire_to>0)
+ {
+ psta->expire_to--;
+ if (psta->expire_to == 0)
+ {
+ rtw_list_delete(&psta->auth_list);
+ pstapriv->auth_list_cnt--;
+
+ DBG_871X("auth expire %02X%02X%02X%02X%02X%02X\n",
+ psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]);
+
+ _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
+
+ _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ rtw_free_stainfo(padapter, psta);
+ _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+
+ _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+ }
+ }
+
+ }
+
+ _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
+
+ psta = NULL;
+
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ //check asoc_queue
+ #ifdef DBG_EXPIRATION_CHK
+ if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+ DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"
+ , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);
+ }
+ #endif
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+ plist = get_next(plist);
+
+ if (chk_sta_is_alive(psta) || !psta->expire_to) {
+ psta->expire_to = pstapriv->expire_to;
+ psta->keep_alive_trycnt = 0;
+ #ifdef CONFIG_TX_MCAST2UNI
+ psta->under_exist_checking = 0;
+ #endif // CONFIG_TX_MCAST2UNI
+ } else {
+ psta->expire_to--;
+ }
+
+#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+#ifdef CONFIG_TX_MCAST2UNI
+#ifdef CONFIG_80211N_HT
+ if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) {
+ // check sta by delba(addba) for 11n STA
+ // ToDo: use CCX report to check for all STAs
+ //DBG_871X("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->htpriv.agg_enable_bitmap, psta->under_exist_checking);
+
+ if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) {
+ DBG_871X("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
+ psta->under_exist_checking = 0;
+ psta->expire_to = 0;
+ } else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) {
+ DBG_871X("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
+ psta->under_exist_checking = 1;
+ //tear down TX AMPDU
+ send_delba(padapter, 1, psta->hwaddr);// // originator
+ psta->htpriv.agg_enable_bitmap = 0x0;//reset
+ psta->htpriv.candidate_tid_bitmap = 0x0;//reset
+ }
+ }
+#endif //CONFIG_80211N_HT
+#endif // CONFIG_TX_MCAST2UNI
+#endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+
+ if (psta->expire_to <= 0)
+ {
+ #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+ if (padapter->registrypriv.wifi_spec == 1)
+ {
+ psta->expire_to = pstapriv->expire_to;
+ continue;
+ }
+
+ if (psta->state & WIFI_SLEEP_STATE) {
+ if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
+ //to check if alive by another methods if staion is at ps mode.
+ psta->expire_to = pstapriv->expire_to;
+ psta->state |= WIFI_STA_ALIVE_CHK_STATE;
+
+ //DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr));
+
+ //to update bcn with tim_bitmap for this station
+ pstapriv->tim_bitmap |= BIT(psta->aid);
+ update_beacon(padapter, _TIM_IE_, NULL, _FALSE);
+
+ if(!pmlmeext->active_keep_alive_check)
+ continue;
+ }
+ }
+
+ if (pmlmeext->active_keep_alive_check) {
+ int stainfo_offset;
+
+ stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+ if (stainfo_offset_valid(stainfo_offset)) {
+ chk_alive_list[chk_alive_num++] = stainfo_offset;
+ }
+
+ continue;
+ }
+ #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
+
+ rtw_list_delete(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+
+ DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
+ updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);
+ }
+ else
+ {
+ /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
+ if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
+ && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
+ ){
+ DBG_871X("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__
+ , MAC_ARG(psta->hwaddr)
+ , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);
+ wakeup_sta_to_xmit(padapter, psta);
+ }
+ }
+ }
+
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+if (chk_alive_num) {
+
+ u8 backup_oper_channel=0;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ /* switch to correct channel of current network before issue keep-alive frames */
+ if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
+ backup_oper_channel = rtw_get_oper_ch(padapter);
+ SelectChannel(padapter, pmlmeext->cur_channel);
+ }
+
+ /* issue null data to check sta alive*/
+ for (i = 0; i < chk_alive_num; i++) {
+
+ int ret = _FAIL;
+
+ psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
+ if(!(psta->state &_FW_LINKED))
+ continue;
+
+ if (psta->state & WIFI_SLEEP_STATE)
+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
+ else
+ ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
+
+ psta->keep_alive_trycnt++;
+ if (ret == _SUCCESS)
+ {
+ DBG_871X("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));
+ psta->expire_to = pstapriv->expire_to;
+ psta->keep_alive_trycnt = 0;
+ continue;
+ }
+ else if (psta->keep_alive_trycnt <= 3)
+ {
+ DBG_871X("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
+ psta->expire_to = 1;
+ continue;
+ }
+
+ psta->keep_alive_trycnt = 0;
+
+ DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) {
+ rtw_list_delete(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+ updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);
+ }
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ }
+
+ if (backup_oper_channel>0) /* back to the original operation channel */
+ SelectChannel(padapter, backup_oper_channel);
+}
+#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
+
+ associated_clients_update(padapter, updated);
+}
+
+void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level)
+{
+ int i;
+ u8 rf_type;
+ u32 init_rate=0;
+ unsigned char sta_band = 0, raid, shortGIrate = _FALSE;
+ unsigned char limit;
+ unsigned int tx_ra_bitmap=0;
+ struct ht_priv *psta_ht = NULL;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+
+#ifdef CONFIG_80211N_HT
+ if(psta)
+ psta_ht = &psta->htpriv;
+ else
+ return;
+#endif //CONFIG_80211N_HT
+
+ if(!(psta->state & _FW_LINKED))
+ return;
+
+ //b/g mode ra_bitmap
+ for (i=0; i<sizeof(psta->bssrateset); i++)
+ {
+ if (psta->bssrateset[i])
+ tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
+ }
+#ifdef CONFIG_80211N_HT
+ //n mode ra_bitmap
+ if(psta_ht->ht_option)
+ {
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if(rf_type == RF_2T2R)
+ limit=16;// 2R
+ else
+ limit=8;// 1R
+
+ for (i=0; i<limit; i++) {
+ if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8))
+ tx_ra_bitmap |= BIT(i+12);
+ }
+
+ //max short GI rate
+ shortGIrate = psta_ht->sgi;
+ }
+#endif //CONFIG_80211N_HT
+
+#if 0//gtest
+ if(get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)
+ {
+ //is this a 2r STA?
+ if((pstat->tx_ra_bitmap & 0x0ff00000) != 0 && !(priv->pshare->has_2r_sta & BIT(pstat->aid)))
+ {
+ priv->pshare->has_2r_sta |= BIT(pstat->aid);
+ if(rtw_read16(padapter, 0x102501f6) != 0xffff)
+ {
+ rtw_write16(padapter, 0x102501f6, 0xffff);
+ reset_1r_sta_RA(priv, 0xffff);
+ Switch_1SS_Antenna(priv, 3);
+ }
+ }
+ else// bg or 1R STA?
+ {
+ if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && priv->pshare->has_2r_sta == 0)
+ {
+ if(rtw_read16(padapter, 0x102501f6) != 0x7777)
+ { // MCS7 SGI
+ rtw_write16(padapter, 0x102501f6,0x7777);
+ reset_1r_sta_RA(priv, 0x7777);
+ Switch_1SS_Antenna(priv, 2);
+ }
+ }
+ }
+
+ }
+
+ if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3))
+ {
+ if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper)
+ pstat->rssi_level = 1;
+ else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) ||
+ ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) &&
+ (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) &&
+ (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))))
+ pstat->rssi_level = 2;
+ else
+ pstat->rssi_level = 3;
+ }
+
+ // rate adaptive by rssi
+ if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len)
+ {
+ if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R))
+ {
+ switch (pstat->rssi_level) {
+ case 1:
+ pstat->tx_ra_bitmap &= 0x100f0000;
+ break;
+ case 2:
+ pstat->tx_ra_bitmap &= 0x100ff000;
+ break;
+ case 3:
+ if (priv->pshare->is_40m_bw)
+ pstat->tx_ra_bitmap &= 0x100ff005;
+ else
+ pstat->tx_ra_bitmap &= 0x100ff001;
+
+ break;
+ }
+ }
+ else
+ {
+ switch (pstat->rssi_level) {
+ case 1:
+ pstat->tx_ra_bitmap &= 0x1f0f0000;
+ break;
+ case 2:
+ pstat->tx_ra_bitmap &= 0x1f0ff000;
+ break;
+ case 3:
+ if (priv->pshare->is_40m_bw)
+ pstat->tx_ra_bitmap &= 0x000ff005;
+ else
+ pstat->tx_ra_bitmap &= 0x000ff001;
+
+ break;
+ }
+
+ // Don't need to mask high rates due to new rate adaptive parameters
+ //if (pstat->is_broadcom_sta) // use MCS12 as the highest rate vs. Broadcom sta
+ // pstat->tx_ra_bitmap &= 0x81ffffff;
+
+ // NIC driver will report not supporting MCS15 and MCS14 in asoc req
+ //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta)
+ // pstat->tx_ra_bitmap &= 0x83ffffff; // if Realtek 1x2 sta, don't use MCS15 and MCS14
+ }
+ }
+ else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat))
+ {
+ switch (pstat->rssi_level) {
+ case 1:
+ pstat->tx_ra_bitmap &= 0x00000f00;
+ break;
+ case 2:
+ pstat->tx_ra_bitmap &= 0x00000ff0;
+ break;
+ case 3:
+ pstat->tx_ra_bitmap &= 0x00000ff5;
+ break;
+ }
+ }
+ else
+ {
+ pstat->tx_ra_bitmap &= 0x0000000d;
+ }
+
+ // disable tx short GI when station cannot rx MCS15(AP is 2T2R)
+ // disable tx short GI when station cannot rx MCS7 (AP is 1T2R or 1T1R)
+ // if there is only 1r STA and we are 2T2R, DO NOT mask SGI rate
+ if ((!(pstat->tx_ra_bitmap & 0x8000000) && (priv->pshare->has_2r_sta > 0) && (get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)) ||
+ (!(pstat->tx_ra_bitmap & 0x80000) && (get_rf_mimo_mode(padapter) != RTL8712_RF_2T2R)))
+ {
+ pstat->tx_ra_bitmap &= ~BIT(28);
+ }
+#endif
+
+ if ( pcur_network->Configuration.DSConfig > 14 ) {
+ // 5G band
+ if (tx_ra_bitmap & 0xffff000)
+ sta_band |= WIRELESS_11_5N ;
+
+ if (tx_ra_bitmap & 0xff0)
+ sta_band |= WIRELESS_11A;
+
+ } else {
+ if (tx_ra_bitmap & 0xffff000)
+ sta_band |= WIRELESS_11_24N;
+
+ if (tx_ra_bitmap & 0xff0)
+ sta_band |= WIRELESS_11G;
+
+ if (tx_ra_bitmap & 0x0f)
+ sta_band |= WIRELESS_11B;
+ }
+
+ psta->wireless_mode = sta_band;
+
+ raid = networktype_to_raid(sta_band);
+ init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f;
+
+ if (psta->aid < NUM_STA)
+ {
+ u8 arg = 0;
+
+ arg = psta->mac_id&0x1f;
+
+ arg |= BIT(7);//support entry 2~31
+
+ if (shortGIrate==_TRUE)
+ arg |= BIT(5);
+
+ tx_ra_bitmap |= ((raid<<28)&0xf0000000);
+
+ DBG_871X("%s=> mac_id:%d , raid:%d , bitmap=0x%x, arg=0x%x\n",
+ __FUNCTION__ , psta->mac_id, raid ,tx_ra_bitmap, arg);
+
+ //bitmap[0:27] = tx_rate_bitmap
+ //bitmap[28:31]= Rate Adaptive id
+ //arg[0:4] = macid
+ //arg[5] = Short GI
+ rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
+
+
+ if (shortGIrate==_TRUE)
+ init_rate |= BIT(6);
+
+ //set ra_id, init_rate
+ psta->raid = raid;
+ psta->init_rate = init_rate;
+
+ }
+ else
+ {
+ DBG_871X("station aid %d exceed the max number\n", psta->aid);
+ }
+
+}
+
+void update_bmc_sta(_adapter *padapter)
+{
+ _irqL irqL;
+ u32 init_rate=0;
+ unsigned char network_type, raid;
+ int i, supportRateNum = 0;
+ unsigned int tx_ra_bitmap=0;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+ struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
+
+ if(psta)
+ {
+ psta->aid = 0;//default set to 0
+ //psta->mac_id = psta->aid+4;
+ psta->mac_id = psta->aid + 1;
+
+ psta->qos_option = 0;
+#ifdef CONFIG_80211N_HT
+ psta->htpriv.ht_option = _FALSE;
+#endif //CONFIG_80211N_HT
+
+ psta->ieee8021x_blocked = 0;
+
+ _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+ //psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this.
+
+
+
+ //prepare for add_RATid
+ supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates);
+ network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, 1);
+
+ _rtw_memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum);
+ psta->bssratelen = supportRateNum;
+
+ //b/g mode ra_bitmap
+ for (i=0; i<supportRateNum; i++)
+ {
+ if (psta->bssrateset[i])
+ tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
+ }
+
+ if ( pcur_network->Configuration.DSConfig > 14 ) {
+ //force to A mode. 5G doesn't support CCK rates
+ network_type = WIRELESS_11A;
+ tx_ra_bitmap = 0x150; // 6, 12, 24 Mbps
+ } else {
+ //force to b mode
+ network_type = WIRELESS_11B;
+ tx_ra_bitmap = 0xf;
+ }
+
+ //tx_ra_bitmap = update_basic_rate(pcur_network->SupportedRates, supportRateNum);
+
+ raid = networktype_to_raid(network_type);
+ init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f;
+
+ //DBG_871X("Add id %d val %08x to ratr for bmc sta\n", psta->aid, tx_ra_bitmap);
+ //ap mode
+ rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
+
+ //if(pHalData->fw_ractrl == _TRUE)
+ {
+ u8 arg = 0;
+
+ arg = psta->mac_id&0x1f;
+
+ arg |= BIT(7);
+
+ //if (shortGIrate==_TRUE)
+ // arg |= BIT(5);
+
+ tx_ra_bitmap |= ((raid<<28)&0xf0000000);
+
+ DBG_871X("update_bmc_sta, mask=0x%x, arg=0x%x\n", tx_ra_bitmap, arg);
+
+ //bitmap[0:27] = tx_rate_bitmap
+ //bitmap[28:31]= Rate Adaptive id
+ //arg[0:4] = macid
+ //arg[5] = Short GI
+ rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
+
+ }
+
+ //set ra_id, init_rate
+ psta->raid = raid;
+ psta->init_rate = init_rate;
+
+ rtw_sta_media_status_rpt(padapter, psta, 1);
+
+ _enter_critical_bh(&psta->lock, &irqL);
+ psta->state = _FW_LINKED;
+ _exit_critical_bh(&psta->lock, &irqL);
+
+ }
+ else
+ {
+ DBG_871X("add_RATid_bmc_sta error!\n");
+ }
+
+}
+
+//notes:
+//AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode
+//MAC_ID = AID+1 for sta in ap/adhoc mode
+//MAC_ID = 1 for bc/mc for sta/ap/adhoc
+//MAC_ID = 0 for bssid for sta/ap/adhoc
+//CAM_ID = //0~3 for default key, cmd_id=macid + 3, macid=aid+1;
+
+void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)
+{
+ _irqL irqL;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+#ifdef CONFIG_80211N_HT
+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
+ struct ht_priv *phtpriv_sta = &psta->htpriv;
+#endif //CONFIG_80211N_HT
+ //set intf_tag to if1
+ //psta->intf_tag = 0;
+
+ //psta->mac_id = psta->aid+4;
+ psta->mac_id = psta->aid+1;
+ DBG_871X("%s\n",__FUNCTION__);
+
+ //ap mode
+ rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);
+
+ if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
+ psta->ieee8021x_blocked = _TRUE;
+ else
+ psta->ieee8021x_blocked = _FALSE;
+
+
+ //update sta's cap
+
+ //ERP
+ VCS_update(padapter, psta);
+#ifdef CONFIG_80211N_HT
+ //HT related cap
+ if(phtpriv_sta->ht_option)
+ {
+ //check if sta supports rx ampdu
+ phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
+
+ //check if sta support s Short GI
+ if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40))
+ {
+ phtpriv_sta->sgi = _TRUE;
+ }
+
+ // bwmode
+ if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
+ {
+ //phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40;
+ phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
+ phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
+
+ }
+
+ psta->qos_option = _TRUE;
+
+ }
+ else
+ {
+ phtpriv_sta->ampdu_enable = _FALSE;
+
+ phtpriv_sta->sgi = _FALSE;
+ phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
+ phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ }
+
+ //Rx AMPDU
+ send_delba(padapter, 0, psta->hwaddr);// recipient
+
+ //TX AMPDU
+ send_delba(padapter, 1, psta->hwaddr);// // originator
+ phtpriv_sta->agg_enable_bitmap = 0x0;//reset
+ phtpriv_sta->candidate_tid_bitmap = 0x0;//reset
+#endif //CONFIG_80211N_HT
+
+ //todo: init other variables
+
+ _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+
+ //add ratid
+ //add_RATid(padapter, psta);//move to ap_sta_info_defer_update()
+
+
+ _enter_critical_bh(&psta->lock, &irqL);
+ psta->state |= _FW_LINKED;
+ _exit_critical_bh(&psta->lock, &irqL);
+
+
+}
+
+static void update_hw_ht_param(_adapter *padapter)
+{
+ unsigned char max_AMPDU_len;
+ unsigned char min_MPDU_spacing;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ DBG_871X("%s\n", __FUNCTION__);
+
+
+ //handle A-MPDU parameter field
+ /*
+ AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+ AMPDU_para [4:2]:Min MPDU Start Spacing
+ */
+ max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
+
+ min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+
+ //
+ // Config SM Power Save setting
+ //
+ pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
+ if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+ {
+ /*u8 i;
+ //update the MCS rates
+ for (i = 0; i < 16; i++)
+ {
+ pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
+ }*/
+ DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);
+ }
+
+ //
+ // Config current HT Protection mode.
+ //
+ //pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
+
+}
+
+static void start_bss_network(_adapter *padapter, u8 *pbuf)
+{
+ u8 *p;
+ u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
+ u16 bcn_interval;
+ u32 acparm;
+ int ie_len;
+ struct registry_priv *pregpriv = &padapter->registrypriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct security_priv* psecuritypriv=&(padapter->securitypriv);
+ WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
+ struct HT_info_element *pht_info=NULL;
+#ifdef CONFIG_P2P
+ struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+#endif //CONFIG_P2P
+
+ //DBG_871X("%s\n", __FUNCTION__);
+
+ bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
+ cur_channel = pnetwork->Configuration.DSConfig;
+ cur_bwmode = HT_CHANNEL_WIDTH_20;;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+
+ //check if there is wps ie,
+ //if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd,
+ //and at first time the security ie ( RSN/WPA IE) will not include in beacon.
+ if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
+ {
+ pmlmeext->bstart_bss = _TRUE;
+ }
+
+ //todo: update wmm, ht cap
+ //pmlmeinfo->WMM_enable;
+ //pmlmeinfo->HT_enable;
+ if(pmlmepriv->qospriv.qos_option)
+ pmlmeinfo->WMM_enable = _TRUE;
+#ifdef CONFIG_80211N_HT
+ if(pmlmepriv->htpriv.ht_option)
+ {
+ pmlmeinfo->WMM_enable = _TRUE;
+ pmlmeinfo->HT_enable = _TRUE;
+ //pmlmeinfo->HT_info_enable = _TRUE;
+ //pmlmeinfo->HT_caps_enable = _TRUE;
+
+ update_hw_ht_param(padapter);
+ }
+#endif //#CONFIG_80211N_HT
+
+
+ if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at first time
+ {
+ //WEP Key will be set before this function, do not clear CAM.
+ if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
+ flush_all_cam_entry(padapter); //clear CAM
+ }
+
+ //set MSR to AP_Mode
+ Set_MSR(padapter, _HW_STATE_AP_);
+
+ //Set BSSID REG
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
+
+ //Set EDCA param reg
+#ifdef CONFIG_CONCURRENT_MODE
+ acparm = 0x005ea42b;
+#else
+ acparm = 0x002F3217; // VO
+#endif
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
+ acparm = 0x005E4317; // VI
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
+ //acparm = 0x00105320; // BE
+ acparm = 0x005ea42b;
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
+ acparm = 0x0000A444; // BK
+ rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
+
+ //Set Security
+ val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+ //Beacon Control related register
+ rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
+
+
+ UpdateBrateTbl(padapter, pnetwork->SupportedRates);
+ rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
+
+ if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at first time
+ {
+ //u32 initialgain;
+
+ //initialgain = 0x1e;
+
+
+ //disable dynamic functions, such as high power, DIG
+ //Save_DM_Func_Flag(padapter);
+ //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
+
+#ifdef CONFIG_CONCURRENT_MODE
+ if(padapter->adapter_type > PRIMARY_ADAPTER)
+ {
+ if(rtw_buddy_adapter_up(padapter))
+ {
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+
+ //turn on all dynamic functions on PRIMARY_ADAPTER, dynamic functions only runs at PRIMARY_ADAPTER
+ Switch_DM_Func(pbuddy_adapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
+
+ //rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+ }
+ }
+ else
+#endif
+ {
+ //turn on all dynamic functions
+ Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
+
+ //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
+ }
+
+ }
+#ifdef CONFIG_80211N_HT
+ //set channel, bwmode
+ p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
+ if( p && ie_len)
+ {
+ pht_info = (struct HT_info_element *)(p+2);
+
+ if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2)))
+ {
+ //switch to the 40M Hz mode
+ //pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
+ cur_bwmode = HT_CHANNEL_WIDTH_40;
+ switch (pht_info->infos[0] & 0x3)
+ {
+ case 1:
+ //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ break;
+
+ case 3:
+ //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ break;
+
+ default:
+ //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+ break;
+ }
+
+ }
+
+ }
+#endif //CONFIG_80211N_HT
+#ifdef CONFIG_DUALMAC_CONCURRENT
+ dc_set_ap_channel_bandwidth(padapter, cur_channel, cur_ch_offset, cur_bwmode);
+#else
+ //TODO: need to judge the phy parameters on concurrent mode for single phy
+ //set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+#ifdef CONFIG_CONCURRENT_MODE
+ if(!check_buddy_fwstate(padapter, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))
+ {
+ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
+ }
+ else if(check_buddy_fwstate(padapter, _FW_LINKED)==_TRUE)//only second adapter can enter AP Mode
+ {
+ _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+ struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+ //To sync cur_channel/cur_bwmode/cur_ch_offset with primary adapter
+ DBG_871X("primary iface is at linked state, sync cur_channel/cur_bwmode/cur_ch_offset\n");
+ DBG_871X("primary adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
+ DBG_871X("second adapter, CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
+
+ cur_channel = pbuddy_mlmeext->cur_channel;
+ if(cur_bwmode == HT_CHANNEL_WIDTH_40)
+ {
+ if(pht_info)
+ pht_info->infos[0] &= ~(BIT(0)|BIT(1));
+
+ if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
+ {
+ cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
+
+ //to update cur_ch_offset value in beacon
+ if(pht_info)
+ {
+ switch(cur_ch_offset)
+ {
+ case HAL_PRIME_CHNL_OFFSET_LOWER:
+ pht_info->infos[0] |= 0x1;
+ break;
+ case HAL_PRIME_CHNL_OFFSET_UPPER:
+ pht_info->infos[0] |= 0x3;
+ break;
+ case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
+ default:
+ break;
+ }
+ }
+
+ }
+ else if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20)
+ {
+ cur_bwmode = HT_CHANNEL_WIDTH_20;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ if(cur_channel>0 && cur_channel<5)
+ {
+ if(pht_info)
+ pht_info->infos[0] |= 0x1;
+
+ cur_bwmode = HT_CHANNEL_WIDTH_40;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+ }
+
+ if(cur_channel>7 && cur_channel<(14+1))
+ {
+ if(pht_info)
+ pht_info->infos[0] |= 0x3;
+
+ cur_bwmode = HT_CHANNEL_WIDTH_40;
+ cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+ }
+
+ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
+ }
+
+ }
+
+ // to update channel value in beacon
+ pnetwork->Configuration.DSConfig = cur_channel;
+ p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
+ if(p && ie_len>0)
+ *(p + 2) = cur_channel;
+
+ if(pht_info)
+ pht_info->primary_channel = cur_channel;
+ }
+#else
+ set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
+#endif //CONFIG_CONCURRENT_MODE
+
+ DBG_871X("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
+
+ //
+ pmlmeext->cur_channel = cur_channel;
+ pmlmeext->cur_bwmode = cur_bwmode;
+ pmlmeext->cur_ch_offset = cur_ch_offset;
+#endif //CONFIG_DUALMAC_CONCURRENT
+ pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
+
+ //update cur_wireless_mode
+ update_wireless_mode(padapter);
+
+ //udpate capability after cur_wireless_mode updated
+ update_capinfo(padapter, rtw_get_capability((WLAN_BSSID_EX *)pnetwork));
+
+ //let pnetwork_mlmeext == pnetwork_mlme.
+ _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
+
+#ifdef CONFIG_P2P
+ _rtw_memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength);
+ pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength;
+#endif //CONFIG_P2P
+
+ if(_TRUE == pmlmeext->bstart_bss)
+ {
+ update_beacon(padapter, _TIM_IE_, NULL, _FALSE);
+
+#ifndef CONFIG_INTERRUPT_BASED_TXBCN //other case will tx beacon when bcn interrupt coming in.
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+ //issue beacon frame
+ if(send_beacon(padapter)==_FAIL)
+ {
+ DBG_871X("issue_beacon, fail!\n");
+ }
+#endif
+#endif //!CONFIG_INTERRUPT_BASED_TXBCN
+
+ }
+
+
+ //update bc/mc sta_info
+ update_bmc_sta(padapter);
+
+ //pmlmeext->bstart_bss = _TRUE;
+
+}
+
+int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len)
+{
+ int ret=_SUCCESS;
+ u8 *p;
+ u8 *pHT_caps_ie=NULL;
+ u8 *pHT_info_ie=NULL;
+ struct sta_info *psta = NULL;
+ u16 cap, ht_cap=_FALSE;
+ uint ie_len = 0;
+ int group_cipher, pairwise_cipher;
+ u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
+ int supportRateNum = 0;
+ u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};
+ u8 wps_oui[4]={0x0,0x50,0xf2,0x04};
+ u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ u8 *ie = pbss_network->IEs;
+
+
+ /* SSID */
+ /* Supported rates */
+ /* DS Params */
+ /* WLAN_EID_COUNTRY */
+ /* ERP Information element */
+ /* Extended supported rates */
+ /* WPA/WPA2 */
+ /* Wi-Fi Wireless Multimedia Extensions */
+ /* ht_capab, ht_oper */
+ /* WPS IE */
+
+ DBG_871X("%s, len=%d\n", __FUNCTION__, len);
+
+ if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
+ return _FAIL;
+
+
+ if(len>MAX_IE_SZ)
+ return _FAIL;
+
+ pbss_network->IELength = len;
+
+ _rtw_memset(ie, 0, MAX_IE_SZ);
+
+ _rtw_memcpy(ie, pbuf, pbss_network->IELength);
+
+
+ if(pbss_network->InfrastructureMode!=Ndis802_11APMode)
+ return _FAIL;
+
+ pbss_network->Rssi = 0;
+
+ _rtw_memcpy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ //beacon interval
+ p = rtw_get_beacon_interval_from_ie(ie);//ie + 8; // 8: TimeStamp, 2: Beacon Interval 2:Capability
+ //pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p);
+ pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
+
+ //capability
+ //cap = *(unsigned short *)rtw_get_capability_from_ie(ie);
+ //cap = le16_to_cpu(cap);
+ cap = RTW_GET_LE16(ie);
+
+ //SSID
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_));
+ if(p && ie_len>0)
+ {
+ _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
+ _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
+ pbss_network->Ssid.SsidLength = ie_len;
+ }
+
+ //chnnel
+ channel = 0;
+ pbss_network->Configuration.Length = 0;
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+ if(p && ie_len>0)
+ channel = *(p + 2);
+
+ pbss_network->Configuration.DSConfig = channel;
+
+
+ _rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
+ // get supported rates
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+ if (p != NULL)
+ {
+ _rtw_memcpy(supportRate, p+2, ie_len);
+ supportRateNum = ie_len;
+ }
+
+ //get ext_supported rates
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
+ if (p != NULL)
+ {
+ _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);
+ supportRateNum += ie_len;
+
+ }
+
+ network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
+
+ rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
+
+
+ //parsing ERP_IE
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+ if(p && ie_len>0)
+ {
+ ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
+ }
+
+ //update privacy/security
+ if (cap & BIT(4))
+ pbss_network->Privacy = 1;
+ else
+ pbss_network->Privacy = 0;
+
+ psecuritypriv->wpa_psk = 0;
+
+ //wpa2
+ group_cipher = 0; pairwise_cipher = 0;
+ psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
+ psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+ if(p && ie_len>0)
+ {
+ if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
+ {
+ psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
+
+ psecuritypriv->dot8021xalg = 1;//psk, todo:802.1x
+ psecuritypriv->wpa_psk |= BIT(1);
+
+ psecuritypriv->wpa2_group_cipher = group_cipher;
+ psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
+#if 0
+ switch(group_cipher)
+ {
+ case WPA_CIPHER_NONE:
+ psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
+ break;
+ case WPA_CIPHER_WEP40:
+ psecuritypriv->wpa2_group_cipher = _WEP40_;
+ break;
+ case WPA_CIPHER_TKIP:
+ psecuritypriv->wpa2_group_cipher = _TKIP_;
+ break;
+ case WPA_CIPHER_CCMP:
+ psecuritypriv->wpa2_group_cipher = _AES_;
+ break;
+ case WPA_CIPHER_WEP104:
+ psecuritypriv->wpa2_group_cipher = _WEP104_;
+ break;
+ }
+
+ switch(pairwise_cipher)
+ {
+ case WPA_CIPHER_NONE:
+ psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
+ break;
+ case WPA_CIPHER_WEP40:
+ psecuritypriv->wpa2_pairwise_cipher = _WEP40_;
+ break;
+ case WPA_CIPHER_TKIP:
+ psecuritypriv->wpa2_pairwise_cipher = _TKIP_;
+ break;
+ case WPA_CIPHER_CCMP:
+ psecuritypriv->wpa2_pairwise_cipher = _AES_;
+ break;
+ case WPA_CIPHER_WEP104:
+ psecuritypriv->wpa2_pairwise_cipher = _WEP104_;
+ break;
+ }
+#endif
+ }
+
+ }
+
+ //wpa
+ ie_len = 0;
+ group_cipher = 0; pairwise_cipher = 0;
+ psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
+ psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
+ for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
+ {
+ p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
+ if ((p) && (_rtw_memcmp(p+2, OUI1, 4)))
+ {
+ if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
+ {
+ psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
+
+ psecuritypriv->dot8021xalg = 1;//psk, todo:802.1x
+
+ psecuritypriv->wpa_psk |= BIT(0);
+
+ psecuritypriv->wpa_group_cipher = group_cipher;
+ psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
+
+#if 0
+ switch(group_cipher)
+ {
+ case WPA_CIPHER_NONE:
+ psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
+ break;
+ case WPA_CIPHER_WEP40:
+ psecuritypriv->wpa_group_cipher = _WEP40_;
+ break;
+ case WPA_CIPHER_TKIP:
+ psecuritypriv->wpa_group_cipher = _TKIP_;
+ break;
+ case WPA_CIPHER_CCMP:
+ psecuritypriv->wpa_group_cipher = _AES_;
+ break;
+ case WPA_CIPHER_WEP104:
+ psecuritypriv->wpa_group_cipher = _WEP104_;
+ break;
+ }
+
+ switch(pairwise_cipher)
+ {
+ case WPA_CIPHER_NONE:
+ psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
+ break;
+ case WPA_CIPHER_WEP40:
+ psecuritypriv->wpa_pairwise_cipher = _WEP40_;
+ break;
+ case WPA_CIPHER_TKIP:
+ psecuritypriv->wpa_pairwise_cipher = _TKIP_;
+ break;
+ case WPA_CIPHER_CCMP:
+ psecuritypriv->wpa_pairwise_cipher = _AES_;
+ break;
+ case WPA_CIPHER_WEP104:
+ psecuritypriv->wpa_pairwise_cipher = _WEP104_;
+ break;
+ }
+#endif
+ }
+
+ break;
+
+ }
+
+ if ((p == NULL) || (ie_len == 0))
+ {
+ break;
+ }
+
+ }
+
+ //wmm
+ ie_len = 0;
+ pmlmepriv->qospriv.qos_option = 0;
+ if(pregistrypriv->wmm_enable)
+ {
+ for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
+ {
+ p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
+ if((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6))
+ {
+ pmlmepriv->qospriv.qos_option = 1;
+
+ *(p+8) |= BIT(7);//QoS Info, support U-APSD
+
+ /* disable all ACM bits since the WMM admission control is not supported */
+ *(p + 10) &= ~BIT(4); /* BE */
+ *(p + 14) &= ~BIT(4); /* BK */
+ *(p + 18) &= ~BIT(4); /* VI */
+ *(p + 22) &= ~BIT(4); /* VO */
+
+ break;
+ }
+
+ if ((p == NULL) || (ie_len == 0))
+ {
+ break;
+ }
+ }
+ }
+#ifdef CONFIG_80211N_HT
+ //parsing HT_CAP_IE
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+ if(p && ie_len>0)
+ {
+ u8 rf_type;
+
+ struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);
+
+ pHT_caps_ie=p;
+
+
+ ht_cap = _TRUE;
+ network_type |= WIRELESS_11_24N;
+
+
+ rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+ if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
+ (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
+ {
+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
+ }
+ else
+ {
+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
+ }
+
+ pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); //set Max Rx AMPDU size to 64K
+
+ if(rf_type == RF_1T1R)
+ {
+ pht_cap->supp_mcs_set[0] = 0xff;
+ pht_cap->supp_mcs_set[1] = 0x0;
+ }
+
+ _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
+
+ }
+
+ //parsing HT_INFO_IE
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+ if(p && ie_len>0)
+ {
+ pHT_info_ie=p;
+ }
+#endif //CONFIG_80211N_HT
+ switch(network_type)
+ {
+ case WIRELESS_11B:
+ pbss_network->NetworkTypeInUse = Ndis802_11DS;
+ break;
+ case WIRELESS_11G:
+ case WIRELESS_11BG:
+ case WIRELESS_11G_24N:
+ case WIRELESS_11BG_24N:
+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ break;
+ case WIRELESS_11A:
+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
+ break;
+ default :
+ pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+ break;
+ }
+
+ pmlmepriv->cur_network.network_type = network_type;
+
+#ifdef CONFIG_80211N_HT
+ pmlmepriv->htpriv.ht_option = _FALSE;
+
+ if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
+ (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP))
+ {
+ //todo:
+ //ht_cap = _FALSE;
+ }
+
+ //ht_cap
+ if(pregistrypriv->ht_enable && ht_cap==_TRUE)
+ {
+ pmlmepriv->htpriv.ht_option = _TRUE;
+ pmlmepriv->qospriv.qos_option = 1;
+
+ if(pregistrypriv->ampdu_enable==1)
+ {
+ pmlmepriv->htpriv.ampdu_enable = _TRUE;
+ }
+
+ HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);
+
+ HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);
+ }
+#endif
+
+
+ pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network);
+
+ //issue beacon to start bss network
+ start_bss_network(padapter, (u8*)pbss_network);
+
+
+ //alloc sta_info for ap itself
+ psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+ if(!psta)
+ {
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+ if (psta == NULL)
+ {
+ return _FAIL;
+ }
+ }
+ psta->state |= WIFI_AP_STATE; //Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724
+ rtw_indicate_connect( padapter);
+
+ pmlmepriv->cur_network.join_res = _TRUE;//for check if already set beacon
+
+ //update bc/mc sta_info
+ //update_bmc_sta(padapter);
+
+ return ret;
+
+}
+
+void rtw_set_macaddr_acl(_adapter *padapter, int mode)
+{
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+
+ DBG_871X("%s, mode=%d\n", __func__, mode);
+
+ pacl_list->mode = mode;
+}
+
+int rtw_acl_add_sta(_adapter *padapter, u8 *addr)
+{
+ _irqL irqL;
+ _list *plist, *phead;
+ u8 added = _FALSE;
+ int i, ret=0;
+ struct rtw_wlan_acl_node *paclnode;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ _queue *pacl_node_q =&pacl_list->acl_node_q;
+
+ DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
+
+ if((NUM_ACL-1) < pacl_list->num)
+ return (-1);
+
+
+ _enter_critical_bh(&(pacl_node_q->lock), &irqL);
+
+ phead = get_list_head(pacl_node_q);
+ plist = get_next(phead);
+
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+ plist = get_next(plist);
+
+ if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN))
+ {
+ if(paclnode->valid == _TRUE)
+ {
+ added = _TRUE;
+ DBG_871X("%s, sta has been added\n", __func__);
+ break;
+ }
+ }
+ }
+
+ _exit_critical_bh(&(pacl_node_q->lock), &irqL);
+
+
+ if(added == _TRUE)
+ return ret;
+
+
+ _enter_critical_bh(&(pacl_node_q->lock), &irqL);
+
+ for(i=0; i< NUM_ACL; i++)
+ {
+ paclnode = &pacl_list->aclnode[i];
+
+ if(paclnode->valid == _FALSE)
+ {
+ _rtw_init_listhead(&paclnode->list);
+
+ _rtw_memcpy(paclnode->addr, addr, ETH_ALEN);
+
+ paclnode->valid = _TRUE;
+
+ rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));
+
+ pacl_list->num++;
+
+ break;
+ }
+ }
+
+ DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
+
+ _exit_critical_bh(&(pacl_node_q->lock), &irqL);
+
+ return ret;
+}
+
+int rtw_acl_remove_sta(_adapter *padapter, u8 *addr)
+{
+ _irqL irqL;
+ _list *plist, *phead;
+ int i, ret=0;
+ struct rtw_wlan_acl_node *paclnode;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ _queue *pacl_node_q =&pacl_list->acl_node_q;
+
+ DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
+
+ _enter_critical_bh(&(pacl_node_q->lock), &irqL);
+
+ phead = get_list_head(pacl_node_q);
+ plist = get_next(phead);
+
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+ plist = get_next(plist);
+
+ if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN))
+ {
+ if(paclnode->valid == _TRUE)
+ {
+ paclnode->valid = _FALSE;
+
+ rtw_list_delete(&paclnode->list);
+
+ pacl_list->num--;
+ }
+ }
+ }
+
+ _exit_critical_bh(&(pacl_node_q->lock), &irqL);
+
+ DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
+
+ return ret;
+
+}
+
+#ifdef CONFIG_NATIVEAP_MLME
+
+static void update_bcn_fixed_ie(_adapter *padapter)
+{
+ DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_erpinfo_ie(_adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
+ unsigned char *p, *ie = pnetwork->IEs;
+ u32 len = 0;
+
+ DBG_871X("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);
+
+ if(!pmlmeinfo->ERP_enable)
+ return;
+
+ //parsing ERP_IE
+ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+ if(p && len>0)
+ {
+ PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;
+
+ if (pmlmepriv->num_sta_non_erp == 1)
+ pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;
+ else
+ pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);
+
+ if(pmlmepriv->num_sta_no_short_preamble > 0)
+ pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
+ else
+ pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
+
+ ERP_IE_handler(padapter, pIE);
+ }
+
+}
+
+static void update_bcn_htcap_ie(_adapter *padapter)
+{
+ DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_htinfo_ie(_adapter *padapter)
+{
+ DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_rsn_ie(_adapter *padapter)
+{
+ DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_wpa_ie(_adapter *padapter)
+{
+ DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_wmm_ie(_adapter *padapter)
+{
+ DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_wps_ie(_adapter *padapter)
+{
+ u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL;
+ uint wps_ielen=0, wps_offset, remainder_ielen;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
+ unsigned char *ie = pnetwork->IEs;
+ u32 ielen = pnetwork->IELength;
+
+
+ DBG_871X("%s\n", __FUNCTION__);
+
+ pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
+
+ if(pwps_ie==NULL || wps_ielen==0)
+ return;
+
+ wps_offset = (uint)(pwps_ie-ie);
+
+ premainder_ie = pwps_ie + wps_ielen;
+
+ remainder_ielen = ielen - wps_offset - wps_ielen;
+
+ if(remainder_ielen>0)
+ {
+ pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+ if(pbackup_remainder_ie)
+ _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+ }
+
+
+ pwps_ie_src = pmlmepriv->wps_beacon_ie;
+ if(pwps_ie_src == NULL)
+ return;
+
+
+ wps_ielen = (uint)pwps_ie_src[1];//to get ie data len
+ if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
+ {
+ _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
+ pwps_ie += (wps_ielen+2);
+
+ if(pbackup_remainder_ie)
+ _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
+
+ //update IELength
+ pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
+ }
+
+ if(pbackup_remainder_ie)
+ rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+
+}
+
+static void update_bcn_p2p_ie(_adapter *padapter)
+{
+
+}
+
+static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui)
+{
+ DBG_871X("%s\n", __FUNCTION__);
+
+ if(_rtw_memcmp(RTW_WPA_OUI, oui, 4))
+ {
+ update_bcn_wpa_ie(padapter);
+ }
+ else if(_rtw_memcmp(WMM_OUI, oui, 4))
+ {
+ update_bcn_wmm_ie(padapter);
+ }
+ else if(_rtw_memcmp(WPS_OUI, oui, 4))
+ {
+ update_bcn_wps_ie(padapter);
+ }
+ else if(_rtw_memcmp(P2P_OUI, oui, 4))
+ {
+ update_bcn_p2p_ie(padapter);
+ }
+ else
+ {
+ DBG_871X("unknown OUI type!\n");
+ }
+
+
+}
+
+void update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
+{
+ _irqL irqL;
+ struct mlme_priv *pmlmepriv;
+ struct mlme_ext_priv *pmlmeext;
+ //struct mlme_ext_info *pmlmeinfo;
+
+ //DBG_871X("%s\n", __FUNCTION__);
+
+ if(!padapter)
+ return;
+
+ pmlmepriv = &(padapter->mlmepriv);
+ pmlmeext = &(padapter->mlmeextpriv);
+ //pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ if(_FALSE == pmlmeext->bstart_bss)
+ return;
+
+ _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
+
+ switch(ie_id)
+ {
+ case 0xFF:
+
+ update_bcn_fixed_ie(padapter);//8: TimeStamp, 2: Beacon Interval 2:Capability
+
+ break;
+
+ case _TIM_IE_:
+
+ update_BCNTIM(padapter);
+
+ break;
+
+ case _ERPINFO_IE_:
+
+ update_bcn_erpinfo_ie(padapter);
+
+ break;
+
+ case _HT_CAPABILITY_IE_:
+
+ update_bcn_htcap_ie(padapter);
+
+ break;
+
+ case _RSN_IE_2_:
+
+ update_bcn_rsn_ie(padapter);
+
+ break;
+
+ case _HT_ADD_INFO_IE_:
+
+ update_bcn_htinfo_ie(padapter);
+
+ break;
+
+ case _VENDOR_SPECIFIC_IE_:
+
+ update_bcn_vendor_spec_ie(padapter, oui);
+
+ break;
+
+ default:
+ break;
+ }
+
+ pmlmepriv->update_bcn = _TRUE;
+
+ _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
+
+#ifndef CONFIG_INTERRUPT_BASED_TXBCN
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+ if(tx)
+ {
+ //send_beacon(padapter);//send_beacon must execute on TSR level
+ set_tx_beacon_cmd(padapter);
+ }
+#else
+ {
+ //PCI will issue beacon when BCN interrupt occurs.
+ }
+#endif
+#endif //!CONFIG_INTERRUPT_BASED_TXBCN
+
+}
+
+#ifdef CONFIG_80211N_HT
+
+/*
+op_mode
+Set to 0 (HT pure) under the followign conditions
+ - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
+ - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
+Set to 1 (HT non-member protection) if there may be non-HT STAs
+ in both the primary and the secondary channel
+Set to 2 if only HT STAs are associated in BSS,
+ however and at least one 20 MHz HT STA is associated
+Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
+ (currently non-GF HT station is considered as non-HT STA also)
+*/
+static int rtw_ht_operation_update(_adapter *padapter)
+{
+ u16 cur_op_mode, new_op_mode;
+ int op_mode_changes = 0;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
+
+ if(pmlmepriv->htpriv.ht_option == _TRUE)
+ return 0;
+
+ //if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
+ // return 0;
+
+ DBG_871X("%s current operation mode=0x%X\n",
+ __FUNCTION__, pmlmepriv->ht_op_mode);
+
+ if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
+ && pmlmepriv->num_sta_ht_no_gf) {
+ pmlmepriv->ht_op_mode |=
+ HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+ op_mode_changes++;
+ } else if ((pmlmepriv->ht_op_mode &
+ HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
+ pmlmepriv->num_sta_ht_no_gf == 0) {
+ pmlmepriv->ht_op_mode &=
+ ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+ op_mode_changes++;
+ }
+
+ if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+ (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
+ pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+ op_mode_changes++;
+ } else if ((pmlmepriv->ht_op_mode &
+ HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+ (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
+ pmlmepriv->ht_op_mode &=
+ ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+ op_mode_changes++;
+ }
+
+ /* Note: currently we switch to the MIXED op mode if HT non-greenfield
+ * station is associated. Probably it's a theoretical case, since
+ * it looks like all known HT STAs support greenfield.
+ */
+ new_op_mode = 0;
+ if (pmlmepriv->num_sta_no_ht ||
+ (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
+ new_op_mode = OP_MODE_MIXED;
+ else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)
+ && pmlmepriv->num_sta_ht_20mhz)
+ new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
+ else if (pmlmepriv->olbc_ht)
+ new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
+ else
+ new_op_mode = OP_MODE_PURE;
+
+ cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+ if (cur_op_mode != new_op_mode) {
+ pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+ pmlmepriv->ht_op_mode |= new_op_mode;
+ op_mode_changes++;
+ }
+
+ DBG_871X("%s new operation mode=0x%X changes=%d\n",
+ __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);
+
+ return op_mode_changes;
+
+}
+
+#endif /* CONFIG_80211N_HT */
+
+void associated_clients_update(_adapter *padapter, u8 updated)
+{
+ //update associcated stations cap.
+ if(updated == _TRUE)
+ {
+ _irqL irqL;
+ _list *phead, *plist;
+ struct sta_info *psta=NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ //check asoc_queue
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+
+ plist = get_next(plist);
+
+ VCS_update(padapter, psta);
+ }
+
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ }
+
+}
+
+/* called > TSR LEVEL for USB or SDIO Interface*/
+void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)
+{
+ u8 beacon_updated = _FALSE;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+
+#if 0
+ if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
+ !psta->no_short_preamble_set) {
+ psta->no_short_preamble_set = 1;
+ pmlmepriv->num_sta_no_short_preamble++;
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_preamble == 1))
+ ieee802_11_set_beacons(hapd->iface);
+ }
+#endif
+
+
+ if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE))
+ {
+ if(!psta->no_short_preamble_set)
+ {
+ psta->no_short_preamble_set = 1;
+
+ pmlmepriv->num_sta_no_short_preamble++;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_preamble == 1))
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, 0xFF, NULL, _TRUE);
+ }
+
+ }
+ }
+ else
+ {
+ if(psta->no_short_preamble_set)
+ {
+ psta->no_short_preamble_set = 0;
+
+ pmlmepriv->num_sta_no_short_preamble--;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_preamble == 0))
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, 0xFF, NULL, _TRUE);
+ }
+
+ }
+ }
+
+#if 0
+ if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {
+ psta->nonerp_set = 1;
+ pmlmepriv->num_sta_non_erp++;
+ if (pmlmepriv->num_sta_non_erp == 1)
+ ieee802_11_set_beacons(hapd->iface);
+ }
+#endif
+
+ if(psta->flags & WLAN_STA_NONERP)
+ {
+ if(!psta->nonerp_set)
+ {
+ psta->nonerp_set = 1;
+
+ pmlmepriv->num_sta_non_erp++;
+
+ if (pmlmepriv->num_sta_non_erp == 1)
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
+ }
+ }
+
+ }
+ else
+ {
+ if(psta->nonerp_set)
+ {
+ psta->nonerp_set = 0;
+
+ pmlmepriv->num_sta_non_erp--;
+
+ if (pmlmepriv->num_sta_non_erp == 0)
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
+ }
+ }
+
+ }
+
+
+#if 0
+ if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&
+ !psta->no_short_slot_time_set) {
+ psta->no_short_slot_time_set = 1;
+ pmlmepriv->num_sta_no_short_slot_time++;
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_slot_time == 1))
+ ieee802_11_set_beacons(hapd->iface);
+ }
+#endif
+
+ if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT))
+ {
+ if(!psta->no_short_slot_time_set)
+ {
+ psta->no_short_slot_time_set = 1;
+
+ pmlmepriv->num_sta_no_short_slot_time++;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_slot_time == 1))
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, 0xFF, NULL, _TRUE);
+ }
+
+ }
+ }
+ else
+ {
+ if(psta->no_short_slot_time_set)
+ {
+ psta->no_short_slot_time_set = 0;
+
+ pmlmepriv->num_sta_no_short_slot_time--;
+
+ if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+ (pmlmepriv->num_sta_no_short_slot_time == 0))
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, 0xFF, NULL, _TRUE);
+ }
+ }
+ }
+
+#ifdef CONFIG_80211N_HT
+
+ if (psta->flags & WLAN_STA_HT)
+ {
+ u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
+
+ DBG_871X("HT: STA " MAC_FMT " HT Capabilities "
+ "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
+
+ if (psta->no_ht_set) {
+ psta->no_ht_set = 0;
+ pmlmepriv->num_sta_no_ht--;
+ }
+
+ if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
+ if (!psta->no_ht_gf_set) {
+ psta->no_ht_gf_set = 1;
+ pmlmepriv->num_sta_ht_no_gf++;
+ }
+ DBG_871X("%s STA " MAC_FMT " - no "
+ "greenfield, num of non-gf stations %d\n",
+ __FUNCTION__, MAC_ARG(psta->hwaddr),
+ pmlmepriv->num_sta_ht_no_gf);
+ }
+
+ if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
+ if (!psta->ht_20mhz_set) {
+ psta->ht_20mhz_set = 1;
+ pmlmepriv->num_sta_ht_20mhz++;
+ }
+ DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, "
+ "num of 20MHz HT STAs %d\n",
+ __FUNCTION__, MAC_ARG(psta->hwaddr),
+ pmlmepriv->num_sta_ht_20mhz);
+ }
+
+ }
+ else
+ {
+ if (!psta->no_ht_set) {
+ psta->no_ht_set = 1;
+ pmlmepriv->num_sta_no_ht++;
+ }
+ if(pmlmepriv->htpriv.ht_option == _TRUE) {
+ DBG_871X("%s STA " MAC_FMT
+ " - no HT, num of non-HT stations %d\n",
+ __FUNCTION__, MAC_ARG(psta->hwaddr),
+ pmlmepriv->num_sta_no_ht);
+ }
+ }
+
+ if (rtw_ht_operation_update(padapter) > 0)
+ {
+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
+ }
+
+#endif /* CONFIG_80211N_HT */
+
+ //update associcated stations cap.
+ associated_clients_update(padapter, beacon_updated);
+
+ DBG_871X("%s, updated=%d\n", __func__, beacon_updated);
+
+}
+
+u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)
+{
+ u8 beacon_updated = _FALSE;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+ if(!psta)
+ return beacon_updated;
+
+ if (psta->no_short_preamble_set) {
+ psta->no_short_preamble_set = 0;
+ pmlmepriv->num_sta_no_short_preamble--;
+ if (pmlmeext->cur_wireless_mode > WIRELESS_11B
+ && pmlmepriv->num_sta_no_short_preamble == 0)
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, 0xFF, NULL, _TRUE);
+ }
+ }
+
+ if (psta->nonerp_set) {
+ psta->nonerp_set = 0;
+ pmlmepriv->num_sta_non_erp--;
+ if (pmlmepriv->num_sta_non_erp == 0)
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
+ }
+ }
+
+ if (psta->no_short_slot_time_set) {
+ psta->no_short_slot_time_set = 0;
+ pmlmepriv->num_sta_no_short_slot_time--;
+ if (pmlmeext->cur_wireless_mode > WIRELESS_11B
+ && pmlmepriv->num_sta_no_short_slot_time == 0)
+ {
+ beacon_updated = _TRUE;
+ update_beacon(padapter, 0xFF, NULL, _TRUE);
+ }
+ }
+
+#ifdef CONFIG_80211N_HT
+
+ if (psta->no_ht_gf_set) {
+ psta->no_ht_gf_set = 0;
+ pmlmepriv->num_sta_ht_no_gf--;
+ }
+
+ if (psta->no_ht_set) {
+ psta->no_ht_set = 0;
+ pmlmepriv->num_sta_no_ht--;
+ }
+
+ if (psta->ht_20mhz_set) {
+ psta->ht_20mhz_set = 0;
+ pmlmepriv->num_sta_ht_20mhz--;
+ }
+
+ if (rtw_ht_operation_update(padapter) > 0)
+ {
+ update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
+ update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
+ }
+
+#endif /* CONFIG_80211N_HT */
+
+ //update associcated stations cap.
+ //associated_clients_update(padapter, beacon_updated); //move it to avoid deadlock
+
+ DBG_871X("%s, updated=%d\n", __func__, beacon_updated);
+
+ return beacon_updated;
+
+}
+
+u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason)
+{
+ _irqL irqL;
+ u8 beacon_updated = _FALSE;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ if(!psta)
+ return beacon_updated;
+
+ if (active == _TRUE)
+ {
+#ifdef CONFIG_80211N_HT
+ //tear down Rx AMPDU
+ send_delba(padapter, 0, psta->hwaddr);// recipient
+
+ //tear down TX AMPDU
+ send_delba(padapter, 1, psta->hwaddr);// // originator
+
+#endif //CONFIG_80211N_HT
+
+ issue_deauth(padapter, psta->hwaddr, reason);
+ }
+
+ psta->htpriv.agg_enable_bitmap = 0x0;//reset
+ psta->htpriv.candidate_tid_bitmap = 0x0;//reset
+
+
+ //report_del_sta_event(padapter, psta->hwaddr, reason);
+
+ //clear cam entry / key
+ //clear_cam_entry(padapter, (psta->mac_id + 3));
+ rtw_clearstakey_cmd(padapter, (u8*)psta, (u8)(psta->mac_id + 3), _TRUE);
+
+
+ _enter_critical_bh(&psta->lock, &irqL);
+ psta->state &= ~_FW_LINKED;
+ _exit_critical_bh(&psta->lock, &irqL);
+
+ #ifdef CONFIG_IOCTL_CFG80211
+ if (1) {
+ #ifdef COMPAT_KERNEL_RELEASE
+ rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
+ #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+ rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
+ #else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+ /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */
+ #endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+ } else
+ #endif //CONFIG_IOCTL_CFG80211
+ {
+ rtw_indicate_sta_disassoc_event(padapter, psta);
+ }
+
+ report_del_sta_event(padapter, psta->hwaddr, reason);
+
+ beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
+
+ _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ rtw_free_stainfo(padapter, psta);
+ _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+
+
+ return beacon_updated;
+
+}
+
+int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)
+{
+ _irqL irqL;
+ _list *phead, *plist;
+ int ret=0;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+ if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+ return ret;
+
+ DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
+ FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ /* for each sta in asoc_queue */
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+ plist = get_next(plist);
+
+ issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
+ psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
+ }
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
+
+ return ret;
+}
+
+int rtw_sta_flush(_adapter *padapter)
+{
+ _irqL irqL;
+ _list *phead, *plist;
+ int ret=0;
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+ u8 chk_alive_num = 0;
+ char chk_alive_list[NUM_STA];
+ int i;
+
+ DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
+
+ if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+ return ret;
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+ int stainfo_offset;
+
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+ plist = get_next(plist);
+
+ /* Remove sta from asoc_list */
+ rtw_list_delete(&psta->asoc_list);
+ pstapriv->asoc_list_cnt--;
+
+ /* Keep sta for ap_free_sta() beyond this asoc_list loop */
+ stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+ if (stainfo_offset_valid(stainfo_offset)) {
+ chk_alive_list[chk_alive_num++] = stainfo_offset;
+ }
+ }
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+
+ /* For each sta in chk_alive_list, call ap_free_sta */
+ for (i = 0; i < chk_alive_num; i++) {
+ psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
+ ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING);
+ }
+
+ issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
+
+ associated_clients_update(padapter, _TRUE);
+
+ return ret;
+
+}
+
+/* called > TSR LEVEL for USB or SDIO Interface*/
+void sta_info_update(_adapter *padapter, struct sta_info *psta)
+{
+ int flags = psta->flags;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+
+ //update wmm cap.
+ if(WLAN_STA_WME&flags)
+ psta->qos_option = 1;
+ else
+ psta->qos_option = 0;
+
+ if(pmlmepriv->qospriv.qos_option == 0)
+ psta->qos_option = 0;
+
+
+#ifdef CONFIG_80211N_HT
+ //update 802.11n ht cap.
+ if(WLAN_STA_HT&flags)
+ {
+ psta->htpriv.ht_option = _TRUE;
+ psta->qos_option = 1;
+ }
+ else
+ {
+ psta->htpriv.ht_option = _FALSE;
+ }
+
+ if(pmlmepriv->htpriv.ht_option == _FALSE)
+ psta->htpriv.ht_option = _FALSE;
+#endif
+
+
+ update_sta_info_apmode(padapter, psta);
+
+
+}
+
+/* called >= TSR LEVEL for USB or SDIO Interface*/
+void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)
+{
+ if(psta->state & _FW_LINKED)
+ {
+ //add ratid
+ add_RATid(padapter, psta, 0);//DM_RATR_STA_INIT
+ }
+}
+/* restore hw setting from sw data structures */
+void rtw_ap_restore_network(_adapter *padapter)
+{
+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct sta_priv * pstapriv = &padapter->stapriv;
+ struct sta_info *psta;
+ struct security_priv* psecuritypriv=&(padapter->securitypriv);
+ _irqL irqL;
+ _list *phead, *plist;
+ u8 chk_alive_num = 0;
+ char chk_alive_list[NUM_STA];
+ int i;
+
+ rtw_setopmode_cmd(padapter, Ndis802_11APMode,_FALSE);
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network);
+
+ if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
+ (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
+ {
+ /* restore group key, WEP keys is restored in ips_leave() */
+ rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0,_FALSE);
+ }
+
+ _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ phead = &pstapriv->asoc_list;
+ plist = get_next(phead);
+
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+ int stainfo_offset;
+
+ psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+ plist = get_next(plist);
+
+ stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+ if (stainfo_offset_valid(stainfo_offset)) {
+ chk_alive_list[chk_alive_num++] = stainfo_offset;
+ }
+ }
+
+ _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+ for (i = 0; i < chk_alive_num; i++) {
+ psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
+
+ if (psta == NULL) {
+ DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
+ }
+ else if(psta->state &_FW_LINKED)
+ {
+ Update_RA_Entry(padapter, psta);
+ //pairwise key
+ /* per sta pairwise key and settings */
+ if( (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
+ (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
+ {
+ rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE,_FALSE);
+ }
+ }
+ }
+
+}
+
+void start_ap_mode(_adapter *padapter)
+{
+ int i;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+
+ pmlmepriv->update_bcn = _FALSE;
+
+ //init_mlme_ap_info(padapter);
+ pmlmeext->bstart_bss = _FALSE;
+
+ pmlmepriv->num_sta_non_erp = 0;
+
+ pmlmepriv->num_sta_no_short_slot_time = 0;
+
+ pmlmepriv->num_sta_no_short_preamble = 0;
+
+ pmlmepriv->num_sta_ht_no_gf = 0;
+#ifdef CONFIG_80211N_HT
+ pmlmepriv->num_sta_no_ht = 0;
+#endif //CONFIG_80211N_HT
+ pmlmepriv->num_sta_ht_20mhz = 0;
+
+ pmlmepriv->olbc = _FALSE;
+
+ pmlmepriv->olbc_ht = _FALSE;
+
+#ifdef CONFIG_80211N_HT
+ pmlmepriv->ht_op_mode = 0;
+#endif
+
+ for(i=0; i<NUM_STA; i++)
+ pstapriv->sta_aid[i] = NULL;
+
+ pmlmepriv->wps_beacon_ie = NULL;
+ pmlmepriv->wps_probe_resp_ie = NULL;
+ pmlmepriv->wps_assoc_resp_ie = NULL;
+
+ pmlmepriv->p2p_beacon_ie = NULL;
+ pmlmepriv->p2p_probe_resp_ie = NULL;
+
+
+ //for ACL
+ _rtw_init_listhead(&(pacl_list->acl_node_q.queue));
+ pacl_list->num = 0;
+ pacl_list->mode = 0;
+ for(i = 0; i < NUM_ACL; i++)
+ {
+ _rtw_init_listhead(&pacl_list->aclnode[i].list);
+ pacl_list->aclnode[i].valid = _FALSE;
+ }
+
+}
+
+void stop_ap_mode(_adapter *padapter)
+{
+ _irqL irqL;
+ _list *phead, *plist;
+ struct rtw_wlan_acl_node *paclnode;
+ struct sta_info *psta=NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+ _queue *pacl_node_q =&pacl_list->acl_node_q;
+
+ pmlmepriv->update_bcn = _FALSE;
+ pmlmeext->bstart_bss = _FALSE;
+ //_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
+
+ //reset and init security priv , this can refine with rtw_reset_securitypriv
+ _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));
+ padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+
+ //for ACL
+ _enter_critical_bh(&(pacl_node_q->lock), &irqL);
+ phead = get_list_head(pacl_node_q);
+ plist = get_next(phead);
+ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+ {
+ paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+ plist = get_next(plist);
+
+ if(paclnode->valid == _TRUE)
+ {
+ paclnode->valid = _FALSE;
+
+ rtw_list_delete(&paclnode->list);
+
+ pacl_list->num--;
+ }
+ }
+ _exit_critical_bh(&(pacl_node_q->lock), &irqL);
+
+ DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);
+
+ rtw_sta_flush(padapter);
+
+ //free_assoc_sta_resources
+ rtw_free_all_stainfo(padapter);
+
+ psta = rtw_get_bcmc_stainfo(padapter);
+ _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ rtw_free_stainfo(padapter, psta);
+ _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+
+ rtw_init_bcmc_stainfo(padapter);
+
+ rtw_free_mlme_priv_ie_data(pmlmepriv);
+
+}
+
+#endif //CONFIG_NATIVEAP_MLME
+#endif //CONFIG_AP_MODE
+
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_bt_mp.c b/drivers/net/wireless/rtl8723as/core/rtw_bt_mp.c index 8b2afecc7b62..e3e0f3d95fec 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_bt_mp.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_bt_mp.c @@ -1,1734 +1,1735 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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, USA - * - * - ******************************************************************************/ - - -#include "rtw_bt_mp.h" -#include <drv_types.h> -#include <rtl8723a_hal.h> - -#ifdef CONFIG_RTL8723A - -void MPh2c_timeout_handle(void *FunctionContext) -{ - _adapter *pAdapter = (_adapter *)FunctionContext; - PMPT_CONTEXT pMptCtx=&pAdapter->mppriv.MptCtx; - - DBG_8192C("[MPT], MPh2c_timeout_handle \n"); - - pMptCtx->bMPh2c_timeout=_TRUE; - - _rtw_up_sema(&pMptCtx->MPh2c_Sema); - - //_cancel_timer_ex( &pMptCtx->MPh2c_timeout_timer); - - return; -} -u32 WaitC2Hevent( PADAPTER pAdapter,BOOLEAN *C2H_event ,u32 delay_time) -{ - PMPT_CONTEXT pMptCtx=&(pAdapter->mppriv.MptCtx); - pMptCtx->bMPh2c_timeout=_FALSE; - - _set_timer( &pMptCtx->MPh2c_timeout_timer, delay_time ); - - _rtw_down_sema(&pMptCtx->MPh2c_Sema); - - if( pMptCtx->bMPh2c_timeout == _TRUE ) - { - C2H_event =_FALSE; - - return _FALSE; - } - - return _TRUE; - -} - -BT_CTRL_STATUS -mptbt_CheckC2hFrame( - PADAPTER Adapter, - PBT_H2C pH2c, - PBT_EXT_C2H pExtC2h - ) -{ - BT_CTRL_STATUS c2hStatus = BT_STATUS_C2H_SUCCESS; - - //DBG_8192C("[MPT], MPT rsp C2H hex: %x %x %x %x %x %x \n"), pExtC2h , pExtC2h+1 ,pExtC2h+2 ,pExtC2h+3 ,pExtC2h+4 ,pExtC2h+5); - - DBG_8192C("[MPT], statusCode = 0x%x\n", pExtC2h->statusCode); - DBG_8192C("[MPT], retLen = %d\n", pExtC2h->retLen); - DBG_8192C("[MPT], opCodeVer : req/rsp=%d/%d\n", pH2c->opCodeVer, pExtC2h->opCodeVer); - DBG_8192C("[MPT], reqNum : req/rsp=%d/%d\n", pH2c->reqNum, pExtC2h->reqNum); - if(pExtC2h->reqNum != pH2c->reqNum) - { - c2hStatus = BT_STATUS_C2H_REQNUM_MISMATCH; - DBG_8192C("[MPT], Error!! C2H reqNum Mismatch!!\n"); - } - else if(pExtC2h->opCodeVer != pH2c->opCodeVer) - { - c2hStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH; - DBG_8192C("[MPT], Error!! OPCode version L mismatch!!\n"); - } - - return c2hStatus; -} - -extern s32 FillH2CCmd(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer); - -BT_CTRL_STATUS -mptbt_SendH2c( - PADAPTER Adapter, - PBT_H2C pH2c, - u2Byte h2cCmdLen - ) -{ - //KIRQL OldIrql = KeGetCurrentIrql(); - BT_CTRL_STATUS h2cStatus=BT_STATUS_H2C_SUCCESS; - PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx); - u1Byte i; - - DBG_8192C("[MPT], mptbt_SendH2c()=========>\n"); - - //PlatformResetEvent(&pMptCtx->MptH2cRspEvent); - //PlatformResetEvent(&pMptCtx->MptBtC2hEvent); - -// if(OldIrql == PASSIVE_LEVEL) -// { - //RTPRINT_DATA(FMPBT, FMPBT_H2C_CONTENT, ("[MPT], MPT H2C hex: \n"), pH2c, h2cCmdLen); - - for(i=0; i<BT_H2C_MAX_RETRY; i++) - { - DBG_8192C("[MPT], Send H2C command to wifi!!!\n"); - FillH2CCmd(Adapter, 70, h2cCmdLen, (pu1Byte)pH2c); - pMptCtx->h2cReqNum++; - pMptCtx->h2cReqNum %= 16; - - if(WaitC2Hevent(Adapter, &pMptCtx->MptH2cRspEvent, 100)) - { - DBG_8192C("[MPT], Received WiFi MptH2cRspEvent!!!\n"); - if(WaitC2Hevent(Adapter, &pMptCtx->MptBtC2hEvent, 400)) - { - DBG_8192C("[MPT], Received MptBtC2hEvent!!!\n"); - break; - } - else - { - DBG_8192C("[MPT], Error!!BT MptBtC2hEvent timeout!!\n"); - h2cStatus = BT_STATUS_H2C_BT_NO_RSP; - } - } - else - { - DBG_8192C("[MPT], Error!!WiFi MptH2cRspEvent timeout!!\n"); - h2cStatus = BT_STATUS_H2C_TIMTOUT; - } - } -// } -// else -// { -// RT_ASSERT(FALSE, ("[MPT], mptbt_SendH2c() can only run under PASSIVE_LEVEL!!\n")); -// h2cStatus = BT_STATUS_WRONG_LEVEL; -// } - - DBG_8192C("[MPT], mptbt_SendH2c()<=========\n"); - return h2cStatus; -} - - - -BT_CTRL_STATUS -mptbt_CheckBtRspStatus( - PADAPTER Adapter, - PBT_EXT_C2H pExtC2h - ) -{ - BT_CTRL_STATUS retStatus=BT_OP_STATUS_SUCCESS; - - switch(pExtC2h->statusCode) - { - case BT_OP_STATUS_SUCCESS: - retStatus = BT_STATUS_BT_OP_SUCCESS; - DBG_8192C("[MPT], BT status : BT_STATUS_SUCCESS\n"); - break; - case BT_OP_STATUS_VERSION_MISMATCH: - retStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH; - DBG_8192C("[MPT], BT status : BT_STATUS_OPCODE_L_VERSION_MISMATCH\n"); - break; - case BT_OP_STATUS_UNKNOWN_OPCODE: - retStatus = BT_STATUS_UNKNOWN_OPCODE_L; - DBG_8192C("[MPT], BT status : BT_STATUS_UNKNOWN_OPCODE_L\n"); - break; - case BT_OP_STATUS_ERROR_PARAMETER: - retStatus = BT_STATUS_PARAMETER_FORMAT_ERROR_L; - DBG_8192C("[MPT], BT status : BT_STATUS_PARAMETER_FORMAT_ERROR_L\n"); - break; - default: - retStatus = BT_STATUS_UNKNOWN_STATUS_L; - DBG_8192C("[MPT], BT status : BT_STATUS_UNKNOWN_STATUS_L\n"); - break; - } - - return retStatus; -} - - - -BT_CTRL_STATUS -mptbt_BtFwOpCodeProcess( - PADAPTER Adapter, - u1Byte btFwOpCode, - u1Byte opCodeVer, - pu1Byte pH2cPar, - u1Byte h2cParaLen - ) -{ - u1Byte H2C_Parameter[6] ={0}; - PBT_H2C pH2c=(PBT_H2C)&H2C_Parameter[0]; - PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx); - PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0]; - u2Byte paraLen=0,i; - BT_CTRL_STATUS h2cStatus=BT_STATUS_H2C_SUCCESS, c2hStatus=BT_STATUS_C2H_SUCCESS; - BT_CTRL_STATUS retStatus=BT_STATUS_H2C_BT_NO_RSP; - - pH2c->opCode = btFwOpCode; - pH2c->opCodeVer = opCodeVer; - pH2c->reqNum = pMptCtx->h2cReqNum; - //PlatformMoveMemory(&pH2c->buf[0], pH2cPar, h2cParaLen); - //_rtw_memcpy(&pH2c->buf[0], pH2cPar, h2cParaLen); - _rtw_memcpy(pH2c->buf, pH2cPar, h2cParaLen); - - DBG_8192C("[MPT], pH2c->opCode=%d\n", pH2c->opCode); - DBG_8192C("[MPT], pH2c->opCodeVer=%d\n", pH2c->opCodeVer); - DBG_8192C("[MPT], pH2c->reqNum=%d\n", pH2c->reqNum); - DBG_8192C("[MPT], h2c parameter length=%d\n", h2cParaLen); - if(h2cParaLen) - { - DBG_8192C("[MPT], parameters(hex): \n"); - for(i=0;i<h2cParaLen;i++) - { - DBG_8192C(" 0x%x \n", pH2c->buf[i]); - } - } - - h2cStatus = mptbt_SendH2c(Adapter, pH2c, h2cParaLen+2); - if(BT_STATUS_H2C_SUCCESS == h2cStatus) - { - // if reach here, it means H2C get the correct c2h response, - c2hStatus = mptbt_CheckC2hFrame(Adapter, pH2c, pExtC2h); - if(BT_STATUS_C2H_SUCCESS == c2hStatus) - { - retStatus = mptbt_CheckBtRspStatus(Adapter, pExtC2h); - } - else - { - DBG_8192C("[MPT], Error!! C2H failed for pH2c->opCode=%d\n", pH2c->opCode); - // check c2h status error, return error status code to upper layer. - retStatus = c2hStatus; - } - } - else - { - DBG_8192C("[MPT], Error!! H2C failed for pH2c->opCode=%d\n", pH2c->opCode); - // check h2c status error, return error status code to upper layer. - retStatus = h2cStatus; - } - - return retStatus; -} - - - - -u2Byte -mptbt_BtReady( - PADAPTER Adapter, - PBT_REQ_CMD pBtReq, - PBT_RSP_CMD pBtRsp - ) -{ - u1Byte h2cParaBuf[6] ={0}; - u1Byte h2cParaLen=0; - u2Byte paraLen=0; - u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS; - u1Byte btOpcode; - u1Byte btOpcodeVer=0; - PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx); - PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0]; - u1Byte i; - u1Byte btFwVer=0, bdAddr[6]={0}; - u2Byte btRealFwVer=0; - pu2Byte pu2Tmp=NULL; - - // - // check upper layer parameters - // - - // 1. check upper layer opcode version - if(pBtReq->opCodeVer != 1) - { - DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n"); - pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH; - return paraLen; - } - - pBtRsp->pParamStart[0] = MP_BT_NOT_READY; - paraLen = 10; - // - // execute lower layer opcodes - // - - // Get BT FW version - // fill h2c parameters - btOpcode = BT_LO_OP_GET_BT_VERSION; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - else - { - pu2Tmp = (pu2Byte)&pExtC2h->buf[0]; - btRealFwVer = *pu2Tmp; - btFwVer = pExtC2h->buf[1]; - DBG_8192C("[MPT], btRealFwVer=0x%x, btFwVer=0x%x\n", btRealFwVer, btFwVer); - } - - // Get BD Address - // fill h2c parameters - btOpcode = BT_LO_OP_GET_BD_ADDR_L; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - else - { - bdAddr[5] = pExtC2h->buf[0]; - bdAddr[4] = pExtC2h->buf[1]; - bdAddr[3] = pExtC2h->buf[2]; - } - - // fill h2c parameters - btOpcode = BT_LO_OP_GET_BD_ADDR_H; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - else - { - bdAddr[2] = pExtC2h->buf[0]; - bdAddr[1] = pExtC2h->buf[1]; - bdAddr[0] = pExtC2h->buf[2]; - } - DBG_8192C("[MPT], Local BDAddr:"); - for(i=0; i<6; i++) - { - DBG_8192C(" 0x%x ", bdAddr[i]); - } - pBtRsp->status = BT_STATUS_SUCCESS; - pBtRsp->pParamStart[0] = MP_BT_READY; - pu2Tmp = (pu2Byte)&pBtRsp->pParamStart[1]; - *pu2Tmp = btRealFwVer; - pBtRsp->pParamStart[3] = btFwVer; - for(i=0; i<6; i++) - { - pBtRsp->pParamStart[4+i] = bdAddr[5-i]; - } - - return paraLen; -} - -void mptbt_close_WiFiRF(PADAPTER Adapter) -{ - PHY_SetBBReg(Adapter, 0x824, 0xF, 0x0); - PHY_SetBBReg(Adapter, 0x824, 0x700000, 0x0); - PHY_SetRFReg(Adapter, RF90_PATH_A, 0x0, 0xF0000, 0x0); -} - -void mptbt_open_WiFiRF(PADAPTER Adapter) -{ - PHY_SetBBReg(Adapter, 0x824, 0x700000, 0x3); - PHY_SetBBReg(Adapter, 0x824, 0xF, 0x2); - PHY_SetRFReg(Adapter, RF90_PATH_A, 0x0, 0xF0000, 0x3); -} - -u4Byte mptbt_switch_RF(PADAPTER Adapter, u1Byte Enter) -{ - u2Byte tmp_2byte = 0; - - //Enter test mode - if (Enter) { - ////1>. close WiFi RF - mptbt_close_WiFiRF(Adapter); - - ////2>. change ant switch to BT - tmp_2byte = rtw_read16(Adapter, 0x860); - tmp_2byte = tmp_2byte | BIT(9); - tmp_2byte = tmp_2byte & (~BIT(8)); - rtw_write16(Adapter, 0x860, tmp_2byte); - rtw_write16(Adapter, 0x870, 0x300); - } else { - ////1>. Open WiFi RF - mptbt_open_WiFiRF(Adapter); - - ////2>. change ant switch back - tmp_2byte = rtw_read16(Adapter, 0x860); - tmp_2byte = tmp_2byte | BIT(8); - tmp_2byte = tmp_2byte & (~BIT(9)); - rtw_write16(Adapter, 0x860, tmp_2byte); - rtw_write16(Adapter, 0x870, 0x300); - } - - return 0; -} - -u2Byte -mptbt_BtSetMode( - PADAPTER Adapter, - PBT_REQ_CMD pBtReq, - PBT_RSP_CMD pBtRsp - ) -{ - u1Byte h2cParaBuf[6] ={0}; - u1Byte h2cParaLen=0; - u2Byte paraLen=0; - u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS; - u1Byte btOpcode; - u1Byte btOpcodeVer=0; - u1Byte btModeToSet=0; - - // - // check upper layer parameters - // - // 1. check upper layer opcode version - if(pBtReq->opCodeVer != 1) - { - DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n"); - pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH; - return paraLen; - } - // 2. check upper layer parameter length - if(1 == pBtReq->paraLength) - { - btModeToSet = pBtReq->pParamStart[0]; - DBG_8192C("[MPT], BtTestMode=%d \n", btModeToSet); - } - else - { - DBG_8192C("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength); - pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U; - return paraLen; - } - - // - // execute lower layer opcodes - // - - // 1. fill h2c parameters - // check bt mode - btOpcode = BT_LO_OP_SET_BT_MODE; - if(btModeToSet >= MP_BT_MODE_MAX) - { - pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - mptbt_switch_RF(Adapter, 1); - - h2cParaBuf[0] = btModeToSet; - h2cParaLen = 1; - // 2. execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // 3. construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS == retStatus) - { - pBtRsp->status = BT_STATUS_SUCCESS; - } - else - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - } - - return paraLen; -} - - -VOID -MPTBT_FwC2hBtMpCtrl( - PADAPTER Adapter, - pu1Byte tmpBuf, - u1Byte length - ) -{ - u32 i; - PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx); - PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)tmpBuf; - - if(Adapter->bBTFWReady == _FALSE || Adapter->registrypriv.mp_mode == 0 ) - { - DBG_8192C("[MPT], %s,bBTFWReady == _FALSE\n",__func__); - return; - } - //cancel_timeout for h2c handle - _cancel_timer_ex( &pMptCtx->MPh2c_timeout_timer); - - DBG_8192C("[MPT], MPTBT_FwC2hBtMpCtrl(), hex: \n"); - for(i=0;i<=length;i++) - { - //DBG_8192C("[MPT], MPTBT_FwC2hBtMpCtrl(), hex: \n",tmpBuf[i], length); - DBG_8192C(" 0x%x ",tmpBuf[i]); - } - DBG_8192C("\n [MPT], pExtC2h->extendId=0x%x\n", pExtC2h->extendId); - - switch(pExtC2h->extendId) - { - case EXT_C2H_WIFI_FW_ACTIVE_RSP: - DBG_8192C("[MPT], EXT_C2H_WIFI_FW_ACTIVE_RSP\n"); - DBG_8192C("[MPT], pExtC2h->buf hex: \n"); - if( length > 32 || length < 3 ) - break ; - for(i=0;i<=(length-3);i++) - DBG_8192C(" 0x%x ",pExtC2h->buf[i]); - //PlatformSetEvent(&pMptCtx->MptH2cRspEvent); - pMptCtx->MptH2cRspEvent=_TRUE; - _rtw_up_sema(&pMptCtx->MPh2c_Sema); - break; - case EXT_C2H_TRIG_BY_BT_FW: - DBG_8192C("[MPT], EXT_C2H_TRIG_BY_BT_FW\n"); - //PlatformMoveMemory(&pMptCtx->c2hBuf[0], tmpBuf, length); - _rtw_memcpy(&pMptCtx->c2hBuf[0], tmpBuf, length); - DBG_8192C("[MPT], pExtC2h->statusCode=0x%x\n", pExtC2h->statusCode); - DBG_8192C("[MPT], pExtC2h->retLen=0x%x\n", pExtC2h->retLen); - DBG_8192C("[MPT], pExtC2h->opCodeVer=0x%x\n", pExtC2h->opCodeVer); - DBG_8192C("[MPT], pExtC2h->reqNum=0x%x\n", pExtC2h->reqNum); - DBG_8192C("[MPT], pExtC2h->buf hex: \n"); - for(i=0;i<=(length-3);i++) - DBG_8192C(" 0x%x ",pExtC2h->buf[0]); - //PlatformSetEvent(&pMptCtx->MptBtC2hEvent); - pMptCtx->MptBtC2hEvent=_TRUE; - _rtw_up_sema(&pMptCtx->MPh2c_Sema); - break; - default: - break; - } - - - -} - - -u2Byte -mptbt_BtGetGeneral( - IN PADAPTER Adapter, - IN PBT_REQ_CMD pBtReq, - IN PBT_RSP_CMD pBtRsp - ) -{ - PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx); - PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0]; - u1Byte h2cParaBuf[6] ={0}; - u1Byte h2cParaLen=0; - u2Byte paraLen=0; - u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS; - u1Byte btOpcode, bdAddr[6]={0}; - u1Byte btOpcodeVer=0; - u1Byte getType=0, i; - u2Byte getParaLen=0, validParaLen=0; - u1Byte regType=0, reportType=0; - u4Byte regAddr=0, regValue=0; - pu4Byte pu4Tmp; - pu2Byte pu2Tmp; - pu1Byte pu1Tmp; - - // - // check upper layer parameters - // - - // check upper layer opcode version - if(pBtReq->opCodeVer != 1) - { - DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n"); - pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH; - return paraLen; - } - // check upper layer parameter length - if(pBtReq->paraLength < 1) - { - DBG_8192C("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength); - pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U; - return paraLen; - } - getParaLen = pBtReq->paraLength - 1; - getType = pBtReq->pParamStart[0]; - - DBG_8192C("[MPT], getType=%d, getParaLen=%d\n", getType, getParaLen); - - // check parameter first - switch(getType) - { - case BT_GGET_REG: - DBG_8192C("[MPT], [BT_GGET_REG]\n"); - validParaLen = 5; - if(getParaLen == validParaLen) - { - btOpcode = BT_LO_OP_READ_REG; - regType = pBtReq->pParamStart[1]; - pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2]; - regAddr = *pu4Tmp; - DBG_8192C("[MPT], BT_GGET_REG regType=0x%x, regAddr=0x%x!!\n", - regType, regAddr); - if(regType >= BT_REG_MAX) - { - pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - if( ((BT_REG_RF==regType)&&(regAddr>0x7f)) || - ((BT_REG_MODEM==regType)&&(regAddr>0x1ff)) || - ((BT_REG_BLUEWIZE==regType)&&(regAddr>0xfff)) || - ((BT_REG_VENDOR==regType)&&(regAddr>0xfff)) || - ((BT_REG_LE==regType)&&(regAddr>0xfff)) ) - { - pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - } - } - break; - case BT_GGET_STATUS: - DBG_8192C("[MPT], [BT_GGET_STATUS]\n"); - validParaLen = 0; - break; - case BT_GGET_REPORT: - DBG_8192C("[MPT], [BT_GGET_REPORT]\n"); - validParaLen = 1; - if(getParaLen == validParaLen) - { - reportType = pBtReq->pParamStart[1]; - DBG_8192C("[MPT], BT_GGET_REPORT reportType=0x%x!!\n", reportType); - if(reportType >= BT_REPORT_MAX) - { - pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - } - break; - default: - { - DBG_8192C("[MPT], Error!! getType=%d, out of range\n", getType); - pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - break; - } - if(getParaLen != validParaLen) - { - DBG_8192C("[MPT], Error!! wrong parameter length=%d for BT_GET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n", - getParaLen, getType, validParaLen); - pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U; - return paraLen; - } - - // - // execute lower layer opcodes - // - if(BT_GGET_REG == getType) - { - // fill h2c parameters - // here we should write reg value first then write the address, adviced by Austin - btOpcode = BT_LO_OP_READ_REG; - h2cParaBuf[0] = regType; - h2cParaBuf[1] = pBtReq->pParamStart[2]; - h2cParaBuf[2] = pBtReq->pParamStart[3]; - h2cParaLen = 3; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - pu2Tmp = (pu2Byte)&pExtC2h->buf[0]; - regValue = *pu2Tmp; - DBG_8192C("[MPT], read reg regType=0x%x, regAddr=0x%x, regValue=0x%x\n", - regType, regAddr, regValue); - - pu4Tmp = (pu4Byte)&pBtRsp->pParamStart[0]; - *pu4Tmp = regValue; - paraLen = 4; - } - else if(BT_GGET_STATUS == getType) - { - btOpcode = BT_LO_OP_GET_BT_STATUS; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - pBtRsp->pParamStart[0] = pExtC2h->buf[0]; - pBtRsp->pParamStart[1] = pExtC2h->buf[1]; - DBG_8192C("[MPT], read bt status, testMode=0x%x, testStatus=0x%x\n", - pBtRsp->pParamStart[0], pBtRsp->pParamStart[1]); - paraLen = 2; - } - else if(BT_GGET_REPORT == getType) - { - switch(reportType) - { - case BT_REPORT_RX_PACKET_CNT: - { - DBG_8192C("[MPT], [Rx Packet Counts]\n"); - btOpcode = BT_LO_OP_GET_RX_PKT_CNT_L; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - pBtRsp->pParamStart[0] = pExtC2h->buf[0]; - pBtRsp->pParamStart[1] = pExtC2h->buf[1]; - - btOpcode = BT_LO_OP_GET_RX_PKT_CNT_H; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - pBtRsp->pParamStart[2] = pExtC2h->buf[0]; - pBtRsp->pParamStart[3] = pExtC2h->buf[1]; - paraLen = 4; - } - break; - case BT_REPORT_RX_ERROR_BITS: - { - DBG_8192C("[MPT], [Rx Error Bits]\n"); - btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_L; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - pBtRsp->pParamStart[0] = pExtC2h->buf[0]; - pBtRsp->pParamStart[1] = pExtC2h->buf[1]; - - btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_H; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - pBtRsp->pParamStart[2] = pExtC2h->buf[0]; - pBtRsp->pParamStart[3] = pExtC2h->buf[1]; - paraLen = 4; - } - break; - case BT_REPORT_RSSI: - { - DBG_8192C("[MPT], [RSSI]\n"); - btOpcode = BT_LO_OP_GET_RSSI; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - pBtRsp->pParamStart[0] = pExtC2h->buf[0]; - pBtRsp->pParamStart[1] = pExtC2h->buf[1]; - paraLen = 2; - } - break; - case BT_REPORT_CFO_HDR_QUALITY: - { - DBG_8192C("[MPT], [CFO & Header Quality]\n"); - btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_L; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - pBtRsp->pParamStart[0] = pExtC2h->buf[0]; - pBtRsp->pParamStart[1] = pExtC2h->buf[1]; - - btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_H; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - pBtRsp->pParamStart[2] = pExtC2h->buf[0]; - pBtRsp->pParamStart[3] = pExtC2h->buf[1]; - paraLen = 4; - } - break; - case BT_REPORT_CONNECT_TARGET_BD_ADDR: - { - DBG_8192C("[MPT], [Connected Target BD ADDR]\n"); - btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_L; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - bdAddr[5] = pExtC2h->buf[0]; - bdAddr[4] = pExtC2h->buf[1]; - bdAddr[3] = pExtC2h->buf[2]; - - btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_H; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - bdAddr[2] = pExtC2h->buf[0]; - bdAddr[1] = pExtC2h->buf[1]; - bdAddr[0] = pExtC2h->buf[2]; - - DBG_8192C("[MPT], Connected Target BDAddr:%s", bdAddr); - for(i=0; i<6; i++) - { - pBtRsp->pParamStart[i] = bdAddr[5-i]; - } - paraLen = 6; - } - break; - default: - pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - break; - } - } - - pBtRsp->status = BT_STATUS_SUCCESS; - return paraLen; -} - - - -u2Byte -mptbt_BtSetGeneral( - IN PADAPTER Adapter, - IN PBT_REQ_CMD pBtReq, - IN PBT_RSP_CMD pBtRsp - ) -{ - u1Byte h2cParaBuf[6] ={0}; - u1Byte h2cParaLen=0; - u2Byte paraLen=0; - u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS; - u1Byte btOpcode; - u1Byte btOpcodeVer=0; - u1Byte setType=0; - u2Byte setParaLen=0, validParaLen=0; - u1Byte regType=0, bdAddr[6]={0}, calVal=0; - u4Byte regAddr=0, regValue=0; - pu4Byte pu4Tmp; - pu2Byte pu2Tmp; - pu1Byte pu1Tmp; - - // - // check upper layer parameters - // - - // check upper layer opcode version - if(pBtReq->opCodeVer != 1) - { - DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n"); - pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH; - return paraLen; - } - // check upper layer parameter length - if(pBtReq->paraLength < 1) - { - DBG_8192C("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength); - pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U; - return paraLen; - } - setParaLen = pBtReq->paraLength - 1; - setType = pBtReq->pParamStart[0]; - - DBG_8192C("[MPT], setType=%d, setParaLen=%d\n", setType, setParaLen); - - // check parameter first - switch(setType) - { - case BT_GSET_REG: - DBG_8192C ("[MPT], [BT_GSET_REG]\n"); - validParaLen = 9; - if(setParaLen == validParaLen) - { - btOpcode = BT_LO_OP_WRITE_REG_VALUE; - regType = pBtReq->pParamStart[1]; - pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2]; - regAddr = *pu4Tmp; - pu4Tmp = (pu4Byte)&pBtReq->pParamStart[6]; - regValue = *pu4Tmp; - DBG_8192C("[MPT], BT_GSET_REG regType=0x%x, regAddr=0x%x, regValue=0x%x!!\n", - regType, regAddr, regValue); - if(regType >= BT_REG_MAX) - { - pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - if( ((BT_REG_RF==regType)&&(regAddr>0x7f)) || - ((BT_REG_MODEM==regType)&&(regAddr>0x1ff)) || - ((BT_REG_BLUEWIZE==regType)&&(regAddr>0xfff)) || - ((BT_REG_VENDOR==regType)&&(regAddr>0xfff)) || - ((BT_REG_LE==regType)&&(regAddr>0xfff)) ) - { - pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - } - } - break; - case BT_GSET_RESET: - DBG_8192C("[MPT], [BT_GSET_RESET]\n"); - validParaLen = 0; - break; - case BT_GSET_TARGET_BD_ADDR: - DBG_8192C("[MPT], [BT_GSET_TARGET_BD_ADDR]\n"); - validParaLen = 6; - if(setParaLen == validParaLen) - { - btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H; - if( (pBtReq->pParamStart[1]==0) && - (pBtReq->pParamStart[2]==0) && - (pBtReq->pParamStart[3]==0) && - (pBtReq->pParamStart[4]==0) && - (pBtReq->pParamStart[5]==0) && - (pBtReq->pParamStart[6]==0) ) - { - DBG_8192C("[MPT], Error!! targetBDAddr=all zero\n"); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - if( (pBtReq->pParamStart[1]==0xff) && - (pBtReq->pParamStart[2]==0xff) && - (pBtReq->pParamStart[3]==0xff) && - (pBtReq->pParamStart[4]==0xff) && - (pBtReq->pParamStart[5]==0xff) && - (pBtReq->pParamStart[6]==0xff) ) - { - DBG_8192C("[MPT], Error!! targetBDAddr=all 0xf\n"); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - bdAddr[0] = pBtReq->pParamStart[6]; - bdAddr[1] = pBtReq->pParamStart[5]; - bdAddr[2] = pBtReq->pParamStart[4]; - bdAddr[3] = pBtReq->pParamStart[3]; - bdAddr[4] = pBtReq->pParamStart[2]; - bdAddr[5] = pBtReq->pParamStart[1]; - DBG_8192C ("[MPT], target BDAddr:%x,%x,%x,%x,%x,%x\n", - bdAddr[0],bdAddr[1],bdAddr[2],bdAddr[3],bdAddr[4],bdAddr[5]); - } - break; - case BT_GSET_TX_PWR_FINETUNE: - DBG_8192C("[MPT], [BT_GSET_TX_PWR_FINETUNE]\n"); - validParaLen = 1; - if(setParaLen == validParaLen) - { - btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION; - calVal = pBtReq->pParamStart[1]; - if( (calVal<1) || (calVal>9) ) - { - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - DBG_8192C ("[MPT], calVal=%d\n", calVal); - } - break; - case BT_SET_TRACKING_INTERVAL: - DBG_871X("[MPT], [BT_SET_TRACKING_INTERVAL] setParaLen =%d \n",setParaLen); - - validParaLen = 1; - if(setParaLen == validParaLen) - calVal = pBtReq->pParamStart[1]; - break; - case BT_SET_THERMAL_METER: - DBG_871X("[MPT], [BT_SET_THERMAL_METER] setParaLen =%d \n",setParaLen); - validParaLen = 1; - if(setParaLen == validParaLen) - calVal = pBtReq->pParamStart[1]; - break; - case BT_ENABLE_CFO_TRACKING: - DBG_871X("[MPT], [BT_ENABLE_CFO_TRACKING] setParaLen =%d \n",setParaLen); - validParaLen = 1; - if(setParaLen == validParaLen) - calVal = pBtReq->pParamStart[1]; - break; - case BT_GSET_UPDATE_BT_PATCH: - if(IS_HARDWARE_TYPE_8723AE(Adapter) && Adapter->bFWReady) - { - u1Byte i; - DBG_8192C ("[MPT], write regs for load patch\n"); - //BTFwPatch8723A(Adapter); - PlatformEFIOWrite1Byte(Adapter, 0xCC, 0x2d); - rtw_msleep_os(50); - PlatformEFIOWrite4Byte(Adapter, 0x68, 0xa005000c); - rtw_msleep_os(50); - PlatformEFIOWrite4Byte(Adapter, 0x68, 0xb005000c); - rtw_msleep_os(50); - PlatformEFIOWrite1Byte(Adapter, 0xCC, 0x29); - for(i=0; i<12; i++) - rtw_msleep_os(100); -//#if (DEV_BUS_TYPE == RT_PCI_INTERFACE) -// BTFwPatch8723A(Adapter); -//#endif - DBG_8192C("[MPT], load BT FW Patch finished!!!\n"); - } - break; - default: - { - DBG_8192C ("[MPT], Error!! setType=%d, out of range\n", setType); - pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - break; - } - if(setParaLen != validParaLen) - { - DBG_8192C("[MPT], Error!! wrong parameter length=%d for BT_SET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n", - setParaLen, setType, validParaLen); - pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U; - return paraLen; - } - - // - // execute lower layer opcodes - // - if(BT_GSET_REG == setType) - { - // fill h2c parameters - // here we should write reg value first then write the address, adviced by Austin - btOpcode = BT_LO_OP_WRITE_REG_VALUE; - h2cParaBuf[0] = pBtReq->pParamStart[6]; - h2cParaBuf[1] = pBtReq->pParamStart[7]; - h2cParaBuf[2] = pBtReq->pParamStart[8]; - h2cParaLen = 3; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - // write reg address - btOpcode = BT_LO_OP_WRITE_REG_ADDR; - h2cParaBuf[0] = regType; - h2cParaBuf[1] = pBtReq->pParamStart[2]; - h2cParaBuf[2] = pBtReq->pParamStart[3]; - h2cParaLen = 3; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - } - else if(BT_GSET_RESET == setType) - { - btOpcode = BT_LO_OP_RESET; - h2cParaLen = 0; - // execute h2c and check respond c2h from bt fw is correct or not - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - } - else if(BT_GSET_TARGET_BD_ADDR == setType) - { - // fill h2c parameters - btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_L; - h2cParaBuf[0] = pBtReq->pParamStart[1]; - h2cParaBuf[1] = pBtReq->pParamStart[2]; - h2cParaBuf[2] = pBtReq->pParamStart[3]; - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H; - h2cParaBuf[0] = pBtReq->pParamStart[4]; - h2cParaBuf[1] = pBtReq->pParamStart[5]; - h2cParaBuf[2] = pBtReq->pParamStart[6]; - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - } - else if(BT_GSET_TX_PWR_FINETUNE == setType) - { - // fill h2c parameters - btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION; - h2cParaBuf[0] = calVal; - h2cParaLen = 1; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - } - else if(BT_SET_TRACKING_INTERVAL == setType) - { - // BT_LO_OP_SET_TRACKING_INTERVAL = 0x22, - // BT_LO_OP_SET_THERMAL_METER = 0x23, - // BT_LO_OP_ENABLE_CFO_TRACKING = 0x24, - btOpcode = BT_LO_OP_SET_TRACKING_INTERVAL; - h2cParaBuf[0] = calVal; - h2cParaLen = 1; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - } - else if(BT_SET_THERMAL_METER == setType) - { - btOpcode = BT_LO_OP_SET_THERMAL_METER; - h2cParaBuf[0] = calVal; - h2cParaLen = 1; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - } - else if(BT_ENABLE_CFO_TRACKING == setType) - { - btOpcode = BT_LO_OP_ENABLE_CFO_TRACKING; - h2cParaBuf[0] = calVal; - h2cParaLen = 1; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - } - - pBtRsp->status = BT_STATUS_SUCCESS; - return paraLen; -} - - - -u2Byte -mptbt_BtSetTxRxPars( - IN PADAPTER Adapter, - IN PBT_REQ_CMD pBtReq, - IN PBT_RSP_CMD pBtRsp - ) -{ - u1Byte h2cParaBuf[6] ={0}; - u1Byte h2cParaLen=0; - u2Byte paraLen=0; - u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS; - u1Byte btOpcode; - u1Byte btOpcodeVer=0; - PBT_TXRX_PARAMETERS pTxRxPars=(PBT_TXRX_PARAMETERS)&pBtReq->pParamStart[0]; - u2Byte lenTxRx=sizeof(BT_TXRX_PARAMETERS); - u1Byte i; - u1Byte bdAddr[6]={0}; - - // - // check upper layer parameters - // - - // 1. check upper layer opcode version - if(pBtReq->opCodeVer != 1) - { - DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n"); - pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH; - return paraLen; - } - // 2. check upper layer parameter length - if(pBtReq->paraLength == sizeof(BT_TXRX_PARAMETERS)) - { - DBG_8192C ("[MPT], pTxRxPars->txrxChannel=0x%x \n", pTxRxPars->txrxChannel); - DBG_8192C ("[MPT], pTxRxPars->txrxTxPktCnt=0x%8x \n", pTxRxPars->txrxTxPktCnt); - DBG_8192C ("[MPT], pTxRxPars->txrxTxPktInterval=0x%x \n", pTxRxPars->txrxTxPktInterval); - DBG_8192C ("[MPT], pTxRxPars->txrxPayloadType=0x%x \n", pTxRxPars->txrxPayloadType); - DBG_8192C ("[MPT], pTxRxPars->txrxPktType=0x%x \n", pTxRxPars->txrxPktType); - DBG_8192C ("[MPT], pTxRxPars->txrxPayloadLen=0x%x \n", pTxRxPars->txrxPayloadLen); - DBG_8192C ("[MPT], pTxRxPars->txrxPktHeader=0x%x \n", pTxRxPars->txrxPktHeader); - DBG_8192C ("[MPT], pTxRxPars->txrxWhitenCoeff=0x%x \n", pTxRxPars->txrxWhitenCoeff); - bdAddr[0] = pTxRxPars->txrxBdaddr[5]; - bdAddr[1] = pTxRxPars->txrxBdaddr[4]; - bdAddr[2] = pTxRxPars->txrxBdaddr[3]; - bdAddr[3] = pTxRxPars->txrxBdaddr[2]; - bdAddr[4] = pTxRxPars->txrxBdaddr[1]; - bdAddr[5] = pTxRxPars->txrxBdaddr[0]; - DBG_8192C ("[MPT], pTxRxPars->txrxBdaddr: %s", &bdAddr[0]); - DBG_8192C ("[MPT], pTxRxPars->txrxTxGainIndex=0x%x \n", pTxRxPars->txrxTxGainIndex); - } - else - { - DBG_8192C ("[MPT], Error!! pBtReq->paraLength=%d, correct Len=%d\n", pBtReq->paraLength, lenTxRx); - pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U; - return paraLen; - } - - // - // execute lower layer opcodes - // - - // fill h2c parameters - btOpcode = BT_LO_OP_SET_PKT_HEADER; - if(pTxRxPars->txrxPktHeader > 0x3ffff) - { - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxPktHeader=0x%x is out of range, (should be between 0x0~0x3ffff)\n", pTxRxPars->txrxPktHeader); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - h2cParaBuf[0] = (u1Byte)(pTxRxPars->txrxPktHeader&0xff); - h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPktHeader&0xff00)>>8); - h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPktHeader&0xff0000)>>16); - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - // fill h2c parameters - btOpcode = BT_LO_OP_SET_PKT_TYPE_LEN; - { - u2Byte payloadLenLimit=0; - switch(pTxRxPars->txrxPktType) - { - case MP_BT_PKT_DH1: - payloadLenLimit = 27*8; - break; - case MP_BT_PKT_DH3: - payloadLenLimit = 183*8; - break; - case MP_BT_PKT_DH5: - payloadLenLimit = 339*8; - break; - case MP_BT_PKT_2DH1: - payloadLenLimit = 54*8; - break; - case MP_BT_PKT_2DH3: - payloadLenLimit = 367*8; - break; - case MP_BT_PKT_2DH5: - payloadLenLimit = 679*8; - break; - case MP_BT_PKT_3DH1: - payloadLenLimit = 83*8; - break; - case MP_BT_PKT_3DH3: - payloadLenLimit = 552*8; - break; - case MP_BT_PKT_3DH5: - payloadLenLimit = 1021*8; - break; - case MP_BT_PKT_LE: - payloadLenLimit = 39*8; - break; - default: - { - DBG_8192C ("[MPT], Error!! Unknown pTxRxPars->txrxPktType=0x%x\n", pTxRxPars->txrxPktType); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - break; - } - - if(pTxRxPars->txrxPayloadLen > payloadLenLimit) - { - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxPayloadLen=0x%x, (should smaller than %d)\n", - pTxRxPars->txrxPayloadLen, payloadLenLimit); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - - h2cParaBuf[0] = pTxRxPars->txrxPktType; - h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPayloadLen&0xff)); - h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPayloadLen&0xff00)>>8); - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - // fill h2c parameters - btOpcode = BT_LO_OP_SET_PKT_CNT_L_PL_TYPE; - if(pTxRxPars->txrxPayloadType > MP_BT_PAYLOAD_MAX) - { - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxPayloadType=0x%x, (should be between 0~4)\n", pTxRxPars->txrxPayloadType); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff)); - h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff00)>>8); - h2cParaBuf[2] = pTxRxPars->txrxPayloadType; - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - // fill h2c parameters - btOpcode = BT_LO_OP_SET_PKT_CNT_H_PKT_INTV; - if(pTxRxPars->txrxTxPktInterval > 15) - { - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxTxPktInterval=0x%x, (should be between 0~15)\n", pTxRxPars->txrxTxPktInterval); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff0000)>>16); - h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff000000)>>24); - h2cParaBuf[2] = pTxRxPars->txrxTxPktInterval; - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - // fill h2c parameters - btOpcode = BT_LO_OP_SET_WHITENCOEFF; - { - h2cParaBuf[0] = pTxRxPars->txrxWhitenCoeff; - h2cParaLen = 1; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - - // fill h2c parameters - btOpcode = BT_LO_OP_SET_CHNL_TX_GAIN; - if( (pTxRxPars->txrxChannel > 78) || - (pTxRxPars->txrxTxGainIndex > 7) ) - { - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxChannel=0x%x, (should be between 0~78)\n", pTxRxPars->txrxChannel); - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxTxGainIndex=0x%x, (should be between 0~7)\n", pTxRxPars->txrxTxGainIndex); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - h2cParaBuf[0] = pTxRxPars->txrxChannel; - h2cParaBuf[1] = pTxRxPars->txrxTxGainIndex; - h2cParaLen = 2; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - // fill h2c parameters - btOpcode = BT_LO_OP_SET_BD_ADDR_L; - if( (pTxRxPars->txrxBdaddr[0]==0) && - (pTxRxPars->txrxBdaddr[1]==0) && - (pTxRxPars->txrxBdaddr[2]==0) && - (pTxRxPars->txrxBdaddr[3]==0) && - (pTxRxPars->txrxBdaddr[4]==0) && - (pTxRxPars->txrxBdaddr[5]==0) ) - { - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxBdaddr=all zero\n"); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - if( (pTxRxPars->txrxBdaddr[0]==0xff) && - (pTxRxPars->txrxBdaddr[1]==0xff) && - (pTxRxPars->txrxBdaddr[2]==0xff) && - (pTxRxPars->txrxBdaddr[3]==0xff) && - (pTxRxPars->txrxBdaddr[4]==0xff) && - (pTxRxPars->txrxBdaddr[5]==0xff) ) - { - DBG_8192C ("[MPT], Error!! pTxRxPars->txrxBdaddr=all 0xf\n"); - pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - - { - h2cParaBuf[0] = pTxRxPars->txrxBdaddr[0]; - h2cParaBuf[1] = pTxRxPars->txrxBdaddr[1]; - h2cParaBuf[2] = pTxRxPars->txrxBdaddr[2]; - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - btOpcode = BT_LO_OP_SET_BD_ADDR_H; - { - h2cParaBuf[0] = pTxRxPars->txrxBdaddr[3]; - h2cParaBuf[1] = pTxRxPars->txrxBdaddr[4]; - h2cParaBuf[2] = pTxRxPars->txrxBdaddr[5]; - h2cParaLen = 3; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - // ckeck bt return status. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - pBtRsp->status = BT_STATUS_SUCCESS; - return paraLen; -} - - - -u2Byte -mptbt_BtTestCtrl( - IN PADAPTER Adapter, - IN PBT_REQ_CMD pBtReq, - IN PBT_RSP_CMD pBtRsp - ) -{ - u1Byte h2cParaBuf[6] ={0}; - u1Byte h2cParaLen=0; - u2Byte paraLen=0; - u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS; - u1Byte btOpcode; - u1Byte btOpcodeVer=0; - u1Byte testCtrl=0; - - // - // check upper layer parameters - // - - // 1. check upper layer opcode version - if(pBtReq->opCodeVer != 1) - { - DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n"); - pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH; - return paraLen; - } - // 2. check upper layer parameter length - if(1 == pBtReq->paraLength) - { - testCtrl = pBtReq->pParamStart[0]; - DBG_8192C("[MPT], testCtrl=%d \n", testCtrl); - } - else - { - DBG_8192C("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength); - pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U; - return paraLen; - } - - // - // execute lower layer opcodes - // - - // 1. fill h2c parameters - // check bt mode - btOpcode = BT_LO_OP_TEST_CTRL; - if(testCtrl >= MP_BT_TEST_MAX) - { - DBG_8192C("[MPT], Error!! testCtrl=0x%x, (should be between smaller or equal to 0x%x)\n", - testCtrl, MP_BT_TEST_MAX-1); - pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U; - return paraLen; - } - else - { - h2cParaBuf[0] = testCtrl; - h2cParaLen = 1; - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - } - - // 3. construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - pBtRsp->status = BT_STATUS_SUCCESS; - return paraLen; -} - - -u2Byte -mptbt_TestBT( - IN PADAPTER Adapter, - IN PBT_REQ_CMD pBtReq, - IN PBT_RSP_CMD pBtRsp - ) -{ - - u1Byte h2cParaBuf[6] ={0}; - u1Byte h2cParaLen=0; - u2Byte paraLen=0; - u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS; - u1Byte btOpcode; - u1Byte btOpcodeVer=0; - u1Byte testCtrl=0; - - // 1. fill h2c parameters - btOpcode = 0x11; - h2cParaBuf[0] = 0x11; - h2cParaBuf[1] = 0x0; - h2cParaBuf[2] = 0x0; - h2cParaBuf[3] = 0x0; - h2cParaBuf[4] = 0x0; - h2cParaLen = 1; - // retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen); - retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, h2cParaBuf, h2cParaLen); - - - // 3. construct respond status code and data. - if(BT_STATUS_BT_OP_SUCCESS != retStatus) - { - pBtRsp->status = ((btOpcode<<8)|retStatus); - DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status); - return paraLen; - } - - pBtRsp->status = BT_STATUS_SUCCESS; - return paraLen; -} - -VOID -mptbt_BtControlProcess( - PADAPTER Adapter, - PVOID pInBuf - ) -{ - u1Byte H2C_Parameter[6] ={0}; - PBT_H2C pH2c=(PBT_H2C)&H2C_Parameter[0]; - PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx); - PBT_REQ_CMD pBtReq=(PBT_REQ_CMD)pInBuf; - PBT_RSP_CMD pBtRsp=(PBT_RSP_CMD)&pMptCtx->mptOutBuf[0]; - u1Byte i; - - DBG_8192C("[MPT], mptbt_BtControlProcess()=========>\n"); - - DBG_8192C("[MPT], input opCodeVer=%d\n", pBtReq->opCodeVer); - DBG_8192C("[MPT], input OpCode=%d\n", pBtReq->OpCode); - DBG_8192C("[MPT], paraLength=%d \n", pBtReq->paraLength); - if(pBtReq->paraLength) - { - //DBG_8192C("[MPT], parameters(hex):0x%x %d \n",&pBtReq->pParamStart[0], pBtReq->paraLength); - } - - // The following we should maintain the User OP codes sent by upper layer - - pBtRsp->status = BT_STATUS_SUCCESS; - pMptCtx->mptOutLen = 4; //length of (BT_RSP_CMD.status+BT_RSP_CMD.paraLength) - pBtRsp->paraLength = 0x0; - - _rtw_memset((PVOID)&pMptCtx->mptOutBuf[0], '\0',100); - - switch(pBtReq->OpCode) - { - case BT_UP_OP_BT_READY: - DBG_8192C("[MPT], OPcode : [BT_READY]\n"); - pBtRsp->paraLength = mptbt_BtReady(Adapter, pBtReq, pBtRsp); - break; - case BT_UP_OP_BT_SET_MODE: - DBG_8192C("[MPT], OPcode : [BT_SET_MODE]\n"); - pBtRsp->paraLength = mptbt_BtSetMode(Adapter, pBtReq, pBtRsp); - break; - case BT_UP_OP_BT_SET_TX_RX_PARAMETER: - DBG_8192C("[MPT], OPcode : [BT_SET_TXRX_PARAMETER]\n"); - pBtRsp->paraLength = mptbt_BtSetTxRxPars(Adapter, pBtReq, pBtRsp); - break; - case BT_UP_OP_BT_SET_GENERAL: - DBG_8192C("[MPT], OPcode : [BT_SET_GENERAL]\n"); - pBtRsp->paraLength = mptbt_BtSetGeneral(Adapter, pBtReq, pBtRsp); - break; - case BT_UP_OP_BT_GET_GENERAL: - DBG_8192C("[MPT], OPcode : [BT_GET_GENERAL]\n"); - pBtRsp->paraLength = mptbt_BtGetGeneral(Adapter, pBtReq, pBtRsp); - break; - case BT_UP_OP_BT_TEST_CTRL: - DBG_8192C("[MPT], OPcode : [BT_TEST_CTRL]\n"); - pBtRsp->paraLength = mptbt_BtTestCtrl(Adapter, pBtReq, pBtRsp); - break; - case BT_UP_OP_TEST_BT: - DBG_8192C("[MPT], OPcode : [TEST_BT]\n"); - pBtRsp->paraLength = mptbt_TestBT(Adapter, pBtReq, pBtRsp); - break; - default: - DBG_8192C("[MPT], Error!! OPcode : UNDEFINED!!!!\n"); - pBtRsp->status = BT_STATUS_UNKNOWN_OPCODE_U; - pBtRsp->paraLength = 0x0; - break; - } - - DBG_8192C("pBtRsp->paraLength =%d \n",pBtRsp->paraLength); - - pMptCtx->mptOutLen += pBtRsp->paraLength; - - DBG_8192C("\n [MPT], OUT to DLL pMptCtx->mptOutLen=%d ,pBtRsp->paraLength =%d ",pMptCtx->mptOutLen,pBtRsp->paraLength); - - DBG_8192C("\n [MPT], mptbt_BtControlProcess()<=========\n"); -} - -#endif - +/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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, USA
+ *
+ *
+ ******************************************************************************/
+
+
+#include "rtw_bt_mp.h"
+#include <drv_types.h>
+#include <rtl8723a_hal.h>
+
+#ifdef CONFIG_RTL8723A
+
+void MPh2c_timeout_handle(void *FunctionContext)
+{
+ _adapter *pAdapter = (_adapter *)FunctionContext;
+ PMPT_CONTEXT pMptCtx=&pAdapter->mppriv.MptCtx;
+
+ DBG_8192C("[MPT], MPh2c_timeout_handle \n");
+
+ pMptCtx->bMPh2c_timeout=_TRUE;
+
+ _rtw_up_sema(&pMptCtx->MPh2c_Sema);
+
+ //_cancel_timer_ex( &pMptCtx->MPh2c_timeout_timer);
+
+ return;
+}
+u32 WaitC2Hevent( PADAPTER pAdapter,BOOLEAN *C2H_event ,u32 delay_time)
+{
+ PMPT_CONTEXT pMptCtx=&(pAdapter->mppriv.MptCtx);
+ pMptCtx->bMPh2c_timeout=_FALSE;
+ DBG_8192C("WaitC2Hevent _set_timer \n");
+ _set_timer( &pMptCtx->MPh2c_timeout_timer, delay_time );
+
+ _rtw_down_sema(&pMptCtx->MPh2c_Sema);
+
+ if( pMptCtx->bMPh2c_timeout == _TRUE )
+ {
+ C2H_event =_FALSE;
+ DBG_8192C("WaitC2Hevent bMPh2c_timeout _TRUE \n");
+ return _FALSE;
+ }
+
+ return _TRUE;
+
+}
+
+BT_CTRL_STATUS
+mptbt_CheckC2hFrame(
+ PADAPTER Adapter,
+ PBT_H2C pH2c,
+ PBT_EXT_C2H pExtC2h
+ )
+{
+ BT_CTRL_STATUS c2hStatus = BT_STATUS_C2H_SUCCESS;
+
+ //DBG_8192C("[MPT], MPT rsp C2H hex: %x %x %x %x %x %x \n"), pExtC2h , pExtC2h+1 ,pExtC2h+2 ,pExtC2h+3 ,pExtC2h+4 ,pExtC2h+5);
+
+ DBG_8192C("[MPT], statusCode = 0x%x\n", pExtC2h->statusCode);
+ DBG_8192C("[MPT], retLen = %d\n", pExtC2h->retLen);
+ DBG_8192C("[MPT], opCodeVer : req/rsp=%d/%d\n", pH2c->opCodeVer, pExtC2h->opCodeVer);
+ DBG_8192C("[MPT], reqNum : req/rsp=%d/%d\n", pH2c->reqNum, pExtC2h->reqNum);
+ if(pExtC2h->reqNum != pH2c->reqNum)
+ {
+ c2hStatus = BT_STATUS_C2H_REQNUM_MISMATCH;
+ DBG_8192C("[MPT], Error!! C2H reqNum Mismatch!!\n");
+ }
+ else if(pExtC2h->opCodeVer != pH2c->opCodeVer)
+ {
+ c2hStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH;
+ DBG_8192C("[MPT], Error!! OPCode version L mismatch!!\n");
+ }
+
+ return c2hStatus;
+}
+
+extern s32 FillH2CCmd(PADAPTER padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer);
+
+BT_CTRL_STATUS
+mptbt_SendH2c(
+ PADAPTER Adapter,
+ PBT_H2C pH2c,
+ u2Byte h2cCmdLen
+ )
+{
+ //KIRQL OldIrql = KeGetCurrentIrql();
+ BT_CTRL_STATUS h2cStatus=BT_STATUS_H2C_SUCCESS;
+ PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx);
+ u1Byte i;
+
+ DBG_8192C("[MPT], mptbt_SendH2c()=========>\n");
+
+ //PlatformResetEvent(&pMptCtx->MptH2cRspEvent);
+ //PlatformResetEvent(&pMptCtx->MptBtC2hEvent);
+
+// if(OldIrql == PASSIVE_LEVEL)
+// {
+ //RTPRINT_DATA(FMPBT, FMPBT_H2C_CONTENT, ("[MPT], MPT H2C hex: \n"), pH2c, h2cCmdLen);
+
+ for(i=0; i<BT_H2C_MAX_RETRY; i++)
+ {
+ DBG_8192C("[MPT], Send H2C command to wifi!!!\n");
+ FillH2CCmd(Adapter, 70, h2cCmdLen, (pu1Byte)pH2c);
+ pMptCtx->h2cReqNum++;
+ pMptCtx->h2cReqNum %= 16;
+
+ if(WaitC2Hevent(Adapter, &pMptCtx->MptH2cRspEvent, 200))
+ {
+ DBG_8192C("[MPT], Received WiFi MptH2cRspEvent!!!\n");
+ if(WaitC2Hevent(Adapter, &pMptCtx->MptBtC2hEvent, 800))
+ {
+ DBG_8192C("[MPT], Received BT MptBtC2hEvent!!!\n");
+ break;
+ }
+ else
+ {
+ DBG_8192C("[MPT], Error!!BT MptBtC2hEvent timeout!!\n");
+ h2cStatus = BT_STATUS_H2C_BT_NO_RSP;
+ }
+ }
+ else
+ {
+ DBG_8192C("[MPT], Error!!WiFi MptH2cRspEvent timeout!!\n");
+ h2cStatus = BT_STATUS_H2C_TIMTOUT;
+ }
+ }
+// }
+// else
+// {
+// RT_ASSERT(FALSE, ("[MPT], mptbt_SendH2c() can only run under PASSIVE_LEVEL!!\n"));
+// h2cStatus = BT_STATUS_WRONG_LEVEL;
+// }
+
+ DBG_8192C("[MPT], mptbt_SendH2c()<=========\n");
+ return h2cStatus;
+}
+
+
+
+BT_CTRL_STATUS
+mptbt_CheckBtRspStatus(
+ PADAPTER Adapter,
+ PBT_EXT_C2H pExtC2h
+ )
+{
+ BT_CTRL_STATUS retStatus=BT_OP_STATUS_SUCCESS;
+
+ switch(pExtC2h->statusCode)
+ {
+ case BT_OP_STATUS_SUCCESS:
+ retStatus = BT_STATUS_BT_OP_SUCCESS;
+ DBG_8192C("[MPT], BT status : BT_STATUS_SUCCESS\n");
+ break;
+ case BT_OP_STATUS_VERSION_MISMATCH:
+ retStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH;
+ DBG_8192C("[MPT], BT status : BT_STATUS_OPCODE_L_VERSION_MISMATCH\n");
+ break;
+ case BT_OP_STATUS_UNKNOWN_OPCODE:
+ retStatus = BT_STATUS_UNKNOWN_OPCODE_L;
+ DBG_8192C("[MPT], BT status : BT_STATUS_UNKNOWN_OPCODE_L\n");
+ break;
+ case BT_OP_STATUS_ERROR_PARAMETER:
+ retStatus = BT_STATUS_PARAMETER_FORMAT_ERROR_L;
+ DBG_8192C("[MPT], BT status : BT_STATUS_PARAMETER_FORMAT_ERROR_L\n");
+ break;
+ default:
+ retStatus = BT_STATUS_UNKNOWN_STATUS_L;
+ DBG_8192C("[MPT], BT status : BT_STATUS_UNKNOWN_STATUS_L\n");
+ break;
+ }
+
+ return retStatus;
+}
+
+
+
+BT_CTRL_STATUS
+mptbt_BtFwOpCodeProcess(
+ PADAPTER Adapter,
+ u1Byte btFwOpCode,
+ u1Byte opCodeVer,
+ pu1Byte pH2cPar,
+ u1Byte h2cParaLen
+ )
+{
+ u1Byte H2C_Parameter[6] ={0};
+ PBT_H2C pH2c=(PBT_H2C)&H2C_Parameter[0];
+ PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx);
+ PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
+ u2Byte paraLen=0,i;
+ BT_CTRL_STATUS h2cStatus=BT_STATUS_H2C_SUCCESS, c2hStatus=BT_STATUS_C2H_SUCCESS;
+ BT_CTRL_STATUS retStatus=BT_STATUS_H2C_BT_NO_RSP;
+
+ pH2c->opCode = btFwOpCode;
+ pH2c->opCodeVer = opCodeVer;
+ pH2c->reqNum = pMptCtx->h2cReqNum;
+ //PlatformMoveMemory(&pH2c->buf[0], pH2cPar, h2cParaLen);
+ //_rtw_memcpy(&pH2c->buf[0], pH2cPar, h2cParaLen);
+ _rtw_memcpy(pH2c->buf, pH2cPar, h2cParaLen);
+
+ DBG_8192C("[MPT], pH2c->opCode=%d\n", pH2c->opCode);
+ DBG_8192C("[MPT], pH2c->opCodeVer=%d\n", pH2c->opCodeVer);
+ DBG_8192C("[MPT], pH2c->reqNum=%d\n", pH2c->reqNum);
+ DBG_8192C("[MPT], h2c parameter length=%d\n", h2cParaLen);
+ if(h2cParaLen)
+ {
+ DBG_8192C("[MPT], parameters(hex): \n");
+ for(i=0;i<h2cParaLen;i++)
+ {
+ DBG_8192C(" 0x%x \n", pH2c->buf[i]);
+ }
+ }
+
+ h2cStatus = mptbt_SendH2c(Adapter, pH2c, h2cParaLen+2);
+ if(BT_STATUS_H2C_SUCCESS == h2cStatus)
+ {
+ // if reach here, it means H2C get the correct c2h response,
+ c2hStatus = mptbt_CheckC2hFrame(Adapter, pH2c, pExtC2h);
+ if(BT_STATUS_C2H_SUCCESS == c2hStatus)
+ {
+ retStatus = mptbt_CheckBtRspStatus(Adapter, pExtC2h);
+ }
+ else
+ {
+ DBG_8192C("[MPT], Error!! C2H failed for pH2c->opCode=%d\n", pH2c->opCode);
+ // check c2h status error, return error status code to upper layer.
+ retStatus = c2hStatus;
+ }
+ }
+ else
+ {
+ DBG_8192C("[MPT], Error!! H2C failed for pH2c->opCode=%d\n", pH2c->opCode);
+ // check h2c status error, return error status code to upper layer.
+ retStatus = h2cStatus;
+ }
+
+ return retStatus;
+}
+
+
+
+
+u2Byte
+mptbt_BtReady(
+ PADAPTER Adapter,
+ PBT_REQ_CMD pBtReq,
+ PBT_RSP_CMD pBtRsp
+ )
+{
+ u1Byte h2cParaBuf[6] ={0};
+ u1Byte h2cParaLen=0;
+ u2Byte paraLen=0;
+ u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS;
+ u1Byte btOpcode;
+ u1Byte btOpcodeVer=0;
+ PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx);
+ PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
+ u1Byte i;
+ u1Byte btFwVer=0, bdAddr[6]={0};
+ u2Byte btRealFwVer=0;
+ pu2Byte pu2Tmp=NULL;
+
+ //
+ // check upper layer parameters
+ //
+
+ // 1. check upper layer opcode version
+ if(pBtReq->opCodeVer != 1)
+ {
+ DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+ pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+ return paraLen;
+ }
+
+ pBtRsp->pParamStart[0] = MP_BT_NOT_READY;
+ paraLen = 10;
+ //
+ // execute lower layer opcodes
+ //
+
+ // Get BT FW version
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_GET_BT_VERSION;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ else
+ {
+ pu2Tmp = (pu2Byte)&pExtC2h->buf[0];
+ btRealFwVer = *pu2Tmp;
+ btFwVer = pExtC2h->buf[1];
+ DBG_8192C("[MPT], btRealFwVer=0x%x, btFwVer=0x%x\n", btRealFwVer, btFwVer);
+ }
+
+ // Get BD Address
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_GET_BD_ADDR_L;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ else
+ {
+ bdAddr[5] = pExtC2h->buf[0];
+ bdAddr[4] = pExtC2h->buf[1];
+ bdAddr[3] = pExtC2h->buf[2];
+ }
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_GET_BD_ADDR_H;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ else
+ {
+ bdAddr[2] = pExtC2h->buf[0];
+ bdAddr[1] = pExtC2h->buf[1];
+ bdAddr[0] = pExtC2h->buf[2];
+ }
+ DBG_8192C("[MPT], Local BDAddr:");
+ for(i=0; i<6; i++)
+ {
+ DBG_8192C(" 0x%x ", bdAddr[i]);
+ }
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ pBtRsp->pParamStart[0] = MP_BT_READY;
+ pu2Tmp = (pu2Byte)&pBtRsp->pParamStart[1];
+ *pu2Tmp = btRealFwVer;
+ pBtRsp->pParamStart[3] = btFwVer;
+ for(i=0; i<6; i++)
+ {
+ pBtRsp->pParamStart[4+i] = bdAddr[5-i];
+ }
+
+ return paraLen;
+}
+
+void mptbt_close_WiFiRF(PADAPTER Adapter)
+{
+ PHY_SetBBReg(Adapter, 0x824, 0xF, 0x0);
+ PHY_SetBBReg(Adapter, 0x824, 0x700000, 0x0);
+ PHY_SetRFReg(Adapter, RF90_PATH_A, 0x0, 0xF0000, 0x0);
+}
+
+void mptbt_open_WiFiRF(PADAPTER Adapter)
+{
+ PHY_SetBBReg(Adapter, 0x824, 0x700000, 0x3);
+ PHY_SetBBReg(Adapter, 0x824, 0xF, 0x2);
+ PHY_SetRFReg(Adapter, RF90_PATH_A, 0x0, 0xF0000, 0x3);
+}
+
+u4Byte mptbt_switch_RF(PADAPTER Adapter, u1Byte Enter)
+{
+ u2Byte tmp_2byte = 0;
+
+ //Enter test mode
+ if (Enter) {
+ ////1>. close WiFi RF
+ mptbt_close_WiFiRF(Adapter);
+
+ ////2>. change ant switch to BT
+ tmp_2byte = rtw_read16(Adapter, 0x860);
+ tmp_2byte = tmp_2byte | BIT(9);
+ tmp_2byte = tmp_2byte & (~BIT(8));
+ rtw_write16(Adapter, 0x860, tmp_2byte);
+ rtw_write16(Adapter, 0x870, 0x300);
+ } else {
+ ////1>. Open WiFi RF
+ mptbt_open_WiFiRF(Adapter);
+
+ ////2>. change ant switch back
+ tmp_2byte = rtw_read16(Adapter, 0x860);
+ tmp_2byte = tmp_2byte | BIT(8);
+ tmp_2byte = tmp_2byte & (~BIT(9));
+ rtw_write16(Adapter, 0x860, tmp_2byte);
+ rtw_write16(Adapter, 0x870, 0x300);
+ }
+
+ return 0;
+}
+
+u2Byte
+mptbt_BtSetMode(
+ PADAPTER Adapter,
+ PBT_REQ_CMD pBtReq,
+ PBT_RSP_CMD pBtRsp
+ )
+{
+ u1Byte h2cParaBuf[6] ={0};
+ u1Byte h2cParaLen=0;
+ u2Byte paraLen=0;
+ u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS;
+ u1Byte btOpcode;
+ u1Byte btOpcodeVer=0;
+ u1Byte btModeToSet=0;
+
+ //
+ // check upper layer parameters
+ //
+ // 1. check upper layer opcode version
+ if(pBtReq->opCodeVer != 1)
+ {
+ DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+ pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+ return paraLen;
+ }
+ // 2. check upper layer parameter length
+ if(1 == pBtReq->paraLength)
+ {
+ btModeToSet = pBtReq->pParamStart[0];
+ DBG_8192C("[MPT], BtTestMode=%d \n", btModeToSet);
+ }
+ else
+ {
+ DBG_8192C("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength);
+ pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+ return paraLen;
+ }
+
+ //
+ // execute lower layer opcodes
+ //
+
+ // 1. fill h2c parameters
+ // check bt mode
+ btOpcode = BT_LO_OP_SET_BT_MODE;
+ if(btModeToSet >= MP_BT_MODE_MAX)
+ {
+ pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ mptbt_switch_RF(Adapter, 1);
+
+ h2cParaBuf[0] = btModeToSet;
+ h2cParaLen = 1;
+ // 2. execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // 3. construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS == retStatus)
+ {
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ }
+ else
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ }
+
+ return paraLen;
+}
+
+
+VOID
+MPTBT_FwC2hBtMpCtrl(
+ PADAPTER Adapter,
+ pu1Byte tmpBuf,
+ u1Byte length
+ )
+{
+ u32 i;
+ PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx);
+ PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)tmpBuf;
+
+ if(Adapter->bBTFWReady == _FALSE || Adapter->registrypriv.mp_mode == 0 )
+ {
+ DBG_8192C("[MPT], %s,bBTFWReady == _FALSE\n",__func__);
+ return;
+ }
+ //cancel_timeout for h2c handle
+ _cancel_timer_ex( &pMptCtx->MPh2c_timeout_timer);
+
+ DBG_8192C("[MPT], MPTBT_FwC2hBtMpCtrl(), hex: \n");
+ for(i=0;i<=length;i++)
+ {
+ //DBG_8192C("[MPT], MPTBT_FwC2hBtMpCtrl(), hex: \n",tmpBuf[i], length);
+ DBG_8192C(" 0x%x ",tmpBuf[i]);
+ }
+ DBG_8192C("\n [MPT], pExtC2h->extendId=0x%x\n", pExtC2h->extendId);
+
+ switch(pExtC2h->extendId)
+ {
+ case EXT_C2H_WIFI_FW_ACTIVE_RSP:
+ DBG_8192C("[MPT], EXT_C2H_WIFI_FW_ACTIVE_RSP\n");
+ DBG_8192C("[MPT], pExtC2h->buf hex: \n");
+ if( length > 32 || length < 3 )
+ break ;
+ for(i=0;i<=(length-3);i++)
+ DBG_8192C(" 0x%x ",pExtC2h->buf[i]);
+ //PlatformSetEvent(&pMptCtx->MptH2cRspEvent);
+ pMptCtx->MptH2cRspEvent=_TRUE;
+ _rtw_up_sema(&pMptCtx->MPh2c_Sema);
+ break;
+ case EXT_C2H_TRIG_BY_BT_FW:
+ DBG_8192C("[MPT], EXT_C2H_TRIG_BY_BT_FW\n");
+ //PlatformMoveMemory(&pMptCtx->c2hBuf[0], tmpBuf, length);
+ _rtw_memcpy(&pMptCtx->c2hBuf[0], tmpBuf, length);
+ DBG_8192C("[MPT], pExtC2h->statusCode=0x%x\n", pExtC2h->statusCode);
+ DBG_8192C("[MPT], pExtC2h->retLen=0x%x\n", pExtC2h->retLen);
+ DBG_8192C("[MPT], pExtC2h->opCodeVer=0x%x\n", pExtC2h->opCodeVer);
+ DBG_8192C("[MPT], pExtC2h->reqNum=0x%x\n", pExtC2h->reqNum);
+ DBG_8192C("[MPT], pExtC2h->buf hex: \n");
+ for(i=0;i<=(length-3);i++)
+ DBG_8192C(" 0x%x ",pExtC2h->buf[0]);
+ //PlatformSetEvent(&pMptCtx->MptBtC2hEvent);
+ pMptCtx->MptBtC2hEvent=_TRUE;
+ _rtw_up_sema(&pMptCtx->MPh2c_Sema);
+ break;
+ default:
+ DBG_8192C("[MPT], EXT_C2H Target not found,pExtC2h->extendId =%d ,pExtC2h->reqNum=%d\n",pExtC2h->extendId,pExtC2h->reqNum);
+ break;
+ }
+
+
+
+}
+
+
+u2Byte
+mptbt_BtGetGeneral(
+ IN PADAPTER Adapter,
+ IN PBT_REQ_CMD pBtReq,
+ IN PBT_RSP_CMD pBtRsp
+ )
+{
+ PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx);
+ PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
+ u1Byte h2cParaBuf[6] ={0};
+ u1Byte h2cParaLen=0;
+ u2Byte paraLen=0;
+ u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS;
+ u1Byte btOpcode, bdAddr[6]={0};
+ u1Byte btOpcodeVer=0;
+ u1Byte getType=0, i;
+ u2Byte getParaLen=0, validParaLen=0;
+ u1Byte regType=0, reportType=0;
+ u4Byte regAddr=0, regValue=0;
+ pu4Byte pu4Tmp;
+ pu2Byte pu2Tmp;
+ pu1Byte pu1Tmp;
+
+ //
+ // check upper layer parameters
+ //
+
+ // check upper layer opcode version
+ if(pBtReq->opCodeVer != 1)
+ {
+ DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+ pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+ return paraLen;
+ }
+ // check upper layer parameter length
+ if(pBtReq->paraLength < 1)
+ {
+ DBG_8192C("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength);
+ pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+ return paraLen;
+ }
+ getParaLen = pBtReq->paraLength - 1;
+ getType = pBtReq->pParamStart[0];
+
+ DBG_8192C("[MPT], getType=%d, getParaLen=%d\n", getType, getParaLen);
+
+ // check parameter first
+ switch(getType)
+ {
+ case BT_GGET_REG:
+ DBG_8192C("[MPT], [BT_GGET_REG]\n");
+ validParaLen = 5;
+ if(getParaLen == validParaLen)
+ {
+ btOpcode = BT_LO_OP_READ_REG;
+ regType = pBtReq->pParamStart[1];
+ pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2];
+ regAddr = *pu4Tmp;
+ DBG_8192C("[MPT], BT_GGET_REG regType=0x%x, regAddr=0x%x!!\n",
+ regType, regAddr);
+ if(regType >= BT_REG_MAX)
+ {
+ pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ if( ((BT_REG_RF==regType)&&(regAddr>0x7f)) ||
+ ((BT_REG_MODEM==regType)&&(regAddr>0x1ff)) ||
+ ((BT_REG_BLUEWIZE==regType)&&(regAddr>0xfff)) ||
+ ((BT_REG_VENDOR==regType)&&(regAddr>0xfff)) ||
+ ((BT_REG_LE==regType)&&(regAddr>0xfff)) )
+ {
+ pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ }
+ }
+ break;
+ case BT_GGET_STATUS:
+ DBG_8192C("[MPT], [BT_GGET_STATUS]\n");
+ validParaLen = 0;
+ break;
+ case BT_GGET_REPORT:
+ DBG_8192C("[MPT], [BT_GGET_REPORT]\n");
+ validParaLen = 1;
+ if(getParaLen == validParaLen)
+ {
+ reportType = pBtReq->pParamStart[1];
+ DBG_8192C("[MPT], BT_GGET_REPORT reportType=0x%x!!\n", reportType);
+ if(reportType >= BT_REPORT_MAX)
+ {
+ pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ }
+ break;
+ default:
+ {
+ DBG_8192C("[MPT], Error!! getType=%d, out of range\n", getType);
+ pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ break;
+ }
+ if(getParaLen != validParaLen)
+ {
+ DBG_8192C("[MPT], Error!! wrong parameter length=%d for BT_GET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n",
+ getParaLen, getType, validParaLen);
+ pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+ return paraLen;
+ }
+
+ //
+ // execute lower layer opcodes
+ //
+ if(BT_GGET_REG == getType)
+ {
+ // fill h2c parameters
+ // here we should write reg value first then write the address, adviced by Austin
+ btOpcode = BT_LO_OP_READ_REG;
+ h2cParaBuf[0] = regType;
+ h2cParaBuf[1] = pBtReq->pParamStart[2];
+ h2cParaBuf[2] = pBtReq->pParamStart[3];
+ h2cParaLen = 3;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ pu2Tmp = (pu2Byte)&pExtC2h->buf[0];
+ regValue = *pu2Tmp;
+ DBG_8192C("[MPT], read reg regType=0x%x, regAddr=0x%x, regValue=0x%x\n",
+ regType, regAddr, regValue);
+
+ pu4Tmp = (pu4Byte)&pBtRsp->pParamStart[0];
+ *pu4Tmp = regValue;
+ paraLen = 4;
+ }
+ else if(BT_GGET_STATUS == getType)
+ {
+ btOpcode = BT_LO_OP_GET_BT_STATUS;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+ DBG_8192C("[MPT], read bt status, testMode=0x%x, testStatus=0x%x\n",
+ pBtRsp->pParamStart[0], pBtRsp->pParamStart[1]);
+ paraLen = 2;
+ }
+ else if(BT_GGET_REPORT == getType)
+ {
+ switch(reportType)
+ {
+ case BT_REPORT_RX_PACKET_CNT:
+ {
+ DBG_8192C("[MPT], [Rx Packet Counts]\n");
+ btOpcode = BT_LO_OP_GET_RX_PKT_CNT_L;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+
+ btOpcode = BT_LO_OP_GET_RX_PKT_CNT_H;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ pBtRsp->pParamStart[2] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[3] = pExtC2h->buf[1];
+ paraLen = 4;
+ }
+ break;
+ case BT_REPORT_RX_ERROR_BITS:
+ {
+ DBG_8192C("[MPT], [Rx Error Bits]\n");
+ btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_L;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+
+ btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_H;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ pBtRsp->pParamStart[2] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[3] = pExtC2h->buf[1];
+ paraLen = 4;
+ }
+ break;
+ case BT_REPORT_RSSI:
+ {
+ DBG_8192C("[MPT], [RSSI]\n");
+ btOpcode = BT_LO_OP_GET_RSSI;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+ paraLen = 2;
+ }
+ break;
+ case BT_REPORT_CFO_HDR_QUALITY:
+ {
+ DBG_8192C("[MPT], [CFO & Header Quality]\n");
+ btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_L;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+
+ btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_H;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ pBtRsp->pParamStart[2] = pExtC2h->buf[0];
+ pBtRsp->pParamStart[3] = pExtC2h->buf[1];
+ paraLen = 4;
+ }
+ break;
+ case BT_REPORT_CONNECT_TARGET_BD_ADDR:
+ {
+ DBG_8192C("[MPT], [Connected Target BD ADDR]\n");
+ btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_L;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ bdAddr[5] = pExtC2h->buf[0];
+ bdAddr[4] = pExtC2h->buf[1];
+ bdAddr[3] = pExtC2h->buf[2];
+
+ btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_H;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ bdAddr[2] = pExtC2h->buf[0];
+ bdAddr[1] = pExtC2h->buf[1];
+ bdAddr[0] = pExtC2h->buf[2];
+
+ DBG_8192C("[MPT], Connected Target BDAddr:%s", bdAddr);
+ for(i=0; i<6; i++)
+ {
+ pBtRsp->pParamStart[i] = bdAddr[5-i];
+ }
+ paraLen = 6;
+ }
+ break;
+ default:
+ pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ break;
+ }
+ }
+
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ return paraLen;
+}
+
+
+
+u2Byte
+mptbt_BtSetGeneral(
+ IN PADAPTER Adapter,
+ IN PBT_REQ_CMD pBtReq,
+ IN PBT_RSP_CMD pBtRsp
+ )
+{
+ u1Byte h2cParaBuf[6] ={0};
+ u1Byte h2cParaLen=0;
+ u2Byte paraLen=0;
+ u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS;
+ u1Byte btOpcode;
+ u1Byte btOpcodeVer=0;
+ u1Byte setType=0;
+ u2Byte setParaLen=0, validParaLen=0;
+ u1Byte regType=0, bdAddr[6]={0}, calVal=0;
+ u4Byte regAddr=0, regValue=0;
+ pu4Byte pu4Tmp;
+ pu2Byte pu2Tmp;
+ pu1Byte pu1Tmp;
+
+ //
+ // check upper layer parameters
+ //
+
+ // check upper layer opcode version
+ if(pBtReq->opCodeVer != 1)
+ {
+ DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+ pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+ return paraLen;
+ }
+ // check upper layer parameter length
+ if(pBtReq->paraLength < 1)
+ {
+ DBG_8192C("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength);
+ pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+ return paraLen;
+ }
+ setParaLen = pBtReq->paraLength - 1;
+ setType = pBtReq->pParamStart[0];
+
+ DBG_8192C("[MPT], setType=%d, setParaLen=%d\n", setType, setParaLen);
+
+ // check parameter first
+ switch(setType)
+ {
+ case BT_GSET_REG:
+ DBG_8192C ("[MPT], [BT_GSET_REG]\n");
+ validParaLen = 9;
+ if(setParaLen == validParaLen)
+ {
+ btOpcode = BT_LO_OP_WRITE_REG_VALUE;
+ regType = pBtReq->pParamStart[1];
+ pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2];
+ regAddr = *pu4Tmp;
+ pu4Tmp = (pu4Byte)&pBtReq->pParamStart[6];
+ regValue = *pu4Tmp;
+ DBG_8192C("[MPT], BT_GSET_REG regType=0x%x, regAddr=0x%x, regValue=0x%x!!\n",
+ regType, regAddr, regValue);
+ if(regType >= BT_REG_MAX)
+ {
+ pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ if( ((BT_REG_RF==regType)&&(regAddr>0x7f)) ||
+ ((BT_REG_MODEM==regType)&&(regAddr>0x1ff)) ||
+ ((BT_REG_BLUEWIZE==regType)&&(regAddr>0xfff)) ||
+ ((BT_REG_VENDOR==regType)&&(regAddr>0xfff)) ||
+ ((BT_REG_LE==regType)&&(regAddr>0xfff)) )
+ {
+ pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ }
+ }
+ break;
+ case BT_GSET_RESET:
+ DBG_8192C("[MPT], [BT_GSET_RESET]\n");
+ validParaLen = 0;
+ break;
+ case BT_GSET_TARGET_BD_ADDR:
+ DBG_8192C("[MPT], [BT_GSET_TARGET_BD_ADDR]\n");
+ validParaLen = 6;
+ if(setParaLen == validParaLen)
+ {
+ btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H;
+ if( (pBtReq->pParamStart[1]==0) &&
+ (pBtReq->pParamStart[2]==0) &&
+ (pBtReq->pParamStart[3]==0) &&
+ (pBtReq->pParamStart[4]==0) &&
+ (pBtReq->pParamStart[5]==0) &&
+ (pBtReq->pParamStart[6]==0) )
+ {
+ DBG_8192C("[MPT], Error!! targetBDAddr=all zero\n");
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ if( (pBtReq->pParamStart[1]==0xff) &&
+ (pBtReq->pParamStart[2]==0xff) &&
+ (pBtReq->pParamStart[3]==0xff) &&
+ (pBtReq->pParamStart[4]==0xff) &&
+ (pBtReq->pParamStart[5]==0xff) &&
+ (pBtReq->pParamStart[6]==0xff) )
+ {
+ DBG_8192C("[MPT], Error!! targetBDAddr=all 0xf\n");
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ bdAddr[0] = pBtReq->pParamStart[6];
+ bdAddr[1] = pBtReq->pParamStart[5];
+ bdAddr[2] = pBtReq->pParamStart[4];
+ bdAddr[3] = pBtReq->pParamStart[3];
+ bdAddr[4] = pBtReq->pParamStart[2];
+ bdAddr[5] = pBtReq->pParamStart[1];
+ DBG_8192C ("[MPT], target BDAddr:%x,%x,%x,%x,%x,%x\n",
+ bdAddr[0],bdAddr[1],bdAddr[2],bdAddr[3],bdAddr[4],bdAddr[5]);
+ }
+ break;
+ case BT_GSET_TX_PWR_FINETUNE:
+ DBG_8192C("[MPT], [BT_GSET_TX_PWR_FINETUNE]\n");
+ validParaLen = 1;
+ if(setParaLen == validParaLen)
+ {
+ btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION;
+ calVal = pBtReq->pParamStart[1];
+ if( (calVal<1) || (calVal>9) )
+ {
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ DBG_8192C ("[MPT], calVal=%d\n", calVal);
+ }
+ break;
+ case BT_SET_TRACKING_INTERVAL:
+ DBG_871X("[MPT], [BT_SET_TRACKING_INTERVAL] setParaLen =%d \n",setParaLen);
+
+ validParaLen = 1;
+ if(setParaLen == validParaLen)
+ calVal = pBtReq->pParamStart[1];
+ break;
+ case BT_SET_THERMAL_METER:
+ DBG_871X("[MPT], [BT_SET_THERMAL_METER] setParaLen =%d \n",setParaLen);
+ validParaLen = 1;
+ if(setParaLen == validParaLen)
+ calVal = pBtReq->pParamStart[1];
+ break;
+ case BT_ENABLE_CFO_TRACKING:
+ DBG_871X("[MPT], [BT_ENABLE_CFO_TRACKING] setParaLen =%d \n",setParaLen);
+ validParaLen = 1;
+ if(setParaLen == validParaLen)
+ calVal = pBtReq->pParamStart[1];
+ break;
+ case BT_GSET_UPDATE_BT_PATCH:
+ if(IS_HARDWARE_TYPE_8723AE(Adapter) && Adapter->bFWReady)
+ {
+ u1Byte i;
+ DBG_8192C ("[MPT], write regs for load patch\n");
+ //BTFwPatch8723A(Adapter);
+ PlatformEFIOWrite1Byte(Adapter, 0xCC, 0x2d);
+ rtw_msleep_os(50);
+ PlatformEFIOWrite4Byte(Adapter, 0x68, 0xa005000c);
+ rtw_msleep_os(50);
+ PlatformEFIOWrite4Byte(Adapter, 0x68, 0xb005000c);
+ rtw_msleep_os(50);
+ PlatformEFIOWrite1Byte(Adapter, 0xCC, 0x29);
+ for(i=0; i<12; i++)
+ rtw_msleep_os(100);
+//#if (DEV_BUS_TYPE == RT_PCI_INTERFACE)
+// BTFwPatch8723A(Adapter);
+//#endif
+ DBG_8192C("[MPT], load BT FW Patch finished!!!\n");
+ }
+ break;
+ default:
+ {
+ DBG_8192C ("[MPT], Error!! setType=%d, out of range\n", setType);
+ pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ break;
+ }
+ if(setParaLen != validParaLen)
+ {
+ DBG_8192C("[MPT], Error!! wrong parameter length=%d for BT_SET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n",
+ setParaLen, setType, validParaLen);
+ pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+ return paraLen;
+ }
+
+ //
+ // execute lower layer opcodes
+ //
+ if(BT_GSET_REG == setType)
+ {
+ // fill h2c parameters
+ // here we should write reg value first then write the address, adviced by Austin
+ btOpcode = BT_LO_OP_WRITE_REG_VALUE;
+ h2cParaBuf[0] = pBtReq->pParamStart[6];
+ h2cParaBuf[1] = pBtReq->pParamStart[7];
+ h2cParaBuf[2] = pBtReq->pParamStart[8];
+ h2cParaLen = 3;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ // write reg address
+ btOpcode = BT_LO_OP_WRITE_REG_ADDR;
+ h2cParaBuf[0] = regType;
+ h2cParaBuf[1] = pBtReq->pParamStart[2];
+ h2cParaBuf[2] = pBtReq->pParamStart[3];
+ h2cParaLen = 3;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ }
+ else if(BT_GSET_RESET == setType)
+ {
+ btOpcode = BT_LO_OP_RESET;
+ h2cParaLen = 0;
+ // execute h2c and check respond c2h from bt fw is correct or not
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ }
+ else if(BT_GSET_TARGET_BD_ADDR == setType)
+ {
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_L;
+ h2cParaBuf[0] = pBtReq->pParamStart[1];
+ h2cParaBuf[1] = pBtReq->pParamStart[2];
+ h2cParaBuf[2] = pBtReq->pParamStart[3];
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H;
+ h2cParaBuf[0] = pBtReq->pParamStart[4];
+ h2cParaBuf[1] = pBtReq->pParamStart[5];
+ h2cParaBuf[2] = pBtReq->pParamStart[6];
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ }
+ else if(BT_GSET_TX_PWR_FINETUNE == setType)
+ {
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION;
+ h2cParaBuf[0] = calVal;
+ h2cParaLen = 1;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ }
+ else if(BT_SET_TRACKING_INTERVAL == setType)
+ {
+ // BT_LO_OP_SET_TRACKING_INTERVAL = 0x22,
+ // BT_LO_OP_SET_THERMAL_METER = 0x23,
+ // BT_LO_OP_ENABLE_CFO_TRACKING = 0x24,
+ btOpcode = BT_LO_OP_SET_TRACKING_INTERVAL;
+ h2cParaBuf[0] = calVal;
+ h2cParaLen = 1;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ }
+ else if(BT_SET_THERMAL_METER == setType)
+ {
+ btOpcode = BT_LO_OP_SET_THERMAL_METER;
+ h2cParaBuf[0] = calVal;
+ h2cParaLen = 1;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ }
+ else if(BT_ENABLE_CFO_TRACKING == setType)
+ {
+ btOpcode = BT_LO_OP_ENABLE_CFO_TRACKING;
+ h2cParaBuf[0] = calVal;
+ h2cParaLen = 1;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+ }
+
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ return paraLen;
+}
+
+
+
+u2Byte
+mptbt_BtSetTxRxPars(
+ IN PADAPTER Adapter,
+ IN PBT_REQ_CMD pBtReq,
+ IN PBT_RSP_CMD pBtRsp
+ )
+{
+ u1Byte h2cParaBuf[6] ={0};
+ u1Byte h2cParaLen=0;
+ u2Byte paraLen=0;
+ u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS;
+ u1Byte btOpcode;
+ u1Byte btOpcodeVer=0;
+ PBT_TXRX_PARAMETERS pTxRxPars=(PBT_TXRX_PARAMETERS)&pBtReq->pParamStart[0];
+ u2Byte lenTxRx=sizeof(BT_TXRX_PARAMETERS);
+ u1Byte i;
+ u1Byte bdAddr[6]={0};
+
+ //
+ // check upper layer parameters
+ //
+
+ // 1. check upper layer opcode version
+ if(pBtReq->opCodeVer != 1)
+ {
+ DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+ pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+ return paraLen;
+ }
+ // 2. check upper layer parameter length
+ if(pBtReq->paraLength == sizeof(BT_TXRX_PARAMETERS))
+ {
+ DBG_8192C ("[MPT], pTxRxPars->txrxChannel=0x%x \n", pTxRxPars->txrxChannel);
+ DBG_8192C ("[MPT], pTxRxPars->txrxTxPktCnt=0x%8x \n", pTxRxPars->txrxTxPktCnt);
+ DBG_8192C ("[MPT], pTxRxPars->txrxTxPktInterval=0x%x \n", pTxRxPars->txrxTxPktInterval);
+ DBG_8192C ("[MPT], pTxRxPars->txrxPayloadType=0x%x \n", pTxRxPars->txrxPayloadType);
+ DBG_8192C ("[MPT], pTxRxPars->txrxPktType=0x%x \n", pTxRxPars->txrxPktType);
+ DBG_8192C ("[MPT], pTxRxPars->txrxPayloadLen=0x%x \n", pTxRxPars->txrxPayloadLen);
+ DBG_8192C ("[MPT], pTxRxPars->txrxPktHeader=0x%x \n", pTxRxPars->txrxPktHeader);
+ DBG_8192C ("[MPT], pTxRxPars->txrxWhitenCoeff=0x%x \n", pTxRxPars->txrxWhitenCoeff);
+ bdAddr[0] = pTxRxPars->txrxBdaddr[5];
+ bdAddr[1] = pTxRxPars->txrxBdaddr[4];
+ bdAddr[2] = pTxRxPars->txrxBdaddr[3];
+ bdAddr[3] = pTxRxPars->txrxBdaddr[2];
+ bdAddr[4] = pTxRxPars->txrxBdaddr[1];
+ bdAddr[5] = pTxRxPars->txrxBdaddr[0];
+ DBG_8192C ("[MPT], pTxRxPars->txrxBdaddr: %s", &bdAddr[0]);
+ DBG_8192C ("[MPT], pTxRxPars->txrxTxGainIndex=0x%x \n", pTxRxPars->txrxTxGainIndex);
+ }
+ else
+ {
+ DBG_8192C ("[MPT], Error!! pBtReq->paraLength=%d, correct Len=%d\n", pBtReq->paraLength, lenTxRx);
+ pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+ return paraLen;
+ }
+
+ //
+ // execute lower layer opcodes
+ //
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_PKT_HEADER;
+ if(pTxRxPars->txrxPktHeader > 0x3ffff)
+ {
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxPktHeader=0x%x is out of range, (should be between 0x0~0x3ffff)\n", pTxRxPars->txrxPktHeader);
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ h2cParaBuf[0] = (u1Byte)(pTxRxPars->txrxPktHeader&0xff);
+ h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPktHeader&0xff00)>>8);
+ h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPktHeader&0xff0000)>>16);
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_PKT_TYPE_LEN;
+ {
+ u2Byte payloadLenLimit=0;
+ switch(pTxRxPars->txrxPktType)
+ {
+ case MP_BT_PKT_DH1:
+ payloadLenLimit = 27*8;
+ break;
+ case MP_BT_PKT_DH3:
+ payloadLenLimit = 183*8;
+ break;
+ case MP_BT_PKT_DH5:
+ payloadLenLimit = 339*8;
+ break;
+ case MP_BT_PKT_2DH1:
+ payloadLenLimit = 54*8;
+ break;
+ case MP_BT_PKT_2DH3:
+ payloadLenLimit = 367*8;
+ break;
+ case MP_BT_PKT_2DH5:
+ payloadLenLimit = 679*8;
+ break;
+ case MP_BT_PKT_3DH1:
+ payloadLenLimit = 83*8;
+ break;
+ case MP_BT_PKT_3DH3:
+ payloadLenLimit = 552*8;
+ break;
+ case MP_BT_PKT_3DH5:
+ payloadLenLimit = 1021*8;
+ break;
+ case MP_BT_PKT_LE:
+ payloadLenLimit = 39*8;
+ break;
+ default:
+ {
+ DBG_8192C ("[MPT], Error!! Unknown pTxRxPars->txrxPktType=0x%x\n", pTxRxPars->txrxPktType);
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ break;
+ }
+
+ if(pTxRxPars->txrxPayloadLen > payloadLenLimit)
+ {
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxPayloadLen=0x%x, (should smaller than %d)\n",
+ pTxRxPars->txrxPayloadLen, payloadLenLimit);
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+
+ h2cParaBuf[0] = pTxRxPars->txrxPktType;
+ h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPayloadLen&0xff));
+ h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPayloadLen&0xff00)>>8);
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_PKT_CNT_L_PL_TYPE;
+ if(pTxRxPars->txrxPayloadType > MP_BT_PAYLOAD_MAX)
+ {
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxPayloadType=0x%x, (should be between 0~4)\n", pTxRxPars->txrxPayloadType);
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff));
+ h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff00)>>8);
+ h2cParaBuf[2] = pTxRxPars->txrxPayloadType;
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_PKT_CNT_H_PKT_INTV;
+ if(pTxRxPars->txrxTxPktInterval > 15)
+ {
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxTxPktInterval=0x%x, (should be between 0~15)\n", pTxRxPars->txrxTxPktInterval);
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff0000)>>16);
+ h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff000000)>>24);
+ h2cParaBuf[2] = pTxRxPars->txrxTxPktInterval;
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_WHITENCOEFF;
+ {
+ h2cParaBuf[0] = pTxRxPars->txrxWhitenCoeff;
+ h2cParaLen = 1;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_CHNL_TX_GAIN;
+ if( (pTxRxPars->txrxChannel > 78) ||
+ (pTxRxPars->txrxTxGainIndex > 7) )
+ {
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxChannel=0x%x, (should be between 0~78)\n", pTxRxPars->txrxChannel);
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxTxGainIndex=0x%x, (should be between 0~7)\n", pTxRxPars->txrxTxGainIndex);
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ h2cParaBuf[0] = pTxRxPars->txrxChannel;
+ h2cParaBuf[1] = pTxRxPars->txrxTxGainIndex;
+ h2cParaLen = 2;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ // fill h2c parameters
+ btOpcode = BT_LO_OP_SET_BD_ADDR_L;
+ if( (pTxRxPars->txrxBdaddr[0]==0) &&
+ (pTxRxPars->txrxBdaddr[1]==0) &&
+ (pTxRxPars->txrxBdaddr[2]==0) &&
+ (pTxRxPars->txrxBdaddr[3]==0) &&
+ (pTxRxPars->txrxBdaddr[4]==0) &&
+ (pTxRxPars->txrxBdaddr[5]==0) )
+ {
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxBdaddr=all zero\n");
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ if( (pTxRxPars->txrxBdaddr[0]==0xff) &&
+ (pTxRxPars->txrxBdaddr[1]==0xff) &&
+ (pTxRxPars->txrxBdaddr[2]==0xff) &&
+ (pTxRxPars->txrxBdaddr[3]==0xff) &&
+ (pTxRxPars->txrxBdaddr[4]==0xff) &&
+ (pTxRxPars->txrxBdaddr[5]==0xff) )
+ {
+ DBG_8192C ("[MPT], Error!! pTxRxPars->txrxBdaddr=all 0xf\n");
+ pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+
+ {
+ h2cParaBuf[0] = pTxRxPars->txrxBdaddr[0];
+ h2cParaBuf[1] = pTxRxPars->txrxBdaddr[1];
+ h2cParaBuf[2] = pTxRxPars->txrxBdaddr[2];
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ btOpcode = BT_LO_OP_SET_BD_ADDR_H;
+ {
+ h2cParaBuf[0] = pTxRxPars->txrxBdaddr[3];
+ h2cParaBuf[1] = pTxRxPars->txrxBdaddr[4];
+ h2cParaBuf[2] = pTxRxPars->txrxBdaddr[5];
+ h2cParaLen = 3;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+ // ckeck bt return status.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ return paraLen;
+}
+
+
+
+u2Byte
+mptbt_BtTestCtrl(
+ IN PADAPTER Adapter,
+ IN PBT_REQ_CMD pBtReq,
+ IN PBT_RSP_CMD pBtRsp
+ )
+{
+ u1Byte h2cParaBuf[6] ={0};
+ u1Byte h2cParaLen=0;
+ u2Byte paraLen=0;
+ u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS;
+ u1Byte btOpcode;
+ u1Byte btOpcodeVer=0;
+ u1Byte testCtrl=0;
+
+ //
+ // check upper layer parameters
+ //
+
+ // 1. check upper layer opcode version
+ if(pBtReq->opCodeVer != 1)
+ {
+ DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+ pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+ return paraLen;
+ }
+ // 2. check upper layer parameter length
+ if(1 == pBtReq->paraLength)
+ {
+ testCtrl = pBtReq->pParamStart[0];
+ DBG_8192C("[MPT], testCtrl=%d \n", testCtrl);
+ }
+ else
+ {
+ DBG_8192C("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength);
+ pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+ return paraLen;
+ }
+
+ //
+ // execute lower layer opcodes
+ //
+
+ // 1. fill h2c parameters
+ // check bt mode
+ btOpcode = BT_LO_OP_TEST_CTRL;
+ if(testCtrl >= MP_BT_TEST_MAX)
+ {
+ DBG_8192C("[MPT], Error!! testCtrl=0x%x, (should be between smaller or equal to 0x%x)\n",
+ testCtrl, MP_BT_TEST_MAX-1);
+ pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+ return paraLen;
+ }
+ else
+ {
+ h2cParaBuf[0] = testCtrl;
+ h2cParaLen = 1;
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ }
+
+ // 3. construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ return paraLen;
+}
+
+
+u2Byte
+mptbt_TestBT(
+ IN PADAPTER Adapter,
+ IN PBT_REQ_CMD pBtReq,
+ IN PBT_RSP_CMD pBtRsp
+ )
+{
+
+ u1Byte h2cParaBuf[6] ={0};
+ u1Byte h2cParaLen=0;
+ u2Byte paraLen=0;
+ u1Byte retStatus=BT_STATUS_BT_OP_SUCCESS;
+ u1Byte btOpcode;
+ u1Byte btOpcodeVer=0;
+ u1Byte testCtrl=0;
+
+ // 1. fill h2c parameters
+ btOpcode = 0x11;
+ h2cParaBuf[0] = 0x11;
+ h2cParaBuf[1] = 0x0;
+ h2cParaBuf[2] = 0x0;
+ h2cParaBuf[3] = 0x0;
+ h2cParaBuf[4] = 0x0;
+ h2cParaLen = 1;
+ // retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+ retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, h2cParaBuf, h2cParaLen);
+
+
+ // 3. construct respond status code and data.
+ if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+ {
+ pBtRsp->status = ((btOpcode<<8)|retStatus);
+ DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+ return paraLen;
+ }
+
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ return paraLen;
+}
+
+VOID
+mptbt_BtControlProcess(
+ PADAPTER Adapter,
+ PVOID pInBuf
+ )
+{
+ u1Byte H2C_Parameter[6] ={0};
+ PBT_H2C pH2c=(PBT_H2C)&H2C_Parameter[0];
+ PMPT_CONTEXT pMptCtx=&(Adapter->mppriv.MptCtx);
+ PBT_REQ_CMD pBtReq=(PBT_REQ_CMD)pInBuf;
+ PBT_RSP_CMD pBtRsp=(PBT_RSP_CMD)&pMptCtx->mptOutBuf[0];
+ u1Byte i;
+
+ DBG_8192C("[MPT], mptbt_BtControlProcess()=========>\n");
+
+ DBG_8192C("[MPT], input opCodeVer=%d\n", pBtReq->opCodeVer);
+ DBG_8192C("[MPT], input OpCode=%d\n", pBtReq->OpCode);
+ DBG_8192C("[MPT], paraLength=%d \n", pBtReq->paraLength);
+ if(pBtReq->paraLength)
+ {
+ //DBG_8192C("[MPT], parameters(hex):0x%x %d \n",&pBtReq->pParamStart[0], pBtReq->paraLength);
+ }
+
+ // The following we should maintain the User OP codes sent by upper layer
+
+ pBtRsp->status = BT_STATUS_SUCCESS;
+ pMptCtx->mptOutLen = 4; //length of (BT_RSP_CMD.status+BT_RSP_CMD.paraLength)
+ pBtRsp->paraLength = 0x0;
+
+ _rtw_memset((PVOID)&pMptCtx->mptOutBuf[0], '\0',100);
+
+ switch(pBtReq->OpCode)
+ {
+ case BT_UP_OP_BT_READY:
+ DBG_8192C("[MPT], OPcode : [BT_READY]\n");
+ pBtRsp->paraLength = mptbt_BtReady(Adapter, pBtReq, pBtRsp);
+ break;
+ case BT_UP_OP_BT_SET_MODE:
+ DBG_8192C("[MPT], OPcode : [BT_SET_MODE]\n");
+ pBtRsp->paraLength = mptbt_BtSetMode(Adapter, pBtReq, pBtRsp);
+ break;
+ case BT_UP_OP_BT_SET_TX_RX_PARAMETER:
+ DBG_8192C("[MPT], OPcode : [BT_SET_TXRX_PARAMETER]\n");
+ pBtRsp->paraLength = mptbt_BtSetTxRxPars(Adapter, pBtReq, pBtRsp);
+ break;
+ case BT_UP_OP_BT_SET_GENERAL:
+ DBG_8192C("[MPT], OPcode : [BT_SET_GENERAL]\n");
+ pBtRsp->paraLength = mptbt_BtSetGeneral(Adapter, pBtReq, pBtRsp);
+ break;
+ case BT_UP_OP_BT_GET_GENERAL:
+ DBG_8192C("[MPT], OPcode : [BT_GET_GENERAL]\n");
+ pBtRsp->paraLength = mptbt_BtGetGeneral(Adapter, pBtReq, pBtRsp);
+ break;
+ case BT_UP_OP_BT_TEST_CTRL:
+ DBG_8192C("[MPT], OPcode : [BT_TEST_CTRL]\n");
+ pBtRsp->paraLength = mptbt_BtTestCtrl(Adapter, pBtReq, pBtRsp);
+ break;
+ case BT_UP_OP_TEST_BT:
+ DBG_8192C("[MPT], OPcode : [TEST_BT]\n");
+ pBtRsp->paraLength = mptbt_TestBT(Adapter, pBtReq, pBtRsp);
+ break;
+ default:
+ DBG_8192C("[MPT], Error!! OPcode : UNDEFINED!!!!\n");
+ pBtRsp->status = BT_STATUS_UNKNOWN_OPCODE_U;
+ pBtRsp->paraLength = 0x0;
+ break;
+ }
+
+ DBG_8192C("pBtRsp->paraLength =%d \n",pBtRsp->paraLength);
+
+ pMptCtx->mptOutLen += pBtRsp->paraLength;
+
+ DBG_8192C("\n [MPT], OUT to DLL pMptCtx->mptOutLen=%d ,pBtRsp->paraLength =%d ",pMptCtx->mptOutLen,pBtRsp->paraLength);
+
+ DBG_8192C("\n [MPT], mptbt_BtControlProcess()<=========\n");
+}
+
+#endif
+
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_cmd.c b/drivers/net/wireless/rtl8723as/core/rtw_cmd.c index 75d1e766c698..5da4fb23be54 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_cmd.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_cmd.c @@ -182,6 +182,7 @@ _func_enter_; rtw_mfree(c2h, 16); } } + rtw_cbuf_free(pevtpriv->c2h_queue); #endif RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("-_rtw_free_evt_priv \n")); @@ -309,7 +310,7 @@ int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) #ifdef SUPPORT_HW_RFOFF_DETECTED //To decide allow or not - if( (pcmdpriv->padapter->pwrctrlpriv.bHWPwrPindetect) + if( (adapter_to_pwrctl(pcmdpriv->padapter)->bHWPwrPindetect) &&(!pcmdpriv->padapter->registrypriv.usbss_enable) ) { @@ -426,6 +427,18 @@ _func_enter_; _func_exit_; } + +void rtw_stop_cmd_thread(_adapter *adapter) +{ + if(adapter->cmdThread && adapter->cmdpriv.cmdthd_running == _TRUE + && adapter->cmdpriv.stop_req == 0) + { + adapter->cmdpriv.stop_req = 1; + _rtw_up_sema(&adapter->cmdpriv.cmd_queue_sema); + _rtw_down_sema(&adapter->cmdpriv.terminate_cmdthread_sema); + } +} + thread_return rtw_cmd_thread(thread_context context) { u8 ret; @@ -443,6 +456,7 @@ _func_enter_; pcmdbuf = pcmdpriv->cmd_buf; prspbuf = pcmdpriv->rsp_buf; + pcmdpriv->stop_req = 0; pcmdpriv->cmdthd_running=_TRUE; _rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema); @@ -450,16 +464,29 @@ _func_enter_; while(1) { - if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) + if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) { + DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break\n", FUNC_ADPT_ARG(padapter)); break; + } if ((padapter->bDriverStopped == _TRUE)||(padapter->bSurpriseRemoved == _TRUE)) { - DBG_871X("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", + DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); break; } + if (pcmdpriv->stop_req) { + DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req); + break; + } + + if(rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue))) + { + //DBG_871X("%s: cmd queue is empty!\n", __func__); + continue; + } + #ifdef CONFIG_LPS_LCLK if (rtw_register_cmd_alive(padapter) != _SUCCESS) { @@ -472,7 +499,7 @@ _func_enter_; _next: if ((padapter->bDriverStopped == _TRUE)||(padapter->bSurpriseRemoved== _TRUE)) { - DBG_871X("%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", + DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%d) SurpriseRemoved(%d) break at line %d\n", __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved, __LINE__); break; } @@ -774,7 +801,7 @@ _func_enter_; #ifdef CONFIG_STA_MODE_SCAN_UNDER_AP_MODE if((padapter->pbuddy_adapter->mlmeextpriv.mlmext_info.state&0x03) == WIFI_FW_AP_STATE) - _set_timer(&pmlmepriv->scan_to_timer, SURVEY_TO * ( 38 + ( 38 / RTW_SCAN_NUM_OF_CH ) * RTW_STAY_AP_CH_MILLISECOND ) + 1000 ); + _set_timer(&pmlmepriv->scan_to_timer, SURVEY_TO * ( padapter->mlmeextpriv.max_chan_nums + ( padapter->mlmeextpriv.max_chan_nums / RTW_SCAN_NUM_OF_CH ) * RTW_STAY_AP_CH_MILLISECOND ) + 1000 ); else #endif //CONFIG_STA_MODE_SCAN_UNDER_AP_MODE _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); @@ -1302,11 +1329,11 @@ _func_enter_; pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength); if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_TENDA) - padapter->pwrctrlpriv.smart_ps = 0; + adapter_to_pwrctl(padapter)->smart_ps = 0; else - padapter->pwrctrlpriv.smart_ps = padapter->registrypriv.smart_ps; + adapter_to_pwrctl(padapter)->smart_ps = padapter->registrypriv.smart_ps; - DBG_871X("%s: smart_ps=%d\n", __func__, padapter->pwrctrlpriv.smart_ps); + DBG_871X("%s: smart_ps=%d\n", __func__, adapter_to_pwrctl(padapter)->smart_ps); #if 0 psecuritypriv->supplicant_ie[0]=(u8)psecnetwork->IELength; @@ -1400,7 +1427,7 @@ _func_exit_; return res; } -u8 rtw_setopmode_cmd(_adapter *padapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype) +u8 rtw_setopmode_cmd(_adapter *padapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, bool enqueue) { struct cmd_obj* ph2c; struct setopmode_parm* psetop; @@ -1409,25 +1436,29 @@ u8 rtw_setopmode_cmd(_adapter *padapter, NDIS_802_11_NETWORK_INFRASTRUCTURE net u8 res=_SUCCESS; _func_enter_; - - ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); - if(ph2c==NULL){ - res= _FALSE; - goto exit; - } psetop = (struct setopmode_parm*)rtw_zmalloc(sizeof(struct setopmode_parm)); - if(psetop==NULL){ - rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj)); - res=_FALSE; + if(psetop==NULL){ + res=_FAIL; goto exit; } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); psetop->mode = (u8)networktype; + + if(enqueue){ + ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); + if(ph2c==NULL){ + rtw_mfree((u8 *)psetop, sizeof(*psetop)); + res= _FAIL; + goto exit; + } - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - + init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); + res = rtw_enqueue_cmd(pcmdpriv, ph2c); + } + else{ + setopmode_hdl(padapter, (u8 *)psetop); + rtw_mfree((u8 *)psetop, sizeof(*psetop)); + } exit: _func_exit_; @@ -1435,7 +1466,7 @@ _func_exit_; return res; } -u8 rtw_setstakey_cmd(_adapter *padapter, u8 *psta, u8 unicast_key) +u8 rtw_setstakey_cmd(_adapter *padapter, u8 *psta, u8 unicast_key, bool enqueue) { struct cmd_obj* ph2c; struct set_stakey_parm *psetstakey_para; @@ -1449,40 +1480,21 @@ u8 rtw_setstakey_cmd(_adapter *padapter, u8 *psta, u8 unicast_key) _func_enter_; - ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); - if ( ph2c == NULL){ - res= _FAIL; - goto exit; - } - psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm)); - if(psetstakey_para==NULL){ - rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj)); + if(psetstakey_para==NULL){ res=_FAIL; goto exit; } - - psetstakey_rsp = (struct set_stakey_rsp*)rtw_zmalloc(sizeof(struct set_stakey_rsp)); - if(psetstakey_rsp == NULL){ - rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj)); - rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm)); - res=_FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); - ph2c->rsp = (u8 *) psetstakey_rsp; - ph2c->rspsz = sizeof(struct set_stakey_rsp); - + _rtw_memcpy(psetstakey_para->addr, sta->hwaddr,ETH_ALEN); - + if(check_fwstate(pmlmepriv, WIFI_STATION_STATE)){ #ifdef CONFIG_TDLS if(sta->tdls_sta_state&TDLS_LINKED_STATE) psetstakey_para->algorithm=(u8)sta->dot118021XPrivacy; else #endif //CONFIG_TDLS - psetstakey_para->algorithm =(unsigned char) psecuritypriv->dot11PrivacyAlgrthm; + psetstakey_para->algorithm =(unsigned char) psecuritypriv->dot11PrivacyAlgrthm; }else{ GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE); } @@ -1494,15 +1506,40 @@ _func_enter_; else #endif //CONFIG_TDLS _rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16); - } else { + } + else { _rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16); - } + } //jeff: set this becasue at least sw key is ready padapter->securitypriv.busetkipkey=_TRUE; - res = rtw_enqueue_cmd(pcmdpriv, ph2c); + if(enqueue) + { + ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); + if ( ph2c == NULL){ + rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm)); + res= _FAIL; + goto exit; + } + psetstakey_rsp = (struct set_stakey_rsp*)rtw_zmalloc(sizeof(struct set_stakey_rsp)); + if(psetstakey_rsp == NULL){ + rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj)); + rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm)); + res=_FAIL; + goto exit; + } + + init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); + ph2c->rsp = (u8 *) psetstakey_rsp; + ph2c->rspsz = sizeof(struct set_stakey_rsp); + res = rtw_enqueue_cmd(pcmdpriv, ph2c); + } + else{ + set_stakey_hdl(padapter, (u8 *)psetstakey_para); + rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm)); + } exit: _func_exit_; @@ -1727,6 +1764,86 @@ _func_exit_; return res; } +//add for CONFIG_IEEE80211W, none 11w can use it +u8 rtw_reset_securitypriv_cmd(_adapter*padapter) +{ + struct cmd_obj* ph2c; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv=&padapter->cmdpriv; + u8 res=_SUCCESS; + +_func_enter_; + + ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); + if(ph2c==NULL){ + res= _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if(pdrvextra_cmd_parm==NULL){ + rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj)); + res= _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV; + pdrvextra_cmd_parm->type_size = 0; + pdrvextra_cmd_parm->pbuf = (u8 *)padapter; + + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + + + //rtw_enqueue_cmd(pcmdpriv, ph2c); + res = rtw_enqueue_cmd(pcmdpriv, ph2c); + +exit: + +_func_exit_; + + return res; + +} + +u8 rtw_free_assoc_resources_cmd(_adapter*padapter) +{ + struct cmd_obj* ph2c; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv=&padapter->cmdpriv; + u8 res=_SUCCESS; + +_func_enter_; + + ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); + if(ph2c==NULL){ + res= _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if(pdrvextra_cmd_parm==NULL){ + rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj)); + res= _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES; + pdrvextra_cmd_parm->type_size = 0; + pdrvextra_cmd_parm->pbuf = (u8 *)padapter; + + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + + + //rtw_enqueue_cmd(pcmdpriv, ph2c); + res = rtw_enqueue_cmd(pcmdpriv, ph2c); + +exit: + +_func_exit_; + + return res; + +} u8 rtw_dynamic_chk_wk_cmd(_adapter*padapter) { @@ -2007,12 +2124,60 @@ _func_exit_; return res; } +#ifdef CONFIG_DETECT_C2H_BY_POLLING +u8 rtw_event_polling_cmd(_adapter*padapter) +{ + struct cmd_obj* ph2c; + struct drvextra_cmd_parm *pdrvextra_cmd_parm; + struct cmd_priv *pcmdpriv=&padapter->cmdpriv; + u8 res=_SUCCESS; + +_func_enter_; + +#if defined(CONFIG_CONCURRENT_MODE) + if (padapter->adapter_type != PRIMARY_ADAPTER) + { + return _FAIL; + } +#endif + + ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); + if(ph2c==NULL){ + res= _FAIL; + goto exit; + } + + pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); + if(pdrvextra_cmd_parm==NULL){ + rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj)); + res= _FAIL; + goto exit; + } + + pdrvextra_cmd_parm->ec_id = EVENT_POLLING_CID; + pdrvextra_cmd_parm->type_size = 0; + pdrvextra_cmd_parm->pbuf = (u8 *)padapter; + + init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra)); + + + //rtw_enqueue_cmd(pcmdpriv, ph2c); + res = rtw_enqueue_cmd(pcmdpriv, ph2c); + +exit: + + _func_exit_; + + return res; +} +#endif + static void traffic_status_watchdog(_adapter *padapter) { #ifdef CONFIG_LPS u8 bEnterPS; #endif - u16 BusyThreshold = 100; + u16 BusyThreshold = 200;// 100; u8 bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE; u8 bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE; #ifdef CONFIG_FTP_PROTECT @@ -2023,23 +2188,19 @@ static void traffic_status_watchdog(_adapter *padapter) struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo); #endif //CONFIG_TDLS + RT_LINK_DETECT_T * link_detect = &pmlmepriv->LinkDetectInfo; + // // Determine if our traffic is busy now // if((check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) { - -#ifdef CONFIG_BT_COEXIST - if( pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 50 || - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 50 ) -#else // !CONFIG_BT_COEXIST // if we raise bBusyTraffic in last watchdog, using lower threshold. if (pmlmepriv->LinkDetectInfo.bBusyTraffic) - BusyThreshold = 75; + BusyThreshold =180; // 75; if( pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold || pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold ) -#endif // !CONFIG_BT_COEXIST { bBusyTraffic = _TRUE; @@ -2076,7 +2237,25 @@ static void traffic_status_watchdog(_adapter *padapter) rtw_unlock_suspend(); } #endif //CONFIG_KEEP_FTP_TRANSMIT - + +#ifdef CONFIG_TRAFFIC_PROTECT +#define TX_ACTIVE_TH 2 +#define RX_ACTIVE_TH 1 +#define TRAFFIC_PROTECT_PERIOD_MS 4500 + + if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH + || link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) { + + DBG_871X_LEVEL(_drv_info_, FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n", + FUNC_ADPT_ARG(padapter), + TRAFFIC_PROTECT_PERIOD_MS, + link_detect->NumTxOkInPeriod, + link_detect->NumRxUnicastOkInPeriod); + + rtw_lock_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS); + } +#endif + #ifdef CONFIG_TDLS #ifdef CONFIG_TDLS_AUTOSETUP if( ( ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD ) == 0 ) //10 * 2sec, periodically sending @@ -2176,7 +2355,7 @@ void dynamic_chk_wk_hdl(_adapter *padapter, u8 *pbuf, int sz) void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type); void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); u8 mstatus; @@ -2211,7 +2390,7 @@ _func_enter_; //DBG_871X("LPS_CTRL_CONNECT \n"); mstatus = 1;//connect // Reset LPS Setting - padapter->pwrctrlpriv.LpsIdleCount = 0; + pwrpriv->LpsIdleCount = 0; rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus)); #ifdef CONFIG_BT_COEXIST BT_WifiMediaStatusNotify(padapter, mstatus); @@ -2263,7 +2442,7 @@ u8 rtw_lps_ctrl_wk_cmd(_adapter*padapter, u8 lps_ctrl_type, u8 enqueue) struct cmd_obj *ph2c; struct drvextra_cmd_parm *pdrvextra_cmd_parm; struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - //struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; + //struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); u8 res = _SUCCESS; _func_enter_; @@ -2271,6 +2450,11 @@ _func_enter_; //if(!pwrctrlpriv->bLeisurePs) // return res; +#ifdef CONFIG_CONCURRENT_MODE + if (padapter->iface_type != IFACE_PORT0) + return res; +#endif + if(enqueue) { ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); @@ -2410,6 +2594,17 @@ void power_saving_wk_hdl(_adapter *padapter, u8 *pbuf, int sz) rtw_ps_processor(padapter); } +//add for CONFIG_IEEE80211W, none 11w can use it +void reset_securitypriv_hdl(_adapter *padapter) +{ + rtw_reset_securitypriv(padapter); +} + +void free_assoc_resources_hdl(_adapter *padapter) +{ + rtw_free_assoc_resources(padapter, 1); +} + #ifdef CONFIG_P2P u8 p2p_protocol_wk_cmd(_adapter*padapter, int intCmdType ) { @@ -2683,6 +2878,51 @@ static void c2h_wk_callback(_workitem *work) } #endif +#ifdef CONFIG_DETECT_C2H_BY_POLLING +void event_polling_hdl(_adapter *padapter, u8 *pbuf, int sz) +{ + c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(padapter); + u8 check_c2hcmd, check_ccx; + + //check_c2hcmd = rtw_read8(padapter, REG_C2HEVT_CLEAR); + //check_ccx= rtw_read8(padapter, REG_C2HEVT_MSG_NORMAL); + + rtw_hal_get_hwreg(padapter, HW_VAR_C2HEVT_CLEAR, (u8 *)(&check_c2hcmd)); + rtw_hal_get_hwreg(padapter, HW_VAR_C2HEVT_MSG_NORMAL, (u8 *)(&check_ccx)); + + if (check_c2hcmd != 0) + { + struct c2h_evt_hdr *c2h_evt; + + if (check_c2hcmd != 0xFF) + { + c2h_evt_clear(padapter); + } + else if (ccx_id_filter(check_ccx & 0x0F) == _FALSE) + { + if ((c2h_evt = (struct c2h_evt_hdr *)rtw_zmalloc(16)) != NULL) { + if (c2h_evt_read(padapter, (u8 *)c2h_evt) == _SUCCESS) { + rtw_hal_c2h_handler(padapter, c2h_evt); + } + rtw_mfree((u8*)c2h_evt, 16); + } else { + /* Error handling for malloc fail */ + if (rtw_cbuf_push(padapter->evtpriv.c2h_queue, (void*)NULL) != _SUCCESS) + DBG_871X("%s rtw_cbuf_push fail\n", __func__); + _set_workitem(&padapter->evtpriv.c2h_wk); + } + } + else + { + if (padapter->xmitpriv.ack_tx == _FALSE) + { + c2h_evt_clear(padapter); + } + } + } +} +#endif + u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf) { struct drvextra_cmd_parm *pdrvextra_cmd; @@ -2735,11 +2975,21 @@ u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf) intel_widi_wk_hdl(padapter, pdrvextra_cmd->type_size, pdrvextra_cmd->pbuf); break; #endif //CONFIG_INTEL_WIDI - + //add for CONFIG_IEEE80211W, none 11w can use it + case RESET_SECURITYPRIV: + reset_securitypriv_hdl(padapter); + break; + case FREE_ASSOC_RESOURCES: + free_assoc_resources_hdl(padapter); + break; case C2H_WK_CID: c2h_evt_hdl(padapter, (struct c2h_evt_hdr *)pdrvextra_cmd->pbuf, NULL); break; - +#ifdef CONFIG_DETECT_C2H_BY_POLLING + case EVENT_POLLING_CID: + event_polling_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type_size); + break; +#endif default: break; } diff --git a/drivers/net/wireless/rtl8723as/core/rtw_debug.c b/drivers/net/wireless/rtl8723as/core/rtw_debug.c index 509ed8106410..d2fc13c061b9 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_debug.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_debug.c @@ -76,6 +76,20 @@ int proc_get_drv_version(char *page, char **start, return len; } +#ifdef DBG_MEM_ALLOC +int proc_get_mstat(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + int len = 0; + + len += _rtw_mstat_dump(page+len, count-len); + *eof = 1; + + return len; +} +#endif /* DBG_MEM_ALLOC */ + int proc_get_write_reg(char *page, char **start, off_t offset, int count, int *eof, void *data) @@ -1121,6 +1135,31 @@ int proc_get_best_channel(char *page, char **start, return len; } + +int proc_set_best_channel(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + char tmp[32]; + + if(count < 1) + return -EFAULT; + + if(buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) + { + int i; + for(i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++) + { + pmlmeext->channel_set[i].rx_count = 0; + } + + DBG_871X("set %s\n", "Clean Best Channel Count"); + } + + return count; +} #endif /* CONFIG_FIND_BEST_CHANNEL */ #ifdef CONFIG_BT_COEXIST #define _bt_dbg_off_ 0 @@ -1214,5 +1253,118 @@ int proc_set_sreset(struct file *file, const char *buffer, unsigned long count, } #endif /* DBG_CONFIG_ERROR_DETECT */ +int proc_get_odm_dbg_comp(char *page, char **start, off_t offset, int count, int *eof, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + int len = 0; + + len += _rtw_odm_dbg_comp_msg(adapter, page, count); + + *eof = 1; + return len; +} + +int proc_set_odm_dbg_comp(struct file *file, const char *buffer, unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + + u64 dbg_comp; + + if (count < 1) + return -EFAULT; + + if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { + + int num = sscanf(tmp, "%llx", &dbg_comp); + + if (num != 1) + return count; + + rtw_odm_dbg_comp_set(adapter, dbg_comp); + } + + return count; +} + +int proc_get_odm_dbg_level(char *page, char **start, off_t offset, int count, int *eof, void *data) +{ + struct net_device *dev = data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + int len = 0; + + len += _rtw_odm_dbg_level_msg(adapter, page, count); + + *eof = 1; + return len; +} + +int proc_set_odm_dbg_level(struct file *file, const char *buffer, unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + _adapter *adapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + + u32 dbg_level; + + if (count < 1) + return -EFAULT; + + if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { + + int num = sscanf(tmp, "%u", &dbg_level); + + if (num != 1) + return count; + + rtw_odm_dbg_level_set(adapter, dbg_level); + } + + return count; +} + +int proc_get_odm_adaptivity(char *page, char **start, off_t offset, int count, int *eof, void *data) +{ + struct net_device *dev = data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + int len = 0; + + len += _rtw_odm_adaptivity_parm_msg(padapter, page, count); + + *eof = 1; + return len; +} + +int proc_set_odm_adaptivity(struct file *file, const char *buffer, unsigned long count, void *data) +{ + struct net_device *dev = (struct net_device *)data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); + char tmp[32]; + u32 TH_L2H_ini; + s8 TH_EDCCA_HL_diff; + u32 IGI_Base; + int ForceEDCCA; + u8 AdapEn_RSSI; + u8 IGI_LowerBound; + + if (count < 1) + return -EFAULT; + + if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { + + int num = sscanf(tmp, "%x %hhd %x %d %hhu %hhu", + &TH_L2H_ini, &TH_EDCCA_HL_diff, &IGI_Base, &ForceEDCCA, &AdapEn_RSSI, &IGI_LowerBound); + + if (num != 6) + return count; + + rtw_odm_adaptivity_parm_set(padapter, (s8)TH_L2H_ini, TH_EDCCA_HL_diff, (s8)IGI_Base, (bool)ForceEDCCA, AdapEn_RSSI, IGI_LowerBound); + } + + return count; +} + #endif diff --git a/drivers/net/wireless/rtl8723as/core/rtw_ieee80211.c b/drivers/net/wireless/rtl8723as/core/rtw_ieee80211.c index ea353d4cfe2a..af32123cbcc0 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_ieee80211.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_ieee80211.c @@ -886,6 +886,28 @@ u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen) return match; } +u8 *rtw_get_wps_ie_from_scan_queue(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen, u8 frame_type) +{ + u8* wps = NULL; + + DBG_871X( "[%s] frame_type = %d\n", __FUNCTION__, frame_type ); + switch( frame_type ) + { + case 1: + case 3: + { // Beacon or Probe Response + wps = rtw_get_wps_ie(in_ie + _PROBERSP_IE_OFFSET_, in_len - _PROBERSP_IE_OFFSET_, wps_ie, wps_ielen); + break; + } + case 2: + { // Probe Request + wps = rtw_get_wps_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , wps_ie, wps_ielen); + break; + } + } + return wps; +} + /** * rtw_get_wps_ie - Search WPS IE from a series of IEs * @in_ie: Address of IEs to search @@ -1331,32 +1353,37 @@ void rtw_macaddr_cfg(u8 *mac_addr) DBG_871X("rtw_macaddr_cfg MAC Address = "MAC_FMT"\n", MAC_ARG(mac_addr)); } -void dump_ies(u8 *buf, u32 buf_len) { +void dump_ies(u8 *buf, u32 buf_len) +{ u8* pos = (u8*)buf; u8 id, len; - + while(pos-buf<=buf_len){ id = *pos; len = *(pos+1); DBG_871X("%s ID:%u, LEN:%u\n", __FUNCTION__, id, len); + dump_wps_ie(pos, len); #ifdef CONFIG_P2P dump_p2p_ie(pos, len); + #ifdef CONFIG_WFD + dump_wfd_ie(pos, len); + #endif #endif - dump_wps_ie(pos, len); pos+=(2+len); - } + } } -void dump_wps_ie(u8 *ie, u32 ie_len) { +void dump_wps_ie(u8 *ie, u32 ie_len) +{ u8* pos = (u8*)ie; u16 id; u16 len; u8 *wps_ie; uint wps_ielen; - + wps_ie = rtw_get_wps_ie(ie, ie_len, NULL, &wps_ielen); if(wps_ie != ie || wps_ielen == 0) return; @@ -1369,10 +1396,81 @@ void dump_wps_ie(u8 *ie, u32 ie_len) { DBG_871X("%s ID:0x%04x, LEN:%u\n", __FUNCTION__, id, len); pos+=(4+len); - } + } } #ifdef CONFIG_P2P +/** + * rtw_get_p2p_merged_len - Get merged ie length from muitiple p2p ies. + * @in_ie: Pointer of the first p2p ie + * @in_len: Total len of muiltiple p2p ies + * Returns: Length of merged p2p ie length + */ +u32 rtw_get_p2p_merged_ies_len(u8 *in_ie, u32 in_len) +{ + PNDIS_802_11_VARIABLE_IEs pIE; + u8 OUI[4] = { 0x50, 0x6f, 0x9a, 0x09 }; + int i=0; + int j=0, len=0; + + while( i < in_len) + { + pIE = (PNDIS_802_11_VARIABLE_IEs)(in_ie+ i); + + if( pIE->ElementID == _VENDOR_SPECIFIC_IE_ && _rtw_memcmp(pIE->data, OUI, 4) ) + { + len += pIE->Length-4; // 4 is P2P OUI length, don't count it in this loop + } + + i += (pIE->Length + 2); + } + + return len + 4; // Append P2P OUI length at last. +} + +/** + * rtw_p2p_merge_ies - Merge muitiple p2p ies into one + * @in_ie: Pointer of the first p2p ie + * @in_len: Total len of muiltiple p2p ies + * @merge_ie: Pointer of merged ie + * Returns: Length of merged p2p ie + */ +int rtw_p2p_merge_ies(u8 *in_ie, u32 in_len, u8 *merge_ie) +{ + PNDIS_802_11_VARIABLE_IEs pIE; + u8 len = 0; + u8 OUI[4] = { 0x50, 0x6f, 0x9a, 0x09 }; + u8 ELOUI[6] = { 0xDD, 0x00, 0x50, 0x6f, 0x9a, 0x09 }; //EID;Len;OUI, Len would copy at the end of function + int i=0; + + if( merge_ie != NULL) + { + //Set first P2P OUI + _rtw_memcpy(merge_ie, ELOUI, 6); + merge_ie += 6; + + while( i < in_len) + { + pIE = (PNDIS_802_11_VARIABLE_IEs)(in_ie+ i); + + // Take out the rest of P2P OUIs + if( pIE->ElementID == _VENDOR_SPECIFIC_IE_ && _rtw_memcmp(pIE->data, OUI, 4) ) + { + _rtw_memcpy( merge_ie, pIE->data +4, pIE->Length -4); + len += pIE->Length-4; + merge_ie += pIE->Length-4; + } + + i += (pIE->Length + 2); + } + + return len + 4; // 4 is for P2P OUI + + } + + return 0; +} + void dump_p2p_ie(u8 *ie, u32 ie_len) { u8* pos = (u8*)ie; u8 id; @@ -1396,6 +1494,28 @@ void dump_p2p_ie(u8 *ie, u32 ie_len) { } } +u8 *rtw_get_p2p_ie_from_scan_queue(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen, u8 frame_type) +{ + u8* p2p = NULL; + + DBG_871X( "[%s] frame_type = %d\n", __FUNCTION__, frame_type ); + switch( frame_type ) + { + case 1: + case 3: + { // Beacon or Probe Response + p2p = rtw_get_p2p_ie(in_ie + _PROBERSP_IE_OFFSET_, in_len - _PROBERSP_IE_OFFSET_, p2p_ie, p2p_ielen); + break; + } + case 2: + { // Probe Request + p2p = rtw_get_p2p_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , p2p_ie, p2p_ielen); + break; + } + } + return p2p; +} + /** * rtw_get_p2p_ie - Search P2P IE from a series of IEs * @in_ie: Address of IEs to search @@ -1640,6 +1760,29 @@ void rtw_WLAN_BSSID_EX_remove_p2p_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id) #endif //CONFIG_P2P #ifdef CONFIG_WFD +void dump_wfd_ie(u8 *ie, u32 ie_len) +{ + u8* pos = (u8*)ie; + u8 id; + u16 len; + + u8 *wfd_ie; + uint wfd_ielen; + + if(rtw_get_wfd_ie(ie, ie_len, NULL, &wfd_ielen) == _FALSE) + return; + + pos+=6; + while(pos-ie < ie_len){ + id = *pos; + len = RTW_GET_BE16(pos+1); + + DBG_871X("%s ID:%u, LEN:%u\n", __FUNCTION__, id, len); + + pos+=(3+len); + } +} + int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen) { int match; @@ -1699,6 +1842,30 @@ int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen) } +int rtw_get_wfd_ie_from_scan_queue(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen, u8 frame_type) +{ + int match; + + match=_FALSE; + + DBG_871X( "[%s] frame_type = %d\n", __FUNCTION__, frame_type ); + switch( frame_type ) + { + case 1: + case 3: + { // Beacon or Probe Response + match = rtw_get_wfd_ie(in_ie + _PROBERSP_IE_OFFSET_, in_len - _PROBERSP_IE_OFFSET_, wfd_ie, wfd_ielen); + break; + } + case 2: + { // Probe Request + match = rtw_get_wfd_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , wfd_ie, wfd_ielen); + break; + } + } + return match; +} + // attr_content: The output buffer, contains the "body field" of WFD attribute. // attr_contentlen: The data length of the "body field" of WFD attribute. int rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id ,u8 *attr_content, uint *attr_contentlen) diff --git a/drivers/net/wireless/rtl8723as/core/rtw_io.c b/drivers/net/wireless/rtl8723as/core/rtw_io.c index 83cd2fbbd395..26797830ffc3 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_io.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_io.c @@ -384,6 +384,32 @@ int rtw_init_io_priv(_adapter *padapter, void (*set_intf_ops)(struct _io_ops *po return _SUCCESS; } +/* +* Increase and check if the continual_io_error of this @param dvobjprive is larger than MAX_CONTINUAL_IO_ERR +* @return _TRUE: +* @return _FALSE: +*/ +int rtw_inc_and_chk_continual_io_error(struct dvobj_priv *dvobj) +{ + int ret = _FALSE; + int value; + if( (value=ATOMIC_INC_RETURN(&dvobj->continual_io_error)) > MAX_CONTINUAL_IO_ERR) { + DBG_871X("[dvobj:%p][ERROR] continual_io_error:%d > %d\n", dvobj, value, MAX_CONTINUAL_IO_ERR); + ret = _TRUE; + } else { + //DBG_871X("[dvobj:%p] continual_io_error:%d\n", dvobj, value); + } + return ret; +} + +/* +* Set the continual_io_error of this @param dvobjprive to 0 +*/ +void rtw_reset_continual_io_error(struct dvobj_priv *dvobj) +{ + ATOMIC_SET(&dvobj->continual_io_error, 0); +} + #ifdef DBG_IO u16 read_sniff_ranges[][2] = { diff --git a/drivers/net/wireless/rtl8723as/core/rtw_ioctl_set.c b/drivers/net/wireless/rtl8723as/core/rtw_ioctl_set.c index 4df2e4e19425..d2d07d7ef386 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_ioctl_set.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_ioctl_set.c @@ -47,6 +47,20 @@ extern void indicate_wx_scan_complete_event(_adapter *padapter); (addr[4] == 0xff) && (addr[5] == 0xff) ) ? _TRUE : _FALSE \ ) +u8 rtw_validate_bssid(u8 *bssid) +{ + u8 ret = _TRUE; + + if (is_zero_mac_addr(bssid) + || is_broadcast_mac_addr(bssid) + || is_multicast_mac_addr(bssid) + ) { + ret = _FALSE; + } + + return ret; +} + u8 rtw_validate_ssid(NDIS_802_11_SSID *ssid) { u8 i; @@ -60,6 +74,7 @@ _func_enter_; goto exit; } +#ifdef CONFIG_VALIDATE_SSID for(i = 0; i < ssid->SsidLength; i++) { //wifi, printable ascii code must be supported @@ -69,6 +84,7 @@ _func_enter_; break; } } +#endif /* CONFIG_VALIDATE_SSID */ exit: @@ -374,24 +390,10 @@ _func_enter_; } handle_tkip_countermeasure: - //should we add something here...? - -#ifdef PLATFORM_LINUX - if (padapter->securitypriv.btkip_countermeasure == _TRUE) { - cur_time = rtw_get_current_time(); - - if( (cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ ) - { - padapter->securitypriv.btkip_countermeasure = _FALSE; - padapter->securitypriv.btkip_countermeasure_time = 0; - } - else - { - status = _FAIL; - goto release_mlme_lock; - } + if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { + status = _FAIL; + goto release_mlme_lock; } -#endif _rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); pmlmepriv->assoc_by_bssid=_TRUE; @@ -506,56 +508,15 @@ _func_enter_; } handle_tkip_countermeasure: -#ifdef PLATFORM_WINDOWS - if (padapter->securitypriv.btkip_countermeasure==_TRUE) - { - LARGE_INTEGER sys_time; - u32 diff_time,cur_time ; - RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_ssid:padapter->securitypriv.btkip_countermeasure==_TRUE\n")); - NdisGetCurrentSystemTime(&sys_time); - cur_time=(u32)(sys_time.QuadPart/10); // In micro-second. - RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_ssid:cur_time=0x%x\n",cur_time)); - RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_ssid:psecuritypriv->last_mic_err_time=0x%x\n",padapter->securitypriv.btkip_countermeasure_time)); - diff_time = cur_time -padapter->securitypriv.btkip_countermeasure_time; // In micro-second. - RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_ssid:diff_time=0x%x\n",diff_time)); - - if (diff_time > 60000000) { - RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_ssid(): countermeasure time >60s.\n")); - padapter->securitypriv.btkip_countermeasure=_FALSE; - // Update MIC error time. - padapter->securitypriv.btkip_countermeasure_time=0; - } else { - // can't join in 60 seconds. - status = _FAIL; - RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_ssid(): countermeasure time <60s.\n")); - goto release_mlme_lock; - } - } -#endif - -#ifdef PLATFORM_LINUX - if (padapter->securitypriv.btkip_countermeasure == _TRUE) { - cur_time = rtw_get_current_time(); - - if( (cur_time - padapter->securitypriv.btkip_countermeasure_time) > 60 * HZ ) - { - padapter->securitypriv.btkip_countermeasure = _FALSE; - padapter->securitypriv.btkip_countermeasure_time = 0; - } - else - { - status = _FAIL; - goto release_mlme_lock; - } + if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { + status = _FAIL; + goto release_mlme_lock; } -#endif - #ifdef CONFIG_VALIDATE_SSID if (rtw_validate_ssid(ssid) == _FALSE) { status = _FAIL; goto release_mlme_lock; } - #endif _rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID)); pmlmepriv->assoc_by_bssid=_FALSE; @@ -580,6 +541,79 @@ _func_exit_; } +u8 rtw_set_802_11_connect(_adapter* padapter, u8 *bssid, NDIS_802_11_SSID *ssid) +{ + _irqL irqL; + u8 status = _SUCCESS; + u32 cur_time = 0; + bool bssid_valid = _TRUE; + bool ssid_valid = _TRUE; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + +_func_enter_; + + if (!ssid || rtw_validate_ssid(ssid) == _FALSE) + ssid_valid = _FALSE; + + if (!bssid || rtw_validate_bssid(bssid) == _FALSE) + bssid_valid = _FALSE; + + if (ssid_valid == _FALSE && bssid_valid == _FALSE) { + DBG_871X(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n", + FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid); + status = _FAIL; + goto exit; + } + + if(padapter->hw_init_completed==_FALSE){ + RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, + ("set_ssid: hw_init_completed==_FALSE=>exit!!!\n")); + status = _FAIL; + goto exit; + } + + _enter_critical_bh(&pmlmepriv->lock, &irqL); + + DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" fw_state=0x%08x\n", + FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv)); + + if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { + goto handle_tkip_countermeasure; + } else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) { + goto release_mlme_lock; + } + +handle_tkip_countermeasure: + if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) { + status = _FAIL; + goto release_mlme_lock; + } + + if (ssid && ssid_valid) + _rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID)); + + if (bssid && bssid_valid) { + _rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN); + pmlmepriv->assoc_by_bssid = _TRUE; + } + + if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) { + pmlmepriv->to_join = _TRUE; + } + else { + status = rtw_do_join(padapter); + } + +release_mlme_lock: + _exit_critical_bh(&pmlmepriv->lock, &irqL); + +exit: + +_func_exit_; + + return status; +} + u8 rtw_set_802_11_infrastructure_mode(_adapter* padapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype) { @@ -683,7 +717,8 @@ _func_enter_; rtw_disassoc_cmd(padapter, 0, _TRUE); rtw_indicate_disconnect(padapter); - rtw_free_assoc_resources(padapter, 1); + //modify for CONFIG_IEEE80211W, none 11w can use it + rtw_free_assoc_resources_cmd(padapter); rtw_pwr_wakeup(padapter); } @@ -832,7 +867,7 @@ _func_enter_; psecuritypriv->dot11DefKey[keyid].skey[9],psecuritypriv->dot11DefKey[keyid].skey[10],psecuritypriv->dot11DefKey[keyid].skey[11], psecuritypriv->dot11DefKey[keyid].skey[12])); - res=rtw_set_key(padapter,psecuritypriv, keyid, 1); + res=rtw_set_key(padapter,psecuritypriv, keyid, 1,_TRUE); if(res==_FAIL) ret= _FALSE; @@ -864,7 +899,7 @@ _func_enter_; _rtw_memset(&psecuritypriv->dot11DefKey[keyindex], 0, 16); - res=rtw_set_key(padapter,psecuritypriv,keyindex, 0); + res=rtw_set_key(padapter,psecuritypriv,keyindex, 0,_TRUE); psecuritypriv->dot11DefKeylen[keyindex]=0; @@ -1180,7 +1215,7 @@ _func_enter_; RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("reset group key")); - res=rtw_set_key(padapter,&padapter->securitypriv, key->KeyIndex, 1); + res=rtw_set_key(padapter,&padapter->securitypriv, key->KeyIndex, 1,_TRUE); if(res==_FAIL) ret= _FAIL; @@ -1230,11 +1265,11 @@ _func_enter_; //Set key to CAM through H2C command if(bgrouptkey)//never go to here { - res=rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, _FALSE); + res=rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, _FALSE, _TRUE); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(group)\n")); } else{ - res=rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, _TRUE); + res=rtw_setstakey_cmd(padapter, (unsigned char *)stainfo, _TRUE, _TRUE); RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(unicast)\n")); } @@ -1441,6 +1476,8 @@ int rtw_set_country(_adapter *adapter, const char *country_code) channel_plan = RT_CHANNEL_DOMAIN_MKK; else if(0 == strcmp(country_code, "CN")) channel_plan = RT_CHANNEL_DOMAIN_CHINA; + else if(0 == strcmp(country_code, "IN")) + channel_plan = RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN; else DBG_871X("%s unknown country_code:%s\n", __FUNCTION__, country_code); diff --git a/drivers/net/wireless/rtl8723as/core/rtw_led.c b/drivers/net/wireless/rtl8723as/core/rtw_led.c index f8de4329ff45..7710f324c3a0 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_led.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_led.c @@ -1,2422 +1,2422 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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, USA - * - * - ******************************************************************************/ - -#include <drv_types.h> - -// -// Description: -// Callback function of LED BlinkTimer, -// it just schedules to corresponding BlinkWorkItem/led_blink_hdl -// -void BlinkTimerCallback(void *data) -{ - PLED_871x pLed = (PLED_871x)data; - _adapter *padapter = pLed->padapter; - - //DBG_871X("%s\n", __FUNCTION__); - - if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE)) - { - //DBG_871X("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->bDriverStopped); - return; - } - -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) - #ifdef CONFIG_LED_HANDLED_BY_CMD_THREAD - rtw_led_blink_cmd(padapter, pLed); - #else - _set_workitem(&(pLed->BlinkWorkItem)); - #endif -#elif defined(CONFIG_PCI_HCI) - BlinkHandler(pLed); -#endif - -} - -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) -// -// Description: -// Callback function of LED BlinkWorkItem. -// We dispatch acture LED blink action according to LedStrategy. -// -void BlinkWorkItemCallback(struct work_struct *work) -{ - PLED_871x pLed = container_of(work, LED_871x, BlinkWorkItem); - BlinkHandler(pLed); -} -#endif - -// -// Description: -// Reset status of LED_871x object. -// -void ResetLedStatus(PLED_871x pLed) { - - pLed->CurrLedState = RTW_LED_OFF; // Current LED state. - pLed->bLedOn = _FALSE; // true if LED is ON, false if LED is OFF. - - pLed->bLedBlinkInProgress = _FALSE; // true if it is blinking, false o.w.. - pLed->bLedWPSBlinkInProgress = _FALSE; - - pLed->BlinkTimes = 0; // Number of times to toggle led state for blinking. - pLed->BlinkingLedState = LED_UNKNOWN; // Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are. - -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) - pLed->bLedNoLinkBlinkInProgress = _FALSE; - pLed->bLedLinkBlinkInProgress = _FALSE; - pLed->bLedStartToLinkBlinkInProgress = _FALSE; - pLed->bLedScanBlinkInProgress = _FALSE; -#endif -} - - // -// Description: -// Initialize an LED_871x object. -// -void -InitLed871x( - _adapter *padapter, - PLED_871x pLed, - LED_PIN_871x LedPin - ) -{ - pLed->padapter = padapter; - pLed->LedPin = LedPin; - - ResetLedStatus(pLed); - - _init_timer(&(pLed->BlinkTimer), padapter->pnetdev, BlinkTimerCallback, pLed); - -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) - _init_workitem(&(pLed->BlinkWorkItem), BlinkWorkItemCallback, pLed); -#endif -} - - -// -// Description: -// DeInitialize an LED_871x object. -// -void -DeInitLed871x( - PLED_871x pLed - ) -{ -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) - _cancel_workitem_sync(&(pLed->BlinkWorkItem)); -#endif - _cancel_timer_ex(&(pLed->BlinkTimer)); - ResetLedStatus(pLed); -} - - -// -// Description: -// Implementation of LED blinking behavior. -// It toggle off LED and schedule corresponding timer if necessary. -// -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) - -void SwLedOn(_adapter *padapter, PLED_871x pLed); -void SwLedOff(_adapter *padapter, PLED_871x pLed); - -#define CONFIG_LED_REMOVE_HAL - -void -SwLedBlink( - PLED_871x pLed - ) -{ - _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u8 bStopBlinking = _FALSE; - - // Change LED according to BlinkingLedState specified. - if( pLed->BlinkingLedState == RTW_LED_ON ) - { - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } - else - { - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,( "Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } - - // Determine if we shall change LED state again. - pLed->BlinkTimes--; - switch(pLed->CurrLedState) - { - - case LED_BLINK_NORMAL: - if(pLed->BlinkTimes == 0) - { - bStopBlinking = _TRUE; - } - break; - - case LED_BLINK_StartToBlink: - if( check_fwstate(pmlmepriv, _FW_LINKED) && check_fwstate(pmlmepriv, WIFI_STATION_STATE) ) - { - bStopBlinking = _TRUE; - } - if( check_fwstate(pmlmepriv, _FW_LINKED) && - (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ) - { - bStopBlinking = _TRUE; - } - else if(pLed->BlinkTimes == 0) - { - bStopBlinking = _TRUE; - } - break; - - case LED_BLINK_WPS: - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - break; - - - default: - bStopBlinking = _TRUE; - break; - - } - - if(bStopBlinking) - { - //if( padapter->pwrctrlpriv.cpwm >= PS_STATE_S2) - if(0) - { - SwLedOff(padapter, pLed); - } - else if( (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) && (pLed->bLedOn == _FALSE)) - { - SwLedOn(padapter, pLed); - } - else if( (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) && pLed->bLedOn == _TRUE) - { - SwLedOff(padapter, pLed); - } - - pLed->BlinkTimes = 0; - pLed->bLedBlinkInProgress = _FALSE; - } - else - { - // Assign LED state to toggle. - if( pLed->BlinkingLedState == RTW_LED_ON ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - - // Schedule a timer to toggle LED state. - switch( pLed->CurrLedState ) - { - case LED_BLINK_NORMAL: - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - break; - - case LED_BLINK_SLOWLY: - case LED_BLINK_StartToBlink: - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); - break; - - case LED_BLINK_WPS: - { - if( pLed->BlinkingLedState == RTW_LED_ON ) - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); - else - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); - } - break; - - default: - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); - break; - } - } -} - -void -SwLedBlink1( - PLED_871x pLed - ) -{ - _adapter *padapter = pLed->padapter; -#ifndef CONFIG_LED_REMOVE_HAL - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); -#endif - struct led_priv *ledpriv = &(padapter->ledpriv); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - PLED_871x pLed1 = &(ledpriv->SwLed1); - u8 bStopBlinking = _FALSE; - -#ifndef CONFIG_LED_REMOVE_HAL - if(pHalData->EEPROMCustomerID == RT_CID_819x_CAMEO) - pLed = &(ledpriv->SwLed1); -#endif - - // Change LED according to BlinkingLedState specified. - if( pLed->BlinkingLedState == RTW_LED_ON ) - { - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,( "Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } - else - { - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } - -#ifndef CONFIG_LED_REMOVE_HAL - if(pHalData->EEPROMCustomerID == RT_CID_DEFAULT) - { - if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) - { - if(!pLed1->bSWLedCtrl) - { - SwLedOn(padapter, pLed1); - pLed1->bSWLedCtrl = _TRUE; - } - else if(!pLed1->bLedOn) - SwLedOn(padapter, pLed1); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (): turn on pLed1\n")); - } - else - { - if(!pLed1->bSWLedCtrl) - { - SwLedOff(padapter, pLed1); - pLed1->bSWLedCtrl = _TRUE; - } - else if(pLed1->bLedOn) - SwLedOff(padapter, pLed1); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (): turn off pLed1\n")); - } - } - -#endif - - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - ResetLedStatus(pLed); - return; - } - - switch(pLed->CurrLedState) - { - case LED_BLINK_SLOWLY: - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - break; - - case LED_BLINK_NORMAL: - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); - break; - - case LED_BLINK_SCAN: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - - if(bStopBlinking) - { - if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) - { - pLed->bLedLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_NORMAL; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE) - { - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - pLed->bLedScanBlinkInProgress = _FALSE; - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - case LED_BLINK_TXRX: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - if(bStopBlinking) - { - if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) - { - pLed->bLedLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_NORMAL; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE) - { - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - pLed->BlinkTimes = 0; - pLed->bLedBlinkInProgress = _FALSE; - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - break; - - case LED_BLINK_WPS: - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - break; - - case LED_BLINK_WPS_STOP: //WPS success - if(pLed->BlinkingLedState == RTW_LED_ON) - bStopBlinking = _FALSE; - else - bStopBlinking = _TRUE; - - if(bStopBlinking) - { - pLed->bLedLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_NORMAL; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - - pLed->bLedWPSBlinkInProgress = _FALSE; - } - else - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); - } - break; - - default: - break; - } - -} - -void -SwLedBlink2( - PLED_871x pLed - ) -{ - _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u8 bStopBlinking = _FALSE; - - // Change LED according to BlinkingLedState specified. - if( pLed->BlinkingLedState == RTW_LED_ON) - { - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } - else - { - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } - - switch(pLed->CurrLedState) - { - case LED_BLINK_SCAN: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) - { - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop scan blink CurrLedState %d\n", pLed->CurrLedState)); - - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop scan blink CurrLedState %d\n", pLed->CurrLedState)); - } - pLed->bLedScanBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - } - break; - - case LED_BLINK_TXRX: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) - { - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop CurrLedState %d\n", pLed->CurrLedState)); - - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop CurrLedState %d\n", pLed->CurrLedState)); - } - pLed->bLedBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - } - break; - - default: - break; - } - -} - -void -SwLedBlink3( - PLED_871x pLed - ) -{ - _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u8 bStopBlinking = _FALSE; - - // Change LED according to BlinkingLedState specified. - if( pLed->BlinkingLedState == RTW_LED_ON ) - { - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } - else - { - if(pLed->CurrLedState != LED_BLINK_WPS_STOP) - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } - - switch(pLed->CurrLedState) - { - case LED_BLINK_SCAN: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) - { - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - if( !pLed->bLedOn ) - SwLedOn(padapter, pLed); - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - if( pLed->bLedOn ) - SwLedOff(padapter, pLed); - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - pLed->bLedScanBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - } - break; - - case LED_BLINK_TXRX: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) - { - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - - if( !pLed->bLedOn ) - SwLedOn(padapter, pLed); - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - - if( pLed->bLedOn ) - SwLedOff(padapter, pLed); - - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - pLed->bLedBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - } - break; - - case LED_BLINK_WPS: - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - break; - - case LED_BLINK_WPS_STOP: //WPS success - if(pLed->BlinkingLedState == RTW_LED_ON) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); - bStopBlinking = _FALSE; - } - else - { - bStopBlinking = _TRUE; - } - - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on ) - { - SwLedOff(padapter, pLed); - } - else - { - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - pLed->bLedWPSBlinkInProgress = _FALSE; - } - break; - - - default: - break; - } - -} - - -void -SwLedBlink4( - PLED_871x pLed - ) -{ - _adapter *padapter = pLed->padapter; - struct led_priv *ledpriv = &(padapter->ledpriv); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - PLED_871x pLed1 = &(ledpriv->SwLed1); - u8 bStopBlinking = _FALSE; - - // Change LED according to BlinkingLedState specified. - if( pLed->BlinkingLedState == RTW_LED_ON ) - { - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } - else - { - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } - - if(!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN) - { - pLed1->BlinkingLedState = RTW_LED_OFF; - pLed1->CurrLedState = RTW_LED_OFF; - SwLedOff(padapter, pLed1); - } - - switch(pLed->CurrLedState) - { - case LED_BLINK_SLOWLY: - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - break; - - case LED_BLINK_StartToBlink: - if( pLed->bLedOn ) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); - } - else - { - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - } - break; - - case LED_BLINK_SCAN: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _FALSE; - } - - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - SwLedOff(padapter, pLed); - } - else - { - pLed->bLedNoLinkBlinkInProgress = _FALSE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - } - pLed->bLedScanBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - } - break; - - case LED_BLINK_TXRX: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - SwLedOff(padapter, pLed); - } - else - { - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - } - pLed->bLedBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - } - break; - - case LED_BLINK_WPS: - if( pLed->bLedOn ) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); - } - else - { - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - } - break; - - case LED_BLINK_WPS_STOP: //WPS authentication fail - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - break; - - case LED_BLINK_WPS_STOP_OVERLAP: //WPS session overlap - pLed->BlinkTimes--; - if(pLed->BlinkTimes == 0) - { - if(pLed->bLedOn) - { - pLed->BlinkTimes = 1; - } - else - { - bStopBlinking = _TRUE; - } - } - - if(bStopBlinking) - { - pLed->BlinkTimes = 10; - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - } - break; - - - default: - break; - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("SwLedBlink4 CurrLedState %d\n", pLed->CurrLedState)); - - -} - -void -SwLedBlink5( - PLED_871x pLed - ) -{ - _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u8 bStopBlinking = _FALSE; - - // Change LED according to BlinkingLedState specified. - if( pLed->BlinkingLedState == RTW_LED_ON ) - { - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } - else - { - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } - - switch(pLed->CurrLedState) - { - case LED_BLINK_SCAN: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - if(pLed->bLedOn) - SwLedOff(padapter, pLed); - } - else - { pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - if(!pLed->bLedOn) - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - - pLed->bLedScanBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - } - break; - - - case LED_BLINK_TXRX: - pLed->BlinkTimes--; - if( pLed->BlinkTimes == 0 ) - { - bStopBlinking = _TRUE; - } - - if(bStopBlinking) - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - if(pLed->bLedOn) - SwLedOff(padapter, pLed); - } - else - { - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - if(!pLed->bLedOn) - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - - pLed->bLedBlinkInProgress = _FALSE; - } - else - { - if( padapter->pwrctrlpriv.rf_pwrstate != rf_on && padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) - { - SwLedOff(padapter, pLed); - } - else - { - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - } - break; - - default: - break; - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("SwLedBlink5 CurrLedState %d\n", pLed->CurrLedState)); - - -} - -void -SwLedBlink6( - PLED_871x pLed - ) -{ - _adapter *padapter = pLed->padapter; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u8 bStopBlinking = _FALSE; - - // Change LED according to BlinkingLedState specified. - if( pLed->BlinkingLedState == RTW_LED_ON ) - { - SwLedOn(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes)); - } - else - { - SwLedOff(padapter, pLed); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes)); - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("<==== blink6\n")); -} - -static void -SwLedControlMode0( - _adapter *padapter, - LED_CTL_MODE LedAction -) -{ - struct led_priv *ledpriv = &(padapter->ledpriv); - PLED_871x pLed = &(ledpriv->SwLed1); - - // Decide led state - switch(LedAction) - { - case LED_CTL_TX: - case LED_CTL_RX: - if( pLed->bLedBlinkInProgress == _FALSE ) - { - pLed->bLedBlinkInProgress = _TRUE; - - pLed->CurrLedState = LED_BLINK_NORMAL; - pLed->BlinkTimes = 2; - - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - } - break; - - case LED_CTL_START_TO_LINK: - if( pLed->bLedBlinkInProgress == _FALSE ) - { - pLed->bLedBlinkInProgress = _TRUE; - - pLed->CurrLedState = LED_BLINK_StartToBlink; - pLed->BlinkTimes = 24; - - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); - } - else - { - pLed->CurrLedState = LED_BLINK_StartToBlink; - } - break; - - case LED_CTL_LINK: - pLed->CurrLedState = RTW_LED_ON; - if( pLed->bLedBlinkInProgress == _FALSE ) - { - SwLedOn(padapter, pLed); - } - break; - - case LED_CTL_NO_LINK: - pLed->CurrLedState = RTW_LED_OFF; - if( pLed->bLedBlinkInProgress == _FALSE ) - { - SwLedOff(padapter, pLed); - } - break; - - case LED_CTL_POWER_OFF: - pLed->CurrLedState = RTW_LED_OFF; - if(pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - SwLedOff(padapter, pLed); - break; - - case LED_CTL_START_WPS: - if( pLed->bLedBlinkInProgress == _FALSE || pLed->CurrLedState == RTW_LED_ON) - { - pLed->bLedBlinkInProgress = _TRUE; - - pLed->CurrLedState = LED_BLINK_WPS; - pLed->BlinkTimes = 20; - - if( pLed->bLedOn ) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); - } - else - { - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL); - } - } - break; - - case LED_CTL_STOP_WPS: - if(pLed->bLedBlinkInProgress) - { - pLed->CurrLedState = RTW_LED_OFF; - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - break; - - - default: - break; - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState)); - -} - - //ALPHA, added by chiyoko, 20090106 -static void -SwLedControlMode1( - _adapter *padapter, - LED_CTL_MODE LedAction -) -{ -#ifndef CONFIG_LED_REMOVE_HAL - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); -#endif - struct led_priv *ledpriv = &(padapter->ledpriv); - PLED_871x pLed = &(ledpriv->SwLed0); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - -#ifndef CONFIG_LED_REMOVE_HAL - if(pHalData->EEPROMCustomerID == RT_CID_819x_CAMEO) - pLed = &(ledpriv->SwLed1); -#endif - - switch(LedAction) - { - case LED_CTL_POWER_ON: - case LED_CTL_START_TO_LINK: - case LED_CTL_NO_LINK: - if( pLed->bLedNoLinkBlinkInProgress == _FALSE ) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - if( pLed->bLedLinkBlinkInProgress == _TRUE ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedLinkBlinkInProgress = _FALSE; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - } - break; - - case LED_CTL_LINK: - if( pLed->bLedLinkBlinkInProgress == _FALSE ) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - pLed->bLedLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_NORMAL; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA); - } - break; - - case LED_CTL_SITE_SURVEY: - if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)) - ; - else if(pLed->bLedScanBlinkInProgress ==_FALSE) - { - if(IS_LED_WPS_BLINKING(pLed)) - return; - - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedLinkBlinkInProgress == _TRUE ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedLinkBlinkInProgress = _FALSE; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - pLed->bLedScanBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SCAN; - pLed->BlinkTimes = 24; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - case LED_CTL_TX: - case LED_CTL_RX: - if(pLed->bLedBlinkInProgress ==_FALSE) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedLinkBlinkInProgress == _TRUE ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedLinkBlinkInProgress = _FALSE; - } - pLed->bLedBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_TXRX; - pLed->BlinkTimes = 2; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - break; - - case LED_CTL_START_WPS: //wait until xinpin finish - case LED_CTL_START_WPS_BOTTON: - if(pLed->bLedWPSBlinkInProgress ==_FALSE) - { - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedLinkBlinkInProgress == _TRUE ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedLinkBlinkInProgress = _FALSE; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if(pLed->bLedScanBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - pLed->bLedWPSBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_WPS; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - - case LED_CTL_STOP_WPS: - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedLinkBlinkInProgress == _TRUE ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedLinkBlinkInProgress = _FALSE; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if(pLed->bLedScanBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - if(pLed->bLedWPSBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - } - else - { - pLed->bLedWPSBlinkInProgress = _TRUE; - } - - pLed->CurrLedState = LED_BLINK_WPS_STOP; - if(pLed->bLedOn) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); - } - else - { - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), 0); - } - break; - - case LED_CTL_STOP_WPS_FAIL: - if(pLed->bLedWPSBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - break; - - case LED_CTL_POWER_OFF: - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - if( pLed->bLedNoLinkBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedLinkBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if( pLed->bLedWPSBlinkInProgress ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - if( pLed->bLedScanBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - - SwLedOff(padapter, pLed); - break; - - default: - break; - - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState)); -} - - //Arcadyan/Sitecom , added by chiyoko, 20090216 -static void -SwLedControlMode2( - _adapter *padapter, - LED_CTL_MODE LedAction -) -{ - struct led_priv *ledpriv = &(padapter->ledpriv); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - PLED_871x pLed = &(ledpriv->SwLed0); - - switch(LedAction) - { - case LED_CTL_SITE_SURVEY: - if(pmlmepriv->LinkDetectInfo.bBusyTraffic) - ; - else if(pLed->bLedScanBlinkInProgress ==_FALSE) - { - if(IS_LED_WPS_BLINKING(pLed)) - return; - - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - pLed->bLedScanBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SCAN; - pLed->BlinkTimes = 24; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - case LED_CTL_TX: - case LED_CTL_RX: - if((pLed->bLedBlinkInProgress ==_FALSE) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - - pLed->bLedBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_TXRX; - pLed->BlinkTimes = 2; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - break; - - case LED_CTL_LINK: - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - if( pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if( pLed->bLedScanBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - - _set_timer(&(pLed->BlinkTimer), 0); - break; - - case LED_CTL_START_WPS: //wait until xinpin finish - case LED_CTL_START_WPS_BOTTON: - if(pLed->bLedWPSBlinkInProgress ==_FALSE) - { - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if(pLed->bLedScanBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - pLed->bLedWPSBlinkInProgress = _TRUE; - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), 0); - } - break; - - case LED_CTL_STOP_WPS: - pLed->bLedWPSBlinkInProgress = _FALSE; - if(padapter->pwrctrlpriv.rf_pwrstate != rf_on) - { - SwLedOff(padapter, pLed); - } - else - { - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), 0); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - break; - - case LED_CTL_STOP_WPS_FAIL: - pLed->bLedWPSBlinkInProgress = _FALSE; - if(padapter->pwrctrlpriv.rf_pwrstate != rf_on) - { - SwLedOff(padapter, pLed); - } - else - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), 0); - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); - } - break; - - case LED_CTL_START_TO_LINK: - case LED_CTL_NO_LINK: - if(!IS_LED_BLINKING(pLed)) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), 0); - } - break; - - case LED_CTL_POWER_OFF: - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - if( pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if( pLed->bLedScanBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - if( pLed->bLedWPSBlinkInProgress ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - - _set_timer(&(pLed->BlinkTimer), 0); - break; - - default: - break; - - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); -} - - //COREGA, added by chiyoko, 20090316 - static void - SwLedControlMode3( - _adapter *padapter, - LED_CTL_MODE LedAction -) -{ - struct led_priv *ledpriv = &(padapter->ledpriv); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - PLED_871x pLed = &(ledpriv->SwLed0); - - switch(LedAction) - { - case LED_CTL_SITE_SURVEY: - if(pmlmepriv->LinkDetectInfo.bBusyTraffic) - ; - else if(pLed->bLedScanBlinkInProgress ==_FALSE) - { - if(IS_LED_WPS_BLINKING(pLed)) - return; - - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - pLed->bLedScanBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SCAN; - pLed->BlinkTimes = 24; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - case LED_CTL_TX: - case LED_CTL_RX: - if((pLed->bLedBlinkInProgress ==_FALSE) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - - pLed->bLedBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_TXRX; - pLed->BlinkTimes = 2; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - break; - - case LED_CTL_LINK: - if(IS_LED_WPS_BLINKING(pLed)) - return; - - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - if( pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if( pLed->bLedScanBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - - _set_timer(&(pLed->BlinkTimer), 0); - break; - - case LED_CTL_START_WPS: //wait until xinpin finish - case LED_CTL_START_WPS_BOTTON: - if(pLed->bLedWPSBlinkInProgress ==_FALSE) - { - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if(pLed->bLedScanBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - pLed->bLedWPSBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_WPS; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - case LED_CTL_STOP_WPS: - if(pLed->bLedWPSBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - else - { - pLed->bLedWPSBlinkInProgress = _TRUE; - } - - pLed->CurrLedState = LED_BLINK_WPS_STOP; - if(pLed->bLedOn) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA); - } - else - { - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), 0); - } - - break; - - case LED_CTL_STOP_WPS_FAIL: - if(pLed->bLedWPSBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), 0); - break; - - case LED_CTL_START_TO_LINK: - case LED_CTL_NO_LINK: - if(!IS_LED_BLINKING(pLed)) - { - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), 0); - } - break; - - case LED_CTL_POWER_OFF: - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - if( pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if( pLed->bLedScanBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - if( pLed->bLedWPSBlinkInProgress ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - - _set_timer(&(pLed->BlinkTimer), 0); - break; - - default: - break; - - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState)); -} - - - //Edimax-Belkin, added by chiyoko, 20090413 -static void -SwLedControlMode4( - _adapter *padapter, - LED_CTL_MODE LedAction -) -{ - struct led_priv *ledpriv = &(padapter->ledpriv); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - PLED_871x pLed = &(ledpriv->SwLed0); - PLED_871x pLed1 = &(ledpriv->SwLed1); - - switch(LedAction) - { - case LED_CTL_START_TO_LINK: - if(pLed1->bLedWPSBlinkInProgress) - { - pLed1->bLedWPSBlinkInProgress = _FALSE; - _cancel_timer_ex(&(pLed1->BlinkTimer)); - - pLed1->BlinkingLedState = RTW_LED_OFF; - pLed1->CurrLedState = RTW_LED_OFF; - - if(pLed1->bLedOn) - _set_timer(&(pLed->BlinkTimer), 0); - } - - if( pLed->bLedStartToLinkBlinkInProgress == _FALSE ) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if(pLed->bLedNoLinkBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - - pLed->bLedStartToLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_StartToBlink; - if( pLed->bLedOn ) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); - } - else - { - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - } - } - break; - - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - //LED1 settings - if(LedAction == LED_CTL_LINK) - { - if(pLed1->bLedWPSBlinkInProgress) - { - pLed1->bLedWPSBlinkInProgress = _FALSE; - _cancel_timer_ex(&(pLed1->BlinkTimer)); - - pLed1->BlinkingLedState = RTW_LED_OFF; - pLed1->CurrLedState = RTW_LED_OFF; - - if(pLed1->bLedOn) - _set_timer(&(pLed->BlinkTimer), 0); - } - } - - if( pLed->bLedNoLinkBlinkInProgress == _FALSE ) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - } - break; - - case LED_CTL_SITE_SURVEY: - if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)) - ; - else if(pLed->bLedScanBlinkInProgress ==_FALSE) - { - if(IS_LED_WPS_BLINKING(pLed)) - return; - - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - pLed->bLedScanBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SCAN; - pLed->BlinkTimes = 24; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - case LED_CTL_TX: - case LED_CTL_RX: - if(pLed->bLedBlinkInProgress ==_FALSE) - { - if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed)) - { - return; - } - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - pLed->bLedBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_TXRX; - pLed->BlinkTimes = 2; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - break; - - case LED_CTL_START_WPS: //wait until xinpin finish - case LED_CTL_START_WPS_BOTTON: - if(pLed1->bLedWPSBlinkInProgress) - { - pLed1->bLedWPSBlinkInProgress = _FALSE; - _cancel_timer_ex(&(pLed1->BlinkTimer)); - - pLed1->BlinkingLedState = RTW_LED_OFF; - pLed1->CurrLedState = RTW_LED_OFF; - - if(pLed1->bLedOn) - _set_timer(&(pLed->BlinkTimer), 0); - } - - if(pLed->bLedWPSBlinkInProgress ==_FALSE) - { - if(pLed->bLedNoLinkBlinkInProgress == _TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if(pLed->bLedScanBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - pLed->bLedWPSBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_WPS; - if( pLed->bLedOn ) - { - pLed->BlinkingLedState = RTW_LED_OFF; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL); - } - else - { - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - } - } - break; - - case LED_CTL_STOP_WPS: //WPS connect success - if(pLed->bLedWPSBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - - break; - - case LED_CTL_STOP_WPS_FAIL: //WPS authentication fail - if(pLed->bLedWPSBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - - //LED1 settings - if(pLed1->bLedWPSBlinkInProgress) - _cancel_timer_ex(&(pLed1->BlinkTimer)); - else - pLed1->bLedWPSBlinkInProgress = _TRUE; - - pLed1->CurrLedState = LED_BLINK_WPS_STOP; - if( pLed1->bLedOn ) - pLed1->BlinkingLedState = RTW_LED_OFF; - else - pLed1->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - - break; - - case LED_CTL_STOP_WPS_FAIL_OVERLAP: //WPS session overlap - if(pLed->bLedWPSBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - - pLed->bLedNoLinkBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SLOWLY; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA); - - //LED1 settings - if(pLed1->bLedWPSBlinkInProgress) - _cancel_timer_ex(&(pLed1->BlinkTimer)); - else - pLed1->bLedWPSBlinkInProgress = _TRUE; - - pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP; - pLed1->BlinkTimes = 10; - if( pLed1->bLedOn ) - pLed1->BlinkingLedState = RTW_LED_OFF; - else - pLed1->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL); - - break; - - case LED_CTL_POWER_OFF: - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - - if( pLed->bLedNoLinkBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedNoLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedLinkBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedLinkBlinkInProgress = _FALSE; - } - if( pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - if( pLed->bLedWPSBlinkInProgress ) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedWPSBlinkInProgress = _FALSE; - } - if( pLed->bLedScanBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedScanBlinkInProgress = _FALSE; - } - if( pLed->bLedStartToLinkBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedStartToLinkBlinkInProgress = _FALSE; - } - - if( pLed1->bLedWPSBlinkInProgress ) - { - _cancel_timer_ex(&(pLed1->BlinkTimer)); - pLed1->bLedWPSBlinkInProgress = _FALSE; - } - - pLed1->BlinkingLedState = LED_UNKNOWN; - SwLedOff(padapter, pLed); - SwLedOff(padapter, pLed1); - break; - - default: - break; - - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState)); -} - - - - //Sercomm-Belkin, added by chiyoko, 20090415 -static void -SwLedControlMode5( - _adapter *padapter, - LED_CTL_MODE LedAction -) -{ -#ifndef CONFIG_LED_REMOVE_HAL - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); -#endif - struct led_priv *ledpriv = &(padapter->ledpriv); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - PLED_871x pLed = &(ledpriv->SwLed0); - -#ifndef CONFIG_LED_REMOVE_HAL - if(pHalData->EEPROMCustomerID == RT_CID_819x_CAMEO) - pLed = &(ledpriv->SwLed1); -#endif - - switch(LedAction) - { - case LED_CTL_POWER_ON: - case LED_CTL_NO_LINK: - case LED_CTL_LINK: //solid blue - pLed->CurrLedState = RTW_LED_ON; - pLed->BlinkingLedState = RTW_LED_ON; - - _set_timer(&(pLed->BlinkTimer), 0); - break; - - case LED_CTL_SITE_SURVEY: - if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)) - ; - else if(pLed->bLedScanBlinkInProgress ==_FALSE) - { - if(pLed->bLedBlinkInProgress ==_TRUE) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - pLed->bLedScanBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_SCAN; - pLed->BlinkTimes = 24; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA); - } - break; - - case LED_CTL_TX: - case LED_CTL_RX: - if(pLed->bLedBlinkInProgress ==_FALSE) - { - if(pLed->CurrLedState == LED_BLINK_SCAN) - { - return; - } - pLed->bLedBlinkInProgress = _TRUE; - pLed->CurrLedState = LED_BLINK_TXRX; - pLed->BlinkTimes = 2; - if( pLed->bLedOn ) - pLed->BlinkingLedState = RTW_LED_OFF; - else - pLed->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA); - } - break; - - case LED_CTL_POWER_OFF: - pLed->CurrLedState = RTW_LED_OFF; - pLed->BlinkingLedState = RTW_LED_OFF; - - if( pLed->bLedBlinkInProgress) - { - _cancel_timer_ex(&(pLed->BlinkTimer)); - pLed->bLedBlinkInProgress = _FALSE; - } - - SwLedOff(padapter, pLed); - break; - - default: - break; - - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState)); -} - - //WNC-Corega, added by chiyoko, 20090902 -static void -SwLedControlMode6( - _adapter *padapter, - LED_CTL_MODE LedAction -) -{ - struct led_priv *ledpriv = &(padapter->ledpriv); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - PLED_871x pLed0 = &(ledpriv->SwLed0); - - switch(LedAction) - { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - _cancel_timer_ex(&(pLed0->BlinkTimer)); - pLed0->CurrLedState = RTW_LED_ON; - pLed0->BlinkingLedState = RTW_LED_ON; - _set_timer(&(pLed0->BlinkTimer), 0); - break; - - case LED_CTL_POWER_OFF: - SwLedOff(padapter, pLed0); - break; - - default: - break; - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("ledcontrol 6 Led %d\n", pLed0->CurrLedState)); -} - -// -// Description: -// Handler function of LED Blinking. -// We dispatch acture LED blink action according to LedStrategy. -// -void BlinkHandler(PLED_871x pLed) -{ - _adapter *padapter = pLed->padapter; - struct led_priv *ledpriv = &(padapter->ledpriv); - - //DBG_871X("%s (%s:%d)\n",__FUNCTION__, current->comm, current->pid); - - if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE)) - { - //DBG_871X("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->bDriverStopped); - return; - } - - switch(ledpriv->LedStrategy) - { - case SW_LED_MODE0: - SwLedBlink(pLed); - break; - - case SW_LED_MODE1: - SwLedBlink1(pLed); - break; - - case SW_LED_MODE2: - SwLedBlink2(pLed); - break; - - case SW_LED_MODE3: - SwLedBlink3(pLed); - break; - - case SW_LED_MODE4: - SwLedBlink4(pLed); - break; - - case SW_LED_MODE5: - SwLedBlink5(pLed); - break; - - case SW_LED_MODE6: - SwLedBlink6(pLed); - break; - - default: - //RT_TRACE(COMP_LED, DBG_LOUD, ("BlinkWorkItemCallback 0x%x \n", pHalData->LedStrategy)); - //SwLedBlink(pLed); - break; - } -} - -void -LedControl871x( - _adapter *padapter, - LED_CTL_MODE LedAction - ) -{ - struct led_priv *ledpriv = &(padapter->ledpriv); - - if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE) - ||(padapter->hw_init_completed == _FALSE) ) - { - return; - } - - - if( ledpriv->bRegUseLed == _FALSE) - return; - - //if (!priv->up) - // return; - - //if(priv->bInHctTest) - // return; - - if( (padapter->pwrctrlpriv.rf_pwrstate != rf_on && - padapter->pwrctrlpriv.rfoff_reason > RF_CHANGE_BY_PS) && - (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX || - LedAction == LED_CTL_SITE_SURVEY || - LedAction == LED_CTL_LINK || - LedAction == LED_CTL_NO_LINK || - LedAction == LED_CTL_POWER_ON) ) - { - return; - } - - switch(ledpriv->LedStrategy) - { - case SW_LED_MODE0: - //SwLedControlMode0(padapter, LedAction); - break; - - case SW_LED_MODE1: - SwLedControlMode1(padapter, LedAction); - break; - case SW_LED_MODE2: - SwLedControlMode2(padapter, LedAction); - break; - - case SW_LED_MODE3: - SwLedControlMode3(padapter, LedAction); - break; - - case SW_LED_MODE4: - SwLedControlMode4(padapter, LedAction); - break; - - case SW_LED_MODE5: - SwLedControlMode5(padapter, LedAction); - break; - - case SW_LED_MODE6: - SwLedControlMode6(padapter, LedAction); - break; - - default: - break; - } - - RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("LedStrategy:%d, LedAction %d\n", ledpriv->LedStrategy,LedAction)); -} - -#endif - +/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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, USA
+ *
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+
+//
+// Description:
+// Callback function of LED BlinkTimer,
+// it just schedules to corresponding BlinkWorkItem/led_blink_hdl
+//
+void BlinkTimerCallback(void *data)
+{
+ PLED_871x pLed = (PLED_871x)data;
+ _adapter *padapter = pLed->padapter;
+
+ //DBG_871X("%s\n", __FUNCTION__);
+
+ if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE))
+ {
+ //DBG_871X("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->bDriverStopped);
+ return;
+ }
+
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
+ #ifdef CONFIG_LED_HANDLED_BY_CMD_THREAD
+ rtw_led_blink_cmd(padapter, pLed);
+ #else
+ _set_workitem(&(pLed->BlinkWorkItem));
+ #endif
+#elif defined(CONFIG_PCI_HCI)
+ BlinkHandler(pLed);
+#endif
+
+}
+
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
+//
+// Description:
+// Callback function of LED BlinkWorkItem.
+// We dispatch acture LED blink action according to LedStrategy.
+//
+void BlinkWorkItemCallback(struct work_struct *work)
+{
+ PLED_871x pLed = container_of(work, LED_871x, BlinkWorkItem);
+ BlinkHandler(pLed);
+}
+#endif
+
+//
+// Description:
+// Reset status of LED_871x object.
+//
+void ResetLedStatus(PLED_871x pLed) {
+
+ pLed->CurrLedState = RTW_LED_OFF; // Current LED state.
+ pLed->bLedOn = _FALSE; // true if LED is ON, false if LED is OFF.
+
+ pLed->bLedBlinkInProgress = _FALSE; // true if it is blinking, false o.w..
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+
+ pLed->BlinkTimes = 0; // Number of times to toggle led state for blinking.
+ pLed->BlinkingLedState = LED_UNKNOWN; // Next state for blinking, either RTW_LED_ON or RTW_LED_OFF are.
+
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ pLed->bLedStartToLinkBlinkInProgress = _FALSE;
+ pLed->bLedScanBlinkInProgress = _FALSE;
+#endif
+}
+
+ //
+// Description:
+// Initialize an LED_871x object.
+//
+void
+InitLed871x(
+ _adapter *padapter,
+ PLED_871x pLed,
+ LED_PIN_871x LedPin
+ )
+{
+ pLed->padapter = padapter;
+ pLed->LedPin = LedPin;
+
+ ResetLedStatus(pLed);
+
+ _init_timer(&(pLed->BlinkTimer), padapter->pnetdev, BlinkTimerCallback, pLed);
+
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI)
+ _init_workitem(&(pLed->BlinkWorkItem), BlinkWorkItemCallback, pLed);
+#endif
+}
+
+
+//
+// Description:
+// DeInitialize an LED_871x object.
+//
+void
+DeInitLed871x(
+ PLED_871x pLed
+ )
+{
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+ _cancel_workitem_sync(&(pLed->BlinkWorkItem));
+#endif
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ ResetLedStatus(pLed);
+}
+
+
+//
+// Description:
+// Implementation of LED blinking behavior.
+// It toggle off LED and schedule corresponding timer if necessary.
+//
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+
+void SwLedOn(_adapter *padapter, PLED_871x pLed);
+void SwLedOff(_adapter *padapter, PLED_871x pLed);
+
+#define CONFIG_LED_REMOVE_HAL
+
+void
+SwLedBlink(
+ PLED_871x pLed
+ )
+{
+ _adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ u8 bStopBlinking = _FALSE;
+
+ // Change LED according to BlinkingLedState specified.
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ {
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ }
+ else
+ {
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,( "Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+ // Determine if we shall change LED state again.
+ pLed->BlinkTimes--;
+ switch(pLed->CurrLedState)
+ {
+
+ case LED_BLINK_NORMAL:
+ if(pLed->BlinkTimes == 0)
+ {
+ bStopBlinking = _TRUE;
+ }
+ break;
+
+ case LED_BLINK_StartToBlink:
+ if( check_fwstate(pmlmepriv, _FW_LINKED) && check_fwstate(pmlmepriv, WIFI_STATION_STATE) )
+ {
+ bStopBlinking = _TRUE;
+ }
+ if( check_fwstate(pmlmepriv, _FW_LINKED) &&
+ (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) )
+ {
+ bStopBlinking = _TRUE;
+ }
+ else if(pLed->BlinkTimes == 0)
+ {
+ bStopBlinking = _TRUE;
+ }
+ break;
+
+ case LED_BLINK_WPS:
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+ break;
+
+
+ default:
+ bStopBlinking = _TRUE;
+ break;
+
+ }
+
+ if(bStopBlinking)
+ {
+ //if(adapter_to_pwrctl(padapter)->cpwm >= PS_STATE_S2)
+ if(0)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else if( (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) && (pLed->bLedOn == _FALSE))
+ {
+ SwLedOn(padapter, pLed);
+ }
+ else if( (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) && pLed->bLedOn == _TRUE)
+ {
+ SwLedOff(padapter, pLed);
+ }
+
+ pLed->BlinkTimes = 0;
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ // Assign LED state to toggle.
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ // Schedule a timer to toggle LED state.
+ switch( pLed->CurrLedState )
+ {
+ case LED_BLINK_NORMAL:
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ break;
+
+ case LED_BLINK_SLOWLY:
+ case LED_BLINK_StartToBlink:
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+ break;
+
+ case LED_BLINK_WPS:
+ {
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+ else
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+ }
+ break;
+
+ default:
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+ break;
+ }
+ }
+}
+
+void
+SwLedBlink1(
+ PLED_871x pLed
+ )
+{
+ _adapter *padapter = pLed->padapter;
+#ifndef CONFIG_LED_REMOVE_HAL
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+#endif
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ PLED_871x pLed1 = &(ledpriv->SwLed1);
+ u8 bStopBlinking = _FALSE;
+
+#ifndef CONFIG_LED_REMOVE_HAL
+ if(pHalData->EEPROMCustomerID == RT_CID_819x_CAMEO)
+ pLed = &(ledpriv->SwLed1);
+#endif
+
+ // Change LED according to BlinkingLedState specified.
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ {
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,( "Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ }
+ else
+ {
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+#ifndef CONFIG_LED_REMOVE_HAL
+ if(pHalData->EEPROMCustomerID == RT_CID_DEFAULT)
+ {
+ if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)
+ {
+ if(!pLed1->bSWLedCtrl)
+ {
+ SwLedOn(padapter, pLed1);
+ pLed1->bSWLedCtrl = _TRUE;
+ }
+ else if(!pLed1->bLedOn)
+ SwLedOn(padapter, pLed1);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (): turn on pLed1\n"));
+ }
+ else
+ {
+ if(!pLed1->bSWLedCtrl)
+ {
+ SwLedOff(padapter, pLed1);
+ pLed1->bSWLedCtrl = _TRUE;
+ }
+ else if(pLed1->bLedOn)
+ SwLedOff(padapter, pLed1);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (): turn off pLed1\n"));
+ }
+ }
+
+#endif
+
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ ResetLedStatus(pLed);
+ return;
+ }
+
+ switch(pLed->CurrLedState)
+ {
+ case LED_BLINK_SLOWLY:
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ break;
+
+ case LED_BLINK_NORMAL:
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+ break;
+
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+
+ if(bStopBlinking)
+ {
+ if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)
+ {
+ pLed->bLedLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE)
+ {
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+ if(bStopBlinking)
+ {
+ if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)
+ {
+ pLed->bLedLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE)
+ {
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->BlinkTimes = 0;
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_BLINK_WPS:
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ break;
+
+ case LED_BLINK_WPS_STOP: //WPS success
+ if(pLed->BlinkingLedState == RTW_LED_ON)
+ bStopBlinking = _FALSE;
+ else
+ bStopBlinking = _TRUE;
+
+ if(bStopBlinking)
+ {
+ pLed->bLedLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+void
+SwLedBlink2(
+ PLED_871x pLed
+ )
+{
+ _adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ u8 bStopBlinking = _FALSE;
+
+ // Change LED according to BlinkingLedState specified.
+ if( pLed->BlinkingLedState == RTW_LED_ON)
+ {
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ }
+ else
+ {
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+ switch(pLed->CurrLedState)
+ {
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+
+ if(bStopBlinking)
+ {
+ if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)
+ {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop scan blink CurrLedState %d\n", pLed->CurrLedState));
+
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE)
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop scan blink CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if( adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)
+ {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop CurrLedState %d\n", pLed->CurrLedState));
+
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE)
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("stop CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+}
+
+void
+SwLedBlink3(
+ PLED_871x pLed
+ )
+{
+ _adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ u8 bStopBlinking = _FALSE;
+
+ // Change LED according to BlinkingLedState specified.
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ {
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ }
+ else
+ {
+ if(pLed->CurrLedState != LED_BLINK_WPS_STOP)
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+ switch(pLed->CurrLedState)
+ {
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)
+ {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if( !pLed->bLedOn )
+ SwLedOn(padapter, pLed);
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE)
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if( pLed->bLedOn )
+ SwLedOff(padapter, pLed);
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE)
+ {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ if( !pLed->bLedOn )
+ SwLedOn(padapter, pLed);
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ else if(check_fwstate(pmlmepriv, _FW_LINKED)== _FALSE)
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+
+ if( pLed->bLedOn )
+ SwLedOff(padapter, pLed);
+
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ case LED_BLINK_WPS:
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ break;
+
+ case LED_BLINK_WPS_STOP: //WPS success
+ if(pLed->BlinkingLedState == RTW_LED_ON)
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ bStopBlinking = _FALSE;
+ }
+ else
+ {
+ bStopBlinking = _TRUE;
+ }
+
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+}
+
+
+void
+SwLedBlink4(
+ PLED_871x pLed
+ )
+{
+ _adapter *padapter = pLed->padapter;
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ PLED_871x pLed1 = &(ledpriv->SwLed1);
+ u8 bStopBlinking = _FALSE;
+
+ // Change LED according to BlinkingLedState specified.
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ {
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ }
+ else
+ {
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+ if(!pLed1->bLedWPSBlinkInProgress && pLed1->BlinkingLedState == LED_UNKNOWN)
+ {
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+ SwLedOff(padapter, pLed1);
+ }
+
+ switch(pLed->CurrLedState)
+ {
+ case LED_BLINK_SLOWLY:
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ break;
+
+ case LED_BLINK_StartToBlink:
+ if( pLed->bLedOn )
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ }
+ break;
+
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _FALSE;
+ }
+
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ case LED_BLINK_WPS:
+ if( pLed->bLedOn )
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ }
+ break;
+
+ case LED_BLINK_WPS_STOP: //WPS authentication fail
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ break;
+
+ case LED_BLINK_WPS_STOP_OVERLAP: //WPS session overlap
+ pLed->BlinkTimes--;
+ if(pLed->BlinkTimes == 0)
+ {
+ if(pLed->bLedOn)
+ {
+ pLed->BlinkTimes = 1;
+ }
+ else
+ {
+ bStopBlinking = _TRUE;
+ }
+ }
+
+ if(bStopBlinking)
+ {
+ pLed->BlinkTimes = 10;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("SwLedBlink4 CurrLedState %d\n", pLed->CurrLedState));
+
+
+}
+
+void
+SwLedBlink5(
+ PLED_871x pLed
+ )
+{
+ _adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ u8 bStopBlinking = _FALSE;
+
+ // Change LED according to BlinkingLedState specified.
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ {
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ }
+ else
+ {
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+ switch(pLed->CurrLedState)
+ {
+ case LED_BLINK_SCAN:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if(pLed->bLedOn)
+ SwLedOff(padapter, pLed);
+ }
+ else
+ { pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if(!pLed->bLedOn)
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+
+ case LED_BLINK_TXRX:
+ pLed->BlinkTimes--;
+ if( pLed->BlinkTimes == 0 )
+ {
+ bStopBlinking = _TRUE;
+ }
+
+ if(bStopBlinking)
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if(pLed->bLedOn)
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if(!pLed->bLedOn)
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on && adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("SwLedBlink5 CurrLedState %d\n", pLed->CurrLedState));
+
+
+}
+
+void
+SwLedBlink6(
+ PLED_871x pLed
+ )
+{
+ _adapter *padapter = pLed->padapter;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ u8 bStopBlinking = _FALSE;
+
+ // Change LED according to BlinkingLedState specified.
+ if( pLed->BlinkingLedState == RTW_LED_ON )
+ {
+ SwLedOn(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn on\n", pLed->BlinkTimes));
+ }
+ else
+ {
+ SwLedOff(padapter, pLed);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Blinktimes (%d): turn off\n", pLed->BlinkTimes));
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("<==== blink6\n"));
+}
+
+static void
+SwLedControlMode0(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+)
+{
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ PLED_871x pLed = &(ledpriv->SwLed1);
+
+ // Decide led state
+ switch(LedAction)
+ {
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if( pLed->bLedBlinkInProgress == _FALSE )
+ {
+ pLed->bLedBlinkInProgress = _TRUE;
+
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ pLed->BlinkTimes = 2;
+
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ }
+ break;
+
+ case LED_CTL_START_TO_LINK:
+ if( pLed->bLedBlinkInProgress == _FALSE )
+ {
+ pLed->bLedBlinkInProgress = _TRUE;
+
+ pLed->CurrLedState = LED_BLINK_StartToBlink;
+ pLed->BlinkTimes = 24;
+
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+ }
+ else
+ {
+ pLed->CurrLedState = LED_BLINK_StartToBlink;
+ }
+ break;
+
+ case LED_CTL_LINK:
+ pLed->CurrLedState = RTW_LED_ON;
+ if( pLed->bLedBlinkInProgress == _FALSE )
+ {
+ SwLedOn(padapter, pLed);
+ }
+ break;
+
+ case LED_CTL_NO_LINK:
+ pLed->CurrLedState = RTW_LED_OFF;
+ if( pLed->bLedBlinkInProgress == _FALSE )
+ {
+ SwLedOff(padapter, pLed);
+ }
+ break;
+
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ if(pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ SwLedOff(padapter, pLed);
+ break;
+
+ case LED_CTL_START_WPS:
+ if( pLed->bLedBlinkInProgress == _FALSE || pLed->CurrLedState == RTW_LED_ON)
+ {
+ pLed->bLedBlinkInProgress = _TRUE;
+
+ pLed->CurrLedState = LED_BLINK_WPS;
+ pLed->BlinkTimes = 20;
+
+ if( pLed->bLedOn )
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LONG_INTERVAL);
+ }
+ }
+ break;
+
+ case LED_CTL_STOP_WPS:
+ if(pLed->bLedBlinkInProgress)
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+
+}
+
+ //ALPHA, added by chiyoko, 20090106
+static void
+SwLedControlMode1(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+)
+{
+#ifndef CONFIG_LED_REMOVE_HAL
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+#endif
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ PLED_871x pLed = &(ledpriv->SwLed0);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+#ifndef CONFIG_LED_REMOVE_HAL
+ if(pHalData->EEPROMCustomerID == RT_CID_819x_CAMEO)
+ pLed = &(ledpriv->SwLed1);
+#endif
+
+ switch(LedAction)
+ {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_START_TO_LINK:
+ case LED_CTL_NO_LINK:
+ if( pLed->bLedNoLinkBlinkInProgress == _FALSE )
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+ if( pLed->bLedLinkBlinkInProgress == _TRUE )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_LINK:
+ if( pLed->bLedLinkBlinkInProgress == _FALSE )
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ pLed->bLedLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_NORMAL;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_LINK_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_SITE_SURVEY:
+ if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE))
+ ;
+ else if(pLed->bLedScanBlinkInProgress ==_FALSE)
+ {
+ if(IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedLinkBlinkInProgress == _TRUE )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ pLed->bLedScanBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if(pLed->bLedBlinkInProgress ==_FALSE)
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedLinkBlinkInProgress == _TRUE )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ }
+ pLed->bLedBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_START_WPS: //wait until xinpin finish
+ case LED_CTL_START_WPS_BOTTON:
+ if(pLed->bLedWPSBlinkInProgress ==_FALSE)
+ {
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedLinkBlinkInProgress == _TRUE )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedScanBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ pLed->bLedWPSBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_WPS;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+
+ case LED_CTL_STOP_WPS:
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedLinkBlinkInProgress == _TRUE )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedScanBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedWPSBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ }
+ else
+ {
+ pLed->bLedWPSBlinkInProgress = _TRUE;
+ }
+
+ pLed->CurrLedState = LED_BLINK_WPS_STOP;
+ if(pLed->bLedOn)
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+ break;
+
+ case LED_CTL_STOP_WPS_FAIL:
+ if(pLed->bLedWPSBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ break;
+
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if( pLed->bLedNoLinkBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedLinkBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedWPSBlinkInProgress )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedScanBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+
+ SwLedOff(padapter, pLed);
+ break;
+
+ default:
+ break;
+
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+}
+
+ //Arcadyan/Sitecom , added by chiyoko, 20090216
+static void
+SwLedControlMode2(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+)
+{
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ PLED_871x pLed = &(ledpriv->SwLed0);
+
+ switch(LedAction)
+ {
+ case LED_CTL_SITE_SURVEY:
+ if(pmlmepriv->LinkDetectInfo.bBusyTraffic)
+ ;
+ else if(pLed->bLedScanBlinkInProgress ==_FALSE)
+ {
+ if(IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ pLed->bLedScanBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if((pLed->bLedBlinkInProgress ==_FALSE) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE))
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+
+ pLed->bLedBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_LINK:
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if( pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedScanBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+
+ _set_timer(&(pLed->BlinkTimer), 0);
+ break;
+
+ case LED_CTL_START_WPS: //wait until xinpin finish
+ case LED_CTL_START_WPS_BOTTON:
+ if(pLed->bLedWPSBlinkInProgress ==_FALSE)
+ {
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedScanBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ pLed->bLedWPSBlinkInProgress = _TRUE;
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+ break;
+
+ case LED_CTL_STOP_WPS:
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ break;
+
+ case LED_CTL_STOP_WPS_FAIL:
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ if(adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on)
+ {
+ SwLedOff(padapter, pLed);
+ }
+ else
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+ }
+ break;
+
+ case LED_CTL_START_TO_LINK:
+ case LED_CTL_NO_LINK:
+ if(!IS_LED_BLINKING(pLed))
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+ break;
+
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if( pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedScanBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedWPSBlinkInProgress )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ _set_timer(&(pLed->BlinkTimer), 0);
+ break;
+
+ default:
+ break;
+
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+}
+
+ //COREGA, added by chiyoko, 20090316
+ static void
+ SwLedControlMode3(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+)
+{
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ PLED_871x pLed = &(ledpriv->SwLed0);
+
+ switch(LedAction)
+ {
+ case LED_CTL_SITE_SURVEY:
+ if(pmlmepriv->LinkDetectInfo.bBusyTraffic)
+ ;
+ else if(pLed->bLedScanBlinkInProgress ==_FALSE)
+ {
+ if(IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ pLed->bLedScanBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if((pLed->bLedBlinkInProgress ==_FALSE) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE))
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+
+ pLed->bLedBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_LINK:
+ if(IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+ if( pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedScanBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+
+ _set_timer(&(pLed->BlinkTimer), 0);
+ break;
+
+ case LED_CTL_START_WPS: //wait until xinpin finish
+ case LED_CTL_START_WPS_BOTTON:
+ if(pLed->bLedWPSBlinkInProgress ==_FALSE)
+ {
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedScanBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ pLed->bLedWPSBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_WPS;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_STOP_WPS:
+ if(pLed->bLedWPSBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+ else
+ {
+ pLed->bLedWPSBlinkInProgress = _TRUE;
+ }
+
+ pLed->CurrLedState = LED_BLINK_WPS_STOP;
+ if(pLed->bLedOn)
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_WPS_SUCESS_INTERVAL_ALPHA);
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+
+ break;
+
+ case LED_CTL_STOP_WPS_FAIL:
+ if(pLed->bLedWPSBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ break;
+
+ case LED_CTL_START_TO_LINK:
+ case LED_CTL_NO_LINK:
+ if(!IS_LED_BLINKING(pLed))
+ {
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+ break;
+
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ if( pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedScanBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedWPSBlinkInProgress )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ _set_timer(&(pLed->BlinkTimer), 0);
+ break;
+
+ default:
+ break;
+
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("CurrLedState %d\n", pLed->CurrLedState));
+}
+
+
+ //Edimax-Belkin, added by chiyoko, 20090413
+static void
+SwLedControlMode4(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+)
+{
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ PLED_871x pLed = &(ledpriv->SwLed0);
+ PLED_871x pLed1 = &(ledpriv->SwLed1);
+
+ switch(LedAction)
+ {
+ case LED_CTL_START_TO_LINK:
+ if(pLed1->bLedWPSBlinkInProgress)
+ {
+ pLed1->bLedWPSBlinkInProgress = _FALSE;
+ _cancel_timer_ex(&(pLed1->BlinkTimer));
+
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+
+ if(pLed1->bLedOn)
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+
+ if( pLed->bLedStartToLinkBlinkInProgress == _FALSE )
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedNoLinkBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+
+ pLed->bLedStartToLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_StartToBlink;
+ if( pLed->bLedOn )
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ }
+ }
+ break;
+
+ case LED_CTL_LINK:
+ case LED_CTL_NO_LINK:
+ //LED1 settings
+ if(LedAction == LED_CTL_LINK)
+ {
+ if(pLed1->bLedWPSBlinkInProgress)
+ {
+ pLed1->bLedWPSBlinkInProgress = _FALSE;
+ _cancel_timer_ex(&(pLed1->BlinkTimer));
+
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+
+ if(pLed1->bLedOn)
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+ }
+
+ if( pLed->bLedNoLinkBlinkInProgress == _FALSE )
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_SITE_SURVEY:
+ if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE))
+ ;
+ else if(pLed->bLedScanBlinkInProgress ==_FALSE)
+ {
+ if(IS_LED_WPS_BLINKING(pLed))
+ return;
+
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ pLed->bLedScanBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if(pLed->bLedBlinkInProgress ==_FALSE)
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN || IS_LED_WPS_BLINKING(pLed))
+ {
+ return;
+ }
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ pLed->bLedBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_START_WPS: //wait until xinpin finish
+ case LED_CTL_START_WPS_BOTTON:
+ if(pLed1->bLedWPSBlinkInProgress)
+ {
+ pLed1->bLedWPSBlinkInProgress = _FALSE;
+ _cancel_timer_ex(&(pLed1->BlinkTimer));
+
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ pLed1->CurrLedState = RTW_LED_OFF;
+
+ if(pLed1->bLedOn)
+ _set_timer(&(pLed->BlinkTimer), 0);
+ }
+
+ if(pLed->bLedWPSBlinkInProgress ==_FALSE)
+ {
+ if(pLed->bLedNoLinkBlinkInProgress == _TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if(pLed->bLedScanBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ pLed->bLedWPSBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_WPS;
+ if( pLed->bLedOn )
+ {
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SLOWLY_INTERVAL);
+ }
+ else
+ {
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+ }
+ }
+ break;
+
+ case LED_CTL_STOP_WPS: //WPS connect success
+ if(pLed->bLedWPSBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+
+ break;
+
+ case LED_CTL_STOP_WPS_FAIL: //WPS authentication fail
+ if(pLed->bLedWPSBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+
+ //LED1 settings
+ if(pLed1->bLedWPSBlinkInProgress)
+ _cancel_timer_ex(&(pLed1->BlinkTimer));
+ else
+ pLed1->bLedWPSBlinkInProgress = _TRUE;
+
+ pLed1->CurrLedState = LED_BLINK_WPS_STOP;
+ if( pLed1->bLedOn )
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed1->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+
+ break;
+
+ case LED_CTL_STOP_WPS_FAIL_OVERLAP: //WPS session overlap
+ if(pLed->bLedWPSBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ pLed->bLedNoLinkBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SLOWLY;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NO_LINK_INTERVAL_ALPHA);
+
+ //LED1 settings
+ if(pLed1->bLedWPSBlinkInProgress)
+ _cancel_timer_ex(&(pLed1->BlinkTimer));
+ else
+ pLed1->bLedWPSBlinkInProgress = _TRUE;
+
+ pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
+ pLed1->BlinkTimes = 10;
+ if( pLed1->bLedOn )
+ pLed1->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed1->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_NORMAL_INTERVAL);
+
+ break;
+
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+
+ if( pLed->bLedNoLinkBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedNoLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedLinkBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedLinkBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedWPSBlinkInProgress )
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedWPSBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedScanBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedScanBlinkInProgress = _FALSE;
+ }
+ if( pLed->bLedStartToLinkBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedStartToLinkBlinkInProgress = _FALSE;
+ }
+
+ if( pLed1->bLedWPSBlinkInProgress )
+ {
+ _cancel_timer_ex(&(pLed1->BlinkTimer));
+ pLed1->bLedWPSBlinkInProgress = _FALSE;
+ }
+
+ pLed1->BlinkingLedState = LED_UNKNOWN;
+ SwLedOff(padapter, pLed);
+ SwLedOff(padapter, pLed1);
+ break;
+
+ default:
+ break;
+
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+}
+
+
+
+ //Sercomm-Belkin, added by chiyoko, 20090415
+static void
+SwLedControlMode5(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+)
+{
+#ifndef CONFIG_LED_REMOVE_HAL
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+#endif
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ PLED_871x pLed = &(ledpriv->SwLed0);
+
+#ifndef CONFIG_LED_REMOVE_HAL
+ if(pHalData->EEPROMCustomerID == RT_CID_819x_CAMEO)
+ pLed = &(ledpriv->SwLed1);
+#endif
+
+ switch(LedAction)
+ {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_NO_LINK:
+ case LED_CTL_LINK: //solid blue
+ pLed->CurrLedState = RTW_LED_ON;
+ pLed->BlinkingLedState = RTW_LED_ON;
+
+ _set_timer(&(pLed->BlinkTimer), 0);
+ break;
+
+ case LED_CTL_SITE_SURVEY:
+ if((pmlmepriv->LinkDetectInfo.bBusyTraffic) && (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE))
+ ;
+ else if(pLed->bLedScanBlinkInProgress ==_FALSE)
+ {
+ if(pLed->bLedBlinkInProgress ==_TRUE)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+ pLed->bLedScanBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_SCAN;
+ pLed->BlinkTimes = 24;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_SCAN_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_TX:
+ case LED_CTL_RX:
+ if(pLed->bLedBlinkInProgress ==_FALSE)
+ {
+ if(pLed->CurrLedState == LED_BLINK_SCAN)
+ {
+ return;
+ }
+ pLed->bLedBlinkInProgress = _TRUE;
+ pLed->CurrLedState = LED_BLINK_TXRX;
+ pLed->BlinkTimes = 2;
+ if( pLed->bLedOn )
+ pLed->BlinkingLedState = RTW_LED_OFF;
+ else
+ pLed->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed->BlinkTimer), LED_BLINK_FASTER_INTERVAL_ALPHA);
+ }
+ break;
+
+ case LED_CTL_POWER_OFF:
+ pLed->CurrLedState = RTW_LED_OFF;
+ pLed->BlinkingLedState = RTW_LED_OFF;
+
+ if( pLed->bLedBlinkInProgress)
+ {
+ _cancel_timer_ex(&(pLed->BlinkTimer));
+ pLed->bLedBlinkInProgress = _FALSE;
+ }
+
+ SwLedOff(padapter, pLed);
+ break;
+
+ default:
+ break;
+
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("Led %d\n", pLed->CurrLedState));
+}
+
+ //WNC-Corega, added by chiyoko, 20090902
+static void
+SwLedControlMode6(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+)
+{
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ PLED_871x pLed0 = &(ledpriv->SwLed0);
+
+ switch(LedAction)
+ {
+ case LED_CTL_POWER_ON:
+ case LED_CTL_LINK:
+ case LED_CTL_NO_LINK:
+ _cancel_timer_ex(&(pLed0->BlinkTimer));
+ pLed0->CurrLedState = RTW_LED_ON;
+ pLed0->BlinkingLedState = RTW_LED_ON;
+ _set_timer(&(pLed0->BlinkTimer), 0);
+ break;
+
+ case LED_CTL_POWER_OFF:
+ SwLedOff(padapter, pLed0);
+ break;
+
+ default:
+ break;
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("ledcontrol 6 Led %d\n", pLed0->CurrLedState));
+}
+
+//
+// Description:
+// Handler function of LED Blinking.
+// We dispatch acture LED blink action according to LedStrategy.
+//
+void BlinkHandler(PLED_871x pLed)
+{
+ _adapter *padapter = pLed->padapter;
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+
+ //DBG_871X("%s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
+
+ if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE))
+ {
+ //DBG_871X("%s bSurpriseRemoved:%d, bDriverStopped:%d\n", __FUNCTION__, padapter->bSurpriseRemoved, padapter->bDriverStopped);
+ return;
+ }
+
+ switch(ledpriv->LedStrategy)
+ {
+ case SW_LED_MODE0:
+ SwLedBlink(pLed);
+ break;
+
+ case SW_LED_MODE1:
+ SwLedBlink1(pLed);
+ break;
+
+ case SW_LED_MODE2:
+ SwLedBlink2(pLed);
+ break;
+
+ case SW_LED_MODE3:
+ SwLedBlink3(pLed);
+ break;
+
+ case SW_LED_MODE4:
+ SwLedBlink4(pLed);
+ break;
+
+ case SW_LED_MODE5:
+ SwLedBlink5(pLed);
+ break;
+
+ case SW_LED_MODE6:
+ SwLedBlink6(pLed);
+ break;
+
+ default:
+ //RT_TRACE(COMP_LED, DBG_LOUD, ("BlinkWorkItemCallback 0x%x \n", pHalData->LedStrategy));
+ //SwLedBlink(pLed);
+ break;
+ }
+}
+
+void
+LedControl871x(
+ _adapter *padapter,
+ LED_CTL_MODE LedAction
+ )
+{
+ struct led_priv *ledpriv = &(padapter->ledpriv);
+
+ if( (padapter->bSurpriseRemoved == _TRUE) || ( padapter->bDriverStopped == _TRUE)
+ ||(padapter->hw_init_completed == _FALSE) )
+ {
+ return;
+ }
+
+
+ if( ledpriv->bRegUseLed == _FALSE)
+ return;
+
+ //if (!priv->up)
+ // return;
+
+ //if(priv->bInHctTest)
+ // return;
+
+ if( (adapter_to_pwrctl(padapter)->rf_pwrstate != rf_on &&
+ adapter_to_pwrctl(padapter)->rfoff_reason > RF_CHANGE_BY_PS) &&
+ (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX ||
+ LedAction == LED_CTL_SITE_SURVEY ||
+ LedAction == LED_CTL_LINK ||
+ LedAction == LED_CTL_NO_LINK ||
+ LedAction == LED_CTL_POWER_ON) )
+ {
+ return;
+ }
+
+ switch(ledpriv->LedStrategy)
+ {
+ case SW_LED_MODE0:
+ //SwLedControlMode0(padapter, LedAction);
+ break;
+
+ case SW_LED_MODE1:
+ SwLedControlMode1(padapter, LedAction);
+ break;
+ case SW_LED_MODE2:
+ SwLedControlMode2(padapter, LedAction);
+ break;
+
+ case SW_LED_MODE3:
+ SwLedControlMode3(padapter, LedAction);
+ break;
+
+ case SW_LED_MODE4:
+ SwLedControlMode4(padapter, LedAction);
+ break;
+
+ case SW_LED_MODE5:
+ SwLedControlMode5(padapter, LedAction);
+ break;
+
+ case SW_LED_MODE6:
+ SwLedControlMode6(padapter, LedAction);
+ break;
+
+ default:
+ break;
+ }
+
+ RT_TRACE(_module_rtl8712_led_c_,_drv_info_,("LedStrategy:%d, LedAction %d\n", ledpriv->LedStrategy,LedAction));
+}
+
+#endif
+
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_mlme.c b/drivers/net/wireless/rtl8723as/core/rtw_mlme.c index a827c0221b36..b5e1807c69d7 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_mlme.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_mlme.c @@ -119,7 +119,7 @@ static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen) { if(*ppie) { - _rtw_mfree(*ppie, *plen); + rtw_mfree(*ppie, *plen); *plen = 0; *ppie=NULL; } @@ -628,7 +628,7 @@ inline int is_same_ess(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b) && _rtw_memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength)==_TRUE; } -int is_same_network(WLAN_BSSID_EX *src, WLAN_BSSID_EX *dst) +int is_same_network(WLAN_BSSID_EX *src, WLAN_BSSID_EX *dst, u8 feature) { u16 s_cap, d_cap; @@ -658,6 +658,14 @@ _func_enter_; _func_exit_; +#ifdef CONFIG_P2P + if ((feature == 1) && // 1: P2P supported + (_rtw_memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN) == _TRUE) + ) { + return _TRUE; + } +#endif + return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) && // (src->Configuration.DSConfig == dst->Configuration.DSConfig) && ( (_rtw_memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) == _TRUE) && @@ -723,10 +731,10 @@ _func_enter_; rtw_hal_antdiv_rssi_compared(padapter, dst, src); //this will update src.Rssi, need consider again #endif - #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 + #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1 if(strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) { - DBG_871X("%s %s("MAC_FMT", ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n" - , __FUNCTION__ + DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT", ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n" + , FUNC_ADPT_ARG(padapter) , src->Ssid.Ssid, MAC_ARG(src->MacAddress), src->Configuration.DSConfig ,ss_ori, sq_ori, rssi_ori ,ss_smp, sq_smp, rssi_smp @@ -735,7 +743,7 @@ _func_enter_; #endif /* The rule below is 1/5 for sample value, 4/5 for history value */ - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src)) { + if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src, 0)) { /* Take the recvpriv's value for the connected AP*/ ss_final = padapter->recvpriv.signal_strength; sq_final = padapter->recvpriv.signal_qual; @@ -759,24 +767,27 @@ _func_enter_; } - if (update_ie) + if (update_ie) { + dst->Reserved[0] = src->Reserved[0]; + dst->Reserved[1] = src->Reserved[1]; _rtw_memcpy((u8 *)dst, (u8 *)src, get_WLAN_BSSID_EX_sz(src)); + } dst->PhyInfo.SignalStrength = ss_final; dst->PhyInfo.SignalQuality = sq_final; dst->Rssi = rssi_final; - #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 + #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1 if(strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) { - DBG_871X("%s %s("MAC_FMT"), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n" - , __FUNCTION__ + DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT"), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n" + , FUNC_ADPT_ARG(padapter) , dst->Ssid.Ssid, MAC_ARG(dst->MacAddress), dst->PhyInfo.SignalStrength, dst->PhyInfo.SignalQuality, dst->Rssi); } #endif #if 0 // old codes, may be useful one day... // DBG_871X("update_network: rssi=0x%lx dst->Rssi=%d ,dst->Rssi=0x%lx , src->Rssi=0x%lx",(dst->Rssi+src->Rssi)/2,dst->Rssi,dst->Rssi,src->Rssi); - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src)) + if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src, 0)) { //DBG_871X("b:ssid=%s update_network: src->rssi=0x%d padapter->recvpriv.ui_rssi=%d\n",src->Ssid.Ssid,src->Rssi,padapter->recvpriv.signal); @@ -825,7 +836,7 @@ _func_enter_; } #endif - if ( (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) && (is_same_network(&(pmlmepriv->cur_network.network), pnetwork))) + if ( (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) && (is_same_network(&(pmlmepriv->cur_network.network), pnetwork, 0))) { //RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"Same Network\n"); @@ -854,9 +865,13 @@ void rtw_update_scanned_network(_adapter *adapter, WLAN_BSSID_EX *target) _list *plist, *phead; ULONG bssid_ex_sz; struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); + struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); + struct wifidirect_info *pwdinfo= &(adapter->wdinfo); _queue *queue = &(pmlmepriv->scanned_queue); struct wlan_network *pnetwork = NULL; struct wlan_network *oldest = NULL; + int target_find = 0; + u8 feature = 0; _func_enter_; @@ -864,6 +879,11 @@ _func_enter_; phead = get_list_head(queue); plist = get_next(phead); +#ifdef CONFIG_P2P + if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) + feature = 1; // p2p enable +#endif + while(1) { if (rtw_end_of_queue_search(phead,plist)== _TRUE) @@ -878,8 +898,10 @@ _func_enter_; #endif } - if (is_same_network(&(pnetwork->network), target)) + if (is_same_network(&(pnetwork->network), target, feature)) { + target_find = 1; break; + } if ((oldest == ((struct wlan_network *)0)) || time_after(oldest->last_scanned, pnetwork->last_scanned)) @@ -892,7 +914,8 @@ _func_enter_; /* If we didn't find a match, then get a new network slot to initialize * with this beacon's information */ - if (rtw_end_of_queue_search(phead,plist)== _TRUE) { + //if (rtw_end_of_queue_search(phead,plist)== _TRUE) { + if (!target_find) { if (_rtw_queue_empty(&(pmlmepriv->free_bss_pool)) == _TRUE) { /* If there are no more slots, expire the oldest */ @@ -955,8 +978,15 @@ _func_enter_; pnetwork->last_scanned = rtw_get_current_time(); //target.Reserved[0]==1, means that scaned network is a bcn frame. - if((pnetwork->network.IELength>target->IELength) && (target->Reserved[0]==1)) + // probe resp(3) > beacon(1) > probe req(2) + if ((target->Reserved[0] != 2) && + (target->Reserved[0] >= pnetwork->network.Reserved[0]) + ) { + update_ie = _TRUE; + } + else { update_ie = _FALSE; + } update_network(&(pnetwork->network), target,adapter, update_ie); } @@ -1026,8 +1056,20 @@ int rtw_is_desired_network(_adapter *adapter, struct wlan_network *pnetwork) } if (adapter->registrypriv.wifi_spec == 1) //for correct flow of 8021X to do.... { + u8 *p=NULL; + uint ie_len=0; + if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0)) bselected = _FALSE; + + if ( psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) { + p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_)); + if (p && ie_len>0) { + bselected = _TRUE; + } else { + bselected = _FALSE; + } + } } @@ -1129,7 +1171,7 @@ _func_enter_; pnetwork->Ssid.SsidLength = 0; } rtw_add_network(adapter, pnetwork); - } + } exit: @@ -1145,6 +1187,7 @@ _func_exit_; void rtw_surveydone_event_callback(_adapter *adapter, u8 *pbuf) { _irqL irqL; + u8 timer_cancelled = _FALSE; struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); #ifdef CONFIG_MLME_EXT @@ -1156,7 +1199,6 @@ void rtw_surveydone_event_callback(_adapter *adapter, u8 *pbuf) _func_enter_; _enter_critical_bh(&pmlmepriv->lock, &irqL); - if(pmlmepriv->wps_probe_req_ie) { u32 free_len = pmlmepriv->wps_probe_req_ie_len; @@ -1169,9 +1211,10 @@ _func_enter_; if (check_fwstate(pmlmepriv,_FW_UNDER_SURVEY)) { - u8 timer_cancelled; - - _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled); + //u8 timer_cancelled; + + timer_cancelled = _TRUE; + //_cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled); _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); } @@ -1179,6 +1222,13 @@ _func_enter_; RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv))); } + _exit_critical_bh(&pmlmepriv->lock, &irqL); + + if(timer_cancelled) + _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled); + + + _enter_critical_bh(&pmlmepriv->lock, &irqL); #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS rtw_set_signal_stat_timer(&adapter->recvpriv); @@ -1293,7 +1343,7 @@ _func_enter_; { struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; if(pmlmeext->sitesurvey_res.bss_cnt == 0){ - rtw_hal_sreset_reset(adapter); + //rtw_hal_sreset_reset(adapter); } } #endif @@ -1413,6 +1463,32 @@ _func_enter_; if(pwlan) { pwlan->fixed = _FALSE; +#ifdef CONFIG_P2P + if(!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE)) + { + u32 p2p_ielen=0; + u8 *p2p_ie; + //u16 capability; + u8 *pcap = NULL; + u32 capability_len=0; + + //DBG_871X("free disconnecting network\n"); + //rtw_free_network_nolock(pmlmepriv, pwlan); + + if((p2p_ie=rtw_get_p2p_ie(pwlan->network.IEs+_FIXED_IE_LENGTH_, pwlan->network.IELength-_FIXED_IE_LENGTH_, NULL, &p2p_ielen))) + { + pcap = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, NULL, &capability_len); + if(pcap && capability_len==2) + { + u16 cap = *(u16*)pcap ; + *(u16*)pcap = cap&0x00ff;//clear group capability when free this network + } + } + + rtw_set_scan_deny(adapter, 2000); + //rtw_clear_scan_deny(adapter); + } +#endif //CONFIG_P2P } else { @@ -1429,7 +1505,7 @@ _func_enter_; if(lock_scanned_queue) _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); - pmlmepriv->key_mask = 0; + adapter->securitypriv.key_mask = 0; _func_exit_; @@ -1536,7 +1612,7 @@ _func_enter_; rtw_os_indicate_disconnect(padapter); //set ips_deny_time to avoid enter IPS before LPS leave - padapter->pwrctrlpriv.ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(3000); + adapter_to_pwrctl(padapter)->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(3000); _clr_fwstate_(pmlmepriv, _FW_LINKED); @@ -1551,9 +1627,6 @@ _func_enter_; #endif // CONFIG_P2P_PS #ifdef CONFIG_LPS -#ifdef CONFIG_WOWLAN - if(padapter->pwrctrlpriv.wowlan_mode==_FALSE) -#endif //CONFIG_WOWLAN rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1); #endif @@ -1587,7 +1660,7 @@ void rtw_scan_abort(_adapter *adapter) if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved) DBG_871X(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev)); - #ifdef CONFIG_PLATFORM_MSTAR_TITANIA12 + #ifdef CONFIG_PLATFORM_MSTAR //_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY); set_survey_timer(pmlmeext, 0); _set_timer(&pmlmepriv->scan_to_timer, 50); @@ -1642,7 +1715,10 @@ static struct sta_info *rtw_joinbss_update_stainfo(_adapter *padapter, struct wl _rtw_memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof (union Keytype)); _rtw_memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof (union Keytype)); - _rtw_memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48)); + _rtw_memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48)); +#ifdef CONFIG_IEEE80211W + _rtw_memset((u8 *)&psta->dot11wtxpn, 0, sizeof (union pn48)); +#endif //CONFIG_IEEE80211W _rtw_memset((u8 *)&psta->dot11rxpn, 0, sizeof (union pn48)); } @@ -1732,9 +1808,9 @@ static void rtw_joinbss_update_network(_adapter *padapter, struct wlan_network * //the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength); #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 - DBG_871X("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u" + DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u" "\n" - , __FUNCTION__ + , FUNC_ADPT_ARG(padapter) , padapter->recvpriv.signal_strength , padapter->recvpriv.rssi , padapter->recvpriv.signal_qual @@ -1911,15 +1987,16 @@ _func_enter_; } //s4. indicate connect - if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) - { - rtw_indicate_connect(adapter); - } - else - { - //adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback - RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv))); - } + if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) + { + pmlmepriv->cur_network_scanned = ptarget_wlan; + rtw_indicate_connect(adapter); + } + else + { + //adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback + RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv))); + } //s5. Cancle assoc_timer @@ -2057,10 +2134,10 @@ u8 search_max_mac_id(_adapter *padapter) } -//FOR AP ,AD-HOC mode -void rtw_stassoc_hw_rpt(_adapter *adapter,struct sta_info *psta) +//FOR STA, AP ,AD-HOC mode +void rtw_sta_media_status_rpt(_adapter *adapter,struct sta_info *psta, u32 mstatus) { - u16 media_status; + u16 media_status_rpt; if(psta==NULL) return; @@ -2070,8 +2147,8 @@ void rtw_stassoc_hw_rpt(_adapter *adapter,struct sta_info *psta) rtw_hal_set_hwreg(adapter,HW_VAR_TX_RPT_MAX_MACID, (u8*)&macid); } #endif - media_status = (psta->mac_id<<8)|1; // MACID|OPMODE:1 connect - rtw_hal_set_hwreg(adapter,HW_VAR_H2C_MEDIA_STATUS_RPT,(u8 *)&media_status); + media_status_rpt = (u16)((psta->mac_id<<8)|mstatus); // MACID|OPMODE:1 connect + rtw_hal_set_hwreg(adapter,HW_VAR_H2C_MEDIA_STATUS_RPT,(u8 *)&media_status_rpt); } void rtw_stassoc_event_callback(_adapter *adapter, u8 *pbuf) @@ -2094,13 +2171,18 @@ _func_enter_; psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr); if(psta) { -#ifdef CONFIG_IOCTL_CFG80211 - #ifdef COMPAT_KERNEL_RELEASE - - #elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) || defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) u8 *passoc_req = NULL; - u32 assoc_req_len; + u32 assoc_req_len = 0; + + rtw_sta_media_status_rpt(adapter, psta, 1); + +#ifndef CONFIG_AUTO_AP_MODE + + ap_sta_info_defer_update(adapter, psta); + //report to upper layer + DBG_871X("indicate_sta_assoc_event to upper layer - hostapd\n"); +#ifdef CONFIG_IOCTL_CFG80211 _enter_critical_bh(&psta->lock, &irqL); if(psta->passoc_req && psta->assoc_req_len>0) { @@ -2110,7 +2192,7 @@ _func_enter_; assoc_req_len = psta->assoc_req_len; _rtw_memcpy(passoc_req, psta->passoc_req, assoc_req_len); - _rtw_mfree(psta->passoc_req , psta->assoc_req_len); + rtw_mfree(psta->passoc_req , psta->assoc_req_len); psta->passoc_req = NULL; psta->assoc_req_len = 0; } @@ -2120,23 +2202,18 @@ _func_enter_; if(passoc_req && assoc_req_len>0) { rtw_cfg80211_indicate_sta_assoc(adapter, passoc_req, assoc_req_len); - - _rtw_mfree(passoc_req, assoc_req_len); - } - #endif //(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) || defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) -#endif //CONFIG_IOCTL_CFG80211 - - //bss_cap_update_on_sta_join(adapter, psta); - //sta_info_update(adapter, psta); - ap_sta_info_defer_update(adapter, psta); - - rtw_stassoc_hw_rpt(adapter,psta); - - } + rtw_mfree(passoc_req, assoc_req_len); + } +#else //!CONFIG_IOCTL_CFG80211 + rtw_indicate_sta_assoc_event(adapter, psta); +#endif //!CONFIG_IOCTL_CFG80211 +#endif //!CONFIG_AUTO_AP_MODE + } goto exit; } -#endif +#endif //defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) + //for AD-HOC mode psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr); if( psta != NULL) @@ -2162,7 +2239,7 @@ _func_enter_; //for ad-hoc mode rtw_hal_set_odm_var(adapter,HAL_ODM_STA_INFO,psta,_TRUE); - rtw_stassoc_hw_rpt(adapter,psta); + rtw_sta_media_status_rpt(adapter, psta, 1); if(adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X) psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm; @@ -2193,7 +2270,7 @@ _func_enter_; #ifdef CONFIG_RTL8711 //submit SetStaKey_cmd to tell fw, fw will allocate an CAM entry for this sta - rtw_setstakey_cmd(adapter, (unsigned char*)psta, _FALSE); + rtw_setstakey_cmd(adapter, (unsigned char*)psta, _FALSE, _TRUE); #endif exit: @@ -2253,7 +2330,9 @@ _func_enter_; if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) ) { #ifdef CONFIG_LAYER2_ROAMING - if (rtw_to_roaming(adapter) > 0) + if(adapter->registrypriv.wifi_spec==1) + rtw_set_roaming(adapter, 0); /* don't roam */ + else if (rtw_to_roaming(adapter) > 0) pmlmepriv->to_roaming--; /* this stadel_event is caused by roaming, decrease to_roaming */ else if (rtw_to_roaming(adapter) == 0) rtw_set_roaming(adapter, adapter->registrypriv.max_roaming_times); @@ -2357,7 +2436,7 @@ _func_enter_; RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("+rtw_cpwm_event_callback !!!\n")); #ifdef CONFIG_LPS_LCLK preportpwrstate = (struct reportpwrstate_parm*)pbuf; - preportpwrstate->state |= (u8)(padapter->pwrctrlpriv.cpwm_tog + 0x80); + preportpwrstate->state |= (u8)(adapter_to_pwrctl(padapter)->cpwm_tog + 0x80); cpwm_int_hdl(padapter, preportpwrstate); #endif @@ -2489,7 +2568,7 @@ void rtw_scan_timeout_handler (_adapter *adapter) static void rtw_auto_scan_handler(_adapter *padapter) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); //auto site survey per 60sec if(pmlmepriv->scan_interval >0) @@ -2549,7 +2628,12 @@ void rtw_dynamic_check_timer_handlder(_adapter *adapter) return; #if defined(CONFIG_CHECK_BT_HANG) && defined(CONFIG_BT_COEXIST) if(adapter->HalFunc.hal_checke_bt_hang) - adapter->HalFunc.hal_checke_bt_hang(adapter); + { +#ifdef CONFIG_CONCURRENT_MODE + if (adapter->adapter_type == PRIMARY_ADAPTER) +#endif + adapter->HalFunc.hal_checke_bt_hang(adapter); + } #endif if(adapter->hw_init_completed == _FALSE) return; @@ -2678,6 +2762,13 @@ void rtw_set_scan_deny(_adapter *adapter, u32 ms) } #endif +#ifdef CONFIG_DETECT_C2H_BY_POLLING +void rtw_event_polling_timer_hdl(_adapter *adapter) +{ + rtw_event_polling_cmd(adapter); +} +#endif + #if defined(IEEE80211_SCAN_RESULT_EXPIRE) #define RTW_SCAN_RESULT_EXPIRE IEEE80211_SCAN_RESULT_EXPIRE/HZ*1000 -1000 //3000 -1000 #else @@ -2953,7 +3044,7 @@ _func_enter_; if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) { - if(is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) + if(is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network), 0) { //DBG_871X("select_and_join(1): _FW_LINKED and is same network, it needn't join again\n"); @@ -2987,7 +3078,7 @@ _func_enter_; if( (roaming_candidate == NULL ||roaming_candidate->network.Rssi<pnetwork->network.Rssi ) && is_same_ess(&pnetwork->network, &pmlmepriv->cur_network.network) - //&&(!is_same_network(&pnetwork->network, &pmlmepriv->cur_network.network)) + //&&(!is_same_network(&pnetwork->network, &pmlmepriv->cur_network.network, 0)) && rtw_get_time_interval_ms((u32)pnetwork->last_scanned,cur_time) < 5000 ) { roaming_candidate = pnetwork; @@ -3030,7 +3121,7 @@ _func_enter_; if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) { #if 0 - if(is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network)) + if(is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) { DBG_871X("select_and_join(2): _FW_LINKED and is same network, it needn't join again\n"); @@ -3141,7 +3232,7 @@ _func_exit_; } -sint rtw_set_key(_adapter * adapter,struct security_priv *psecuritypriv,sint keyid, u8 set_tx) +sint rtw_set_key(_adapter * adapter,struct security_priv *psecuritypriv,sint keyid, u8 set_tx, bool enqueue) { u8 keylen; struct cmd_obj *pcmd; @@ -3151,19 +3242,12 @@ sint rtw_set_key(_adapter * adapter,struct security_priv *psecuritypriv,sint key sint res=_SUCCESS; _func_enter_; - - pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); - if(pcmd==NULL){ - res= _FAIL; //try again - goto exit; - } + psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm)); - if(psetkeyparm==NULL){ - rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj)); + if(psetkeyparm==NULL){ res= _FAIL; goto exit; } - _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm)); if(psecuritypriv->dot11AuthAlgrthm ==dot11AuthAlgrthm_8021X){ @@ -3178,20 +3262,13 @@ _func_enter_; psetkeyparm->keyid = (u8)keyid;//0~3 psetkeyparm->set_tx = set_tx; if (is_wep_enc(psetkeyparm->algorithm)) - pmlmepriv->key_mask |= BIT(psetkeyparm->keyid); + psecuritypriv->key_mask |= BIT(psetkeyparm->keyid); -#ifdef CONFIG_AUTOSUSPEND - if( _TRUE == adapter->pwrctrlpriv.bInternalAutoSuspend) - { - adapter->pwrctrlpriv.wepkeymask = pmlmepriv->key_mask; - DBG_871X("....AutoSuspend pwrctrlpriv.wepkeymask(%x)\n",adapter->pwrctrlpriv.wepkeymask); - } -#endif - DBG_871X("==> rtw_set_key algorithm(%x),keyid(%x),key_mask(%x)\n",psetkeyparm->algorithm,psetkeyparm->keyid,pmlmepriv->key_mask); + DBG_871X("==> rtw_set_key algorithm(%x),keyid(%x),key_mask(%x)\n",psetkeyparm->algorithm,psetkeyparm->keyid, psecuritypriv->key_mask); RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n rtw_set_key: psetkeyparm->algorithm=%d psetkeyparm->keyid=(u8)keyid=%d \n",psetkeyparm->algorithm, keyid)); switch(psetkeyparm->algorithm){ - + case _WEP40_: keylen=5; _rtw_memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen); @@ -3201,7 +3278,7 @@ _func_enter_; _rtw_memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen); break; case _TKIP_: - keylen=16; + keylen=16; _rtw_memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen); psetkeyparm->grpkey=1; break; @@ -3213,23 +3290,35 @@ _func_enter_; default: RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n rtw_set_key:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n",psecuritypriv->dot11PrivacyAlgrthm)); res= _FAIL; + rtw_mfree((unsigned char *)psetkeyparm, sizeof(struct setkey_parm)); goto exit; } + + + if(enqueue){ + pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj)); + if(pcmd==NULL){ + rtw_mfree((unsigned char *)psetkeyparm, sizeof(struct setkey_parm)); + res= _FAIL; //try again + goto exit; + } + + pcmd->cmdcode = _SetKey_CMD_; + pcmd->parmbuf = (u8 *)psetkeyparm; + pcmd->cmdsz = (sizeof(struct setkey_parm)); + pcmd->rsp = NULL; + pcmd->rspsz = 0; - - pcmd->cmdcode = _SetKey_CMD_; - pcmd->parmbuf = (u8 *)psetkeyparm; - pcmd->cmdsz = (sizeof(struct setkey_parm)); - pcmd->rsp = NULL; - pcmd->rspsz = 0; - - - _rtw_init_listhead(&pcmd->list); - - //_rtw_init_sema(&(pcmd->cmd_sem), 0); + _rtw_init_listhead(&pcmd->list); - res = rtw_enqueue_cmd(pcmdpriv, pcmd); + //_rtw_init_sema(&(pcmd->cmd_sem), 0); + res = rtw_enqueue_cmd(pcmdpriv, pcmd); + } + else{ + setkey_hdl(adapter, (u8 *)psetkeyparm); + rtw_mfree((u8 *) psetkeyparm, sizeof(struct setkey_parm)); + } exit: _func_exit_; return res; @@ -3389,6 +3478,14 @@ _func_enter_; { //copy RSN or SSN _rtw_memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1]+2); + /* debug for CONFIG_IEEE80211W + { + int jj; + printk("supplicant_ie_length=%d &&&&&&&&&&&&&&&&&&&\n", psecuritypriv->supplicant_ie[1]+2); + for(jj=0; jj < psecuritypriv->supplicant_ie[1]+2; jj++) + printk(" %02x ", psecuritypriv->supplicant_ie[jj]); + printk("\n"); + }*/ ielength+=psecuritypriv->supplicant_ie[1]+2; rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie); @@ -3655,7 +3752,7 @@ unsigned int rtw_restructure_ht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, ui p = rtw_get_ie(in_ie+12, _HT_ADD_INFO_IE_, &ielen, in_len-12); if(p && (ielen==sizeof(struct ieee80211_ht_addt_info))) { - out_len = *pout_len; + out_len = *pout_len; pframe = rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2 , pout_len); } diff --git a/drivers/net/wireless/rtl8723as/core/rtw_mlme_ext.c b/drivers/net/wireless/rtl8723as/core/rtw_mlme_ext.c index fbf4b0668014..79961ad7df62 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_mlme_ext.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_mlme_ext.c @@ -85,7 +85,14 @@ struct action_handler OnAction_tbl[]={ {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved}, {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved}, {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht}, +#ifdef CONFIG_IEEE80211W + {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query}, +#else {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved}, +#endif //CONFIG_IEEE80211W + //add for CONFIG_IEEE80211W + {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved}, + {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved}, {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm}, {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p}, }; @@ -307,7 +314,11 @@ static void init_mlme_ext_priv_value(_adapter* padapter) ATOMIC_SET(&pmlmeext->event_seq, 0); pmlmeext->mgnt_seq = 0;//reset to zero when disconnect at client mode - +#ifdef CONFIG_IEEE80211W + pmlmeext->sa_query_seq = 0; + pmlmeext->mgnt_80211w_IPN=0; + pmlmeext->mgnt_80211w_IPN_rx=0; +#endif //CONFIG_IEEE80211W pmlmeext->cur_channel = padapter->registrypriv.channel; pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20; pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; @@ -754,7 +765,7 @@ void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame) } #else - _mgt_dispatcher(padapter, ptable, precv_frame); + _mgt_dispatcher(padapter, ptable, precv_frame); #endif @@ -764,27 +775,32 @@ void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame) u32 p2p_listen_state_process(_adapter *padapter, unsigned char *da) { bool response = _TRUE; - + #ifdef CONFIG_IOCTL_CFG80211 - if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == _FALSE - || padapter->mlmepriv.wps_probe_resp_ie == NULL - || padapter->mlmepriv.p2p_probe_resp_ie == NULL - ) + if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 ) { - DBG_871X("DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n", - wdev_to_priv(padapter->rtw_wdev)->p2p_enabled, - padapter->mlmepriv.wps_probe_resp_ie, - padapter->mlmepriv.p2p_probe_resp_ie); - response = _FALSE; + if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled == _FALSE + || padapter->mlmepriv.wps_probe_resp_ie == NULL + || padapter->mlmepriv.p2p_probe_resp_ie == NULL + ) + { + DBG_871X("DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n", + wdev_to_priv(padapter->rtw_wdev)->p2p_enabled, + padapter->mlmepriv.wps_probe_resp_ie, + padapter->mlmepriv.p2p_probe_resp_ie); + response = _FALSE; + } } -#else - - // do nothing if the device name is empty - if ( !padapter->wdinfo.device_name_len ) + else +#endif //CONFIG_IOCTL_CFG80211 + if( padapter->wdinfo.driver_interface == DRIVER_WEXT ) { - response = _FALSE; + // do nothing if the device name is empty + if ( !padapter->wdinfo.device_name_len ) + { + response = _FALSE; + } } -#endif if (response == _TRUE) issue_probersp_p2p( padapter, da); @@ -910,8 +926,8 @@ _continue: _issue_probersp: - if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE && - pmlmepriv->cur_network.join_res == _TRUE) + if(((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE && + pmlmepriv->cur_network.join_res == _TRUE)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { //DBG_871X("+issue_probersp during ap mode\n"); issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); @@ -986,7 +1002,7 @@ unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame) } } } -#endif +#endif //CONFIG_P2P if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) @@ -994,10 +1010,10 @@ unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame) report_survey_event(padapter, precv_frame); #ifdef CONFIG_CONCURRENT_MODE report_survey_event(padapter->pbuddy_adapter, precv_frame); -#endif +#endif //CONFIG_CONCURRENT_MODE #ifdef CONFIG_DUALMAC_CONCURRENT dc_report_survey_event(padapter, precv_frame); -#endif +#endif //CONFIG_DUALMAC_CONCURRENT return _SUCCESS; } @@ -1105,7 +1121,7 @@ unsigned int OnBeacon(_adapter *padapter, union recv_frame *precv_frame) ret = rtw_check_bcn_info(padapter, pframe, len); if (!ret) { DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n "); - receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535); + receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 0); return _SUCCESS; } //update WMM, ERP in the beacon @@ -2104,56 +2120,34 @@ unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame) bss_cap_update_on_sta_join(padapter, pstat); sta_info_update(padapter, pstat); - //issue assoc rsp before notify station join event. + //.2 issue assoc rsp before notify station join event. if (frame_type == WIFI_ASSOCREQ) issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); else issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); - //.2 - report to upper layer - DBG_871X("indicate_sta_join_event to upper layer - hostapd\n"); - #ifdef CONFIG_IOCTL_CFG80211 - if (1) { - #ifdef COMPAT_KERNEL_RELEASE - rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len); - #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) - rtw_cfg80211_indicate_sta_assoc(padapter, pframe, pkt_len); - #else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) - _enter_critical_bh(&pstat->lock, &irqL); - if(pstat->passoc_req) - { - rtw_mfree(pstat->passoc_req, pstat->assoc_req_len); - pstat->passoc_req = NULL; - pstat->assoc_req_len = 0; - } - - pstat->passoc_req = rtw_zmalloc(pkt_len); - if(pstat->passoc_req) - { - _rtw_memcpy(pstat->passoc_req, pframe, pkt_len); - pstat->assoc_req_len = pkt_len; - } - _exit_critical_bh(&pstat->lock, &irqL); - #endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) +#ifdef CONFIG_IOCTL_CFG80211 + _enter_critical_bh(&pstat->lock, &irqL); + if(pstat->passoc_req) + { + rtw_mfree(pstat->passoc_req, pstat->assoc_req_len); + pstat->passoc_req = NULL; + pstat->assoc_req_len = 0; } - else - #endif //CONFIG_IOCTL_CFG80211 + + pstat->passoc_req = rtw_zmalloc(pkt_len); + if(pstat->passoc_req) { - rtw_indicate_sta_assoc_event(padapter, pstat); + _rtw_memcpy(pstat->passoc_req, pframe, pkt_len); + pstat->assoc_req_len = pkt_len; } + _exit_critical_bh(&pstat->lock, &irqL); +#endif //CONFIG_IOCTL_CFG80211 //.3-(1) report sta add event report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); -/* - //issue assoc rsp before notify station join event. - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); - else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); -*/ - -#endif +#endif //CONFIG_NATIVEAP_MLME } return _SUCCESS; @@ -2364,10 +2358,32 @@ unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame) else #endif { - DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n", - reason, GetAddr3Ptr(pframe)); + int ignore_received_deauth = 0; + + // Commented by Albert 20130604 + // Before sending the auth frame to start the STA/GC mode connection with AP/GO, + // we will send the deauth first. + // However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. + // Added the following code to avoid this case. + if ( ( pmlmeinfo->state & WIFI_FW_AUTH_STATE ) || + ( pmlmeinfo->state & WIFI_FW_ASSOC_STATE ) ) + { + if ( reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA ) + { + ignore_received_deauth = 1; + } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) { + // TODO: 802.11r + ignore_received_deauth = 1; + } + } + + DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n", + reason, GetAddr3Ptr(pframe), ignore_received_deauth); - receive_disconnect(padapter, GetAddr3Ptr(pframe) ,reason); + if ( 0 == ignore_received_deauth ) + { + receive_disconnect(padapter, GetAddr3Ptr(pframe) ,reason); + } } pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE; return _SUCCESS; @@ -3835,13 +3851,60 @@ void issue_p2p_GO_confirm(_adapter *padapter, u8* raddr, u8 result) // Type: p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST; - // Length: - *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( pwdinfo->channel_list_attr_len ); + *(u16*) ( p2pie + p2pielen ) = 6; p2pielen += 2; + // Country String + p2pie[ p2pielen++ ] = 'X'; + p2pie[ p2pielen++ ] = 'X'; + + // The third byte should be set to 0x04. + // Described in the "Operating Channel Attribute" section. + p2pie[ p2pielen++ ] = 0x04; + // Value: - _rtw_memcpy( p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len ); - p2pielen += pwdinfo->channel_list_attr_len; + if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) ) + { + if ( pwdinfo->peer_operating_ch <= 14 ) + { + // Operating Class + p2pie[ p2pielen++ ] = 0x51; + } + else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) ) + { + // Operating Class + p2pie[ p2pielen++ ] = 0x73; + } + else + { + // Operating Class + p2pie[ p2pielen++ ] = 0x7c; + } + p2pie[ p2pielen++ ] = 1; + p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch; + } + else + { + if ( pwdinfo->operating_channel <= 14 ) + { + // Operating Class + p2pie[ p2pielen++ ] = 0x51; + } + else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) ) + { + // Operating Class + p2pie[ p2pielen++ ] = 0x73; + } + else + { + // Operating Class + p2pie[ p2pielen++ ] = 0x7c; + } + + // Channel Number + p2pie[ p2pielen++ ] = 1; + p2pie[ p2pielen++ ] = pwdinfo->operating_channel; // Use the listen channel as the operating channel + } if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) ) { @@ -4655,11 +4718,6 @@ void issue_probersp_p2p(_adapter *padapter, unsigned char *da) #ifdef CONFIG_WFD u32 wfdielen = 0; #endif //CONFIG_WFD -#ifdef CONFIG_IOCTL_CFG80211 - struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo; - struct ieee80211_channel *ieee_ch = &pcfg80211_wdinfo->remain_on_ch_channel; - u8 listen_channel = (u8) ieee80211_frequency_to_channel(ieee_ch->center_freq); -#endif //CONFIG_IOCTL_CFG80211 #ifdef CONFIG_INTEL_WIDI u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 }; #endif //CONFIG_INTEL_WIDI @@ -4725,20 +4783,10 @@ void issue_probersp_p2p(_adapter *padapter, unsigned char *da) pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen); // DS parameter set -#ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && listen_channel !=0 ) - { - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&listen_channel, &pattrib->pktlen); - } - else -#endif //CONFIG_IOCTL_CFG80211 - { - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen); - } - + pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen); #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 ) { if( pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL ) { @@ -4781,7 +4829,8 @@ void issue_probersp_p2p(_adapter *padapter, unsigned char *da) #ifdef CONFIG_INTEL_WIDI // Commented by Kurt // Appended WiDi info. only if we did issued_probereq_widi(), and then we saved ven. ext. in pmlmepriv->sa_ext. - if( _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE ) + if( _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE + || pmlmepriv->num_p2p_sdt != 0 ) { //Sec dev type *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SEC_DEV_TYPE_LIST ); @@ -4803,9 +4852,12 @@ void issue_probersp_p2p(_adapter *padapter, unsigned char *da) *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_WIDI_CONSUMER_SINK ); wpsielen += 2; - // Vendor Extension - _rtw_memcpy( wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN ); - wpsielen += L2SDTA_SERVICE_VE_LEN; + if( _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE ) + { + // Vendor Extension + _rtw_memcpy( wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN ); + wpsielen += L2SDTA_SERVICE_VE_LEN; + } } #endif //CONFIG_INTEL_WIDI @@ -4843,7 +4895,12 @@ void issue_probersp_p2p(_adapter *padapter, unsigned char *da) wpsielen += 2; // Value: - _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN ); + if (pwdinfo->external_uuid == 0) { + _rtw_memset( wpsie + wpsielen, 0x0, 16 ); + _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN ); + } else { + _rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 ); + } wpsielen += 0x10; // Manufacturer @@ -4967,7 +5024,7 @@ void issue_probersp_p2p(_adapter *padapter, unsigned char *da) pattrib->pktlen += wfdielen; } #ifdef CONFIG_IOCTL_CFG80211 - else if (pmlmepriv->wfd_probe_resp_ie != NULL && pmlmepriv->wfd_probe_resp_ie_len>0) + else if (pmlmepriv->wfd_probe_resp_ie != NULL && pmlmepriv->wfd_probe_resp_ie_len>0) { //WFD IE _rtw_memcpy(pframe, pmlmepriv->wfd_probe_resp_ie, pmlmepriv->wfd_probe_resp_ie_len); @@ -5069,7 +5126,7 @@ int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack) pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen); #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 ) { if( pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL ) { @@ -5121,7 +5178,12 @@ int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack) wpsielen += 2; // Value: - _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN ); + if (pwdinfo->external_uuid == 0) { + _rtw_memset( wpsie + wpsielen, 0x0, 16 ); + _rtw_memcpy( wpsie + wpsielen, myid( &padapter->eeprompriv ), ETH_ALEN ); + } else { + _rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 ); + } wpsielen += 0x10; // Config Method @@ -5430,6 +5492,8 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) struct wifidirect_info *pwdinfo = &( padapter->wdinfo ); u8 result = P2P_STATUS_SUCCESS; u8 empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + u8 *merged_p2pie = NULL; + u32 merged_p2p_ielen = 0; #endif //CONFIG_P2P frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); @@ -5442,7 +5506,7 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) #ifdef CONFIG_P2P _cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey ); #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) { rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len); } @@ -5499,6 +5563,7 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) ) { padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION; + _cancel_timer_ex(&(padapter->mlmepriv.listen_timer)); intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL); } #endif //CONFIG_INTEL_WIDI @@ -5530,6 +5595,11 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT ) { pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch; + #ifdef P2P_OP_CHECK_SOCIAL_CH + pwdinfo->p2p_info.operation_ch[ 1 ] = 1; //Check whether GO is operating in channel 1; + pwdinfo->p2p_info.operation_ch[ 2 ] = 6; //Check whether GO is operating in channel 6; + pwdinfo->p2p_info.operation_ch[ 3 ] = 11; //Check whether GO is operating in channel 11; + #endif //P2P_OP_CHECK_SOCIAL_CH pwdinfo->p2p_info.scan_op_ch_only = 1; _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH ); } @@ -5559,6 +5629,11 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT ) { pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch; + #ifdef P2P_OP_CHECK_SOCIAL_CH + pwdinfo->p2p_info.operation_ch[ 1 ] = 1; //Check whether GO is operating in channel 1; + pwdinfo->p2p_info.operation_ch[ 2 ] = 6; //Check whether GO is operating in channel 6; + pwdinfo->p2p_info.operation_ch[ 3 ] = 11; //Check whether GO is operating in channel 11; + #endif //P2P_OP_CHECK_SOCIAL_CH pwdinfo->p2p_info.scan_op_ch_only = 1; _set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH ); } @@ -5580,11 +5655,24 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) struct group_id_info group_id; u8 invitation_flag = 0; - rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen); + + merged_p2p_ielen = rtw_get_p2p_merged_ies_len(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_); + + merged_p2pie = rtw_malloc(merged_p2p_ielen); + if (merged_p2pie == NULL) + { + DBG_871X( "[%s] Malloc p2p ie fail\n", __FUNCTION__); + goto exit; + } + _rtw_memset(merged_p2pie, 0x00, merged_p2p_ielen); + + merged_p2p_ielen = rtw_p2p_merge_ies(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, merged_p2pie); + + rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen); if ( attr_contentlen ) { - rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen); + rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen); // Commented by Albert 20120510 // Copy to the pwdinfo->p2p_peer_interface_addr. // So that the WFD UI ( or Sigma ) can get the peer interface address by using the following command. @@ -5604,7 +5692,7 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) // Re-invoke the persistent group. _rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) ); - rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen); + rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen); if ( attr_contentlen ) { if ( _rtw_memcmp( group_id.go_device_addr, myid( &padapter->eeprompriv ), ETH_ALEN ) ) @@ -5620,18 +5708,24 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) if ( is_matched_in_profilelist( pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ] ) ) { u8 operatingch_info[5] = { 0x00 }; - if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) ) + + if ( rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) ) { if( rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4] ) ) { // The operating channel is acceptable for this device. pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4]; + #ifdef P2P_OP_CHECK_SOCIAL_CH + pwdinfo->rx_invitereq_info.operation_ch[1]= 1; //Check whether GO is operating in channel 1; + pwdinfo->rx_invitereq_info.operation_ch[2]= 6; //Check whether GO is operating in channel 6; + pwdinfo->rx_invitereq_info.operation_ch[3]= 11; //Check whether GO is operating in channel 11; + #endif //P2P_OP_CHECK_SOCIAL_CH pwdinfo->rx_invitereq_info.scan_op_ch_only = 1; _set_timer( &pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH ); rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH ); rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT ); status_code = P2P_STATUS_SUCCESS; - } + } else { // The operating channel isn't supported by this device. @@ -5674,7 +5768,7 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) // Received the invitation to join a P2P group. _rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) ); - rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen); + rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen); if ( attr_contentlen ) { if ( _rtw_memcmp( group_id.go_device_addr, myid( &padapter->eeprompriv ), ETH_ALEN ) ) @@ -5714,11 +5808,13 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) pwdinfo->inviteresp_info.token = frame_body[ 7 ]; issue_p2p_invitation_response( padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code ); + _set_timer( &pwdinfo->restore_p2p_state_timer, 3000 ); } #ifdef CONFIG_INTEL_WIDI if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) ) { padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION; + _cancel_timer_ex(&(padapter->mlmepriv.listen_timer)); intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL); } #endif //CONFIG_INTEL_WIDI @@ -5804,6 +5900,7 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) if( (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) && (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_WFD_CONNECTION) ) { padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION; + _cancel_timer_ex(&(padapter->mlmepriv.listen_timer)); intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL); } #endif //CONFIG_INTEL_WIDI @@ -5824,7 +5921,14 @@ unsigned int on_action_public_p2p(union recv_frame *precv_frame) } } #endif //CONFIG_P2P - + +exit: + + if(merged_p2pie) + { + rtw_mfree(merged_p2pie, merged_p2p_ielen); + } + return _SUCCESS; } @@ -5904,6 +6008,45 @@ unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame) return _SUCCESS; } +#ifdef CONFIG_IEEE80211W +unsigned int OnAction_sa_query(_adapter *padapter, union recv_frame *precv_frame) +{ + u8 *pframe = precv_frame->u.hdr.rx_data; + struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + unsigned short tid; + //Baron + + DBG_871X("OnAction_sa_query\n"); + + switch (pframe[WLAN_HDR_A3_LEN+1]) + { + case 0: //SA Query req + _rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short)); + DBG_871X("OnAction_sa_query request,action=%d, tid=%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid); + issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid); + break; + + case 1: //SA Query rsp + _cancel_timer_ex(&pmlmeext->sa_query_timer); + DBG_871X("OnAction_sa_query response,action=%d, tid=%04x, cahcel timer\n", pframe[WLAN_HDR_A3_LEN+1], pframe[WLAN_HDR_A3_LEN+2]); + break; + default: + break; + } + if(0) + { + int pp; + printk("pattrib->pktlen = %d =>", pattrib->pkt_len); + for(pp=0;pp< pattrib->pkt_len; pp++) + printk(" %02x ", pframe[pp]); + printk("\n"); + } + + return _SUCCESS; +} +#endif //CONFIG_IEEE80211W + unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame) { return _SUCCESS; @@ -5935,7 +6078,7 @@ unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame) return _SUCCESS; #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 ) { rtw_cfg80211_rx_action_p2p(padapter, pframe, len); return _SUCCESS; @@ -6087,7 +6230,7 @@ void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib) pattrib->raid = 5;//a/g mode pattrib->encrypt = _NO_PRIVACY_; - pattrib->bswenc = _FALSE; + pattrib->bswenc = _FALSE; pattrib->qos_en = _FALSE; pattrib->ht_en = _FALSE; @@ -6105,7 +6248,11 @@ void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe) { if(padapter->bSurpriseRemoved == _TRUE || padapter->bDriverStopped == _TRUE) + { + rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); + rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); return; + } rtw_hal_mgnt_xmit(padapter, pmgntframe); } @@ -6120,7 +6267,11 @@ s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, i if(padapter->bSurpriseRemoved == _TRUE || padapter->bDriverStopped == _TRUE) + { + rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); + rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); return ret; + } rtw_sctx_init(&sctx, timeout_ms); pxmitbuf->sctx = &sctx; @@ -6147,10 +6298,14 @@ s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntfram if (padapter->pbuddy_adapter && !padapter->isprimary) pxmitpriv = &(padapter->pbuddy_adapter->xmitpriv); #endif - + if(padapter->bSurpriseRemoved == _TRUE || padapter->bDriverStopped == _TRUE) + { + rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); + rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); return -1; + } _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL); pxmitpriv->ack_tx = _TRUE; @@ -6288,7 +6443,7 @@ void issue_beacon(_adapter *padapter, int timeout_ms) remainder_ielen = cur_network->IELength - wps_offset - wpsielen; #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 ) { if(pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len>0) { @@ -6405,7 +6560,7 @@ void issue_beacon(_adapter *padapter, int timeout_ms) { u32 len; #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 ) { len = pmlmepriv->p2p_beacon_ie_len; if(pmlmepriv->p2p_beacon_ie && len>0) @@ -6434,7 +6589,7 @@ void issue_beacon(_adapter *padapter, int timeout_ms) { len = pmlmepriv->wfd_beacon_ie_len; _rtw_memcpy(pframe, pmlmepriv->wfd_beacon_ie, len); - } + } } #endif //CONFIG_IOCTL_CFG80211 pframe += len; @@ -6725,11 +6880,11 @@ void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probe } #ifdef CONFIG_P2P - if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) + if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) /*&& is_valid_p2p_probereq*/) { u32 len; #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 ) { //if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p() len = pmlmepriv->p2p_go_probe_resp_ie_len; @@ -7236,17 +7391,18 @@ void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *p } #ifdef CONFIG_P2P -#ifndef CONFIG_IOCTL_CFG80211 - if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE)) + if( padapter->wdinfo.driver_interface == DRIVER_WEXT ) { - u32 len; + if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE)) + { + u32 len; - len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code); + len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code); - pframe += len; - pattrib->pktlen += len; + pframe += len; + pattrib->pktlen += len; + } } -#endif //CONFIG_IOCTL_CFG80211 #ifdef CONFIG_WFD if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) #ifdef CONFIG_IOCTL_CFG80211 @@ -7564,7 +7720,7 @@ void issue_assocreq(_adapter *padapter) #ifdef CONFIG_P2P #ifdef CONFIG_IOCTL_CFG80211 - if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled) + if(wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 ) { if(pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len>0) { @@ -8202,6 +8358,84 @@ void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_of } +#ifdef CONFIG_IEEE80211W +void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid) +{ + u8 category = RTW_WLAN_CATEGORY_SA_QUERY; + u16 reason_code; + struct xmit_frame *pmgntframe; + struct pkt_attrib *pattrib; + u8 *pframe; + struct rtw_ieee80211_hdr *pwlanhdr; + u16 *fctrl; + struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct sta_info *psta; + struct sta_priv *pstapriv = &padapter->stapriv; + struct registry_priv *pregpriv = &padapter->registrypriv; + + + DBG_871X("%s\n", __FUNCTION__); + + if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) + { + DBG_871X("%s: alloc_mgtxmitframe fail\n", __FUNCTION__); + return; + } + + //update attribute + pattrib = &pmgntframe->attrib; + update_mgntframe_attrib(padapter, pattrib); + + _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); + + pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + + fctrl = &(pwlanhdr->frame_ctl); + *(fctrl) = 0; + + if(raddr) + _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); + else + _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); + _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + + SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); + pmlmeext->mgnt_seq++; + SetFrameSubType(pframe, WIFI_ACTION); + + pframe += sizeof(struct rtw_ieee80211_hdr_3addr); + pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); + + pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); + pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); + + switch (action) + { + case 0: //SA Query req + pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen); + pmlmeext->sa_query_seq++; + //send sa query request to AP, AP should reply sa query response in 1 second + set_sa_query_timer(pmlmeext, 1000); + break; + + case 1: //SA Query rsp + tid = cpu_to_le16(tid); + pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&tid, &pattrib->pktlen); + break; + default: + break; + } + + pattrib->last_txcmdsz = pattrib->pktlen; + + dump_mgntframe(padapter, pmgntframe); +} +#endif //CONFIG_IEEE80211W + void issue_action_BA(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status) { u8 category = RTW_WLAN_CATEGORY_BACK; @@ -8776,7 +9010,6 @@ void site_survey(_adapter *padapter) { pmlmeinfo->scan_cnt = 0; survey_channel = pbuddy_mlmeext->cur_channel; - ScanType = SCAN_ACTIVE; stay_buddy_ch = 1; } else @@ -8877,19 +9110,24 @@ void site_survey(_adapter *padapter) u8 cur_bwmode; u8 cur_ch_offset; - if(check_fwstate(pmlmepriv, _FW_LINKED)) + if (rtw_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0) { - cur_channel = pmlmeext->cur_channel; - cur_bwmode = pmlmeext->cur_bwmode; - cur_ch_offset = pmlmeext->cur_ch_offset; + if (0) + DBG_871X(FUNC_ADPT_FMT" back to linked union - ch:%u, bw:%u, offset:%u\n", + FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset); } - //else if((pbuddy_mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) - else if(check_buddy_fwstate(padapter, _FW_LINKED)) // for AP or STA + #ifdef CONFIG_IOCTL_CFG80211 + else if(padapter->pbuddy_adapter + && pbuddy_adapter->wdinfo.driver_interface == DRIVER_CFG80211 + && wdev_to_priv(pbuddy_adapter->rtw_wdev)->p2p_enabled + && rtw_p2p_chk_state(&pbuddy_adapter->wdinfo, P2P_STATE_LISTEN) + ) { - cur_channel = pbuddy_mlmeext->cur_channel; + cur_channel = pbuddy_adapter->wdinfo.listen_channel; cur_bwmode = pbuddy_mlmeext->cur_bwmode; cur_ch_offset = pbuddy_mlmeext->cur_ch_offset; } + #endif else { cur_channel = pmlmeext->cur_channel; @@ -8954,12 +9192,13 @@ void site_survey(_adapter *padapter) if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) { #ifdef CONFIG_CONCURRENT_MODE - #ifndef CONFIG_IOCTL_CFG80211 - if ( check_buddy_fwstate(padapter, _FW_LINKED ) ) + if( pwdinfo->driver_interface == DRIVER_WEXT ) { - _set_timer( &pwdinfo->ap_p2p_switch_timer, 500 ); - } - #endif //CONFIG_IOCTL_CFG80211 + if ( check_buddy_fwstate(padapter, _FW_LINKED ) ) + { + _set_timer( &pwdinfo->ap_p2p_switch_timer, 500 ); + } + } rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); #else rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); @@ -8974,20 +9213,25 @@ void site_survey(_adapter *padapter) //SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); { +#ifdef CONFIG_CONCURRENT_MODE + set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); +#else #ifdef CONFIG_DUALMAC_CONCURRENT dc_set_channel_bwmode_survey_done(padapter); #else -#ifndef CONFIG_IOCTL_CFG80211 - if( rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ) + if( pwdinfo->driver_interface == DRIVER_WEXT ) { - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); + if( rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ) + { + set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); + } + else + set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); } - else -#endif //CONFIG_IOCTL_CFG80211 -#ifdef CONFIG_CONCURRENT_MODE - set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); -#else + else if( pwdinfo->driver_interface == DRIVER_CFG80211 ) + { set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); + } #endif //CONFIG_DUALMAC_CONCURRENT #endif //CONFIG_CONCURRENT_MODE } @@ -9030,7 +9274,19 @@ void site_survey(_adapter *padapter) report_surveydone_event(padapter); +#if defined(CONFIG_BT_COEXIST) && defined(CONFIG_RTL8723A) + if ((BT_1Ant(padapter) == _TRUE) && (BT_GetBtState(padapter) > BT_INFO_STATE_NO_CONNECTION)) + { + pmlmeext->chan_scan_time = SURVEY_TO * 2; + } + else + { + pmlmeext->chan_scan_time = SURVEY_TO; + } +#else pmlmeext->chan_scan_time = SURVEY_TO; +#endif + pmlmeext->sitesurvey_res.state = SCAN_DISABLE; issue_action_BSSCoexistPacket(padapter); @@ -9089,12 +9345,12 @@ u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSI ie_offset = _BEACON_IE_OFFSET_; } else { // FIXME : more type - if (subtype == WIFI_PROBEREQ) { - ie_offset = _PROBEREQ_IE_OFFSET_; - bssid->Reserved[0] = 2; - } else if (subtype == WIFI_PROBERSP) { + if (subtype == WIFI_PROBERSP) { ie_offset = _PROBERSP_IE_OFFSET_; bssid->Reserved[0] = 3; + } else if (subtype == WIFI_PROBEREQ) { + ie_offset = _PROBEREQ_IE_OFFSET_; + bssid->Reserved[0] = 2; } else { bssid->Reserved[0] = 0; ie_offset = _FIXED_IE_LENGTH_; @@ -9109,7 +9365,7 @@ u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSI //get the signal strength //bssid->Rssi = precv_frame->u.hdr.attrib.SignalStrength; // 0-100 index. - bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; // in dBM.raw data + bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; // in dBM.raw data bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;//in percentage bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;//in percentage #ifdef CONFIG_ANTENNA_DIVERSITY @@ -9181,6 +9437,31 @@ u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSI if (bssid->IELength < 12) return _FAIL; +#ifdef CONFIG_P2P + if (subtype == WIFI_PROBEREQ) { + u8 *p2p_ie; + u32 p2p_ielen; + // Set Listion Channel + if ((p2p_ie = rtw_get_p2p_ie(bssid->IEs, bssid->IELength, NULL, &p2p_ielen))) { + u32 attr_contentlen = 0; + u8 listen_ch[5] = { 0x00 }; + + rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, listen_ch, &attr_contentlen); + bssid->Configuration.DSConfig = listen_ch[4]; + } + else { // use current channel + bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter); + DBG_871X("%s()-%d: Cannot get p2p_ie. set DSconfig to op_ch(%d)\n", __FUNCTION__, __LINE__, bssid->Configuration.DSConfig); + } + + // FIXME + bssid->InfrastructureMode = Ndis802_11Infrastructure; + _rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); + bssid->Privacy = 1; + return _SUCCESS; + } +#endif //CONFIG_P2P + // Checking for DSConfig p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset); @@ -9206,15 +9487,6 @@ u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSI } } - if (subtype==WIFI_PROBEREQ) - { - // FIXME - bssid->InfrastructureMode = Ndis802_11Infrastructure; - _rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); - bssid->Privacy = 1; - return _SUCCESS; - } - _rtw_memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2); bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod); @@ -9270,7 +9542,7 @@ u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSI } #endif // CONFIG_INTEL_WIDI - #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) & 1 + #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1 if(strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) { DBG_871X("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n" , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig @@ -9346,6 +9618,8 @@ void start_create_ibss(_adapter* padapter) DBG_871X("start_create_ibss, invalid cap:%x\n", caps); return; } + //update bc/mc sta_info + update_bmc_sta(padapter); } @@ -9358,9 +9632,6 @@ void start_clnt_join(_adapter* padapter) WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network)); int beacon_timeout; - pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; - pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); - //update wireless mode update_wireless_mode(padapter); @@ -9369,23 +9640,6 @@ void start_clnt_join(_adapter* padapter) update_capinfo(padapter, caps); if (caps&cap_ESS) { - -#ifdef CONFIG_DUALMAC_CONCURRENT - if(dc_handle_join_request(padapter) == _FAIL) - { - DBG_871X("dc_handle_join_request fail !!!\n"); - return; - } - //switch channel - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); -#elif defined (CONFIG_CONCURRENT_MODE) - if(concurrent_chk_start_clnt_join(padapter) == _FAIL) - return; -#else //NON CONCURRENT_MODE - //switch channel - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); -#endif - Set_MSR(padapter, WIFI_FW_STATION_STATE); val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf; @@ -9399,8 +9653,48 @@ void start_clnt_join(_adapter* padapter) #endif rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); - //switch channel - //set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); + #ifdef CONFIG_DEAUTH_BEFORE_CONNECT + // Because of AP's not receiving deauth before + // AP may: 1)not response auth or 2)deauth us after link is complete + // issue deauth before issuing auth to deal with the situation + + // Commented by Albert 2012/07/21 + // For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. + { + #ifdef CONFIG_P2P + _queue *queue = &(padapter->mlmepriv.scanned_queue); + _list *head = get_list_head(queue); + _list *pos = get_next(head); + struct wlan_network *scanned = NULL; + u8 ie_offset = 0; + _irqL irqL; + bool has_p2p_ie = _FALSE; + + _enter_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL); + + for (pos = get_next(head);!rtw_end_of_queue_search(head, pos); pos = get_next(pos)) { + + scanned = LIST_CONTAINOR(pos, struct wlan_network, list); + if(scanned==NULL) + rtw_warn_on(1); + + if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE + && _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE + ) { + ie_offset = (scanned->network.Reserved[0] == 2? 0:12); + if (rtw_get_p2p_ie(scanned->network.IEs+ie_offset, scanned->network.IELength-ie_offset, NULL, NULL)) + has_p2p_ie = _TRUE; + break; + } + } + + _exit_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL); + + if (scanned == NULL || rtw_end_of_queue_search(head, pos) || has_p2p_ie == _FALSE) + #endif /* CONFIG_P2P */ + issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100); + } + #endif /* CONFIG_DEAUTH_BEFORE_CONNECT */ //here wait for receiving the beacon to start auth //and enable a timer @@ -9410,6 +9704,20 @@ void start_clnt_join(_adapter* padapter) (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) +beacon_timeout); pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; + + {//only for STA mode + u16 media_status; + u8 mac_id = 0; + + #ifdef CONFIG_CONCURRENT_MODE + if(PRIMARY_ADAPTER == padapter->adapter_type) + mac_id=0; + else + mac_id=2; + #endif + media_status = (mac_id<<8)|1; // MACID|OPMODE:1 connect + rtw_hal_set_hwreg(padapter,HW_VAR_H2C_MEDIA_STATUS_RPT,(u8 *)&media_status); + } } else if (caps&cap_IBSS) //adhoc client { @@ -9426,9 +9734,6 @@ void start_clnt_join(_adapter* padapter) val8 = 0xcf; rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); - //switch channel - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - beacon_timing_control(padapter); pmlmeinfo->state = WIFI_FW_ADHOC_STATE; @@ -9460,15 +9765,6 @@ void start_clnt_auth(_adapter* padapter) pmlmeext->retry = 0; - // Because of AP's not receiving deauth before - // AP may: 1)not response auth or 2)deauth us after link is complete - // issue deauth before issuing auth to deal with the situation -#ifndef CONFIG_PLATFORM_RTK_DMP - // Commented by Albert 2012/07/21 - // For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. - issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING); -#endif - DBG_871X_LEVEL(_drv_always_, "start auth\n"); issue_auth(padapter, NULL, 0); @@ -10159,6 +10455,8 @@ void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res) u8 join_type; u16 media_status; + psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); + if(join_res < 0) { join_type = 1; @@ -10168,6 +10466,11 @@ void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res) //restore to initial setting. update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode); + if (psta){//only for STA mode + media_status = (psta->mac_id<<8)|0; // MACID|OPMODE:1 connect + rtw_hal_set_hwreg(padapter,HW_VAR_H2C_MEDIA_STATUS_RPT,(u8 *)&media_status); + } + goto exit_mlmeext_joinbss_event_callback; } @@ -10181,6 +10484,8 @@ void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res) update_bmc_sta_support_rate(padapter, psta_bmc->mac_id); Update_RA_Entry(padapter, psta_bmc); } + //update bc/mc sta_info + update_bmc_sta(padapter); } @@ -10210,7 +10515,7 @@ void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res) set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); #endif - psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); + if (psta) //only for infra. mode { pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; @@ -10222,11 +10527,7 @@ void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res) //set per sta rate after updating HT cap. set_sta_rate(padapter, psta); - #if (RATE_ADAPTIVE_SUPPORT==1) //for 88E RA - rtw_hal_set_hwreg(padapter,HW_VAR_TX_RPT_MAX_MACID, (u8*)&psta->mac_id); - #endif - media_status = (psta->mac_id<<8)|1; // MACID|OPMODE: 1 means connect - rtw_hal_set_hwreg(padapter,HW_VAR_H2C_MEDIA_STATUS_RPT,(u8 *)&media_status); + rtw_sta_media_status_rpt(padapter, psta, 1); } join_type = 2; @@ -10403,8 +10704,8 @@ void _linked_rx_signal_strehgth_display(_adapter *padapter) #endif - rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); - DBG_871X("UndecoratedSmoothedPWDB:%d\n",UndecoratedSmoothedPWDB); + //rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); + //DBG_871X("UndecoratedSmoothedPWDB:%d\n",UndecoratedSmoothedPWDB); } @@ -10483,10 +10784,13 @@ void linked_status_chk(_adapter *padapter) rx_chk_limit = 8; #endif - #ifdef CONFIG_INTEL_WIDI - if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE) - rx_chk_limit = 1; - #endif + // Marked by Kurt 20130715 + // For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly. + // todo: To check why we under miracast session, rx_chk would be _FALSE + //#ifdef CONFIG_INTEL_WIDI + //if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE) + // rx_chk_limit = 1; + //#endif if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) { @@ -10861,6 +11165,27 @@ void addba_timer_hdl(struct sta_info *psta) #endif //CONFIG_80211N_HT } +#ifdef CONFIG_IEEE80211W +void sa_query_timer_hdl(_adapter *padapter) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_priv * pmlmepriv = &padapter->mlmepriv; + _irqL irqL; + //disconnect + _enter_critical_bh(&pmlmepriv->lock, &irqL); + + if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) + { + rtw_disassoc_cmd(padapter, 0, _TRUE); + rtw_indicate_disconnect(padapter); + rtw_free_assoc_resources(padapter, 1); + } + + _exit_critical_bh(&pmlmepriv->lock, &irqL); + DBG_871X("SA query timeout disconnect\n"); +} +#endif //CONFIG_IEEE80211W + u8 NULL_hdl(_adapter *padapter, u8 *pbuf) { return H2C_SUCCESS; @@ -11037,6 +11362,9 @@ u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf) _rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength); + pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; + pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); + //Check AP vendor to move rtw_joinbss_cmd() //pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); @@ -11135,6 +11463,20 @@ u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf) //initialgain = 0x1E; //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); + /* check channel, bandwidth, offset and switch */ +#ifdef CONFIG_DUALMAC_CONCURRENT + if(dc_handle_join_request(padapter) == _FAIL) { + DBG_871X("dc_handle_join_request fail !!!\n"); + return H2C_SUCCESS; + } + set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); +#else //NON CONFIG_DUALMAC_CONCURRENT + if(rtw_chk_start_clnt_join(padapter) == _FAIL) { + report_join_res(padapter, (-4)); + return H2C_SUCCESS; + } +#endif + rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress); join_type = 0; rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); @@ -11290,8 +11632,10 @@ u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf) if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { +#ifdef CONFIG_CONCURRENT_MODE //for first time sitesurvey_cmd rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0); +#endif //CONFIG_CONCURRENT_MODE pmlmeext->sitesurvey_res.state = SCAN_START; pmlmeext->sitesurvey_res.bss_cnt = 0; @@ -11379,23 +11723,17 @@ u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf) Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE); //config the initial gain under scaning, need to write the BB registers +#ifdef CONFIG_P2P #ifdef CONFIG_IOCTL_CFG80211 - if((wdev_to_priv(padapter->rtw_wdev))->p2p_enabled == _TRUE) - { + if((wdev_to_priv(padapter->rtw_wdev))->p2p_enabled == _TRUE && pwdinfo->driver_interface == DRIVER_CFG80211 ) initialgain = 0x30; - } - else - initialgain = 0x1E; -#else // go through the WEXT interface //CONFIG_IOCTL_CFG80211 -#ifdef CONFIG_P2P - if ( rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) ) - initialgain = 0x1E; else +#endif //CONFIG_IOCTL_CFG80211 + if ( !rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) ) initialgain = 0x28; -#else // CONFIG_P2P - initialgain = 0x1E; -#endif // CONFIG_P2P -#endif // CONFIG_IOCTL_CFG80211 + else +#endif //CONFIG_P2P + initialgain = 0x1e; rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); @@ -12461,108 +12799,6 @@ sint check_buddy_mlmeinfo_state(_adapter *padapter, u32 state) } -int concurrent_chk_start_clnt_join(_adapter *padapter) -{ - int ret = _FAIL; - PADAPTER pbuddy_adapter; - struct mlme_ext_priv *pbuddy_mlmeext; - struct mlme_ext_info *pbuddy_pmlmeinfo; - struct mlme_priv *pbuddy_mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - unsigned char cur_ch = pmlmeext->cur_channel; - unsigned char cur_bw = pmlmeext->cur_bwmode; - unsigned char cur_ch_offset = pmlmeext->cur_ch_offset; - - if(!rtw_buddy_adapter_up(padapter)) - { - goto start_join_set_ch_bw; - } - - pbuddy_adapter = padapter->pbuddy_adapter; - pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; - pbuddy_pmlmeinfo = &(pbuddy_mlmeext->mlmext_info); - pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv); - - if((pbuddy_pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)//for AP MODE - { - bool inform_ch_switch = _FALSE; - if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel) - { - inform_ch_switch = _TRUE; - } - else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && - (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && - (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)) - { - inform_ch_switch = _TRUE; - } - else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20) && - (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)) - { - inform_ch_switch = _FALSE; - cur_ch = pmlmeext->cur_channel; - cur_bw = pbuddy_mlmeext->cur_bwmode; - cur_ch_offset = pbuddy_mlmeext->cur_ch_offset; - } - - - if (inform_ch_switch) { - #ifdef CONFIG_SPCT_CH_SWITCH - if (1) { - rtw_ap_inform_ch_switch(pbuddy_adapter, pmlmeext->cur_channel , pmlmeext->cur_ch_offset); - } else - #endif - { - //issue deauth to all stas if if2 is at ap mode - rtw_sta_flush(pbuddy_adapter); - } - rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0); - } - } - else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE && - check_fwstate(pbuddy_mlmepriv, WIFI_STATION_STATE) == _TRUE) //for Client Mode/p2p client - { -#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) - struct wifidirect_info *pbuddy_wdinfo = &(pbuddy_adapter->wdinfo); - if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) - { - goto start_join_set_ch_bw;//wlan0-sta mode has higher priority than p2p0-p2p client - } -#endif //CONFIG_P2P && CONFIG_IOCTL_CFG80211 - - if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel) - { - DBG_871X("start_clnt_join(ch=%d), but channel mismatch with buddy(ch=%d) interface\n", - pmlmeext->cur_channel, pbuddy_mlmeext->cur_channel); - - report_join_res(padapter, (-4)); - - return ret; - } - - if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && - (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && - (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)) - { - DBG_871X("start_clnt_join(bwmode=%d, ch_offset=%d), but bwmode & ch_offset mismatch with buddy(bwmode=%d, ch_offset=%d) interface\n", - pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset); - - report_join_res(padapter, (-4)); - - return ret; - } - - } - - -start_join_set_ch_bw: - - set_channel_bwmode(padapter, cur_ch, cur_ch_offset, cur_bw); - - return _SUCCESS; - -} - void concurrent_chk_joinbss_done(_adapter *padapter, int join_res) { struct mlme_ext_priv *pmlmeext; @@ -12573,15 +12809,16 @@ void concurrent_chk_joinbss_done(_adapter *padapter, int join_res) struct mlme_ext_info *pbuddy_mlmeinfo; WLAN_BSSID_EX *pbuddy_network_mlmeext; + pmlmeext = &padapter->mlmeextpriv; + pmlmeinfo = &(pmlmeext->mlmext_info); + + if(!rtw_buddy_adapter_up(padapter)) { set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); return; } - pmlmeext = &padapter->mlmeextpriv; - pmlmeinfo = &(pmlmeext->mlmext_info); - pbuddy_adapter = padapter->pbuddy_adapter; pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv); pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; @@ -12772,6 +13009,181 @@ void concurrent_chk_joinbss_done(_adapter *padapter, int join_res) } #endif //CONFIG_CONCURRENT_MODE +int rtw_chk_start_clnt_join(_adapter *padapter) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + unsigned char cur_ch = pmlmeext->cur_channel; + unsigned char cur_bw = pmlmeext->cur_bwmode; + unsigned char cur_ch_offset = pmlmeext->cur_ch_offset; + bool chbw_allow = _TRUE; + bool connect_allow = _TRUE; + +#ifdef CONFIG_CONCURRENT_MODE + PADAPTER pbuddy_adapter; + struct mlme_ext_priv *pbuddy_mlmeext; + struct mlme_ext_info *pbuddy_pmlmeinfo; + struct mlme_priv *pbuddy_mlmepriv; + + if (!rtw_buddy_adapter_up(padapter)) { + goto start_join_set_ch_bw; + } + + pbuddy_adapter = padapter->pbuddy_adapter; + pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; + pbuddy_pmlmeinfo = &(pbuddy_mlmeext->mlmext_info); + pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv); + + if((pbuddy_pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)//for AP MODE + { + DBG_871X("start_clnt_join: "ADPT_FMT"(ch=%d, bw=%d, ch_offset=%d)" + ", "ADPT_FMT" AP mode(ch=%d, bw=%d, ch_offset=%d)\n", + ADPT_ARG(padapter), pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset, + ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset); + + if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel) + { + chbw_allow = _FALSE; + } + else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && + (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && + (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)) + { + chbw_allow = _FALSE; + } + else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20) && + (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)) + { + cur_ch = pmlmeext->cur_channel; + cur_bw = pbuddy_mlmeext->cur_bwmode; + cur_ch_offset = pbuddy_mlmeext->cur_ch_offset; + } + + DBG_871X("start_clnt_join: connect_allow:%d, chbw_allow:%d\n", connect_allow, chbw_allow); + if (chbw_allow == _FALSE) { + #ifdef CONFIG_SPCT_CH_SWITCH + if (1) { + rtw_ap_inform_ch_switch(pbuddy_adapter, pmlmeext->cur_channel , pmlmeext->cur_ch_offset); + } else + #endif + { + //issue deauth to all stas if if2 is at ap mode + rtw_sta_flush(pbuddy_adapter); + } + rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0); + } + } + else if(check_fwstate(pbuddy_mlmepriv, _FW_LINKED) == _TRUE && + check_fwstate(pbuddy_mlmepriv, WIFI_STATION_STATE) == _TRUE) //for Client Mode/p2p client + { + DBG_871X("start_clnt_join: "ADPT_FMT"(ch=%d, bw=%d, ch_offset=%d)" + ", "ADPT_FMT" STA mode(ch=%d, bw=%d, ch_offset=%d)\n", + ADPT_ARG(padapter), pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset, + ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset); + + if(pmlmeext->cur_channel != pbuddy_mlmeext->cur_channel) + { + chbw_allow = _FALSE; + } + else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20) && + (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)) + { + cur_bw = HT_CHANNEL_WIDTH_40; + cur_ch_offset = pbuddy_mlmeext->cur_ch_offset; + } + else if((pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && + (pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40) && + (pmlmeext->cur_ch_offset != pbuddy_mlmeext->cur_ch_offset)) + { + chbw_allow = _FALSE; + } + + connect_allow = chbw_allow; + + #if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) + /* wlan0-sta mode has higher priority than p2p0-p2p client */ + if (!rtw_p2p_chk_state(&(pbuddy_adapter->wdinfo), P2P_STATE_NONE) + && pbuddy_adapter->wdinfo.driver_interface == DRIVER_CFG80211) + { + connect_allow = _TRUE; + } + #endif /* CONFIG_P2P && CONFIG_IOCTL_CFG80211 */ + + DBG_871X("start_clnt_join: connect_allow:%d, chbw_allow:%d\n", connect_allow, chbw_allow); + if (connect_allow == _TRUE && chbw_allow == _FALSE) { + /* disconnect buddy's connection */ + rtw_disassoc_cmd(pbuddy_adapter, 500, _FALSE); + rtw_indicate_disconnect(pbuddy_adapter); + rtw_free_assoc_resources(pbuddy_adapter, 1); + } + } + +start_join_set_ch_bw: +#endif /* CONFIG_CONCURRENT_MODE */ + + if (connect_allow == _TRUE) { + DBG_871X("start_join_set_ch_bw: ch=%d, bwmode=%d, ch_offset=%d\n", cur_ch, cur_bw, cur_ch_offset); + set_channel_bwmode(padapter, cur_ch, cur_ch_offset, cur_bw); + } + + return connect_allow == _TRUE ? _SUCCESS : _FAIL; +} + +/* Find union about ch, bw, ch_offset of all linked interfaces */ +int rtw_get_ch_setting_union(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset) +{ + struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); + _adapter *iface; + struct mlme_ext_priv *mlmeext; + int i; + u8 ch_ret = 0; + u8 bw_ret = HT_CHANNEL_WIDTH_20; + u8 offset_ret = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + int num = 0; + + if (ch) *ch = 0; + if (bw) *bw = HT_CHANNEL_WIDTH_20; + if (offset) *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + + for (i = 0; i<dvobj->iface_nums; i++) { + iface = dvobj->padapters[i]; + mlmeext = &iface->mlmeextpriv; + + if (!check_fwstate(&iface->mlmepriv, _FW_LINKED)) + continue; + + if (num == 0) { + ch_ret = mlmeext->cur_channel; + bw_ret = mlmeext->cur_bwmode; + offset_ret = mlmeext->cur_ch_offset; + num++; + continue; + } + + if (ch_ret != mlmeext->cur_channel) { + num = 0; + break; + } + + if (bw_ret < mlmeext->cur_bwmode) { + bw_ret = mlmeext->cur_bwmode; + offset_ret = mlmeext->cur_ch_offset; + } else if (bw_ret == mlmeext->cur_bwmode && offset_ret != mlmeext->cur_ch_offset) { + num = 0; + break; + } + + num++; + } + + if (num) { + if (ch) *ch = ch_ret; + if (bw) *bw = bw_ret; + if (offset) *offset = offset_ret; + } + + return num; +} + u8 set_ch_hdl(_adapter *padapter, u8 *pbuf) { struct set_ch_parm *set_ch_parm; diff --git a/drivers/net/wireless/rtl8723as/core/rtw_mp.c b/drivers/net/wireless/rtl8723as/core/rtw_mp.c index a63604fcc61e..75f0da1ab224 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_mp.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_mp.c @@ -570,7 +570,7 @@ static void disable_dm(PADAPTER padapter) #endif HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; - + PDM_ODM_T pDM_Odm = &(pHalData->odmpriv); //3 1. disable firmware dynamic mechanism // disable Power Training, Rate Adaptive @@ -590,7 +590,7 @@ static void disable_dm(PADAPTER padapter) // enable APK, LCK and IQK but disable power tracking #ifndef CONFIG_RTL8188E - pdmpriv->TxPowerTrackControl = _FALSE; + pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = _FALSE; #endif Switch_DM_Func(padapter, DYNAMIC_RF_CALIBRATION, _TRUE); } @@ -600,7 +600,7 @@ void MPT_PwrCtlDM(PADAPTER padapter, u32 bstart) { HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); struct dm_priv *pdmpriv = &pHalData->dmpriv; - + PDM_ODM_T pDM_Odm = &(pHalData->odmpriv); //Switch_DM_Func(padapter, DYNAMIC_RF_CALIBRATION, bstart); if (bstart==1){ DBG_871X("in MPT_PwrCtlDM start \n"); @@ -608,10 +608,16 @@ void MPT_PwrCtlDM(PADAPTER padapter, u32 bstart) pdmpriv->InitODMFlag |= ODM_RF_TX_PWR_TRACK ; pdmpriv->InitODMFlag |= ODM_RF_CALIBRATION ; pdmpriv->TxPowerTrackControl = _TRUE; +#ifndef CONFIG_RTL8188E + pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = _TRUE; +#endif }else{ DBG_871X("in MPT_PwrCtlDM stop \n"); disable_dm(padapter); pdmpriv->TxPowerTrackControl = _FALSE; + #ifndef CONFIG_RTL8188E + pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = _FALSE; + #endif } @@ -638,7 +644,6 @@ s32 mp_start_test(PADAPTER padapter) //3 disable dynamic mechanism disable_dm(padapter); - //3 0. update mp_priv if (padapter->registrypriv.rf_config == RF_819X_MAX_TYPE) { @@ -1316,16 +1321,17 @@ void SetPacketRx(PADAPTER pAdapter, u8 bStartRx) if(bStartRx) { - #ifdef CONFIG_RTL8723A - rtl8723a_InitAntenna_Selection(pAdapter); - #endif //CONFIG_RTL8723A - // Accept CRC error and destination address + // Accept CRC error and destination address #if 1 //ndef CONFIG_RTL8723A - pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | ADF | AMF | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS; - - pHalData->ReceiveConfig |= ACRC32; + //pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | ADF | AMF | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS; + //pHalData->ReceiveConfig |= ACRC32; + + pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | AMF | ADF | APP_FCS | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS; + + pHalData->ReceiveConfig |= (RCR_ACRC32|RCR_AAP); + rtw_write32(pAdapter, REG_RCR, pHalData->ReceiveConfig); // Accept all data frames @@ -1488,8 +1494,13 @@ void _rtw_mp_xmit_priv (struct xmit_priv *pxmitpriv) } else { - max_xmit_extbuf_size = 6000; - num_xmit_extbuf = 8; + #ifdef CONFIG_RTL8723A_SDIO + max_xmit_extbuf_size = 20000; + num_xmit_extbuf = 1; + #else + max_xmit_extbuf_size = 6000; + num_xmit_extbuf = 8; + #endif } pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; @@ -1506,8 +1517,13 @@ void _rtw_mp_xmit_priv (struct xmit_priv *pxmitpriv) if(padapter->registrypriv.mp_mode ==0) { - max_xmit_extbuf_size = 6000; - num_xmit_extbuf = 8; + #ifdef CONFIG_RTL8723A_SDIO + max_xmit_extbuf_size = 20000; + num_xmit_extbuf = 1; + #else + max_xmit_extbuf_size = 6000; + num_xmit_extbuf = 8; + #endif } else { diff --git a/drivers/net/wireless/rtl8723as/core/rtw_mp_ioctl.c b/drivers/net/wireless/rtl8723as/core/rtw_mp_ioctl.c index 4771bc6a050a..95570d1e75e8 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_mp_ioctl.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_mp_ioctl.c @@ -1677,12 +1677,12 @@ _func_enter_; return NDIS_STATUS_INVALID_LENGTH; *poid_par_priv->bytes_rw = 8; - _rtw_memcpy(poid_par_priv->information_buf, &(Adapter->pwrctrlpriv.pwr_mode), 8); + _rtw_memcpy(poid_par_priv->information_buf, &(adapter_to_pwrctl(Adapter)->pwr_mode), 8); *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len; RT_TRACE(_module_mp_, _drv_notice_, ("-oid_rt_pro_qry_pwrstate_hdl: pwr_mode=%d smart_ps=%d\n", - Adapter->pwrctrlpriv.pwr_mode, Adapter->pwrctrlpriv.smart_ps)); + adapter_to_pwrctl(Adapter)->pwr_mode, adapter_to_pwrctl(Adapter)->smart_ps)); _func_exit_; diff --git a/drivers/net/wireless/rtl8723as/core/rtw_odm.c b/drivers/net/wireless/rtl8723as/core/rtw_odm.c new file mode 100755 index 000000000000..b7176266e149 --- /dev/null +++ b/drivers/net/wireless/rtl8723as/core/rtw_odm.c @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * Copyright(c) 2013 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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, USA + * + * + ******************************************************************************/ + +#include <rtw_odm.h> +#ifdef CONFIG_RTL8192C +#include <rtl8192c_hal.h> +#endif +#ifdef CONFIG_RTL8192D +#include <rtl8192d_hal.h> +#endif +#ifdef CONFIG_RTL8723A +#include <rtl8723a_hal.h> +#endif +#ifdef CONFIG_RTL8188E +#include <rtl8188e_hal.h> +#endif + +const char *odm_comp_str[] = { + "ODM_COMP_DIG", + "ODM_COMP_RA_MASK", + "ODM_COMP_DYNAMIC_TXPWR", + "ODM_COMP_FA_CNT", + "ODM_COMP_RSSI_MONITOR", + "ODM_COMP_CCK_PD", + "ODM_COMP_ANT_DIV", + "ODM_COMP_PWR_SAVE", + "ODM_COMP_PWR_TRAIN", + "ODM_COMP_RATE_ADAPTIVE", + "ODM_COMP_PATH_DIV", + "ODM_COMP_PSD", + "ODM_COMP_DYNAMIC_PRICCA", + "ODM_COMP_RXHP", + NULL, + NULL, + "ODM_COMP_EDCA_TURBO", + "ODM_COMP_EARLY_MODE", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "ODM_COMP_TX_PWR_TRACK", + "ODM_COMP_RX_GAIN_TRACK", + "ODM_COMP_CALIBRATION", + NULL, + NULL, + NULL, + "ODM_COMP_COMMON", + "ODM_COMP_INIT", +}; + +#define RTW_ODM_COMP_MAX 32 + +const char *odm_ability_str[] = { + "ODM_BB_DIG", + "ODM_BB_RA_MASK", + "ODM_BB_DYNAMIC_TXPWR", + "ODM_BB_FA_CNT", + "ODM_BB_RSSI_MONITOR", + "ODM_BB_CCK_PD ", + "ODM_BB_ANT_DIV", + "ODM_BB_PWR_SAVE", + "ODM_BB_PWR_TRAIN", + "ODM_BB_RATE_ADAPTIVE", + "ODM_BB_PATH_DIV", + "ODM_BB_PSD", + "ODM_BB_RXHP", + "ODM_BB_ADAPTIVITY", + "ODM_BB_DYNAMIC_ATC", + NULL, + "ODM_MAC_EDCA_TURBO", + "ODM_MAC_EARLY_MODE", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "ODM_RF_TX_PWR_TRACK", + "ODM_RF_RX_GAIN_TRACK", + "ODM_RF_CALIBRATION", +}; + +#define RTW_ODM_ABILITY_MAX 27 + +const char *odm_dbg_level_str[] = { + NULL, + "ODM_DBG_OFF", + "ODM_DBG_SERIOUS", + "ODM_DBG_WARNING", + "ODM_DBG_LOUD", + "ODM_DBG_TRACE ", +}; + +#define RTW_ODM_DBG_LEVEL_NUM 6 + +int _rtw_odm_dbg_comp_msg(_adapter *adapter, char *buf, int len) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + DM_ODM_T *odm = &pHalData->odmpriv; + int cnt = 0; + u64 dbg_comp; + int i; + + rtw_hal_get_def_var(adapter, HW_DEF_ODM_DBG_FLAG, &dbg_comp); + cnt += snprintf(buf+cnt, len-cnt, "odm.DebugComponents = 0x%016llx \n", dbg_comp); + for (i=0;i<RTW_ODM_COMP_MAX;i++) { + if (odm_comp_str[i]) + cnt += snprintf(buf+cnt, len-cnt, "%cBIT%-2d %s\n", + (BIT0 << i) & dbg_comp ? '+' : ' ', i, odm_comp_str[i]); + } + + return cnt; +} + +void rtw_odm_dbg_comp_msg(_adapter *adapter) +{ + char buf[768] = {0}; + + _rtw_odm_dbg_comp_msg(adapter, buf, 768); + DBG_871X_LEVEL(_drv_always_, "\n%s", buf); +} + +inline void rtw_odm_dbg_comp_set(_adapter *adapter, u64 comps) +{ + rtw_hal_set_def_var(adapter, HW_DEF_ODM_DBG_FLAG, &comps); +} + +int _rtw_odm_dbg_level_msg(_adapter *adapter, char *buf, int len) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + DM_ODM_T *odm = &pHalData->odmpriv; + int cnt = 0; + u32 dbg_level; + int i; + + rtw_hal_get_def_var(adapter, HW_DEF_ODM_DBG_LEVEL, &dbg_level); + cnt += snprintf(buf+cnt, len-cnt, "odm.DebugDebugLevel = %u\n", dbg_level); + for (i=0;i<RTW_ODM_DBG_LEVEL_NUM;i++) { + if (odm_dbg_level_str[i]) + cnt += snprintf(buf+cnt, len-cnt, "%u %s\n", i, odm_dbg_level_str[i]); + } + + return cnt; +} + +void rtw_odm_dbg_level_msg(_adapter *adapter) +{ + char buf[100] = {0}; + + _rtw_odm_dbg_comp_msg(adapter, buf, 100); + DBG_871X_LEVEL(_drv_always_, "\n%s", buf); +} + +inline void rtw_odm_dbg_level_set(_adapter *adapter, u32 level) +{ + rtw_hal_set_def_var(adapter, HW_DEF_ODM_DBG_LEVEL, &level); +} + +int _rtw_odm_adaptivity_parm_msg(_adapter *adapter, char *buf, int len) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + DM_ODM_T *odm = &pHalData->odmpriv; + + return snprintf(buf, len, + "%10s %16s %8s %10s %11s %14s\n" + "0x%-8x %-16d 0x%-6x %-10d %-11u %-14u\n", + "TH_L2H_ini", "TH_EDCCA_HL_diff", "IGI_Base", "ForceEDCCA", "AdapEn_RSSI", "IGI_LowerBound", + (u8)odm->TH_L2H_ini, + odm->TH_EDCCA_HL_diff, + odm->IGI_Base, + odm->ForceEDCCA, + odm->AdapEn_RSSI, + odm->IGI_LowerBound + ); +} + +void rtw_odm_adaptivity_parm_msg(_adapter *adapter) +{ + char buf[256] = {0}; + + _rtw_odm_dbg_comp_msg(adapter, buf, 256); + DBG_871X_LEVEL(_drv_always_, "\n%s", buf); +} + +void rtw_odm_adaptivity_parm_set(_adapter *adapter, s8 TH_L2H_ini, s8 TH_EDCCA_HL_diff, + s8 IGI_Base, bool ForceEDCCA, u8 AdapEn_RSSI, u8 IGI_LowerBound) +{ + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); + DM_ODM_T *odm = &pHalData->odmpriv; + + odm->TH_L2H_ini = TH_L2H_ini; + odm->TH_EDCCA_HL_diff = TH_EDCCA_HL_diff; + odm->IGI_Base = IGI_Base; + odm->ForceEDCCA = ForceEDCCA; + odm->AdapEn_RSSI = AdapEn_RSSI; + odm->IGI_LowerBound = IGI_LowerBound; +} + diff --git a/drivers/net/wireless/rtl8723as/core/rtw_p2p.c b/drivers/net/wireless/rtl8723as/core/rtw_p2p.c index 0ed4b5e31065..348bdb88357c 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_p2p.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_p2p.c @@ -1888,7 +1888,18 @@ u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 }; u32 len=0, p2pielen = 0; #ifdef CONFIG_INTEL_WIDI + struct mlme_priv *pmlmepriv = &(pwdinfo->padapter->mlmepriv); u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 }; + u8 widi_version = 0, i = 0; + + if( _rtw_memcmp( pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN ) == _FALSE ) + { + widi_version = 35; + } + else if( pmlmepriv->num_p2p_sdt != 0 ) + { + widi_version = 40; + } #endif //CONFIG_INTEL_WIDI // P2P OUI @@ -1977,10 +1988,14 @@ u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) // + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) //*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); #ifdef CONFIG_INTEL_WIDI - if( _rtw_memcmp( pwdinfo->padapter->mlmepriv.sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN ) == _FALSE ) + if( widi_version == 35 ) { RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 + pwdinfo->device_name_len); } + else if( widi_version == 40 ) + { + RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 * pmlmepriv->num_p2p_sdt + pwdinfo->device_name_len); + } else #endif //CONFIG_INTEL_WIDI RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len); @@ -1997,25 +2012,48 @@ u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm); p2pielen += 2; - // Primary Device Type - // Category ID - //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); - RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; +#ifdef CONFIG_INTEL_WIDI + if( widi_version == 40 ) + { + // Primary Device Type + // Category ID + //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); + RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_cid ); + p2pielen += 2; - // OUI - //*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); - RTW_PUT_BE32(p2pie + p2pielen, WPSOUI); - p2pielen += 4; + // OUI + //*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); + RTW_PUT_BE32(p2pie + p2pielen, WPSOUI); + p2pielen += 4; - // Sub Category ID - //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); - RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; + // Sub Category ID + //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); + RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_scid); + p2pielen += 2; + } + else +#endif //CONFIG_INTEL_WIDI + { + // Primary Device Type + // Category ID + //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA ); + RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA); + p2pielen += 2; + + // OUI + //*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI ); + RTW_PUT_BE32(p2pie + p2pielen, WPSOUI); + p2pielen += 4; + + // Sub Category ID + //*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER ); + RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER); + p2pielen += 2; + } // Number of Secondary Device Types #ifdef CONFIG_INTEL_WIDI - if( _rtw_memcmp( pwdinfo->padapter->mlmepriv.sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN ) == _FALSE ) + if( widi_version == 35 ) { p2pie[ p2pielen++ ] = 0x01; @@ -2028,6 +2066,21 @@ u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf) RTW_PUT_BE16(p2pie + p2pielen, P2P_SCID_WIDI_CONSUMER_SINK); p2pielen += 2; } + else if( widi_version == 40 ) + { + p2pie[ p2pielen++ ] = pmlmepriv->num_p2p_sdt; + for( ; i < pmlmepriv->num_p2p_sdt; i++ ) + { + RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_cid[i]); + p2pielen += 2; + + RTW_PUT_BE32(p2pie + p2pielen, INTEL_DEV_TYPE_OUI); + p2pielen += 4; + + RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_scid[i]); + p2pielen += 2; + } + } else #endif //CONFIG_INTEL_WIDI p2pie[ p2pielen++ ] = 0x00; // No Secondary Device Type List @@ -2732,11 +2785,11 @@ u8 process_p2p_group_negotation_req( struct wifidirect_info *pwdinfo, u8 *pframe { u8 attr_content = 0x00; u32 attr_contentlen = 0; - u8 ch_content[50] = { 0x00 }; + u8 ch_content[100] = { 0x00 }; uint ch_cnt = 0; - u8 peer_ch_list[50] = { 0x00 }; + u8 peer_ch_list[100] = { 0x00 }; u8 peer_ch_num = 0; - u8 ch_list_inclusioned[50] = { 0x00 }; + u8 ch_list_inclusioned[100] = { 0x00 }; u8 ch_num_inclusioned = 0; u16 cap_attr; @@ -2934,12 +2987,12 @@ u8 process_p2p_group_negotation_resp( struct wifidirect_info *pwdinfo, u8 *pfram u32 attr_contentlen = 0; u8 operatingch_info[5] = { 0x00 }; uint ch_cnt = 0; - u8 ch_content[50] = { 0x00 }; + u8 ch_content[100] = { 0x00 }; u8 groupid[ 38 ]; u16 cap_attr; - u8 peer_ch_list[50] = { 0x00 }; + u8 peer_ch_list[100] = { 0x00 }; u8 peer_ch_num = 0; - u8 ch_list_inclusioned[50] = { 0x00 }; + u8 ch_list_inclusioned[100] = { 0x00 }; u8 ch_num_inclusioned = 0; while ( p2p_ie ) // Found the P2P IE. @@ -3392,98 +3445,100 @@ _func_enter_; struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; pwdinfo->operating_channel = pbuddy_mlmeext->cur_channel; -#ifdef CONFIG_IOCTL_CFG80211 - DBG_871X("%s, switch ch back to buddy's cur_channel=%d\n", __func__, pbuddy_mlmeext->cur_channel); + if( pwdinfo->driver_interface == DRIVER_CFG80211 ) + { + DBG_871X("%s, switch ch back to buddy's cur_channel=%d\n", __func__, pbuddy_mlmeext->cur_channel); - set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode); + set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode); - issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500); - -#else //CONFIG_IOCTL_CFG80211 - if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) + issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500); + } + else if( pwdinfo->driver_interface == DRIVER_WEXT ) { - // Now, the driver stays on the AP's channel. - // If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. - if ( pwdinfo->ext_listen_period > 0 ) + if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) + { + // Now, the driver stays on the AP's channel. + // If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. + if ( pwdinfo->ext_listen_period > 0 ) + { + DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period ); + + if ( pbuddy_mlmeext->cur_channel != pwdinfo->listen_channel ) + { + // Will switch to listen channel so that need to send the NULL data with PW bit to AP. + issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500); + set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); + } + + rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN); + val8 = 1; + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + + // Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. + _set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period ); + } + } + else if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) || + rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) || + ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE ) || + rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ) ) { - DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period ); + // Now, the driver is in the listen state of P2P mode. + DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval ); + // Commented by Albert 2012/11/01 + // If the AP's channel is the same as the listen channel, we should still be in the listen state + // Other P2P device is still able to find this device out even this device is in the AP's channel. + // So, configure this device to be able to receive the probe request frame and set it to listen state. if ( pbuddy_mlmeext->cur_channel != pwdinfo->listen_channel ) { - // Will switch to listen channel so that need to send the NULL data with PW bit to AP. - issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500); - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); + set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode); + val8 = 0; + padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE); + issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500); } - rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN); - val8 = 1; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - - // Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. - _set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period ); + // Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. + _set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval ); } - } - else if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) || - rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) || - ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE ) || - rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ) ) - { - // Now, the driver is in the listen state of P2P mode. - DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval ); - - // Commented by Albert 2012/11/01 - // If the AP's channel is the same as the listen channel, we should still be in the listen state - // Other P2P device is still able to find this device out even this device is in the AP's channel. - // So, configure this device to be able to receive the probe request frame and set it to listen state. - if ( pbuddy_mlmeext->cur_channel != pwdinfo->listen_channel ) + else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) { - set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode); + // The driver had finished the P2P handshake successfully. val8 = 0; - padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE); + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode); issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500); } - - // Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. - _set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval ); - } - else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) - { - // The driver had finished the P2P handshake successfully. - val8 = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode); - issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500); - } - else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) - { - val8 = 1; - set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - issue_probereq_p2p(padapter, NULL); - _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); - } - else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) - { - val8 = 1; - set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - issue_probereq_p2p(padapter, NULL); - _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); - } - else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) && pwdinfo->invitereq_info.benable == _TRUE) - { - /* - val8 = 1; - set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - issue_probereq_p2p(padapter, NULL); - _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); - */ + else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) + { + val8 = 1; + set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + issue_probereq_p2p(padapter, NULL); + _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); + } + else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) + { + val8 = 1; + set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + issue_probereq_p2p(padapter, NULL); + _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); + } + else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) && pwdinfo->invitereq_info.benable == _TRUE) + { + /* + val8 = 1; + set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); + rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); + issue_probereq_p2p(padapter, NULL); + _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT ); + */ + } } -#endif //CONFIG_IOCTL_CFG80211 - } + } else { set_channel_bwmode( padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); @@ -3498,39 +3553,38 @@ static void ro_ch_handler(_adapter *padapter) { struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo; struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + u8 ch, bw, offset; _func_enter_; - { - -#ifdef CONFIG_CONCURRENT_MODE - if ( check_buddy_fwstate(padapter, _FW_LINKED ) ) - { - PADAPTER pbuddy_adapter = padapter->pbuddy_adapter; - struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; - - DBG_871X("%s, switch ch back to buddy's cur_channel=%d\n", __func__, pbuddy_mlmeext->cur_channel); - - set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode); + if (rtw_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) { + if (0) + DBG_871X(FUNC_ADPT_FMT" back to linked union - ch:%u, bw:%u, offset:%u\n", + FUNC_ADPT_ARG(padapter), ch, bw, offset); + } + else if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled && pwdinfo->listen_channel) { + ch = pwdinfo->listen_channel; + bw = HT_CHANNEL_WIDTH_20; + offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + if (0) + DBG_871X(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n", + FUNC_ADPT_ARG(padapter), ch, bw, offset); + } + else { + ch = pcfg80211_wdinfo->restore_channel; + bw = HT_CHANNEL_WIDTH_20; + offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + if (0) + DBG_871X(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n", + FUNC_ADPT_ARG(padapter), ch, bw, offset); + } - pmlmeext->cur_channel = pbuddy_mlmeext->cur_channel; - - }else -#endif //CONFIG_CONCURRENT_MODE - if( pcfg80211_wdinfo->restore_channel != pmlmeext->cur_channel ) - { - if ( !check_fwstate(&padapter->mlmepriv, _FW_LINKED ) ) - pmlmeext->cur_channel = pcfg80211_wdinfo->restore_channel; + set_channel_bwmode(padapter, ch, offset, bw); - set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - } - - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); -#ifdef CONFIG_DEBUG_CFG80211 - DBG_871X("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo)); + rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); +#ifdef CONFIG_DEBUG_CFG80211 + DBG_871X("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo)); #endif - } pcfg80211_wdinfo->is_ro_ch = _FALSE; @@ -3558,6 +3612,162 @@ static void ro_ch_timer_process (void *FunctionContext) p2p_protocol_wk_cmd( adapter, P2P_RO_CH_WK); } +static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch) +{ + u8 *ies, *p2p_ie; + u32 ies_len, p2p_ielen; + PADAPTER pbuddy_adapter = padapter->pbuddy_adapter; + struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; + + ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_); + ies_len = len - _PUBLIC_ACTION_IE_OFFSET_; + + p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen ); + + while ( p2p_ie ) { + u32 attr_contentlen = 0; + u8 *pattr = NULL; + + //Check P2P_ATTR_OPERATING_CH + attr_contentlen = 0; + pattr = NULL; + if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL) + { + *(pattr+4) = ch; + } + + //Get the next P2P IE + p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen); + } +} + +static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch) +{ + u8 *ies, *p2p_ie; + u32 ies_len, p2p_ielen; + PADAPTER pbuddy_adapter = padapter->pbuddy_adapter; + struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; + + ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_); + ies_len = len - _PUBLIC_ACTION_IE_OFFSET_; + + p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen ); + + while (p2p_ie) { + u32 attr_contentlen = 0; + u8 *pattr = NULL; + + //Check P2P_ATTR_CH_LIST + if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL) { + int i; + u32 num_of_ch; + u8 *pattr_temp = pattr + 3 ; + + attr_contentlen -= 3; + + while (attr_contentlen>0) { + num_of_ch = *(pattr_temp+1); + + for(i=0; i<num_of_ch; i++) + *(pattr_temp+2+i) = ch; + + pattr_temp += (2+num_of_ch); + attr_contentlen -= (2+num_of_ch); + } + } + + //Get the next P2P IE + p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen); + } +} + +static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len) +{ + bool fit = _FALSE; +#ifdef CONFIG_CONCURRENT_MODE + u8 *ies, *p2p_ie; + u32 ies_len, p2p_ielen; + PADAPTER pbuddy_adapter = padapter->pbuddy_adapter; + struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; + u8 buddy_ch = pbuddy_mlmeext->cur_channel; + + ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_); + ies_len = len - _PUBLIC_ACTION_IE_OFFSET_; + + p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen ); + + while (p2p_ie) { + u32 attr_contentlen = 0; + u8 *pattr = NULL; + + //Check P2P_ATTR_CH_LIST + if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL) { + int i; + u32 num_of_ch; + u8 *pattr_temp = pattr + 3 ; + + attr_contentlen -= 3; + + while (attr_contentlen>0) { + num_of_ch = *(pattr_temp+1); + + for(i=0; i<num_of_ch; i++) { + if (*(pattr_temp+2+i) == buddy_ch) { + DBG_871X(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), buddy_ch); + fit = _TRUE; + break; + } + } + + pattr_temp += (2+num_of_ch); + attr_contentlen -= (2+num_of_ch); + } + } + + //Get the next P2P IE + p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen); + } +#endif + return fit; +} + +static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len) +{ + bool fit = _FALSE; +#ifdef CONFIG_CONCURRENT_MODE + u8 *ies, *p2p_ie; + u32 ies_len, p2p_ielen; + PADAPTER pbuddy_adapter = padapter->pbuddy_adapter; + struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv; + u8 buddy_ch = pbuddy_mlmeext->cur_channel; + + ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_); + ies_len = len - _PUBLIC_ACTION_IE_OFFSET_; + + p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen ); + + while (p2p_ie) { + u32 attr_contentlen = 0; + u8 *pattr = NULL; + + //Check P2P_ATTR_OPERATING_CH + attr_contentlen = 0; + pattr = NULL; + if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL) { + if (*(pattr+4) == buddy_ch) { + DBG_871X(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), buddy_ch); + fit = _TRUE; + break; + } + } + + //Get the next P2P IE + p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen); + } +#endif + return fit; +} + static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len) { #ifdef CONFIG_CONCURRENT_MODE @@ -3730,6 +3940,69 @@ void rtw_append_wfd_ie(_adapter *padapter, u8 *buf, u32* len) } #endif +u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len) +{ + uint attr_contentlen = 0; + u8 *pattr = NULL; + int w_sz = 0; + u8 ch_cnt = 0; + u8 ch_list[40]; + bool continuous = _FALSE; + + if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen))!=NULL) { + int i, j; + u32 num_of_ch; + u8 *pattr_temp = pattr + 3 ; + + attr_contentlen -= 3; + + _rtw_memset(ch_list, 0, 40); + + while (attr_contentlen>0) { + num_of_ch = *(pattr_temp+1); + + for(i=0; i<num_of_ch; i++) { + for (j=0;j<ch_cnt;j++) { + if (ch_list[j] == *(pattr_temp+2+i)) + break; + } + if (j>=ch_cnt) + ch_list[ch_cnt++] = *(pattr_temp+2+i); + + } + + pattr_temp += (2+num_of_ch); + attr_contentlen -= (2+num_of_ch); + } + + for (j=0;j<ch_cnt;j++) { + if (j == 0) { + w_sz += snprintf(buf+w_sz, buf_len-w_sz, "%u", ch_list[j]); + } else if (ch_list[j] - ch_list[j-1] != 1) { + w_sz += snprintf(buf+w_sz, buf_len-w_sz, ", %u", ch_list[j]); + } else if (j != ch_cnt-1 && ch_list[j+1] - ch_list[j] == 1) { + /* empty */ + } else { + w_sz += snprintf(buf+w_sz, buf_len-w_sz, "-%u", ch_list[j]); + } + } + } + return buf; +} + +/* + * return _TRUE if requester is GO, _FALSE if responder is GO + */ +bool rtw_p2p_nego_intent_compare(u8 req, u8 resp) +{ + if (req>>1 == resp >>1) + return req&0x01 ? _TRUE : _FALSE; + else if (req>>1 > resp>>1) + return _TRUE; + else + return _FALSE; +} + int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx) { int is_p2p_frame = (-1); @@ -3738,6 +4011,11 @@ int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx) u8 *p2p_ie = NULL; uint p2p_ielen = 0; struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev); + int status = -1; + u8 ch_list_buf[128] = {'\0'}; + int op_ch = -1; + int listen_ch = -1; + u8 intent = 0; frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr)); category = frame_body[0]; @@ -3767,60 +4045,152 @@ int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx) u8 *cont; uint cont_len; case P2P_GO_NEGO_REQ: - DBG_871X("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken); - - if(tx) - { -#ifdef CONFIG_DRV_ISSUE_PROV_REQ // IOT FOR S2 + { + struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info; + + if (tx) { + #ifdef CONFIG_DRV_ISSUE_PROV_REQ // IOT FOR S2 if(pwdev_priv->provdisc_req_issued == _FALSE) rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len); -#endif //CONFIG_DRV_ISSUE_PROV_REQ + #endif //CONFIG_DRV_ISSUE_PROV_REQ //pwdev_priv->provdisc_req_issued = _FALSE; - -#ifdef CONFIG_CONCURRENT_MODE + + #ifdef CONFIG_CONCURRENT_MODE if(check_buddy_fwstate(padapter, _FW_LINKED)) rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)); -#endif + #endif } - + + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len))) + op_ch = *(cont+4); + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len))) + listen_ch = *(cont+4); + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len))) + intent = *cont; + + if (nego_info->token != dialogToken) + rtw_wdev_nego_info_init(nego_info); + + _rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN); + nego_info->active = tx ? 1 : 0; + nego_info->token = dialogToken; + nego_info->req_op_ch = op_ch; + nego_info->req_listen_ch = listen_ch; + nego_info->req_intent = intent; + nego_info->state = 0; + + dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128); + DBG_871X("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s\n", + (tx==_TRUE)?"Tx":"Rx", dialogToken, (intent>>1), intent&0x1 ? "+" : "-", listen_ch, op_ch, ch_list_buf); + + if (!tx) { + #ifdef CONFIG_CONCURRENT_MODE + if(check_buddy_fwstate(padapter, _FW_LINKED) + && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) + { + DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter)); + rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0); + } + #endif + } + break; + } case P2P_GO_NEGO_RESP: - cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len); - DBG_871X("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, status:%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken, cont?*cont:-1); + { + struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info; - if(!tx) - { - pwdev_priv->provdisc_req_issued = _FALSE; - } -#ifdef CONFIG_CONCURRENT_MODE - else - { + if (tx) { + #ifdef CONFIG_CONCURRENT_MODE if(check_buddy_fwstate(padapter, _FW_LINKED)) rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)); + #endif } -#endif - break; + + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len))) + op_ch = *(cont+4); + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len))) + intent = *cont; + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len))) + status = *cont; + + if (nego_info->token == dialogToken && nego_info->state == 0 + && _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE + ) { + nego_info->status = (status==-1) ? 0xff : status; + nego_info->rsp_op_ch= op_ch; + nego_info->rsp_intent = intent; + nego_info->state = 1; + if (status != 0) + nego_info->token = 0; /* init */ + } + + dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128); + DBG_871X("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s\n", + (tx==_TRUE)?"Tx":"Rx", dialogToken, (intent>>1), intent&0x1 ? "+" : "-", status, op_ch, ch_list_buf); + + if (!tx) { + pwdev_priv->provdisc_req_issued = _FALSE; + #ifdef CONFIG_CONCURRENT_MODE + if(check_buddy_fwstate(padapter, _FW_LINKED) + && rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) + { + DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter)); + rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0); + } + #endif + } + + break; + } case P2P_GO_NEGO_CONF: - cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len); - DBG_871X("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken, cont?*cont:-1); + { + struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info; + bool is_go = _FALSE; -#ifdef CONFIG_CONCURRENT_MODE - if(tx) - { + if (tx) { + #ifdef CONFIG_CONCURRENT_MODE if(check_buddy_fwstate(padapter, _FW_LINKED)) rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)); + #endif } -#endif - break; + + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len))) + op_ch = *(cont+4); + if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len))) + status = *cont; + + if (nego_info->token == dialogToken && nego_info->state == 1 + && _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE + ) { + nego_info->status = (status==-1) ? 0xff : status; + nego_info->conf_op_ch = (op_ch==-1) ? 0 : op_ch; + nego_info->state = 2; + + if (status == 0) { + if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) && tx) + is_go = _TRUE; + } + + nego_info->token = 0; /* init */ + } + + dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128); + DBG_871X("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n", + (tx==_TRUE)?"Tx":"Rx", dialogToken, status, op_ch, ch_list_buf); + + if (!tx) { + } + + break; + } case P2P_INVIT_REQ: { struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info; int flags = -1; - int op_ch = 0; - if(tx) - { + if (tx) { #ifdef CONFIG_CONCURRENT_MODE if(check_buddy_fwstate(padapter, _FW_LINKED)) rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)); @@ -3835,21 +4205,38 @@ int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx) if (invit_info->token != dialogToken) rtw_wdev_invit_info_init(invit_info); + _rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN); + invit_info->active = tx ? 1 : 0; invit_info->token = dialogToken; invit_info->flags = (flags==-1) ? 0x0 : flags; invit_info->req_op_ch= op_ch; + invit_info->state = 0; + + dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128); + DBG_871X("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s\n", + (tx==_TRUE)?"Tx":"Rx", dialogToken, flags, op_ch, ch_list_buf); + + if (!tx) { + #ifdef CONFIG_CONCURRENT_MODE + if(check_buddy_fwstate(padapter, _FW_LINKED)) { + if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) { + DBG_871X(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch); + rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0); + } else if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) { + DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter)); + rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0); + } + } + #endif + } - DBG_871X("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken, flags, op_ch); break; } case P2P_INVIT_RESP: { struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info; - int status = -1; - int op_ch = 0; - if(tx) - { + if (tx) { #ifdef CONFIG_CONCURRENT_MODE if(check_buddy_fwstate(padapter, _FW_LINKED)) rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)); @@ -3857,19 +4244,35 @@ int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx) } if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len))) + { +#ifdef CONFIG_P2P_INVITE_IOT + if(tx && *cont==7) + { + DBG_871X("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n"); + *cont = 8; //unknow group status + } +#endif //CONFIG_P2P_INVITE_IOT status = *cont; + } if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len))) op_ch = *(cont+4); - if (invit_info->token != dialogToken) { - rtw_wdev_invit_info_init(invit_info); - } else { - invit_info->token = 0; + if (invit_info->token == dialogToken && invit_info->state == 0 + && _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE + ) { invit_info->status = (status==-1) ? 0xff : status; invit_info->rsp_op_ch= op_ch; + invit_info->state = 1; + invit_info->token = 0; /* init */ + } + + dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128); + DBG_871X("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n", + (tx==_TRUE)?"Tx":"Rx", dialogToken, status, op_ch, ch_list_buf); + + if (!tx) { } - DBG_871X("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken, status, op_ch); break; } case P2P_DEVDISC_REQ: @@ -3954,10 +4357,9 @@ int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx) } } - else + else { DBG_871X("RTW_%s:action frame category=%d\n", (tx==_TRUE)?"TX":"RX", category); - //is_p2p_frame = (-1); } return is_p2p_frame; @@ -4138,7 +4540,7 @@ _func_enter_; { pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW; // driver should wait LPS for entering CTWindow - if(padapter->pwrctrlpriv.bFwCurrentInPSMode == _TRUE) + if(adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE) { p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1); } @@ -4175,7 +4577,7 @@ _func_exit_; void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct wifidirect_info *pwdinfo= &(padapter->wdinfo); _func_enter_; @@ -4193,12 +4595,12 @@ _func_enter_; pwdinfo->opp_ps = 0; pwdinfo->noa_num = 0; pwdinfo->p2p_ps_mode = P2P_PS_NONE; - if(padapter->pwrctrlpriv.bFwCurrentInPSMode == _TRUE) + if(pwrpriv->bFwCurrentInPSMode == _TRUE) { if(pwrpriv->smart_ps == 0) { pwrpriv->smart_ps = 2; - rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(padapter->pwrctrlpriv.pwr_mode))); + rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode))); } } break; @@ -4212,7 +4614,7 @@ _func_enter_; { pwrpriv->smart_ps = 0; DBG_871X("%s(): Enter CTW, change SmartPS\n", __FUNCTION__); - rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(padapter->pwrctrlpriv.pwr_mode))); + rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode))); } } rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state)); @@ -4300,6 +4702,11 @@ static void reset_ch_sitesurvey_timer_process (void *FunctionContext) DBG_871X( "[%s] In\n", __FUNCTION__ ); // Reset the operation channel information pwdinfo->rx_invitereq_info.operation_ch[0] = 0; +#ifdef P2P_OP_CHECK_SOCIAL_CH + pwdinfo->rx_invitereq_info.operation_ch[1] = 0; + pwdinfo->rx_invitereq_info.operation_ch[2] = 0; + pwdinfo->rx_invitereq_info.operation_ch[3] = 0; +#endif //P2P_OP_CHECK_SOCIAL_CH pwdinfo->rx_invitereq_info.scan_op_ch_only = 0; } @@ -4314,6 +4721,11 @@ static void reset_ch_sitesurvey_timer_process2 (void *FunctionContext) DBG_871X( "[%s] In\n", __FUNCTION__ ); // Reset the operation channel information pwdinfo->p2p_info.operation_ch[0] = 0; +#ifdef P2P_OP_CHECK_SOCIAL_CH + pwdinfo->p2p_info.operation_ch[1] = 0; + pwdinfo->p2p_info.operation_ch[2] = 0; + pwdinfo->p2p_info.operation_ch[3] = 0; +#endif //P2P_OP_CHECK_SOCIAL_CH pwdinfo->p2p_info.scan_op_ch_only = 0; } @@ -4611,45 +5023,118 @@ void init_wifidirect_info( _adapter* padapter, enum P2P_ROLE role) pwdinfo->ext_listen_period = 1000; #endif //!CONFIG_IOCTL_CFG80211 #endif + +// Commented by Kurt 20130319 +// For WiDi purpose: Use CFG80211 interface but controled WFD/RDS frame by driver itself. +#ifdef CONFIG_IOCTL_CFG80211 + pwdinfo->driver_interface = DRIVER_CFG80211; +#else + pwdinfo->driver_interface = DRIVER_WEXT; +#endif //CONFIG_IOCTL_CFG80211 + pwdinfo->wfd_tdls_enable = 0; _rtw_memset( pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN ); _rtw_memset( pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN ); pwdinfo->rx_invitereq_info.operation_ch[0] = 0; pwdinfo->rx_invitereq_info.operation_ch[1] = 0; // Used to indicate the scan end in site survey function +#ifdef P2P_OP_CHECK_SOCIAL_CH + pwdinfo->rx_invitereq_info.operation_ch[2] = 0; + pwdinfo->rx_invitereq_info.operation_ch[3] = 0; + pwdinfo->rx_invitereq_info.operation_ch[4] = 0; +#endif //P2P_OP_CHECK_SOCIAL_CH pwdinfo->rx_invitereq_info.scan_op_ch_only = 0; pwdinfo->p2p_info.operation_ch[0] = 0; pwdinfo->p2p_info.operation_ch[1] = 0; // Used to indicate the scan end in site survey function +#ifdef P2P_OP_CHECK_SOCIAL_CH + pwdinfo->p2p_info.operation_ch[2] = 0; + pwdinfo->p2p_info.operation_ch[3] = 0; + pwdinfo->p2p_info.operation_ch[4] = 0; +#endif //P2P_OP_CHECK_SOCIAL_CH pwdinfo->p2p_info.scan_op_ch_only = 0; } #ifdef CONFIG_DBG_P2P -char * p2p_role_str[] = { - "P2P_ROLE_DISABLE", - "P2P_ROLE_DEVICE", - "P2P_ROLE_CLIENT", - "P2P_ROLE_GO" -}; - -char * p2p_state_str[] = { - "P2P_STATE_NONE", - "P2P_STATE_IDLE", - "P2P_STATE_LISTEN", - "P2P_STATE_SCAN", - "P2P_STATE_FIND_PHASE_LISTEN", - "P2P_STATE_FIND_PHASE_SEARCH", - "P2P_STATE_TX_PROVISION_DIS_REQ", - "P2P_STATE_RX_PROVISION_DIS_RSP", - "P2P_STATE_RX_PROVISION_DIS_REQ", - "P2P_STATE_GONEGO_ING", - "P2P_STATE_GONEGO_OK", - "P2P_STATE_GONEGO_FAIL", - "P2P_STATE_RECV_INVITE_REQ_MATCH", - "P2P_STATE_PROVISIONING_ING", - "P2P_STATE_PROVISIONING_DONE", - "P2P_STATE_RECV_INVITE_REQ_DISMATCH", - "P2P_STATE_RECV_INVITE_REQ_GO" -}; + +/** + * rtw_p2p_role_txt - Get the p2p role name as a text string + * @role: P2P role + * Returns: The state name as a printable text string + */ +const char * rtw_p2p_role_txt(enum P2P_ROLE role) +{ + switch (role) { + case P2P_ROLE_DISABLE: + return "P2P_ROLE_DISABLE"; + case P2P_ROLE_DEVICE: + return "P2P_ROLE_DEVICE"; + case P2P_ROLE_CLIENT: + return "P2P_ROLE_CLIENT"; + case P2P_ROLE_GO: + return "P2P_ROLE_GO"; + default: + return "UNKNOWN"; + } +} + +/** + * rtw_p2p_state_txt - Get the p2p state name as a text string + * @state: P2P state + * Returns: The state name as a printable text string + */ +const char * rtw_p2p_state_txt(enum P2P_STATE state) +{ + switch (state) { + case P2P_STATE_NONE: + return "P2P_STATE_NONE"; + case P2P_STATE_IDLE: + return "P2P_STATE_IDLE"; + case P2P_STATE_LISTEN: + return "P2P_STATE_LISTEN"; + case P2P_STATE_SCAN: + return "P2P_STATE_SCAN"; + case P2P_STATE_FIND_PHASE_LISTEN: + return "P2P_STATE_FIND_PHASE_LISTEN"; + case P2P_STATE_FIND_PHASE_SEARCH: + return "P2P_STATE_FIND_PHASE_SEARCH"; + case P2P_STATE_TX_PROVISION_DIS_REQ: + return "P2P_STATE_TX_PROVISION_DIS_REQ"; + case P2P_STATE_RX_PROVISION_DIS_RSP: + return "P2P_STATE_RX_PROVISION_DIS_RSP"; + case P2P_STATE_RX_PROVISION_DIS_REQ: + return "P2P_STATE_RX_PROVISION_DIS_REQ"; + case P2P_STATE_GONEGO_ING: + return "P2P_STATE_GONEGO_ING"; + case P2P_STATE_GONEGO_OK: + return "P2P_STATE_GONEGO_OK"; + case P2P_STATE_GONEGO_FAIL: + return "P2P_STATE_GONEGO_FAIL"; + case P2P_STATE_RECV_INVITE_REQ_MATCH: + return "P2P_STATE_RECV_INVITE_REQ_MATCH"; + case P2P_STATE_PROVISIONING_ING: + return "P2P_STATE_PROVISIONING_ING"; + case P2P_STATE_PROVISIONING_DONE: + return "P2P_STATE_PROVISIONING_DONE"; + case P2P_STATE_TX_INVITE_REQ: + return "P2P_STATE_TX_INVITE_REQ"; + case P2P_STATE_RX_INVITE_RESP_OK: + return "P2P_STATE_RX_INVITE_RESP_OK"; + case P2P_STATE_RECV_INVITE_REQ_DISMATCH: + return "P2P_STATE_RECV_INVITE_REQ_DISMATCH"; + case P2P_STATE_RECV_INVITE_REQ_GO: + return "P2P_STATE_RECV_INVITE_REQ_GO"; + case P2P_STATE_RECV_INVITE_REQ_JOIN: + return "P2P_STATE_RECV_INVITE_REQ_JOIN"; + case P2P_STATE_RX_INVITE_RESP_FAIL: + return "P2P_STATE_RX_INVITE_RESP_FAIL"; + case P2P_STATE_RX_INFOR_NOREADY: + return "P2P_STATE_RX_INFOR_NOREADY"; + case P2P_STATE_TX_INFOR_NOREADY: + return "P2P_STATE_TX_INFOR_NOREADY"; + default: + return "UNKNOWN"; + } +} void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line) { @@ -4657,11 +5142,11 @@ void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, enum P2P_STATE old_state = _rtw_p2p_state(wdinfo); _rtw_p2p_set_state(wdinfo, state); DBG_871X("[CONFIG_DBG_P2P]%s:%d set_state from %s to %s\n", caller, line - , p2p_state_str[old_state], p2p_state_str[_rtw_p2p_state(wdinfo)] + , rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_state(wdinfo)) ); } else { DBG_871X("[CONFIG_DBG_P2P]%s:%d set_state to same state %s\n", caller, line - , p2p_state_str[_rtw_p2p_state(wdinfo)] + , rtw_p2p_state_txt(_rtw_p2p_state(wdinfo)) ); } } @@ -4671,11 +5156,11 @@ void dbg_rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, enum P2P_STATE st enum P2P_STATE old_state = _rtw_p2p_pre_state(wdinfo); _rtw_p2p_set_pre_state(wdinfo, state); DBG_871X("[CONFIG_DBG_P2P]%s:%d set_pre_state from %s to %s\n", caller, line - , p2p_state_str[old_state], p2p_state_str[_rtw_p2p_pre_state(wdinfo)] + , rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo)) ); } else { DBG_871X("[CONFIG_DBG_P2P]%s:%d set_pre_state to same state %s\n", caller, line - , p2p_state_str[_rtw_p2p_pre_state(wdinfo)] + , rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo)) ); } } @@ -4700,11 +5185,11 @@ void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, co enum P2P_ROLE old_role = wdinfo->role; _rtw_p2p_set_role(wdinfo, role); DBG_871X("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line - , p2p_role_str[old_role], p2p_role_str[wdinfo->role] + , rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role) ); } else { DBG_871X("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line - , p2p_role_str[wdinfo->role] + , rtw_p2p_role_txt(wdinfo->role) ); } } @@ -4715,7 +5200,6 @@ int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role) { int ret = _SUCCESS; struct wifidirect_info *pwdinfo= &(padapter->wdinfo); - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT|| role == P2P_ROLE_GO) { @@ -4757,6 +5241,11 @@ int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role) } else if (role == P2P_ROLE_DISABLE) { +#ifdef CONFIG_INTEL_WIDI + if( padapter->mlmepriv.p2p_reject_disable == _TRUE ) + return ret; +#endif //CONFIG_INTEL_WIDI + if (_FAIL == rtw_pwr_wakeup(padapter)) { ret = _FAIL; goto exit; @@ -4787,6 +5276,18 @@ int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role) //Restore to initial setting. update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode); + +#ifdef CONFIG_INTEL_WIDI + rtw_reset_widi_info(padapter); +#endif //CONFIG_INTEL_WIDI + + //For WiDi purpose. +#ifdef CONFIG_IOCTL_CFG80211 + pwdinfo->driver_interface = DRIVER_CFG80211; +#else + pwdinfo->driver_interface = DRIVER_WEXT; +#endif //CONFIG_IOCTL_CFG80211 + } exit: diff --git a/drivers/net/wireless/rtl8723as/core/rtw_pwrctrl.c b/drivers/net/wireless/rtl8723as/core/rtw_pwrctrl.c index 9e53994211b2..77b86f344dca 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_pwrctrl.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_pwrctrl.c @@ -29,11 +29,15 @@ #endif #ifdef CONFIG_IPS -void ips_enter(_adapter * padapter) +void _ips_enter(_adapter * padapter) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); - _enter_pwrlock(&pwrpriv->lock); + if (padapter->hw_init_completed == _FALSE) { + DBG_871X("%s: hw_init_completed: %d\n", + __func__, padapter->hw_init_completed); + return; + } pwrpriv->bips_processing = _TRUE; @@ -58,20 +62,21 @@ void ips_enter(_adapter * padapter) } pwrpriv->bips_processing = _FALSE; - _exit_pwrlock(&pwrpriv->lock); - } -int ips_leave(_adapter * padapter) +void ips_enter(_adapter * padapter) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct security_priv* psecuritypriv=&(padapter->securitypriv); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - int result = _SUCCESS; - sint keyid; - + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); _enter_pwrlock(&pwrpriv->lock); + _ips_enter(padapter); + _exit_pwrlock(&pwrpriv->lock); +} + +int _ips_leave(_adapter * padapter) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + int result = _SUCCESS; if((pwrpriv->rf_pwrstate == rf_off) &&(!pwrpriv->bips_processing)) { @@ -84,20 +89,6 @@ int ips_leave(_adapter * padapter) pwrpriv->rf_pwrstate = rf_on; } DBG_871X_LEVEL(_drv_always_, "nolinked power save leave\n"); - - if((_WEP40_ == psecuritypriv->dot11PrivacyAlgrthm) ||(_WEP104_ == psecuritypriv->dot11PrivacyAlgrthm)) - { - DBG_871X("==>%s,channel(%d),processing(%x)\n",__FUNCTION__,padapter->mlmeextpriv.cur_channel,pwrpriv->bips_processing); - set_channel_bwmode(padapter, padapter->mlmeextpriv.cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20); - for(keyid=0;keyid<4;keyid++){ - if(pmlmepriv->key_mask & BIT(keyid)){ - if(keyid == psecuritypriv->dot11PrivacyKeyIndex) - result=rtw_set_key(padapter,psecuritypriv, keyid, 1); - else - result=rtw_set_key(padapter,psecuritypriv, keyid, 0); - } - } - } DBG_871X("==> ips_leave.....LED(0x%08x)...\n",rtw_read32(padapter,0x4c)); pwrpriv->bips_processing = _FALSE; @@ -106,13 +97,21 @@ int ips_leave(_adapter * padapter) pwrpriv->bpower_saving = _FALSE; } - _exit_pwrlock(&pwrpriv->lock); - return result; } +int ips_leave(_adapter * padapter) +{ + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + int ret; + + _enter_pwrlock(&pwrpriv->lock); + ret = _ips_leave(padapter); + _exit_pwrlock(&pwrpriv->lock); -#endif + return ret; +} +#endif /* CONFIG_IPS */ #ifdef CONFIG_AUTOSUSPEND extern void autosuspend_enter(_adapter* padapter); @@ -138,7 +137,7 @@ bool rtw_pwr_unassociated_idle(_adapter *adapter) bool ret = _FALSE; - if (adapter->pwrctrlpriv.ips_deny_time >= rtw_get_current_time()) { + if (adapter_to_pwrctl(adapter)->ips_deny_time >= rtw_get_current_time()) { //DBG_871X("%s ips_deny_time\n", __func__); goto exit; } @@ -211,7 +210,7 @@ void rtw_ps_processor(_adapter*padapter) #ifdef CONFIG_P2P struct wifidirect_info *pwdinfo = &( padapter->wdinfo ); #endif //CONFIG_P2P - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); #ifdef SUPPORT_HW_RFOFF_DETECTED rt_rf_power_state rfpwrstate; @@ -224,7 +223,7 @@ void rtw_ps_processor(_adapter*padapter) goto exit; //DBG_871X("==> fw report state(0x%x)\n",rtw_read8(padapter,0x1ca)); - if(padapter->pwrctrlpriv.bHWPwrPindetect) + if(pwrpriv->bHWPwrPindetect) { #ifdef CONFIG_AUTOSUSPEND if(padapter->registrypriv.usbss_enable) @@ -277,11 +276,7 @@ void rtw_ps_processor(_adapter*padapter) } #endif //SUPPORT_HW_RFOFF_DETECTED - if (pwrpriv->ips_mode_req == IPS_NONE - #ifdef CONFIG_CONCURRENT_MODE - || padapter->pbuddy_adapter->pwrctrlpriv.ips_mode_req == IPS_NONE - #endif - ) + if (pwrpriv->ips_mode_req == IPS_NONE) goto exit; if (rtw_pwr_unassociated_idle(padapter) == _FALSE) @@ -333,7 +328,7 @@ void rtw_ps_processor(_adapter*padapter) } } exit: - rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv); + rtw_set_pwr_state_check_timer(pwrpriv); pwrpriv->ps_processing = _FALSE; return; } @@ -359,7 +354,13 @@ void pwr_state_check_handler(void *FunctionContext) void rtw_set_rpwm(PADAPTER padapter, u8 pslv) { u8 rpwm; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); +#ifdef CONFIG_DETECT_CPWM_BY_POLLING + u8 cpwm_orig = 0; + u8 cpwm_now = 0; + u32 cpwm_polling_start_time = 0; + u8 pollingRes = _FAIL; +#endif _func_enter_; @@ -382,8 +383,10 @@ _func_enter_; { if ( (pwrpriv->rpwm == pslv) #ifdef CONFIG_LPS_LCLK +#ifndef CONFIG_RTL8723A || ((pwrpriv->rpwm >= PS_STATE_S2)&&(pslv >= PS_STATE_S2)) #endif +#endif ) { RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_, @@ -427,10 +430,18 @@ _func_enter_; pwrpriv->rpwm = pslv; -#ifdef CONFIG_LPS_RPWM_TIMER +#ifdef CONFIG_DETECT_CPWM_BY_POLLING + if (rpwm & PS_ACK) + { + //cpwm_orig = rtw_read8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HCPWM1); + rtw_hal_get_hwreg(padapter, HW_VAR_GET_CPWM, (u8 *)(&cpwm_orig)); + } +#endif + +#if defined(CONFIG_LPS_RPWM_TIMER) && !defined(CONFIG_DETECT_CPWM_BY_POLLING) if (rpwm & PS_ACK) _set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS); -#endif // CONFIG_LPS_RPWM_TIMER +#endif // CONFIG_LPS_RPWM_TIMER && !CONFIG_DETECT_CPWM_BY_POLLING rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm)); pwrpriv->tog += 0x80; @@ -443,6 +454,42 @@ _func_enter_; pwrpriv->cpwm = pslv; } +#ifdef CONFIG_DETECT_CPWM_BY_POLLING + if (rpwm & PS_ACK) + { + cpwm_polling_start_time = rtw_get_current_time(); + + //polling cpwm + do{ + rtw_mdelay_os(1); + + //cpwm_now = rtw_read8(padapter, SDIO_LOCAL_BASE | SDIO_REG_HCPWM1); + rtw_hal_get_hwreg(padapter, HW_VAR_GET_CPWM, (u8 *)(&cpwm_now)); + if ((cpwm_orig ^ cpwm_now) & 0x80) + { +#ifdef CONFIG_LPS_LCLK + #ifdef CONFIG_RTL8723A + pwrpriv->cpwm = PS_STATE(cpwm_now); + #else // !CONFIG_RTL8723A + pwrpriv->cpwm = PS_STATE_S4; + #endif // !CONFIG_RTL8723A + pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE; +#endif + pollingRes = _SUCCESS; + break; + } + }while (rtw_get_passing_time_ms(cpwm_polling_start_time) < LPS_RPWM_WAIT_MS); + + if (pollingRes == _FAIL) + { +#ifdef CONFIG_LPS_RPWM_TIMER + _set_timer(&pwrpriv->pwr_rpwm_timer, 1); +#endif + DBG_871X("%s polling cpwm timeout!!!!!!!!!!\n", __FUNCTION__); + } + } +#endif + _func_exit_; } @@ -450,9 +497,18 @@ u8 PS_RDY_CHECK(_adapter * padapter); u8 PS_RDY_CHECK(_adapter * padapter) { u32 curr_time, delta_time; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); +#ifdef CONFIG_WOWLAN + if(_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_mode) + return _TRUE; + else if (_TRUE == pwrpriv->bInSuspend) + return _FALSE; +#else + if(_TRUE == pwrpriv->bInSuspend ) + return _FALSE; +#endif curr_time = rtw_get_current_time(); delta_time = curr_time -pwrpriv->DelayLPSLastTimeStamp; @@ -464,24 +520,18 @@ u8 PS_RDY_CHECK(_adapter * padapter) if ((check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE) || (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) || + (check_fwstate(pmlmepriv, WIFI_UNDER_WPS) == _TRUE) || (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) || (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) || (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) ) return _FALSE; -#ifdef CONFIG_WOWLAN - if(_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_mode) - return _TRUE; - else - return _FALSE; -#else - if(_TRUE == pwrpriv->bInSuspend ) - return _FALSE; -#endif + if( (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == _FALSE) ) { DBG_871X("Group handshake still in progress !!!\n"); return _FALSE; } + #ifdef CONFIG_IOCTL_CFG80211 if (!rtw_cfg80211_pwr_mgmt(padapter)) return _FALSE; @@ -492,7 +542,7 @@ u8 PS_RDY_CHECK(_adapter * padapter) void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); #ifdef CONFIG_P2P struct wifidirect_info *pwdinfo = &( padapter->wdinfo ); #endif //CONFIG_P2P @@ -562,6 +612,26 @@ _func_enter_; pwrpriv->pwr_mode = ps_mode; rtw_set_rpwm(padapter, PS_STATE_S4); +#ifdef CONFIG_WOWLAN + if (pwrpriv->wowlan_mode == _TRUE) + { + u32 start_time, delay_ms; + u8 val8; + delay_ms = 20; + start_time = rtw_get_current_time(); + do { + val8 = rtw_read8(padapter, 0x90); + if (!(val8 & BIT(0))) break; + if (rtw_get_passing_time_ms(start_time) > delay_ms) + { + DBG_871X("%s: Wait for FW 32K leave more than %u ms!!!\n", __FUNCTION__, delay_ms); + break; + } + rtw_usleep_os(100); + } while (1); + pwrpriv->cpwm = PS_STATE_S4; + } +#endif rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode)); pwrpriv->bFwCurrentInPSMode = _FALSE; } @@ -610,8 +680,9 @@ _func_enter_; #endif //CONFIG_P2P_PS #ifdef CONFIG_LPS_LCLK - if (pwrpriv->alives == 0) - rtw_set_rpwm(padapter, PS_STATE_S0); + DBG_871X("%s: alives: %d\n", __FUNCTION__, pwrpriv->alives); + if (pwrpriv->alives == 0) + rtw_set_rpwm(padapter, PS_STATE_S0); #else rtw_set_rpwm(padapter, PS_STATE_S2); #endif @@ -670,7 +741,7 @@ s32 LPS_RF_ON_check(PADAPTER padapter, u32 delay_ms) // void LPS_Enter(PADAPTER padapter) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); _adapter *buddy = padapter->pbuddy_adapter; @@ -721,7 +792,7 @@ _func_enter_; pwrpriv->bpower_saving = _TRUE; DBG_871X("%s smart_ps:%d\n", __func__, pwrpriv->smart_ps); //For Tenda W311R IOT issue - rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0); + rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, pwrpriv->smart_ps, 0x40); } } else @@ -741,7 +812,7 @@ void LPS_Leave(PADAPTER padapter) { #define LPS_LEAVE_TIMEOUT_MS 100 - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); u32 start_time; u8 bAwake = _FALSE; @@ -758,7 +829,7 @@ _func_enter_; { if(pwrpriv->pwr_mode != PS_MODE_ACTIVE) { - rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0); + rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0x40); if(pwrpriv->pwr_mode == PS_MODE_ACTIVE) LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS); @@ -805,7 +876,7 @@ _func_enter_; } else { - if(Adapter->pwrctrlpriv.rf_pwrstate== rf_off) + if(adapter_to_pwrctl(Adapter)->rf_pwrstate== rf_off) { #ifdef CONFIG_AUTOSUSPEND if(Adapter->registrypriv.usbss_enable) @@ -844,7 +915,7 @@ void LPS_Leave_check( _func_enter_; - pwrpriv = &padapter->pwrctrlpriv; + pwrpriv = adapter_to_pwrctl(padapter); bReady = _FALSE; start_time = rtw_get_current_time(); @@ -897,7 +968,7 @@ void cpwm_int_hdl( _func_enter_; - pwrpriv = &padapter->pwrctrlpriv; + pwrpriv = adapter_to_pwrctl(padapter); #if 0 if (pwrpriv->cpwm_tog == (preportpwrstate->state & PS_TOGGLE)) { RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_, @@ -942,7 +1013,8 @@ _func_exit_; static void cpwm_event_callback(struct work_struct *work) { struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event); - _adapter *adapter = container_of(pwrpriv, _adapter, pwrctrlpriv); + struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv); + _adapter *adapter = dvobj->if1; struct reportpwrstate_parm report; //DBG_871X("%s\n",__FUNCTION__); @@ -955,11 +1027,13 @@ static void cpwm_event_callback(struct work_struct *work) static void rpwmtimeout_workitem_callback(struct work_struct *work) { PADAPTER padapter; + struct dvobj_priv *dvobj; struct pwrctrl_priv *pwrpriv; pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi); - padapter = container_of(pwrpriv, _adapter, pwrctrlpriv); + dvobj = pwrctl_to_dvobj(pwrpriv); + padapter = dvobj->if1; // DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm); _enter_pwrlock(&pwrpriv->lock); @@ -1010,7 +1084,7 @@ static void pwr_rpwm_timeout_handler(void *FunctionContext) padapter = (PADAPTER)FunctionContext; - pwrpriv = &padapter->pwrctrlpriv; + pwrpriv = adapter_to_pwrctl(padapter); // DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm); if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2)) @@ -1055,9 +1129,9 @@ s32 rtw_register_tx_alive(PADAPTER padapter) _func_enter_; res = _SUCCESS; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); #ifdef CONFIG_BT_COEXIST - if (_TRUE == padapter->pwrctrlpriv.btcoex_rfon) + if (_TRUE == adapter_to_pwrctl(padapter)->btcoex_rfon) pslv = PS_STATE_S3; else #endif @@ -1086,6 +1160,14 @@ _func_enter_; _exit_pwrlock(&pwrctrl->lock); +#ifdef CONFIG_DETECT_CPWM_BY_POLLING + if (_FAIL == res) + { + if (pwrctrl->cpwm >= PS_STATE_S2) + res = _SUCCESS; + } +#endif // CONFIG_DETECT_CPWM_BY_POLLING + _func_exit_; return res; @@ -1113,9 +1195,9 @@ s32 rtw_register_cmd_alive(PADAPTER padapter) _func_enter_; res = _SUCCESS; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); #ifdef CONFIG_BT_COEXIST - if (_TRUE == padapter->pwrctrlpriv.btcoex_rfon) + if (_TRUE == adapter_to_pwrctl(padapter)->btcoex_rfon) pslv = PS_STATE_S3; else #endif @@ -1144,6 +1226,14 @@ _func_enter_; _exit_pwrlock(&pwrctrl->lock); +#ifdef CONFIG_DETECT_CPWM_BY_POLLING + if (_FAIL == res) + { + if (pwrctrl->cpwm >= PS_STATE_S2) + res = _SUCCESS; + } +#endif // CONFIG_DETECT_CPWM_BY_POLLING + _func_exit_; return res; @@ -1164,7 +1254,7 @@ s32 rtw_register_rx_alive(PADAPTER padapter) _func_enter_; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); _enter_pwrlock(&pwrctrl->lock); @@ -1195,7 +1285,7 @@ s32 rtw_register_evt_alive(PADAPTER padapter) _func_enter_; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); _enter_pwrlock(&pwrctrl->lock); @@ -1224,7 +1314,7 @@ void rtw_unregister_tx_alive(PADAPTER padapter) _func_enter_; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); _enter_pwrlock(&pwrctrl->lock); @@ -1262,7 +1352,7 @@ void rtw_unregister_cmd_alive(PADAPTER padapter) _func_enter_; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); _enter_pwrlock(&pwrctrl->lock); @@ -1296,7 +1386,7 @@ void rtw_unregister_rx_alive(PADAPTER padapter) _func_enter_; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); _enter_pwrlock(&pwrctrl->lock); @@ -1317,7 +1407,7 @@ void rtw_unregister_evt_alive(PADAPTER padapter) _func_enter_; - pwrctrl = &padapter->pwrctrlpriv; + pwrctrl = adapter_to_pwrctl(padapter); unregister_task_alive(pwrctrl, EVT_ALIVE); @@ -1337,7 +1427,12 @@ static void resume_workitem_callback(struct work_struct *work); void rtw_init_pwrctrl_priv(PADAPTER padapter) { - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); + +#if defined(CONFIG_CONCURRENT_MODE) + if (padapter->adapter_type != PRIMARY_ADAPTER) + return; +#endif _func_enter_; @@ -1421,7 +1516,12 @@ _func_exit_; void rtw_free_pwrctrl_priv(PADAPTER adapter) { - struct pwrctrl_priv *pwrctrlpriv = &adapter->pwrctrlpriv; + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(adapter); + +#if defined(CONFIG_CONCURRENT_MODE) + if (adapter->adapter_type != PRIMARY_ADAPTER) + return; +#endif _func_enter_; @@ -1452,7 +1552,8 @@ extern int rtw_resume_process(_adapter *padapter); static void resume_workitem_callback(struct work_struct *work) { struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, resume_work); - _adapter *adapter = container_of(pwrpriv, _adapter, pwrctrlpriv); + struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv); + _adapter *adapter = dvobj->if1; DBG_871X("%s\n",__FUNCTION__); @@ -1507,7 +1608,8 @@ static void rtw_early_suspend(struct early_suspend *h) static void rtw_late_resume(struct early_suspend *h) { struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend); - _adapter *adapter = container_of(pwrpriv, _adapter, pwrctrlpriv); + struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv); + _adapter *adapter = dvobj->if1; DBG_871X("%s\n",__FUNCTION__); if(pwrpriv->do_late_resume) { @@ -1527,8 +1629,6 @@ void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv) pwrpriv->early_suspend.suspend = rtw_early_suspend; pwrpriv->early_suspend.resume = rtw_late_resume; register_early_suspend(&pwrpriv->early_suspend); - - } void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv) @@ -1560,7 +1660,8 @@ static void rtw_early_suspend(android_early_suspend_t *h) static void rtw_late_resume(android_early_suspend_t *h) { struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend); - _adapter *adapter = container_of(pwrpriv, _adapter, pwrctrlpriv); + struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv); + _adapter *adapter = dvobj->if1; DBG_871X("%s\n",__FUNCTION__); if(pwrpriv->do_late_resume) { @@ -1607,7 +1708,7 @@ u8 rtw_interface_ps_func(_adapter *padapter,HAL_INTF_PS_FUNC efunc_id,u8* val) inline void rtw_set_ips_deny(_adapter *padapter, u32 ms) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ms); } @@ -1620,7 +1721,7 @@ inline void rtw_set_ips_deny(_adapter *padapter, u32 ms) int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller) { - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int ret = _SUCCESS; u32 start = rtw_get_current_time(); @@ -1631,7 +1732,6 @@ int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller) if ((padapter->isprimary == _FALSE) && padapter->pbuddy_adapter){ padapter = padapter->pbuddy_adapter; - pwrpriv = &padapter->pwrctrlpriv; pmlmepriv = &padapter->mlmepriv; } #endif @@ -1774,7 +1874,7 @@ exit: int rtw_pm_set_lps(_adapter *padapter, u8 mode) { int ret = 0; - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); if ( mode < PS_MODE_NUM ) { @@ -1802,7 +1902,7 @@ int rtw_pm_set_lps(_adapter *padapter, u8 mode) int rtw_pm_set_ips(_adapter *padapter, u8 mode) { - struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv; + struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); if( mode == IPS_NORMAL || mode == IPS_LEVEL_2 ) { rtw_ips_mode_req(pwrctrlpriv, mode); diff --git a/drivers/net/wireless/rtl8723as/core/rtw_recv.c b/drivers/net/wireless/rtl8723as/core/rtw_recv.c index e7f8708c2028..05a514ea6926 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_recv.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_recv.c @@ -31,6 +31,10 @@ #include <usb_ops.h> #endif +#ifdef CONFIG_BT_COEXIST +#include <rtl8723a_hal.h> +#endif + #if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS) #error "Shall be Linux or Windows, but not both!\n" @@ -279,7 +283,7 @@ _func_enter_; #ifdef CONFIG_BSD_RX_USE_MBUF m_freem(precvframe->u.hdr.pkt); #else // CONFIG_BSD_RX_USE_MBUF - dev_kfree_skb_any(precvframe->u.hdr.pkt);//free skb by driver + rtw_skb_free(precvframe->u.hdr.pkt);//free skb by driver #endif // CONFIG_BSD_RX_USE_MBUF precvframe->u.hdr.pkt = NULL; } @@ -737,6 +741,9 @@ _func_enter_; return_packet = NULL; } + else{ + prxattrib->bdecrypted = _TRUE; + } //recvframe_chkmic(adapter, precv_frame); //move to recvframme_defrag function _func_exit_; @@ -761,7 +768,6 @@ union recv_frame * portctrl(_adapter *adapter,union recv_frame * precv_frame) _func_enter_; pstapriv = &adapter->stapriv; - psta = rtw_get_stainfo(pstapriv, psta_addr); auth_alg = adapter->securitypriv.dot11AuthAlgrthm; @@ -772,6 +778,8 @@ _func_enter_; prtnframe = NULL; + psta = rtw_get_stainfo(pstapriv, psta_addr); + RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n",adapter->securitypriv.dot11AuthAlgrthm)); if(auth_alg==2) @@ -1739,7 +1747,7 @@ union recv_frame* recvframe_chk_defrag(PADAPTER padapter, union recv_frame *prec sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame); sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame) { - //struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + //struct mlme_priv *pmlmepriv = &padapter->mlmepriv; RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+validate_recv_mgnt_frame\n")); @@ -2012,6 +2020,127 @@ _func_exit_; return ret; } +#ifdef CONFIG_IEEE80211W +static sint validate_80211w_mgmt(_adapter *adapter, union recv_frame *precv_frame) +{ + struct mlme_priv *pmlmepriv = &adapter->mlmepriv; + struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; + u8 *ptr = precv_frame->u.hdr.rx_data; + u8 type; + u8 subtype; + + type = GetFrameType(ptr); + subtype = GetFrameSubType(ptr); //bit(7)~bit(2) + + //only support station mode + if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) + && adapter->securitypriv.binstallBIPkey == _TRUE) + { + //unicast management frame decrypt + if(pattrib->privacy && !(IS_MCAST(GetAddr1Ptr(ptr))) && + (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) + { + u8 *ppp, *mgmt_DATA; + u32 data_len=0; + ppp = GetAddr2Ptr(ptr); + + pattrib->bdecrypted = 0; + pattrib->encrypt = _AES_; + pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); + //set iv and icv length + SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); + _rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); + _rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); + //actual management data frame body + data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; + mgmt_DATA = rtw_zmalloc(data_len); + if(mgmt_DATA == NULL) + { + DBG_871X("%s mgmt allocate fail !!!!!!!!!\n", __FUNCTION__); + goto validate_80211w_fail; + } + /*//dump the packet content before decrypt + { + int pp; + printk("pattrib->pktlen = %d =>", pattrib->pkt_len); + for(pp=0;pp< pattrib->pkt_len; pp++) + printk(" %02x ", ptr[pp]); + printk("\n"); + }*/ + + precv_frame = decryptor(adapter, precv_frame); + //save actual management data frame body + _rtw_memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len); + //overwrite the iv field + _rtw_memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len); + //remove the iv and icv length + pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len; + rtw_mfree(mgmt_DATA, data_len); + /*//print packet content after decryption + { + int pp; + printk("after decryption pattrib->pktlen = %d @@=>", pattrib->pkt_len); + for(pp=0;pp< pattrib->pkt_len; pp++) + printk(" %02x ", ptr[pp]); + printk("\n"); + }*/ + if(!precv_frame) + { + DBG_871X("%s mgmt descrypt fail !!!!!!!!!\n", __FUNCTION__); + goto validate_80211w_fail; + } + } + else if(IS_MCAST(GetAddr1Ptr(ptr)) && + (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) + { + sint BIP_ret = _SUCCESS; + //verify BIP MME IE of broadcast/multicast de-auth/disassoc packet + BIP_ret = rtw_BIP_verify(adapter, (u8 * )precv_frame); + if(BIP_ret == _FAIL) + { + //DBG_871X("802.11w BIP verify fail\n"); + goto validate_80211w_fail; + } + else if(BIP_ret == RTW_RX_HANDLED) + { + //DBG_871X("802.11w recv none protected packet\n"); + //issue sa query request + issue_action_SA_Query(adapter, NULL, 0, 0); + goto validate_80211w_fail; + } + }//802.11w protect + else + { + if(subtype == WIFI_ACTION) + { + //according 802.11-2012 standard, these five types are not robust types + if( ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_PUBLIC && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_HT && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_UNPROTECTED_WNM && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_SELF_PROTECTED && + ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_P2P) + { + DBG_871X("action frame category=%d should robust\n", ptr[WLAN_HDR_A3_LEN]); + goto validate_80211w_fail; + } + } + else if(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) + { + DBG_871X("802.11w recv none protected packet\n"); + //issue sa query request + issue_action_SA_Query(adapter, NULL, 0, 0); + goto validate_80211w_fail; + } + } + } + return _SUCCESS; + +validate_80211w_fail: + return _FAIL; + +} +#endif //CONFIG_IEEE80211W + sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame); sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame) { @@ -2022,7 +2151,6 @@ sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame) u8 type; u8 subtype; sint retval = _SUCCESS; - struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; u8 *ptr = precv_frame->u.hdr.rx_data; @@ -2138,6 +2266,14 @@ _func_enter_; switch (type) { case WIFI_MGT_TYPE: //mgnt +#ifdef CONFIG_IEEE80211W + if(validate_80211w_mgmt(adapter, precv_frame) == _FAIL) + { + retval = _FAIL; + break; + } +#endif //CONFIG_IEEE80211W + retval = validate_recv_mgnt_frame(adapter, precv_frame); if (retval == _FAIL) { @@ -2454,12 +2590,8 @@ static void recvframe_expand_pkt( //3 1. alloc new skb // prepare extra space for 4 bytes alignment -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html - ppkt = dev_alloc_skb(alloc_sz); - if (ppkt) ppkt->dev = padapter->pnetdev; -#else - ppkt = netdev_alloc_skb(padapter->pnetdev, alloc_sz); -#endif + ppkt = rtw_skb_alloc(alloc_sz); + if (!ppkt) return; // no way to expand //3 2. Prepare new skb to replace & release old skb @@ -2471,7 +2603,7 @@ static void recvframe_expand_pkt( // copy data to new pkt _rtw_memcpy(skb_put(ppkt, pfhdr->len), pfhdr->rx_data, pfhdr->len); - dev_kfree_skb_any(pfhdr->pkt); + rtw_skb_free(pfhdr->pkt); // attach new pkt to recvframe pfhdr->pkt = ppkt; @@ -2770,7 +2902,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) /* Allocate new skb for releasing to upper layer */ #ifdef CONFIG_SKB_COPY - sub_skb = dev_alloc_skb(nSubframe_Length + 12); + sub_skb = rtw_skb_alloc(nSubframe_Length + 12); if(sub_skb) { skb_reserve(sub_skb, 12); @@ -2780,7 +2912,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) else #endif // CONFIG_SKB_COPY { - sub_skb = skb_clone(prframe->u.hdr.pkt, GFP_ATOMIC); + sub_skb = rtw_skb_clone(prframe->u.hdr.pkt); if(sub_skb) { sub_skb->data = pdata; @@ -2789,7 +2921,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) } else { - DBG_871X("skb_clone() Fail!!! , nr_subframes = %d\n",nr_subframes); + DBG_871X("rtw_skb_clone() Fail!!! , nr_subframes = %d\n",nr_subframes); break; } } @@ -2890,7 +3022,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) #if 1 // bypass this frame to upper layer!! #else - dev_kfree_skb_any(sub_skb); + rtw_skb_free(sub_skb); continue; #endif } @@ -2910,7 +3042,7 @@ int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) sub_skb->ip_summed = CHECKSUM_NONE; #endif //CONFIG_TCP_CSUM_OFFLOAD_RX - netif_rx(sub_skb); + rtw_netif_rx(padapter->pnetdev, sub_skb); } #else //PLATFORM_FREEBSD @@ -3151,11 +3283,8 @@ exit: _rtw_init_listhead(&pnrframe_new->u.hdr.list); - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) // http://www.mail-archive.com/netdev@vger.kernel.org/msg17214.html - pskb_copy = dev_alloc_skb(copy_len+64); - #else - pskb_copy = netdev_alloc_skb(padapter->pnetdev, copy_len + 64); - #endif + pskb_copy = rtw_skb_alloc(copy_len+64); + if(pskb_copy==NULL) { DBG_871X("amsdu_to_msdu:can not all(ocate memory for skb copy\n"); @@ -3230,7 +3359,7 @@ exit: #ifdef PLATFORM_LINUX if(pskb) { - pnrframe_new->u.hdr.pkt = skb_clone(pskb, GFP_ATOMIC); + pnrframe_new->u.hdr.pkt = rtw_skb_clone(pskb); } #endif //PLATFORM_LINUX @@ -3597,8 +3726,9 @@ int recv_indicatepkt_reorder(_adapter *padapter, union recv_frame *prframe) //s1. wlanhdr_to_ethhdr(prframe); - if ((pattrib->qos!=1) /*|| pattrib->priority!=0 || IS_MCAST(pattrib->ra)*/ - || (pattrib->eth_type==0x0806) || (pattrib->ack_policy!=0)) + //if ((pattrib->qos!=1) /*|| pattrib->priority!=0 || IS_MCAST(pattrib->ra)*/ + // || (pattrib->eth_type==0x0806) || (pattrib->ack_policy!=0)) + if (pattrib->qos!=1) { if ((padapter->bDriverStopped == _FALSE) && (padapter->bSurpriseRemoved == _FALSE)) @@ -3863,7 +3993,8 @@ int recv_func_prehandle(_adapter *padapter, union recv_frame *rframe) struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib; struct recv_priv *precvpriv = &padapter->recvpriv; _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; - + + #ifdef CONFIG_MP_INCLUDED struct mlme_priv *pmlmepriv = &padapter->mlmepriv; #endif //CONFIG_MP_INCLUDED @@ -3871,20 +4002,20 @@ int recv_func_prehandle(_adapter *padapter, union recv_frame *rframe) #ifdef CONFIG_MP_INCLUDED if (padapter->registrypriv.mp_mode == 1) { - if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0)) - { if (pattrib->crc_err == 1) + { padapter->mppriv.rx_crcerrpktcount++; + } else + { padapter->mppriv.rx_pktcount++; - + } if (check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE) == _FALSE) { RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("MP - Not in loopback mode , drop pkt \n")); ret = _FAIL; rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame goto exit; } - } } #endif @@ -4189,41 +4320,65 @@ void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS){ recvpriv->signal_qual_data.update_req = 1; } - //update value of signal_strength, rssi, signal_qual - if(check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == _FALSE) { - tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength); - if(tmp_s %_alpha) - tmp_s = tmp_s/_alpha + 1; - else - tmp_s = tmp_s/_alpha; - if(tmp_s>100) - tmp_s = 100; + if (num_signal_strength == 0) { + if (rtw_get_on_cur_ch_time(adapter) == 0 + || rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval +#ifdef CONFIG_BT_COEXIST + || ((BTDM_IsBtDisabled(adapter) == _FALSE) && (BT_IsBtInquiryPage(adapter) == _TRUE)) +#endif + ) { + goto set_timer; + } + } - tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual); - if(tmp_q %_alpha) - tmp_q = tmp_q/_alpha + 1; - else - tmp_q = tmp_q/_alpha; - if(tmp_q>100) - tmp_q = 100; - - recvpriv->signal_strength = tmp_s; - recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s); - recvpriv->signal_qual = tmp_q; - - #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 - DBG_871X("%s signal_strength:%3u, rssi:%3d, signal_qual:%3u" - ", num_signal_strength:%u, num_signal_qual:%u" - "\n" - , __FUNCTION__ - , recvpriv->signal_strength - , recvpriv->rssi - , recvpriv->signal_qual - , num_signal_strength, num_signal_qual - ); - #endif + if(check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == _TRUE + || check_fwstate(&adapter->mlmepriv, _FW_LINKED) == _FALSE + ) { + goto set_timer; } + + #ifdef CONFIG_CONCURRENT_MODE + if (check_buddy_fwstate(adapter, _FW_UNDER_SURVEY) == _TRUE) + goto set_timer; + #endif + + //update value of signal_strength, rssi, signal_qual + tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength); + if(tmp_s %_alpha) + tmp_s = tmp_s/_alpha + 1; + else + tmp_s = tmp_s/_alpha; + if(tmp_s>100) + tmp_s = 100; + + tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual); + if(tmp_q %_alpha) + tmp_q = tmp_q/_alpha + 1; + else + tmp_q = tmp_q/_alpha; + if(tmp_q>100) + tmp_q = 100; + + recvpriv->signal_strength = tmp_s; + recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s); + recvpriv->signal_qual = tmp_q; + + #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 + DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u" + ", num_signal_strength:%u, num_signal_qual:%u" + ", on_cur_ch_ms:%d" + "\n" + , FUNC_ADPT_ARG(adapter) + , recvpriv->signal_strength + , recvpriv->rssi + , recvpriv->signal_qual + , num_signal_strength, num_signal_qual + , rtw_get_on_cur_ch_time(adapter) ? rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) : 0 + ); + #endif } + +set_timer: rtw_set_signal_stat_timer(recvpriv); } diff --git a/drivers/net/wireless/rtl8723as/core/rtw_security.c b/drivers/net/wireless/rtl8723as/core/rtw_security.c index 4a3b20a9caed..68dfafb18de5 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_security.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_security.c @@ -212,7 +212,7 @@ _func_enter_; length=pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len; - *((unsigned long *)crc)=cpu_to_le32(getcrc32(payload,length)); + *((u32 *)crc)=cpu_to_le32(getcrc32(payload,length)); arcfour_init(&mycontext, wepkey,3+keylength); arcfour_encrypt(&mycontext, payload, payload, length); @@ -222,7 +222,7 @@ _func_enter_; else { length=pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ; - *((unsigned long *)crc)=cpu_to_le32(getcrc32(payload,length)); + *((u32 *)crc)=cpu_to_le32(getcrc32(payload,length)); arcfour_init(&mycontext, wepkey,3+keylength); arcfour_encrypt(&mycontext, payload, payload, length); arcfour_encrypt(&mycontext, payload+length, crc, 4); @@ -275,7 +275,7 @@ _func_enter_; arcfour_encrypt(&mycontext, payload, payload, length); //calculate icv and compare the icv - *((unsigned long *)crc)=le32_to_cpu(getcrc32(payload,length-4)); + *((u32 *)crc)=le32_to_cpu(getcrc32(payload,length-4)); if(crc[3]!=payload[length-1] || crc[2]!=payload[length-2] || crc[1]!=payload[length-3] || crc[0]!=payload[length-4]) { @@ -801,12 +801,42 @@ _func_enter_; if(IS_MCAST(prxattrib->ra)) { + static u32 start = 0; + static u32 no_gkey_bc_cnt = 0; + static u32 no_gkey_mc_cnt = 0; + if(psecuritypriv->binstallGrpkey==_FALSE) { - res=_FAIL; - DBG_8192C("%s:rx bc/mc packets,but didn't install group key!!!!!!!!!!\n",__FUNCTION__); + res=_FAIL; + + if (start == 0) + start = rtw_get_current_time(); + + if (is_broadcast_mac_addr(prxattrib->ra)) + no_gkey_bc_cnt++; + else + no_gkey_mc_cnt++; + + if (rtw_get_passing_time_ms(start) > 1000) { + if (no_gkey_bc_cnt || no_gkey_mc_cnt) { + DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n", + FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt); + } + start = rtw_get_current_time(); + no_gkey_bc_cnt = 0; + no_gkey_mc_cnt = 0; + } goto exit; } + + if (no_gkey_bc_cnt || no_gkey_mc_cnt) { + DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n", + FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt); + } + start = 0; + no_gkey_bc_cnt = 0; + no_gkey_mc_cnt = 0; + //DBG_871X("rx bc/mc packets, to perform sw rtw_tkip_decrypt\n"); //prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; @@ -916,11 +946,13 @@ static void construct_mic_iv( sint a4_exists, u8 *mpdu, uint payload_length, - u8 * pn_vector); + u8 * pn_vector, + uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use static void construct_mic_header1( u8 *mic_header1, sint header_length, - u8 *mpdu); + u8 *mpdu, + uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use static void construct_mic_header2( u8 *mic_header2, u8 *mpdu, @@ -932,7 +964,8 @@ static void construct_ctr_preload( sint qc_exists, u8 *mpdu, u8 *pn_vector, - sint c); + sint c, + uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use static void xor_128(u8 *a, u8 *b, u8 *out); static void xor_32(u8 *a, u8 *b, u8 *out); static u8 sbox(u8 a); @@ -1152,6 +1185,8 @@ _func_exit_; /************************************************/ /* construct_mic_iv() */ /* Builds the MIC IV from header fields and PN */ +/* Baron think the function is construct CCM */ +/* nonce */ /************************************************/ static void construct_mic_iv( u8 *mic_iv, @@ -1159,7 +1194,8 @@ static void construct_mic_iv( sint a4_exists, u8 *mpdu, uint payload_length, - u8 *pn_vector + u8 *pn_vector, + uint frtype// add for CONFIG_IEEE80211W, none 11w also can use ) { sint i; @@ -1168,6 +1204,11 @@ _func_enter_; if (qc_exists && a4_exists) mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ if (qc_exists && !a4_exists) mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ if (!qc_exists) mic_iv[1] = 0x00; +#ifdef CONFIG_IEEE80211W + //802.11w management frame should set management bit(4) + if(frtype == WIFI_MGT_TYPE) + mic_iv[1] |= BIT(4); +#endif //CONFIG_IEEE80211W for (i = 2; i < 8; i++) mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ #ifdef CONSISTENT_PN_ORDER @@ -1187,17 +1228,26 @@ _func_exit_; /* construct_mic_header1() */ /* Builds the first MIC header block from */ /* header fields. */ +/* Build AAD SC,A1,A2 */ /************************************************/ static void construct_mic_header1( u8 *mic_header1, sint header_length, - u8 *mpdu + u8 *mpdu, + uint frtype// add for CONFIG_IEEE80211W, none 11w also can use ) { _func_enter_; mic_header1[0] = (u8)((header_length - 2) / 256); mic_header1[1] = (u8)((header_length - 2) % 256); - mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ +#ifdef CONFIG_IEEE80211W + //802.11w management frame don't AND subtype bits 4,5,6 of frame control field + if(frtype == WIFI_MGT_TYPE) + mic_header1[2] = mpdu[0]; /* Mute CF poll & CF ack bits */ + else +#endif //CONFIG_IEEE80211W + mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ + mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ mic_header1[4] = mpdu[4]; /* A1 */ mic_header1[5] = mpdu[5]; @@ -1271,6 +1321,8 @@ _func_exit_; /* construct_mic_header2() */ /* Builds the last MIC header block from */ /* header fields. */ +/* Baron think the function is construct CCM */ +/* nonce */ /************************************************/ static void construct_ctr_preload( u8 *ctr_preload, @@ -1278,20 +1330,25 @@ static void construct_ctr_preload( sint qc_exists, u8 *mpdu, u8 *pn_vector, - sint c + sint c, + uint frtype // add for CONFIG_IEEE80211W, none 11w also can use ) { sint i = 0; _func_enter_; for (i=0; i<16; i++) ctr_preload[i] = 0x00; i = 0; - + ctr_preload[0] = 0x01; /* flag */ if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f; - +#ifdef CONFIG_IEEE80211W + //802.11w management frame should set management bit(4) + if(frtype == WIFI_MGT_TYPE) + ctr_preload[1] |= BIT(4); +#endif //CONFIG_IEEE80211W for (i = 2; i < 8; i++) ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ #ifdef CONSISTENT_PN_ORDER @@ -1363,9 +1420,9 @@ _func_enter_; a4_exists = 1; if ( - (frtype == WIFI_DATA_CFACK) || - (frtype == WIFI_DATA_CFPOLL)|| - (frtype == WIFI_DATA_CFACKPOLL)) + ((frtype|frsubtype) == WIFI_DATA_CFACK) || + ((frtype|frsubtype) == WIFI_DATA_CFPOLL)|| + ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) { qc_exists = 1; if(hdrlen != WLAN_HDR_A3_QOS_LEN){ @@ -1373,11 +1430,12 @@ _func_enter_; hdrlen += 2; } } - else if ( - (frsubtype == 0x08) || + // add for CONFIG_IEEE80211W, none 11w also can use + else if ((frtype == WIFI_DATA) && + ((frsubtype == 0x08) || (frsubtype == 0x09)|| (frsubtype == 0x0a)|| - (frsubtype == 0x0b)) + (frsubtype == 0x0b))) { if(hdrlen != WLAN_HDR_A3_QOS_LEN){ @@ -1401,13 +1459,15 @@ _func_enter_; a4_exists, pframe, //message, plen, - pn_vector + pn_vector, + frtype // add for CONFIG_IEEE80211W, none 11w also can use ); construct_mic_header1( mic_header1, hdrlen, - pframe //message + pframe, //message + frtype // add for CONFIG_IEEE80211W, none 11w also can use ); construct_mic_header2( mic_header2, @@ -1466,7 +1526,8 @@ _func_enter_; qc_exists, pframe, //message, pn_vector, - i+1); + i+1, + frtype); // add for CONFIG_IEEE80211W, none 11w also can use aes128k128d(key, ctr_preload, aes_out); bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);//bitwise_xor(aes_out, &message[payload_index], chain_buffer); for (j=0; j<16;j++) pframe[payload_index++] = chain_buffer[j];//for (j=0; j<16;j++) message[payload_index++] = chain_buffer[j]; @@ -1480,7 +1541,8 @@ _func_enter_; qc_exists, pframe, //message, pn_vector, - num_blocks+1); + num_blocks+1, + frtype); // add for CONFIG_IEEE80211W, none 11w also can use for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < payload_remainder; j++) @@ -1499,7 +1561,8 @@ _func_enter_; qc_exists, pframe, //message, pn_vector, - 0); + 0, + frtype); // add for CONFIG_IEEE80211W, none 11w also can use for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < 8; j++) @@ -1566,7 +1629,7 @@ _func_enter_; { DBG_871X("%s, call rtw_get_stainfo()\n", __func__); stainfo=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0] ); - } + } if (stainfo!=NULL){ @@ -1671,7 +1734,7 @@ _func_enter_; //start to decrypt the payload - num_blocks = (plen-8) / 16; //(plen including llc, payload_length and mic ) + num_blocks = (plen-8) / 16; //(plen including LLC, payload_length and mic ) payload_remainder = (plen-8) % 16; @@ -1688,21 +1751,21 @@ _func_enter_; a4_exists = 1; if ( - (frtype == WIFI_DATA_CFACK) || - (frtype == WIFI_DATA_CFPOLL)|| - (frtype == WIFI_DATA_CFACKPOLL)) + ((frtype|frsubtype) == WIFI_DATA_CFACK) || + ((frtype|frsubtype) == WIFI_DATA_CFPOLL)|| + ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) { qc_exists = 1; if(hdrlen != WLAN_HDR_A3_QOS_LEN){ hdrlen += 2; } - } - else if ( - (frsubtype == 0x08) || + }//only for data packet . add for CONFIG_IEEE80211W, none 11w also can use + else if ((frtype == WIFI_DATA) && + ((frsubtype == 0x08) || (frsubtype == 0x09)|| (frsubtype == 0x0a)|| - (frsubtype == 0x0b)) + (frsubtype == 0x0b))) { if(hdrlen != WLAN_HDR_A3_QOS_LEN){ @@ -1726,7 +1789,8 @@ _func_enter_; qc_exists, pframe, pn_vector, - i+1 + i+1, + frtype ); aes128k128d(key, ctr_preload, aes_out); @@ -1743,7 +1807,8 @@ _func_enter_; qc_exists, pframe, pn_vector, - num_blocks+1 + num_blocks+1, + frtype // add for CONFIG_IEEE80211W, none 11w also can use ); for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; @@ -1776,13 +1841,15 @@ _func_enter_; a4_exists, message, plen-8, - pn_vector + pn_vector, + frtype // add for CONFIG_IEEE80211W, none 11w also can use ); construct_mic_header1( mic_header1, hdrlen, - message + message, + frtype // add for CONFIG_IEEE80211W, none 11w also can use ); construct_mic_header2( mic_header2, @@ -1841,7 +1908,8 @@ _func_enter_; qc_exists, message, pn_vector, - i+1); + i+1, + frtype); // add for CONFIG_IEEE80211W, none 11w also can use aes128k128d(key, ctr_preload, aes_out); bitwise_xor(aes_out, &message[payload_index], chain_buffer); for (j=0; j<16;j++) message[payload_index++] = chain_buffer[j]; @@ -1855,7 +1923,8 @@ _func_enter_; qc_exists, message, pn_vector, - num_blocks+1); + num_blocks+1, + frtype); // add for CONFIG_IEEE80211W, none 11w also can use for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < payload_remainder; j++) @@ -1874,7 +1943,8 @@ _func_enter_; qc_exists, message, pn_vector, - 0); + 0, + frtype); // add for CONFIG_IEEE80211W, none 11w also can use for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < 8; j++) @@ -1952,9 +2022,31 @@ _func_enter_; { prwskey=&stainfo->dot118021x_UncstKey.skey[0]; } - + length= ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len; - + /*// add for CONFIG_IEEE80211W, debug + if(0) + printk("@@@@@@@@@@@@@@@@@@ length=%d, prxattrib->hdrlen=%d, prxattrib->pkt_len=%d \n" + , length, prxattrib->hdrlen, prxattrib->pkt_len); + if(0) + { + int no; + //test print PSK + printk("PSK key below:\n"); + for(no=0;no<16;no++) + printk(" %02x ", prwskey[no]); + printk("\n"); + } + if(0) + { + int no; + //test print PSK + printk("frame:\n"); + for(no=0;no<prxattrib->pkt_len;no++) + printk(" %02x ", pframe[no]); + printk("\n"); + }*/ + res= aes_decipher(prwskey,prxattrib->hdrlen,pframe, length); @@ -1969,6 +2061,109 @@ _func_exit_; exit: return res; } + +#ifdef CONFIG_IEEE80211W +u32 rtw_BIP_verify(_adapter *padapter, u8 *precvframe) +{ + struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib; + u8 *pframe; + u8 *BIP_AAD, *p; + u32 res=_FAIL; + uint len, ori_len; + struct rtw_ieee80211_hdr *pwlanhdr; + u8 mic[16]; + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE; + BIP_AAD = rtw_zmalloc(ori_len); + + if(BIP_AAD == NULL) + { + DBG_871X("BIP AAD allocate fail\n"); + return _FAIL; + } + //PKT start + pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data; + //mapping to wlan header + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + //save the frame body + MME + _rtw_memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN); + //find MME IE pointer + p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, _MME_IE_, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN); + //Baron + if(p) + { + u16 keyid=0; + u64 temp_ipn=0; + //save packet number + _rtw_memcpy(&temp_ipn, p+4, 6); + temp_ipn = le64_to_cpu(temp_ipn); + //BIP packet number should bigger than previous BIP packet + if(temp_ipn <= pmlmeext->mgnt_80211w_IPN_rx) + { + DBG_871X("replay BIP packet\n"); + goto BIP_exit; + } + //copy key index + _rtw_memcpy(&keyid, p+2, 2); + keyid = le16_to_cpu(keyid); + if(keyid != padapter->securitypriv.dot11wBIPKeyid) + { + DBG_871X("BIP key index error!\n"); + goto BIP_exit; + } + //clear the MIC field of MME to zero + _rtw_memset(p+2+len-8, 0, 8); + + //conscruct AAD, copy frame control field + _rtw_memcpy(BIP_AAD, &pwlanhdr->frame_ctl, 2); + ClearRetry(BIP_AAD); + ClearPwrMgt(BIP_AAD); + ClearMData(BIP_AAD); + //conscruct AAD, copy address 1 to address 3 + _rtw_memcpy(BIP_AAD+2, pwlanhdr->addr1, 18); + + if(omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey + , BIP_AAD, ori_len, mic)) + goto BIP_exit; + + /*//management packet content + { + int pp; + DBG_871X("pkt: "); + for(pp=0;pp< pattrib->pkt_len; pp++) + printk(" %02x ", pframe[pp]); + DBG_871X("\n"); + //BIP AAD + management frame body + MME(MIC is zero) + DBG_871X("AAD+PKT: "); + for(pp=0;pp< ori_len; pp++) + DBG_871X(" %02x ", BIP_AAD[pp]); + DBG_871X("\n"); + //show the MIC result + DBG_871X("mic: "); + for(pp=0;pp<16; pp++) + DBG_871X(" %02x ", mic[pp]); + DBG_871X("\n"); + } + */ + //MIC field should be last 8 bytes of packet (packet without FCS) + if(_rtw_memcmp(mic, pframe+pattrib->pkt_len-8, 8)) + { + pmlmeext->mgnt_80211w_IPN_rx = temp_ipn; + res=_SUCCESS; + } + else + DBG_871X("BIP MIC error!\n"); + + } + else + res = RTW_RX_HANDLED; +BIP_exit: + + rtw_mfree(BIP_AAD, ori_len); + return res; +} +#endif //CONFIG_IEEE80211W + #ifndef PLATFORM_FREEBSD /* compress 512-bits */ static int sha256_compress(struct sha256_state *md, unsigned char *buf) @@ -2676,8 +2871,8 @@ static int omac1_aes_128_vector(u8 *key, size_t num_elem, * This is a mode for using block cipher (AES in this case) for authentication. * OMAC1 was standardized with the name CMAC by NIST in a Special Publication * (SP) 800-38B. - */ -static int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac) + */ //modify for CONFIG_IEEE80211W +int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); } @@ -2891,3 +3086,43 @@ _func_exit_; } +/* Restore HW wep key setting according to key_mask */ +void rtw_sec_restore_wep_key(_adapter *adapter) +{ + struct security_priv* securitypriv=&(adapter->securitypriv); + sint keyid; + + if((_WEP40_ == securitypriv->dot11PrivacyAlgrthm) ||(_WEP104_ == securitypriv->dot11PrivacyAlgrthm)) { + for(keyid=0;keyid<4;keyid++){ + if(securitypriv->key_mask & BIT(keyid)){ + if(keyid == securitypriv->dot11PrivacyKeyIndex) + rtw_set_key(adapter,securitypriv, keyid, 1, _TRUE); + else + rtw_set_key(adapter,securitypriv, keyid, 0, _TRUE); + } + } + } +} + +u8 rtw_handle_tkip_countermeasure(_adapter* adapter, const char *caller) +{ + struct security_priv* securitypriv=&(adapter->securitypriv); + u8 status = _SUCCESS; + + if (securitypriv->btkip_countermeasure == _TRUE) { + u32 passing_ms = rtw_get_passing_time_ms(securitypriv->btkip_countermeasure_time); + if (passing_ms > 60*1000) { + DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%ds > 60s \n", + caller, ADPT_ARG(adapter), passing_ms/1000); + securitypriv->btkip_countermeasure = _FALSE; + securitypriv->btkip_countermeasure_time = 0; + } else { + DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%ds < 60s \n", + caller, ADPT_ARG(adapter), passing_ms/1000); + status = _FAIL; + } + } + + return status; +} + diff --git a/drivers/net/wireless/rtl8723as/core/rtw_sreset.c b/drivers/net/wireless/rtl8723as/core/rtw_sreset.c index b700bbfe5958..bc34827b492b 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_sreset.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_sreset.c @@ -1,350 +1,356 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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, USA - * - * - ******************************************************************************/ - -#include<rtw_sreset.h> - -void sreset_init_value(_adapter *padapter) -{ -#if defined(DBG_CONFIG_ERROR_DETECT) - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - _rtw_mutex_init(&psrtpriv->silentreset_mutex); - psrtpriv->silent_reset_inprogress = _FALSE; - psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS; - psrtpriv->last_tx_time =0; - psrtpriv->last_tx_complete_time =0; -#endif -} -void sreset_reset_value(_adapter *padapter) -{ -#if defined(DBG_CONFIG_ERROR_DETECT) - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - psrtpriv->silent_reset_inprogress = _FALSE; - psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS; - psrtpriv->last_tx_time =0; - psrtpriv->last_tx_complete_time =0; -#endif -} - -u8 sreset_get_wifi_status(_adapter *padapter) -{ -#if defined(DBG_CONFIG_ERROR_DETECT) - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - - u8 status = WIFI_STATUS_SUCCESS; - u32 val32 = 0; - _irqL irqL; - if(psrtpriv->silent_reset_inprogress == _TRUE) - { - return status; - } - val32 =rtw_read32(padapter,REG_TXDMA_STATUS); - if(val32==0xeaeaeaea){ - psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST; - } - else if(val32!=0){ - DBG_8192C("txdmastatu(%x)\n",val32); - psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR; - } - - if(WIFI_STATUS_SUCCESS !=psrtpriv->Wifi_Error_Status) - { - DBG_8192C("==>%s error_status(0x%x) \n",__FUNCTION__,psrtpriv->Wifi_Error_Status); - status = (psrtpriv->Wifi_Error_Status &( ~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL))); - } - DBG_8192C("==> %s wifi_status(0x%x)\n",__FUNCTION__,status); - - //status restore - psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS; - - return status; -#else - return WIFI_STATUS_SUCCESS; -#endif -} - -void sreset_set_wifi_error_status(_adapter *padapter, u32 status) -{ -#if defined(DBG_CONFIG_ERROR_DETECT) - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - pHalData->srestpriv.Wifi_Error_Status = status; -#endif -} - -void sreset_set_trigger_point(_adapter *padapter, s32 tgp) -{ -#if defined(DBG_CONFIG_ERROR_DETECT) - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - pHalData->srestpriv.dbg_trigger_point = tgp; -#endif -} - -bool sreset_inprogress(_adapter *padapter) -{ -#if defined(DBG_CONFIG_ERROR_RESET) - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - return pHalData->srestpriv.silent_reset_inprogress; -#else - return _FALSE; -#endif -} - -void sreset_restore_security_station(_adapter *padapter) -{ - u8 EntryId = 0; - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct sta_priv * pstapriv = &padapter->stapriv; - struct sta_info *psta; - struct security_priv* psecuritypriv=&(padapter->securitypriv); - struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info; - - { - u8 val8; - - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) { - val8 = 0xcc; - #ifdef CONFIG_WAPI_SUPPORT - } else if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI) { - //Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey. - val8 = 0x4c; - #endif - } else { - val8 = 0xcf; - } - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); - } - - #if 0 - if ( ( padapter->securitypriv.dot11PrivacyAlgrthm == _WEP40_ ) || - ( padapter->securitypriv.dot11PrivacyAlgrthm == _WEP104_ )) - { - - for(EntryId=0; EntryId<4; EntryId++) - { - if(EntryId == psecuritypriv->dot11PrivacyKeyIndex) - rtw_set_key(padapter,&padapter->securitypriv, EntryId, 1); - else - rtw_set_key(padapter,&padapter->securitypriv, EntryId, 0); - } - - } - else - #endif - if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) || - (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) - { - psta = rtw_get_stainfo(pstapriv, get_bssid(mlmepriv)); - if (psta == NULL) { - //DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail \n")); - } - else - { - //pairwise key - rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE); - //group key - rtw_set_key(padapter,&padapter->securitypriv,padapter->securitypriv.dot118021XGrpKeyid, 0); - } - } -} - -void sreset_restore_network_station(_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - #if 0 - { - //======================================================= - // reset related register of Beacon control - - //set MSR to nolink - Set_MSR(padapter, _HW_STATE_NOLINK_); - // reject all data frame - rtw_write16(padapter, REG_RXFLTMAP2,0x00); - //reset TSF - rtw_write8(padapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1))); - - // disable update TSF - SetBcnCtrlReg(padapter, BIT(4), 0); - - //======================================================= - } - #endif - - rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure); - - { - u8 threshold; - #ifdef CONFIG_USB_HCI - // TH=1 => means that invalidate usb rx aggregation - // TH=0 => means that validate usb rx aggregation, use init value. - if(mlmepriv->htpriv.ht_option) { - if(padapter->registrypriv.wifi_spec==1) - threshold = 1; - else - threshold = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold)); - } else { - threshold = 1; - rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold)); - } - #endif - } - - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - //disable dynamic functions, such as high power, DIG - //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE); - - rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress); - - { - u8 join_type = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); - } - - Set_MSR(padapter, (pmlmeinfo->state & 0x3)); - - mlmeext_joinbss_event_callback(padapter, 1); - //restore Sequence No. - rtw_write8(padapter,0x4dc,padapter->xmitpriv.nqos_ssn); - - sreset_restore_security_station(padapter); -} - -void sreset_restore_network_status(_adapter *padapter) -{ - struct mlme_priv *mlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) { - DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv)); - sreset_restore_network_station(padapter); - } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) { - DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv)); - rtw_ap_restore_network(padapter); - } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) { - DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv)); - } else { - DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv)); - } -} - -void sreset_stop_adapter(_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); - - if (!rtw_netif_queue_stopped(padapter->pnetdev)) - rtw_netif_stop_queue(padapter->pnetdev); - - rtw_cancel_all_timer(padapter); - - /* TODO: OS and HCI independent */ - #if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI) - tasklet_kill(&pxmitpriv->xmit_tasklet); - #endif - - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - rtw_scan_abort(padapter); - - if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) - _rtw_join_timeout_handler(padapter); - -} - -void sreset_start_adapter(_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - if (padapter == NULL) - return; - - DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); - - if (check_fwstate(pmlmepriv, _FW_LINKED)) { - sreset_restore_network_status(padapter); - } - - /* TODO: OS and HCI independent */ - #if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI) - tasklet_hi_schedule(&pxmitpriv->xmit_tasklet); - #endif - - _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000); - - if (rtw_netif_queue_stopped(padapter->pnetdev)) - rtw_netif_wake_queue(padapter->pnetdev); - -} - -void sreset_reset(_adapter *padapter) -{ -#ifdef DBG_CONFIG_ERROR_RESET - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - struct sreset_priv *psrtpriv = &pHalData->srestpriv; - struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - _irqL irqL; - u32 start = rtw_get_current_time(); - - DBG_871X("%s\n", __FUNCTION__); - - psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS; - - _enter_critical_mutex(&psrtpriv->silentreset_mutex, &irqL); - psrtpriv->silent_reset_inprogress = _TRUE; - pwrpriv->change_rfpwrstate = rf_off; - - sreset_stop_adapter(padapter); - #ifdef CONFIG_CONCURRENT_MODE - sreset_stop_adapter(padapter->pbuddy_adapter); - #endif - - #ifdef CONFIG_IPS - ips_enter(padapter); - ips_leave(padapter); - #endif - - sreset_start_adapter(padapter); - #ifdef CONFIG_CONCURRENT_MODE - sreset_start_adapter(padapter->pbuddy_adapter); - #endif - - psrtpriv->silent_reset_inprogress = _FALSE; - _exit_critical_mutex(&psrtpriv->silentreset_mutex, &irqL); - - DBG_871X("%s done in %d ms\n", __FUNCTION__, rtw_get_passing_time_ms(start)); -#endif -} - +/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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, USA
+ *
+ *
+ ******************************************************************************/
+
+#include<rtw_sreset.h>
+
+void sreset_init_value(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+ _rtw_mutex_init(&psrtpriv->silentreset_mutex);
+ psrtpriv->silent_reset_inprogress = _FALSE;
+ psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+ psrtpriv->last_tx_time =0;
+ psrtpriv->last_tx_complete_time =0;
+#endif
+}
+void sreset_reset_value(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+ //psrtpriv->silent_reset_inprogress = _FALSE;
+ psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+ psrtpriv->last_tx_time =0;
+ psrtpriv->last_tx_complete_time =0;
+#endif
+}
+
+u8 sreset_get_wifi_status(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+ u8 status = WIFI_STATUS_SUCCESS;
+ u32 val32 = 0;
+ _irqL irqL;
+ if(psrtpriv->silent_reset_inprogress == _TRUE)
+ {
+ return status;
+ }
+ val32 =rtw_read32(padapter,REG_TXDMA_STATUS);
+ if(val32==0xeaeaeaea){
+ psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
+ }
+ else if(val32!=0){
+ DBG_8192C("txdmastatu(%x)\n",val32);
+ psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
+ }
+
+ if(WIFI_STATUS_SUCCESS !=psrtpriv->Wifi_Error_Status)
+ {
+ DBG_8192C("==>%s error_status(0x%x) \n",__FUNCTION__,psrtpriv->Wifi_Error_Status);
+ status = (psrtpriv->Wifi_Error_Status &( ~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL)));
+ }
+ DBG_8192C("==> %s wifi_status(0x%x)\n",__FUNCTION__,status);
+
+ //status restore
+ psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+
+ return status;
+#else
+ return WIFI_STATUS_SUCCESS;
+#endif
+}
+
+void sreset_set_wifi_error_status(_adapter *padapter, u32 status)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ pHalData->srestpriv.Wifi_Error_Status = status;
+#endif
+}
+
+void sreset_set_trigger_point(_adapter *padapter, s32 tgp)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ pHalData->srestpriv.dbg_trigger_point = tgp;
+#endif
+}
+
+bool sreset_inprogress(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_RESET)
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ return pHalData->srestpriv.silent_reset_inprogress;
+#else
+ return _FALSE;
+#endif
+}
+
+void sreset_restore_security_station(_adapter *padapter)
+{
+ u8 EntryId = 0;
+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+ struct sta_priv * pstapriv = &padapter->stapriv;
+ struct sta_info *psta;
+ struct security_priv* psecuritypriv=&(padapter->securitypriv);
+ struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
+
+ {
+ u8 val8;
+
+ if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) {
+ val8 = 0xcc;
+ #ifdef CONFIG_WAPI_SUPPORT
+ } else if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI) {
+ //Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey.
+ val8 = 0x4c;
+ #endif
+ } else {
+ val8 = 0xcf;
+ }
+ rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+ }
+
+ #if 0
+ if ( ( padapter->securitypriv.dot11PrivacyAlgrthm == _WEP40_ ) ||
+ ( padapter->securitypriv.dot11PrivacyAlgrthm == _WEP104_ ))
+ {
+
+ for(EntryId=0; EntryId<4; EntryId++)
+ {
+ if(EntryId == psecuritypriv->dot11PrivacyKeyIndex)
+ rtw_set_key(padapter,&padapter->securitypriv, EntryId, 1,_FALSE);
+ else
+ rtw_set_key(padapter,&padapter->securitypriv, EntryId, 0,_FALSE);
+ }
+
+ }
+ else
+ #endif
+ if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
+ (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
+ {
+ psta = rtw_get_stainfo(pstapriv, get_bssid(mlmepriv));
+ if (psta == NULL) {
+ //DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail \n"));
+ }
+ else
+ {
+ //pairwise key
+ rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE,_FALSE);
+ //group key
+ rtw_set_key(padapter,&padapter->securitypriv,padapter->securitypriv.dot118021XGrpKeyid, 0,_FALSE);
+ }
+ }
+}
+
+void sreset_restore_network_station(_adapter *padapter)
+{
+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ #if 0
+ {
+ //=======================================================
+ // reset related register of Beacon control
+
+ //set MSR to nolink
+ Set_MSR(padapter, _HW_STATE_NOLINK_);
+ // reject all data frame
+ rtw_write16(padapter, REG_RXFLTMAP2,0x00);
+ //reset TSF
+ rtw_write8(padapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1)));
+
+ // disable update TSF
+ SetBcnCtrlReg(padapter, BIT(4), 0);
+
+ //=======================================================
+ }
+ #endif
+
+ rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure,_FALSE);
+
+ {
+ u8 threshold;
+ #ifdef CONFIG_USB_HCI
+ // TH=1 => means that invalidate usb rx aggregation
+ // TH=0 => means that validate usb rx aggregation, use init value.
+ if(mlmepriv->htpriv.ht_option) {
+ if(padapter->registrypriv.wifi_spec==1)
+ threshold = 1;
+ else
+ threshold = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+ } else {
+ threshold = 1;
+ rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+ }
+ #endif
+ }
+
+ set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+ //disable dynamic functions, such as high power, DIG
+ //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
+
+ rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
+
+ {
+ u8 join_type = 0;
+ rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+ }
+
+ Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+
+ mlmeext_joinbss_event_callback(padapter, 1);
+ //restore Sequence No.
+ rtw_write8(padapter,0x4dc,padapter->xmitpriv.nqos_ssn);
+
+ sreset_restore_security_station(padapter);
+}
+
+
+void sreset_restore_network_status(_adapter *padapter)
+{
+ struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
+ DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+ sreset_restore_network_station(padapter);
+ } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
+ DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+ rtw_ap_restore_network(padapter);
+ } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
+ DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+ } else {
+ DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+ }
+}
+
+void sreset_stop_adapter(_adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ if (padapter == NULL)
+ return;
+
+ DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+ if (!rtw_netif_queue_stopped(padapter->pnetdev))
+ rtw_netif_stop_queue(padapter->pnetdev);
+
+ rtw_cancel_all_timer(padapter);
+
+ /* TODO: OS and HCI independent */
+ #if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI)
+ tasklet_kill(&pxmitpriv->xmit_tasklet);
+ #endif
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+ rtw_scan_abort(padapter);
+
+ if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+ {
+ rtw_set_roaming(padapter, 0);
+ _rtw_join_timeout_handler(padapter);
+ }
+
+}
+
+void sreset_start_adapter(_adapter *padapter)
+{
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+ if (padapter == NULL)
+ return;
+
+ DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+ if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+ sreset_restore_network_status(padapter);
+ }
+
+ /* TODO: OS and HCI independent */
+ #if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI)
+ tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+ #endif
+
+ _set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);
+
+ if (rtw_netif_queue_stopped(padapter->pnetdev))
+ rtw_netif_wake_queue(padapter->pnetdev);
+
+}
+
+void sreset_reset(_adapter *padapter)
+{
+#ifdef DBG_CONFIG_ERROR_RESET
+ HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+ struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+ struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ _irqL irqL;
+ u32 start = rtw_get_current_time();
+
+ DBG_871X("%s\n", __FUNCTION__);
+
+ psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+
+ _enter_pwrlock(&pwrpriv->lock);
+
+ psrtpriv->silent_reset_inprogress = _TRUE;
+ pwrpriv->change_rfpwrstate = rf_off;
+
+ sreset_stop_adapter(padapter);
+ #ifdef CONFIG_CONCURRENT_MODE
+ sreset_stop_adapter(padapter->pbuddy_adapter);
+ #endif
+
+ #ifdef CONFIG_IPS
+ _ips_enter(padapter);
+ _ips_leave(padapter);
+ #endif
+
+ sreset_start_adapter(padapter);
+ #ifdef CONFIG_CONCURRENT_MODE
+ sreset_start_adapter(padapter->pbuddy_adapter);
+ #endif
+
+ psrtpriv->silent_reset_inprogress = _FALSE;
+
+ _exit_pwrlock(&pwrpriv->lock);
+
+ DBG_871X("%s done in %d ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
+#endif
+}
+
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_sta_mgt.c b/drivers/net/wireless/rtl8723as/core/rtw_sta_mgt.c index 3c1e4c305dc3..3ba598f87371 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_sta_mgt.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_sta_mgt.c @@ -87,7 +87,18 @@ _func_enter_; psta->keep_alive_trycnt = 0; #endif // CONFIG_AP_MODE + +#ifdef DBG_TRX_STA_PKTS + psta->tx_be_cnt = 0; + psta->tx_bk_cnt = 0; + psta->tx_vi_cnt = 0; + psta->tx_vo_cnt = 0; + psta->rx_be_cnt = 0; + psta->rx_bk_cnt = 0; + psta->rx_vi_cnt = 0; + psta->rx_vo_cnt = 0; +#endif _func_exit_; } diff --git a/drivers/net/wireless/rtl8723as/core/rtw_tdls.c b/drivers/net/wireless/rtl8723as/core/rtw_tdls.c index 231b240c89b7..f7ca24aab826 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_tdls.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_tdls.c @@ -1,2941 +1,2941 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * 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, USA - * - * - ******************************************************************************/ -#define _RTW_TDLS_C_ - -#include <drv_types.h> -#include <ethernet.h> -#include <rtw_tdls.h> -#include <wifi.h> - -#ifdef CONFIG_TDLS -extern unsigned char MCS_rate_2R[16]; -extern unsigned char MCS_rate_1R[16]; -extern void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame); -extern s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe); - -void rtw_reset_tdls_info(_adapter* padapter) -{ - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - - ptdlsinfo->ap_prohibited = _FALSE; - ptdlsinfo->setup_state = TDLS_STATE_NONE; - ptdlsinfo->sta_cnt = 0; - ptdlsinfo->sta_maximum = _FALSE; - ptdlsinfo->macid_index= 6; - ptdlsinfo->clear_cam= 0; - ptdlsinfo->ch_sensing = 0; - ptdlsinfo->cur_channel = 0; - ptdlsinfo->candidate_ch = 1; //when inplement channel switching, default candidate channel is 1 - ptdlsinfo->watchdog_count = 0; - ptdlsinfo->dev_discovered = 0; - -#ifdef CONFIG_WFD - ptdlsinfo->wfd_info = &padapter->wfd_info; -#endif //CONFIG_WFD -} - -int rtw_init_tdls_info(_adapter* padapter) -{ - int res = _SUCCESS; - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - - ptdlsinfo->enable = 1; - rtw_reset_tdls_info(padapter); - - _rtw_spinlock_init(&ptdlsinfo->cmd_lock); - _rtw_spinlock_init(&ptdlsinfo->hdl_lock); - - return res; - -} - -void rtw_free_tdls_info(struct tdls_info *ptdlsinfo) -{ - _rtw_spinlock_free(&ptdlsinfo->cmd_lock); - _rtw_spinlock_free(&ptdlsinfo->hdl_lock); - - _rtw_memset(ptdlsinfo, 0, sizeof(struct tdls_info) ); - -} - -void issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, struct sta_info *ptdls_sta, unsigned int power_mode) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; -// SetToDs(fctrl); - if (power_mode) - { - SetPwrMgt(fctrl); - } - - _rtw_memcpy(pwlanhdr->addr1, ptdls_sta->hwaddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - - ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority]++; - ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF; - pattrib->seqnum = ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority]; - SetSeqNum(pwlanhdr, pattrib->seqnum); - - SetFrameSubType(pframe, WIFI_DATA_NULL); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe(padapter, pmgntframe); - - return; -} - -s32 update_tdls_attrib(_adapter *padapter, struct pkt_attrib *pattrib) -{ - - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct qos_priv *pqospriv= &pmlmepriv->qospriv; - - s32 res=_SUCCESS; - sint bmcast; - - bmcast = IS_MCAST(pattrib->ra); - - psta = rtw_get_stainfo(pstapriv, pattrib->ra); - if (psta == NULL) { - res =_FAIL; - goto exit; - } - - pattrib->mac_id = psta->mac_id; - - pattrib->psta = psta; - - pattrib->ack_policy = 0; - // get ether_hdr_len - pattrib->pkt_hdrlen = ETH_HLEN;//(pattrib->ether_type == 0x8100) ? (14 + 4 ): 14; //vlan tag - - if (pqospriv->qos_option && psta->qos_option) { - pattrib->priority = 1; //tdls management frame should be AC_BK - pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN; - pattrib->subtype = WIFI_QOS_DATA_TYPE; - } else { - pattrib->hdrlen = WLAN_HDR_A3_LEN; - pattrib->subtype = WIFI_DATA_TYPE; - pattrib->priority = 0; - } - - if (psta->ieee8021x_blocked == _TRUE) - { - pattrib->encrypt = 0; - } - else - { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); - - switch(psecuritypriv->dot11AuthAlgrthm) - { - case dot11AuthAlgrthm_Open: - case dot11AuthAlgrthm_Shared: - case dot11AuthAlgrthm_Auto: - pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex; - break; - case dot11AuthAlgrthm_8021X: - pattrib->key_idx = 0; - break; - default: - pattrib->key_idx = 0; - break; - } - } - - switch (pattrib->encrypt) - { - case _WEP40_: - case _WEP104_: - pattrib->iv_len = 4; - pattrib->icv_len = 4; - break; - case _TKIP_: - pattrib->iv_len = 8; - pattrib->icv_len = 4; - if(padapter->securitypriv.busetkipkey==_FAIL) - { - res =_FAIL; - goto exit; - } - break; - case _AES_: - pattrib->iv_len = 8; - pattrib->icv_len = 8; - break; - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - - if (pattrib->encrypt && - ((padapter->securitypriv.sw_encrypt == _TRUE) || (psecuritypriv->hw_decrypted == _FALSE))) - { - pattrib->bswenc = _TRUE; - } else { - pattrib->bswenc = _FALSE; - } - - //qos_en, ht_en, init rate, ,bw, ch_offset, sgi - pattrib->qos_en = psta->qos_option; - pattrib->ht_en = psta->htpriv.ht_option; - pattrib->raid = psta->raid; - pattrib->bwmode = psta->htpriv.bwmode; - pattrib->ch_offset = psta->htpriv.ch_offset; - pattrib->sgi= psta->htpriv.sgi; - pattrib->ampdu_en = _FALSE; - - //if(pattrib->ht_en && psta->htpriv.ampdu_enable) - //{ - // if(psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority)) - // pattrib->ampdu_en = _TRUE; - //} - -exit: - - return res; -} - -void free_tdls_sta(_adapter *padapter, struct sta_info *ptdls_sta) -{ - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - struct sta_priv *pstapriv = &padapter->stapriv; - _irqL irqL; - - //free peer sta_info - _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - if(ptdlsinfo->sta_cnt != 0) - ptdlsinfo->sta_cnt--; - _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - if( ptdlsinfo->sta_cnt < (NUM_STA - 2) ) // -2: AP + BC/MC sta - { - ptdlsinfo->sta_maximum = _FALSE; - _rtw_memset( &ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record) ); - } - //ready to clear cam - if(ptdls_sta->mac_id!=0){ - ptdlsinfo->clear_cam=ptdls_sta->mac_id; - rtw_setstakey_cmd(padapter, (u8 *)ptdls_sta, _TRUE); - } - - if(ptdlsinfo->sta_cnt==0){ - rtw_tdls_cmd(padapter, myid(&(padapter->eeprompriv)), TDLS_RS_RCR); - ptdlsinfo->setup_state=TDLS_STATE_NONE; - } - else - DBG_871X("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt); - - rtw_free_stainfo(padapter, ptdls_sta); - -} - -// cam entry will be the same as mac_id -void rtw_tdls_set_mac_id(struct tdls_info *ptdlsinfo, struct sta_info *ptdls_sta) -{ - if(ptdls_sta->mac_id==0) - { - ptdls_sta->mac_id = ptdlsinfo->macid_index; - if( (++ptdlsinfo->macid_index) > (NUM_STA -2) ) - ptdlsinfo->macid_index= TDLS_INI_MACID_ENTRY; - } -} - -//TDLS encryption(if needed) will always be CCMP -void rtw_tdls_set_key(_adapter *adapter, struct rx_pkt_attrib *prx_pkt_attrib, struct sta_info *ptdls_sta) -{ - if(prx_pkt_attrib->encrypt) - { - ptdls_sta->dot118021XPrivacy=_AES_; - rtw_setstakey_cmd(adapter, (u8*)ptdls_sta, _TRUE); - } -} - -void rtw_tdls_process_ht_cap(_adapter *adapter, struct sta_info *ptdls_sta, u8 *data, u8 Length) -{ - /* save HT capabilities in the sta object */ - _rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap)); - if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap) ) - { - ptdls_sta->flags |= WLAN_STA_HT; - - ptdls_sta->flags |= WLAN_STA_WME; - - _rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap)); - - } else - ptdls_sta->flags &= ~WLAN_STA_HT; - - if(ptdls_sta->flags & WLAN_STA_HT) - { - if(adapter->registrypriv.ht_enable == _TRUE) - { - ptdls_sta->htpriv.ht_option = _TRUE; - } - else - { - ptdls_sta->htpriv.ht_option = _FALSE; - ptdls_sta->stat_code = _STATS_FAILURE_; - } - } - - //HT related cap - if(ptdls_sta->htpriv.ht_option) - { - //check if sta supports rx ampdu - if(adapter->registrypriv.ampdu_enable==1) - ptdls_sta->htpriv.ampdu_enable = _TRUE; - - //check if sta support s Short GI - if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40)) - { - ptdls_sta->htpriv.sgi = _TRUE; - } - - // bwmode would still followed AP's setting - if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) - { - ptdls_sta->htpriv.bwmode = adapter->mlmeextpriv.cur_bwmode; - ptdls_sta->htpriv.ch_offset = adapter->mlmeextpriv.cur_ch_offset; - } - } -} - -u8 *rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib) -{ - struct rtw_ieee80211_ht_cap ht_capie; - u8 rf_type; - - //HT capabilities - _rtw_memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap)); - - ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |IEEE80211_HT_CAP_SGI_20 |IEEE80211_HT_CAP_SM_PS | - IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_TX_STBC |IEEE80211_HT_CAP_DSSSCCK40; - - { - u32 rx_packet_offset, max_recvbuf_sz; - padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset); - padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz); - if(max_recvbuf_sz-rx_packet_offset>(8191-256)) - ht_capie.cap_info = ht_capie.cap_info |IEEE80211_HT_CAP_MAX_AMSDU; - } - - ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR&0x03); - - padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - switch(rf_type) - { - case RF_1T1R: - ht_capie.cap_info |= 0x0100;//RX STBC One spatial stream - _rtw_memcpy(ht_capie.supp_mcs_set, MCS_rate_1R, 16); - break; - - case RF_2T2R: - case RF_1T2R: - default: - ht_capie.cap_info|= 0x0200;//RX STBC two spatial stream - _rtw_memcpy(ht_capie.supp_mcs_set, MCS_rate_2R, 16); - break; - } - - return(rtw_set_ie(pframe, _HT_CAPABILITY_IE_, - sizeof(struct rtw_ieee80211_ht_cap), (unsigned char*)&ht_capie, &(pattrib->pktlen))); -} - -u8 *rtw_tdls_set_sup_ch(struct mlme_ext_priv *pmlmeext, u8 *pframe, struct pkt_attrib *pattrib) -{ - u8 sup_ch[ 30 * 2 ] = { 0x00 }, sup_ch_idx = 0, idx_5g = 2; //For supported channel - do{ - if( pmlmeext->channel_set[sup_ch_idx].ChannelNum <= 14 ) - { - sup_ch[0] = 1; //First channel number - sup_ch[1] = pmlmeext->channel_set[sup_ch_idx].ChannelNum; //Number of channel - } - else - { - sup_ch[idx_5g++] = pmlmeext->channel_set[sup_ch_idx].ChannelNum; - sup_ch[idx_5g++] = 1; - } - - sup_ch_idx++; - } - while( pmlmeext->channel_set[sup_ch_idx].ChannelNum != 0 ); - return(rtw_set_ie(pframe, _SUPPORTED_CH_IE_, idx_5g, sup_ch, &(pattrib->pktlen))); -} - -#ifdef CONFIG_WFD -void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length) -{ - u8 wfd_ie[ 128 ] = { 0x00 }; - u32 wfd_ielen = 0; - u32 wfd_offset = 0; - // Try to get the TCP port information when receiving the negotiation response. - // - - wfd_offset = 0; - wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen ); - while( wfd_offset ) - { - u8 attr_content[ 10 ] = { 0x00 }; - u32 attr_contentlen = 0; - int i; - - DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ ); - rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen); - if ( attr_contentlen ) - { - ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 ); - DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport ); - } - - _rtw_memset( attr_content, 0x00, 10); - attr_contentlen = 0; - rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, attr_content, &attr_contentlen); - if ( attr_contentlen ) - { - _rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, ( attr_content + 1 ), 4); - DBG_871X( "[%s] Peer IP = %02u.%02u.%02u.%02u \n", __FUNCTION__, - ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1], - ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3] - ); - } - wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen ); - } -} - -void issue_tunneled_probe_req(_adapter *padapter) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - DBG_871X("[%s]\n", __FUNCTION__); - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN); - - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - pattrib->qsel=pattrib->priority; - if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TUNNELED_PROBE_REQ) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; -} - -void issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib; - - DBG_871X("[%s]\n", __FUNCTION__); - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN); - - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - pattrib->qsel=pattrib->priority; - if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TUNNELED_PROBE_RSP) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; -} -#endif //CONFIG_WFD - -void issue_tdls_setup_req(_adapter *padapter, u8 *mac_addr) -{ - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *ptdls_sta= NULL; - _irqL irqL; - static u8 dialogtoken = 0; - u32 timeout_interval= TPK_RESEND_COUNT * 1000; //retry timer should set at least 301 sec, using TPK_count counting 301 times. - - if(ptdlsinfo->ap_prohibited == _TRUE) - goto exit; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN); - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - - //init peer sta_info - ptdls_sta = rtw_get_stainfo(pstapriv, mac_addr); - if(ptdls_sta==NULL) - { - ptdls_sta = rtw_alloc_stainfo(pstapriv, mac_addr); - if(ptdls_sta) - { - _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)) - ptdlsinfo->sta_cnt++; - _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - if( ptdlsinfo->sta_cnt == (NUM_STA - 2) ) // -2: AP + BC/MC sta - { - ptdlsinfo->sta_maximum = _TRUE; - } - } - else - { - rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - } - - if(ptdls_sta){ - ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE; - //for tdls; ptdls_sta->aid is used to fill dialogtoken - ptdls_sta->dialog = dialogtoken; - dialogtoken = (dialogtoken+1)%256; - ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval; - _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME ); - } - - pattrib->qsel=pattrib->priority; - if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_REQUEST) !=_SUCCESS ){ - rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; -} - -void issue_tdls_teardown(_adapter *padapter, u8 *mac_addr) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *ptdls_sta=NULL; - _irqL irqL; - - ptdls_sta = rtw_get_stainfo(pstapriv, mac_addr); - if(ptdls_sta==NULL){ - DBG_871X("issue tdls teardown unsuccessful\n"); - return; - }else{ - ptdls_sta->tdls_sta_state=TDLS_STATE_NONE; - } - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN); - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - pattrib->qsel=pattrib->priority; - if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_TEARDOWN) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - - if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){ - rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CS_OFF); - } - - if( ptdls_sta->timer_flag == 1 ) - { - _enter_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL); - ptdls_sta->timer_flag = 2; - _exit_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL); - } - else - rtw_tdls_cmd(padapter, mac_addr, TDLS_FREE_STA ); - - -exit: - - return; -} - -void issue_tdls_dis_req(_adapter *padapter, u8 *mac_addr) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - if(mac_addr == NULL) - _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN); - else - _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN); - - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - pattrib->qsel=pattrib->priority; - if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_DISCOVERY_REQUEST) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - DBG_871X("issue tdls dis req\n"); - -exit: - - return; -} - -void issue_tdls_setup_rsp(_adapter *padapter, union recv_frame *precv_frame) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib; - _irqL irqL; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN); - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, rx_pkt_pattrib->bssid, ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - pattrib->qsel=pattrib->priority; - if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_RESPONSE) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; - -} - -void issue_tdls_setup_cfm(_adapter *padapter, union recv_frame *precv_frame) -{ - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct sta_info *ptdls_sta=NULL; - _irqL irqL; - - struct rx_pkt_attrib *rx_pkt_pattrib = & precv_frame->u.hdr.attrib; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN); - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, rx_pkt_pattrib->bssid, ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - pattrib->qsel=pattrib->priority; - if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_CONFIRM) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; - -} - -//TDLS Discovery Response frame is a management action frame -void issue_tdls_dis_rsp(_adapter *padapter, union recv_frame *precv_frame, u8 dialog) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - - struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; - - // unicast probe request frame - _rtw_memcpy(pwlanhdr->addr1, rx_pkt_pattrib->src, ETH_ALEN); - _rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN); - - _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - _rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN); - - _rtw_memcpy(pwlanhdr->addr3, rx_pkt_pattrib->bssid, ETH_ALEN); - _rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - SetFrameSubType(pframe, WIFI_ACTION); - - pframe += sizeof (struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr); - - rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, dialog); - - pattrib->nr_frags = 1; - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - - return; -} - -void issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - - static u8 dialogtoken=0; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN); - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - //for tdls; pattrib->nr_frags is used to fill dialogtoken - ptdls_sta->dialog = dialogtoken; - dialogtoken = (dialogtoken+1)%256; - //PTI frame's priority should be AC_VO - pattrib->priority = 7; - - update_tdls_attrib(padapter, pattrib); - pattrib->qsel=pattrib->priority; - if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_PEER_TRAFFIC_INDICATION) != _SUCCESS) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; -} - -void issue_tdls_ch_switch_req(_adapter *padapter, u8 *mac_addr) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN); - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - - pattrib->qsel=pattrib->priority; - if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_CHANNEL_SWITCH_REQUEST) !=_SUCCESS ){ - rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; -} - -void issue_tdls_ch_switch_rsp(_adapter *padapter, u8 *mac_addr) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - - _irqL irqL; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - { - return; - } - - //update attribute - pattrib = &pmgntframe->attrib; - - pmgntframe->frame_tag = DATA_FRAMETAG; - pattrib->ether_type = 0x890d; - pattrib->pctrl =0; - - _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN); - _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN); - - _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN); - _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); - - update_tdls_attrib(padapter, pattrib); - - pattrib->qsel=pattrib->priority; -/* - _enter_critical_bh(&pxmitpriv->lock, &irqL); - if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){ - _exit_critical_bh(&pxmitpriv->lock, &irqL); - return _FALSE; - } -*/ - if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_CHANNEL_SWITCH_RESPONSE) !=_SUCCESS ){ - rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; - } - rtw_dump_xframe(padapter, pmgntframe); - -exit: - - return; -} - -sint On_TDLS_Dis_Rsp(_adapter *adapter, union recv_frame *precv_frame) -{ - struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(adapter->stapriv), get_bssid(&(adapter->mlmepriv))); - struct recv_priv *precvpriv = &(adapter->recvpriv); - u8 *ptr = precv_frame->u.hdr.rx_data, *psa; - struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib); - struct tdls_info *ptdlsinfo = &(adapter->tdlsinfo); - u8 empty_addr[ETH_ALEN] = { 0x00 }; - int UndecoratedSmoothedPWDB; - - - //WFDTDLS: for sigma test, not to setup direct link automatically - ptdlsinfo->dev_discovered = 1; - -#ifdef CONFIG_TDLS_AUTOSETUP - psa = get_sa(ptr); - ptdls_sta = rtw_get_stainfo(&(adapter->stapriv), psa); - - if(ptdls_sta != NULL) - { - ptdls_sta->tdls_sta_state |= TDLS_ALIVE_STATE; - - //Record the tdls sta with lowest signal strength - if( (ptdlsinfo->sta_maximum == _TRUE) && (ptdls_sta->alive_count >= 1) ) - { - if( _rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN) ) - { - _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN); - ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll; - } - else - { - if( ptdlsinfo->ss_record.RxPWDBAll < pattrib->RxPWDBAll ) - { - _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN); - ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll; - } - } - } - - } - else - { - if( ptdlsinfo->sta_maximum == _TRUE) - { - if( _rtw_memcmp( ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN ) ) - { - //All traffics are busy, do not set up another direct link. - return _FAIL; - } - else - { - if( pattrib->RxPWDBAll > ptdlsinfo->ss_record.RxPWDBAll ) - { - issue_tdls_teardown(adapter, ptdlsinfo->ss_record.macaddr); - } - else - { - return _FAIL; - } - } - } - - adapter->HalFunc.GetHalDefVarHandler(adapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); - - if( pattrib->RxPWDBAll + TDLS_SIGNAL_THRESH >= UndecoratedSmoothedPWDB); - { - DBG_871X("pattrib->RxPWDBAll=%d, pdmpriv->UndecoratedSmoothedPWDB=%d\n", pattrib->RxPWDBAll, UndecoratedSmoothedPWDB); - issue_tdls_setup_req(adapter, psa); - } - } -#endif //CONFIG_TDLS_AUTOSETUP - - return _SUCCESS; -} - -sint On_TDLS_Setup_Req(_adapter *adapter, union recv_frame *precv_frame) -{ - struct tdls_info *ptdlsinfo = &adapter->tdlsinfo; - u8 *psa, *pmyid; - struct sta_info *ptdls_sta= NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - u8 *ptr = precv_frame->u.hdr.rx_data; - struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); - struct security_priv *psecuritypriv = &adapter->securitypriv; - _irqL irqL; - struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib; - u8 *prsnie, *ppairwise_cipher; - u8 i, k, pairwise_count; - u8 ccmp_have=0, rsnie_have=0; - u16 j; - u8 SNonce[32]; - u32 *timeout_interval; - sint parsing_length; //frame body length, without icv_len - PNDIS_802_11_VARIABLE_IEs pIE; - u8 FIXED_IE = 5; - unsigned char supportRate[16]; - int supportRateNum = 0; - - psa = get_sa(ptr); - ptdls_sta = rtw_get_stainfo(pstapriv, psa); - - pmyid=myid(&(adapter->eeprompriv)); - ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1; - parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len - -prx_pkt_attrib->hdrlen - -prx_pkt_attrib->iv_len - -prx_pkt_attrib->icv_len - -LLC_HEADER_SIZE - -ETH_TYPE_LEN - -PAYLOAD_TYPE_LEN - -FIXED_IE; - - if(ptdlsinfo->ap_prohibited == _TRUE) - { - goto exit; - } - - if(ptdls_sta==NULL){ - ptdls_sta = rtw_alloc_stainfo(pstapriv, psa); - }else{ - if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){ - //If the direct link is already set up - //Process as re-setup after tear down - DBG_871X("re-setup a direct link\n"); - } - //already receiving TDLS setup request - else if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){ - DBG_871X("receive duplicated TDLS setup request frame in handshaking\n"); - goto exit; - } - //When receiving and sending setup_req to the same link at the same time, STA with higher MAC_addr would be initiator - //following is to check out MAC_addr - else if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){ - DBG_871X("receive setup_req after sending setup_req\n"); - for (i=0;i<6;i++){ - if(*(pmyid+i)==*(psa+i)){ - } - else if(*(pmyid+i)>*(psa+i)){ - goto exit; - }else if(*(pmyid+i)<*(psa+i)){ - ptdls_sta->tdls_sta_state=TDLS_INITIATOR_STATE; - break; - } - } - } - } - - if(ptdls_sta) - { - ptdls_sta->dialog = *(ptr+2); //copy dialog token - ptdls_sta->stat_code = 0; - - //parsing information element - for(j=FIXED_IE; j<parsing_length;){ - - pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j); - - switch (pIE->ElementID) - { - case _SUPPORTEDRATES_IE_: - _rtw_memcpy(supportRate, pIE->data, pIE->Length); - supportRateNum = pIE->Length; - break; - case _COUNTRY_IE_: - break; - case _EXT_SUPPORTEDRATES_IE_: - if(supportRateNum<=sizeof(supportRate)) - { - _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length); - supportRateNum += pIE->Length; - } - break; - case _SUPPORTED_CH_IE_: - break; - case _RSN_IE_2_: - rsnie_have=1; - if(prx_pkt_attrib->encrypt){ - prsnie=(u8*)pIE; - //check whether initiator STA has CCMP pairwise_cipher. - ppairwise_cipher=prsnie+10; - _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 1); - for(k=0;k<pairwise_count;k++){ - if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE) - ccmp_have=1; - } - if(ccmp_have==0){ - //invalid contents of RSNIE - ptdls_sta->stat_code=72; - } - } - break; - case _EXT_CAP_IE_: - break; - case _VENDOR_SPECIFIC_IE_: - break; - case _FTIE_: - if(prx_pkt_attrib->encrypt) - _rtw_memcpy(SNonce, (ptr+j+52), 32); - break; - case _TIMEOUT_ITVL_IE_: - if(prx_pkt_attrib->encrypt) - timeout_interval = (u32 *)(ptr+j+3); - break; - case _RIC_Descriptor_IE_: - break; - case _HT_CAPABILITY_IE_: - rtw_tdls_process_ht_cap(adapter, ptdls_sta, pIE->data, pIE->Length); - break; - case EID_BSSCoexistence: - break; - case _LINK_ID_IE_: - if(_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE) - { - //not in the same BSS - ptdls_sta->stat_code=7; - } - break; - default: - break; - } - - j += (pIE->Length + 2); - - } - - //update station supportRate - ptdls_sta->bssratelen = supportRateNum; - _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum); - - //check status code - //if responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject - if(ptdls_sta->stat_code == 0 ) - { - if(rsnie_have && (prx_pkt_attrib->encrypt==0)){ - //security disabled - ptdls_sta->stat_code = 5; - }else if(rsnie_have==0 && (prx_pkt_attrib->encrypt)){ - //request haven't RSNIE - ptdls_sta->stat_code = 38; - } - -#ifdef CONFIG_WFD - //WFD test plan version 0.18.2 test item 5.1.5 - //SoUT does not use TDLS if AP uses weak security - if ( adapter->wdinfo.wfd_tdls_enable ) - { - if(rsnie_have && (prx_pkt_attrib->encrypt != _AES_)) - { - ptdls_sta->stat_code = 5; - } - } -#endif //CONFIG_WFD - } - - ptdls_sta->tdls_sta_state|= TDLS_INITIATOR_STATE; - if(prx_pkt_attrib->encrypt){ - _rtw_memcpy(ptdls_sta->SNonce, SNonce, 32); - _rtw_memcpy(&(ptdls_sta->TDLS_PeerKey_Lifetime), timeout_interval, 4); - } - _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)) - ptdlsinfo->sta_cnt++; - _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); - if( ptdlsinfo->sta_cnt == (NUM_STA - 2) ) // -2: AP + BC/MC sta - { - ptdlsinfo->sta_maximum = _TRUE; - } - -#ifdef CONFIG_WFD - rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE); -#endif // CONFIG_WFD - - } - else - { - goto exit; - } - - issue_tdls_setup_rsp(adapter, precv_frame); - - if(ptdls_sta->stat_code==0) - { - _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME); - } - else //status code!=0 ; setup unsuccess - { - free_tdls_sta(adapter, ptdls_sta); - } - -exit: - - return _FAIL; -} - -sint On_TDLS_Setup_Rsp(_adapter *adapter, union recv_frame *precv_frame) -{ - struct tdls_info *ptdlsinfo = &adapter->tdlsinfo; - struct sta_info *ptdls_sta= NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - u8 *ptr = precv_frame->u.hdr.rx_data; - _irqL irqL; - struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib; - u8 *psa; - u16 stat_code; - sint parsing_length; //frame body length, without icv_len - PNDIS_802_11_VARIABLE_IEs pIE; - u8 FIXED_IE =7; - u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic, *ppairwise_cipher; - u16 pairwise_count, j, k; - u8 verify_ccmp=0; - unsigned char supportRate[16]; - int supportRateNum = 0; - - psa = get_sa(ptr); - ptdls_sta = rtw_get_stainfo(pstapriv, psa); - - if ( NULL == ptdls_sta ) - { - return _FAIL; - } - - ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1; - parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len - -prx_pkt_attrib->hdrlen - -prx_pkt_attrib->iv_len - -prx_pkt_attrib->icv_len - -LLC_HEADER_SIZE - -TYPE_LENGTH_FIELD_SIZE - -1 - -FIXED_IE; - - _rtw_memcpy(&stat_code, ptr+2, 2); - - if(stat_code!=0) - { - DBG_871X( "[%s] status_code = %d, free_tdls_sta\n", __FUNCTION__, stat_code ); - free_tdls_sta(adapter, ptdls_sta); - return _FAIL; - } - - stat_code = 0; - - //parsing information element - for(j=FIXED_IE; j<parsing_length;) - { - pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j); - - switch (pIE->ElementID) - { - case _SUPPORTEDRATES_IE_: - _rtw_memcpy(supportRate, pIE->data, pIE->Length); - supportRateNum = pIE->Length; - break; - case _COUNTRY_IE_: - break; - case _EXT_SUPPORTEDRATES_IE_: - if(supportRateNum<=sizeof(supportRate)) - { - _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length); - supportRateNum += pIE->Length; - } - break; - case _SUPPORTED_CH_IE_: - break; - case _RSN_IE_2_: - prsnie=(u8*)pIE; - //check whether responder STA has CCMP pairwise_cipher. - ppairwise_cipher=prsnie+10; - _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 2); - for(k=0;k<pairwise_count;k++){ - if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE) - verify_ccmp=1; - } - case _EXT_CAP_IE_: - break; - case _VENDOR_SPECIFIC_IE_: - break; - case _FTIE_: - pftie=(u8*)pIE; - _rtw_memcpy(ptdls_sta->ANonce, (ptr+j+20), 32); - break; - case _TIMEOUT_ITVL_IE_: - ptimeout_ie=(u8*)pIE; - break; - case _RIC_Descriptor_IE_: - break; - case _HT_CAPABILITY_IE_: - rtw_tdls_process_ht_cap(adapter, ptdls_sta, pIE->data, pIE->Length); - break; - case EID_BSSCoexistence: - break; - case _LINK_ID_IE_: - plinkid_ie=(u8*)pIE; - break; - default: - break; - } - - j += (pIE->Length + 2); - - } - - //update station supportRate - ptdls_sta->bssratelen = supportRateNum; - _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum); - -#ifdef CONFIG_WFD - rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE); -#endif // CONFIG_WFD - - if(stat_code != 0) - { - ptdls_sta->stat_code = stat_code; - } - else - { - if(prx_pkt_attrib->encrypt) - { - if(verify_ccmp==1) - { - wpa_tdls_generate_tpk(adapter, ptdls_sta); - ptdls_sta->stat_code=0; - if(tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie)==0) //0: Invalid, 1: valid - { - free_tdls_sta(adapter, ptdls_sta); - return _FAIL; - } - } - else - { - ptdls_sta->stat_code=72; //invalide contents of RSNIE - } - - }else{ - ptdls_sta->stat_code=0; - } - } - - DBG_871X("issue_tdls_setup_cfm\n"); - issue_tdls_setup_cfm(adapter, precv_frame); - - if(ptdls_sta->stat_code==0) - { - ptdlsinfo->setup_state = TDLS_LINKED_STATE; - - if( ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE ) - { - ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE; - _cancel_timer_ex( &ptdls_sta->handshake_timer); -#ifdef CONFIG_TDLS_AUTOCHECKALIVE - _set_timer( &ptdls_sta->alive_timer1, TDLS_ALIVE_TIMER_PH1); -#endif //CONFIG_TDLS_AUTOSETUP - } - - rtw_tdls_set_mac_id(ptdlsinfo, ptdls_sta); - rtw_tdls_set_key(adapter, prx_pkt_attrib, ptdls_sta); - - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_WRCR); - - } - else //status code!=0 ; setup unsuccessful - { - free_tdls_sta(adapter, ptdls_sta); - } - - return _FAIL; - -} - -sint On_TDLS_Setup_Cfm(_adapter *adapter, union recv_frame *precv_frame) -{ - struct tdls_info *ptdlsinfo = &adapter->tdlsinfo; - struct sta_info *ptdls_sta= NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - u8 *ptr = precv_frame->u.hdr.rx_data; - _irqL irqL; - struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib; - u8 *psa; - u16 stat_code; - sint parsing_length; - PNDIS_802_11_VARIABLE_IEs pIE; - u8 FIXED_IE =5; - u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic, *ppairwise_cipher; - u16 j, pairwise_count; - - psa = get_sa(ptr); - ptdls_sta = rtw_get_stainfo(pstapriv, psa); - - ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1; - parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len - -prx_pkt_attrib->hdrlen - -prx_pkt_attrib->iv_len - -prx_pkt_attrib->icv_len - -LLC_HEADER_SIZE - -ETH_TYPE_LEN - -PAYLOAD_TYPE_LEN - -FIXED_IE; - _rtw_memcpy(&stat_code, ptr+2, 2); - - if(stat_code!=0){ - DBG_871X( "[%s] stat_code = %d\n, free_tdls_sta", __FUNCTION__, stat_code ); - free_tdls_sta(adapter, ptdls_sta); - return _FAIL; - } - - if(prx_pkt_attrib->encrypt){ - //parsing information element - for(j=FIXED_IE; j<parsing_length;){ - - pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j); - - switch (pIE->ElementID) - { - case _RSN_IE_2_: - prsnie=(u8*)pIE; - break; - case _VENDOR_SPECIFIC_IE_: - break; - case _FTIE_: - pftie=(u8*)pIE; - break; - case _TIMEOUT_ITVL_IE_: - ptimeout_ie=(u8*)pIE; - break; - case _HT_EXTRA_INFO_IE_: - break; - case _LINK_ID_IE_: - plinkid_ie=(u8*)pIE; - break; - default: - break; - } - - j += (pIE->Length + 2); - - } - - //verify mic in FTIE MIC field - if(tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie)==0){ //0: Invalid, 1: Valid - free_tdls_sta(adapter, ptdls_sta); - return _FAIL; - } - - } - - ptdlsinfo->setup_state = TDLS_LINKED_STATE; - if( ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE ) - { - ptdls_sta->tdls_sta_state|=TDLS_LINKED_STATE; - _cancel_timer_ex( &ptdls_sta->handshake_timer); -#ifdef CONFIG_TDLS_AUTOCHECKALIVE - _set_timer( &ptdls_sta->alive_timer1, TDLS_ALIVE_TIMER_PH1); -#endif //CONFIG_TDLS_AUTOCHECKALIVE - } - - rtw_tdls_set_mac_id(ptdlsinfo, ptdls_sta); - rtw_tdls_set_key(adapter, prx_pkt_attrib, ptdls_sta); - - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_WRCR); - - return _FAIL; - -} - -sint On_TDLS_Dis_Req(_adapter *adapter, union recv_frame *precv_frame) -{ - struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - struct sta_info *psta_ap; - u8 *ptr = precv_frame->u.hdr.rx_data; - sint parsing_length; //frame body length, without icv_len - PNDIS_802_11_VARIABLE_IEs pIE; - u8 FIXED_IE = 3, *dst, *pdialog = NULL; - u16 j; - - ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE + 1; - pdialog=ptr+2; - - parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len - -prx_pkt_attrib->hdrlen - -prx_pkt_attrib->iv_len - -prx_pkt_attrib->icv_len - -LLC_HEADER_SIZE - -TYPE_LENGTH_FIELD_SIZE - -1 - -FIXED_IE; - - //parsing information element - for(j=FIXED_IE; j<parsing_length;){ - - pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j); - - switch (pIE->ElementID) - { - case _LINK_ID_IE_: - psta_ap = rtw_get_stainfo(pstapriv, pIE->data); - if(psta_ap == NULL) - { - goto exit; - } - dst = pIE->data + 12; - if( (MacAddr_isBcst(dst) == _FALSE) && (_rtw_memcmp(myid(&(adapter->eeprompriv)), dst, 6) == _FALSE) ) - { - goto exit; - } - break; - default: - break; - } - - j += (pIE->Length + 2); - - } - - //check frame contents - - issue_tdls_dis_rsp(adapter, precv_frame, *(pdialog) ); - -exit: - - return _FAIL; - -} - -sint On_TDLS_Teardown(_adapter *adapter, union recv_frame *precv_frame) -{ - u8 *psa; - u8 *ptr = precv_frame->u.hdr.rx_data; - struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib; - struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct sta_priv *pstapriv = &adapter->stapriv; - struct sta_info *ptdls_sta= NULL; - _irqL irqL; - - psa = get_sa(ptr); - - ptdls_sta = rtw_get_stainfo(pstapriv, psa); - if(ptdls_sta!=NULL){ - if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){ - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF); - } - free_tdls_sta(adapter, ptdls_sta); - } - - return _FAIL; - -} - -u8 TDLS_check_ch_state(uint state){ - if( (state & TDLS_CH_SWITCH_ON_STATE) && - (state & TDLS_AT_OFF_CH_STATE) && - (state & TDLS_PEER_AT_OFF_STATE) ){ - - if(state & TDLS_PEER_SLEEP_STATE) - return 2; //U-APSD + ch. switch - else - return 1; //ch. switch - }else - return 0; -} - -//we process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here -sint On_TDLS_Peer_Traffic_Rsp(_adapter *adapter, union recv_frame *precv_frame) -{ - struct tdls_info *ptdlsinfo = &adapter->tdlsinfo; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; - struct sta_priv *pstapriv = &adapter->stapriv; - //get peer sta infomation - struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src); - u8 wmmps_ac=0, state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state); - int i; - - ptdls_sta->sta_stats.rx_data_pkts++; - - //receive peer traffic response frame, sleeping STA wakes up - //ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_SLEEP_STATE); - process_wmmps_data( adapter, precv_frame); - - // if noticed peer STA wakes up by receiving peer traffic response - // and we want to do channel swtiching, then we will transmit channel switch request first - if(ptdls_sta->tdls_sta_state & TDLS_APSD_CHSW_STATE){ - issue_tdls_ch_switch_req(adapter, pattrib->src); - ptdls_sta->tdls_sta_state &= ~(TDLS_APSD_CHSW_STATE); - return _FAIL; - } - - //check 4-AC queue bit - if(ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk) - wmmps_ac=1; - - //if it's a direct link and have buffered frame - if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){ - if(wmmps_ac && state) - { - _irqL irqL; - _list *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe=NULL; - - _enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL); - - xmitframe_phead = get_list_head(&ptdls_sta->sleep_q); - xmitframe_plist = get_next(xmitframe_phead); - - //transmit buffered frames - while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) - { - pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); - xmitframe_plist = get_next(xmitframe_plist); - rtw_list_delete(&pxmitframe->list); - - ptdls_sta->sleepq_len--; - if(ptdls_sta->sleepq_len>0){ - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - }else{ - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - //pxmitframe->attrib.triggered = 1; //maybe doesn't need in TDLS - if(adapter->HalFunc.hal_xmit(adapter, pxmitframe) == _TRUE) - { - rtw_os_xmit_complete(adapter, pxmitframe); - } - - } - - if(ptdls_sta->sleepq_len==0) - { - DBG_871X("no buffered packets for tdls to xmit\n"); - //on U-APSD + CH. switch state, when there is no buffered date to xmit, - // we should go back to base channel - if(state==2){ - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF); - }else if(ptdls_sta->tdls_sta_state&TDLS_SW_OFF_STATE){ - ptdls_sta->tdls_sta_state &= ~(TDLS_SW_OFF_STATE); - ptdlsinfo->candidate_ch= pmlmeext->cur_channel; - issue_tdls_ch_switch_req(adapter, pattrib->src); - DBG_871X("issue tdls ch switch req back to base channel\n"); - } - - } - else - { - DBG_871X("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len); - ptdls_sta->sleepq_len=0; - } - - _exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL); - - } - - } - - return _FAIL; -} - -sint On_TDLS_Ch_Switch_Req(_adapter *adapter, union recv_frame *precv_frame) -{ - struct sta_info *ptdls_sta= NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - u8 *ptr = precv_frame->u.hdr.rx_data; - struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib; - u8 *psa; - sint parsing_length; - PNDIS_802_11_VARIABLE_IEs pIE; - u8 FIXED_IE =3; - u16 j; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - - psa = get_sa(ptr); - ptdls_sta = rtw_get_stainfo(pstapriv, psa); - - ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1; - parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len - -prx_pkt_attrib->hdrlen - -prx_pkt_attrib->iv_len - -prx_pkt_attrib->icv_len - -LLC_HEADER_SIZE - -ETH_TYPE_LEN - -PAYLOAD_TYPE_LEN - -FIXED_IE; - - ptdls_sta->off_ch = *(ptr+2); - - //parsing information element - for(j=FIXED_IE; j<parsing_length;){ - - pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j); - - switch (pIE->ElementID) - { - case _COUNTRY_IE_: - break; - case _CH_SWTICH_ANNOUNCE_: - break; - case _LINK_ID_IE_: - break; - case _CH_SWITCH_TIMING_: - _rtw_memcpy(&ptdls_sta->ch_switch_time, pIE->data, 2); - _rtw_memcpy(&ptdls_sta->ch_switch_timeout, pIE->data+2, 2); - default: - break; - } - - j += (pIE->Length + 2); - - } - - //todo: check status - ptdls_sta->stat_code=0; - ptdls_sta->tdls_sta_state |= TDLS_CH_SWITCH_ON_STATE; - - issue_nulldata(adapter, NULL, 1, 0, 0); - - issue_tdls_ch_switch_rsp(adapter, psa); - - DBG_871X("issue tdls channel switch response\n"); - - if((ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE) && ptdls_sta->off_ch==pmlmeext->cur_channel){ - DBG_871X("back to base channel %x\n", pmlmeext->cur_channel); - ptdls_sta->option=7; - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_BASE_CH); - }else{ - ptdls_sta->option=6; - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH); - } - return _FAIL; -} - -sint On_TDLS_Ch_Switch_Rsp(_adapter *adapter, union recv_frame *precv_frame) -{ - struct sta_info *ptdls_sta= NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - u8 *ptr = precv_frame->u.hdr.rx_data; - struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib; - u8 *psa; - sint parsing_length; - PNDIS_802_11_VARIABLE_IEs pIE; - u8 FIXED_IE =4; - u16 stat_code, j, switch_time, switch_timeout; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - - psa = get_sa(ptr); - ptdls_sta = rtw_get_stainfo(pstapriv, psa); - - //if channel switch is running and receiving Unsolicited TDLS Channel Switch Response, - //it will go back to base channel and terminate this channel switch procedure - if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE ){ - if(pmlmeext->cur_channel==ptdls_sta->off_ch){ - DBG_871X("back to base channel %x\n", pmlmeext->cur_channel); - ptdls_sta->option=7; - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH); - }else{ - DBG_871X("receive unsolicited channel switch response \n"); - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF); - } - return _FAIL; - } - - //avoiding duplicated or unconditional ch. switch. rsp - if((ptdls_sta->tdls_sta_state & TDLS_CH_SW_INITIATOR_STATE) != TDLS_CH_SW_INITIATOR_STATE) - return _FAIL; - - ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1; - parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len - -prx_pkt_attrib->hdrlen - -prx_pkt_attrib->iv_len - -prx_pkt_attrib->icv_len - -LLC_HEADER_SIZE - -ETH_TYPE_LEN - -PAYLOAD_TYPE_LEN - -FIXED_IE; - - _rtw_memcpy(&stat_code, ptr+2, 2); - - if(stat_code!=0){ - return _FAIL; - } - - //parsing information element - for(j=FIXED_IE; j<parsing_length;){ - - pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j); - - switch (pIE->ElementID) - { - case _LINK_ID_IE_: - break; - case _CH_SWITCH_TIMING_: - _rtw_memcpy(&switch_time, pIE->data, 2); - if(switch_time > ptdls_sta->ch_switch_time) - _rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2); - - _rtw_memcpy(&switch_timeout, pIE->data+2, 2); - if(switch_timeout > ptdls_sta->ch_switch_timeout) - _rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2); - - default: - break; - } - - j += (pIE->Length + 2); - - } - - ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SW_INITIATOR_STATE); - ptdls_sta->tdls_sta_state |=TDLS_CH_SWITCH_ON_STATE; - - //goto set_channel_workitem_callback() - ptdls_sta->option=6; - rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH); - - return _FAIL; -} - -#ifdef CONFIG_WFD -void wfd_ie_tdls(_adapter * padapter, u8 *pframe, u32 *pktlen ) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct wifi_display_info *pwfd_info = padapter->tdlsinfo.wfd_info; - u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 }; - u32 wfdielen = 0; - - // WFD OUI - wfdielen = 0; - wfdie[ wfdielen++ ] = 0x50; - wfdie[ wfdielen++ ] = 0x6F; - wfdie[ wfdielen++ ] = 0x9A; - wfdie[ wfdielen++ ] = 0x0A; // WFA WFD v1.0 - - // Commented by Albert 20110825 - // According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes - // 1. WFD Device Information - // 2. Associated BSSID ( Optional ) - // 3. Local IP Adress ( Optional ) - - // WFD Device Information ATTR - // Type: - wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO; - - // Length: - // Note: In the WFD specification, the size of length field is 2. - RTW_PUT_BE16(wfdie + wfdielen, 0x0006); - wfdielen += 2; - - // Value1: - // WFD device information - // available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery ) - RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL - | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD); - wfdielen += 2; - - // Value2: - // Session Management Control Port - // Default TCP port for RTSP messages is 554 - RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport ); - wfdielen += 2; - - // Value3: - // WFD Device Maximum Throughput - // 300Mbps is the maximum throughput - RTW_PUT_BE16(wfdie + wfdielen, 300); - wfdielen += 2; - - // Associated BSSID ATTR - // Type: - wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID; - - // Length: - // Note: In the WFD specification, the size of length field is 2. - RTW_PUT_BE16(wfdie + wfdielen, 0x0006); - wfdielen += 2; - - // Value: - // Associated BSSID - if ( check_fwstate( pmlmepriv, _FW_LINKED) == _TRUE ) - { - _rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN ); - } - else - { - _rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN ); - } - - // Local IP Address ATTR - wfdie[ wfdielen++ ] = WFD_ATTR_LOCAL_IP_ADDR; - - // Length: - // Note: In the WFD specification, the size of length field is 2. - RTW_PUT_BE16(wfdie + wfdielen, 0x0005); - wfdielen += 2; - - // Version: - // 0x01: Version1;IPv4 - wfdie[ wfdielen++ ] = 0x01; - - // IPv4 Address - _rtw_memcpy( wfdie + wfdielen, pwfd_info->ip_address, 4 ); - wfdielen += 4; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen); - -} -#endif //CONFIG_WFD - -void rtw_build_tdls_setup_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst); - - u8 payload_type = 0x02; - u8 category = RTW_WLAN_CATEGORY_TDLS; - u8 action = TDLS_SETUP_REQUEST; - u8 bssrate[NDIS_802_11_LENGTH_RATES_EX]; //Use NDIS_802_11_LENGTH_RATES_EX in order to call func.rtw_set_supported_rate - int bssrate_len = 0, i = 0 ; - u8 more_supportedrates = 0; - unsigned int ie_len; - u8 *p; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 link_id_addr[18] = {0}; - u8 iedata=0; - u8 sup_ch[ 30 * 2 ] = {0x00 }, sup_ch_idx = 0, idx_5g = 2; //For supported channel - u8 timeout_itvl[5]; //set timeout interval to maximum value - u32 time; - - //SNonce - if(pattrib->encrypt){ - for(i=0;i<8;i++){ - time=rtw_get_current_time(); - _rtw_memcpy(&ptdls_sta->SNonce[4*i], (u8 *)&time, 4); - } - } - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, dialog token - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen)); - - //capability - _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); - - if(pattrib->encrypt) - *pframe =*pframe | BIT(4); - pframe += 2; - pattrib->pktlen += 2; - - //supported rates - rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N); - bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN; - - if (bssrate_len > 8) - { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen)); - more_supportedrates = 1; - } - else - { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen)); - } - - //country(optional) - //extended supported rates - if(more_supportedrates==1){ - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); - } - - //supported channels - pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib); - - // SRC IE - pframe = rtw_set_ie( pframe, _SRC_IE_, 16, TDLS_SRC, &(pattrib->pktlen)); - - //RSNIE - if(pattrib->encrypt) - pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen)); - - //extended capabilities - pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen)); - - //QoS capability(WMM_IE) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 7, TDLS_WMMIE, &(pattrib->pktlen)); - - - if(pattrib->encrypt){ - //FTIE - _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0 - _rtw_memset(pframe, _FTIE_, 1); //version - _rtw_memset((pframe+1), 82, 1); //length - _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32); - pframe += 84; - pattrib->pktlen += 84; - - //Timeout interval - timeout_itvl[0]=0x02; - _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4); - pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen)); - } - - //Sup_reg_classes(optional) - //HT capabilities - pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib); - - //20/40 BSS coexistence - if(pmlmepriv->num_FortyMHzIntolerant>0) - iedata |= BIT(2);//20 MHz BSS Width Request - pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen)); - - //Link identifier - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->src, 6); - _rtw_memcpy((link_id_addr+12), pattrib->dst, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - -#ifdef CONFIG_WFD - wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) ); -#endif //CONFIG_WFD - -} - -void rtw_build_tdls_setup_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_info *ptdls_sta; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - - u8 payload_type = 0x02; - unsigned char category = RTW_WLAN_CATEGORY_TDLS; - unsigned char action = TDLS_SETUP_RESPONSE; - unsigned char bssrate[NDIS_802_11_LENGTH_RATES_EX]; - int bssrate_len = 0; - u8 more_supportedrates = 0; - unsigned int ie_len; - unsigned char *p; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 link_id_addr[18] = {0}; - u8 iedata=0; - u8 timeout_itvl[5]; //setup response timeout interval will copy from request - u8 ANonce[32]; //maybe it can put in ontdls_req - u8 k; //for random ANonce - u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic; - u32 time; - - ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst); - - if(ptdls_sta == NULL ) - { - DBG_871X("[%s] %d\n", __FUNCTION__, __LINE__); - return; - } - - if(pattrib->encrypt){ - for(k=0;k<8;k++){ - time=rtw_get_current_time(); - _rtw_memcpy(&ptdls_sta->ANonce[4*k], (u8*)&time, 4); - } - } - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, status code - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen)); - - if(ptdls_sta->stat_code!=0) //invalid setup request - { - DBG_871X("ptdls_sta->stat_code:%04x \n", ptdls_sta->stat_code); - return; - } - - //dialog token - pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen)); - - //capability - _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); - - if(pattrib->encrypt ) - *pframe =*pframe | BIT(4); - pframe += 2; - pattrib->pktlen += 2; - - //supported rates - rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N); - bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN; - - if (bssrate_len > 8) - { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen)); - more_supportedrates = 1; - } - else - { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen)); - } - - //country(optional) - //extended supported rates - if(more_supportedrates==1){ - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); - } - - //supported channels - pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib); - - // SRC IE - pframe = rtw_set_ie(pframe, _SRC_IE_ , 16, TDLS_SRC, &(pattrib->pktlen)); - - //RSNIE - if(pattrib->encrypt){ - prsnie = pframe; - pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen)); - } - - //extended capabilities - pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen)); - - //QoS capability(WMM_IE) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 7, TDLS_WMMIE, &(pattrib->pktlen)); - - if(pattrib->encrypt){ - wpa_tdls_generate_tpk(padapter, ptdls_sta); - - //FTIE - pftie = pframe; - pftie_mic = pframe+4; - _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0 - _rtw_memset(pframe, _FTIE_, 1); //version - _rtw_memset((pframe+1), 82, 1); //length - _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32); - _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32); - pframe += 84; - pattrib->pktlen += 84; - - //Timeout interval - ptimeout_ie = pframe; - timeout_itvl[0]=0x02; - _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4); - pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen)); - } - - //Sup_reg_classes(optional) - //HT capabilities - pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib); - - //20/40 BSS coexistence - if(pmlmepriv->num_FortyMHzIntolerant>0) - iedata |= BIT(2);//20 MHz BSS Width Request - pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen)); - - //Link identifier - plinkid_ie = pframe; - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->dst, 6); - _rtw_memcpy((link_id_addr+12), pattrib->src, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - - //fill FTIE mic - if(pattrib->encrypt) - wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic); - -#ifdef CONFIG_WFD - wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) ); -#endif //CONFIG_WFD - -} - -void rtw_build_tdls_setup_cfm_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst); - - u8 payload_type = 0x02; - unsigned char category = RTW_WLAN_CATEGORY_TDLS; - unsigned char action = TDLS_SETUP_CONFIRM; - u8 more_supportedrates = 0; - unsigned int ie_len; - unsigned char *p; - u8 timeout_itvl[5]; //set timeout interval to maximum value - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 link_id_addr[18] = {0}; - u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic; - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, status code, dialog token - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen)); - - if(ptdls_sta->stat_code!=0) //invalid setup request - return; - - //RSNIE - if(pattrib->encrypt){ - prsnie = pframe; - pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen)); - } - - //EDCA param set; WMM param ele. - if(pattrib->encrypt){ - //FTIE - pftie = pframe; - pftie_mic = pframe+4; - _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0 - _rtw_memset(pframe, _FTIE_, 1); //version - _rtw_memset((pframe+1), 82, 1); //length - _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32); - _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32); - pframe += 84; - pattrib->pktlen += 84; - - //Timeout interval - ptimeout_ie = pframe; - timeout_itvl[0]=0x02; - _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4); - ptdls_sta->TPK_count=0; - _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT); - pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen)); - } - - //HT operation; todo - //Link identifier - plinkid_ie = pframe; - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->src, 6); - _rtw_memcpy((link_id_addr+12), pattrib->dst, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - - //fill FTIE mic - if(pattrib->encrypt) - wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic); - -} - -void rtw_build_tdls_teardown_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct pkt_attrib *pattrib = &pxmitframe->attrib; - u8 payload_type = 0x02; - unsigned char category = RTW_WLAN_CATEGORY_TDLS; - unsigned char action = TDLS_TEARDOWN; - u8 link_id_addr[18] = {0}; - - struct sta_info *ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst); - struct sta_priv *pstapriv = &padapter->stapriv; - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, reason code - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen)); - - //Link identifier - if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){ - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->src, 6); - _rtw_memcpy((link_id_addr+12), pattrib->dst, 6); - }else if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){ - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->dst, 6); - _rtw_memcpy((link_id_addr+12), pattrib->src, 6); - } - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - -} - -void rtw_build_tdls_dis_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct pkt_attrib *pattrib = &pxmitframe->attrib; - u8 payload_type = 0x02; - u8 category = RTW_WLAN_CATEGORY_TDLS; - u8 action = TDLS_DISCOVERY_REQUEST; - u8 link_id_addr[18] = {0}; - static u8 dialogtoken=0; - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, reason code - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen)); - dialogtoken = (dialogtoken+1)%256; - - //Link identifier - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->src, 6); - _rtw_memcpy((link_id_addr+12), pattrib->dst, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - -} - -void rtw_build_tdls_dis_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, u8 dialog) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - - u8 category = RTW_WLAN_CATEGORY_PUBLIC; - u8 action = TDLS_DISCOVERY_RESPONSE; - u8 bssrate[NDIS_802_11_LENGTH_RATES_EX]; - int bssrate_len = 0; - u8 more_supportedrates = 0; - u8 *p; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 link_id_addr[18] = {0}; - u8 iedata=0; - u8 timeout_itvl[5]; //set timeout interval to maximum value - u32 timeout_interval= TPK_RESEND_COUNT * 1000; - - //category, action, dialog token - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(dialog), &(pattrib->pktlen)); - - //capability - _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); - - if(pattrib->encrypt) - *pframe =*pframe | BIT(4); - pframe += 2; - pattrib->pktlen += 2; - - //supported rates - rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N); - bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN; - - if (bssrate_len > 8) - { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen)); - more_supportedrates = 1; - } - else - { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen)); - } - - //extended supported rates - if(more_supportedrates==1){ - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); - } - - //supported channels - pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib); - - //RSNIE - if(pattrib->encrypt) - pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen)); - - //extended capability - pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen)); - - if(pattrib->encrypt){ - //FTIE - _rtw_memset(pframe, 0, 84); //All fields shall be set to 0 - _rtw_memset(pframe, _FTIE_, 1); //version - _rtw_memset((pframe+1), 82, 1); //length - pframe += 84; - pattrib->pktlen += 84; - - //Timeout interval - timeout_itvl[0]=0x02; - _rtw_memcpy(timeout_itvl+1, &timeout_interval, 4); - pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen)); - } - - //Sup_reg_classes(optional) - //HT capabilities - pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib); - - //20/40 BSS coexistence - if(pmlmepriv->num_FortyMHzIntolerant>0) - iedata |= BIT(2);//20 MHz BSS Width Request - pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen)); - - //Link identifier - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->dst, 6); - _rtw_memcpy((link_id_addr+12), pattrib->src, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - -} - -void rtw_build_tdls_peer_traffic_indication_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct pkt_attrib *pattrib = &pxmitframe->attrib; - u8 payload_type = 0x02; - unsigned char category = RTW_WLAN_CATEGORY_TDLS; - unsigned char action = TDLS_PEER_TRAFFIC_INDICATION; - - u8 link_id_addr[18] = {0}; - u8 AC_queue=0; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst); - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, reason code - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen)); - - //Link identifier - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->src, 6); - _rtw_memcpy((link_id_addr+12), pattrib->dst, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - - //PTI control - //PU buffer status - if(ptdls_sta->uapsd_bk&BIT(1)) - AC_queue=BIT(0); - if(ptdls_sta->uapsd_be&BIT(1)) - AC_queue=BIT(1); - if(ptdls_sta->uapsd_vi&BIT(1)) - AC_queue=BIT(2); - if(ptdls_sta->uapsd_vo&BIT(1)) - AC_queue=BIT(3); - pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen)); - -} - -void rtw_build_tdls_ch_switch_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - u8 payload_type = 0x02; - unsigned char category = RTW_WLAN_CATEGORY_TDLS; - unsigned char action = TDLS_CHANNEL_SWITCH_REQUEST; - u8 link_id_addr[18] = {0}; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst); - u8 ch_switch_timing[4] = {0}; - u16 switch_time= CH_SWITCH_TIME, switch_timeout=CH_SWITCH_TIMEOUT; - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, target_ch - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(ptdlsinfo->candidate_ch), &(pattrib->pktlen)); - - //Link identifier - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->src, 6); - _rtw_memcpy((link_id_addr+12), pattrib->dst, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - - //ch switch timing - _rtw_memcpy(ch_switch_timing, &switch_time, 2); - _rtw_memcpy(ch_switch_timing+2, &switch_timeout, 2); - pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen)); - - //update ch switch attrib to sta_info - ptdls_sta->off_ch=ptdlsinfo->candidate_ch; - ptdls_sta->ch_switch_time=switch_time; - ptdls_sta->ch_switch_timeout=switch_timeout; - -} - -void rtw_build_tdls_ch_switch_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct pkt_attrib *pattrib = &pxmitframe->attrib; - u8 payload_type = 0x02; - unsigned char category = RTW_WLAN_CATEGORY_TDLS; - unsigned char action = TDLS_CHANNEL_SWITCH_RESPONSE; - u8 link_id_addr[18] = {0}; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - u8 ch_switch_timing[4] = {0}; - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, action, status_code - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen)); - - //Link identifier - _rtw_memcpy(link_id_addr, pattrib->ra, 6); - _rtw_memcpy((link_id_addr+6), pattrib->src, 6); - _rtw_memcpy((link_id_addr+12), pattrib->dst, 6); - pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen)); - - //ch switch timing - _rtw_memcpy(ch_switch_timing, &ptdls_sta->ch_switch_time, 2); - _rtw_memcpy(ch_switch_timing+2, &ptdls_sta->ch_switch_timeout, 2); - pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen)); - -} - -#ifdef CONFIG_WFD -void rtw_build_tunneled_probe_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo; - u8 payload_type = 0x02; - u8 category = RTW_WLAN_CATEGORY_P2P; - u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a}; - u8 probe_req = 4; - u8 wfdielen = 0; - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, OUI, frame_body_type - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen)); - - if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - { - wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; - } - else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) - { - wfdielen = build_probe_req_wfd_ie(pbuddy_wdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; - } - -} - -void rtw_build_tunneled_probe_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe) -{ - - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct wifidirect_info *pwdinfo = &padapter->wdinfo; - struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo; - u8 payload_type = 0x02; - u8 category = RTW_WLAN_CATEGORY_P2P; - u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a}; - u8 probe_rsp = 5; - u8 wfdielen = 0; - - //payload type - pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen)); - //category, OUI, frame_body_type - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen)); - - if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - { - wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1); - pframe += wfdielen; - pattrib->pktlen += wfdielen; - } - else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) - { - wfdielen = build_probe_resp_wfd_ie(pbuddy_wdinfo, pframe, 1); - pframe += wfdielen; - pattrib->pktlen += wfdielen; - } - -} -#endif //CONFIG_WFD - -void _TPK_timer_hdl(void *FunctionContext) -{ - struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext; - - ptdls_sta->TPK_count++; - //TPK_timer set 1000 as default - //retry timer should set at least 301 sec. - if(ptdls_sta->TPK_count==TPK_RESEND_COUNT){ - ptdls_sta->TPK_count=0; - issue_tdls_setup_req(ptdls_sta->padapter, ptdls_sta->hwaddr); - } - - _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT); -} - -void init_TPK_timer(_adapter *padapter, struct sta_info *psta) -{ - psta->padapter=padapter; - - _init_timer(&psta->TPK_timer, padapter->pnetdev, _TPK_timer_hdl, psta); -} - -// TDLS_DONE_CH_SEN: channel sensing and report candidate channel -// TDLS_OFF_CH: first time set channel to off channel -// TDLS_BASE_CH: when go back to the channel linked with AP, send null data to peer STA as an indication -void _ch_switch_timer_hdl(void *FunctionContext) -{ - - struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext; - _adapter *padapter = ptdls_sta->padapter; - - if( ptdls_sta->option == TDLS_DONE_CH_SEN ){ - rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_DONE_CH_SEN); - }else if( ptdls_sta->option == TDLS_OFF_CH ){ - issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta, 0); - _set_timer(&ptdls_sta->base_ch_timer, 500); - }else if( ptdls_sta->option == TDLS_BASE_CH){ - issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta, 0); - } -} - -void init_ch_switch_timer(_adapter *padapter, struct sta_info *psta) -{ - psta->padapter=padapter; - _init_timer(&psta->option_timer, padapter->pnetdev, _ch_switch_timer_hdl, psta); -} - -void _base_ch_timer_hdl(void *FunctionContext) -{ - struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext; - rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_OFF_CH); -} - -void init_base_ch_timer(_adapter *padapter, struct sta_info *psta) -{ - psta->padapter=padapter; - _init_timer(&psta->base_ch_timer, padapter->pnetdev, _base_ch_timer_hdl, psta); -} - -void _off_ch_timer_hdl(void *FunctionContext) -{ - struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext; - rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_BASE_CH ); -} - -void init_off_ch_timer(_adapter *padapter, struct sta_info *psta) -{ - psta->padapter=padapter; - _init_timer(&psta->off_ch_timer, padapter->pnetdev, _off_ch_timer_hdl, psta); -} - -void _tdls_handshake_timer_hdl(void *FunctionContext) -{ - struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext; - - if(ptdls_sta != NULL) - { - if( !(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) ) - { - DBG_871X("tdls handshake time out\n"); - free_tdls_sta(ptdls_sta->padapter, ptdls_sta); - } - } -} - -void init_handshake_timer(_adapter *padapter, struct sta_info *psta) -{ - psta->padapter=padapter; - _init_timer(&psta->handshake_timer, padapter->pnetdev, _tdls_handshake_timer_hdl, psta); -} - -//Check tdls peer sta alive. -void _tdls_alive_timer_phase1_hdl(void *FunctionContext) -{ - _irqL irqL; - struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext; - _adapter *padapter = ptdls_sta->padapter; - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - - _enter_critical_bh(&ptdlsinfo->hdl_lock, &irqL); - ptdls_sta->timer_flag = 1; - _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL); - - ptdls_sta->tdls_sta_state &= (~TDLS_ALIVE_STATE); - - DBG_871X("issue_tdls_dis_req to check alive\n"); - issue_tdls_dis_req( padapter, ptdls_sta->hwaddr); - rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH1); - sta_update_last_rx_pkts(ptdls_sta); - - if ( ptdls_sta->timer_flag == 2 ) - rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_FREE_STA); - else - { - _enter_critical_bh(&ptdlsinfo->hdl_lock, &irqL); - ptdls_sta->timer_flag = 0; - _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL); - } - -} - -void _tdls_alive_timer_phase2_hdl(void *FunctionContext) -{ - _irqL irqL; - struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext; - _adapter *padapter = ptdls_sta->padapter; - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; - - _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); - ptdls_sta->timer_flag = 1; - _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL); - - if( (ptdls_sta->tdls_sta_state & TDLS_ALIVE_STATE) && - (sta_last_rx_pkts(ptdls_sta) + 3 <= sta_rx_pkts(ptdls_sta)) ) - { - DBG_871X("TDLS STA ALIVE, ptdls_sta->sta_stats.last_rx_pkts:%llu, ptdls_sta->sta_stats.rx_pkts:%llu\n", - sta_last_rx_pkts(ptdls_sta), sta_rx_pkts(ptdls_sta)); - - ptdls_sta->alive_count = 0; - rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH2); - } - else - { - if( !(ptdls_sta->tdls_sta_state & TDLS_ALIVE_STATE) ) - DBG_871X("TDLS STA TOO FAR\n"); - if( !(sta_last_rx_pkts(ptdls_sta) + 3 <= sta_rx_pkts(ptdls_sta))) - DBG_871X("TDLS LINK WITH LOW TRAFFIC, ptdls_sta->sta_stats.last_rx_pkts:%llu, ptdls_sta->sta_stats.rx_pkts:%llu\n", - sta_last_rx_pkts(ptdls_sta), sta_rx_pkts(ptdls_sta)); - - ptdls_sta->alive_count++; - if( ptdls_sta->alive_count == TDLS_ALIVE_COUNT ) - { - ptdls_sta->stat_code = _RSON_TDLS_TEAR_TOOFAR_; - issue_tdls_teardown(padapter, ptdls_sta->hwaddr); - } - else - { - rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH2); - } - } - - if ( ptdls_sta->timer_flag == 2 ) - rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_FREE_STA); - else - { - _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); - ptdls_sta->timer_flag = 0; - _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL); -} - -} - -void init_tdls_alive_timer(_adapter *padapter, struct sta_info *psta) -{ - psta->padapter=padapter; - _init_timer(&psta->alive_timer1, padapter->pnetdev, _tdls_alive_timer_phase1_hdl, psta); - _init_timer(&psta->alive_timer2, padapter->pnetdev, _tdls_alive_timer_phase2_hdl, psta); -} - -int update_sgi_tdls(_adapter *padapter, struct sta_info *psta) -{ - struct ht_priv *psta_ht = NULL; - psta_ht = &psta->htpriv; - - if(psta_ht->ht_option) - { - return psta_ht->sgi; - } - else - return _FALSE; -} - -u32 update_mask_tdls(_adapter *padapter, struct sta_info *psta) -{ - int i; - u8 rf_type, id; - unsigned char sta_band = 0; - unsigned char limit; - unsigned int tx_ra_bitmap=0; - struct ht_priv *psta_ht = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; - - psta_ht = &psta->htpriv; - //b/g mode ra_bitmap - for (i=0; i<sizeof(psta->bssrateset); i++) - { - if (psta->bssrateset[i]) - tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f); - } - - //n mode ra_bitmap - if(psta_ht->ht_option) - { - padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - if(rf_type == RF_2T2R) - limit=16;// 2R - else - limit=8;// 1R - - for (i=0; i<limit; i++) { - if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8)) - tx_ra_bitmap |= BIT(i+12); - } - } - - if ( pcur_network->Configuration.DSConfig > 14 ) { - // 5G band - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N | WIRELESS_11A; - else - sta_band |= WIRELESS_11A; - } else { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B; - else if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11G |WIRELESS_11B; - else - sta_band |= WIRELESS_11B; - } - - id = networktype_to_raid(sta_band); - tx_ra_bitmap |= ((id<<28)&0xf0000000); - return tx_ra_bitmap; -} - -#endif //CONFIG_TDLS - +/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_TDLS_C_
+
+#include <drv_types.h>
+#include <ethernet.h>
+#include <rtw_tdls.h>
+#include <wifi.h>
+
+#ifdef CONFIG_TDLS
+extern unsigned char MCS_rate_2R[16];
+extern unsigned char MCS_rate_1R[16];
+extern void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame);
+extern s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe);
+
+void rtw_reset_tdls_info(_adapter* padapter)
+{
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+ ptdlsinfo->ap_prohibited = _FALSE;
+ ptdlsinfo->setup_state = TDLS_STATE_NONE;
+ ptdlsinfo->sta_cnt = 0;
+ ptdlsinfo->sta_maximum = _FALSE;
+ ptdlsinfo->macid_index= 6;
+ ptdlsinfo->clear_cam= 0;
+ ptdlsinfo->ch_sensing = 0;
+ ptdlsinfo->cur_channel = 0;
+ ptdlsinfo->candidate_ch = 1; //when inplement channel switching, default candidate channel is 1
+ ptdlsinfo->watchdog_count = 0;
+ ptdlsinfo->dev_discovered = 0;
+
+#ifdef CONFIG_WFD
+ ptdlsinfo->wfd_info = &padapter->wfd_info;
+#endif //CONFIG_WFD
+}
+
+int rtw_init_tdls_info(_adapter* padapter)
+{
+ int res = _SUCCESS;
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+ ptdlsinfo->enable = 1;
+ rtw_reset_tdls_info(padapter);
+
+ _rtw_spinlock_init(&ptdlsinfo->cmd_lock);
+ _rtw_spinlock_init(&ptdlsinfo->hdl_lock);
+
+ return res;
+
+}
+
+void rtw_free_tdls_info(struct tdls_info *ptdlsinfo)
+{
+ _rtw_spinlock_free(&ptdlsinfo->cmd_lock);
+ _rtw_spinlock_free(&ptdlsinfo->hdl_lock);
+
+ _rtw_memset(ptdlsinfo, 0, sizeof(struct tdls_info) );
+
+}
+
+void issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, struct sta_info *ptdls_sta, unsigned int power_mode)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ unsigned short *fctrl;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &(pwlanhdr->frame_ctl);
+ *(fctrl) = 0;
+// SetToDs(fctrl);
+ if (power_mode)
+ {
+ SetPwrMgt(fctrl);
+ }
+
+ _rtw_memcpy(pwlanhdr->addr1, ptdls_sta->hwaddr, ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+ ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
+ ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
+ pattrib->seqnum = ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority];
+ SetSeqNum(pwlanhdr, pattrib->seqnum);
+
+ SetFrameSubType(pframe, WIFI_DATA_NULL);
+
+ pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+ pattrib->last_txcmdsz = pattrib->pktlen;
+ dump_mgntframe(padapter, pmgntframe);
+
+ return;
+}
+
+s32 update_tdls_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
+{
+
+ struct sta_info *psta = NULL;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct qos_priv *pqospriv= &pmlmepriv->qospriv;
+
+ s32 res=_SUCCESS;
+ sint bmcast;
+
+ bmcast = IS_MCAST(pattrib->ra);
+
+ psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+ if (psta == NULL) {
+ res =_FAIL;
+ goto exit;
+ }
+
+ pattrib->mac_id = psta->mac_id;
+
+ pattrib->psta = psta;
+
+ pattrib->ack_policy = 0;
+ // get ether_hdr_len
+ pattrib->pkt_hdrlen = ETH_HLEN;//(pattrib->ether_type == 0x8100) ? (14 + 4 ): 14; //vlan tag
+
+ if (pqospriv->qos_option && psta->qos_option) {
+ pattrib->priority = 1; //tdls management frame should be AC_BK
+ pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
+ pattrib->subtype = WIFI_QOS_DATA_TYPE;
+ } else {
+ pattrib->hdrlen = WLAN_HDR_A3_LEN;
+ pattrib->subtype = WIFI_DATA_TYPE;
+ pattrib->priority = 0;
+ }
+
+ if (psta->ieee8021x_blocked == _TRUE)
+ {
+ pattrib->encrypt = 0;
+ }
+ else
+ {
+ GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
+
+ switch(psecuritypriv->dot11AuthAlgrthm)
+ {
+ case dot11AuthAlgrthm_Open:
+ case dot11AuthAlgrthm_Shared:
+ case dot11AuthAlgrthm_Auto:
+ pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex;
+ break;
+ case dot11AuthAlgrthm_8021X:
+ pattrib->key_idx = 0;
+ break;
+ default:
+ pattrib->key_idx = 0;
+ break;
+ }
+ }
+
+ switch (pattrib->encrypt)
+ {
+ case _WEP40_:
+ case _WEP104_:
+ pattrib->iv_len = 4;
+ pattrib->icv_len = 4;
+ break;
+ case _TKIP_:
+ pattrib->iv_len = 8;
+ pattrib->icv_len = 4;
+ if(padapter->securitypriv.busetkipkey==_FAIL)
+ {
+ res =_FAIL;
+ goto exit;
+ }
+ break;
+ case _AES_:
+ pattrib->iv_len = 8;
+ pattrib->icv_len = 8;
+ break;
+ default:
+ pattrib->iv_len = 0;
+ pattrib->icv_len = 0;
+ break;
+ }
+
+ if (pattrib->encrypt &&
+ ((padapter->securitypriv.sw_encrypt == _TRUE) || (psecuritypriv->hw_decrypted == _FALSE)))
+ {
+ pattrib->bswenc = _TRUE;
+ } else {
+ pattrib->bswenc = _FALSE;
+ }
+
+ //qos_en, ht_en, init rate, ,bw, ch_offset, sgi
+ pattrib->qos_en = psta->qos_option;
+ pattrib->ht_en = psta->htpriv.ht_option;
+ pattrib->raid = psta->raid;
+ pattrib->bwmode = psta->htpriv.bwmode;
+ pattrib->ch_offset = psta->htpriv.ch_offset;
+ pattrib->sgi= psta->htpriv.sgi;
+ pattrib->ampdu_en = _FALSE;
+
+ //if(pattrib->ht_en && psta->htpriv.ampdu_enable)
+ //{
+ // if(psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
+ // pattrib->ampdu_en = _TRUE;
+ //}
+
+exit:
+
+ return res;
+}
+
+void free_tdls_sta(_adapter *padapter, struct sta_info *ptdls_sta)
+{
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ _irqL irqL;
+
+ //free peer sta_info
+ _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ if(ptdlsinfo->sta_cnt != 0)
+ ptdlsinfo->sta_cnt--;
+ _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ if( ptdlsinfo->sta_cnt < (NUM_STA - 2) ) // -2: AP + BC/MC sta
+ {
+ ptdlsinfo->sta_maximum = _FALSE;
+ _rtw_memset( &ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record) );
+ }
+ //ready to clear cam
+ if(ptdls_sta->mac_id!=0){
+ ptdlsinfo->clear_cam=ptdls_sta->mac_id;
+ rtw_setstakey_cmd(padapter, (u8 *)ptdls_sta, _TRUE, _TRUE);
+ }
+
+ if(ptdlsinfo->sta_cnt==0){
+ rtw_tdls_cmd(padapter, myid(&(padapter->eeprompriv)), TDLS_RS_RCR);
+ ptdlsinfo->setup_state=TDLS_STATE_NONE;
+ }
+ else
+ DBG_871X("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt);
+
+ rtw_free_stainfo(padapter, ptdls_sta);
+
+}
+
+// cam entry will be the same as mac_id
+void rtw_tdls_set_mac_id(struct tdls_info *ptdlsinfo, struct sta_info *ptdls_sta)
+{
+ if(ptdls_sta->mac_id==0)
+ {
+ ptdls_sta->mac_id = ptdlsinfo->macid_index;
+ if( (++ptdlsinfo->macid_index) > (NUM_STA -2) )
+ ptdlsinfo->macid_index= TDLS_INI_MACID_ENTRY;
+ }
+}
+
+//TDLS encryption(if needed) will always be CCMP
+void rtw_tdls_set_key(_adapter *adapter, struct rx_pkt_attrib *prx_pkt_attrib, struct sta_info *ptdls_sta)
+{
+ if(prx_pkt_attrib->encrypt)
+ {
+ ptdls_sta->dot118021XPrivacy=_AES_;
+ rtw_setstakey_cmd(adapter, (u8*)ptdls_sta, _TRUE, _TRUE);
+ }
+}
+
+void rtw_tdls_process_ht_cap(_adapter *adapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)
+{
+ /* save HT capabilities in the sta object */
+ _rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
+ if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap) )
+ {
+ ptdls_sta->flags |= WLAN_STA_HT;
+
+ ptdls_sta->flags |= WLAN_STA_WME;
+
+ _rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap));
+
+ } else
+ ptdls_sta->flags &= ~WLAN_STA_HT;
+
+ if(ptdls_sta->flags & WLAN_STA_HT)
+ {
+ if(adapter->registrypriv.ht_enable == _TRUE)
+ {
+ ptdls_sta->htpriv.ht_option = _TRUE;
+ }
+ else
+ {
+ ptdls_sta->htpriv.ht_option = _FALSE;
+ ptdls_sta->stat_code = _STATS_FAILURE_;
+ }
+ }
+
+ //HT related cap
+ if(ptdls_sta->htpriv.ht_option)
+ {
+ //check if sta supports rx ampdu
+ if(adapter->registrypriv.ampdu_enable==1)
+ ptdls_sta->htpriv.ampdu_enable = _TRUE;
+
+ //check if sta support s Short GI
+ if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40))
+ {
+ ptdls_sta->htpriv.sgi = _TRUE;
+ }
+
+ // bwmode would still followed AP's setting
+ if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
+ {
+ ptdls_sta->htpriv.bwmode = adapter->mlmeextpriv.cur_bwmode;
+ ptdls_sta->htpriv.ch_offset = adapter->mlmeextpriv.cur_ch_offset;
+ }
+ }
+}
+
+u8 *rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+ struct rtw_ieee80211_ht_cap ht_capie;
+ u8 rf_type;
+
+ //HT capabilities
+ _rtw_memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
+
+ ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |IEEE80211_HT_CAP_SGI_20 |IEEE80211_HT_CAP_SM_PS |
+ IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_TX_STBC |IEEE80211_HT_CAP_DSSSCCK40;
+
+ {
+ u32 rx_packet_offset, max_recvbuf_sz;
+ padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
+ padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
+ if(max_recvbuf_sz-rx_packet_offset>(8191-256))
+ ht_capie.cap_info = ht_capie.cap_info |IEEE80211_HT_CAP_MAX_AMSDU;
+ }
+
+ ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR&0x03);
+
+ padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ switch(rf_type)
+ {
+ case RF_1T1R:
+ ht_capie.cap_info |= 0x0100;//RX STBC One spatial stream
+ _rtw_memcpy(ht_capie.supp_mcs_set, MCS_rate_1R, 16);
+ break;
+
+ case RF_2T2R:
+ case RF_1T2R:
+ default:
+ ht_capie.cap_info|= 0x0200;//RX STBC two spatial stream
+ _rtw_memcpy(ht_capie.supp_mcs_set, MCS_rate_2R, 16);
+ break;
+ }
+
+ return(rtw_set_ie(pframe, _HT_CAPABILITY_IE_,
+ sizeof(struct rtw_ieee80211_ht_cap), (unsigned char*)&ht_capie, &(pattrib->pktlen)));
+}
+
+u8 *rtw_tdls_set_sup_ch(struct mlme_ext_priv *pmlmeext, u8 *pframe, struct pkt_attrib *pattrib)
+{
+ u8 sup_ch[ 30 * 2 ] = { 0x00 }, sup_ch_idx = 0, idx_5g = 2; //For supported channel
+ do{
+ if( pmlmeext->channel_set[sup_ch_idx].ChannelNum <= 14 )
+ {
+ sup_ch[0] = 1; //First channel number
+ sup_ch[1] = pmlmeext->channel_set[sup_ch_idx].ChannelNum; //Number of channel
+ }
+ else
+ {
+ sup_ch[idx_5g++] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;
+ sup_ch[idx_5g++] = 1;
+ }
+
+ sup_ch_idx++;
+ }
+ while( pmlmeext->channel_set[sup_ch_idx].ChannelNum != 0 );
+ return(rtw_set_ie(pframe, _SUPPORTED_CH_IE_, idx_5g, sup_ch, &(pattrib->pktlen)));
+}
+
+#ifdef CONFIG_WFD
+void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length)
+{
+ u8 wfd_ie[ 128 ] = { 0x00 };
+ u32 wfd_ielen = 0;
+ u32 wfd_offset = 0;
+ // Try to get the TCP port information when receiving the negotiation response.
+ //
+
+ wfd_offset = 0;
+ wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );
+ while( wfd_offset )
+ {
+ u8 attr_content[ 10 ] = { 0x00 };
+ u32 attr_contentlen = 0;
+ int i;
+
+ DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ );
+ rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
+ if ( attr_contentlen )
+ {
+ ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
+ DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport );
+ }
+
+ _rtw_memset( attr_content, 0x00, 10);
+ attr_contentlen = 0;
+ rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, attr_content, &attr_contentlen);
+ if ( attr_contentlen )
+ {
+ _rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, ( attr_content + 1 ), 4);
+ DBG_871X( "[%s] Peer IP = %02u.%02u.%02u.%02u \n", __FUNCTION__,
+ ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1],
+ ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3]
+ );
+ }
+ wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );
+ }
+}
+
+void issue_tunneled_probe_req(_adapter *padapter)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ DBG_871X("[%s]\n", __FUNCTION__);
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);
+
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+ pattrib->qsel=pattrib->priority;
+ if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TUNNELED_PROBE_REQ) != _SUCCESS) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+}
+
+void issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib;
+
+ DBG_871X("[%s]\n", __FUNCTION__);
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN);
+
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+ pattrib->qsel=pattrib->priority;
+ if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TUNNELED_PROBE_RSP) != _SUCCESS) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+}
+#endif //CONFIG_WFD
+
+void issue_tdls_setup_req(_adapter *padapter, u8 *mac_addr)
+{
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *ptdls_sta= NULL;
+ _irqL irqL;
+ static u8 dialogtoken = 0;
+ u32 timeout_interval= TPK_RESEND_COUNT * 1000; //retry timer should set at least 301 sec, using TPK_count counting 301 times.
+
+ if(ptdlsinfo->ap_prohibited == _TRUE)
+ goto exit;
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+
+ //init peer sta_info
+ ptdls_sta = rtw_get_stainfo(pstapriv, mac_addr);
+ if(ptdls_sta==NULL)
+ {
+ ptdls_sta = rtw_alloc_stainfo(pstapriv, mac_addr);
+ if(ptdls_sta)
+ {
+ _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
+ ptdlsinfo->sta_cnt++;
+ _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ if( ptdlsinfo->sta_cnt == (NUM_STA - 2) ) // -2: AP + BC/MC sta
+ {
+ ptdlsinfo->sta_maximum = _TRUE;
+ }
+ }
+ else
+ {
+ rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ }
+
+ if(ptdls_sta){
+ ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE;
+ //for tdls; ptdls_sta->aid is used to fill dialogtoken
+ ptdls_sta->dialog = dialogtoken;
+ dialogtoken = (dialogtoken+1)%256;
+ ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
+ _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME );
+ }
+
+ pattrib->qsel=pattrib->priority;
+ if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_REQUEST) !=_SUCCESS ){
+ rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+}
+
+void issue_tdls_teardown(_adapter *padapter, u8 *mac_addr)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *ptdls_sta=NULL;
+ _irqL irqL;
+
+ ptdls_sta = rtw_get_stainfo(pstapriv, mac_addr);
+ if(ptdls_sta==NULL){
+ DBG_871X("issue tdls teardown unsuccessful\n");
+ return;
+ }else{
+ ptdls_sta->tdls_sta_state=TDLS_STATE_NONE;
+ }
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+ pattrib->qsel=pattrib->priority;
+ if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_TEARDOWN) != _SUCCESS) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+ if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
+ }
+
+ if( ptdls_sta->timer_flag == 1 )
+ {
+ _enter_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL);
+ ptdls_sta->timer_flag = 2;
+ _exit_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL);
+ }
+ else
+ rtw_tdls_cmd(padapter, mac_addr, TDLS_FREE_STA );
+
+
+exit:
+
+ return;
+}
+
+void issue_tdls_dis_req(_adapter *padapter, u8 *mac_addr)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ if(mac_addr == NULL)
+ _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);
+ else
+ _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
+
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+ pattrib->qsel=pattrib->priority;
+ if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_DISCOVERY_REQUEST) != _SUCCESS) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+ DBG_871X("issue tdls dis req\n");
+
+exit:
+
+ return;
+}
+
+void issue_tdls_setup_rsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib;
+ _irqL irqL;
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN);
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, rx_pkt_pattrib->bssid, ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+ pattrib->qsel=pattrib->priority;
+ if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_RESPONSE) != _SUCCESS) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+
+}
+
+void issue_tdls_setup_cfm(_adapter *padapter, union recv_frame *precv_frame)
+{
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct sta_info *ptdls_sta=NULL;
+ _irqL irqL;
+
+ struct rx_pkt_attrib *rx_pkt_pattrib = & precv_frame->u.hdr.attrib;
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN);
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, rx_pkt_pattrib->bssid, ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+ pattrib->qsel=pattrib->priority;
+ if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_CONFIRM) != _SUCCESS) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+
+}
+
+//TDLS Discovery Response frame is a management action frame
+void issue_tdls_dis_rsp(_adapter *padapter, union recv_frame *precv_frame, u8 dialog)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ unsigned char *pframe;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ unsigned short *fctrl;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+ struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib;
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+ update_mgntframe_attrib(padapter, pattrib);
+
+ _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+ pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+ fctrl = &(pwlanhdr->frame_ctl);
+ *(fctrl) = 0;
+
+ // unicast probe request frame
+ _rtw_memcpy(pwlanhdr->addr1, rx_pkt_pattrib->src, ETH_ALEN);
+ _rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN);
+
+ _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
+ _rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN);
+
+ _rtw_memcpy(pwlanhdr->addr3, rx_pkt_pattrib->bssid, ETH_ALEN);
+ _rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN);
+
+ SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+ pmlmeext->mgnt_seq++;
+ SetFrameSubType(pframe, WIFI_ACTION);
+
+ pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
+ pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
+
+ rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, dialog);
+
+ pattrib->nr_frags = 1;
+ pattrib->last_txcmdsz = pattrib->pktlen;
+
+ dump_mgntframe(padapter, pmgntframe);
+
+ return;
+}
+
+void issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+
+ static u8 dialogtoken=0;
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ //for tdls; pattrib->nr_frags is used to fill dialogtoken
+ ptdls_sta->dialog = dialogtoken;
+ dialogtoken = (dialogtoken+1)%256;
+ //PTI frame's priority should be AC_VO
+ pattrib->priority = 7;
+
+ update_tdls_attrib(padapter, pattrib);
+ pattrib->qsel=pattrib->priority;
+ if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_PEER_TRAFFIC_INDICATION) != _SUCCESS) {
+ rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+}
+
+void issue_tdls_ch_switch_req(_adapter *padapter, u8 *mac_addr)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+
+ pattrib->qsel=pattrib->priority;
+ if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_CHANNEL_SWITCH_REQUEST) !=_SUCCESS ){
+ rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+}
+
+void issue_tdls_ch_switch_rsp(_adapter *padapter, u8 *mac_addr)
+{
+ struct xmit_frame *pmgntframe;
+ struct pkt_attrib *pattrib;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+
+ _irqL irqL;
+
+ if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+ {
+ return;
+ }
+
+ //update attribute
+ pattrib = &pmgntframe->attrib;
+
+ pmgntframe->frame_tag = DATA_FRAMETAG;
+ pattrib->ether_type = 0x890d;
+ pattrib->pctrl =0;
+
+ _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
+ _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
+
+ _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+ _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+ update_tdls_attrib(padapter, pattrib);
+
+ pattrib->qsel=pattrib->priority;
+/*
+ _enter_critical_bh(&pxmitpriv->lock, &irqL);
+ if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){
+ _exit_critical_bh(&pxmitpriv->lock, &irqL);
+ return _FALSE;
+ }
+*/
+ if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_CHANNEL_SWITCH_RESPONSE) !=_SUCCESS ){
+ rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ goto exit;
+ }
+ rtw_dump_xframe(padapter, pmgntframe);
+
+exit:
+
+ return;
+}
+
+sint On_TDLS_Dis_Rsp(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(adapter->stapriv), get_bssid(&(adapter->mlmepriv)));
+ struct recv_priv *precvpriv = &(adapter->recvpriv);
+ u8 *ptr = precv_frame->u.hdr.rx_data, *psa;
+ struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib);
+ struct tdls_info *ptdlsinfo = &(adapter->tdlsinfo);
+ u8 empty_addr[ETH_ALEN] = { 0x00 };
+ int UndecoratedSmoothedPWDB;
+
+
+ //WFDTDLS: for sigma test, not to setup direct link automatically
+ ptdlsinfo->dev_discovered = 1;
+
+#ifdef CONFIG_TDLS_AUTOSETUP
+ psa = get_sa(ptr);
+ ptdls_sta = rtw_get_stainfo(&(adapter->stapriv), psa);
+
+ if(ptdls_sta != NULL)
+ {
+ ptdls_sta->tdls_sta_state |= TDLS_ALIVE_STATE;
+
+ //Record the tdls sta with lowest signal strength
+ if( (ptdlsinfo->sta_maximum == _TRUE) && (ptdls_sta->alive_count >= 1) )
+ {
+ if( _rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN) )
+ {
+ _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
+ ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll;
+ }
+ else
+ {
+ if( ptdlsinfo->ss_record.RxPWDBAll < pattrib->RxPWDBAll )
+ {
+ _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
+ ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll;
+ }
+ }
+ }
+
+ }
+ else
+ {
+ if( ptdlsinfo->sta_maximum == _TRUE)
+ {
+ if( _rtw_memcmp( ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN ) )
+ {
+ //All traffics are busy, do not set up another direct link.
+ return _FAIL;
+ }
+ else
+ {
+ if( pattrib->RxPWDBAll > ptdlsinfo->ss_record.RxPWDBAll )
+ {
+ issue_tdls_teardown(adapter, ptdlsinfo->ss_record.macaddr);
+ }
+ else
+ {
+ return _FAIL;
+ }
+ }
+ }
+
+ adapter->HalFunc.GetHalDefVarHandler(adapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
+
+ if( pattrib->RxPWDBAll + TDLS_SIGNAL_THRESH >= UndecoratedSmoothedPWDB);
+ {
+ DBG_871X("pattrib->RxPWDBAll=%d, pdmpriv->UndecoratedSmoothedPWDB=%d\n", pattrib->RxPWDBAll, UndecoratedSmoothedPWDB);
+ issue_tdls_setup_req(adapter, psa);
+ }
+ }
+#endif //CONFIG_TDLS_AUTOSETUP
+
+ return _SUCCESS;
+}
+
+sint On_TDLS_Setup_Req(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
+ u8 *psa, *pmyid;
+ struct sta_info *ptdls_sta= NULL;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+ struct security_priv *psecuritypriv = &adapter->securitypriv;
+ _irqL irqL;
+ struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+ u8 *prsnie, *ppairwise_cipher;
+ u8 i, k, pairwise_count;
+ u8 ccmp_have=0, rsnie_have=0;
+ u16 j;
+ u8 SNonce[32];
+ u32 *timeout_interval;
+ sint parsing_length; //frame body length, without icv_len
+ PNDIS_802_11_VARIABLE_IEs pIE;
+ u8 FIXED_IE = 5;
+ unsigned char supportRate[16];
+ int supportRateNum = 0;
+
+ psa = get_sa(ptr);
+ ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+ pmyid=myid(&(adapter->eeprompriv));
+ ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
+ parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+ -prx_pkt_attrib->hdrlen
+ -prx_pkt_attrib->iv_len
+ -prx_pkt_attrib->icv_len
+ -LLC_HEADER_SIZE
+ -ETH_TYPE_LEN
+ -PAYLOAD_TYPE_LEN
+ -FIXED_IE;
+
+ if(ptdlsinfo->ap_prohibited == _TRUE)
+ {
+ goto exit;
+ }
+
+ if(ptdls_sta==NULL){
+ ptdls_sta = rtw_alloc_stainfo(pstapriv, psa);
+ }else{
+ if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){
+ //If the direct link is already set up
+ //Process as re-setup after tear down
+ DBG_871X("re-setup a direct link\n");
+ }
+ //already receiving TDLS setup request
+ else if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){
+ DBG_871X("receive duplicated TDLS setup request frame in handshaking\n");
+ goto exit;
+ }
+ //When receiving and sending setup_req to the same link at the same time, STA with higher MAC_addr would be initiator
+ //following is to check out MAC_addr
+ else if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){
+ DBG_871X("receive setup_req after sending setup_req\n");
+ for (i=0;i<6;i++){
+ if(*(pmyid+i)==*(psa+i)){
+ }
+ else if(*(pmyid+i)>*(psa+i)){
+ goto exit;
+ }else if(*(pmyid+i)<*(psa+i)){
+ ptdls_sta->tdls_sta_state=TDLS_INITIATOR_STATE;
+ break;
+ }
+ }
+ }
+ }
+
+ if(ptdls_sta)
+ {
+ ptdls_sta->dialog = *(ptr+2); //copy dialog token
+ ptdls_sta->stat_code = 0;
+
+ //parsing information element
+ for(j=FIXED_IE; j<parsing_length;){
+
+ pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+ switch (pIE->ElementID)
+ {
+ case _SUPPORTEDRATES_IE_:
+ _rtw_memcpy(supportRate, pIE->data, pIE->Length);
+ supportRateNum = pIE->Length;
+ break;
+ case _COUNTRY_IE_:
+ break;
+ case _EXT_SUPPORTEDRATES_IE_:
+ if(supportRateNum<=sizeof(supportRate))
+ {
+ _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
+ supportRateNum += pIE->Length;
+ }
+ break;
+ case _SUPPORTED_CH_IE_:
+ break;
+ case _RSN_IE_2_:
+ rsnie_have=1;
+ if(prx_pkt_attrib->encrypt){
+ prsnie=(u8*)pIE;
+ //check whether initiator STA has CCMP pairwise_cipher.
+ ppairwise_cipher=prsnie+10;
+ _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 1);
+ for(k=0;k<pairwise_count;k++){
+ if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)
+ ccmp_have=1;
+ }
+ if(ccmp_have==0){
+ //invalid contents of RSNIE
+ ptdls_sta->stat_code=72;
+ }
+ }
+ break;
+ case _EXT_CAP_IE_:
+ break;
+ case _VENDOR_SPECIFIC_IE_:
+ break;
+ case _FTIE_:
+ if(prx_pkt_attrib->encrypt)
+ _rtw_memcpy(SNonce, (ptr+j+52), 32);
+ break;
+ case _TIMEOUT_ITVL_IE_:
+ if(prx_pkt_attrib->encrypt)
+ timeout_interval = (u32 *)(ptr+j+3);
+ break;
+ case _RIC_Descriptor_IE_:
+ break;
+ case _HT_CAPABILITY_IE_:
+ rtw_tdls_process_ht_cap(adapter, ptdls_sta, pIE->data, pIE->Length);
+ break;
+ case EID_BSSCoexistence:
+ break;
+ case _LINK_ID_IE_:
+ if(_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE)
+ {
+ //not in the same BSS
+ ptdls_sta->stat_code=7;
+ }
+ break;
+ default:
+ break;
+ }
+
+ j += (pIE->Length + 2);
+
+ }
+
+ //update station supportRate
+ ptdls_sta->bssratelen = supportRateNum;
+ _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
+
+ //check status code
+ //if responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject
+ if(ptdls_sta->stat_code == 0 )
+ {
+ if(rsnie_have && (prx_pkt_attrib->encrypt==0)){
+ //security disabled
+ ptdls_sta->stat_code = 5;
+ }else if(rsnie_have==0 && (prx_pkt_attrib->encrypt)){
+ //request haven't RSNIE
+ ptdls_sta->stat_code = 38;
+ }
+
+#ifdef CONFIG_WFD
+ //WFD test plan version 0.18.2 test item 5.1.5
+ //SoUT does not use TDLS if AP uses weak security
+ if ( adapter->wdinfo.wfd_tdls_enable )
+ {
+ if(rsnie_have && (prx_pkt_attrib->encrypt != _AES_))
+ {
+ ptdls_sta->stat_code = 5;
+ }
+ }
+#endif //CONFIG_WFD
+ }
+
+ ptdls_sta->tdls_sta_state|= TDLS_INITIATOR_STATE;
+ if(prx_pkt_attrib->encrypt){
+ _rtw_memcpy(ptdls_sta->SNonce, SNonce, 32);
+ _rtw_memcpy(&(ptdls_sta->TDLS_PeerKey_Lifetime), timeout_interval, 4);
+ }
+ _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
+ ptdlsinfo->sta_cnt++;
+ _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+ if( ptdlsinfo->sta_cnt == (NUM_STA - 2) ) // -2: AP + BC/MC sta
+ {
+ ptdlsinfo->sta_maximum = _TRUE;
+ }
+
+#ifdef CONFIG_WFD
+ rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);
+#endif // CONFIG_WFD
+
+ }
+ else
+ {
+ goto exit;
+ }
+
+ issue_tdls_setup_rsp(adapter, precv_frame);
+
+ if(ptdls_sta->stat_code==0)
+ {
+ _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
+ }
+ else //status code!=0 ; setup unsuccess
+ {
+ free_tdls_sta(adapter, ptdls_sta);
+ }
+
+exit:
+
+ return _FAIL;
+}
+
+sint On_TDLS_Setup_Rsp(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
+ struct sta_info *ptdls_sta= NULL;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ _irqL irqL;
+ struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+ u8 *psa;
+ u16 stat_code;
+ sint parsing_length; //frame body length, without icv_len
+ PNDIS_802_11_VARIABLE_IEs pIE;
+ u8 FIXED_IE =7;
+ u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic, *ppairwise_cipher;
+ u16 pairwise_count, j, k;
+ u8 verify_ccmp=0;
+ unsigned char supportRate[16];
+ int supportRateNum = 0;
+
+ psa = get_sa(ptr);
+ ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+ if ( NULL == ptdls_sta )
+ {
+ return _FAIL;
+ }
+
+ ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
+ parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+ -prx_pkt_attrib->hdrlen
+ -prx_pkt_attrib->iv_len
+ -prx_pkt_attrib->icv_len
+ -LLC_HEADER_SIZE
+ -TYPE_LENGTH_FIELD_SIZE
+ -1
+ -FIXED_IE;
+
+ _rtw_memcpy(&stat_code, ptr+2, 2);
+
+ if(stat_code!=0)
+ {
+ DBG_871X( "[%s] status_code = %d, free_tdls_sta\n", __FUNCTION__, stat_code );
+ free_tdls_sta(adapter, ptdls_sta);
+ return _FAIL;
+ }
+
+ stat_code = 0;
+
+ //parsing information element
+ for(j=FIXED_IE; j<parsing_length;)
+ {
+ pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+ switch (pIE->ElementID)
+ {
+ case _SUPPORTEDRATES_IE_:
+ _rtw_memcpy(supportRate, pIE->data, pIE->Length);
+ supportRateNum = pIE->Length;
+ break;
+ case _COUNTRY_IE_:
+ break;
+ case _EXT_SUPPORTEDRATES_IE_:
+ if(supportRateNum<=sizeof(supportRate))
+ {
+ _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
+ supportRateNum += pIE->Length;
+ }
+ break;
+ case _SUPPORTED_CH_IE_:
+ break;
+ case _RSN_IE_2_:
+ prsnie=(u8*)pIE;
+ //check whether responder STA has CCMP pairwise_cipher.
+ ppairwise_cipher=prsnie+10;
+ _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 2);
+ for(k=0;k<pairwise_count;k++){
+ if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)
+ verify_ccmp=1;
+ }
+ case _EXT_CAP_IE_:
+ break;
+ case _VENDOR_SPECIFIC_IE_:
+ break;
+ case _FTIE_:
+ pftie=(u8*)pIE;
+ _rtw_memcpy(ptdls_sta->ANonce, (ptr+j+20), 32);
+ break;
+ case _TIMEOUT_ITVL_IE_:
+ ptimeout_ie=(u8*)pIE;
+ break;
+ case _RIC_Descriptor_IE_:
+ break;
+ case _HT_CAPABILITY_IE_:
+ rtw_tdls_process_ht_cap(adapter, ptdls_sta, pIE->data, pIE->Length);
+ break;
+ case EID_BSSCoexistence:
+ break;
+ case _LINK_ID_IE_:
+ plinkid_ie=(u8*)pIE;
+ break;
+ default:
+ break;
+ }
+
+ j += (pIE->Length + 2);
+
+ }
+
+ //update station supportRate
+ ptdls_sta->bssratelen = supportRateNum;
+ _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
+
+#ifdef CONFIG_WFD
+ rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);
+#endif // CONFIG_WFD
+
+ if(stat_code != 0)
+ {
+ ptdls_sta->stat_code = stat_code;
+ }
+ else
+ {
+ if(prx_pkt_attrib->encrypt)
+ {
+ if(verify_ccmp==1)
+ {
+ wpa_tdls_generate_tpk(adapter, ptdls_sta);
+ ptdls_sta->stat_code=0;
+ if(tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie)==0) //0: Invalid, 1: valid
+ {
+ free_tdls_sta(adapter, ptdls_sta);
+ return _FAIL;
+ }
+ }
+ else
+ {
+ ptdls_sta->stat_code=72; //invalide contents of RSNIE
+ }
+
+ }else{
+ ptdls_sta->stat_code=0;
+ }
+ }
+
+ DBG_871X("issue_tdls_setup_cfm\n");
+ issue_tdls_setup_cfm(adapter, precv_frame);
+
+ if(ptdls_sta->stat_code==0)
+ {
+ ptdlsinfo->setup_state = TDLS_LINKED_STATE;
+
+ if( ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE )
+ {
+ ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
+ _cancel_timer_ex( &ptdls_sta->handshake_timer);
+#ifdef CONFIG_TDLS_AUTOCHECKALIVE
+ _set_timer( &ptdls_sta->alive_timer1, TDLS_ALIVE_TIMER_PH1);
+#endif //CONFIG_TDLS_AUTOSETUP
+ }
+
+ rtw_tdls_set_mac_id(ptdlsinfo, ptdls_sta);
+ rtw_tdls_set_key(adapter, prx_pkt_attrib, ptdls_sta);
+
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_WRCR);
+
+ }
+ else //status code!=0 ; setup unsuccessful
+ {
+ free_tdls_sta(adapter, ptdls_sta);
+ }
+
+ return _FAIL;
+
+}
+
+sint On_TDLS_Setup_Cfm(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
+ struct sta_info *ptdls_sta= NULL;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ _irqL irqL;
+ struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+ u8 *psa;
+ u16 stat_code;
+ sint parsing_length;
+ PNDIS_802_11_VARIABLE_IEs pIE;
+ u8 FIXED_IE =5;
+ u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic, *ppairwise_cipher;
+ u16 j, pairwise_count;
+
+ psa = get_sa(ptr);
+ ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+ ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
+ parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+ -prx_pkt_attrib->hdrlen
+ -prx_pkt_attrib->iv_len
+ -prx_pkt_attrib->icv_len
+ -LLC_HEADER_SIZE
+ -ETH_TYPE_LEN
+ -PAYLOAD_TYPE_LEN
+ -FIXED_IE;
+ _rtw_memcpy(&stat_code, ptr+2, 2);
+
+ if(stat_code!=0){
+ DBG_871X( "[%s] stat_code = %d\n, free_tdls_sta", __FUNCTION__, stat_code );
+ free_tdls_sta(adapter, ptdls_sta);
+ return _FAIL;
+ }
+
+ if(prx_pkt_attrib->encrypt){
+ //parsing information element
+ for(j=FIXED_IE; j<parsing_length;){
+
+ pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+ switch (pIE->ElementID)
+ {
+ case _RSN_IE_2_:
+ prsnie=(u8*)pIE;
+ break;
+ case _VENDOR_SPECIFIC_IE_:
+ break;
+ case _FTIE_:
+ pftie=(u8*)pIE;
+ break;
+ case _TIMEOUT_ITVL_IE_:
+ ptimeout_ie=(u8*)pIE;
+ break;
+ case _HT_EXTRA_INFO_IE_:
+ break;
+ case _LINK_ID_IE_:
+ plinkid_ie=(u8*)pIE;
+ break;
+ default:
+ break;
+ }
+
+ j += (pIE->Length + 2);
+
+ }
+
+ //verify mic in FTIE MIC field
+ if(tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie)==0){ //0: Invalid, 1: Valid
+ free_tdls_sta(adapter, ptdls_sta);
+ return _FAIL;
+ }
+
+ }
+
+ ptdlsinfo->setup_state = TDLS_LINKED_STATE;
+ if( ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE )
+ {
+ ptdls_sta->tdls_sta_state|=TDLS_LINKED_STATE;
+ _cancel_timer_ex( &ptdls_sta->handshake_timer);
+#ifdef CONFIG_TDLS_AUTOCHECKALIVE
+ _set_timer( &ptdls_sta->alive_timer1, TDLS_ALIVE_TIMER_PH1);
+#endif //CONFIG_TDLS_AUTOCHECKALIVE
+ }
+
+ rtw_tdls_set_mac_id(ptdlsinfo, ptdls_sta);
+ rtw_tdls_set_key(adapter, prx_pkt_attrib, ptdls_sta);
+
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_WRCR);
+
+ return _FAIL;
+
+}
+
+sint On_TDLS_Dis_Req(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct sta_info *psta_ap;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ sint parsing_length; //frame body length, without icv_len
+ PNDIS_802_11_VARIABLE_IEs pIE;
+ u8 FIXED_IE = 3, *dst, *pdialog = NULL;
+ u16 j;
+
+ ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE + 1;
+ pdialog=ptr+2;
+
+ parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+ -prx_pkt_attrib->hdrlen
+ -prx_pkt_attrib->iv_len
+ -prx_pkt_attrib->icv_len
+ -LLC_HEADER_SIZE
+ -TYPE_LENGTH_FIELD_SIZE
+ -1
+ -FIXED_IE;
+
+ //parsing information element
+ for(j=FIXED_IE; j<parsing_length;){
+
+ pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+ switch (pIE->ElementID)
+ {
+ case _LINK_ID_IE_:
+ psta_ap = rtw_get_stainfo(pstapriv, pIE->data);
+ if(psta_ap == NULL)
+ {
+ goto exit;
+ }
+ dst = pIE->data + 12;
+ if( (MacAddr_isBcst(dst) == _FALSE) && (_rtw_memcmp(myid(&(adapter->eeprompriv)), dst, 6) == _FALSE) )
+ {
+ goto exit;
+ }
+ break;
+ default:
+ break;
+ }
+
+ j += (pIE->Length + 2);
+
+ }
+
+ //check frame contents
+
+ issue_tdls_dis_rsp(adapter, precv_frame, *(pdialog) );
+
+exit:
+
+ return _FAIL;
+
+}
+
+sint On_TDLS_Teardown(_adapter *adapter, union recv_frame *precv_frame)
+{
+ u8 *psa;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+ struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ struct sta_info *ptdls_sta= NULL;
+ _irqL irqL;
+
+ psa = get_sa(ptr);
+
+ ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+ if(ptdls_sta!=NULL){
+ if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
+ }
+ free_tdls_sta(adapter, ptdls_sta);
+ }
+
+ return _FAIL;
+
+}
+
+u8 TDLS_check_ch_state(uint state){
+ if( (state & TDLS_CH_SWITCH_ON_STATE) &&
+ (state & TDLS_AT_OFF_CH_STATE) &&
+ (state & TDLS_PEER_AT_OFF_STATE) ){
+
+ if(state & TDLS_PEER_SLEEP_STATE)
+ return 2; //U-APSD + ch. switch
+ else
+ return 1; //ch. switch
+ }else
+ return 0;
+}
+
+//we process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here
+sint On_TDLS_Peer_Traffic_Rsp(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+ struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ //get peer sta infomation
+ struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src);
+ u8 wmmps_ac=0, state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state);
+ int i;
+
+ ptdls_sta->sta_stats.rx_data_pkts++;
+
+ //receive peer traffic response frame, sleeping STA wakes up
+ //ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_SLEEP_STATE);
+ process_wmmps_data( adapter, precv_frame);
+
+ // if noticed peer STA wakes up by receiving peer traffic response
+ // and we want to do channel swtiching, then we will transmit channel switch request first
+ if(ptdls_sta->tdls_sta_state & TDLS_APSD_CHSW_STATE){
+ issue_tdls_ch_switch_req(adapter, pattrib->src);
+ ptdls_sta->tdls_sta_state &= ~(TDLS_APSD_CHSW_STATE);
+ return _FAIL;
+ }
+
+ //check 4-AC queue bit
+ if(ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk)
+ wmmps_ac=1;
+
+ //if it's a direct link and have buffered frame
+ if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){
+ if(wmmps_ac && state)
+ {
+ _irqL irqL;
+ _list *xmitframe_plist, *xmitframe_phead;
+ struct xmit_frame *pxmitframe=NULL;
+
+ _enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
+
+ xmitframe_phead = get_list_head(&ptdls_sta->sleep_q);
+ xmitframe_plist = get_next(xmitframe_phead);
+
+ //transmit buffered frames
+ while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
+ {
+ pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+ xmitframe_plist = get_next(xmitframe_plist);
+ rtw_list_delete(&pxmitframe->list);
+
+ ptdls_sta->sleepq_len--;
+ if(ptdls_sta->sleepq_len>0){
+ pxmitframe->attrib.mdata = 1;
+ pxmitframe->attrib.eosp = 0;
+ }else{
+ pxmitframe->attrib.mdata = 0;
+ pxmitframe->attrib.eosp = 1;
+ }
+ //pxmitframe->attrib.triggered = 1; //maybe doesn't need in TDLS
+ if(adapter->HalFunc.hal_xmit(adapter, pxmitframe) == _TRUE)
+ {
+ rtw_os_xmit_complete(adapter, pxmitframe);
+ }
+
+ }
+
+ if(ptdls_sta->sleepq_len==0)
+ {
+ DBG_871X("no buffered packets for tdls to xmit\n");
+ //on U-APSD + CH. switch state, when there is no buffered date to xmit,
+ // we should go back to base channel
+ if(state==2){
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
+ }else if(ptdls_sta->tdls_sta_state&TDLS_SW_OFF_STATE){
+ ptdls_sta->tdls_sta_state &= ~(TDLS_SW_OFF_STATE);
+ ptdlsinfo->candidate_ch= pmlmeext->cur_channel;
+ issue_tdls_ch_switch_req(adapter, pattrib->src);
+ DBG_871X("issue tdls ch switch req back to base channel\n");
+ }
+
+ }
+ else
+ {
+ DBG_871X("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len);
+ ptdls_sta->sleepq_len=0;
+ }
+
+ _exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
+
+ }
+
+ }
+
+ return _FAIL;
+}
+
+sint On_TDLS_Ch_Switch_Req(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct sta_info *ptdls_sta= NULL;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+ u8 *psa;
+ sint parsing_length;
+ PNDIS_802_11_VARIABLE_IEs pIE;
+ u8 FIXED_IE =3;
+ u16 j;
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+
+ psa = get_sa(ptr);
+ ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+ ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
+ parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+ -prx_pkt_attrib->hdrlen
+ -prx_pkt_attrib->iv_len
+ -prx_pkt_attrib->icv_len
+ -LLC_HEADER_SIZE
+ -ETH_TYPE_LEN
+ -PAYLOAD_TYPE_LEN
+ -FIXED_IE;
+
+ ptdls_sta->off_ch = *(ptr+2);
+
+ //parsing information element
+ for(j=FIXED_IE; j<parsing_length;){
+
+ pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+ switch (pIE->ElementID)
+ {
+ case _COUNTRY_IE_:
+ break;
+ case _CH_SWTICH_ANNOUNCE_:
+ break;
+ case _LINK_ID_IE_:
+ break;
+ case _CH_SWITCH_TIMING_:
+ _rtw_memcpy(&ptdls_sta->ch_switch_time, pIE->data, 2);
+ _rtw_memcpy(&ptdls_sta->ch_switch_timeout, pIE->data+2, 2);
+ default:
+ break;
+ }
+
+ j += (pIE->Length + 2);
+
+ }
+
+ //todo: check status
+ ptdls_sta->stat_code=0;
+ ptdls_sta->tdls_sta_state |= TDLS_CH_SWITCH_ON_STATE;
+
+ issue_nulldata(adapter, NULL, 1, 0, 0);
+
+ issue_tdls_ch_switch_rsp(adapter, psa);
+
+ DBG_871X("issue tdls channel switch response\n");
+
+ if((ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE) && ptdls_sta->off_ch==pmlmeext->cur_channel){
+ DBG_871X("back to base channel %x\n", pmlmeext->cur_channel);
+ ptdls_sta->option=7;
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_BASE_CH);
+ }else{
+ ptdls_sta->option=6;
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH);
+ }
+ return _FAIL;
+}
+
+sint On_TDLS_Ch_Switch_Rsp(_adapter *adapter, union recv_frame *precv_frame)
+{
+ struct sta_info *ptdls_sta= NULL;
+ struct sta_priv *pstapriv = &adapter->stapriv;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+ u8 *psa;
+ sint parsing_length;
+ PNDIS_802_11_VARIABLE_IEs pIE;
+ u8 FIXED_IE =4;
+ u16 stat_code, j, switch_time, switch_timeout;
+ struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+
+ psa = get_sa(ptr);
+ ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+ //if channel switch is running and receiving Unsolicited TDLS Channel Switch Response,
+ //it will go back to base channel and terminate this channel switch procedure
+ if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE ){
+ if(pmlmeext->cur_channel==ptdls_sta->off_ch){
+ DBG_871X("back to base channel %x\n", pmlmeext->cur_channel);
+ ptdls_sta->option=7;
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH);
+ }else{
+ DBG_871X("receive unsolicited channel switch response \n");
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
+ }
+ return _FAIL;
+ }
+
+ //avoiding duplicated or unconditional ch. switch. rsp
+ if((ptdls_sta->tdls_sta_state & TDLS_CH_SW_INITIATOR_STATE) != TDLS_CH_SW_INITIATOR_STATE)
+ return _FAIL;
+
+ ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
+ parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+ -prx_pkt_attrib->hdrlen
+ -prx_pkt_attrib->iv_len
+ -prx_pkt_attrib->icv_len
+ -LLC_HEADER_SIZE
+ -ETH_TYPE_LEN
+ -PAYLOAD_TYPE_LEN
+ -FIXED_IE;
+
+ _rtw_memcpy(&stat_code, ptr+2, 2);
+
+ if(stat_code!=0){
+ return _FAIL;
+ }
+
+ //parsing information element
+ for(j=FIXED_IE; j<parsing_length;){
+
+ pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+ switch (pIE->ElementID)
+ {
+ case _LINK_ID_IE_:
+ break;
+ case _CH_SWITCH_TIMING_:
+ _rtw_memcpy(&switch_time, pIE->data, 2);
+ if(switch_time > ptdls_sta->ch_switch_time)
+ _rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2);
+
+ _rtw_memcpy(&switch_timeout, pIE->data+2, 2);
+ if(switch_timeout > ptdls_sta->ch_switch_timeout)
+ _rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2);
+
+ default:
+ break;
+ }
+
+ j += (pIE->Length + 2);
+
+ }
+
+ ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SW_INITIATOR_STATE);
+ ptdls_sta->tdls_sta_state |=TDLS_CH_SWITCH_ON_STATE;
+
+ //goto set_channel_workitem_callback()
+ ptdls_sta->option=6;
+ rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH);
+
+ return _FAIL;
+}
+
+#ifdef CONFIG_WFD
+void wfd_ie_tdls(_adapter * padapter, u8 *pframe, u32 *pktlen )
+{
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct wifi_display_info *pwfd_info = padapter->tdlsinfo.wfd_info;
+ u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+ u32 wfdielen = 0;
+
+ // WFD OUI
+ wfdielen = 0;
+ wfdie[ wfdielen++ ] = 0x50;
+ wfdie[ wfdielen++ ] = 0x6F;
+ wfdie[ wfdielen++ ] = 0x9A;
+ wfdie[ wfdielen++ ] = 0x0A; // WFA WFD v1.0
+
+ // Commented by Albert 20110825
+ // According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
+ // 1. WFD Device Information
+ // 2. Associated BSSID ( Optional )
+ // 3. Local IP Adress ( Optional )
+
+ // WFD Device Information ATTR
+ // Type:
+ wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+ // Length:
+ // Note: In the WFD specification, the size of length field is 2.
+ RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+ wfdielen += 2;
+
+ // Value1:
+ // WFD device information
+ // available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery )
+ RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL
+ | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD);
+ wfdielen += 2;
+
+ // Value2:
+ // Session Management Control Port
+ // Default TCP port for RTSP messages is 554
+ RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+ wfdielen += 2;
+
+ // Value3:
+ // WFD Device Maximum Throughput
+ // 300Mbps is the maximum throughput
+ RTW_PUT_BE16(wfdie + wfdielen, 300);
+ wfdielen += 2;
+
+ // Associated BSSID ATTR
+ // Type:
+ wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+ // Length:
+ // Note: In the WFD specification, the size of length field is 2.
+ RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+ wfdielen += 2;
+
+ // Value:
+ // Associated BSSID
+ if ( check_fwstate( pmlmepriv, _FW_LINKED) == _TRUE )
+ {
+ _rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+ }
+ else
+ {
+ _rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+ }
+
+ // Local IP Address ATTR
+ wfdie[ wfdielen++ ] = WFD_ATTR_LOCAL_IP_ADDR;
+
+ // Length:
+ // Note: In the WFD specification, the size of length field is 2.
+ RTW_PUT_BE16(wfdie + wfdielen, 0x0005);
+ wfdielen += 2;
+
+ // Version:
+ // 0x01: Version1;IPv4
+ wfdie[ wfdielen++ ] = 0x01;
+
+ // IPv4 Address
+ _rtw_memcpy( wfdie + wfdielen, pwfd_info->ip_address, 4 );
+ wfdielen += 4;
+
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen);
+
+}
+#endif //CONFIG_WFD
+
+void rtw_build_tdls_setup_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+ struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
+
+ u8 payload_type = 0x02;
+ u8 category = RTW_WLAN_CATEGORY_TDLS;
+ u8 action = TDLS_SETUP_REQUEST;
+ u8 bssrate[NDIS_802_11_LENGTH_RATES_EX]; //Use NDIS_802_11_LENGTH_RATES_EX in order to call func.rtw_set_supported_rate
+ int bssrate_len = 0, i = 0 ;
+ u8 more_supportedrates = 0;
+ unsigned int ie_len;
+ u8 *p;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 link_id_addr[18] = {0};
+ u8 iedata=0;
+ u8 sup_ch[ 30 * 2 ] = {0x00 }, sup_ch_idx = 0, idx_5g = 2; //For supported channel
+ u8 timeout_itvl[5]; //set timeout interval to maximum value
+ u32 time;
+
+ //SNonce
+ if(pattrib->encrypt){
+ for(i=0;i<8;i++){
+ time=rtw_get_current_time();
+ _rtw_memcpy(&ptdls_sta->SNonce[4*i], (u8 *)&time, 4);
+ }
+ }
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, dialog token
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
+
+ //capability
+ _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+
+ if(pattrib->encrypt)
+ *pframe =*pframe | BIT(4);
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ //supported rates
+ rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);
+ bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;
+
+ if (bssrate_len > 8)
+ {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
+ more_supportedrates = 1;
+ }
+ else
+ {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
+ }
+
+ //country(optional)
+ //extended supported rates
+ if(more_supportedrates==1){
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
+ }
+
+ //supported channels
+ pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
+
+ // SRC IE
+ pframe = rtw_set_ie( pframe, _SRC_IE_, 16, TDLS_SRC, &(pattrib->pktlen));
+
+ //RSNIE
+ if(pattrib->encrypt)
+ pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
+
+ //extended capabilities
+ pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen));
+
+ //QoS capability(WMM_IE)
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 7, TDLS_WMMIE, &(pattrib->pktlen));
+
+
+ if(pattrib->encrypt){
+ //FTIE
+ _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0
+ _rtw_memset(pframe, _FTIE_, 1); //version
+ _rtw_memset((pframe+1), 82, 1); //length
+ _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);
+ pframe += 84;
+ pattrib->pktlen += 84;
+
+ //Timeout interval
+ timeout_itvl[0]=0x02;
+ _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
+ pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
+ }
+
+ //Sup_reg_classes(optional)
+ //HT capabilities
+ pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib);
+
+ //20/40 BSS coexistence
+ if(pmlmepriv->num_FortyMHzIntolerant>0)
+ iedata |= BIT(2);//20 MHz BSS Width Request
+ pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
+
+ //Link identifier
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+#ifdef CONFIG_WFD
+ wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );
+#endif //CONFIG_WFD
+
+}
+
+void rtw_build_tdls_setup_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct sta_info *ptdls_sta;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+
+ u8 payload_type = 0x02;
+ unsigned char category = RTW_WLAN_CATEGORY_TDLS;
+ unsigned char action = TDLS_SETUP_RESPONSE;
+ unsigned char bssrate[NDIS_802_11_LENGTH_RATES_EX];
+ int bssrate_len = 0;
+ u8 more_supportedrates = 0;
+ unsigned int ie_len;
+ unsigned char *p;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 link_id_addr[18] = {0};
+ u8 iedata=0;
+ u8 timeout_itvl[5]; //setup response timeout interval will copy from request
+ u8 ANonce[32]; //maybe it can put in ontdls_req
+ u8 k; //for random ANonce
+ u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic;
+ u32 time;
+
+ ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
+
+ if(ptdls_sta == NULL )
+ {
+ DBG_871X("[%s] %d\n", __FUNCTION__, __LINE__);
+ return;
+ }
+
+ if(pattrib->encrypt){
+ for(k=0;k<8;k++){
+ time=rtw_get_current_time();
+ _rtw_memcpy(&ptdls_sta->ANonce[4*k], (u8*)&time, 4);
+ }
+ }
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, status code
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
+
+ if(ptdls_sta->stat_code!=0) //invalid setup request
+ {
+ DBG_871X("ptdls_sta->stat_code:%04x \n", ptdls_sta->stat_code);
+ return;
+ }
+
+ //dialog token
+ pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
+
+ //capability
+ _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+
+ if(pattrib->encrypt )
+ *pframe =*pframe | BIT(4);
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ //supported rates
+ rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);
+ bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;
+
+ if (bssrate_len > 8)
+ {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
+ more_supportedrates = 1;
+ }
+ else
+ {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
+ }
+
+ //country(optional)
+ //extended supported rates
+ if(more_supportedrates==1){
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
+ }
+
+ //supported channels
+ pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
+
+ // SRC IE
+ pframe = rtw_set_ie(pframe, _SRC_IE_ , 16, TDLS_SRC, &(pattrib->pktlen));
+
+ //RSNIE
+ if(pattrib->encrypt){
+ prsnie = pframe;
+ pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
+ }
+
+ //extended capabilities
+ pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen));
+
+ //QoS capability(WMM_IE)
+ pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 7, TDLS_WMMIE, &(pattrib->pktlen));
+
+ if(pattrib->encrypt){
+ wpa_tdls_generate_tpk(padapter, ptdls_sta);
+
+ //FTIE
+ pftie = pframe;
+ pftie_mic = pframe+4;
+ _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0
+ _rtw_memset(pframe, _FTIE_, 1); //version
+ _rtw_memset((pframe+1), 82, 1); //length
+ _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32);
+ _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);
+ pframe += 84;
+ pattrib->pktlen += 84;
+
+ //Timeout interval
+ ptimeout_ie = pframe;
+ timeout_itvl[0]=0x02;
+ _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
+ pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
+ }
+
+ //Sup_reg_classes(optional)
+ //HT capabilities
+ pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib);
+
+ //20/40 BSS coexistence
+ if(pmlmepriv->num_FortyMHzIntolerant>0)
+ iedata |= BIT(2);//20 MHz BSS Width Request
+ pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
+
+ //Link identifier
+ plinkid_ie = pframe;
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+ //fill FTIE mic
+ if(pattrib->encrypt)
+ wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
+
+#ifdef CONFIG_WFD
+ wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );
+#endif //CONFIG_WFD
+
+}
+
+void rtw_build_tdls_setup_cfm_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
+
+ u8 payload_type = 0x02;
+ unsigned char category = RTW_WLAN_CATEGORY_TDLS;
+ unsigned char action = TDLS_SETUP_CONFIRM;
+ u8 more_supportedrates = 0;
+ unsigned int ie_len;
+ unsigned char *p;
+ u8 timeout_itvl[5]; //set timeout interval to maximum value
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 link_id_addr[18] = {0};
+ u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic;
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, status code, dialog token
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
+
+ if(ptdls_sta->stat_code!=0) //invalid setup request
+ return;
+
+ //RSNIE
+ if(pattrib->encrypt){
+ prsnie = pframe;
+ pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
+ }
+
+ //EDCA param set; WMM param ele.
+ if(pattrib->encrypt){
+ //FTIE
+ pftie = pframe;
+ pftie_mic = pframe+4;
+ _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0
+ _rtw_memset(pframe, _FTIE_, 1); //version
+ _rtw_memset((pframe+1), 82, 1); //length
+ _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32);
+ _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);
+ pframe += 84;
+ pattrib->pktlen += 84;
+
+ //Timeout interval
+ ptimeout_ie = pframe;
+ timeout_itvl[0]=0x02;
+ _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
+ ptdls_sta->TPK_count=0;
+ _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT);
+ pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
+ }
+
+ //HT operation; todo
+ //Link identifier
+ plinkid_ie = pframe;
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+ //fill FTIE mic
+ if(pattrib->encrypt)
+ wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
+
+}
+
+void rtw_build_tdls_teardown_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ u8 payload_type = 0x02;
+ unsigned char category = RTW_WLAN_CATEGORY_TDLS;
+ unsigned char action = TDLS_TEARDOWN;
+ u8 link_id_addr[18] = {0};
+
+ struct sta_info *ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, reason code
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
+
+ //Link identifier
+ if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+ }else if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
+ }
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+}
+
+void rtw_build_tdls_dis_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ u8 payload_type = 0x02;
+ u8 category = RTW_WLAN_CATEGORY_TDLS;
+ u8 action = TDLS_DISCOVERY_REQUEST;
+ u8 link_id_addr[18] = {0};
+ static u8 dialogtoken=0;
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, reason code
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen));
+ dialogtoken = (dialogtoken+1)%256;
+
+ //Link identifier
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+}
+
+void rtw_build_tdls_dis_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, u8 dialog)
+{
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct registry_priv *pregistrypriv = &padapter->registrypriv;
+
+ u8 category = RTW_WLAN_CATEGORY_PUBLIC;
+ u8 action = TDLS_DISCOVERY_RESPONSE;
+ u8 bssrate[NDIS_802_11_LENGTH_RATES_EX];
+ int bssrate_len = 0;
+ u8 more_supportedrates = 0;
+ u8 *p;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 link_id_addr[18] = {0};
+ u8 iedata=0;
+ u8 timeout_itvl[5]; //set timeout interval to maximum value
+ u32 timeout_interval= TPK_RESEND_COUNT * 1000;
+
+ //category, action, dialog token
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(dialog), &(pattrib->pktlen));
+
+ //capability
+ _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+
+ if(pattrib->encrypt)
+ *pframe =*pframe | BIT(4);
+ pframe += 2;
+ pattrib->pktlen += 2;
+
+ //supported rates
+ rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);
+ bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;
+
+ if (bssrate_len > 8)
+ {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
+ more_supportedrates = 1;
+ }
+ else
+ {
+ pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
+ }
+
+ //extended supported rates
+ if(more_supportedrates==1){
+ pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
+ }
+
+ //supported channels
+ pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
+
+ //RSNIE
+ if(pattrib->encrypt)
+ pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
+
+ //extended capability
+ pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen));
+
+ if(pattrib->encrypt){
+ //FTIE
+ _rtw_memset(pframe, 0, 84); //All fields shall be set to 0
+ _rtw_memset(pframe, _FTIE_, 1); //version
+ _rtw_memset((pframe+1), 82, 1); //length
+ pframe += 84;
+ pattrib->pktlen += 84;
+
+ //Timeout interval
+ timeout_itvl[0]=0x02;
+ _rtw_memcpy(timeout_itvl+1, &timeout_interval, 4);
+ pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
+ }
+
+ //Sup_reg_classes(optional)
+ //HT capabilities
+ pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib);
+
+ //20/40 BSS coexistence
+ if(pmlmepriv->num_FortyMHzIntolerant>0)
+ iedata |= BIT(2);//20 MHz BSS Width Request
+ pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
+
+ //Link identifier
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+}
+
+void rtw_build_tdls_peer_traffic_indication_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ u8 payload_type = 0x02;
+ unsigned char category = RTW_WLAN_CATEGORY_TDLS;
+ unsigned char action = TDLS_PEER_TRAFFIC_INDICATION;
+
+ u8 link_id_addr[18] = {0};
+ u8 AC_queue=0;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, reason code
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
+
+ //Link identifier
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+ //PTI control
+ //PU buffer status
+ if(ptdls_sta->uapsd_bk&BIT(1))
+ AC_queue=BIT(0);
+ if(ptdls_sta->uapsd_be&BIT(1))
+ AC_queue=BIT(1);
+ if(ptdls_sta->uapsd_vi&BIT(1))
+ AC_queue=BIT(2);
+ if(ptdls_sta->uapsd_vo&BIT(1))
+ AC_queue=BIT(3);
+ pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen));
+
+}
+
+void rtw_build_tdls_ch_switch_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+ u8 payload_type = 0x02;
+ unsigned char category = RTW_WLAN_CATEGORY_TDLS;
+ unsigned char action = TDLS_CHANNEL_SWITCH_REQUEST;
+ u8 link_id_addr[18] = {0};
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
+ u8 ch_switch_timing[4] = {0};
+ u16 switch_time= CH_SWITCH_TIME, switch_timeout=CH_SWITCH_TIMEOUT;
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, target_ch
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(ptdlsinfo->candidate_ch), &(pattrib->pktlen));
+
+ //Link identifier
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+ //ch switch timing
+ _rtw_memcpy(ch_switch_timing, &switch_time, 2);
+ _rtw_memcpy(ch_switch_timing+2, &switch_timeout, 2);
+ pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen));
+
+ //update ch switch attrib to sta_info
+ ptdls_sta->off_ch=ptdlsinfo->candidate_ch;
+ ptdls_sta->ch_switch_time=switch_time;
+ ptdls_sta->ch_switch_timeout=switch_timeout;
+
+}
+
+void rtw_build_tdls_ch_switch_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ u8 payload_type = 0x02;
+ unsigned char category = RTW_WLAN_CATEGORY_TDLS;
+ unsigned char action = TDLS_CHANNEL_SWITCH_RESPONSE;
+ u8 link_id_addr[18] = {0};
+ struct sta_priv *pstapriv = &padapter->stapriv;
+ struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+ u8 ch_switch_timing[4] = {0};
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, action, status_code
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
+
+ //Link identifier
+ _rtw_memcpy(link_id_addr, pattrib->ra, 6);
+ _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+ _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+ pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+
+ //ch switch timing
+ _rtw_memcpy(ch_switch_timing, &ptdls_sta->ch_switch_time, 2);
+ _rtw_memcpy(ch_switch_timing+2, &ptdls_sta->ch_switch_timeout, 2);
+ pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen));
+
+}
+
+#ifdef CONFIG_WFD
+void rtw_build_tunneled_probe_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
+ u8 payload_type = 0x02;
+ u8 category = RTW_WLAN_CATEGORY_P2P;
+ u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
+ u8 probe_req = 4;
+ u8 wfdielen = 0;
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, OUI, frame_body_type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen));
+
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
+ pframe += wfdielen;
+ pattrib->pktlen += wfdielen;
+ }
+ else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
+ {
+ wfdielen = build_probe_req_wfd_ie(pbuddy_wdinfo, pframe);
+ pframe += wfdielen;
+ pattrib->pktlen += wfdielen;
+ }
+
+}
+
+void rtw_build_tunneled_probe_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+ struct pkt_attrib *pattrib = &pxmitframe->attrib;
+ struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+ struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
+ u8 payload_type = 0x02;
+ u8 category = RTW_WLAN_CATEGORY_P2P;
+ u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
+ u8 probe_rsp = 5;
+ u8 wfdielen = 0;
+
+ //payload type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+ //category, OUI, frame_body_type
+ pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
+ pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen));
+
+ if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+ {
+ wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1);
+ pframe += wfdielen;
+ pattrib->pktlen += wfdielen;
+ }
+ else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
+ {
+ wfdielen = build_probe_resp_wfd_ie(pbuddy_wdinfo, pframe, 1);
+ pframe += wfdielen;
+ pattrib->pktlen += wfdielen;
+ }
+
+}
+#endif //CONFIG_WFD
+
+void _TPK_timer_hdl(void *FunctionContext)
+{
+ struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+
+ ptdls_sta->TPK_count++;
+ //TPK_timer set 1000 as default
+ //retry timer should set at least 301 sec.
+ if(ptdls_sta->TPK_count==TPK_RESEND_COUNT){
+ ptdls_sta->TPK_count=0;
+ issue_tdls_setup_req(ptdls_sta->padapter, ptdls_sta->hwaddr);
+ }
+
+ _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT);
+}
+
+void init_TPK_timer(_adapter *padapter, struct sta_info *psta)
+{
+ psta->padapter=padapter;
+
+ _init_timer(&psta->TPK_timer, padapter->pnetdev, _TPK_timer_hdl, psta);
+}
+
+// TDLS_DONE_CH_SEN: channel sensing and report candidate channel
+// TDLS_OFF_CH: first time set channel to off channel
+// TDLS_BASE_CH: when go back to the channel linked with AP, send null data to peer STA as an indication
+void _ch_switch_timer_hdl(void *FunctionContext)
+{
+
+ struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+ _adapter *padapter = ptdls_sta->padapter;
+
+ if( ptdls_sta->option == TDLS_DONE_CH_SEN ){
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_DONE_CH_SEN);
+ }else if( ptdls_sta->option == TDLS_OFF_CH ){
+ issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta, 0);
+ _set_timer(&ptdls_sta->base_ch_timer, 500);
+ }else if( ptdls_sta->option == TDLS_BASE_CH){
+ issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta, 0);
+ }
+}
+
+void init_ch_switch_timer(_adapter *padapter, struct sta_info *psta)
+{
+ psta->padapter=padapter;
+ _init_timer(&psta->option_timer, padapter->pnetdev, _ch_switch_timer_hdl, psta);
+}
+
+void _base_ch_timer_hdl(void *FunctionContext)
+{
+ struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+ rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_OFF_CH);
+}
+
+void init_base_ch_timer(_adapter *padapter, struct sta_info *psta)
+{
+ psta->padapter=padapter;
+ _init_timer(&psta->base_ch_timer, padapter->pnetdev, _base_ch_timer_hdl, psta);
+}
+
+void _off_ch_timer_hdl(void *FunctionContext)
+{
+ struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+ rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_BASE_CH );
+}
+
+void init_off_ch_timer(_adapter *padapter, struct sta_info *psta)
+{
+ psta->padapter=padapter;
+ _init_timer(&psta->off_ch_timer, padapter->pnetdev, _off_ch_timer_hdl, psta);
+}
+
+void _tdls_handshake_timer_hdl(void *FunctionContext)
+{
+ struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+
+ if(ptdls_sta != NULL)
+ {
+ if( !(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) )
+ {
+ DBG_871X("tdls handshake time out\n");
+ free_tdls_sta(ptdls_sta->padapter, ptdls_sta);
+ }
+ }
+}
+
+void init_handshake_timer(_adapter *padapter, struct sta_info *psta)
+{
+ psta->padapter=padapter;
+ _init_timer(&psta->handshake_timer, padapter->pnetdev, _tdls_handshake_timer_hdl, psta);
+}
+
+//Check tdls peer sta alive.
+void _tdls_alive_timer_phase1_hdl(void *FunctionContext)
+{
+ _irqL irqL;
+ struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+ _adapter *padapter = ptdls_sta->padapter;
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+ _enter_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
+ ptdls_sta->timer_flag = 1;
+ _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
+
+ ptdls_sta->tdls_sta_state &= (~TDLS_ALIVE_STATE);
+
+ DBG_871X("issue_tdls_dis_req to check alive\n");
+ issue_tdls_dis_req( padapter, ptdls_sta->hwaddr);
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH1);
+ sta_update_last_rx_pkts(ptdls_sta);
+
+ if ( ptdls_sta->timer_flag == 2 )
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_FREE_STA);
+ else
+ {
+ _enter_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
+ ptdls_sta->timer_flag = 0;
+ _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
+ }
+
+}
+
+void _tdls_alive_timer_phase2_hdl(void *FunctionContext)
+{
+ _irqL irqL;
+ struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+ _adapter *padapter = ptdls_sta->padapter;
+ struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+ _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
+ ptdls_sta->timer_flag = 1;
+ _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
+
+ if( (ptdls_sta->tdls_sta_state & TDLS_ALIVE_STATE) &&
+ (sta_last_rx_pkts(ptdls_sta) + 3 <= sta_rx_pkts(ptdls_sta)) )
+ {
+ DBG_871X("TDLS STA ALIVE, ptdls_sta->sta_stats.last_rx_pkts:%llu, ptdls_sta->sta_stats.rx_pkts:%llu\n",
+ sta_last_rx_pkts(ptdls_sta), sta_rx_pkts(ptdls_sta));
+
+ ptdls_sta->alive_count = 0;
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH2);
+ }
+ else
+ {
+ if( !(ptdls_sta->tdls_sta_state & TDLS_ALIVE_STATE) )
+ DBG_871X("TDLS STA TOO FAR\n");
+ if( !(sta_last_rx_pkts(ptdls_sta) + 3 <= sta_rx_pkts(ptdls_sta)))
+ DBG_871X("TDLS LINK WITH LOW TRAFFIC, ptdls_sta->sta_stats.last_rx_pkts:%llu, ptdls_sta->sta_stats.rx_pkts:%llu\n",
+ sta_last_rx_pkts(ptdls_sta), sta_rx_pkts(ptdls_sta));
+
+ ptdls_sta->alive_count++;
+ if( ptdls_sta->alive_count == TDLS_ALIVE_COUNT )
+ {
+ ptdls_sta->stat_code = _RSON_TDLS_TEAR_TOOFAR_;
+ issue_tdls_teardown(padapter, ptdls_sta->hwaddr);
+ }
+ else
+ {
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH2);
+ }
+ }
+
+ if ( ptdls_sta->timer_flag == 2 )
+ rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_FREE_STA);
+ else
+ {
+ _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
+ ptdls_sta->timer_flag = 0;
+ _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
+}
+
+}
+
+void init_tdls_alive_timer(_adapter *padapter, struct sta_info *psta)
+{
+ psta->padapter=padapter;
+ _init_timer(&psta->alive_timer1, padapter->pnetdev, _tdls_alive_timer_phase1_hdl, psta);
+ _init_timer(&psta->alive_timer2, padapter->pnetdev, _tdls_alive_timer_phase2_hdl, psta);
+}
+
+int update_sgi_tdls(_adapter *padapter, struct sta_info *psta)
+{
+ struct ht_priv *psta_ht = NULL;
+ psta_ht = &psta->htpriv;
+
+ if(psta_ht->ht_option)
+ {
+ return psta_ht->sgi;
+ }
+ else
+ return _FALSE;
+}
+
+u32 update_mask_tdls(_adapter *padapter, struct sta_info *psta)
+{
+ int i;
+ u8 rf_type, id;
+ unsigned char sta_band = 0;
+ unsigned char limit;
+ unsigned int tx_ra_bitmap=0;
+ struct ht_priv *psta_ht = NULL;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+ WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+
+ psta_ht = &psta->htpriv;
+ //b/g mode ra_bitmap
+ for (i=0; i<sizeof(psta->bssrateset); i++)
+ {
+ if (psta->bssrateset[i])
+ tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
+ }
+
+ //n mode ra_bitmap
+ if(psta_ht->ht_option)
+ {
+ padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+ if(rf_type == RF_2T2R)
+ limit=16;// 2R
+ else
+ limit=8;// 1R
+
+ for (i=0; i<limit; i++) {
+ if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8))
+ tx_ra_bitmap |= BIT(i+12);
+ }
+ }
+
+ if ( pcur_network->Configuration.DSConfig > 14 ) {
+ // 5G band
+ if (tx_ra_bitmap & 0xffff000)
+ sta_band |= WIRELESS_11_5N | WIRELESS_11A;
+ else
+ sta_band |= WIRELESS_11A;
+ } else {
+ if (tx_ra_bitmap & 0xffff000)
+ sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
+ else if (tx_ra_bitmap & 0xff0)
+ sta_band |= WIRELESS_11G |WIRELESS_11B;
+ else
+ sta_band |= WIRELESS_11B;
+ }
+
+ id = networktype_to_raid(sta_band);
+ tx_ra_bitmap |= ((id<<28)&0xf0000000);
+ return tx_ra_bitmap;
+}
+
+#endif //CONFIG_TDLS
+
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_wapi.c b/drivers/net/wireless/rtl8723as/core/rtw_wapi.c index 1d4e197a85db..6c6268c0a56f 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_wapi.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_wapi.c @@ -1,1326 +1,1326 @@ -#ifdef CONFIG_WAPI_SUPPORT - -#include <linux/unistd.h> -#include <linux/etherdevice.h> -#include <drv_types.h> -#include <rtw_wapi.h> - - -u32 wapi_debug_component = -// WAPI_INIT | -// WAPI_API | -// WAPI_TX | -// WAPI_RX | - WAPI_ERR ; //always open err flags on - -void WapiFreeAllStaInfo(_adapter *padapter) -{ - PRT_WAPI_T pWapiInfo; - PRT_WAPI_STA_INFO pWapiStaInfo; - PRT_WAPI_BKID pWapiBkid; - - WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); - pWapiInfo = &padapter->wapiInfo; - - //Pust to Idle List - rtw_wapi_return_all_sta_info(padapter); - - //Sta Info List - while(!list_empty(&(pWapiInfo->wapiSTAIdleList))) - { - pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list); - list_del_init(&pWapiStaInfo->list); - } - - //BKID List - while(!list_empty(&(pWapiInfo->wapiBKIDIdleList))) - { - pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list); - list_del_init(&pWapiBkid->list); - } - WAPI_TRACE(WAPI_INIT, "<=========== %s\n", __FUNCTION__); - return; -} - -void WapiSetIE(_adapter *padapter) -{ - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - //PRT_WAPI_BKID pWapiBkid; - u16 protocolVer = 1; - u16 akmCnt = 1; - u16 suiteCnt = 1; - u16 capability = 0; - u8 OUI[3]; - - OUI[0] = 0x00; - OUI[1] = 0x14; - OUI[2] = 0x72; - - pWapiInfo->wapiIELength = 0; -//protocol version - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &protocolVer, 2); - pWapiInfo->wapiIELength +=2; -//akm - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &akmCnt, 2); - pWapiInfo->wapiIELength +=2; - - if(pWapiInfo->bWapiPSK){ - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); - pWapiInfo->wapiIELength +=3; - pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x2; - pWapiInfo->wapiIELength +=1; - }else{ - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); - pWapiInfo->wapiIELength +=3; - pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1; - pWapiInfo->wapiIELength +=1; - } - -//usk - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &suiteCnt, 2); - pWapiInfo->wapiIELength +=2; - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); - pWapiInfo->wapiIELength +=3; - pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1; - pWapiInfo->wapiIELength +=1; - -//msk - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); - pWapiInfo->wapiIELength +=3; - pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1; - pWapiInfo->wapiIELength +=1; - -//Capbility - memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &capability, 2); - pWapiInfo->wapiIELength +=2; -} - - -/* PN1 > PN2, return 1, - * else return 0. - */ -u32 WapiComparePN(u8 *PN1, u8 *PN2) -{ - char i; - - if ((NULL == PN1) || (NULL == PN2)) - return 1; - - // overflow case - if ((PN2[15] - PN1[15]) & 0x80) - return 1; - - for (i=16; i>0; i--) - { - if(PN1[i-1] == PN2[i-1]) - continue; - else if(PN1[i-1] > PN2[i-1]) - return 1; - else - return 0; - } - - return 0; -} - -u8 -WapiGetEntryForCamWrite(_adapter *padapter,u8 *pMacAddr,u8 KID,BOOLEAN IsMsk) -{ - PRT_WAPI_T pWapiInfo=NULL; - //PRT_WAPI_CAM_ENTRY pEntry=NULL; - u8 i=0; - u8 ret = 0xff; - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - pWapiInfo = &padapter->wapiInfo; - - //exist? - for(i=0;i<WAPI_CAM_ENTRY_NUM;i++) - { - if(pWapiInfo->wapiCamEntry[i].IsUsed - && (_rtw_memcmp(pMacAddr, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN) == _TRUE) - && pWapiInfo->wapiCamEntry[i].keyidx == KID - && pWapiInfo->wapiCamEntry[i].type == IsMsk) - { - ret = pWapiInfo->wapiCamEntry[i].entry_idx; //cover it - break; - } - } - - if(i == WAPI_CAM_ENTRY_NUM) //not found - { - for(i=0;i<WAPI_CAM_ENTRY_NUM;i++) - { - if(pWapiInfo->wapiCamEntry[i].IsUsed == 0) - { - pWapiInfo->wapiCamEntry[i].IsUsed = 1; - pWapiInfo->wapiCamEntry[i].type = IsMsk; - pWapiInfo->wapiCamEntry[i].keyidx = KID; - _rtw_memcpy(pWapiInfo->wapiCamEntry[i].PeerMacAddr, pMacAddr,ETH_ALEN); - ret = pWapiInfo->wapiCamEntry[i].entry_idx; - break; - } - } - } - - WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); - return ret; - -/* - if(RTIsListEmpty(&pWapiInfo->wapiCamIdleList)){ - RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n")); - return 0; - } - - pEntry = (PRT_WAPI_CAM_ENTRY)RTRemoveHeadList(&pWapiInfo->wapiCamIdleList); - RTInsertTailList(&pWapiInfo->wapiCamUsedList, &pEntry->list); - - RT_TRACE(COMP_SEC,DBG_LOUD,("<====WapiGetCamEntry(),Get Entry Idx:%d.but we just return 4 for test\n",pEntry->entry_idx)); - - return pEntry->entry_idx;*/ -} - -u8 WapiGetEntryForCamClear(_adapter *padapter,u8 *pPeerMac,u8 keyid,u8 IsMsk) -{ - PRT_WAPI_T pWapiInfo=NULL; - u8 i=0; - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - pWapiInfo = &padapter->wapiInfo; - - for(i=0;i<WAPI_CAM_ENTRY_NUM;i++) - { - if(pWapiInfo->wapiCamEntry[i].IsUsed - && (_rtw_memcmp(pPeerMac, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN) == _TRUE) - && pWapiInfo->wapiCamEntry[i].keyidx == keyid - && pWapiInfo->wapiCamEntry[i].type == IsMsk) - { - pWapiInfo->wapiCamEntry[i].IsUsed = 0; - pWapiInfo->wapiCamEntry[i].keyidx = 2; - _rtw_memset(pWapiInfo->wapiCamEntry[i].PeerMacAddr,0,ETH_ALEN); - - WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); - return pWapiInfo->wapiCamEntry[i].entry_idx; - } - } - - WAPI_TRACE(WAPI_API,"<====WapiGetReturnCamEntry(), No this cam entry.\n"); - return 0xff; -/* - if(RTIsListEmpty(&pWapiInfo->wapiCamUsedList)){ - RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n")); - return FALSE; - } - - pList = &pWapiInfo->wapiCamUsedList; - while(pList->Flink != &pWapiInfo->wapiCamUsedList) - { - pEntry = (PRT_WAPI_CAM_ENTRY)pList->Flink; - if(PlatformCompareMemory(pPeerMac,pEntry->PeerMacAddr, ETHER_ADDRLEN)== 0 - && keyid == pEntry->keyidx) - { - RTRemoveEntryList(pList); - RTInsertHeadList(&pWapiInfo->wapiCamIdleList, pList); - return pEntry->entry_idx; - } - pList = pList->Flink; - } - - return 0; -*/ -} - -void -WapiResetAllCamEntry(_adapter *padapter) -{ - PRT_WAPI_T pWapiInfo; - int i; - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - pWapiInfo = &padapter->wapiInfo; - - for (i=0;i<WAPI_CAM_ENTRY_NUM;i++) - { - _rtw_memset(pWapiInfo->wapiCamEntry[i].PeerMacAddr, 0, ETH_ALEN); - pWapiInfo->wapiCamEntry[i].IsUsed = 0; - pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid - pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2; - } - - WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); - - return; -} - -u8 WapiWriteOneCamEntry( - _adapter *padapter, - u8 *pMacAddr, - u8 KeyId, - u8 EntryId, - u8 EncAlg, - u8 bGroupKey, - u8 *pKey -) -{ - u8 retVal = 0; - u16 usConfig = 0; - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - if(EntryId >= 32) - { - WAPI_TRACE(WAPI_ERR, "<=== CamAddOneEntry(): ulKeyId exceed!\n"); - return retVal; - } - - usConfig=usConfig|(0x01<<15)|((u16)(EncAlg)<<2)|(KeyId); - - if(EncAlg == _SMS4_ ) - { - if(bGroupKey == 1) - usConfig |= (0x01<<6); - if((EntryId % 2)==1) // ==0 sec key; == 1mic key - usConfig |= (0x01<<5); - } - - write_cam(padapter, EntryId, usConfig, pMacAddr, pKey); - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - return 1; -} - -void rtw_wapi_init(_adapter *padapter) -{ - PRT_WAPI_T pWapiInfo; - int i; - - WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); - RT_ASSERT_RET(padapter); - - if (!padapter->WapiSupport) - { - WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__); - return; - } - - pWapiInfo = &padapter->wapiInfo; - pWapiInfo->bWapiEnable = false; - - //Init BKID List - INIT_LIST_HEAD(&pWapiInfo->wapiBKIDIdleList); - INIT_LIST_HEAD(&pWapiInfo->wapiBKIDStoreList); - for(i=0;i<WAPI_MAX_BKID_NUM;i++) - { - list_add_tail(&pWapiInfo->wapiBKID[i].list, &pWapiInfo->wapiBKIDIdleList); - } - - //Init STA List - INIT_LIST_HEAD(&pWapiInfo->wapiSTAIdleList); - INIT_LIST_HEAD(&pWapiInfo->wapiSTAUsedList); - for(i=0;i<WAPI_MAX_STAINFO_NUM;i++) - { - list_add_tail(&pWapiInfo->wapiSta[i].list, &pWapiInfo->wapiSTAIdleList); - } - - for (i=0;i<WAPI_CAM_ENTRY_NUM;i++) - { - pWapiInfo->wapiCamEntry[i].IsUsed = 0; - pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid - pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2; - } - - WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__); -} - -void rtw_wapi_free(_adapter *padapter) -{ - WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); - RT_ASSERT_RET(padapter); - - if (!padapter->WapiSupport) - { - WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__); - return; - } - - WapiFreeAllStaInfo(padapter); - - WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__); -} - -void rtw_wapi_disable_tx(_adapter *padapter) -{ - WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); - RT_ASSERT_RET(padapter); - - if (!padapter->WapiSupport) - { - WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__); - return; - } - - padapter->wapiInfo.wapiTxMsk.bTxEnable = false; - padapter->wapiInfo.wapiTxMsk.bSet = false; - - WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__); -} - -u8 rtw_wapi_is_wai_packet(_adapter* padapter,u8 *pkt_data) -{ - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - PRT_WAPI_STA_INFO pWapiSta = NULL; - u8 WaiPkt = 0, *pTaddr, bFind = false; - u8 Offset_TypeWAI = 0 ; // (mac header len + llc length) - - WAPI_TRACE(WAPI_TX|WAPI_RX, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return 0; - } - - Offset_TypeWAI = 24 + 6 ; - - //YJ,add,091103. Data frame may also have skb->data[30]=0x88 and skb->data[31]=0xb4. - if ((pkt_data[1]&0x40) !=0) - { - DBG_871X("data is privacy \n"); - return 0; - } - - pTaddr = GetAddr2Ptr(pkt_data); - if(list_empty(&pWapiInfo->wapiSTAUsedList)){ - bFind = false; - }else{ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){ - if (_rtw_memcmp(pTaddr, pWapiSta->PeerMacAddr, 6) == _TRUE) { - bFind = true; - break; - } - } - } - - WAPI_TRACE(WAPI_TX|WAPI_RX, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(pTaddr)); - - if (pkt_data[0] == WIFI_QOS_DATA_TYPE) - { - Offset_TypeWAI += 2; - } - - // 88b4? - if( (pkt_data[Offset_TypeWAI]==0x88) && (pkt_data[Offset_TypeWAI+1]==0xb4) ){ - WaiPkt = pkt_data[Offset_TypeWAI+5]; - - psecuritypriv->hw_decrypted = _TRUE; - }else{ - WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): non wai packet\n",__FUNCTION__); - } - - WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): Recvd WAI frame. IsWAIPkt(%d)\n",__FUNCTION__, WaiPkt); - - return WaiPkt; -} - - -void rtw_wapi_update_info(_adapter *padapter, union recv_frame *precv_frame) -{ - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - struct recv_frame_hdr *precv_hdr; - u8 *ptr; - u8 *pTA; - u8 *pRecvPN; - - - WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return; - } - - precv_hdr = &precv_frame->u.hdr; - ptr = precv_hdr->rx_data; - - if (precv_hdr->attrib.qos == 1) - { - precv_hdr->UserPriority = GetTid(ptr); - } - else - { - precv_hdr->UserPriority = 0; - } - - pTA = GetAddr2Ptr(ptr); - _rtw_memcpy((u8 *)precv_hdr->WapiSrcAddr, pTA, 6); - pRecvPN = ptr + precv_hdr->attrib.hdrlen + 2; - _rtw_memcpy((u8 *)precv_hdr->WapiTempPN, pRecvPN, 16); - - WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__); -} - -/**************************************************************************** -TRUE-----------------Drop -FALSE---------------- handle -add to support WAPI to N-mode -*****************************************************************************/ -u8 rtw_wapi_check_for_drop( - _adapter *padapter, - union recv_frame *precv_frame -) -{ - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - u8 *pLastRecvPN = NULL; - u8 bFind = false; - PRT_WAPI_STA_INFO pWapiSta = NULL; - u8 bDrop = false; - struct recv_frame_hdr *precv_hdr = &precv_frame->u.hdr; - u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - u8 *ptr = precv_frame->u.hdr.rx_data; - int i; - - WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return false; - } - - if(precv_hdr->bIsWaiPacket !=0) - { - if(precv_hdr->bIsWaiPacket== 0x8) - { - - DBG_871X("rtw_wapi_check_for_drop: dump packet \n"); - for(i=0;i<50;i++) - { - DBG_871X("%02X ",ptr[i]); - if((i+1) %8 ==0) - DBG_871X("\n"); - } - DBG_871X("\n rtw_wapi_check_for_drop: dump packet \n"); - - for(i=0;i<16;i++) - { - if(ptr[i+27] !=0) - break; - } - - if(i== 16) - { - WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: drop with zero BKID \n"); - return true; - } - else - { - return false; - } - } - else - return false; - } - - if(list_empty(&pWapiInfo->wapiSTAUsedList)){ - bFind = false; - }else{ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { - if (_rtw_memcmp(precv_hdr->WapiSrcAddr, pWapiSta->PeerMacAddr, ETH_ALEN) == _TRUE) { - bFind = true; - break; - } - } - } - WAPI_TRACE(WAPI_RX, "%s: bFind=%d prxb->WapiSrcAddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(precv_hdr->WapiSrcAddr)); - - if(bFind) - { - if(IS_MCAST(precv_hdr->attrib.ra)) - { - WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: multicast case \n"); - pLastRecvPN = pWapiSta->lastRxMulticastPN; - } - else - { - WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: unicast case \n"); - switch(precv_hdr->UserPriority) - { - case 0: - case 3: - pLastRecvPN = pWapiSta->lastRxUnicastPNBEQueue; - break; - case 1: - case 2: - pLastRecvPN = pWapiSta->lastRxUnicastPNBKQueue; - break; - case 4: - case 5: - pLastRecvPN = pWapiSta->lastRxUnicastPNVIQueue; - break; - case 6: - case 7: - pLastRecvPN = pWapiSta->lastRxUnicastPNVOQueue; - break; - default: - WAPI_TRACE(WAPI_ERR,"%s: Unknown TID \n",__FUNCTION__); - break; - } - } - - if(!WapiComparePN(precv_hdr->WapiTempPN,pLastRecvPN)) - { - WAPI_TRACE(WAPI_RX,"%s: Equal PN!!\n",__FUNCTION__); - if(IS_MCAST(precv_hdr->attrib.ra)) - _rtw_memcpy(pLastRecvPN,WapiAEMultiCastPNInitialValueSrc,16); - else - _rtw_memcpy(pLastRecvPN,WapiAEPNInitialValueSrc,16); - bDrop = true; - } - else - { - _rtw_memcpy(pLastRecvPN,precv_hdr->WapiTempPN,16); - } - } - - WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__); - return bDrop; -} - -void rtw_build_probe_resp_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib) -{ - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - u8 WapiIELength = 0; - - WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__); - return; - } - - WapiSetIE(padapter); - WapiIELength = pWapiInfo->wapiIELength; - pframe[0] = _WAPI_IE_; - pframe[1] = WapiIELength; - _rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength); - pframe += WapiIELength+2; - pattrib->pktlen += WapiIELength+2; - - WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__); -} - -void rtw_build_beacon_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib) -{ - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - u8 WapiIELength = 0; - WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__); - return; - } - - WapiSetIE(padapter); - WapiIELength = pWapiInfo->wapiIELength; - pframe[0] = _WAPI_IE_; - pframe[1] = WapiIELength; - _rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength); - pframe += WapiIELength+2; - pattrib->pktlen += WapiIELength+2; - - WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__); -} - -void rtw_build_assoc_req_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib) -{ - PRT_WAPI_BKID pWapiBKID; - u16 bkidNum; - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - u8 WapiIELength = 0; - - WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__); - return; - } - - WapiSetIE(padapter); - WapiIELength = pWapiInfo->wapiIELength; - bkidNum = 0; - if(!list_empty(&(pWapiInfo->wapiBKIDStoreList))){ - list_for_each_entry(pWapiBKID, &pWapiInfo->wapiBKIDStoreList, list) { - bkidNum ++; - _rtw_memcpy(pWapiInfo->wapiIE+WapiIELength+2, pWapiBKID->bkid,16); - WapiIELength += 16; - } - } - _rtw_memcpy(pWapiInfo->wapiIE+WapiIELength, &bkidNum, 2); - WapiIELength += 2; - - pframe[0] = _WAPI_IE_; - pframe[1] = WapiIELength; - _rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength); - pframe += WapiIELength+2; - pattrib->pktlen += WapiIELength+2; - WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__); -} - -void rtw_wapi_on_assoc_ok(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE) -{ - PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo); - PRT_WAPI_STA_INFO pWapiSta; - u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - //u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - - WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return; - } - - pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list); - list_del_init(&pWapiSta->list); - list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList); - _rtw_memcpy(pWapiSta->PeerMacAddr,padapter->mlmeextpriv.mlmext_info.network.MacAddress,6); - _rtw_memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16); - _rtw_memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16); - - //For chenk PN error with Qos Data after s3: add by ylb 20111114 - _rtw_memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16); - _rtw_memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16); - _rtw_memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16); - _rtw_memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16); - - WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__); -} - - -void rtw_wapi_return_one_sta_info(_adapter *padapter, u8 *MacAddr) -{ - PRT_WAPI_T pWapiInfo; - PRT_WAPI_STA_INFO pWapiStaInfo = NULL; - PRT_WAPI_BKID pWapiBkid = NULL; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - pWapiInfo = &padapter->wapiInfo; - - WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return; - } - - if(check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - { - while(!list_empty(&(pWapiInfo->wapiBKIDStoreList))) - { - pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list); - list_del_init(&pWapiBkid->list); - _rtw_memset(pWapiBkid->bkid,0,16); - list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList); - } - } - - - WAPI_TRACE(WAPI_API, " %s: after clear bkid \n", __FUNCTION__); - - - //Remove STA info - if(list_empty(&(pWapiInfo->wapiSTAUsedList))){ - WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is null \n", __FUNCTION__); - return; - }else{ - - WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is not null \n", __FUNCTION__); -#if 0 - pWapiStaInfo=(PRT_WAPI_STA_INFO)list_entry((pWapiInfo->wapiSTAUsedList.next),RT_WAPI_STA_INFO,list); - - list_for_each_entry(pWapiStaInfo, &(pWapiInfo->wapiSTAUsedList), list) { - - DBG_871X("MAC Addr %02x-%02x-%02x-%02x-%02x-%02x \n",MacAddr[0],MacAddr[1],MacAddr[2],MacAddr[3],MacAddr[4],MacAddr[5]); - - - DBG_871X("peer Addr %02x-%02x-%02x-%02x-%02x-%02x \n",pWapiStaInfo->PeerMacAddr[0],pWapiStaInfo->PeerMacAddr[1],pWapiStaInfo->PeerMacAddr[2],pWapiStaInfo->PeerMacAddr[3],pWapiStaInfo->PeerMacAddr[4],pWapiStaInfo->PeerMacAddr[5]); - - if(pWapiStaInfo == NULL) - { - WAPI_TRACE(WAPI_API, " %s: pWapiStaInfo == NULL Case \n", __FUNCTION__); - return; - } - - if(pWapiStaInfo->PeerMacAddr == NULL) - { - WAPI_TRACE(WAPI_API, " %s: pWapiStaInfo->PeerMacAddr == NULL Case \n", __FUNCTION__); - return; - } - - if(MacAddr == NULL) - { - WAPI_TRACE(WAPI_API, " %s: MacAddr == NULL Case \n", __FUNCTION__); - return; - } - - if (_rtw_memcmp(pWapiStaInfo->PeerMacAddr, MacAddr, ETH_ALEN) == _TRUE) { - pWapiStaInfo->bAuthenticateInProgress = false; - pWapiStaInfo->bSetkeyOk = false; - _rtw_memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN); - list_del_init(&pWapiStaInfo->list); - list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList); - break; - } - - } -#endif - - while(!list_empty(&(pWapiInfo->wapiSTAUsedList))) - { - pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list); - - DBG_871X("peer Addr %02x-%02x-%02x-%02x-%02x-%02x \n",pWapiStaInfo->PeerMacAddr[0],pWapiStaInfo->PeerMacAddr[1],pWapiStaInfo->PeerMacAddr[2],pWapiStaInfo->PeerMacAddr[3],pWapiStaInfo->PeerMacAddr[4],pWapiStaInfo->PeerMacAddr[5]); - - list_del_init(&pWapiStaInfo->list); - memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN); - pWapiStaInfo->bSetkeyOk = 0; - list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList); - } - - } - - WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); - return; -} - -void rtw_wapi_return_all_sta_info(_adapter *padapter) -{ - PRT_WAPI_T pWapiInfo; - PRT_WAPI_STA_INFO pWapiStaInfo; - PRT_WAPI_BKID pWapiBkid; - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - pWapiInfo = &padapter->wapiInfo; - - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return; - } - - //Sta Info List - while(!list_empty(&(pWapiInfo->wapiSTAUsedList))) - { - pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list); - list_del_init(&pWapiStaInfo->list); - memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN); - pWapiStaInfo->bSetkeyOk = 0; - list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList); - } - - //BKID List - while(!list_empty(&(pWapiInfo->wapiBKIDStoreList))) - { - pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list); - list_del_init(&pWapiBkid->list); - memset(pWapiBkid->bkid,0,16); - list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList); - } - WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); -} - -void rtw_wapi_clear_cam_entry(_adapter *padapter, u8 *pMacAddr) -{ - u8 UcIndex = 0; - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return; - } - - UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 0); - if(UcIndex != 0xff){ - //CAM_mark_invalid(Adapter, UcIndex); - CAM_empty_entry(padapter, UcIndex); - } - - UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 0); - if(UcIndex != 0xff){ - //CAM_mark_invalid(Adapter, UcIndex); - CAM_empty_entry(padapter, UcIndex); - } - - UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 1); - if(UcIndex != 0xff){ - //CAM_mark_invalid(Adapter, UcIndex); - CAM_empty_entry(padapter, UcIndex); - } - - UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 1); - if(UcIndex != 0xff){ - //CAM_mark_invalid(padapter, UcIndex); - CAM_empty_entry(padapter, UcIndex); - } - - WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); -} - -void rtw_wapi_clear_all_cam_entry(_adapter *padapter) -{ - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable)) - { - WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return; - } - - invalidate_cam_all(padapter); // is this ok? - WapiResetAllCamEntry(padapter); - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); -} - -void rtw_wapi_set_key(_adapter *padapter, RT_WAPI_KEY *pWapiKey, RT_WAPI_STA_INFO *pWapiSta, u8 bGroupKey, u8 bUseDefaultKey) -{ - PRT_WAPI_T pWapiInfo = &padapter->wapiInfo; - u8 *pMacAddr = pWapiSta->PeerMacAddr; - u32 EntryId = 0; - BOOLEAN IsPairWise = false ; - u8 EncAlgo; - - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable)) - { - WAPI_TRACE(WAPI_API, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__); - return; - } - - EncAlgo = _SMS4_; - - //For Tx bc/mc pkt,use defualt key entry - if(bUseDefaultKey) - { - // when WAPI update key, keyid will be 0 or 1 by turns. - if (pWapiKey->keyId == 0) - EntryId = 0; - else - EntryId = 2; - } - else - { - // tx/rx unicast pkt, or rx broadcast, find the key entry by peer's MacAddr - EntryId = WapiGetEntryForCamWrite(padapter,pMacAddr,pWapiKey->keyId,bGroupKey); - } - - if(EntryId == 0xff){ - WAPI_TRACE(WAPI_API, "===>No entry for WAPI setkey! !!\n"); - return; - } - - //EntryId is also used to diff Sec key and Mic key - //Sec Key - WapiWriteOneCamEntry(padapter, - pMacAddr, - pWapiKey->keyId, //keyid - EntryId, //entry - EncAlgo, //type - bGroupKey, //pairwise or group key - pWapiKey->dataKey); - //MIC key - WapiWriteOneCamEntry(padapter, - pMacAddr, - pWapiKey->keyId, //keyid - EntryId+1, //entry - EncAlgo, //type - bGroupKey, //pairwise or group key - pWapiKey->micKey); - - WAPI_TRACE(WAPI_API, "Set Wapi Key :KeyId:%d,EntryId:%d,PairwiseKey:%d.\n",pWapiKey->keyId,EntryId,!bGroupKey); - WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__); - -} - -#if 0 -//YJ,test,091013 -void wapi_test_set_key(struct _adapter *padapter, u8* buf) -{ /*Data: keyType(1) + bTxEnable(1) + bAuthenticator(1) + bUpdate(1) + PeerAddr(6) + DataKey(16) + MicKey(16) + KeyId(1)*/ - PRT_WAPI_T pWapiInfo = &padapter->wapiInfo; - PRT_WAPI_BKID pWapiBkid; - PRT_WAPI_STA_INFO pWapiSta; - u8 data[43]; - bool bTxEnable; - bool bUpdate; - bool bAuthenticator; - u8 PeerAddr[6]; - u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; - - WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__); - - if (!padapter->WapiSupport){ - return; - } - - copy_from_user(data, buf, 43); - bTxEnable = data[1]; - bAuthenticator = data[2]; - bUpdate = data[3]; - memcpy(PeerAddr,data+4,6); - - if(data[0] == 0x3){ - if(!list_empty(&(pWapiInfo->wapiBKIDIdleList))){ - pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list); - list_del_init(&pWapiBkid->list); - memcpy(pWapiBkid->bkid, data+10, 16); - WAPI_DATA(WAPI_INIT, "SetKey - BKID", pWapiBkid->bkid, 16); - list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDStoreList); - } - }else{ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { - if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){ - pWapiSta->bAuthenticatorInUpdata = false; - switch(data[0]){ - case 1: //usk - if(bAuthenticator){ //authenticator - memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16); - if(!bUpdate) { //first - WAPI_TRACE(WAPI_INIT,"AE fisrt set usk \n"); - pWapiSta->wapiUsk.bSet = true; - memcpy(pWapiSta->wapiUsk.dataKey,data+10,16); - memcpy(pWapiSta->wapiUsk.micKey,data+26,16); - pWapiSta->wapiUsk.keyId = *(data+42); - pWapiSta->wapiUsk.bTxEnable = true; - WAPI_DATA(WAPI_INIT, "SetKey - AE USK Data Key", pWapiSta->wapiUsk.dataKey, 16); - WAPI_DATA(WAPI_INIT, "SetKey - AE USK Mic Key", pWapiSta->wapiUsk.micKey, 16); - } - else //update - { - WAPI_TRACE(WAPI_INIT, "AE update usk \n"); - pWapiSta->wapiUskUpdate.bSet = true; - pWapiSta->bAuthenticatorInUpdata = true; - memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16); - memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16); - memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16); - pWapiSta->wapiUskUpdate.keyId = *(data+42); - pWapiSta->wapiUskUpdate.bTxEnable = true; - } - } - else{ - if(!bUpdate){ - WAPI_TRACE(WAPI_INIT,"ASUE fisrt set usk \n"); - if(bTxEnable){ - pWapiSta->wapiUsk.bTxEnable = true; - memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16); - }else{ - pWapiSta->wapiUsk.bSet = true; - memcpy(pWapiSta->wapiUsk.dataKey,data+10,16); - memcpy(pWapiSta->wapiUsk.micKey,data+26,16); - pWapiSta->wapiUsk.keyId = *(data+42); - pWapiSta->wapiUsk.bTxEnable = false; - } - }else{ - WAPI_TRACE(WAPI_INIT,"ASUE update usk \n"); - if(bTxEnable){ - pWapiSta->wapiUskUpdate.bTxEnable = true; - if(pWapiSta->wapiUskUpdate.bSet){ - memcpy(pWapiSta->wapiUsk.dataKey,pWapiSta->wapiUskUpdate.dataKey,16); - memcpy(pWapiSta->wapiUsk.micKey,pWapiSta->wapiUskUpdate.micKey,16); - pWapiSta->wapiUsk.keyId=pWapiSta->wapiUskUpdate.keyId; - memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16); - memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16); - pWapiSta->wapiUskUpdate.bTxEnable = false; - pWapiSta->wapiUskUpdate.bSet = false; - } - memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16); - }else{ - pWapiSta->wapiUskUpdate.bSet = true; - memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16); - memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16); - pWapiSta->wapiUskUpdate.keyId = *(data+42); - pWapiSta->wapiUskUpdate.bTxEnable = false; - } - } - } - break; - case 2: //msk - if(bAuthenticator){ //authenticator - pWapiInfo->wapiTxMsk.bSet = true; - memcpy(pWapiInfo->wapiTxMsk.dataKey,data+10,16); - memcpy(pWapiInfo->wapiTxMsk.micKey,data+26,16); - pWapiInfo->wapiTxMsk.keyId = *(data+42); - pWapiInfo->wapiTxMsk.bTxEnable = true; - memcpy(pWapiInfo->lastTxMulticastPN,WapiAEMultiCastPNInitialValueSrc,16); - - if(!bUpdate){ //first - WAPI_TRACE(WAPI_INIT, "AE fisrt set msk \n"); - if(!pWapiSta->bSetkeyOk) - pWapiSta->bSetkeyOk = true; - pWapiInfo->bFirstAuthentiateInProgress= false; - }else{ //update - WAPI_TRACE(WAPI_INIT,"AE update msk \n"); - } - - WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Data Key", pWapiInfo->wapiTxMsk.dataKey, 16); - WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Mic Key", pWapiInfo->wapiTxMsk.micKey, 16); - } - else{ - if(!bUpdate){ - WAPI_TRACE(WAPI_INIT,"ASUE fisrt set msk \n"); - pWapiSta->wapiMsk.bSet = true; - memcpy(pWapiSta->wapiMsk.dataKey,data+10,16); - memcpy(pWapiSta->wapiMsk.micKey,data+26,16); - pWapiSta->wapiMsk.keyId = *(data+42); - pWapiSta->wapiMsk.bTxEnable = false; - if(!pWapiSta->bSetkeyOk) - pWapiSta->bSetkeyOk = true; - pWapiInfo->bFirstAuthentiateInProgress= false; - WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Data Key", pWapiSta->wapiMsk.dataKey, 16); - WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Mic Key", pWapiSta->wapiMsk.micKey, 16); - }else{ - WAPI_TRACE(WAPI_INIT,"ASUE update msk \n"); - pWapiSta->wapiMskUpdate.bSet = true; - memcpy(pWapiSta->wapiMskUpdate.dataKey,data+10,16); - memcpy(pWapiSta->wapiMskUpdate.micKey,data+26,16); - pWapiSta->wapiMskUpdate.keyId = *(data+42); - pWapiSta->wapiMskUpdate.bTxEnable = false; - } - } - break; - default: - WAPI_TRACE(WAPI_ERR,"Unknown Flag \n"); - break; - } - } - } - } - WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__); -} - - -void wapi_test_init(struct _adapter *padapter) -{ - u8 keybuf[100]; - u8 mac_addr[6]={0x00,0xe0,0x4c,0x72,0x04,0x70}; - u8 UskDataKey[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; - u8 UskMicKey[16]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f}; - u8 UskId = 0; - u8 MskDataKey[16]={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f}; - u8 MskMicKey[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f}; - u8 MskId = 0; - - WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__); - - //Enable Wapi - WAPI_TRACE(WAPI_INIT, "%s: Enable wapi!!!!\n", __FUNCTION__); - padapter->wapiInfo.bWapiEnable = true; - padapter->pairwise_key_type = KEY_TYPE_SMS4; - ieee->group_key_type = KEY_TYPE_SMS4; - padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN; - padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN; - - //set usk - WAPI_TRACE(WAPI_INIT, "%s: Set USK!!!!\n", __FUNCTION__); - memset(keybuf,0,100); - keybuf[0] = 1; //set usk - keybuf[1] = 1; //enable tx - keybuf[2] = 1; //AE - keybuf[3] = 0; //not update - - memcpy(keybuf+4,mac_addr,6); - memcpy(keybuf+10,UskDataKey,16); - memcpy(keybuf+26,UskMicKey,16); - keybuf[42]=UskId; - wapi_test_set_key(padapter, keybuf); - - memset(keybuf,0,100); - keybuf[0] = 1; //set usk - keybuf[1] = 1; //enable tx - keybuf[2] = 0; //AE - keybuf[3] = 0; //not update - - memcpy(keybuf+4,mac_addr,6); - memcpy(keybuf+10,UskDataKey,16); - memcpy(keybuf+26,UskMicKey,16); - keybuf[42]=UskId; - wapi_test_set_key(padapter, keybuf); - - //set msk - WAPI_TRACE(WAPI_INIT, "%s: Set MSK!!!!\n", __FUNCTION__); - memset(keybuf,0,100); - keybuf[0] = 2; //set msk - keybuf[1] = 1; //Enable TX - keybuf[2] = 1; //AE - keybuf[3] = 0; //not update - memcpy(keybuf+4,mac_addr,6); - memcpy(keybuf+10,MskDataKey,16); - memcpy(keybuf+26,MskMicKey,16); - keybuf[42] = MskId; - wapi_test_set_key(padapter, keybuf); - - memset(keybuf,0,100); - keybuf[0] = 2; //set msk - keybuf[1] = 1; //Enable TX - keybuf[2] = 0; //AE - keybuf[3] = 0; //not update - memcpy(keybuf+4,mac_addr,6); - memcpy(keybuf+10,MskDataKey,16); - memcpy(keybuf+26,MskMicKey,16); - keybuf[42] = MskId; - wapi_test_set_key(padapter, keybuf); - WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__); -} -#endif - -void rtw_wapi_get_iv(_adapter *padapter,u8 *pRA, u8*IV) -{ - PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL; - PRT_WAPI_T pWapiInfo = &padapter->wapiInfo; - bool bPNOverflow = false; - bool bFindMatchPeer = false; - PRT_WAPI_STA_INFO pWapiSta = NULL; - - pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)IV; - - WAPI_DATA(WAPI_RX,"wapi_get_iv: pra",pRA,6); - - if(IS_MCAST(pRA)){ - if(!pWapiInfo->wapiTxMsk.bTxEnable){ - WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__); - return; - } - - if(pWapiInfo->wapiTxMsk.keyId <= 1){ - pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId; - pWapiExt->Reserved = 0; - bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1); - memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16); - } - } - else - { - if(list_empty(&pWapiInfo->wapiSTAUsedList)){ - WAPI_TRACE(WAPI_RX,"rtw_wapi_get_iv: list is empty \n"); - _rtw_memset(IV,10,18); - return; - } - else{ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){ - WAPI_DATA(WAPI_RX,"rtw_wapi_get_iv: peermacaddr ",pWapiSta->PeerMacAddr,6); - if (_rtw_memcmp((u8*)pWapiSta->PeerMacAddr, pRA, 6) == _TRUE) { - bFindMatchPeer = true; - break; - } - } - - WAPI_TRACE(WAPI_RX,"bFindMatchPeer: %d \n",bFindMatchPeer); - WAPI_DATA(WAPI_RX,"Addr",pRA,6); - - if (bFindMatchPeer){ - if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable)) - return; - - if (pWapiSta->wapiUsk.keyId <= 1){ - if(pWapiSta->wapiUskUpdate.bTxEnable) - pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId; - else - pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId; - - pWapiExt->Reserved = 0; - bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2); - _rtw_memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16); - - } - } - } - - } - -} - -bool rtw_wapi_drop_for_key_absent(_adapter *padapter,u8 *pRA) -{ - PRT_WAPI_T pWapiInfo = &padapter->wapiInfo; - bool bFindMatchPeer = false; - bool bDrop = false; - PRT_WAPI_STA_INFO pWapiSta = NULL; - struct security_priv *psecuritypriv = &padapter->securitypriv; - - WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: ra ",pRA,6); - - if(psecuritypriv->dot11PrivacyAlgrthm == _SMS4_) - { - if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable)) - return true; - - if(IS_MCAST(pRA)){ - if(!pWapiInfo->wapiTxMsk.bTxEnable){ - bDrop = true; - WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: multicast key is absent \n"); - return bDrop; - } - } - else{ - if(!list_empty(&pWapiInfo->wapiSTAUsedList)){ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){ - WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: pWapiSta->PeerMacAddr ",pWapiSta->PeerMacAddr,6); - if (_rtw_memcmp(pRA, pWapiSta->PeerMacAddr, 6) == _TRUE){ - bFindMatchPeer = true; - break; - } - } - if (bFindMatchPeer) { - if (!pWapiSta->wapiUsk.bTxEnable){ - bDrop = true; - WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: unicast key is absent \n"); - return bDrop; - } - } - else{ - bDrop = true; - WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no peer find \n"); - return bDrop; - } - - } - else{ - bDrop = true; - WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no sta exist \n"); - return bDrop; - } - } - } - else - { - return bDrop; - } - - return bDrop; -} - -#endif +#ifdef CONFIG_WAPI_SUPPORT
+
+#include <linux/unistd.h>
+#include <linux/etherdevice.h>
+#include <drv_types.h>
+#include <rtw_wapi.h>
+
+
+u32 wapi_debug_component =
+// WAPI_INIT |
+// WAPI_API |
+// WAPI_TX |
+// WAPI_RX |
+ WAPI_ERR ; //always open err flags on
+
+void WapiFreeAllStaInfo(_adapter *padapter)
+{
+ PRT_WAPI_T pWapiInfo;
+ PRT_WAPI_STA_INFO pWapiStaInfo;
+ PRT_WAPI_BKID pWapiBkid;
+
+ WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+ pWapiInfo = &padapter->wapiInfo;
+
+ //Pust to Idle List
+ rtw_wapi_return_all_sta_info(padapter);
+
+ //Sta Info List
+ while(!list_empty(&(pWapiInfo->wapiSTAIdleList)))
+ {
+ pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+ list_del_init(&pWapiStaInfo->list);
+ }
+
+ //BKID List
+ while(!list_empty(&(pWapiInfo->wapiBKIDIdleList)))
+ {
+ pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list);
+ list_del_init(&pWapiBkid->list);
+ }
+ WAPI_TRACE(WAPI_INIT, "<=========== %s\n", __FUNCTION__);
+ return;
+}
+
+void WapiSetIE(_adapter *padapter)
+{
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ //PRT_WAPI_BKID pWapiBkid;
+ u16 protocolVer = 1;
+ u16 akmCnt = 1;
+ u16 suiteCnt = 1;
+ u16 capability = 0;
+ u8 OUI[3];
+
+ OUI[0] = 0x00;
+ OUI[1] = 0x14;
+ OUI[2] = 0x72;
+
+ pWapiInfo->wapiIELength = 0;
+//protocol version
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &protocolVer, 2);
+ pWapiInfo->wapiIELength +=2;
+//akm
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &akmCnt, 2);
+ pWapiInfo->wapiIELength +=2;
+
+ if(pWapiInfo->bWapiPSK){
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+ pWapiInfo->wapiIELength +=3;
+ pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x2;
+ pWapiInfo->wapiIELength +=1;
+ }else{
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+ pWapiInfo->wapiIELength +=3;
+ pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+ pWapiInfo->wapiIELength +=1;
+ }
+
+//usk
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &suiteCnt, 2);
+ pWapiInfo->wapiIELength +=2;
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+ pWapiInfo->wapiIELength +=3;
+ pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+ pWapiInfo->wapiIELength +=1;
+
+//msk
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+ pWapiInfo->wapiIELength +=3;
+ pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+ pWapiInfo->wapiIELength +=1;
+
+//Capbility
+ memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &capability, 2);
+ pWapiInfo->wapiIELength +=2;
+}
+
+
+/* PN1 > PN2, return 1,
+ * else return 0.
+ */
+u32 WapiComparePN(u8 *PN1, u8 *PN2)
+{
+ char i;
+
+ if ((NULL == PN1) || (NULL == PN2))
+ return 1;
+
+ // overflow case
+ if ((PN2[15] - PN1[15]) & 0x80)
+ return 1;
+
+ for (i=16; i>0; i--)
+ {
+ if(PN1[i-1] == PN2[i-1])
+ continue;
+ else if(PN1[i-1] > PN2[i-1])
+ return 1;
+ else
+ return 0;
+ }
+
+ return 0;
+}
+
+u8
+WapiGetEntryForCamWrite(_adapter *padapter,u8 *pMacAddr,u8 KID,BOOLEAN IsMsk)
+{
+ PRT_WAPI_T pWapiInfo=NULL;
+ //PRT_WAPI_CAM_ENTRY pEntry=NULL;
+ u8 i=0;
+ u8 ret = 0xff;
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ pWapiInfo = &padapter->wapiInfo;
+
+ //exist?
+ for(i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+ {
+ if(pWapiInfo->wapiCamEntry[i].IsUsed
+ && (_rtw_memcmp(pMacAddr, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN) == _TRUE)
+ && pWapiInfo->wapiCamEntry[i].keyidx == KID
+ && pWapiInfo->wapiCamEntry[i].type == IsMsk)
+ {
+ ret = pWapiInfo->wapiCamEntry[i].entry_idx; //cover it
+ break;
+ }
+ }
+
+ if(i == WAPI_CAM_ENTRY_NUM) //not found
+ {
+ for(i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+ {
+ if(pWapiInfo->wapiCamEntry[i].IsUsed == 0)
+ {
+ pWapiInfo->wapiCamEntry[i].IsUsed = 1;
+ pWapiInfo->wapiCamEntry[i].type = IsMsk;
+ pWapiInfo->wapiCamEntry[i].keyidx = KID;
+ _rtw_memcpy(pWapiInfo->wapiCamEntry[i].PeerMacAddr, pMacAddr,ETH_ALEN);
+ ret = pWapiInfo->wapiCamEntry[i].entry_idx;
+ break;
+ }
+ }
+ }
+
+ WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+ return ret;
+
+/*
+ if(RTIsListEmpty(&pWapiInfo->wapiCamIdleList)){
+ RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n"));
+ return 0;
+ }
+
+ pEntry = (PRT_WAPI_CAM_ENTRY)RTRemoveHeadList(&pWapiInfo->wapiCamIdleList);
+ RTInsertTailList(&pWapiInfo->wapiCamUsedList, &pEntry->list);
+
+ RT_TRACE(COMP_SEC,DBG_LOUD,("<====WapiGetCamEntry(),Get Entry Idx:%d.but we just return 4 for test\n",pEntry->entry_idx));
+
+ return pEntry->entry_idx;*/
+}
+
+u8 WapiGetEntryForCamClear(_adapter *padapter,u8 *pPeerMac,u8 keyid,u8 IsMsk)
+{
+ PRT_WAPI_T pWapiInfo=NULL;
+ u8 i=0;
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ pWapiInfo = &padapter->wapiInfo;
+
+ for(i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+ {
+ if(pWapiInfo->wapiCamEntry[i].IsUsed
+ && (_rtw_memcmp(pPeerMac, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN) == _TRUE)
+ && pWapiInfo->wapiCamEntry[i].keyidx == keyid
+ && pWapiInfo->wapiCamEntry[i].type == IsMsk)
+ {
+ pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+ pWapiInfo->wapiCamEntry[i].keyidx = 2;
+ _rtw_memset(pWapiInfo->wapiCamEntry[i].PeerMacAddr,0,ETH_ALEN);
+
+ WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+ return pWapiInfo->wapiCamEntry[i].entry_idx;
+ }
+ }
+
+ WAPI_TRACE(WAPI_API,"<====WapiGetReturnCamEntry(), No this cam entry.\n");
+ return 0xff;
+/*
+ if(RTIsListEmpty(&pWapiInfo->wapiCamUsedList)){
+ RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n"));
+ return FALSE;
+ }
+
+ pList = &pWapiInfo->wapiCamUsedList;
+ while(pList->Flink != &pWapiInfo->wapiCamUsedList)
+ {
+ pEntry = (PRT_WAPI_CAM_ENTRY)pList->Flink;
+ if(PlatformCompareMemory(pPeerMac,pEntry->PeerMacAddr, ETHER_ADDRLEN)== 0
+ && keyid == pEntry->keyidx)
+ {
+ RTRemoveEntryList(pList);
+ RTInsertHeadList(&pWapiInfo->wapiCamIdleList, pList);
+ return pEntry->entry_idx;
+ }
+ pList = pList->Flink;
+ }
+
+ return 0;
+*/
+}
+
+void
+WapiResetAllCamEntry(_adapter *padapter)
+{
+ PRT_WAPI_T pWapiInfo;
+ int i;
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ pWapiInfo = &padapter->wapiInfo;
+
+ for (i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+ {
+ _rtw_memset(pWapiInfo->wapiCamEntry[i].PeerMacAddr, 0, ETH_ALEN);
+ pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+ pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid
+ pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2;
+ }
+
+ WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+
+ return;
+}
+
+u8 WapiWriteOneCamEntry(
+ _adapter *padapter,
+ u8 *pMacAddr,
+ u8 KeyId,
+ u8 EntryId,
+ u8 EncAlg,
+ u8 bGroupKey,
+ u8 *pKey
+)
+{
+ u8 retVal = 0;
+ u16 usConfig = 0;
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ if(EntryId >= 32)
+ {
+ WAPI_TRACE(WAPI_ERR, "<=== CamAddOneEntry(): ulKeyId exceed!\n");
+ return retVal;
+ }
+
+ usConfig=usConfig|(0x01<<15)|((u16)(EncAlg)<<2)|(KeyId);
+
+ if(EncAlg == _SMS4_ )
+ {
+ if(bGroupKey == 1)
+ usConfig |= (0x01<<6);
+ if((EntryId % 2)==1) // ==0 sec key; == 1mic key
+ usConfig |= (0x01<<5);
+ }
+
+ write_cam(padapter, EntryId, usConfig, pMacAddr, pKey);
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+ return 1;
+}
+
+void rtw_wapi_init(_adapter *padapter)
+{
+ PRT_WAPI_T pWapiInfo;
+ int i;
+
+ WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+ RT_ASSERT_RET(padapter);
+
+ if (!padapter->WapiSupport)
+ {
+ WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+ return;
+ }
+
+ pWapiInfo = &padapter->wapiInfo;
+ pWapiInfo->bWapiEnable = false;
+
+ //Init BKID List
+ INIT_LIST_HEAD(&pWapiInfo->wapiBKIDIdleList);
+ INIT_LIST_HEAD(&pWapiInfo->wapiBKIDStoreList);
+ for(i=0;i<WAPI_MAX_BKID_NUM;i++)
+ {
+ list_add_tail(&pWapiInfo->wapiBKID[i].list, &pWapiInfo->wapiBKIDIdleList);
+ }
+
+ //Init STA List
+ INIT_LIST_HEAD(&pWapiInfo->wapiSTAIdleList);
+ INIT_LIST_HEAD(&pWapiInfo->wapiSTAUsedList);
+ for(i=0;i<WAPI_MAX_STAINFO_NUM;i++)
+ {
+ list_add_tail(&pWapiInfo->wapiSta[i].list, &pWapiInfo->wapiSTAIdleList);
+ }
+
+ for (i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+ {
+ pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+ pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid
+ pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2;
+ }
+
+ WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_free(_adapter *padapter)
+{
+ WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+ RT_ASSERT_RET(padapter);
+
+ if (!padapter->WapiSupport)
+ {
+ WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+ return;
+ }
+
+ WapiFreeAllStaInfo(padapter);
+
+ WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_disable_tx(_adapter *padapter)
+{
+ WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+ RT_ASSERT_RET(padapter);
+
+ if (!padapter->WapiSupport)
+ {
+ WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+ return;
+ }
+
+ padapter->wapiInfo.wapiTxMsk.bTxEnable = false;
+ padapter->wapiInfo.wapiTxMsk.bSet = false;
+
+ WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+u8 rtw_wapi_is_wai_packet(_adapter* padapter,u8 *pkt_data)
+{
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+ PRT_WAPI_STA_INFO pWapiSta = NULL;
+ u8 WaiPkt = 0, *pTaddr, bFind = false;
+ u8 Offset_TypeWAI = 0 ; // (mac header len + llc length)
+
+ WAPI_TRACE(WAPI_TX|WAPI_RX, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return 0;
+ }
+
+ Offset_TypeWAI = 24 + 6 ;
+
+ //YJ,add,091103. Data frame may also have skb->data[30]=0x88 and skb->data[31]=0xb4.
+ if ((pkt_data[1]&0x40) !=0)
+ {
+ DBG_871X("data is privacy \n");
+ return 0;
+ }
+
+ pTaddr = GetAddr2Ptr(pkt_data);
+ if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+ bFind = false;
+ }else{
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+ if (_rtw_memcmp(pTaddr, pWapiSta->PeerMacAddr, 6) == _TRUE) {
+ bFind = true;
+ break;
+ }
+ }
+ }
+
+ WAPI_TRACE(WAPI_TX|WAPI_RX, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(pTaddr));
+
+ if (pkt_data[0] == WIFI_QOS_DATA_TYPE)
+ {
+ Offset_TypeWAI += 2;
+ }
+
+ // 88b4?
+ if( (pkt_data[Offset_TypeWAI]==0x88) && (pkt_data[Offset_TypeWAI+1]==0xb4) ){
+ WaiPkt = pkt_data[Offset_TypeWAI+5];
+
+ psecuritypriv->hw_decrypted = _TRUE;
+ }else{
+ WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): non wai packet\n",__FUNCTION__);
+ }
+
+ WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): Recvd WAI frame. IsWAIPkt(%d)\n",__FUNCTION__, WaiPkt);
+
+ return WaiPkt;
+}
+
+
+void rtw_wapi_update_info(_adapter *padapter, union recv_frame *precv_frame)
+{
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ struct recv_frame_hdr *precv_hdr;
+ u8 *ptr;
+ u8 *pTA;
+ u8 *pRecvPN;
+
+
+ WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return;
+ }
+
+ precv_hdr = &precv_frame->u.hdr;
+ ptr = precv_hdr->rx_data;
+
+ if (precv_hdr->attrib.qos == 1)
+ {
+ precv_hdr->UserPriority = GetTid(ptr);
+ }
+ else
+ {
+ precv_hdr->UserPriority = 0;
+ }
+
+ pTA = GetAddr2Ptr(ptr);
+ _rtw_memcpy((u8 *)precv_hdr->WapiSrcAddr, pTA, 6);
+ pRecvPN = ptr + precv_hdr->attrib.hdrlen + 2;
+ _rtw_memcpy((u8 *)precv_hdr->WapiTempPN, pRecvPN, 16);
+
+ WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__);
+}
+
+/****************************************************************************
+TRUE-----------------Drop
+FALSE---------------- handle
+add to support WAPI to N-mode
+*****************************************************************************/
+u8 rtw_wapi_check_for_drop(
+ _adapter *padapter,
+ union recv_frame *precv_frame
+)
+{
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ u8 *pLastRecvPN = NULL;
+ u8 bFind = false;
+ PRT_WAPI_STA_INFO pWapiSta = NULL;
+ u8 bDrop = false;
+ struct recv_frame_hdr *precv_hdr = &precv_frame->u.hdr;
+ u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+ u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+ u8 *ptr = precv_frame->u.hdr.rx_data;
+ int i;
+
+ WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return false;
+ }
+
+ if(precv_hdr->bIsWaiPacket !=0)
+ {
+ if(precv_hdr->bIsWaiPacket== 0x8)
+ {
+
+ DBG_871X("rtw_wapi_check_for_drop: dump packet \n");
+ for(i=0;i<50;i++)
+ {
+ DBG_871X("%02X ",ptr[i]);
+ if((i+1) %8 ==0)
+ DBG_871X("\n");
+ }
+ DBG_871X("\n rtw_wapi_check_for_drop: dump packet \n");
+
+ for(i=0;i<16;i++)
+ {
+ if(ptr[i+27] !=0)
+ break;
+ }
+
+ if(i== 16)
+ {
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: drop with zero BKID \n");
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+
+ if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+ bFind = false;
+ }else{
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+ if (_rtw_memcmp(precv_hdr->WapiSrcAddr, pWapiSta->PeerMacAddr, ETH_ALEN) == _TRUE) {
+ bFind = true;
+ break;
+ }
+ }
+ }
+ WAPI_TRACE(WAPI_RX, "%s: bFind=%d prxb->WapiSrcAddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(precv_hdr->WapiSrcAddr));
+
+ if(bFind)
+ {
+ if(IS_MCAST(precv_hdr->attrib.ra))
+ {
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: multicast case \n");
+ pLastRecvPN = pWapiSta->lastRxMulticastPN;
+ }
+ else
+ {
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: unicast case \n");
+ switch(precv_hdr->UserPriority)
+ {
+ case 0:
+ case 3:
+ pLastRecvPN = pWapiSta->lastRxUnicastPNBEQueue;
+ break;
+ case 1:
+ case 2:
+ pLastRecvPN = pWapiSta->lastRxUnicastPNBKQueue;
+ break;
+ case 4:
+ case 5:
+ pLastRecvPN = pWapiSta->lastRxUnicastPNVIQueue;
+ break;
+ case 6:
+ case 7:
+ pLastRecvPN = pWapiSta->lastRxUnicastPNVOQueue;
+ break;
+ default:
+ WAPI_TRACE(WAPI_ERR,"%s: Unknown TID \n",__FUNCTION__);
+ break;
+ }
+ }
+
+ if(!WapiComparePN(precv_hdr->WapiTempPN,pLastRecvPN))
+ {
+ WAPI_TRACE(WAPI_RX,"%s: Equal PN!!\n",__FUNCTION__);
+ if(IS_MCAST(precv_hdr->attrib.ra))
+ _rtw_memcpy(pLastRecvPN,WapiAEMultiCastPNInitialValueSrc,16);
+ else
+ _rtw_memcpy(pLastRecvPN,WapiAEPNInitialValueSrc,16);
+ bDrop = true;
+ }
+ else
+ {
+ _rtw_memcpy(pLastRecvPN,precv_hdr->WapiTempPN,16);
+ }
+ }
+
+ WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__);
+ return bDrop;
+}
+
+void rtw_build_probe_resp_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+{
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ u8 WapiIELength = 0;
+
+ WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+ return;
+ }
+
+ WapiSetIE(padapter);
+ WapiIELength = pWapiInfo->wapiIELength;
+ pframe[0] = _WAPI_IE_;
+ pframe[1] = WapiIELength;
+ _rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+ pframe += WapiIELength+2;
+ pattrib->pktlen += WapiIELength+2;
+
+ WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_build_beacon_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+{
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ u8 WapiIELength = 0;
+ WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+ return;
+ }
+
+ WapiSetIE(padapter);
+ WapiIELength = pWapiInfo->wapiIELength;
+ pframe[0] = _WAPI_IE_;
+ pframe[1] = WapiIELength;
+ _rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+ pframe += WapiIELength+2;
+ pattrib->pktlen += WapiIELength+2;
+
+ WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_build_assoc_req_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+{
+ PRT_WAPI_BKID pWapiBKID;
+ u16 bkidNum;
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ u8 WapiIELength = 0;
+
+ WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+ return;
+ }
+
+ WapiSetIE(padapter);
+ WapiIELength = pWapiInfo->wapiIELength;
+ bkidNum = 0;
+ if(!list_empty(&(pWapiInfo->wapiBKIDStoreList))){
+ list_for_each_entry(pWapiBKID, &pWapiInfo->wapiBKIDStoreList, list) {
+ bkidNum ++;
+ _rtw_memcpy(pWapiInfo->wapiIE+WapiIELength+2, pWapiBKID->bkid,16);
+ WapiIELength += 16;
+ }
+ }
+ _rtw_memcpy(pWapiInfo->wapiIE+WapiIELength, &bkidNum, 2);
+ WapiIELength += 2;
+
+ pframe[0] = _WAPI_IE_;
+ pframe[1] = WapiIELength;
+ _rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+ pframe += WapiIELength+2;
+ pattrib->pktlen += WapiIELength+2;
+ WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_on_assoc_ok(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+ PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+ PRT_WAPI_STA_INFO pWapiSta;
+ u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+ //u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+ u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+
+ WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return;
+ }
+
+ pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+ list_del_init(&pWapiSta->list);
+ list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList);
+ _rtw_memcpy(pWapiSta->PeerMacAddr,padapter->mlmeextpriv.mlmext_info.network.MacAddress,6);
+ _rtw_memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
+ _rtw_memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16);
+
+ //For chenk PN error with Qos Data after s3: add by ylb 20111114
+ _rtw_memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16);
+ _rtw_memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16);
+ _rtw_memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16);
+ _rtw_memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16);
+
+ WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+
+void rtw_wapi_return_one_sta_info(_adapter *padapter, u8 *MacAddr)
+{
+ PRT_WAPI_T pWapiInfo;
+ PRT_WAPI_STA_INFO pWapiStaInfo = NULL;
+ PRT_WAPI_BKID pWapiBkid = NULL;
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+ pWapiInfo = &padapter->wapiInfo;
+
+ WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return;
+ }
+
+ if(check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+ {
+ while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+ {
+ pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+ list_del_init(&pWapiBkid->list);
+ _rtw_memset(pWapiBkid->bkid,0,16);
+ list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+ }
+ }
+
+
+ WAPI_TRACE(WAPI_API, " %s: after clear bkid \n", __FUNCTION__);
+
+
+ //Remove STA info
+ if(list_empty(&(pWapiInfo->wapiSTAUsedList))){
+ WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is null \n", __FUNCTION__);
+ return;
+ }else{
+
+ WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is not null \n", __FUNCTION__);
+#if 0
+ pWapiStaInfo=(PRT_WAPI_STA_INFO)list_entry((pWapiInfo->wapiSTAUsedList.next),RT_WAPI_STA_INFO,list);
+
+ list_for_each_entry(pWapiStaInfo, &(pWapiInfo->wapiSTAUsedList), list) {
+
+ DBG_871X("MAC Addr %02x-%02x-%02x-%02x-%02x-%02x \n",MacAddr[0],MacAddr[1],MacAddr[2],MacAddr[3],MacAddr[4],MacAddr[5]);
+
+
+ DBG_871X("peer Addr %02x-%02x-%02x-%02x-%02x-%02x \n",pWapiStaInfo->PeerMacAddr[0],pWapiStaInfo->PeerMacAddr[1],pWapiStaInfo->PeerMacAddr[2],pWapiStaInfo->PeerMacAddr[3],pWapiStaInfo->PeerMacAddr[4],pWapiStaInfo->PeerMacAddr[5]);
+
+ if(pWapiStaInfo == NULL)
+ {
+ WAPI_TRACE(WAPI_API, " %s: pWapiStaInfo == NULL Case \n", __FUNCTION__);
+ return;
+ }
+
+ if(pWapiStaInfo->PeerMacAddr == NULL)
+ {
+ WAPI_TRACE(WAPI_API, " %s: pWapiStaInfo->PeerMacAddr == NULL Case \n", __FUNCTION__);
+ return;
+ }
+
+ if(MacAddr == NULL)
+ {
+ WAPI_TRACE(WAPI_API, " %s: MacAddr == NULL Case \n", __FUNCTION__);
+ return;
+ }
+
+ if (_rtw_memcmp(pWapiStaInfo->PeerMacAddr, MacAddr, ETH_ALEN) == _TRUE) {
+ pWapiStaInfo->bAuthenticateInProgress = false;
+ pWapiStaInfo->bSetkeyOk = false;
+ _rtw_memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+ list_del_init(&pWapiStaInfo->list);
+ list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+ break;
+ }
+
+ }
+#endif
+
+ while(!list_empty(&(pWapiInfo->wapiSTAUsedList)))
+ {
+ pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list);
+
+ DBG_871X("peer Addr %02x-%02x-%02x-%02x-%02x-%02x \n",pWapiStaInfo->PeerMacAddr[0],pWapiStaInfo->PeerMacAddr[1],pWapiStaInfo->PeerMacAddr[2],pWapiStaInfo->PeerMacAddr[3],pWapiStaInfo->PeerMacAddr[4],pWapiStaInfo->PeerMacAddr[5]);
+
+ list_del_init(&pWapiStaInfo->list);
+ memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+ pWapiStaInfo->bSetkeyOk = 0;
+ list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+ }
+
+ }
+
+ WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+ return;
+}
+
+void rtw_wapi_return_all_sta_info(_adapter *padapter)
+{
+ PRT_WAPI_T pWapiInfo;
+ PRT_WAPI_STA_INFO pWapiStaInfo;
+ PRT_WAPI_BKID pWapiBkid;
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ pWapiInfo = &padapter->wapiInfo;
+
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return;
+ }
+
+ //Sta Info List
+ while(!list_empty(&(pWapiInfo->wapiSTAUsedList)))
+ {
+ pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list);
+ list_del_init(&pWapiStaInfo->list);
+ memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+ pWapiStaInfo->bSetkeyOk = 0;
+ list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+ }
+
+ //BKID List
+ while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+ {
+ pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+ list_del_init(&pWapiBkid->list);
+ memset(pWapiBkid->bkid,0,16);
+ list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+ }
+ WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_clear_cam_entry(_adapter *padapter, u8 *pMacAddr)
+{
+ u8 UcIndex = 0;
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return;
+ }
+
+ UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 0);
+ if(UcIndex != 0xff){
+ //CAM_mark_invalid(Adapter, UcIndex);
+ CAM_empty_entry(padapter, UcIndex);
+ }
+
+ UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 0);
+ if(UcIndex != 0xff){
+ //CAM_mark_invalid(Adapter, UcIndex);
+ CAM_empty_entry(padapter, UcIndex);
+ }
+
+ UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 1);
+ if(UcIndex != 0xff){
+ //CAM_mark_invalid(Adapter, UcIndex);
+ CAM_empty_entry(padapter, UcIndex);
+ }
+
+ UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 1);
+ if(UcIndex != 0xff){
+ //CAM_mark_invalid(padapter, UcIndex);
+ CAM_empty_entry(padapter, UcIndex);
+ }
+
+ WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_clear_all_cam_entry(_adapter *padapter)
+{
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return;
+ }
+
+ invalidate_cam_all(padapter); // is this ok?
+ WapiResetAllCamEntry(padapter);
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_set_key(_adapter *padapter, RT_WAPI_KEY *pWapiKey, RT_WAPI_STA_INFO *pWapiSta, u8 bGroupKey, u8 bUseDefaultKey)
+{
+ PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+ u8 *pMacAddr = pWapiSta->PeerMacAddr;
+ u32 EntryId = 0;
+ BOOLEAN IsPairWise = false ;
+ u8 EncAlgo;
+
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_API, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+ return;
+ }
+
+ EncAlgo = _SMS4_;
+
+ //For Tx bc/mc pkt,use defualt key entry
+ if(bUseDefaultKey)
+ {
+ // when WAPI update key, keyid will be 0 or 1 by turns.
+ if (pWapiKey->keyId == 0)
+ EntryId = 0;
+ else
+ EntryId = 2;
+ }
+ else
+ {
+ // tx/rx unicast pkt, or rx broadcast, find the key entry by peer's MacAddr
+ EntryId = WapiGetEntryForCamWrite(padapter,pMacAddr,pWapiKey->keyId,bGroupKey);
+ }
+
+ if(EntryId == 0xff){
+ WAPI_TRACE(WAPI_API, "===>No entry for WAPI setkey! !!\n");
+ return;
+ }
+
+ //EntryId is also used to diff Sec key and Mic key
+ //Sec Key
+ WapiWriteOneCamEntry(padapter,
+ pMacAddr,
+ pWapiKey->keyId, //keyid
+ EntryId, //entry
+ EncAlgo, //type
+ bGroupKey, //pairwise or group key
+ pWapiKey->dataKey);
+ //MIC key
+ WapiWriteOneCamEntry(padapter,
+ pMacAddr,
+ pWapiKey->keyId, //keyid
+ EntryId+1, //entry
+ EncAlgo, //type
+ bGroupKey, //pairwise or group key
+ pWapiKey->micKey);
+
+ WAPI_TRACE(WAPI_API, "Set Wapi Key :KeyId:%d,EntryId:%d,PairwiseKey:%d.\n",pWapiKey->keyId,EntryId,!bGroupKey);
+ WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+}
+
+#if 0
+//YJ,test,091013
+void wapi_test_set_key(struct _adapter *padapter, u8* buf)
+{ /*Data: keyType(1) + bTxEnable(1) + bAuthenticator(1) + bUpdate(1) + PeerAddr(6) + DataKey(16) + MicKey(16) + KeyId(1)*/
+ PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+ PRT_WAPI_BKID pWapiBkid;
+ PRT_WAPI_STA_INFO pWapiSta;
+ u8 data[43];
+ bool bTxEnable;
+ bool bUpdate;
+ bool bAuthenticator;
+ u8 PeerAddr[6];
+ u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+ u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+ u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+
+ WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__);
+
+ if (!padapter->WapiSupport){
+ return;
+ }
+
+ copy_from_user(data, buf, 43);
+ bTxEnable = data[1];
+ bAuthenticator = data[2];
+ bUpdate = data[3];
+ memcpy(PeerAddr,data+4,6);
+
+ if(data[0] == 0x3){
+ if(!list_empty(&(pWapiInfo->wapiBKIDIdleList))){
+ pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list);
+ list_del_init(&pWapiBkid->list);
+ memcpy(pWapiBkid->bkid, data+10, 16);
+ WAPI_DATA(WAPI_INIT, "SetKey - BKID", pWapiBkid->bkid, 16);
+ list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDStoreList);
+ }
+ }else{
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+ if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){
+ pWapiSta->bAuthenticatorInUpdata = false;
+ switch(data[0]){
+ case 1: //usk
+ if(bAuthenticator){ //authenticator
+ memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16);
+ if(!bUpdate) { //first
+ WAPI_TRACE(WAPI_INIT,"AE fisrt set usk \n");
+ pWapiSta->wapiUsk.bSet = true;
+ memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+ memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+ pWapiSta->wapiUsk.keyId = *(data+42);
+ pWapiSta->wapiUsk.bTxEnable = true;
+ WAPI_DATA(WAPI_INIT, "SetKey - AE USK Data Key", pWapiSta->wapiUsk.dataKey, 16);
+ WAPI_DATA(WAPI_INIT, "SetKey - AE USK Mic Key", pWapiSta->wapiUsk.micKey, 16);
+ }
+ else //update
+ {
+ WAPI_TRACE(WAPI_INIT, "AE update usk \n");
+ pWapiSta->wapiUskUpdate.bSet = true;
+ pWapiSta->bAuthenticatorInUpdata = true;
+ memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+ memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+ memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+ pWapiSta->wapiUskUpdate.keyId = *(data+42);
+ pWapiSta->wapiUskUpdate.bTxEnable = true;
+ }
+ }
+ else{
+ if(!bUpdate){
+ WAPI_TRACE(WAPI_INIT,"ASUE fisrt set usk \n");
+ if(bTxEnable){
+ pWapiSta->wapiUsk.bTxEnable = true;
+ memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+ }else{
+ pWapiSta->wapiUsk.bSet = true;
+ memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+ memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+ pWapiSta->wapiUsk.keyId = *(data+42);
+ pWapiSta->wapiUsk.bTxEnable = false;
+ }
+ }else{
+ WAPI_TRACE(WAPI_INIT,"ASUE update usk \n");
+ if(bTxEnable){
+ pWapiSta->wapiUskUpdate.bTxEnable = true;
+ if(pWapiSta->wapiUskUpdate.bSet){
+ memcpy(pWapiSta->wapiUsk.dataKey,pWapiSta->wapiUskUpdate.dataKey,16);
+ memcpy(pWapiSta->wapiUsk.micKey,pWapiSta->wapiUskUpdate.micKey,16);
+ pWapiSta->wapiUsk.keyId=pWapiSta->wapiUskUpdate.keyId;
+ memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+ memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+ pWapiSta->wapiUskUpdate.bTxEnable = false;
+ pWapiSta->wapiUskUpdate.bSet = false;
+ }
+ memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+ }else{
+ pWapiSta->wapiUskUpdate.bSet = true;
+ memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+ memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+ pWapiSta->wapiUskUpdate.keyId = *(data+42);
+ pWapiSta->wapiUskUpdate.bTxEnable = false;
+ }
+ }
+ }
+ break;
+ case 2: //msk
+ if(bAuthenticator){ //authenticator
+ pWapiInfo->wapiTxMsk.bSet = true;
+ memcpy(pWapiInfo->wapiTxMsk.dataKey,data+10,16);
+ memcpy(pWapiInfo->wapiTxMsk.micKey,data+26,16);
+ pWapiInfo->wapiTxMsk.keyId = *(data+42);
+ pWapiInfo->wapiTxMsk.bTxEnable = true;
+ memcpy(pWapiInfo->lastTxMulticastPN,WapiAEMultiCastPNInitialValueSrc,16);
+
+ if(!bUpdate){ //first
+ WAPI_TRACE(WAPI_INIT, "AE fisrt set msk \n");
+ if(!pWapiSta->bSetkeyOk)
+ pWapiSta->bSetkeyOk = true;
+ pWapiInfo->bFirstAuthentiateInProgress= false;
+ }else{ //update
+ WAPI_TRACE(WAPI_INIT,"AE update msk \n");
+ }
+
+ WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Data Key", pWapiInfo->wapiTxMsk.dataKey, 16);
+ WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Mic Key", pWapiInfo->wapiTxMsk.micKey, 16);
+ }
+ else{
+ if(!bUpdate){
+ WAPI_TRACE(WAPI_INIT,"ASUE fisrt set msk \n");
+ pWapiSta->wapiMsk.bSet = true;
+ memcpy(pWapiSta->wapiMsk.dataKey,data+10,16);
+ memcpy(pWapiSta->wapiMsk.micKey,data+26,16);
+ pWapiSta->wapiMsk.keyId = *(data+42);
+ pWapiSta->wapiMsk.bTxEnable = false;
+ if(!pWapiSta->bSetkeyOk)
+ pWapiSta->bSetkeyOk = true;
+ pWapiInfo->bFirstAuthentiateInProgress= false;
+ WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Data Key", pWapiSta->wapiMsk.dataKey, 16);
+ WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Mic Key", pWapiSta->wapiMsk.micKey, 16);
+ }else{
+ WAPI_TRACE(WAPI_INIT,"ASUE update msk \n");
+ pWapiSta->wapiMskUpdate.bSet = true;
+ memcpy(pWapiSta->wapiMskUpdate.dataKey,data+10,16);
+ memcpy(pWapiSta->wapiMskUpdate.micKey,data+26,16);
+ pWapiSta->wapiMskUpdate.keyId = *(data+42);
+ pWapiSta->wapiMskUpdate.bTxEnable = false;
+ }
+ }
+ break;
+ default:
+ WAPI_TRACE(WAPI_ERR,"Unknown Flag \n");
+ break;
+ }
+ }
+ }
+ }
+ WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__);
+}
+
+
+void wapi_test_init(struct _adapter *padapter)
+{
+ u8 keybuf[100];
+ u8 mac_addr[6]={0x00,0xe0,0x4c,0x72,0x04,0x70};
+ u8 UskDataKey[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
+ u8 UskMicKey[16]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
+ u8 UskId = 0;
+ u8 MskDataKey[16]={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f};
+ u8 MskMicKey[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f};
+ u8 MskId = 0;
+
+ WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__);
+
+ //Enable Wapi
+ WAPI_TRACE(WAPI_INIT, "%s: Enable wapi!!!!\n", __FUNCTION__);
+ padapter->wapiInfo.bWapiEnable = true;
+ padapter->pairwise_key_type = KEY_TYPE_SMS4;
+ ieee->group_key_type = KEY_TYPE_SMS4;
+ padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
+ padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
+
+ //set usk
+ WAPI_TRACE(WAPI_INIT, "%s: Set USK!!!!\n", __FUNCTION__);
+ memset(keybuf,0,100);
+ keybuf[0] = 1; //set usk
+ keybuf[1] = 1; //enable tx
+ keybuf[2] = 1; //AE
+ keybuf[3] = 0; //not update
+
+ memcpy(keybuf+4,mac_addr,6);
+ memcpy(keybuf+10,UskDataKey,16);
+ memcpy(keybuf+26,UskMicKey,16);
+ keybuf[42]=UskId;
+ wapi_test_set_key(padapter, keybuf);
+
+ memset(keybuf,0,100);
+ keybuf[0] = 1; //set usk
+ keybuf[1] = 1; //enable tx
+ keybuf[2] = 0; //AE
+ keybuf[3] = 0; //not update
+
+ memcpy(keybuf+4,mac_addr,6);
+ memcpy(keybuf+10,UskDataKey,16);
+ memcpy(keybuf+26,UskMicKey,16);
+ keybuf[42]=UskId;
+ wapi_test_set_key(padapter, keybuf);
+
+ //set msk
+ WAPI_TRACE(WAPI_INIT, "%s: Set MSK!!!!\n", __FUNCTION__);
+ memset(keybuf,0,100);
+ keybuf[0] = 2; //set msk
+ keybuf[1] = 1; //Enable TX
+ keybuf[2] = 1; //AE
+ keybuf[3] = 0; //not update
+ memcpy(keybuf+4,mac_addr,6);
+ memcpy(keybuf+10,MskDataKey,16);
+ memcpy(keybuf+26,MskMicKey,16);
+ keybuf[42] = MskId;
+ wapi_test_set_key(padapter, keybuf);
+
+ memset(keybuf,0,100);
+ keybuf[0] = 2; //set msk
+ keybuf[1] = 1; //Enable TX
+ keybuf[2] = 0; //AE
+ keybuf[3] = 0; //not update
+ memcpy(keybuf+4,mac_addr,6);
+ memcpy(keybuf+10,MskDataKey,16);
+ memcpy(keybuf+26,MskMicKey,16);
+ keybuf[42] = MskId;
+ wapi_test_set_key(padapter, keybuf);
+ WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__);
+}
+#endif
+
+void rtw_wapi_get_iv(_adapter *padapter,u8 *pRA, u8*IV)
+{
+ PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL;
+ PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+ bool bPNOverflow = false;
+ bool bFindMatchPeer = false;
+ PRT_WAPI_STA_INFO pWapiSta = NULL;
+
+ pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)IV;
+
+ WAPI_DATA(WAPI_RX,"wapi_get_iv: pra",pRA,6);
+
+ if(IS_MCAST(pRA)){
+ if(!pWapiInfo->wapiTxMsk.bTxEnable){
+ WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+ return;
+ }
+
+ if(pWapiInfo->wapiTxMsk.keyId <= 1){
+ pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+ pWapiExt->Reserved = 0;
+ bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1);
+ memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16);
+ }
+ }
+ else
+ {
+ if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_get_iv: list is empty \n");
+ _rtw_memset(IV,10,18);
+ return;
+ }
+ else{
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+ WAPI_DATA(WAPI_RX,"rtw_wapi_get_iv: peermacaddr ",pWapiSta->PeerMacAddr,6);
+ if (_rtw_memcmp((u8*)pWapiSta->PeerMacAddr, pRA, 6) == _TRUE) {
+ bFindMatchPeer = true;
+ break;
+ }
+ }
+
+ WAPI_TRACE(WAPI_RX,"bFindMatchPeer: %d \n",bFindMatchPeer);
+ WAPI_DATA(WAPI_RX,"Addr",pRA,6);
+
+ if (bFindMatchPeer){
+ if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable))
+ return;
+
+ if (pWapiSta->wapiUsk.keyId <= 1){
+ if(pWapiSta->wapiUskUpdate.bTxEnable)
+ pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+ else
+ pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId;
+
+ pWapiExt->Reserved = 0;
+ bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2);
+ _rtw_memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16);
+
+ }
+ }
+ }
+
+ }
+
+}
+
+bool rtw_wapi_drop_for_key_absent(_adapter *padapter,u8 *pRA)
+{
+ PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+ bool bFindMatchPeer = false;
+ bool bDrop = false;
+ PRT_WAPI_STA_INFO pWapiSta = NULL;
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+ WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: ra ",pRA,6);
+
+ if(psecuritypriv->dot11PrivacyAlgrthm == _SMS4_)
+ {
+ if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+ return true;
+
+ if(IS_MCAST(pRA)){
+ if(!pWapiInfo->wapiTxMsk.bTxEnable){
+ bDrop = true;
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: multicast key is absent \n");
+ return bDrop;
+ }
+ }
+ else{
+ if(!list_empty(&pWapiInfo->wapiSTAUsedList)){
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+ WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: pWapiSta->PeerMacAddr ",pWapiSta->PeerMacAddr,6);
+ if (_rtw_memcmp(pRA, pWapiSta->PeerMacAddr, 6) == _TRUE){
+ bFindMatchPeer = true;
+ break;
+ }
+ }
+ if (bFindMatchPeer) {
+ if (!pWapiSta->wapiUsk.bTxEnable){
+ bDrop = true;
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: unicast key is absent \n");
+ return bDrop;
+ }
+ }
+ else{
+ bDrop = true;
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no peer find \n");
+ return bDrop;
+ }
+
+ }
+ else{
+ bDrop = true;
+ WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no sta exist \n");
+ return bDrop;
+ }
+ }
+ }
+ else
+ {
+ return bDrop;
+ }
+
+ return bDrop;
+}
+
+#endif
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_wapi_sms4.c b/drivers/net/wireless/rtl8723as/core/rtw_wapi_sms4.c index aa6419390673..6126ed9a00c6 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_wapi_sms4.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_wapi_sms4.c @@ -1,923 +1,923 @@ -#ifdef CONFIG_WAPI_SUPPORT - -#include <linux/unistd.h> -#include <linux/etherdevice.h> -#include <drv_types.h> -#include <rtw_wapi.h> - - -#ifdef CONFIG_WAPI_SW_SMS4 - -#define WAPI_LITTLE_ENDIAN -//#define BIG_ENDIAN -#define ENCRYPT 0 -#define DECRYPT 1 - - -/********************************************************** - **********************************************************/ -const u8 Sbox[256] = { -0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05, -0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99, -0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62, -0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6, -0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8, -0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35, -0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87, -0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e, -0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1, -0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3, -0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f, -0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51, -0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8, -0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0, -0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84, -0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48 -}; - -const u32 CK[32] = { - 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, - 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, - 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, - 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, - 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, - 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, - 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, - 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 }; - -#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y)))) - -#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 | \ - Sbox[(_A) >> 16 & 0xFF] << 16 | \ - Sbox[(_A) >> 8 & 0xFF] << 8 | \ - Sbox[(_A) & 0xFF]) - -#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24)) -#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23)) - -static void -xor_block(void *dst, void *src1, void *src2) -/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned */ -{ - ((u32 *)dst)[0] = ((u32 *)src1)[0] ^ ((u32 *)src2)[0]; - ((u32 *)dst)[1] = ((u32 *)src1)[1] ^ ((u32 *)src2)[1]; - ((u32 *)dst)[2] = ((u32 *)src1)[2] ^ ((u32 *)src2)[2]; - ((u32 *)dst)[3] = ((u32 *)src1)[3] ^ ((u32 *)src2)[3]; -} - - -void SMS4Crypt(u8 *Input, u8 *Output, u32 *rk) -{ - u32 r, mid, x0, x1, x2, x3, *p; - p = (u32 *)Input; - x0 = p[0]; - x1 = p[1]; - x2 = p[2]; - x3 = p[3]; -#ifdef WAPI_LITTLE_ENDIAN - x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8); - x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8); - x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8); - x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8); -#endif - for (r = 0; r < 32; r += 4) - { - mid = x1 ^ x2 ^ x3 ^ rk[r + 0]; - mid = ByteSub(mid); - x0 ^= L1(mid); - mid = x2 ^ x3 ^ x0 ^ rk[r + 1]; - mid = ByteSub(mid); - x1 ^= L1(mid); - mid = x3 ^ x0 ^ x1 ^ rk[r + 2]; - mid = ByteSub(mid); - x2 ^= L1(mid); - mid = x0 ^ x1 ^ x2 ^ rk[r + 3]; - mid = ByteSub(mid); - x3 ^= L1(mid); - } -#ifdef WAPI_LITTLE_ENDIAN - x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8); - x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8); - x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8); - x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8); -#endif - p = (u32 *)Output; - p[0] = x3; - p[1] = x2; - p[2] = x1; - p[3] = x0; -} - - - -void SMS4KeyExt(u8 *Key, u32 *rk, u32 CryptFlag) -{ - u32 r, mid, x0, x1, x2, x3, *p; - - p = (u32 *)Key; - x0 = p[0]; - x1 = p[1]; - x2 = p[2]; - x3 = p[3]; -#ifdef WAPI_LITTLE_ENDIAN - x0 = Rotl(x0, 16); x0 = ((x0 & 0xFF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8); - x1 = Rotl(x1, 16); x1 = ((x1 & 0xFF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8); - x2 = Rotl(x2, 16); x2 = ((x2 & 0xFF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8); - x3 = Rotl(x3, 16); x3 = ((x3 & 0xFF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8); -#endif - - x0 ^= 0xa3b1bac6; - x1 ^= 0x56aa3350; - x2 ^= 0x677d9197; - x3 ^= 0xb27022dc; - for (r = 0; r < 32; r += 4) - { - mid = x1 ^ x2 ^ x3 ^ CK[r + 0]; - mid = ByteSub(mid); - rk[r + 0] = x0 ^= L2(mid); - mid = x2 ^ x3 ^ x0 ^ CK[r + 1]; - mid = ByteSub(mid); - rk[r + 1] = x1 ^= L2(mid); - mid = x3 ^ x0 ^ x1 ^ CK[r + 2]; - mid = ByteSub(mid); - rk[r + 2] = x2 ^= L2(mid); - mid = x0 ^ x1 ^ x2 ^ CK[r + 3]; - mid = ByteSub(mid); - rk[r + 3] = x3 ^= L2(mid); - } - if (CryptFlag == DECRYPT) - { - for (r = 0; r < 16; r++) - mid = rk[r], rk[r] = rk[31 - r], rk[31 - r] = mid; - } -} - - -void WapiSMS4Cryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength, - u8 *Output, u16 *OutputLength, u32 CryptFlag) -{ - u32 blockNum,i,j, rk[32]; - u16 remainder; - u8 blockIn[16],blockOut[16], tempIV[16], k; - - *OutputLength = 0; - remainder = InputLength & 0x0F; - blockNum = InputLength >> 4; - if(remainder !=0) - blockNum++; - else - remainder = 16; - - for(k=0;k<16;k++) - tempIV[k] = IV[15-k]; - - memcpy(blockIn, tempIV, 16); - - SMS4KeyExt((u8 *)Key, rk,CryptFlag); - - for(i=0; i<blockNum-1; i++) - { - SMS4Crypt((u8 *)blockIn, blockOut, rk); - xor_block(&Output[i*16], &Input[i*16], blockOut); - memcpy(blockIn,blockOut,16); - } - - *OutputLength = i*16; - - SMS4Crypt((u8 *)blockIn, blockOut, rk); - - for(j=0; j<remainder; j++) - { - Output[i*16+j] = Input[i*16+j] ^ blockOut[j]; - } - *OutputLength += remainder; - -} - -void WapiSMS4Encryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength, - u8 *Output, u16 *OutputLength) -{ - - WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT); -} - -void WapiSMS4Decryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength, - u8 *Output, u16 *OutputLength) -{ - // OFB mode: is also ENCRYPT flag - WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT); -} - -void WapiSMS4CalculateMic(u8 *Key, u8 *IV, u8 *Input1, u8 Input1Length, - u8 *Input2, u16 Input2Length, u8 *Output, u8 *OutputLength) -{ - u32 blockNum, i, remainder, rk[32]; - u8 BlockIn[16], BlockOut[16], TempBlock[16], tempIV[16], k; - - *OutputLength = 0; - remainder = Input1Length & 0x0F; - blockNum = Input1Length >> 4; - - for(k=0;k<16;k++) - tempIV[k] = IV[15-k]; - - memcpy(BlockIn, tempIV, 16); - - SMS4KeyExt((u8 *)Key, rk, ENCRYPT); - - SMS4Crypt((u8 *)BlockIn, BlockOut, rk); - - for(i=0; i<blockNum; i++){ - xor_block(BlockIn, (Input1+i*16), BlockOut); - SMS4Crypt((u8 *)BlockIn, BlockOut, rk); - } - - if(remainder !=0){ - memset(TempBlock, 0, 16); - memcpy(TempBlock, (Input1+blockNum*16), remainder); - - xor_block(BlockIn, TempBlock, BlockOut); - SMS4Crypt((u8 *)BlockIn, BlockOut, rk); - } - - remainder = Input2Length & 0x0F; - blockNum = Input2Length >> 4; - - for(i=0; i<blockNum; i++){ - xor_block(BlockIn, (Input2+i*16), BlockOut); - SMS4Crypt((u8 *)BlockIn, BlockOut, rk); - } - - if(remainder !=0){ - memset(TempBlock, 0, 16); - memcpy(TempBlock, (Input2+blockNum*16), remainder); - - xor_block(BlockIn, TempBlock, BlockOut); - SMS4Crypt((u8 *)BlockIn, BlockOut, rk); - } - - memcpy(Output, BlockOut, 16); - *OutputLength = 16; -} - -void SecCalculateMicSMS4( - u8 KeyIdx, - u8 *MicKey, - u8 *pHeader, - u8 *pData, - u16 DataLen, - u8 *MicBuffer - ) -{ -#if 0 - struct ieee80211_hdr_3addr_qos *header; - u8 TempBuf[34], TempLen = 32, MicLen, QosOffset, *IV; - u16 *pTemp, fc; - - WAPI_TRACE(WAPI_TX|WAPI_RX, "=========>%s\n", __FUNCTION__); - - header = (struct ieee80211_hdr_3addr_qos *)pHeader; - memset(TempBuf, 0, 34); - memcpy(TempBuf, pHeader, 2); //FrameCtrl - pTemp = (u16*)TempBuf; - *pTemp &= 0xc78f; //bit4,5,6,11,12,13 - - memcpy((TempBuf+2), (pHeader+4), 12); //Addr1, Addr2 - memcpy((TempBuf+14), (pHeader+22), 2); // SeqCtrl - pTemp = (u16*)(TempBuf + 14); - *pTemp &= 0x000f; - - memcpy((TempBuf+16), (pHeader+16), 6); //Addr3 - - fc = le16_to_cpu(header->frame_ctl); - - - - if (GetFrDs((u16*)&fc) && GetToDs((u16 *)&fc)) - { - memcpy((TempBuf+22), (pHeader+24), 6); - QosOffset = 30; - }else{ - memset((TempBuf+22), 0, 6); - QosOffset = 24; - } - - if((fc & 0x0088) == 0x0088){ - memcpy((TempBuf+28), (pHeader+QosOffset), 2); - TempLen += 2; - //IV = pHeader + QosOffset + 2 + SNAP_SIZE + sizeof(u16) + 2; - IV = pHeader + QosOffset + 2 + 2; - }else{ - IV = pHeader + QosOffset + 2; - //IV = pHeader + QosOffset + SNAP_SIZE + sizeof(u16) + 2; - } - - TempBuf[TempLen-1] = (u8)(DataLen & 0xff); - TempBuf[TempLen-2] = (u8)((DataLen & 0xff00)>>8); - TempBuf[TempLen-4] = KeyIdx; - - WAPI_DATA(WAPI_TX, "CalculateMic - KEY", MicKey, 16); - WAPI_DATA(WAPI_TX, "CalculateMic - IV", IV, 16); - WAPI_DATA(WAPI_TX, "CalculateMic - TempBuf", TempBuf, TempLen); - WAPI_DATA(WAPI_TX, "CalculateMic - pData", pData, DataLen); - - WapiSMS4CalculateMic(MicKey, IV, TempBuf, TempLen, - pData, DataLen, MicBuffer, &MicLen); - - if (MicLen != 16) - WAPI_TRACE(WAPI_ERR,"%s: MIC Length Error!!\n",__FUNCTION__); - - WAPI_TRACE(WAPI_TX|WAPI_RX, "<=========%s\n", __FUNCTION__); -#endif -} - -/* AddCount: 1 or 2. - * If overflow, return 1, - * else return 0. - */ -u8 WapiIncreasePN(u8 *PN, u8 AddCount) -{ - u8 i; - - if (NULL == PN) - return 1; - //YJ,test,091102 - /* - if(AddCount == 2){ - DBG_8192C("############################%s(): PN[0]=0x%x\n", __FUNCTION__, PN[0]); - if(PN[0] == 0x48){ - PN[0] += AddCount; - return 1; - }else{ - PN[0] += AddCount; - return 0; - } - } - */ - //YJ,test,091102,end - - for (i=0; i<16; i++) - { - if (PN[i] + AddCount <= 0xff) - { - PN[i] += AddCount; - return 0; - } - else - { - PN[i] += AddCount; - AddCount = 1; - } - } - return 1; -} - - -void WapiGetLastRxUnicastPNForQoSData( - u8 UserPriority, - PRT_WAPI_STA_INFO pWapiStaInfo, - u8 *PNOut -) -{ - WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__); - switch(UserPriority) - { - case 0: - case 3: - memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBEQueue,16); - break; - case 1: - case 2: - memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBKQueue,16); - break; - case 4: - case 5: - memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVIQueue,16); - break; - case 6: - case 7: - memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVOQueue,16); - break; - default: - WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__); - break; - } - WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__); -} - - -void WapiSetLastRxUnicastPNForQoSData( - u8 UserPriority, - u8 *PNIn, - PRT_WAPI_STA_INFO pWapiStaInfo -) -{ - WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__); - switch(UserPriority) - { - case 0: - case 3: - memcpy(pWapiStaInfo->lastRxUnicastPNBEQueue,PNIn,16); - break; - case 1: - case 2: - memcpy(pWapiStaInfo->lastRxUnicastPNBKQueue,PNIn,16); - break; - case 4: - case 5: - memcpy(pWapiStaInfo->lastRxUnicastPNVIQueue,PNIn,16); - break; - case 6: - case 7: - memcpy(pWapiStaInfo->lastRxUnicastPNVOQueue,PNIn,16); - break; - default: - WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__); - break; - } - WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__); -} - - -/**************************************************************************** - FALSE not RX-Reorder - TRUE do RX Reorder -add to support WAPI to N-mode -*****************************************************************************/ -u8 WapiCheckPnInSwDecrypt( - _adapter *padapter, - struct sk_buff *pskb -) -{ - u8 ret = false; - -#if 0 - struct ieee80211_hdr_3addr_qos *header; - u16 fc; - u8 *pDaddr, *pTaddr, *pRaddr; - - header = (struct ieee80211_hdr_3addr_qos *)pskb->data; - pTaddr = header->addr2; - pRaddr = header->addr1; - fc = le16_to_cpu(header->frame_ctl); - - if(GetToDs(&fc)) - pDaddr = header->addr3; - else - pDaddr = header->addr1; - - if ((_rtw_memcmp(pRaddr, padapter->pnetdev->dev_addr, ETH_ALEN) == 0) - && ! (pDaddr) - && (GetFrameType(&fc) == WIFI_QOS_DATA_TYPE)) - //&& ieee->pHTInfo->bCurrentHTSupport && - //ieee->pHTInfo->bCurRxReorderEnable) - ret = false; - else - ret = true; -#endif - WAPI_TRACE(WAPI_RX, "%s: return %d\n", __FUNCTION__, ret); - return ret; -} - -int SecSMS4HeaderFillIV(_adapter *padapter, u8 *pxmitframe) -{ - struct pkt_attrib *pattrib = &((struct xmit_frame*)pxmitframe)->attrib; - u8 * frame = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET; - u8 *pSecHeader = NULL, *pos = NULL, *pRA = NULL; - u8 bPNOverflow = false, bFindMatchPeer = false, hdr_len = 0; - PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL; - PRT_WAPI_T pWapiInfo = &padapter->wapiInfo; - PRT_WAPI_STA_INFO pWapiSta = NULL; - int ret = 0; - - WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__); - - return ret; -#if 0 - hdr_len = sMacHdrLng; - if (GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE) - { - hdr_len += 2; - } - //hdr_len += SNAP_SIZE + sizeof(u16); - - pos = skb_push(pskb, padapter->wapiInfo.extra_prefix_len); - memmove(pos, pos+padapter->wapiInfo.extra_prefix_len, hdr_len); - - pSecHeader = pskb->data + hdr_len; - pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)pSecHeader; - pRA = pskb->data + 4; - - WAPI_DATA(WAPI_TX, "FillIV - Before Fill IV", pskb->data, pskb->len); - - //Address 1 is always receiver's address - if( IS_MCAST(pRA) ){ - if(!pWapiInfo->wapiTxMsk.bTxEnable){ - WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__); - return -2; - } - if(pWapiInfo->wapiTxMsk.keyId <= 1){ - pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId; - pWapiExt->Reserved = 0; - bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1); - memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16); - if (bPNOverflow){ - // Update MSK Notification. - WAPI_TRACE(WAPI_ERR,"===============>%s():multicast PN overflow\n",__FUNCTION__); - rtw_wapi_app_event_handler(padapter,NULL,0,pRA, false, false, true, 0, false); - } - }else{ - WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Multicast KeyIdx!!\n",__FUNCTION__); - ret = -3; - } - } - else{ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { - if(!memcmp(pWapiSta->PeerMacAddr,pRA,6)){ - bFindMatchPeer = true; - break; - } - } - if (bFindMatchPeer){ - if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable)){ - WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__); - return -4; - } - if (pWapiSta->wapiUsk.keyId <= 1){ - if(pWapiSta->wapiUskUpdate.bTxEnable) - pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId; - else - pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId; - - pWapiExt->Reserved = 0; - bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2); - memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16); - if (bPNOverflow){ - // Update USK Notification. - WAPI_TRACE(WAPI_ERR,"===============>%s():unicast PN overflow\n",__FUNCTION__); - rtw_wapi_app_event_handler(padapter,NULL,0,pWapiSta->PeerMacAddr, false, true, false, 0, false); - } - }else{ - WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Unicast KeyIdx!!\n",__FUNCTION__); - ret = -5; - } - } - else{ - WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta "MAC_FMT"!!\n",__FUNCTION__, MAC_ARG(pRA)); - ret = -6; - } - } - - WAPI_DATA(WAPI_TX, "FillIV - After Fill IV", pskb->data, pskb->len); - WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__); - return ret; -#endif -} - -// WAPI SW Enc: must have done Coalesce! -void SecSWSMS4Encryption( - _adapter *padapter, - u8 * pxmitframe - ) -{ - PRT_WAPI_T pWapiInfo = &padapter->wapiInfo; - PRT_WAPI_STA_INFO pWapiSta = NULL; - u8 *pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_SIZE; - struct pkt_attrib *pattrib = &((struct xmit_frame*)pxmitframe)->attrib; - - u8 *SecPtr = NULL, *pRA, *pMicKey = NULL, *pDataKey = NULL, *pIV = NULL; - u8 IVOffset, DataOffset, bFindMatchPeer = false, KeyIdx = 0, MicBuffer[16]; - u16 OutputLength; - - WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__); - - WAPI_TRACE(WAPI_TX,"hdrlen: %d \n",pattrib->hdrlen); - - return; - - DataOffset = pattrib->hdrlen + pattrib->iv_len; - - pRA = pframe + 4; - - - if( IS_MCAST(pRA) ){ - KeyIdx = pWapiInfo->wapiTxMsk.keyId; - pIV = pWapiInfo->lastTxMulticastPN; - pMicKey = pWapiInfo->wapiTxMsk.micKey; - pDataKey = pWapiInfo->wapiTxMsk.dataKey; - }else{ - if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { - if (0 == memcmp(pWapiSta->PeerMacAddr, pRA, 6)){ - bFindMatchPeer = true; - break; - } - } - - if (bFindMatchPeer){ - if (pWapiSta->wapiUskUpdate.bTxEnable){ - KeyIdx = pWapiSta->wapiUskUpdate.keyId; - WAPI_TRACE(WAPI_TX, "%s(): Use update USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx); - pIV = pWapiSta->lastTxUnicastPN; - pMicKey = pWapiSta->wapiUskUpdate.micKey; - pDataKey = pWapiSta->wapiUskUpdate.dataKey; - }else{ - KeyIdx = pWapiSta->wapiUsk.keyId; - WAPI_TRACE(WAPI_TX, "%s(): Use USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx); - pIV = pWapiSta->lastTxUnicastPN; - pMicKey = pWapiSta->wapiUsk.micKey; - pDataKey = pWapiSta->wapiUsk.dataKey; - } - }else{ - WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta!!\n",__FUNCTION__); - return; - } - }else{ - WAPI_TRACE(WAPI_ERR,"%s: wapiSTAUsedList is empty!!\n",__FUNCTION__); - return; - } - } - - SecPtr = pframe; - SecCalculateMicSMS4(KeyIdx, pMicKey, SecPtr, (SecPtr+DataOffset), pattrib->pktlen, MicBuffer); - - WAPI_DATA(WAPI_TX, "Encryption - MIC", MicBuffer, padapter->wapiInfo.extra_postfix_len); - - memcpy(pframe+pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen-pattrib->icv_len, - (u8 *)MicBuffer, - padapter->wapiInfo.extra_postfix_len - ); - - - WapiSMS4Encryption(pDataKey, pIV, (SecPtr+DataOffset),pattrib->pktlen+pattrib->icv_len, (SecPtr+DataOffset), &OutputLength); - - WAPI_DATA(WAPI_TX, "Encryption - After SMS4 encryption",pframe,pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen); - - WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__); -} - -u8 SecSWSMS4Decryption( - _adapter *padapter, - u8 *precv_frame, - struct recv_priv *precv_priv - ) -{ - PRT_WAPI_T pWapiInfo = &padapter->wapiInfo; - struct recv_frame_hdr *precv_hdr; - PRT_WAPI_STA_INFO pWapiSta = NULL; - u8 IVOffset, DataOffset, bFindMatchPeer = false, bUseUpdatedKey = false; - u8 KeyIdx, MicBuffer[16], lastRxPNforQoS[16]; - u8 *pRA, *pTA, *pMicKey, *pDataKey, *pLastRxPN, *pRecvPN, *pSecData, *pRecvMic, *pos; - u8 TID = 0; - u16 OutputLength, DataLen; - u8 bQosData; - struct sk_buff * pskb; - - WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__); - - return 0; - - precv_hdr = &((union recv_frame*)precv_frame)->u.hdr; - pskb = (struct sk_buff *)(precv_hdr->rx_data); - precv_hdr->bWapiCheckPNInDecrypt = WapiCheckPnInSwDecrypt(padapter, pskb); - WAPI_TRACE(WAPI_RX, "=========>%s: check PN %d\n", __FUNCTION__,precv_hdr->bWapiCheckPNInDecrypt); - WAPI_DATA(WAPI_RX, "Decryption - Before decryption", pskb->data, pskb->len); - - IVOffset = sMacHdrLng; - bQosData = GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE; - if (bQosData){ - IVOffset += 2; - } - - //if(GetHTC()) - // IVOffset += 4; - - //IVOffset += SNAP_SIZE + sizeof(u16); - - DataOffset = IVOffset + padapter->wapiInfo.extra_prefix_len; - - pRA = pskb->data + 4; - pTA = pskb->data + 10; - KeyIdx = *(pskb->data + IVOffset); - pRecvPN = pskb->data + IVOffset + 2; - pSecData = pskb->data + DataOffset; - DataLen = pskb->len - DataOffset; - pRecvMic = pskb->data + pskb->len - padapter->wapiInfo.extra_postfix_len; - TID = GetTid(pskb->data); - - if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){ - list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { - if (0 == memcmp(pWapiSta->PeerMacAddr, pTA, 6)){ - bFindMatchPeer = true; - break; - } - } - } - - if (!bFindMatchPeer){ - WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT" for Key Info!!!\n", __FUNCTION__, MAC_ARG(pTA)); - return false; - } - - if( IS_MCAST(pRA) ){ - WAPI_TRACE(WAPI_RX, "%s: Multicast decryption !!!\n", __FUNCTION__); - if (pWapiSta->wapiMsk.keyId == KeyIdx && pWapiSta->wapiMsk.bSet){ - pLastRxPN = pWapiSta->lastRxMulticastPN; - if (!WapiComparePN(pRecvPN, pLastRxPN)){ - WAPI_TRACE(WAPI_ERR, "%s: MSK PN is not larger than last, Dropped!!!\n", __FUNCTION__); - WAPI_DATA(WAPI_ERR, "pRecvPN:", pRecvPN, 16); - WAPI_DATA(WAPI_ERR, "pLastRxPN:", pLastRxPN, 16); - return false; - } - - memcpy(pLastRxPN, pRecvPN, 16); - pMicKey = pWapiSta->wapiMsk.micKey; - pDataKey = pWapiSta->wapiMsk.dataKey; - }else if (pWapiSta->wapiMskUpdate.keyId == KeyIdx && pWapiSta->wapiMskUpdate.bSet){ - WAPI_TRACE(WAPI_RX, "%s: Use Updated MSK for Decryption !!!\n", __FUNCTION__); - bUseUpdatedKey = true; - memcpy(pWapiSta->lastRxMulticastPN, pRecvPN, 16); - pMicKey = pWapiSta->wapiMskUpdate.micKey; - pDataKey = pWapiSta->wapiMskUpdate.dataKey; - }else{ - WAPI_TRACE(WAPI_ERR, "%s: Can not find MSK with matched KeyIdx(%d), Dropped !!!\n", __FUNCTION__,KeyIdx); - return false; - } - } - else{ - WAPI_TRACE(WAPI_RX, "%s: Unicast decryption !!!\n", __FUNCTION__); - if (pWapiSta->wapiUsk.keyId == KeyIdx && pWapiSta->wapiUsk.bSet){ - WAPI_TRACE(WAPI_RX, "%s: Use USK for Decryption!!!\n", __FUNCTION__); - if(precv_hdr->bWapiCheckPNInDecrypt){ - if(GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE){ - WapiGetLastRxUnicastPNForQoSData(TID, pWapiSta, lastRxPNforQoS); - pLastRxPN = lastRxPNforQoS; - }else{ - pLastRxPN = pWapiSta->lastRxUnicastPN; - } - if (!WapiComparePN(pRecvPN, pLastRxPN)){ - return false; - } - if(bQosData){ - WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta); - }else{ - memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16); - } - }else{ - memcpy(precv_hdr->WapiTempPN,pRecvPN,16); - } - - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) - { - if ((pRecvPN[0] & 0x1) == 0){ - WAPI_TRACE(WAPI_ERR, "%s: Rx USK PN is not odd when Infra STA mode, Dropped !!!\n", __FUNCTION__); - return false; - } - } - - pMicKey = pWapiSta->wapiUsk.micKey; - pDataKey = pWapiSta->wapiUsk.dataKey; - } - else if (pWapiSta->wapiUskUpdate.keyId == KeyIdx && pWapiSta->wapiUskUpdate.bSet ){ - WAPI_TRACE(WAPI_RX, "%s: Use Updated USK for Decryption!!!\n", __FUNCTION__); - if(pWapiSta->bAuthenticatorInUpdata) - bUseUpdatedKey = true; - else - bUseUpdatedKey = false; - - if(bQosData){ - WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta); - }else{ - memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16); - } - pMicKey = pWapiSta->wapiUskUpdate.micKey; - pDataKey = pWapiSta->wapiUskUpdate.dataKey; - }else{ - WAPI_TRACE(WAPI_ERR, "%s: No valid USK!!!KeyIdx=%d pWapiSta->wapiUsk.keyId=%d pWapiSta->wapiUskUpdate.keyId=%d\n", __FUNCTION__, KeyIdx, pWapiSta->wapiUsk.keyId, pWapiSta->wapiUskUpdate.keyId); - //dump_buf(pskb->data,pskb->len); - return false; - } - } - - WAPI_DATA(WAPI_RX, "Decryption - DataKey", pDataKey, 16); - WAPI_DATA(WAPI_RX, "Decryption - IV", pRecvPN, 16); - WapiSMS4Decryption(pDataKey, pRecvPN, pSecData, DataLen, pSecData, &OutputLength); - - if (OutputLength != DataLen) - WAPI_TRACE(WAPI_ERR, "%s: Output Length Error!!!!\n", __FUNCTION__); - - WAPI_DATA(WAPI_RX, "Decryption - After decryption", pskb->data, pskb->len); - - DataLen -= padapter->wapiInfo.extra_postfix_len; - - SecCalculateMicSMS4(KeyIdx, pMicKey, pskb->data, pSecData, DataLen, MicBuffer); - - WAPI_DATA(WAPI_RX, "Decryption - MIC received", pRecvMic, SMS4_MIC_LEN); - WAPI_DATA(WAPI_RX, "Decryption - MIC calculated", MicBuffer, SMS4_MIC_LEN); - - if (0 == memcmp(MicBuffer, pRecvMic, padapter->wapiInfo.extra_postfix_len)){ - WAPI_TRACE(WAPI_RX, "%s: Check MIC OK!!\n", __FUNCTION__); - if (bUseUpdatedKey){ - // delete the old key - if ( IS_MCAST(pRA) ){ - WAPI_TRACE(WAPI_API, "%s(): AE use new update MSK!!\n", __FUNCTION__); - pWapiSta->wapiMsk.keyId = pWapiSta->wapiMskUpdate.keyId; - memcpy(pWapiSta->wapiMsk.dataKey, pWapiSta->wapiMskUpdate.dataKey, 16); - memcpy(pWapiSta->wapiMsk.micKey, pWapiSta->wapiMskUpdate.micKey, 16); - pWapiSta->wapiMskUpdate.bTxEnable = pWapiSta->wapiMskUpdate.bSet = false; - }else{ - WAPI_TRACE(WAPI_API, "%s(): AE use new update USK!!\n", __FUNCTION__); - pWapiSta->wapiUsk.keyId = pWapiSta->wapiUskUpdate.keyId; - memcpy(pWapiSta->wapiUsk.dataKey, pWapiSta->wapiUskUpdate.dataKey, 16); - memcpy(pWapiSta->wapiUsk.micKey, pWapiSta->wapiUskUpdate.micKey, 16); - pWapiSta->wapiUskUpdate.bTxEnable = pWapiSta->wapiUskUpdate.bSet = false; - } - } - }else{ - WAPI_TRACE(WAPI_ERR, "%s: Check MIC Error, Dropped !!!!\n", __FUNCTION__); - return false; - } - - pos = pskb->data; - memmove(pos+padapter->wapiInfo.extra_prefix_len, pos, IVOffset); - skb_pull(pskb, padapter->wapiInfo.extra_prefix_len); - - WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__); - - return true; -} - -u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe) -{ - - u8 *pframe; - u32 res = _SUCCESS; - - WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable)) - { - WAPI_TRACE(WAPI_TX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__); - return _FAIL; - } - - if(((struct xmit_frame*)pxmitframe)->buf_addr==NULL) - return _FAIL; - - pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_OFFSET; - - SecSWSMS4Encryption(padapter, pxmitframe); - - WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__); - return res; -} - -u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe) -{ - u8 *pframe; - u32 res = _SUCCESS; - - WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__); - - if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable)) - { - WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__); - return _FAIL; - } - - - //drop packet when hw decrypt fail - //return tempraily - return _FAIL; - - //pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data; - - if (false == SecSWSMS4Decryption(padapter, precvframe, &padapter->recvpriv)) - { - WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__FUNCTION__); - return _FAIL; - } - - WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__); - return res; -} - -#else - -u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe) -{ - WAPI_TRACE(WAPI_TX, "=========>Dummy %s\n", __FUNCTION__); - WAPI_TRACE(WAPI_TX, "<=========Dummy %s\n", __FUNCTION__); - return _SUCCESS; -} - -u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe) -{ - WAPI_TRACE(WAPI_RX, "=========>Dummy %s\n", __FUNCTION__); - WAPI_TRACE(WAPI_RX, "<=========Dummy %s\n", __FUNCTION__); - return _SUCCESS; -} - -#endif - -#endif +#ifdef CONFIG_WAPI_SUPPORT
+
+#include <linux/unistd.h>
+#include <linux/etherdevice.h>
+#include <drv_types.h>
+#include <rtw_wapi.h>
+
+
+#ifdef CONFIG_WAPI_SW_SMS4
+
+#define WAPI_LITTLE_ENDIAN
+//#define BIG_ENDIAN
+#define ENCRYPT 0
+#define DECRYPT 1
+
+
+/**********************************************************
+ **********************************************************/
+const u8 Sbox[256] = {
+0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
+0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
+0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
+0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
+0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
+0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
+0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
+0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
+0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
+0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
+0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
+0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
+0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
+0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
+0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
+0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48
+};
+
+const u32 CK[32] = {
+ 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
+ 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
+ 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
+ 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
+ 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
+ 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
+ 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
+ 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };
+
+#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y))))
+
+#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 | \
+ Sbox[(_A) >> 16 & 0xFF] << 16 | \
+ Sbox[(_A) >> 8 & 0xFF] << 8 | \
+ Sbox[(_A) & 0xFF])
+
+#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24))
+#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23))
+
+static void
+xor_block(void *dst, void *src1, void *src2)
+/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned */
+{
+ ((u32 *)dst)[0] = ((u32 *)src1)[0] ^ ((u32 *)src2)[0];
+ ((u32 *)dst)[1] = ((u32 *)src1)[1] ^ ((u32 *)src2)[1];
+ ((u32 *)dst)[2] = ((u32 *)src1)[2] ^ ((u32 *)src2)[2];
+ ((u32 *)dst)[3] = ((u32 *)src1)[3] ^ ((u32 *)src2)[3];
+}
+
+
+void SMS4Crypt(u8 *Input, u8 *Output, u32 *rk)
+{
+ u32 r, mid, x0, x1, x2, x3, *p;
+ p = (u32 *)Input;
+ x0 = p[0];
+ x1 = p[1];
+ x2 = p[2];
+ x3 = p[3];
+#ifdef WAPI_LITTLE_ENDIAN
+ x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+ x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+ x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+ x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+ for (r = 0; r < 32; r += 4)
+ {
+ mid = x1 ^ x2 ^ x3 ^ rk[r + 0];
+ mid = ByteSub(mid);
+ x0 ^= L1(mid);
+ mid = x2 ^ x3 ^ x0 ^ rk[r + 1];
+ mid = ByteSub(mid);
+ x1 ^= L1(mid);
+ mid = x3 ^ x0 ^ x1 ^ rk[r + 2];
+ mid = ByteSub(mid);
+ x2 ^= L1(mid);
+ mid = x0 ^ x1 ^ x2 ^ rk[r + 3];
+ mid = ByteSub(mid);
+ x3 ^= L1(mid);
+ }
+#ifdef WAPI_LITTLE_ENDIAN
+ x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+ x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+ x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+ x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+ p = (u32 *)Output;
+ p[0] = x3;
+ p[1] = x2;
+ p[2] = x1;
+ p[3] = x0;
+}
+
+
+
+void SMS4KeyExt(u8 *Key, u32 *rk, u32 CryptFlag)
+{
+ u32 r, mid, x0, x1, x2, x3, *p;
+
+ p = (u32 *)Key;
+ x0 = p[0];
+ x1 = p[1];
+ x2 = p[2];
+ x3 = p[3];
+#ifdef WAPI_LITTLE_ENDIAN
+ x0 = Rotl(x0, 16); x0 = ((x0 & 0xFF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+ x1 = Rotl(x1, 16); x1 = ((x1 & 0xFF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+ x2 = Rotl(x2, 16); x2 = ((x2 & 0xFF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+ x3 = Rotl(x3, 16); x3 = ((x3 & 0xFF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+
+ x0 ^= 0xa3b1bac6;
+ x1 ^= 0x56aa3350;
+ x2 ^= 0x677d9197;
+ x3 ^= 0xb27022dc;
+ for (r = 0; r < 32; r += 4)
+ {
+ mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
+ mid = ByteSub(mid);
+ rk[r + 0] = x0 ^= L2(mid);
+ mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
+ mid = ByteSub(mid);
+ rk[r + 1] = x1 ^= L2(mid);
+ mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
+ mid = ByteSub(mid);
+ rk[r + 2] = x2 ^= L2(mid);
+ mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
+ mid = ByteSub(mid);
+ rk[r + 3] = x3 ^= L2(mid);
+ }
+ if (CryptFlag == DECRYPT)
+ {
+ for (r = 0; r < 16; r++)
+ mid = rk[r], rk[r] = rk[31 - r], rk[31 - r] = mid;
+ }
+}
+
+
+void WapiSMS4Cryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
+ u8 *Output, u16 *OutputLength, u32 CryptFlag)
+{
+ u32 blockNum,i,j, rk[32];
+ u16 remainder;
+ u8 blockIn[16],blockOut[16], tempIV[16], k;
+
+ *OutputLength = 0;
+ remainder = InputLength & 0x0F;
+ blockNum = InputLength >> 4;
+ if(remainder !=0)
+ blockNum++;
+ else
+ remainder = 16;
+
+ for(k=0;k<16;k++)
+ tempIV[k] = IV[15-k];
+
+ memcpy(blockIn, tempIV, 16);
+
+ SMS4KeyExt((u8 *)Key, rk,CryptFlag);
+
+ for(i=0; i<blockNum-1; i++)
+ {
+ SMS4Crypt((u8 *)blockIn, blockOut, rk);
+ xor_block(&Output[i*16], &Input[i*16], blockOut);
+ memcpy(blockIn,blockOut,16);
+ }
+
+ *OutputLength = i*16;
+
+ SMS4Crypt((u8 *)blockIn, blockOut, rk);
+
+ for(j=0; j<remainder; j++)
+ {
+ Output[i*16+j] = Input[i*16+j] ^ blockOut[j];
+ }
+ *OutputLength += remainder;
+
+}
+
+void WapiSMS4Encryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
+ u8 *Output, u16 *OutputLength)
+{
+
+ WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
+}
+
+void WapiSMS4Decryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
+ u8 *Output, u16 *OutputLength)
+{
+ // OFB mode: is also ENCRYPT flag
+ WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
+}
+
+void WapiSMS4CalculateMic(u8 *Key, u8 *IV, u8 *Input1, u8 Input1Length,
+ u8 *Input2, u16 Input2Length, u8 *Output, u8 *OutputLength)
+{
+ u32 blockNum, i, remainder, rk[32];
+ u8 BlockIn[16], BlockOut[16], TempBlock[16], tempIV[16], k;
+
+ *OutputLength = 0;
+ remainder = Input1Length & 0x0F;
+ blockNum = Input1Length >> 4;
+
+ for(k=0;k<16;k++)
+ tempIV[k] = IV[15-k];
+
+ memcpy(BlockIn, tempIV, 16);
+
+ SMS4KeyExt((u8 *)Key, rk, ENCRYPT);
+
+ SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+
+ for(i=0; i<blockNum; i++){
+ xor_block(BlockIn, (Input1+i*16), BlockOut);
+ SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+ }
+
+ if(remainder !=0){
+ memset(TempBlock, 0, 16);
+ memcpy(TempBlock, (Input1+blockNum*16), remainder);
+
+ xor_block(BlockIn, TempBlock, BlockOut);
+ SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+ }
+
+ remainder = Input2Length & 0x0F;
+ blockNum = Input2Length >> 4;
+
+ for(i=0; i<blockNum; i++){
+ xor_block(BlockIn, (Input2+i*16), BlockOut);
+ SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+ }
+
+ if(remainder !=0){
+ memset(TempBlock, 0, 16);
+ memcpy(TempBlock, (Input2+blockNum*16), remainder);
+
+ xor_block(BlockIn, TempBlock, BlockOut);
+ SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+ }
+
+ memcpy(Output, BlockOut, 16);
+ *OutputLength = 16;
+}
+
+void SecCalculateMicSMS4(
+ u8 KeyIdx,
+ u8 *MicKey,
+ u8 *pHeader,
+ u8 *pData,
+ u16 DataLen,
+ u8 *MicBuffer
+ )
+{
+#if 0
+ struct ieee80211_hdr_3addr_qos *header;
+ u8 TempBuf[34], TempLen = 32, MicLen, QosOffset, *IV;
+ u16 *pTemp, fc;
+
+ WAPI_TRACE(WAPI_TX|WAPI_RX, "=========>%s\n", __FUNCTION__);
+
+ header = (struct ieee80211_hdr_3addr_qos *)pHeader;
+ memset(TempBuf, 0, 34);
+ memcpy(TempBuf, pHeader, 2); //FrameCtrl
+ pTemp = (u16*)TempBuf;
+ *pTemp &= 0xc78f; //bit4,5,6,11,12,13
+
+ memcpy((TempBuf+2), (pHeader+4), 12); //Addr1, Addr2
+ memcpy((TempBuf+14), (pHeader+22), 2); // SeqCtrl
+ pTemp = (u16*)(TempBuf + 14);
+ *pTemp &= 0x000f;
+
+ memcpy((TempBuf+16), (pHeader+16), 6); //Addr3
+
+ fc = le16_to_cpu(header->frame_ctl);
+
+
+
+ if (GetFrDs((u16*)&fc) && GetToDs((u16 *)&fc))
+ {
+ memcpy((TempBuf+22), (pHeader+24), 6);
+ QosOffset = 30;
+ }else{
+ memset((TempBuf+22), 0, 6);
+ QosOffset = 24;
+ }
+
+ if((fc & 0x0088) == 0x0088){
+ memcpy((TempBuf+28), (pHeader+QosOffset), 2);
+ TempLen += 2;
+ //IV = pHeader + QosOffset + 2 + SNAP_SIZE + sizeof(u16) + 2;
+ IV = pHeader + QosOffset + 2 + 2;
+ }else{
+ IV = pHeader + QosOffset + 2;
+ //IV = pHeader + QosOffset + SNAP_SIZE + sizeof(u16) + 2;
+ }
+
+ TempBuf[TempLen-1] = (u8)(DataLen & 0xff);
+ TempBuf[TempLen-2] = (u8)((DataLen & 0xff00)>>8);
+ TempBuf[TempLen-4] = KeyIdx;
+
+ WAPI_DATA(WAPI_TX, "CalculateMic - KEY", MicKey, 16);
+ WAPI_DATA(WAPI_TX, "CalculateMic - IV", IV, 16);
+ WAPI_DATA(WAPI_TX, "CalculateMic - TempBuf", TempBuf, TempLen);
+ WAPI_DATA(WAPI_TX, "CalculateMic - pData", pData, DataLen);
+
+ WapiSMS4CalculateMic(MicKey, IV, TempBuf, TempLen,
+ pData, DataLen, MicBuffer, &MicLen);
+
+ if (MicLen != 16)
+ WAPI_TRACE(WAPI_ERR,"%s: MIC Length Error!!\n",__FUNCTION__);
+
+ WAPI_TRACE(WAPI_TX|WAPI_RX, "<=========%s\n", __FUNCTION__);
+#endif
+}
+
+/* AddCount: 1 or 2.
+ * If overflow, return 1,
+ * else return 0.
+ */
+u8 WapiIncreasePN(u8 *PN, u8 AddCount)
+{
+ u8 i;
+
+ if (NULL == PN)
+ return 1;
+ //YJ,test,091102
+ /*
+ if(AddCount == 2){
+ DBG_8192C("############################%s(): PN[0]=0x%x\n", __FUNCTION__, PN[0]);
+ if(PN[0] == 0x48){
+ PN[0] += AddCount;
+ return 1;
+ }else{
+ PN[0] += AddCount;
+ return 0;
+ }
+ }
+ */
+ //YJ,test,091102,end
+
+ for (i=0; i<16; i++)
+ {
+ if (PN[i] + AddCount <= 0xff)
+ {
+ PN[i] += AddCount;
+ return 0;
+ }
+ else
+ {
+ PN[i] += AddCount;
+ AddCount = 1;
+ }
+ }
+ return 1;
+}
+
+
+void WapiGetLastRxUnicastPNForQoSData(
+ u8 UserPriority,
+ PRT_WAPI_STA_INFO pWapiStaInfo,
+ u8 *PNOut
+)
+{
+ WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+ switch(UserPriority)
+ {
+ case 0:
+ case 3:
+ memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBEQueue,16);
+ break;
+ case 1:
+ case 2:
+ memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBKQueue,16);
+ break;
+ case 4:
+ case 5:
+ memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVIQueue,16);
+ break;
+ case 6:
+ case 7:
+ memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVOQueue,16);
+ break;
+ default:
+ WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+ break;
+ }
+ WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+}
+
+
+void WapiSetLastRxUnicastPNForQoSData(
+ u8 UserPriority,
+ u8 *PNIn,
+ PRT_WAPI_STA_INFO pWapiStaInfo
+)
+{
+ WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+ switch(UserPriority)
+ {
+ case 0:
+ case 3:
+ memcpy(pWapiStaInfo->lastRxUnicastPNBEQueue,PNIn,16);
+ break;
+ case 1:
+ case 2:
+ memcpy(pWapiStaInfo->lastRxUnicastPNBKQueue,PNIn,16);
+ break;
+ case 4:
+ case 5:
+ memcpy(pWapiStaInfo->lastRxUnicastPNVIQueue,PNIn,16);
+ break;
+ case 6:
+ case 7:
+ memcpy(pWapiStaInfo->lastRxUnicastPNVOQueue,PNIn,16);
+ break;
+ default:
+ WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+ break;
+ }
+ WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+}
+
+
+/****************************************************************************
+ FALSE not RX-Reorder
+ TRUE do RX Reorder
+add to support WAPI to N-mode
+*****************************************************************************/
+u8 WapiCheckPnInSwDecrypt(
+ _adapter *padapter,
+ struct sk_buff *pskb
+)
+{
+ u8 ret = false;
+
+#if 0
+ struct ieee80211_hdr_3addr_qos *header;
+ u16 fc;
+ u8 *pDaddr, *pTaddr, *pRaddr;
+
+ header = (struct ieee80211_hdr_3addr_qos *)pskb->data;
+ pTaddr = header->addr2;
+ pRaddr = header->addr1;
+ fc = le16_to_cpu(header->frame_ctl);
+
+ if(GetToDs(&fc))
+ pDaddr = header->addr3;
+ else
+ pDaddr = header->addr1;
+
+ if ((_rtw_memcmp(pRaddr, padapter->pnetdev->dev_addr, ETH_ALEN) == 0)
+ && ! (pDaddr)
+ && (GetFrameType(&fc) == WIFI_QOS_DATA_TYPE))
+ //&& ieee->pHTInfo->bCurrentHTSupport &&
+ //ieee->pHTInfo->bCurRxReorderEnable)
+ ret = false;
+ else
+ ret = true;
+#endif
+ WAPI_TRACE(WAPI_RX, "%s: return %d\n", __FUNCTION__, ret);
+ return ret;
+}
+
+int SecSMS4HeaderFillIV(_adapter *padapter, u8 *pxmitframe)
+{
+ struct pkt_attrib *pattrib = &((struct xmit_frame*)pxmitframe)->attrib;
+ u8 * frame = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
+ u8 *pSecHeader = NULL, *pos = NULL, *pRA = NULL;
+ u8 bPNOverflow = false, bFindMatchPeer = false, hdr_len = 0;
+ PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL;
+ PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+ PRT_WAPI_STA_INFO pWapiSta = NULL;
+ int ret = 0;
+
+ WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+
+ return ret;
+#if 0
+ hdr_len = sMacHdrLng;
+ if (GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE)
+ {
+ hdr_len += 2;
+ }
+ //hdr_len += SNAP_SIZE + sizeof(u16);
+
+ pos = skb_push(pskb, padapter->wapiInfo.extra_prefix_len);
+ memmove(pos, pos+padapter->wapiInfo.extra_prefix_len, hdr_len);
+
+ pSecHeader = pskb->data + hdr_len;
+ pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)pSecHeader;
+ pRA = pskb->data + 4;
+
+ WAPI_DATA(WAPI_TX, "FillIV - Before Fill IV", pskb->data, pskb->len);
+
+ //Address 1 is always receiver's address
+ if( IS_MCAST(pRA) ){
+ if(!pWapiInfo->wapiTxMsk.bTxEnable){
+ WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+ return -2;
+ }
+ if(pWapiInfo->wapiTxMsk.keyId <= 1){
+ pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+ pWapiExt->Reserved = 0;
+ bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1);
+ memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16);
+ if (bPNOverflow){
+ // Update MSK Notification.
+ WAPI_TRACE(WAPI_ERR,"===============>%s():multicast PN overflow\n",__FUNCTION__);
+ rtw_wapi_app_event_handler(padapter,NULL,0,pRA, false, false, true, 0, false);
+ }
+ }else{
+ WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Multicast KeyIdx!!\n",__FUNCTION__);
+ ret = -3;
+ }
+ }
+ else{
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+ if(!memcmp(pWapiSta->PeerMacAddr,pRA,6)){
+ bFindMatchPeer = true;
+ break;
+ }
+ }
+ if (bFindMatchPeer){
+ if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable)){
+ WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+ return -4;
+ }
+ if (pWapiSta->wapiUsk.keyId <= 1){
+ if(pWapiSta->wapiUskUpdate.bTxEnable)
+ pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+ else
+ pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId;
+
+ pWapiExt->Reserved = 0;
+ bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2);
+ memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16);
+ if (bPNOverflow){
+ // Update USK Notification.
+ WAPI_TRACE(WAPI_ERR,"===============>%s():unicast PN overflow\n",__FUNCTION__);
+ rtw_wapi_app_event_handler(padapter,NULL,0,pWapiSta->PeerMacAddr, false, true, false, 0, false);
+ }
+ }else{
+ WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Unicast KeyIdx!!\n",__FUNCTION__);
+ ret = -5;
+ }
+ }
+ else{
+ WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta "MAC_FMT"!!\n",__FUNCTION__, MAC_ARG(pRA));
+ ret = -6;
+ }
+ }
+
+ WAPI_DATA(WAPI_TX, "FillIV - After Fill IV", pskb->data, pskb->len);
+ WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+ return ret;
+#endif
+}
+
+// WAPI SW Enc: must have done Coalesce!
+void SecSWSMS4Encryption(
+ _adapter *padapter,
+ u8 * pxmitframe
+ )
+{
+ PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+ PRT_WAPI_STA_INFO pWapiSta = NULL;
+ u8 *pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_SIZE;
+ struct pkt_attrib *pattrib = &((struct xmit_frame*)pxmitframe)->attrib;
+
+ u8 *SecPtr = NULL, *pRA, *pMicKey = NULL, *pDataKey = NULL, *pIV = NULL;
+ u8 IVOffset, DataOffset, bFindMatchPeer = false, KeyIdx = 0, MicBuffer[16];
+ u16 OutputLength;
+
+ WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+
+ WAPI_TRACE(WAPI_TX,"hdrlen: %d \n",pattrib->hdrlen);
+
+ return;
+
+ DataOffset = pattrib->hdrlen + pattrib->iv_len;
+
+ pRA = pframe + 4;
+
+
+ if( IS_MCAST(pRA) ){
+ KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+ pIV = pWapiInfo->lastTxMulticastPN;
+ pMicKey = pWapiInfo->wapiTxMsk.micKey;
+ pDataKey = pWapiInfo->wapiTxMsk.dataKey;
+ }else{
+ if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+ if (0 == memcmp(pWapiSta->PeerMacAddr, pRA, 6)){
+ bFindMatchPeer = true;
+ break;
+ }
+ }
+
+ if (bFindMatchPeer){
+ if (pWapiSta->wapiUskUpdate.bTxEnable){
+ KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+ WAPI_TRACE(WAPI_TX, "%s(): Use update USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+ pIV = pWapiSta->lastTxUnicastPN;
+ pMicKey = pWapiSta->wapiUskUpdate.micKey;
+ pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+ }else{
+ KeyIdx = pWapiSta->wapiUsk.keyId;
+ WAPI_TRACE(WAPI_TX, "%s(): Use USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+ pIV = pWapiSta->lastTxUnicastPN;
+ pMicKey = pWapiSta->wapiUsk.micKey;
+ pDataKey = pWapiSta->wapiUsk.dataKey;
+ }
+ }else{
+ WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta!!\n",__FUNCTION__);
+ return;
+ }
+ }else{
+ WAPI_TRACE(WAPI_ERR,"%s: wapiSTAUsedList is empty!!\n",__FUNCTION__);
+ return;
+ }
+ }
+
+ SecPtr = pframe;
+ SecCalculateMicSMS4(KeyIdx, pMicKey, SecPtr, (SecPtr+DataOffset), pattrib->pktlen, MicBuffer);
+
+ WAPI_DATA(WAPI_TX, "Encryption - MIC", MicBuffer, padapter->wapiInfo.extra_postfix_len);
+
+ memcpy(pframe+pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen-pattrib->icv_len,
+ (u8 *)MicBuffer,
+ padapter->wapiInfo.extra_postfix_len
+ );
+
+
+ WapiSMS4Encryption(pDataKey, pIV, (SecPtr+DataOffset),pattrib->pktlen+pattrib->icv_len, (SecPtr+DataOffset), &OutputLength);
+
+ WAPI_DATA(WAPI_TX, "Encryption - After SMS4 encryption",pframe,pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen);
+
+ WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+}
+
+u8 SecSWSMS4Decryption(
+ _adapter *padapter,
+ u8 *precv_frame,
+ struct recv_priv *precv_priv
+ )
+{
+ PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+ struct recv_frame_hdr *precv_hdr;
+ PRT_WAPI_STA_INFO pWapiSta = NULL;
+ u8 IVOffset, DataOffset, bFindMatchPeer = false, bUseUpdatedKey = false;
+ u8 KeyIdx, MicBuffer[16], lastRxPNforQoS[16];
+ u8 *pRA, *pTA, *pMicKey, *pDataKey, *pLastRxPN, *pRecvPN, *pSecData, *pRecvMic, *pos;
+ u8 TID = 0;
+ u16 OutputLength, DataLen;
+ u8 bQosData;
+ struct sk_buff * pskb;
+
+ WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
+
+ return 0;
+
+ precv_hdr = &((union recv_frame*)precv_frame)->u.hdr;
+ pskb = (struct sk_buff *)(precv_hdr->rx_data);
+ precv_hdr->bWapiCheckPNInDecrypt = WapiCheckPnInSwDecrypt(padapter, pskb);
+ WAPI_TRACE(WAPI_RX, "=========>%s: check PN %d\n", __FUNCTION__,precv_hdr->bWapiCheckPNInDecrypt);
+ WAPI_DATA(WAPI_RX, "Decryption - Before decryption", pskb->data, pskb->len);
+
+ IVOffset = sMacHdrLng;
+ bQosData = GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE;
+ if (bQosData){
+ IVOffset += 2;
+ }
+
+ //if(GetHTC())
+ // IVOffset += 4;
+
+ //IVOffset += SNAP_SIZE + sizeof(u16);
+
+ DataOffset = IVOffset + padapter->wapiInfo.extra_prefix_len;
+
+ pRA = pskb->data + 4;
+ pTA = pskb->data + 10;
+ KeyIdx = *(pskb->data + IVOffset);
+ pRecvPN = pskb->data + IVOffset + 2;
+ pSecData = pskb->data + DataOffset;
+ DataLen = pskb->len - DataOffset;
+ pRecvMic = pskb->data + pskb->len - padapter->wapiInfo.extra_postfix_len;
+ TID = GetTid(pskb->data);
+
+ if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+ list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+ if (0 == memcmp(pWapiSta->PeerMacAddr, pTA, 6)){
+ bFindMatchPeer = true;
+ break;
+ }
+ }
+ }
+
+ if (!bFindMatchPeer){
+ WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT" for Key Info!!!\n", __FUNCTION__, MAC_ARG(pTA));
+ return false;
+ }
+
+ if( IS_MCAST(pRA) ){
+ WAPI_TRACE(WAPI_RX, "%s: Multicast decryption !!!\n", __FUNCTION__);
+ if (pWapiSta->wapiMsk.keyId == KeyIdx && pWapiSta->wapiMsk.bSet){
+ pLastRxPN = pWapiSta->lastRxMulticastPN;
+ if (!WapiComparePN(pRecvPN, pLastRxPN)){
+ WAPI_TRACE(WAPI_ERR, "%s: MSK PN is not larger than last, Dropped!!!\n", __FUNCTION__);
+ WAPI_DATA(WAPI_ERR, "pRecvPN:", pRecvPN, 16);
+ WAPI_DATA(WAPI_ERR, "pLastRxPN:", pLastRxPN, 16);
+ return false;
+ }
+
+ memcpy(pLastRxPN, pRecvPN, 16);
+ pMicKey = pWapiSta->wapiMsk.micKey;
+ pDataKey = pWapiSta->wapiMsk.dataKey;
+ }else if (pWapiSta->wapiMskUpdate.keyId == KeyIdx && pWapiSta->wapiMskUpdate.bSet){
+ WAPI_TRACE(WAPI_RX, "%s: Use Updated MSK for Decryption !!!\n", __FUNCTION__);
+ bUseUpdatedKey = true;
+ memcpy(pWapiSta->lastRxMulticastPN, pRecvPN, 16);
+ pMicKey = pWapiSta->wapiMskUpdate.micKey;
+ pDataKey = pWapiSta->wapiMskUpdate.dataKey;
+ }else{
+ WAPI_TRACE(WAPI_ERR, "%s: Can not find MSK with matched KeyIdx(%d), Dropped !!!\n", __FUNCTION__,KeyIdx);
+ return false;
+ }
+ }
+ else{
+ WAPI_TRACE(WAPI_RX, "%s: Unicast decryption !!!\n", __FUNCTION__);
+ if (pWapiSta->wapiUsk.keyId == KeyIdx && pWapiSta->wapiUsk.bSet){
+ WAPI_TRACE(WAPI_RX, "%s: Use USK for Decryption!!!\n", __FUNCTION__);
+ if(precv_hdr->bWapiCheckPNInDecrypt){
+ if(GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE){
+ WapiGetLastRxUnicastPNForQoSData(TID, pWapiSta, lastRxPNforQoS);
+ pLastRxPN = lastRxPNforQoS;
+ }else{
+ pLastRxPN = pWapiSta->lastRxUnicastPN;
+ }
+ if (!WapiComparePN(pRecvPN, pLastRxPN)){
+ return false;
+ }
+ if(bQosData){
+ WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+ }else{
+ memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+ }
+ }else{
+ memcpy(precv_hdr->WapiTempPN,pRecvPN,16);
+ }
+
+ if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE))
+ {
+ if ((pRecvPN[0] & 0x1) == 0){
+ WAPI_TRACE(WAPI_ERR, "%s: Rx USK PN is not odd when Infra STA mode, Dropped !!!\n", __FUNCTION__);
+ return false;
+ }
+ }
+
+ pMicKey = pWapiSta->wapiUsk.micKey;
+ pDataKey = pWapiSta->wapiUsk.dataKey;
+ }
+ else if (pWapiSta->wapiUskUpdate.keyId == KeyIdx && pWapiSta->wapiUskUpdate.bSet ){
+ WAPI_TRACE(WAPI_RX, "%s: Use Updated USK for Decryption!!!\n", __FUNCTION__);
+ if(pWapiSta->bAuthenticatorInUpdata)
+ bUseUpdatedKey = true;
+ else
+ bUseUpdatedKey = false;
+
+ if(bQosData){
+ WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+ }else{
+ memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+ }
+ pMicKey = pWapiSta->wapiUskUpdate.micKey;
+ pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+ }else{
+ WAPI_TRACE(WAPI_ERR, "%s: No valid USK!!!KeyIdx=%d pWapiSta->wapiUsk.keyId=%d pWapiSta->wapiUskUpdate.keyId=%d\n", __FUNCTION__, KeyIdx, pWapiSta->wapiUsk.keyId, pWapiSta->wapiUskUpdate.keyId);
+ //dump_buf(pskb->data,pskb->len);
+ return false;
+ }
+ }
+
+ WAPI_DATA(WAPI_RX, "Decryption - DataKey", pDataKey, 16);
+ WAPI_DATA(WAPI_RX, "Decryption - IV", pRecvPN, 16);
+ WapiSMS4Decryption(pDataKey, pRecvPN, pSecData, DataLen, pSecData, &OutputLength);
+
+ if (OutputLength != DataLen)
+ WAPI_TRACE(WAPI_ERR, "%s: Output Length Error!!!!\n", __FUNCTION__);
+
+ WAPI_DATA(WAPI_RX, "Decryption - After decryption", pskb->data, pskb->len);
+
+ DataLen -= padapter->wapiInfo.extra_postfix_len;
+
+ SecCalculateMicSMS4(KeyIdx, pMicKey, pskb->data, pSecData, DataLen, MicBuffer);
+
+ WAPI_DATA(WAPI_RX, "Decryption - MIC received", pRecvMic, SMS4_MIC_LEN);
+ WAPI_DATA(WAPI_RX, "Decryption - MIC calculated", MicBuffer, SMS4_MIC_LEN);
+
+ if (0 == memcmp(MicBuffer, pRecvMic, padapter->wapiInfo.extra_postfix_len)){
+ WAPI_TRACE(WAPI_RX, "%s: Check MIC OK!!\n", __FUNCTION__);
+ if (bUseUpdatedKey){
+ // delete the old key
+ if ( IS_MCAST(pRA) ){
+ WAPI_TRACE(WAPI_API, "%s(): AE use new update MSK!!\n", __FUNCTION__);
+ pWapiSta->wapiMsk.keyId = pWapiSta->wapiMskUpdate.keyId;
+ memcpy(pWapiSta->wapiMsk.dataKey, pWapiSta->wapiMskUpdate.dataKey, 16);
+ memcpy(pWapiSta->wapiMsk.micKey, pWapiSta->wapiMskUpdate.micKey, 16);
+ pWapiSta->wapiMskUpdate.bTxEnable = pWapiSta->wapiMskUpdate.bSet = false;
+ }else{
+ WAPI_TRACE(WAPI_API, "%s(): AE use new update USK!!\n", __FUNCTION__);
+ pWapiSta->wapiUsk.keyId = pWapiSta->wapiUskUpdate.keyId;
+ memcpy(pWapiSta->wapiUsk.dataKey, pWapiSta->wapiUskUpdate.dataKey, 16);
+ memcpy(pWapiSta->wapiUsk.micKey, pWapiSta->wapiUskUpdate.micKey, 16);
+ pWapiSta->wapiUskUpdate.bTxEnable = pWapiSta->wapiUskUpdate.bSet = false;
+ }
+ }
+ }else{
+ WAPI_TRACE(WAPI_ERR, "%s: Check MIC Error, Dropped !!!!\n", __FUNCTION__);
+ return false;
+ }
+
+ pos = pskb->data;
+ memmove(pos+padapter->wapiInfo.extra_prefix_len, pos, IVOffset);
+ skb_pull(pskb, padapter->wapiInfo.extra_prefix_len);
+
+ WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
+
+ return true;
+}
+
+u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
+{
+
+ u8 *pframe;
+ u32 res = _SUCCESS;
+
+ WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_TX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
+ return _FAIL;
+ }
+
+ if(((struct xmit_frame*)pxmitframe)->buf_addr==NULL)
+ return _FAIL;
+
+ pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_OFFSET;
+
+ SecSWSMS4Encryption(padapter, pxmitframe);
+
+ WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+ return res;
+}
+
+u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
+{
+ u8 *pframe;
+ u32 res = _SUCCESS;
+
+ WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
+
+ if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+ {
+ WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
+ return _FAIL;
+ }
+
+
+ //drop packet when hw decrypt fail
+ //return tempraily
+ return _FAIL;
+
+ //pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+
+ if (false == SecSWSMS4Decryption(padapter, precvframe, &padapter->recvpriv))
+ {
+ WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__FUNCTION__);
+ return _FAIL;
+ }
+
+ WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
+ return res;
+}
+
+#else
+
+u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
+{
+ WAPI_TRACE(WAPI_TX, "=========>Dummy %s\n", __FUNCTION__);
+ WAPI_TRACE(WAPI_TX, "<=========Dummy %s\n", __FUNCTION__);
+ return _SUCCESS;
+}
+
+u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
+{
+ WAPI_TRACE(WAPI_RX, "=========>Dummy %s\n", __FUNCTION__);
+ WAPI_TRACE(WAPI_RX, "<=========Dummy %s\n", __FUNCTION__);
+ return _SUCCESS;
+}
+
+#endif
+
+#endif
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_wlan_util.c b/drivers/net/wireless/rtl8723as/core/rtw_wlan_util.c index 182865daaab0..8615468f2648 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_wlan_util.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_wlan_util.c @@ -24,6 +24,9 @@ #include <drv_types.h> #include <wifi.h> +#ifdef CONFIG_WOWLAN +#include <linux/inetdevice.h> +#endif unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f}; unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74}; @@ -361,66 +364,21 @@ void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen) void Save_DM_Func_Flag(_adapter *padapter) { u8 bSaveFlag = _TRUE; - -#ifdef CONFIG_CONCURRENT_MODE - _adapter *pbuddy_adapter = padapter->pbuddy_adapter; - if(pbuddy_adapter) - rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag)); -#endif - rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag)); - } void Restore_DM_Func_Flag(_adapter *padapter) { u8 bSaveFlag = _FALSE; -#ifdef CONFIG_CONCURRENT_MODE - _adapter *pbuddy_adapter = padapter->pbuddy_adapter; - if(pbuddy_adapter) - rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag)); -#endif rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_OP, (u8 *)(&bSaveFlag)); } void Switch_DM_Func(_adapter *padapter, u32 mode, u8 enable) { -#ifdef CONFIG_CONCURRENT_MODE - _adapter *pbuddy_adapter = padapter->pbuddy_adapter; -#endif - if(enable == _TRUE) - { -#ifdef CONFIG_CONCURRENT_MODE - if(pbuddy_adapter) - rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode)); -#endif rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_SET, (u8 *)(&mode)); - } else - { -#ifdef CONFIG_CONCURRENT_MODE - if(pbuddy_adapter) - rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode)); -#endif rtw_hal_set_hwreg(padapter, HW_VAR_DM_FUNC_CLR, (u8 *)(&mode)); - } - -#if 0 - u8 val8; - - val8 = rtw_read8(padapter, FW_DYNAMIC_FUN_SWITCH); - - if(enable == _TRUE) - { - rtw_write8(padapter, FW_DYNAMIC_FUN_SWITCH, (val8 | mode)); - } - else - { - rtw_write8(padapter, FW_DYNAMIC_FUN_SWITCH, (val8 & mode)); - } -#endif - } static void Set_NETYPE1_MSR(_adapter *padapter, u8 type) @@ -454,6 +412,9 @@ inline u8 rtw_get_oper_ch(_adapter *adapter) inline void rtw_set_oper_ch(_adapter *adapter, u8 ch) { + if (adapter_to_dvobj(adapter)->oper_channel != ch) + adapter_to_dvobj(adapter)->on_oper_ch_time = rtw_get_current_time(); + adapter_to_dvobj(adapter)->oper_channel = ch; } @@ -477,6 +438,19 @@ inline void rtw_set_oper_choffset(_adapter *adapter, u8 offset) adapter_to_dvobj(adapter)->oper_ch_offset = offset; } +inline u32 rtw_get_on_oper_ch_time(_adapter *adapter) +{ + return adapter_to_dvobj(adapter)->on_oper_ch_time; +} + +inline u32 rtw_get_on_cur_ch_time(_adapter *adapter) +{ + if (adapter->mlmeextpriv.cur_channel == adapter_to_dvobj(adapter)->oper_channel) + return adapter_to_dvobj(adapter)->on_oper_ch_time; + else + return 0; +} + void SelectChannel(_adapter *padapter, unsigned char channel) { struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; @@ -707,20 +681,25 @@ static u32 _ReadCAM(_adapter *padapter ,u32 addr) return rtw_read32(padapter,REG_CAMREAD); } +#endif void read_cam(_adapter *padapter ,u8 entry) { - u32 j,count = 0, addr, cmd; + u32 j,count = 0, addr; + u32 cam_val[2]; //cam_val[0] is read_val, cam_val[1] is the address addr = entry << 3; DBG_8192C("********* DUMP CAM Entry_#%02d***************\n",entry); for (j = 0; j < 6; j++) { - cmd = _ReadCAM(padapter ,addr+j); - DBG_8192C("offset:0x%02x => 0x%08x \n",addr+j,cmd); + //cmd = _ReadCAM(padapter ,addr+j); + //HW_VAR_CAM_READ + cam_val[1]=addr+j; + rtw_hal_get_hwreg(padapter, HW_VAR_CAM_READ, (u8 *)cam_val); + DBG_8192C("offset:0x%02x => 0x%08x \n",addr+j,cam_val[0]); } DBG_8192C("*********************************\n"); } -#endif + void write_cam(_adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key) { @@ -2612,4 +2591,72 @@ int rtw_handle_dualmac(_adapter *adapter, bool init) exit: return status; } +#ifdef CONFIG_WOWLAN +void rtw_get_current_ip_address(PADAPTER padapter, u8 *pcurrentip) +{ + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct in_device *my_ip_ptr = padapter->pnetdev->ip_ptr; + u8 ipaddress[4]; + + if ( (pmlmeinfo->state & WIFI_FW_LINKING_STATE) ) { + if ( my_ip_ptr != NULL ) { + struct in_ifaddr *my_ifa_list = my_ip_ptr->ifa_list ; + if ( my_ifa_list != NULL ) { + ipaddress[0] = my_ifa_list->ifa_address & 0xFF; + ipaddress[1] = (my_ifa_list->ifa_address >> 8) & 0xFF; + ipaddress[2] = (my_ifa_list->ifa_address >> 16) & 0xFF; + ipaddress[3] = my_ifa_list->ifa_address >> 24; + DBG_871X("%s: %d.%d.%d.%d ==========\n", __func__, + ipaddress[0], ipaddress[1], ipaddress[2], ipaddress[3]); + _rtw_memcpy(pcurrentip, ipaddress, 4); + } + } + } +} +void rtw_get_sec_iv(PADAPTER padapter, u8*pcur_dot11txpn, u8 *StaAddr) +{ + struct sta_info *psta; + struct security_priv *psecpriv = &padapter->securitypriv; + + _rtw_memset(pcur_dot11txpn, 0, 8); + if(NULL == StaAddr) + return; + psta = rtw_get_stainfo(&padapter->stapriv, StaAddr); + DBG_871X("%s(): StaAddr: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + __func__, StaAddr[0], StaAddr[1], StaAddr[2], StaAddr[3], StaAddr[4], StaAddr[5]); + if(psta) + { + if (psecpriv->dot11PrivacyAlgrthm != _NO_PRIVACY_ && psta->dot11txpn.val > 0) + psta->dot11txpn.val--; + + _rtw_memcpy(pcur_dot11txpn, (u8*)&psta->dot11txpn, 8); + + DBG_871X("%s(): CurrentIV: 0x%016llx\n", __func__, psta->dot11txpn.val); + } +} +void rtw_set_sec_iv(PADAPTER padapter) +{ + struct sta_info *psta; + struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); + struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter); + struct security_priv *psecpriv = &padapter->securitypriv; + + psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(&pmlmeinfo->network)); + + if(psta) + { + if (pwrpriv->wowlan_fw_iv > psta->dot11txpn.val) + { + if (psecpriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) + psta->dot11txpn.val = pwrpriv->wowlan_fw_iv + 2; + } else { + DBG_871X("%s(): FW IV is smaller than driver\n", __func__); + psta->dot11txpn.val += 2; + } + DBG_871X("%s: dot11txpn: 0x%016llx\n", __func__ ,psta->dot11txpn.val); + } +} +#endif //CONFIG_WOWLAN diff --git a/drivers/net/wireless/rtl8723as/core/rtw_xmit.c b/drivers/net/wireless/rtl8723as/core/rtw_xmit.c index 0ba3bce864fb..73043534f56c 100755 --- a/drivers/net/wireless/rtl8723as/core/rtw_xmit.c +++ b/drivers/net/wireless/rtl8723as/core/rtw_xmit.c @@ -1960,6 +1960,244 @@ _func_exit_; return res; } +#ifdef CONFIG_IEEE80211W +//broadcast or multicast management pkt use BIP, unicast management pkt use CCMP encryption +s32 rtw_mgmt_xmitframe_coalesce(_adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe) +{ + struct pkt_file pktfile; + s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; + SIZE_PTR addr; + u8 *pframe, *mem_start = NULL, *tmp_buf=NULL; + u8 hw_hdr_offset, subtype ; + struct sta_info *psta = NULL; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct pkt_attrib *pattrib = &pxmitframe->attrib; + u8 *pbuf_start; + s32 bmcst = IS_MCAST(pattrib->ra); + s32 res = _FAIL; + u8 *BIP_AAD; + u8 *MGMT_body=NULL; + + struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + struct rtw_ieee80211_hdr *pwlanhdr; + u8 MME[_MME_IE_LENGTH_]; + + _irqL irqL; + u32 ori_len; + mem_start = pframe = (u8 *)(pxmitframe->buf_addr) + TXDESC_OFFSET; + pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; + tmp_buf = BIP_AAD; + +_func_enter_; + ori_len = BIP_AAD_SIZE+pattrib->pktlen; + tmp_buf = BIP_AAD = rtw_zmalloc(ori_len); + subtype = GetFrameSubType(pframe); //bit(7)~bit(2) + + if(BIP_AAD == NULL) + return _FAIL; + + _enter_critical_bh(&padapter->security_key_mutex, &irqL); + + //only support station mode + if(!check_fwstate(pmlmepriv, WIFI_STATION_STATE) || !check_fwstate(pmlmepriv, _FW_LINKED)) + goto xmitframe_coalesce_success; + + //IGTK key is not install, it may not support 802.11w + if(padapter->securitypriv.binstallBIPkey != _TRUE) + { + DBG_871X("no instll BIP key\n"); + goto xmitframe_coalesce_success; + } + //station mode doesn't need TX BIP, just ready the code + if(bmcst) + { + int frame_body_len; + u8 mic[16]; + + _rtw_memset(MME, 0, 18); + + //other types doesn't need the BIP + if(GetFrameSubType(pframe) != WIFI_DEAUTH && GetFrameSubType(pframe) != WIFI_DISASSOC) + goto xmitframe_coalesce_fail; + + MGMT_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); + pframe += pattrib->pktlen; + + //octent 0 and 1 is key index ,BIP keyid is 4 or 5, LSB only need octent 0 + MME[0]=padapter->securitypriv.dot11wBIPKeyid; + //copy packet number + _rtw_memcpy(&MME[2], &pmlmeext->mgnt_80211w_IPN, 6); + //increase the packet number + pmlmeext->mgnt_80211w_IPN++; + + //add MME IE with MIC all zero, MME string doesn't include element id and length + pframe = rtw_set_ie(pframe, _MME_IE_ , 16 , MME, &(pattrib->pktlen)); + pattrib->last_txcmdsz = pattrib->pktlen; + // total frame length - header length + frame_body_len = pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr); + + //conscruct AAD, copy frame control field + _rtw_memcpy(BIP_AAD, &pwlanhdr->frame_ctl, 2); + ClearRetry(BIP_AAD); + ClearPwrMgt(BIP_AAD); + ClearMData(BIP_AAD); + //conscruct AAD, copy address 1 to address 3 + _rtw_memcpy(BIP_AAD+2, pwlanhdr->addr1, 18); + //copy management fram body + _rtw_memcpy(BIP_AAD+BIP_AAD_SIZE, MGMT_body, frame_body_len); + /*//dump total packet include MME with zero MIC + { + int i; + printk("Total packet: "); + for(i=0; i < BIP_AAD_SIZE+frame_body_len; i++) + printk(" %02x ", BIP_AAD[i]); + printk("\n"); + }*/ + //calculate mic + if(omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey + , BIP_AAD, BIP_AAD_SIZE+frame_body_len, mic)) + goto xmitframe_coalesce_fail; + + /*//dump calculated mic result + { + int i; + printk("Calculated mic result: "); + for(i=0; i<16; i++) + printk(" %02x ", mic[i]); + printk("\n"); + }*/ + //copy right BIP mic value, total is 128bits, we use the 0~63 bits + _rtw_memcpy(pframe-8, mic, 8); + /*/dump all packet after mic ok + { + int pp; + printk("pattrib->pktlen = %d \n", pattrib->pktlen); + for(pp=0;pp< pattrib->pktlen; pp++) + printk(" %02x ", mem_start[pp]); + printk("\n"); + }*/ + } + else //unicast mgmt frame TX + { + //start to encrypt mgmt frame + if(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || + subtype == WIFI_REASSOCREQ || subtype == WIFI_ACTION) + { + if (pattrib->psta) + psta = pattrib->psta; + else + { + psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); + } + + if(psta==NULL) + { + + DBG_871X("%s, psta==NUL\n", __func__); + goto xmitframe_coalesce_fail; + } + + if(!(psta->state & _FW_LINKED) || pxmitframe->buf_addr==NULL) + { + DBG_871X("%s, not _FW_LINKED or addr null\n", __func__); + goto xmitframe_coalesce_fail; + } + + //DBG_871X("%s, action frame category=%d \n", __func__, pframe[WLAN_HDR_A3_LEN]); + //according 802.11-2012 standard, these five types are not robust types + if(subtype == WIFI_ACTION && + (pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_PUBLIC || + pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_HT || + pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_UNPROTECTED_WNM || + pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_SELF_PROTECTED || + pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_P2P)) + goto xmitframe_coalesce_fail; + /*//before encrypt dump the management packet content + { + int i; + printk("Management pkt: "); + for(i=0; i<pattrib->pktlen; i++) + printk(" %02x ", pframe[i]); + printk("=======\n"); + }*/ + + //bakeup original management packet + _rtw_memcpy(tmp_buf, pframe, pattrib->pktlen); + //move to data portion + pframe += pattrib->hdrlen; + + //802.11w unicast management packet must be _AES_ + pattrib->iv_len = 8; + //it's MIC of AES + pattrib->icv_len = 8; + + switch(pattrib->encrypt) + { + case _AES_: + //set AES IV header + AES_IV(pattrib->iv, psta->dot11wtxpn, 0); + break; + default: + goto xmitframe_coalesce_fail; + } + //insert iv header into management frame + _rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len); + pframe += pattrib->iv_len; + //copy mgmt data portion after CCMP header + _rtw_memcpy(pframe, tmp_buf+pattrib->hdrlen, pattrib->pktlen-pattrib->hdrlen); + //move pframe to end of mgmt pkt + pframe += pattrib->pktlen-pattrib->hdrlen; + //add 8 bytes CCMP IV header to length + pattrib->pktlen += pattrib->iv_len; + /*//dump management packet include AES IV header + { + int i; + printk("Management pkt + IV: "); + //for(i=0; i<pattrib->pktlen; i++) + //printk(" %02x ", mem_start[i]); + printk("@@@@@@@@@@@@@\n"); + }*/ + + if ((pattrib->icv_len >0 )&& (pattrib->bswenc)) { + _rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len); + pframe += pattrib->icv_len; + } + //add 8 bytes MIC + pattrib->pktlen += pattrib->icv_len; + //set final tx command size + pattrib->last_txcmdsz = pattrib->pktlen; + + //set protected bit must be beofre SW encrypt + SetPrivacy(mem_start); + /*//dump management packet include AES header + { + int i; + printk("prepare to enc Management pkt + IV: "); + for(i=0; i<pattrib->pktlen; i++) + printk(" %02x ", mem_start[i]); + printk("@@@@@@@@@@@@@\n"); + }*/ + //software encrypt + xmitframe_swencrypt(padapter, pxmitframe); + } + } + +xmitframe_coalesce_success: + _exit_critical_bh(&padapter->security_key_mutex, &irqL); + rtw_mfree(BIP_AAD, ori_len); +_func_exit_; + return _SUCCESS; + +xmitframe_coalesce_fail: + _exit_critical_bh(&padapter->security_key_mutex, &irqL); + rtw_mfree(BIP_AAD, ori_len); +_func_exit_; + + return _FAIL; +} +#endif //CONFIG_IEEE80211W + /* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header * IEEE LLC/SNAP header contains 8 octets * First 3 octets comprise the LLC portion @@ -2996,14 +3234,14 @@ int rtw_br_client_tx(_adapter *padapter, struct sk_buff **pskb) *((unsigned short *)(skb->data+MACADDRLEN*2+2)) = vlan_hdr; } - newskb = skb_copy(skb, GFP_ATOMIC); + newskb = rtw_skb_copy(skb); if (newskb == NULL) { //priv->ext_stats.tx_drops++; - DEBUG_ERR("TX DROP: skb_copy fail!\n"); + DEBUG_ERR("TX DROP: rtw_skb_copy fail!\n"); //goto stop_proc; return -1; } - dev_kfree_skb_any(skb); + rtw_skb_free(skb); *pskb = skb = newskb; if (is_vlan_tag) { @@ -3606,10 +3844,12 @@ void wakeup_sta_to_xmit(_adapter *padapter, struct sta_info *psta) struct sta_priv *pstapriv = &padapter->stapriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + psta_bmc = rtw_get_bcmc_stainfo(padapter); + + //_enter_critical_bh(&psta->sleep_q.lock, &irqL); _enter_critical_bh(&pxmitpriv->lock, &irqL); - xmitframe_phead = get_list_head(&psta->sleep_q); xmitframe_plist = get_next(xmitframe_phead); @@ -3678,52 +3918,12 @@ void wakeup_sta_to_xmit(_adapter *padapter, struct sta_info *psta) } - if(psta->sleepq_len==0) - { -#ifdef CONFIG_TDLS - if( psta->tdls_sta_state & TDLS_LINKED_STATE ) - { - if(psta->state&WIFI_SLEEP_STATE) - psta->state ^= WIFI_SLEEP_STATE; - - //_exit_critical_bh(&psta->sleep_q.lock, &irqL); - _exit_critical_bh(&pxmitpriv->lock, &irqL); - return; - } -#endif //CONFIG_TDLS - pstapriv->tim_bitmap &= ~BIT(psta->aid); - - //DBG_871X("wakeup to xmit, qlen==0, update_BCNTIM, tim=%x\n", pstapriv->tim_bitmap); - //upate BCN for TIM IE - //update_BCNTIM(padapter); - update_mask = BIT(0); - - if(psta->state&WIFI_SLEEP_STATE) - psta->state ^= WIFI_SLEEP_STATE; - - if(psta->state & WIFI_STA_ALIVE_CHK_STATE) - { - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); - } - - //_exit_critical_bh(&psta->sleep_q.lock, &irqL); - _exit_critical_bh(&pxmitpriv->lock, &irqL); - - //for BC/MC Frames - psta_bmc = rtw_get_bcmc_stainfo(padapter); if(!psta_bmc) - return; + goto _exit; if((pstapriv->sta_dz_bitmap&0xfffe) == 0x0)//no any sta in ps mode { - //_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL); - _enter_critical_bh(&pxmitpriv->lock, &irqL); - xmitframe_phead = get_list_head(&psta_bmc->sleep_q); xmitframe_plist = get_next(xmitframe_phead); @@ -3767,11 +3967,42 @@ void wakeup_sta_to_xmit(_adapter *padapter, struct sta_info *psta) update_mask |= BIT(1); } - //_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL); - _exit_critical_bh(&pxmitpriv->lock, &irqL); - } + if(psta->sleepq_len==0) + { +#ifdef CONFIG_TDLS + if( psta->tdls_sta_state & TDLS_LINKED_STATE ) + { + if(psta->state&WIFI_SLEEP_STATE) + psta->state ^= WIFI_SLEEP_STATE; + + goto _exit; + } +#endif //CONFIG_TDLS + pstapriv->tim_bitmap &= ~BIT(psta->aid); + + //DBG_871X("wakeup to xmit, qlen==0, update_BCNTIM, tim=%x\n", pstapriv->tim_bitmap); + //upate BCN for TIM IE + //update_BCNTIM(padapter); + update_mask = BIT(0); + + if(psta->state&WIFI_SLEEP_STATE) + psta->state ^= WIFI_SLEEP_STATE; + + if(psta->state & WIFI_STA_ALIVE_CHK_STATE) + { + psta->expire_to = pstapriv->expire_to; + psta->state ^= WIFI_STA_ALIVE_CHK_STATE; + } + + pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); + } + +_exit: + + //_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL); + _exit_critical_bh(&pxmitpriv->lock, &irqL); if(update_mask) { @@ -4150,8 +4381,66 @@ int rtw_ack_tx_polling(struct xmit_priv *pxmitpriv, u32 timeout_ms) } #endif +#ifdef CONFIG_DETECT_C2H_BY_POLLING +s32 c2h_evt_hdl(_adapter *adapter, struct c2h_evt_hdr *c2h_evt, c2h_id_filter filter); +#endif + int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms) { +#ifdef CONFIG_DETECT_C2H_BY_POLLING + _adapter *adapter = container_of(pxmitpriv, _adapter, xmitpriv); + c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter); + struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; + u8 check_c2hcmd; + u8 check_ccx; + int ret = _FAIL; + + pack_tx_ops->submit_time = rtw_get_current_time(); + pack_tx_ops->timeout_ms = timeout_ms; + pack_tx_ops->status = RTW_SCTX_SUBMITTED; + + do { + rtw_msleep_os(10); + //check_c2hcmd = rtw_read8(adapter, 0x1AF); + //check_ccx = rtw_read8(adapter, 0x1A0); + rtw_hal_get_hwreg(adapter, HW_VAR_C2HEVT_CLEAR, (u8 *)(&check_c2hcmd)); + rtw_hal_get_hwreg(adapter, HW_VAR_C2HEVT_MSG_NORMAL, (u8 *)(&check_ccx)); + + + if (check_c2hcmd != 0) + { + if (check_c2hcmd != 0xFF) + { + c2h_evt_clear(adapter); + } + else if (ccx_id_filter(check_ccx & 0x0F) == _TRUE) + { + c2h_evt_hdl(adapter, NULL, ccx_id_filter); + if (pack_tx_ops->status != RTW_SCTX_SUBMITTED) + break; + + if (adapter->bDriverStopped) { + pack_tx_ops->status = RTW_SCTX_DONE_DRV_STOP; + break; + } + if (adapter->bSurpriseRemoved) { + pack_tx_ops->status = RTW_SCTX_DONE_DEV_REMOVE; + break; + } + } + } + } while (rtw_get_passing_time_ms(pack_tx_ops->submit_time) < timeout_ms); + + if (pack_tx_ops->status == RTW_SCTX_SUBMITTED) { + pack_tx_ops->status = RTW_SCTX_DONE_TIMEOUT; + DBG_871X("%s timeout\n", __func__); + } + + if (pack_tx_ops->status == RTW_SCTX_DONE_SUCCESS) + ret = _SUCCESS; + + return ret; +#else #ifdef CONFIG_XMIT_ACK_POLLING return rtw_ack_tx_polling(pxmitpriv, timeout_ms); #else @@ -4163,6 +4452,7 @@ int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms) return rtw_sctx_wait(pack_tx_ops); #endif +#endif } void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status) |