From 632d9755b6c0480633feca2cad588e63bb78beae Mon Sep 17 00:00:00 2001 From: kimocoder Date: Fri, 23 Aug 2019 10:10:11 +0200 Subject: [PATCH] Cleanup patch files --- core/rtw_ap.c.orig | 5470 ------------ core/rtw_ieee80211.c.orig | 2878 ------- core/rtw_mlme_ext.c | 0 core/rtw_mlme_ext.c.orig | 16784 ------------------------------------ core/rtw_recv.c | 0 5 files changed, 25132 deletions(-) delete mode 100644 core/rtw_ap.c.orig delete mode 100644 core/rtw_ieee80211.c.orig mode change 100755 => 100644 core/rtw_mlme_ext.c delete mode 100755 core/rtw_mlme_ext.c.orig mode change 100755 => 100644 core/rtw_recv.c diff --git a/core/rtw_ap.c.orig b/core/rtw_ap.c.orig deleted file mode 100644 index 6debd94..0000000 --- a/core/rtw_ap.c.orig +++ /dev/null @@ -1,5470 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2017 Realtek Corporation. - * - * 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. - * - *****************************************************************************/ -#define _RTW_AP_C_ - -#include -#include - -#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_priv *pmlmepriv = &(padapter->mlmepriv); - - _rtw_spinlock_init(&pmlmepriv->bcn_update_lock); - /* pmlmeext->bstart_bss = _FALSE; */ -} - -void free_mlme_ap_info(_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - stop_ap_mode(padapter); - _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); - -} - -/* -* Set TIM IE -* return length of total TIM IE -*/ -u8 rtw_set_tim_ie(u8 dtim_cnt, u8 dtim_period - , const u8 *tim_bmp, u8 tim_bmp_len, u8 *tim_ie) -{ - u8 *p = tim_ie; - u8 i, n1, n2; - u8 bmp_len; - - if (rtw_bmp_not_empty(tim_bmp, tim_bmp_len)) { - /* find the first nonzero octet in tim_bitmap */ - for (i = 0; i < tim_bmp_len; i++) - if (tim_bmp[i]) - break; - n1 = i & 0xFE; - - /* find the last nonzero octet in tim_bitmap, except octet 0 */ - for (i = tim_bmp_len - 1; i > 0; i--) - if (tim_bmp[i]) - break; - n2 = i; - bmp_len = n2 - n1 + 1; - } else { - n1 = n2 = 0; - bmp_len = 1; - } - - *p++ = WLAN_EID_TIM; - *p++ = 2 + 1 + bmp_len; - *p++ = dtim_cnt; - *p++ = dtim_period; - *p++ = (rtw_bmp_is_set(tim_bmp, tim_bmp_len, 0) ? BIT0 : 0) | n1; - _rtw_memcpy(p, tim_bmp + n1, bmp_len); - -#if 0 - RTW_INFO("n1:%u, n2:%u, bmp_offset:%u, bmp_len:%u\n", n1, n2, n1 / 2, bmp_len); - RTW_INFO_DUMP("tim_ie: ", tim_ie + 2, 2 + 1 + bmp_len); -#endif - return 2 + 2 + 1 + bmp_len; -} - -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; - -#if 0 - - - /* update TIM IE */ - /* if(rtw_tim_map_anyone_be_set(padapter, pstapriv->tim_bitmap)) */ -#endif - if (_TRUE) { - u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; - uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; - - 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; - - /*calculate 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); - } - - /* append TIM IE */ - dst_ie += rtw_set_tim_ie(0, 1, pstapriv->tim_bitmap, pstapriv->aid_bmp_len, dst_ie); - - /*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; - - } -} - -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 = NULL, *dst_ie = NULL, *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 (dst_ie == NULL) - 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); - } - - *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 = NULL, *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 - RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n" - , MAC_ARG(psta->cmn.mac_addr) - , psta->cmn.rssi_stat.rssi - /* , 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 -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(psta->padapter) && - (psta->sta_stats.last_rx_hwmp_pkts != - psta->sta_stats.rx_hwmp_pkts)) - ret = _TRUE; -#endif - } else - ret = _TRUE; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -/** - * issue_aka_chk_frame - issue active keep alive check frame - * aka = active keep alive - */ -static int issue_aka_chk_frame(_adapter *adapter, struct sta_info *psta) -{ - int ret = _FAIL; - u8 *target_addr = psta->cmn.mac_addr; - - if (MLME_IS_AP(adapter)) { - /* issue null data to check sta alive */ - if (psta->state & WIFI_SLEEP_STATE) - ret = issue_nulldata(adapter, target_addr, 0, 1, 50); - else - ret = issue_nulldata(adapter, target_addr, 0, 3, 50); - } - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(adapter)) { - struct rtw_mesh_path *mpath; - - rtw_rcu_read_lock(); - mpath = rtw_mesh_path_lookup(adapter, target_addr); - if (!mpath) { - mpath = rtw_mesh_path_add(adapter, target_addr); - if (IS_ERR(mpath)) { - rtw_rcu_read_unlock(); - RTW_ERR(FUNC_ADPT_FMT" rtw_mesh_path_add for "MAC_FMT" fail.\n", - FUNC_ADPT_ARG(adapter), MAC_ARG(target_addr)); - return _FAIL; - } - } - if (mpath->flags & RTW_MESH_PATH_ACTIVE) - ret = _SUCCESS; - else { - u8 flags = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_PEER_AKA; - /* issue PREQ to check peer alive */ - rtw_mesh_queue_preq(mpath, flags); - ret = _FALSE; - } - rtw_rcu_read_unlock(); - } -#endif - return ret; -} - -#ifdef RTW_CONFIG_RFREG18_WA -static void rtw_check_restore_rf18(_adapter *padapter) -{ - PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - u32 reg; - u8 union_ch = 0, union_bw = 0, union_offset = 0, setchbw = _FALSE; - - reg = rtw_hal_read_rfreg(padapter, 0, 0x18, 0x3FF); - if ((reg & 0xFF) == 0) - setchbw = _TRUE; - reg = rtw_hal_read_rfreg(padapter, 1, 0x18, 0x3FF); - if ((reg & 0xFF) == 0) - setchbw = _TRUE; - - if (setchbw) { - if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)) { - RTW_INFO("Hit RF(0x18)=0!! restore original channel setting.\n"); - union_ch = pmlmeext->cur_channel; - union_offset = pmlmeext->cur_ch_offset ; - union_bw = pmlmeext->cur_bwmode; - } else { - RTW_INFO("Hit RF(0x18)=0!! set ch(%x) offset(%x) bwmode(%x)\n", union_ch, union_offset, union_bw); - } - /* Initial the channel_bw setting procedure. */ - pHalData->current_channel = 0; - set_channel_bwmode(padapter, union_ch, union_offset, union_bw); - } -} -#endif - -void expire_timeout_chk(_adapter *padapter) -{ - _irqL irqL; - _list *phead, *plist; - u8 updated = _FALSE; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 chk_alive_num = 0; - char chk_alive_list[NUM_STA]; - int i; - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter) - && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) - ) { - struct rtw_mesh_cfg *mcfg = &padapter->mesh_cfg; - - rtw_mesh_path_expire(padapter); - - /* TBD: up layer timeout mechanism */ - /* if (!mcfg->plink_timeout) - return; */ -#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - return; -#endif - } -#endif - -#ifdef CONFIG_MCC_MODE - /* then driver may check fail due to not recv client's frame under sitesurvey, - * don't expire timeout chk under MCC under sitesurvey */ - - if (rtw_hal_mcc_link_status_chk(padapter, __func__) == _FALSE) - return; -#endif - - _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) { - RTW_INFO(FUNC_ADPT_FMT" auth_list, cnt:%u\n" - , FUNC_ADPT_ARG(padapter), 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); - - -#ifdef CONFIG_ATMEL_RC_PATCH - if (_rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->cmn.mac_addr), ETH_ALEN) == _TRUE) - continue; - if (psta->flag_atmel_rc) - continue; -#endif - if (psta->expire_to > 0) { - psta->expire_to--; - if (psta->expire_to == 0) { - rtw_list_delete(&psta->auth_list); - pstapriv->auth_list_cnt--; - - RTW_INFO(FUNC_ADPT_FMT" auth expire "MAC_FMT"\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)); - - _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) { - RTW_INFO(FUNC_ADPT_FMT" asoc_list, cnt:%u\n" - , FUNC_ADPT_ARG(padapter), 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); -#ifdef CONFIG_ATMEL_RC_PATCH - RTW_INFO("%s:%d psta=%p, %02x,%02x||%02x,%02x \n\n", __func__, __LINE__, - psta, pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->cmn.mac_addr[0], psta->cmn.mac_addr[5]); - if (_rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->cmn.mac_addr), ETH_ALEN) == _TRUE) - continue; - if (psta->flag_atmel_rc) - continue; - RTW_INFO("%s: debug line:%d\n", __func__, __LINE__); -#endif -#ifdef CONFIG_AUTO_AP_MODE - if (psta->isrc) - continue; -#endif - 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_80211N_HT -#ifdef CONFIG_TX_MCAST2UNI - 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 */ - /* RTW_INFO("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)) { - RTW_INFO("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)) { - RTW_INFO("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->cmn.mac_addr);/* */ /* originator */ - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ - } - } -#endif /* CONFIG_TX_MCAST2UNI */ -#endif /* CONFIG_80211N_HT */ -#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ - - if (psta->expire_to <= 0) { - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (padapter->registrypriv.wifi_spec == 1) { - psta->expire_to = pstapriv->expire_to; - continue; - } - -#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK -#ifdef CONFIG_80211N_HT - -#define KEEP_ALIVE_TRYCNT (3) - - if (psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT) { - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - else - psta->keep_alive_trycnt = 0; - - } else if ((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE)) - psta->keep_alive_trycnt = 0; - if ((psta->htpriv.ht_option == _TRUE) && (psta->htpriv.ampdu_enable == _TRUE)) { - uint priority = 1; /* test using BK */ - u8 issued = 0; - - /* issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1; */ - issued |= (psta->htpriv.candidate_tid_bitmap >> priority) & 0x1; - - if (0 == issued) { - if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { - psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority); - - if (psta->state & WIFI_SLEEP_STATE) - psta->expire_to = 2; /* 2x2=4 sec */ - else - psta->expire_to = 1; /* 2 sec */ - - psta->state |= WIFI_STA_ALIVE_CHK_STATE; - - /* add_ba_hdl(padapter, (u8*)paddbareq_parm); */ - - RTW_INFO("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt); - - issue_addba_req(padapter, psta->cmn.mac_addr, (u8)priority); - - _set_timer(&psta->addba_retry_timer, ADDBA_TO); - - psta->keep_alive_trycnt++; - - continue; - } - } - } - if (psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE) { - psta->keep_alive_trycnt = 0; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - RTW_INFO("change to another methods to check alive if staion is at ps mode\n"); - } - -#endif /* CONFIG_80211N_HT */ -#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ - 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; - - /* RTW_INFO("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->cmn.mac_addr)); */ - - /* to update bcn with tim_bitmap for this station */ - rtw_tim_map_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid); - update_beacon(padapter, _TIM_IE_, NULL, _TRUE); - - if (!pmlmeext->active_keep_alive_check) - continue; - } - } - - { - 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; - } - } 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) - ) { - RTW_INFO(FUNC_ADPT_FMT" sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr) - , 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); - - if (chk_alive_num) { -#if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) - u8 backup_ch = 0, backup_bw = 0, backup_offset = 0; - u8 union_ch = 0, union_bw = 0, union_offset = 0; - u8 switch_channel_by_drv = _TRUE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; -#endif - char del_asoc_list[NUM_STA]; - - _rtw_memset(del_asoc_list, NUM_STA, NUM_STA); - - #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - if (pmlmeext->active_keep_alive_check) { - #ifdef CONFIG_MCC_MODE - if (MCC_EN(padapter)) { - /* driver doesn't switch channel under MCC */ - if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) - switch_channel_by_drv = _FALSE; - } - #endif - - if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset) - || pmlmeext->cur_channel != union_ch) - switch_channel_by_drv = _FALSE; - - /* switch to correct channel of current network before issue keep-alive frames */ - if (switch_channel_by_drv == _TRUE && rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) { - backup_ch = rtw_get_oper_ch(padapter); - backup_bw = rtw_get_oper_bw(padapter); - backup_offset = rtw_get_oper_choffset(padapter); - set_channel_bwmode(padapter, union_ch, union_offset, union_bw); - } - } - #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ - - /* check loop */ - for (i = 0; i < chk_alive_num; i++) { - #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - int ret = _FAIL; - #endif - - psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]); - - #ifdef CONFIG_ATMEL_RC_PATCH - if (_rtw_memcmp(pstapriv->atmel_rc_pattern, psta->cmn.mac_addr, ETH_ALEN) == _TRUE) - continue; - if (psta->flag_atmel_rc) - continue; - #endif - - if (!(psta->state & _FW_LINKED)) - continue; - - #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - if (pmlmeext->active_keep_alive_check) { - /* issue active keep alive frame to check */ - ret = issue_aka_chk_frame(padapter, psta); - - psta->keep_alive_trycnt++; - if (ret == _SUCCESS) { - RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" is alive\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)); - psta->expire_to = pstapriv->expire_to; - psta->keep_alive_trycnt = 0; - continue; - } else if (psta->keep_alive_trycnt <= 3) { - RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" keep_alive_trycnt=%d\n" - , FUNC_ADPT_ARG(padapter) , MAC_ARG(psta->cmn.mac_addr), psta->keep_alive_trycnt); - psta->expire_to = 1; - continue; - } - } - #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ - - psta->keep_alive_trycnt = 0; - del_asoc_list[i] = chk_alive_list[i]; - _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--; - STA_SET_MESH_PLINK(psta, NULL); - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - } - - /* delete loop */ - for (i = 0; i < chk_alive_num; i++) { - u8 sta_addr[ETH_ALEN]; - - if (del_asoc_list[i] >= NUM_STA) - continue; - - psta = rtw_get_stainfo_by_offset(pstapriv, del_asoc_list[i]); - _rtw_memcpy(sta_addr, psta->cmn.mac_addr, ETH_ALEN); - - RTW_INFO(FUNC_ADPT_FMT" asoc expire "MAC_FMT", state=0x%x\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr), psta->state); - updated |= ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _FALSE); - #ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) - rtw_mesh_expire_peer(padapter, sta_addr); - #endif - } - - #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - if (pmlmeext->active_keep_alive_check) { - /* back to the original operation channel */ - if (switch_channel_by_drv == _TRUE && backup_ch > 0) - set_channel_bwmode(padapter, backup_ch, backup_offset, backup_bw); - } - #endif - } - -#ifdef RTW_CONFIG_RFREG18_WA - rtw_check_restore_rf18(padapter); -#endif - associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL); -} - -void rtw_ap_update_sta_ra_info(_adapter *padapter, struct sta_info *psta) -{ - unsigned char sta_band = 0; - u64 tx_ra_bitmap = 0; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; - - if (!psta) - return; - - if (!(psta->state & _FW_LINKED)) - return; - - rtw_hal_update_sta_ra_info(padapter, psta); - tx_ra_bitmap = psta->cmn.ra_info.ramask; - - if (pcur_network->Configuration.DSConfig > 14) { - - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N; - - if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11A; - - /* 5G band */ -#ifdef CONFIG_80211AC_VHT - if (psta->vhtpriv.vht_option) - sta_band = WIRELESS_11_5AC; -#endif - } 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; - rtw_hal_update_sta_wset(padapter, psta); - RTW_INFO("%s=> mac_id:%d , tx_ra_bitmap:0x%016llx, networkType:0x%02x\n", - __FUNCTION__, psta->cmn.mac_id, tx_ra_bitmap, psta->wireless_mode); -} - -#ifdef CONFIG_BMC_TX_RATE_SELECT -u8 rtw_ap_find_mini_tx_rate(_adapter *adapter) -{ - _irqL irqL; - _list *phead, *plist; - u8 miini_tx_rate = ODM_RATEVHTSS4MCS9, sta_tx_rate; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &adapter->stapriv; - - _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) { - psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - plist = get_next(plist); - - sta_tx_rate = psta->cmn.ra_info.curr_tx_rate & 0x7F; - if (sta_tx_rate < miini_tx_rate) - miini_tx_rate = sta_tx_rate; - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - return miini_tx_rate; -} - -u8 rtw_ap_find_bmc_rate(_adapter *adapter, u8 tx_rate) -{ - PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter); - u8 tx_ini_rate = ODM_RATE6M; - - switch (tx_rate) { - case ODM_RATEVHTSS3MCS9: - case ODM_RATEVHTSS3MCS8: - case ODM_RATEVHTSS3MCS7: - case ODM_RATEVHTSS3MCS6: - case ODM_RATEVHTSS3MCS5: - case ODM_RATEVHTSS3MCS4: - case ODM_RATEVHTSS3MCS3: - case ODM_RATEVHTSS2MCS9: - case ODM_RATEVHTSS2MCS8: - case ODM_RATEVHTSS2MCS7: - case ODM_RATEVHTSS2MCS6: - case ODM_RATEVHTSS2MCS5: - case ODM_RATEVHTSS2MCS4: - case ODM_RATEVHTSS2MCS3: - case ODM_RATEVHTSS1MCS9: - case ODM_RATEVHTSS1MCS8: - case ODM_RATEVHTSS1MCS7: - case ODM_RATEVHTSS1MCS6: - case ODM_RATEVHTSS1MCS5: - case ODM_RATEVHTSS1MCS4: - case ODM_RATEVHTSS1MCS3: - case ODM_RATEMCS15: - case ODM_RATEMCS14: - case ODM_RATEMCS13: - case ODM_RATEMCS12: - case ODM_RATEMCS11: - case ODM_RATEMCS7: - case ODM_RATEMCS6: - case ODM_RATEMCS5: - case ODM_RATEMCS4: - case ODM_RATEMCS3: - case ODM_RATE54M: - case ODM_RATE48M: - case ODM_RATE36M: - case ODM_RATE24M: - tx_ini_rate = ODM_RATE24M; - break; - case ODM_RATEVHTSS3MCS2: - case ODM_RATEVHTSS3MCS1: - case ODM_RATEVHTSS2MCS2: - case ODM_RATEVHTSS2MCS1: - case ODM_RATEVHTSS1MCS2: - case ODM_RATEVHTSS1MCS1: - case ODM_RATEMCS10: - case ODM_RATEMCS9: - case ODM_RATEMCS2: - case ODM_RATEMCS1: - case ODM_RATE18M: - case ODM_RATE12M: - tx_ini_rate = ODM_RATE12M; - break; - case ODM_RATEVHTSS3MCS0: - case ODM_RATEVHTSS2MCS0: - case ODM_RATEVHTSS1MCS0: - case ODM_RATEMCS8: - case ODM_RATEMCS0: - case ODM_RATE9M: - case ODM_RATE6M: - tx_ini_rate = ODM_RATE6M; - break; - case ODM_RATE11M: - case ODM_RATE5_5M: - case ODM_RATE2M: - case ODM_RATE1M: - tx_ini_rate = ODM_RATE1M; - break; - default: - tx_ini_rate = ODM_RATE6M; - break; - } - - if (hal_data->current_band_type == BAND_ON_5G) - if (tx_ini_rate < ODM_RATE6M) - tx_ini_rate = ODM_RATE6M; - - return tx_ini_rate; -} - -void rtw_update_bmc_sta_tx_rate(_adapter *adapter) -{ - struct sta_info *psta = NULL; - u8 tx_rate; - - psta = rtw_get_bcmc_stainfo(adapter); - if (psta == NULL) { - RTW_ERR(ADPT_FMT "could not get bmc_sta !!\n", ADPT_ARG(adapter)); - return; - } - - if (adapter->bmc_tx_rate != MGN_UNKNOWN) { - psta->init_rate = adapter->bmc_tx_rate; - goto _exit; - } - - if (adapter->stapriv.asoc_sta_count <= 2) - goto _exit; - - tx_rate = rtw_ap_find_mini_tx_rate(adapter); - #ifdef CONFIG_BMC_TX_LOW_RATE - tx_rate = rtw_ap_find_bmc_rate(adapter, tx_rate); - #endif - - psta->init_rate = hw_rate_to_m_rate(tx_rate); - -_exit: - RTW_INFO(ADPT_FMT" BMC Tx rate - %s\n", ADPT_ARG(adapter), MGN_RATE_STR(psta->init_rate)); -} -#endif - -void rtw_init_bmc_sta_tx_rate(_adapter *padapter, struct sta_info *psta) -{ -#ifdef CONFIG_BMC_TX_LOW_RATE - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); -#endif - u8 rate_idx = 0; - u8 brate_table[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M, - MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M}; - - if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter)) - return; - - if (padapter->bmc_tx_rate != MGN_UNKNOWN) - psta->init_rate = padapter->bmc_tx_rate; - else { - #ifdef CONFIG_BMC_TX_LOW_RATE - if (IsEnableHWOFDM(pmlmeext->cur_wireless_mode) && (psta->cmn.ra_info.ramask && 0xFF0)) - rate_idx = get_lowest_rate_idx_ex(psta->cmn.ra_info.ramask, 4); /*from basic rate*/ - else - rate_idx = get_lowest_rate_idx(psta->cmn.ra_info.ramask); /*from basic rate*/ - #else - rate_idx = get_highest_rate_idx(psta->cmn.ra_info.ramask); /*from basic rate*/ - #endif - if (rate_idx < 12) - psta->init_rate = brate_table[rate_idx]; - else - psta->init_rate = MGN_1M; - } - - RTW_INFO(ADPT_FMT" BMC Init Tx rate - %s\n", ADPT_ARG(padapter), MGN_RATE_STR(psta->init_rate)); -} - -void update_bmc_sta(_adapter *padapter) -{ - _irqL irqL; - unsigned char network_type; - int supportRateNum = 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->cmn.aid = 0;/* default set to 0 */ -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) - psta->qos_option = 1; - else -#endif - 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. */ - - supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates); - network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig); - if (IsSupportedTxCCK(network_type)) - network_type = WIRELESS_11B; - else if (network_type == WIRELESS_INVALID) { /* error handling */ - if (pcur_network->Configuration.DSConfig > 14) - network_type = WIRELESS_11A; - else - network_type = WIRELESS_11B; - } - update_sta_basic_rate(psta, network_type); - psta->wireless_mode = network_type; - - rtw_hal_update_sta_ra_info(padapter, psta); - - _enter_critical_bh(&psta->lock, &irqL); - psta->state = _FW_LINKED; - _exit_critical_bh(&psta->lock, &irqL); - - rtw_sta_media_status_rpt(padapter, psta, 1); - rtw_init_bmc_sta_tx_rate(padapter, psta); - - } else - RTW_INFO("add_RATid_bmc_sta error!\n"); - -} - -#if defined(CONFIG_80211N_HT) && defined(CONFIG_BEAMFORMING) -void update_sta_info_apmode_ht_bf_cap(_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; - struct ht_priv *phtpriv_sta = &psta->htpriv; - - u8 cur_beamform_cap = 0; - - /*Config Tx beamforming setting*/ - if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) && - GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap))) { - SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE); - /*Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/ - SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 6); - } - - if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) && - GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap))) { - SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE); - /*Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/ - SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 4); - } - if (cur_beamform_cap) - RTW_INFO("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->cmn.aid, cur_beamform_cap); - - phtpriv_sta->beamform_cap = cur_beamform_cap; - psta->cmn.bf_info.ht_beamform_cap = cur_beamform_cap; - -} -#endif /*CONFIG_80211N_HT && CONFIG_BEAMFORMING*/ - -/* notes: - * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */ -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 */ - u8 cur_ldpc_cap = 0, cur_stbc_cap = 0; - /* set intf_tag to if1 */ - /* psta->intf_tag = 0; */ - - RTW_INFO("%s\n", __FUNCTION__); - - /*alloc macid when call rtw_alloc_stainfo(),release macid when call rtw_free_stainfo()*/ - - if (!MLME_IS_MESH(padapter) && 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; - - phtpriv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; - - /* bwmode */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) - psta->cmn.bw_mode = CHANNEL_WIDTH_40; - else - psta->cmn.bw_mode = CHANNEL_WIDTH_20; - - if (phtpriv_sta->op_present - && !GET_HT_OP_ELE_STA_CHL_WIDTH(phtpriv_sta->ht_op)) - psta->cmn.bw_mode = CHANNEL_WIDTH_20; - - if (psta->ht_40mhz_intolerant) - psta->cmn.bw_mode = CHANNEL_WIDTH_20; - - if (pmlmeext->cur_bwmode < psta->cmn.bw_mode) - psta->cmn.bw_mode = pmlmeext->cur_bwmode; - - phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; - - - /* check if sta support s Short GI 20M */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) - phtpriv_sta->sgi_20m = _TRUE; - - /* check if sta support s Short GI 40M */ - if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) { - if (psta->cmn.bw_mode == CHANNEL_WIDTH_40) /* according to psta->bw_mode */ - phtpriv_sta->sgi_40m = _TRUE; - else - phtpriv_sta->sgi_40m = _FALSE; - } - - psta->qos_option = _TRUE; - - /* B0 Config LDPC Coding Capability */ - if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) && - GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap))) { - SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX)); - RTW_INFO("Enable HT Tx LDPC for STA(%d)\n", psta->cmn.aid); - } - - /* B7 B8 B9 Config STBC setting */ - if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) && - GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap))) { - SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX)); - RTW_INFO("Enable HT Tx STBC for STA(%d)\n", psta->cmn.aid); - } - - #ifdef CONFIG_BEAMFORMING - update_sta_info_apmode_ht_bf_cap(padapter, psta); - #endif - } else { - phtpriv_sta->ampdu_enable = _FALSE; - - phtpriv_sta->sgi_20m = _FALSE; - phtpriv_sta->sgi_40m = _FALSE; - psta->cmn.bw_mode = CHANNEL_WIDTH_20; - phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - phtpriv_sta->ldpc_cap = cur_ldpc_cap; - phtpriv_sta->stbc_cap = cur_stbc_cap; - - /* Rx AMPDU */ - send_delba(padapter, 0, psta->cmn.mac_addr);/* recipient */ - - /* TX AMPDU */ - send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */ - phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */ - phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */ -#endif /* CONFIG_80211N_HT */ - -#ifdef CONFIG_80211AC_VHT - update_sta_vht_info_apmode(padapter, psta); -#endif - psta->cmn.ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta)); - update_ldpc_stbc_cap(psta); - - /* 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() */ - - /* ap mode */ - rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE); - - _enter_critical_bh(&psta->lock, &irqL); - - /* Check encryption */ - if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) - psta->state |= WIFI_UNDER_KEY_HANDSHAKE; - - psta->state |= _FW_LINKED; - - _exit_critical_bh(&psta->lock, &irqL); -} - -static void update_ap_info(_adapter *padapter, struct sta_info *psta) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); -#ifdef CONFIG_80211N_HT - struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; -#endif /* CONFIG_80211N_HT */ - - psta->wireless_mode = pmlmeext->cur_wireless_mode; - - psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates); - _rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen); - -#ifdef CONFIG_80211N_HT - /* HT related cap */ - if (phtpriv_ap->ht_option) { - /* check if sta supports rx ampdu */ - /* phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable; */ - - /* check if sta support s Short GI 20M */ - if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) - phtpriv_ap->sgi_20m = _TRUE; - /* check if sta support s Short GI 40M */ - if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) - phtpriv_ap->sgi_40m = _TRUE; - - psta->qos_option = _TRUE; - } else { - phtpriv_ap->ampdu_enable = _FALSE; - - phtpriv_ap->sgi_20m = _FALSE; - phtpriv_ap->sgi_40m = _FALSE; - } - - psta->cmn.bw_mode = pmlmeext->cur_bwmode; - phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset; - - phtpriv_ap->agg_enable_bitmap = 0x0;/* reset */ - phtpriv_ap->candidate_tid_bitmap = 0x0;/* reset */ - - _rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv)); - -#ifdef CONFIG_80211AC_VHT - _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv)); -#endif /* CONFIG_80211AC_VHT */ - -#endif /* CONFIG_80211N_HT */ - - psta->state |= WIFI_AP_STATE; /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */ -} - -static void rtw_set_hw_wmm_param(_adapter *padapter) -{ - u8 AIFS, ECWMin, ECWMax, aSifsTime; - u8 acm_mask; - u16 TXOP; - u32 acParm, i; - u32 edca[4], inx[4]; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - - acm_mask = 0; -#ifdef CONFIG_80211N_HT - if (pregpriv->ht_enable && - (is_supported_5g(pmlmeext->cur_wireless_mode) || - (pmlmeext->cur_wireless_mode & WIRELESS_11_24N))) - aSifsTime = 16; - else -#endif /* CONFIG_80211N_HT */ - aSifsTime = 10; - - if (pmlmeinfo->WMM_enable == 0) { - padapter->mlmepriv.acm_mask = 0; - - AIFS = aSifsTime + (2 * pmlmeinfo->slotTime); - - if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) { - ECWMin = 4; - ECWMax = 10; - } else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) { - ECWMin = 5; - ECWMax = 10; - } else { - ECWMin = 4; - ECWMax = 10; - } - - TXOP = 0; - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm)); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm)); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm)); - - ECWMin = 2; - ECWMax = 3; - TXOP = 0x2f; - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm)); - - } else { - edca[0] = edca[1] = edca[2] = edca[3] = 0; - - /*TODO:*/ - acm_mask = 0; - padapter->mlmepriv.acm_mask = acm_mask; - -#if 0 - /* BK */ - /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */ -#endif - AIFS = (7 * pmlmeinfo->slotTime) + aSifsTime; - ECWMin = 4; - ECWMax = 10; - TXOP = 0; - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm)); - edca[XMIT_BK_QUEUE] = acParm; - RTW_INFO("WMM(BK): %x\n", acParm); - - /* BE */ - AIFS = (3 * pmlmeinfo->slotTime) + aSifsTime; - ECWMin = 4; - ECWMax = 6; - TXOP = 0; - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm)); - edca[XMIT_BE_QUEUE] = acParm; - RTW_INFO("WMM(BE): %x\n", acParm); - - /* VI */ - AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime; - ECWMin = 3; - ECWMax = 4; - TXOP = 94; - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm)); - edca[XMIT_VI_QUEUE] = acParm; - RTW_INFO("WMM(VI): %x\n", acParm); - - /* VO */ - AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime; - ECWMin = 2; - ECWMax = 3; - TXOP = 47; - acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16); - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm)); - edca[XMIT_VO_QUEUE] = acParm; - RTW_INFO("WMM(VO): %x\n", acParm); - - - if (padapter->registrypriv.acm_method == 1) - rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask)); - else - padapter->mlmepriv.acm_mask = acm_mask; - - inx[0] = 0; - inx[1] = 1; - inx[2] = 2; - inx[3] = 3; - - if (pregpriv->wifi_spec == 1) { - u32 j, tmp, change_inx = _FALSE; - - /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ - for (i = 0 ; i < 4 ; i++) { - for (j = i + 1 ; j < 4 ; j++) { - /* compare CW and AIFS */ - if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) - change_inx = _TRUE; - else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) { - /* compare TXOP */ - if ((edca[j] >> 16) > (edca[i] >> 16)) - change_inx = _TRUE; - } - - if (change_inx) { - tmp = edca[i]; - edca[i] = edca[j]; - edca[j] = tmp; - - tmp = inx[i]; - inx[i] = inx[j]; - inx[j] = tmp; - - change_inx = _FALSE; - } - } - } - } - - for (i = 0 ; i < 4 ; i++) { - pxmitpriv->wmm_para_seq[i] = inx[i]; - RTW_INFO("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]); - } - - } - -} -#ifdef CONFIG_80211N_HT -static void update_hw_ht_param(_adapter *padapter) -{ - unsigned char max_AMPDU_len; - unsigned char min_MPDU_spacing; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - RTW_INFO("%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) { -#if 0 - 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]; -#endif - RTW_INFO("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __FUNCTION__); - } - - /* */ - /* Config current HT Protection mode. */ - /* */ - /* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */ - -} -#endif /* CONFIG_80211N_HT */ -static void rtw_ap_check_scan(_adapter *padapter) -{ - _irqL irqL; - _list *plist, *phead; - u32 delta_time, lifetime; - struct wlan_network *pnetwork = NULL; - WLAN_BSSID_EX *pbss = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - _queue *queue = &(pmlmepriv->scanned_queue); - u8 do_scan = _FALSE; - u8 reason = RTW_AUTO_SCAN_REASON_UNSPECIFIED; - - lifetime = SCANQUEUE_LIFETIME; /* 20 sec */ - - _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); - phead = get_list_head(queue); - if (rtw_end_of_queue_search(phead, get_next(phead)) == _TRUE) - if (padapter->registrypriv.wifi_spec) { - do_scan = _TRUE; - reason |= RTW_AUTO_SCAN_REASON_2040_BSS; - } - _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); - -#ifdef CONFIG_RTW_ACS - if (padapter->registrypriv.acs_auto_scan) { - do_scan = _TRUE; - reason |= RTW_AUTO_SCAN_REASON_ACS; - rtw_acs_start(padapter); - } -#endif/*CONFIG_RTW_ACS*/ - - if (_TRUE == do_scan) { - RTW_INFO("%s : drv scans by itself and wait_completed\n", __func__); - rtw_drv_scan_by_self(padapter, reason); - rtw_scan_wait_completed(padapter); - } - -#ifdef CONFIG_RTW_ACS - if (padapter->registrypriv.acs_auto_scan) - rtw_acs_stop(padapter); -#endif - - _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); - - phead = get_list_head(queue); - plist = get_next(phead); - - while (1) { - - if (rtw_end_of_queue_search(phead, plist) == _TRUE) - break; - - pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); - - if (rtw_chset_search_ch(adapter_to_chset(padapter), pnetwork->network.Configuration.DSConfig) >= 0 - && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE - && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))) { - delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned); - - if (delta_time < lifetime) { - - uint ie_len = 0; - u8 *pbuf = NULL; - u8 *ie = NULL; - - pbss = &pnetwork->network; - ie = pbss->IEs; - - /*check if HT CAP INFO IE exists or not*/ - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss->IELength - _BEACON_IE_OFFSET_)); - if (pbuf == NULL) { - /* HT CAP INFO IE don't exist, it is b/g mode bss.*/ - - if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc)) - ATOMIC_SET(&pmlmepriv->olbc, _TRUE); - - if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht)) - ATOMIC_SET(&pmlmepriv->olbc_ht, _TRUE); - - if (padapter->registrypriv.wifi_spec) - RTW_INFO("%s: %s is a/b/g ap\n", __func__, pnetwork->network.Ssid.Ssid); - } - } - } - - plist = get_next(plist); - - } - - _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); -#ifdef CONFIG_80211N_HT - pmlmepriv->num_sta_no_ht = 0; /* reset to 0 after ap do scanning*/ -#endif -} - -void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter) -{ - WLAN_BSSID_EX *pnetwork = &(adapter->mlmepriv.cur_network.network); - struct sta_info *sta = NULL; - - /* update cur_wireless_mode */ - update_wireless_mode(adapter); - - /* update RRSR and RTS_INIT_RATE register after set channel and bandwidth */ - UpdateBrateTbl(adapter, pnetwork->SupportedRates); - rtw_hal_set_hwreg(adapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates); - - /* update capability after cur_wireless_mode updated */ - update_capinfo(adapter, rtw_get_capability(pnetwork)); - - /* update bc/mc sta_info */ - update_bmc_sta(adapter); - - /* update AP's sta info */ - sta = rtw_get_stainfo(&adapter->stapriv, pnetwork->MacAddress); - if (!sta) { - RTW_INFO(FUNC_ADPT_FMT" !sta for macaddr="MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(pnetwork->MacAddress)); - rtw_warn_on(1); - return; - } - - update_ap_info(adapter, sta); -} - -#ifdef CONFIG_FW_HANDLE_TXBCN -bool rtw_ap_nums_check(_adapter *adapter) -{ - if (rtw_ap_get_nums(adapter) < CONFIG_LIMITED_AP_NUM) - return _TRUE; - return _FALSE; -} -u8 rtw_ap_allocate_vapid(struct dvobj_priv *dvobj) -{ - u8 vap_id; - - for (vap_id = 0; vap_id < CONFIG_LIMITED_AP_NUM; vap_id++) { - if (!(dvobj->vap_map & BIT(vap_id))) - break; - } - - if (vap_id < CONFIG_LIMITED_AP_NUM) - dvobj->vap_map |= BIT(vap_id); - - return vap_id; -} -u8 rtw_ap_release_vapid(struct dvobj_priv *dvobj, u8 vap_id) -{ - if (vap_id >= CONFIG_LIMITED_AP_NUM) { - RTW_ERR("%s - vapid(%d) failed\n", __func__, vap_id); - rtw_warn_on(1); - return _FAIL; - } - dvobj->vap_map &= ~ BIT(vap_id); - return _SUCCESS; -} -#endif -static void _rtw_iface_undersurvey_chk(const char *func, _adapter *adapter) -{ - int i; - _adapter *iface; - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - struct mlme_priv *pmlmepriv; - - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - if ((iface) && rtw_is_adapter_up(iface)) { - pmlmepriv = &iface->mlmepriv; - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) - RTW_ERR("%s ("ADPT_FMT") under survey\n", func, ADPT_ARG(iface)); - } - } -} -void start_bss_network(_adapter *padapter, struct createbss_parm *parm) -{ -#define DUMP_ADAPTERS_STATUS 0 - u8 mlme_act = MLME_ACTION_UNKNOWN; - u8 val8; - u16 bcn_interval; - u32 acparm; - 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; /* used as input */ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network); - struct dvobj_priv *pdvobj = padapter->dvobj; - s16 req_ch = REQ_CH_NONE, req_bw = REQ_BW_NONE, req_offset = REQ_OFFSET_NONE; - u8 ch_to_set = 0, bw_to_set, offset_to_set; - u8 doiqk = _FALSE; - /* use for check ch bw offset can be allowed or not */ - u8 chbw_allow = _TRUE; - int i; - u8 ifbmp_ch_changed = 0; - - if (parm->req_ch != 0) { - /* bypass other setting, go checking ch, bw, offset */ - mlme_act = MLME_OPCH_SWITCH; - req_ch = parm->req_ch; - req_bw = parm->req_bw; - req_offset = parm->req_offset; - goto chbw_decision; - } else { - /* request comes from upper layer */ - if (MLME_IS_AP(padapter)) - mlme_act = MLME_AP_STARTED; - else if (MLME_IS_MESH(padapter)) - mlme_act = MLME_MESH_STARTED; - else - rtw_warn_on(1); - req_ch = 0; - _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length); - } - - bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod; - - /* 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 */ - -#ifdef CONFIG_80211AC_VHT - if (pmlmepriv->vhtpriv.vht_option) { - pmlmeinfo->VHT_enable = _TRUE; - update_hw_vht_param(padapter); - } -#endif /* CONFIG_80211AC_VHT */ - - 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_) - && !MLME_IS_MESH(padapter) /* mesh group key is set before this function */ - ) - 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 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)); - - rtw_hal_rcr_set_chk_bssid(padapter, mlme_act); - -chbw_decision: - ifbmp_ch_changed = rtw_ap_chbw_decision(padapter, parm->ifbmp, parm->excl_ifbmp - , req_ch, req_bw, req_offset - , &ch_to_set, &bw_to_set, &offset_to_set, &chbw_allow); - - for (i = 0; i < pdvobj->iface_nums; i++) { - if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i]) - continue; - - /* let pnetwork_mlme == pnetwork_mlmeext */ - _rtw_memcpy(&(pdvobj->padapters[i]->mlmepriv.cur_network.network) - , &(pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network) - , pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network.Length); - - rtw_start_bss_hdl_after_chbw_decided(pdvobj->padapters[i]); - - /* Set EDCA param reg after update cur_wireless_mode & update_capinfo */ - if (pregpriv->wifi_spec == 1) - rtw_set_hw_wmm_param(pdvobj->padapters[i]); - } - -#if defined(CONFIG_DFS_MASTER) - rtw_dfs_rd_en_decision(padapter, mlme_act, parm->excl_ifbmp); -#endif - -#ifdef CONFIG_MCC_MODE - if (MCC_EN(padapter)) { - /* - * due to check under rtw_ap_chbw_decision - * if under MCC mode, means req channel setting is the same as current channel setting - * if not under MCC mode, mean req channel setting is not the same as current channel setting - */ - if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) { - RTW_INFO(FUNC_ADPT_FMT": req channel setting is the same as current channel setting, go to update BCN\n" - , FUNC_ADPT_ARG(padapter)); - - goto update_beacon; - - } - } - - /* issue null data to AP for all interface connecting to AP before switch channel setting for softap */ - rtw_hal_mcc_issue_null_data(padapter, chbw_allow, 1); -#endif /* CONFIG_MCC_MODE */ - - if (!IS_CH_WAITING(adapter_to_rfctl(padapter))) { - doiqk = _TRUE; - rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk); - } - - if (ch_to_set != 0) { - set_channel_bwmode(padapter, ch_to_set, offset_to_set, bw_to_set); - rtw_mi_update_union_chan_inf(padapter, ch_to_set, offset_to_set, bw_to_set); - } - - doiqk = _FALSE; - rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk); - -#ifdef CONFIG_MCC_MODE - /* after set_channel_bwmode for backup IQK */ - rtw_hal_set_mcc_setting_start_bss_network(padapter, chbw_allow); -#endif - -#if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) - for (i = 0; i < pdvobj->iface_nums; i++) { - if (!(ifbmp_ch_changed & BIT(i)) || !pdvobj->padapters[i]) - continue; - - /* pure AP is not needed*/ - if (MLME_IS_GO(pdvobj->padapters[i]) - || MLME_IS_MESH(pdvobj->padapters[i]) - ) { - u8 ht_option = 0; - - #ifdef CONFIG_80211N_HT - ht_option = pdvobj->padapters[i]->mlmepriv.htpriv.ht_option; - #endif - - rtw_cfg80211_ch_switch_notify(pdvobj->padapters[i] - , pdvobj->padapters[i]->mlmeextpriv.cur_channel - , pdvobj->padapters[i]->mlmeextpriv.cur_bwmode - , pdvobj->padapters[i]->mlmeextpriv.cur_ch_offset - , ht_option); - } - } -#endif /* defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */ - - if (DUMP_ADAPTERS_STATUS) { - RTW_INFO(FUNC_ADPT_FMT" done\n", FUNC_ADPT_ARG(padapter)); - dump_adapters_status(RTW_DBGDUMP , adapter_to_dvobj(padapter)); - } - -#ifdef CONFIG_MCC_MODE -update_beacon: -#endif - - for (i = 0; i < pdvobj->iface_nums; i++) { - struct mlme_priv *mlme; - - if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i]) - continue; - - /* update beacon content only if bstart_bss is _TRUE */ - if (pdvobj->padapters[i]->mlmeextpriv.bstart_bss != _TRUE) - continue; - - mlme = &(pdvobj->padapters[i]->mlmepriv); - - #ifdef CONFIG_80211N_HT - if ((ATOMIC_READ(&mlme->olbc) == _TRUE) || (ATOMIC_READ(&mlme->olbc_ht) == _TRUE)) { - /* AP is not starting a 40 MHz BSS in presence of an 802.11g BSS. */ - mlme->ht_op_mode &= (~HT_INFO_OPERATION_MODE_OP_MODE_MASK); - mlme->ht_op_mode |= OP_MODE_MAY_BE_LEGACY_STAS; - update_beacon(pdvobj->padapters[i], _HT_ADD_INFO_IE_, NULL, _FALSE); - } - #endif - - update_beacon(pdvobj->padapters[i], _TIM_IE_, NULL, _FALSE); - } - - if (mlme_act != MLME_OPCH_SWITCH - && pmlmeext->bstart_bss == _TRUE - ) { -#ifdef CONFIG_SUPPORT_MULTI_BCN - _irqL irqL; - - _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - if (rtw_is_list_empty(&padapter->list)) { - #ifdef CONFIG_FW_HANDLE_TXBCN - padapter->vap_id = rtw_ap_allocate_vapid(pdvobj); - #endif - rtw_list_insert_tail(&padapter->list, get_list_head(&pdvobj->ap_if_q)); - pdvobj->nr_ap_if++; - pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL / pdvobj->nr_ap_if; - } - _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - - #ifdef CONFIG_SWTIMER_BASED_TXBCN - rtw_ap_set_mbid_num(padapter, pdvobj->nr_ap_if); - rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pdvobj->inter_bcn_space)); - #endif /*CONFIG_SWTIMER_BASED_TXBCN*/ - -#endif /*CONFIG_SUPPORT_MULTI_BCN*/ - - #ifdef CONFIG_HW_P0_TSF_SYNC - correct_TSF(padapter, mlme_act); - #endif - } - - rtw_scan_wait_completed(padapter); - - _rtw_iface_undersurvey_chk(__func__, padapter); - /* send beacon */ - ResumeTxBeacon(padapter); - { -#if !defined(CONFIG_INTERRUPT_BASED_TXBCN) -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING) -#ifdef CONFIG_SWTIMER_BASED_TXBCN - if (pdvobj->nr_ap_if == 1 - && mlme_act != MLME_OPCH_SWITCH - ) { - RTW_INFO("start SW BCN TIMER!\n"); - _set_timer(&pdvobj->txbcn_timer, bcn_interval); - } -#else - for (i = 0; i < pdvobj->iface_nums; i++) { - if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i]) - continue; - - if (send_beacon(pdvobj->padapters[i]) == _FAIL) - RTW_INFO(ADPT_FMT" issue_beacon, fail!\n", ADPT_ARG(pdvobj->padapters[i])); - } -#endif -#endif -#endif /* !defined(CONFIG_INTERRUPT_BASED_TXBCN) */ - -#ifdef CONFIG_FW_HANDLE_TXBCN - if (mlme_act != MLME_OPCH_SWITCH) - rtw_ap_mbid_bcn_en(padapter, padapter->vap_id); -#endif - } -} - -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; - u16 cap, ht_cap = _FALSE; - uint ie_len = 0; - int group_cipher, pairwise_cipher; - u32 akm; - u8 mfp_opt = MFP_NO; - u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; - int supportRateNum = 0; - u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01}; - u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - HT_CAP_AMPDU_DENSITY best_ampdu_density; - 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; - u8 *ie = pbss_network->IEs; - u8 vht_cap = _FALSE; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - u8 rf_num = 0; - int ret_rm; - /* 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 */ - - RTW_INFO("%s, len=%d\n", __FUNCTION__, len); - - if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter)) - return _FAIL; - - if (len < 0 || 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 - && pbss_network->InfrastructureMode != Ndis802_11_mesh - ) { - rtw_warn_on(1); - return _FAIL; - } - - - rtw_ap_check_scan(padapter); - - - pbss_network->Rssi = 0; - - _rtw_memcpy(pbss_network->MacAddress, adapter_mac_addr(padapter), 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; -#ifdef CONFIG_P2P - _rtw_memcpy(padapter->wdinfo.p2p_group_ssid, pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength); - padapter->wdinfo.p2p_group_ssid_len = pbss_network->Ssid.SsidLength; -#endif - } - -#ifdef CONFIG_RTW_MESH - /* Mesh ID */ - if (MLME_IS_MESH(padapter)) { - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_MESH_ID, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if (p && ie_len > 0) { - _rtw_memset(&pbss_network->mesh_id, 0, sizeof(NDIS_802_11_SSID)); - _rtw_memcpy(pbss_network->mesh_id.Ssid, (p + 2), ie_len); - pbss_network->mesh_id.SsidLength = ie_len; - } - } -#endif - - /* 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) { - if (padapter->registrypriv.wireless_mode == WIRELESS_11B) { - ret_rm = rtw_remove_ie_g_rate(ie , &len, _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_); - RTW_DBG("%s, rtw_remove_ie_g_rate=%d\n", __FUNCTION__,ret_rm); - ie_len = ie_len - ret_rm; - pbss_network->IELength=pbss_network->IELength - ret_rm; - } - RTW_DBG("%s, ie_len=%u\n", __FUNCTION__, ie_len); - _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) { - if (padapter->registrypriv.wireless_mode == WIRELESS_11B) { - pbss_network->IELength = pbss_network->IELength-*(p+1) -2; - ret_rm = rtw_ies_remove_ie(ie , &len,_BEACON_IE_OFFSET_, - _EXT_SUPPORTEDRATES_IE_,NULL,0); - RTW_DBG("%s, remove_ie of ext_supported rates =%d\n", __FUNCTION__, ret_rm); - } else { - _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) { - if(padapter->registrypriv.wireless_mode == WIRELESS_11B ) { - - pbss_network->IELength = pbss_network->IELength - *(p+1) - 2; - ret_rm = rtw_ies_remove_ie(ie , &len, _BEACON_IE_OFFSET_, _ERPINFO_IE_,NULL,0); - RTW_DBG("%s, remove_ie of ERP_IE=%d\n", __FUNCTION__, ret_rm); - } else - 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 */ - akm = 0; - 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, &akm, &mfp_opt) == _SUCCESS) { - psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; - psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; - psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ - psecuritypriv->wpa_psk |= BIT(1); - - psecuritypriv->wpa2_group_cipher = group_cipher; - psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; - - /* - Kernel < v5.1, the auth_type set as NL80211_AUTHTYPE_AUTOMATIC - in cfg80211_rtw_start_ap(). - if the AKM SAE in the RSN IE, we have to update the auth_type for SAE - in rtw_check_beacon_data(). - */ - if (CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) - psecuritypriv->auth_type = NL80211_AUTHTYPE_SAE; -#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->ndisauthtype = Ndis802_11AuthModeWPAPSK; - 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; - - } - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) { - /* MFP is mandatory for secure mesh */ - if (padapter->mesh_info.mesh_auth_id) - mfp_opt = MFP_REQUIRED; - } else -#endif - if (mfp_opt == MFP_INVALID) { - RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter)); - return _FAIL; - } - psecuritypriv->mfp_opt = mfp_opt; - - /* wmm */ - ie_len = 0; - pmlmepriv->qospriv.qos_option = 0; -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) - pmlmepriv->qospriv.qos_option = 1; -#endif - 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 */ - - WMM_param_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p); - - break; - } - - if ((p == NULL) || (ie_len == 0)) - break; - } - } -#ifdef CONFIG_80211N_HT - if(padapter->registrypriv.ht_enable && - is_supported_ht(padapter->registrypriv.wireless_mode)) { - /* 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 = 0; - HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor = MAX_AMPDU_FACTOR_64K; - struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2); - - if (0) { - RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter)); - dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len); - } - - pHT_caps_ie = p; - - ht_cap = _TRUE; - network_type |= WIRELESS_11_24N; - - rtw_ht_use_default_setting(padapter); - - /* Update HT Capabilities Info field */ - if (pmlmepriv->htpriv.sgi_20m == _FALSE) - pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20); - - if (pmlmepriv->htpriv.sgi_40m == _FALSE) - pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40); - - if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX)) - pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING); - - if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX)) - pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC); - - if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX)) - pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R); - - /* Update A-MPDU Parameters field */ - pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY); - - if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || - (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) { - rtw_hal_get_def_var(padapter, HW_VAR_BEST_AMPDU_DENSITY, &best_ampdu_density); - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (best_ampdu_density << 2)); - } else - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00); - - rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); - pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); /* set Max Rx AMPDU size to 64K */ - - _rtw_memcpy(&(pmlmeinfo->HT_caps), pht_cap, sizeof(struct HT_caps_element)); - - /* Update Supported MCS Set field */ - { - struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter); - u8 rx_nss = 0; - int i; - - rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type)); - rx_nss = rtw_min(rf_type_to_rf_rx_cnt(rf_type), hal_spec->rx_nss_num); - - /* RX MCS Bitmask */ - switch (rx_nss) { - case 1: - set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R); - break; - case 2: - set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R); - break; - case 3: - set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R); - break; - case 4: - set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_4R); - break; - default: - RTW_WARN("rf_type:%d or rx_nss:%u is not expected\n", rf_type, hal_spec->rx_nss_num); - } - for (i = 0; i < 10; i++) - *(HT_CAP_ELE_RX_MCS_MAP(pht_cap) + i) &= padapter->mlmeextpriv.default_supported_mcs_set[i]; - } - -#ifdef CONFIG_BEAMFORMING - /* Use registry value to enable HT Beamforming. */ - /* ToDo: use configure file to set these capability. */ - pht_cap->tx_BF_cap_info = 0; - - /* HT Beamformer */ - if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) { - /* Transmit NDP Capable */ - SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1); - /* Explicit Compressed Steering Capable */ - SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1); - /* Compressed Steering Number Antennas */ - SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1); - rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num); - SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pht_cap, rf_num); - } - - /* HT Beamformee */ - if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) { - /* Receive NDP Capable */ - SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1); - /* Explicit Compressed Beamforming Feedback Capable */ - SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2); - rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num); - SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, rf_num); - } -#endif /* CONFIG_BEAMFORMING */ - - _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len); - - if (0) { - RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter)); - dump_ht_cap_ie_content(RTW_DBGDUMP, 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; - if (channel == 0) - pbss_network->Configuration.DSConfig = GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2); - else if (channel != GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2)) { - RTW_INFO(FUNC_ADPT_FMT" ch inconsistent, DSSS:%u, HT primary:%u\n" - , FUNC_ADPT_ARG(padapter), channel, GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2)); - } - } - } -#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 (padapter->registrypriv.ht_enable && - is_supported_ht(padapter->registrypriv.wireless_mode) && ht_cap == _TRUE) { - - pmlmepriv->htpriv.ht_option = _TRUE; - pmlmepriv->qospriv.qos_option = 1; - - pmlmepriv->htpriv.ampdu_enable = pregistrypriv->ampdu_enable ? _TRUE : _FALSE; - - 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 - -#ifdef CONFIG_80211AC_VHT - pmlmepriv->ori_vht_en = 0; - pmlmepriv->vhtpriv.vht_option = _FALSE; - - if (pmlmepriv->htpriv.ht_option == _TRUE - && pbss_network->Configuration.DSConfig > 14 - && REGSTY_IS_11AC_ENABLE(pregistrypriv) - && is_supported_vht(pregistrypriv->wireless_mode) - && (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent)) - ) { - /* Parsing VHT CAP IE */ - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_)); - if (p && ie_len > 0) - vht_cap = _TRUE; - - /* Parsing VHT OPERATION IE */ - - if (vht_cap == _TRUE - ) { - if(MLME_IS_MESH(padapter)) /* allow only mesh temporarily before VHT IE checking is ready */ - rtw_check_for_vht20(padapter, ie + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_); - pmlmepriv->ori_vht_en = 1; - pmlmepriv->vhtpriv.vht_option = _TRUE; - } else if (REGSTY_IS_11AC_AUTO(pregistrypriv)) { - rtw_vht_ies_detach(padapter, pbss_network); - rtw_vht_ies_attach(padapter, pbss_network); - } - } - - if (pmlmepriv->vhtpriv.vht_option == _FALSE) - rtw_vht_ies_detach(padapter, pbss_network); -#endif /* CONFIG_80211AC_VHT */ - -#ifdef CONFIG_80211N_HT - if(padapter->registrypriv.ht_enable && - is_supported_ht(padapter->registrypriv.wireless_mode) && - pbss_network->Configuration.DSConfig <= 14 && padapter->registrypriv.wifi_spec == 1 && - pbss_network->IELength + 10 <= MAX_IE_SZ) { - uint len = 0; - - SET_EXT_CAPABILITY_ELE_BSS_COEXIST(pmlmepriv->ext_capab_ie_data, 1); - pmlmepriv->ext_capab_ie_len = 10; - rtw_set_ie(pbss_network->IEs + pbss_network->IELength, EID_EXTCapability, 8, pmlmepriv->ext_capab_ie_data, &len); - pbss_network->IELength += pmlmepriv->ext_capab_ie_len; - } -#endif /* CONFIG_80211N_HT */ - - pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network); - - rtw_ies_get_chbw(pbss_network->IEs + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_ - , &pmlmepriv->ori_ch, &pmlmepriv->ori_bw, &pmlmepriv->ori_offset, 1, 1); - rtw_warn_on(pmlmepriv->ori_ch == 0); - - { - /* alloc sta_info for ap itself */ - - struct sta_info *sta; - - sta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress); - if (!sta) { - sta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress); - if (sta == NULL) - return _FAIL; - } - } - - rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK); - { - int sk_band = RTW_GET_SCAN_BAND_SKIP(padapter); - - if (sk_band) - RTW_CLR_SCAN_BAND_SKIP(padapter, sk_band); - } - - 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; - -} - -#if CONFIG_RTW_MACADDR_ACL -void rtw_macaddr_acl_init(_adapter *adapter, u8 period) -{ - struct sta_priv *stapriv = &adapter->stapriv; - struct wlan_acl_pool *acl; - _queue *acl_node_q; - int i; - _irqL irqL; - - if (period >= RTW_ACL_PERIOD_NUM) { - rtw_warn_on(1); - return; - } - - acl = &stapriv->acl_list[period]; - acl_node_q = &acl->acl_node_q; - - _rtw_spinlock_init(&(acl_node_q->lock)); - - _enter_critical_bh(&(acl_node_q->lock), &irqL); - _rtw_init_listhead(&(acl_node_q->queue)); - acl->num = 0; - acl->mode = RTW_ACL_MODE_DISABLED; - for (i = 0; i < NUM_ACL; i++) { - _rtw_init_listhead(&acl->aclnode[i].list); - acl->aclnode[i].valid = _FALSE; - } - _exit_critical_bh(&(acl_node_q->lock), &irqL); -} - -static void _rtw_macaddr_acl_deinit(_adapter *adapter, u8 period, bool clear_only) -{ - struct sta_priv *stapriv = &adapter->stapriv; - struct wlan_acl_pool *acl; - _queue *acl_node_q; - _irqL irqL; - _list *head, *list; - struct rtw_wlan_acl_node *acl_node; - - if (period >= RTW_ACL_PERIOD_NUM) { - rtw_warn_on(1); - return; - } - - acl = &stapriv->acl_list[period]; - acl_node_q = &acl->acl_node_q; - - _enter_critical_bh(&(acl_node_q->lock), &irqL); - head = get_list_head(acl_node_q); - list = get_next(head); - while (rtw_end_of_queue_search(head, list) == _FALSE) { - acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list); - list = get_next(list); - - if (acl_node->valid == _TRUE) { - acl_node->valid = _FALSE; - rtw_list_delete(&acl_node->list); - acl->num--; - } - } - _exit_critical_bh(&(acl_node_q->lock), &irqL); - - if (!clear_only) - _rtw_spinlock_free(&(acl_node_q->lock)); - - rtw_warn_on(acl->num); - acl->mode = RTW_ACL_MODE_DISABLED; -} - -void rtw_macaddr_acl_deinit(_adapter *adapter, u8 period) -{ - _rtw_macaddr_acl_deinit(adapter, period, 0); -} - -void rtw_macaddr_acl_clear(_adapter *adapter, u8 period) -{ - _rtw_macaddr_acl_deinit(adapter, period, 1); -} - -void rtw_set_macaddr_acl(_adapter *adapter, u8 period, int mode) -{ - struct sta_priv *stapriv = &adapter->stapriv; - struct wlan_acl_pool *acl; - - if (period >= RTW_ACL_PERIOD_NUM) { - rtw_warn_on(1); - return; - } - - acl = &stapriv->acl_list[period]; - - RTW_INFO(FUNC_ADPT_FMT" p=%u, mode=%d\n" - , FUNC_ADPT_ARG(adapter), period, mode); - - acl->mode = mode; -} - -int rtw_acl_add_sta(_adapter *adapter, u8 period, const u8 *addr) -{ - _irqL irqL; - _list *list, *head; - u8 existed = 0; - int i = -1, ret = 0; - struct rtw_wlan_acl_node *acl_node; - struct sta_priv *stapriv = &adapter->stapriv; - struct wlan_acl_pool *acl; - _queue *acl_node_q; - - if (period >= RTW_ACL_PERIOD_NUM) { - rtw_warn_on(1); - ret = -1; - goto exit; - } - - acl = &stapriv->acl_list[period]; - acl_node_q = &acl->acl_node_q; - - _enter_critical_bh(&(acl_node_q->lock), &irqL); - - head = get_list_head(acl_node_q); - list = get_next(head); - - /* search for existed entry */ - while (rtw_end_of_queue_search(head, list) == _FALSE) { - acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list); - list = get_next(list); - - if (_rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) { - if (acl_node->valid == _TRUE) { - existed = 1; - break; - } - } - } - if (existed) - goto release_lock; - - if (acl->num >= NUM_ACL) - goto release_lock; - - /* find empty one and use */ - for (i = 0; i < NUM_ACL; i++) { - - acl_node = &acl->aclnode[i]; - if (acl_node->valid == _FALSE) { - - _rtw_init_listhead(&acl_node->list); - _rtw_memcpy(acl_node->addr, addr, ETH_ALEN); - acl_node->valid = _TRUE; - - rtw_list_insert_tail(&acl_node->list, get_list_head(acl_node_q)); - acl->num++; - break; - } - } - -release_lock: - _exit_critical_bh(&(acl_node_q->lock), &irqL); - - if (!existed && (i < 0 || i >= NUM_ACL)) - ret = -1; - - RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n" - , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr) - , (existed ? "existed" : ((i < 0 || i >= NUM_ACL) ? "no room" : "added")) - , acl->num); -exit: - return ret; -} - -int rtw_acl_remove_sta(_adapter *adapter, u8 period, const u8 *addr) -{ - _irqL irqL; - _list *list, *head; - int ret = 0; - struct rtw_wlan_acl_node *acl_node; - struct sta_priv *stapriv = &adapter->stapriv; - struct wlan_acl_pool *acl; - _queue *acl_node_q; - u8 is_baddr = is_broadcast_mac_addr(addr); - u8 match = 0; - - if (period >= RTW_ACL_PERIOD_NUM) { - rtw_warn_on(1); - goto exit; - } - - acl = &stapriv->acl_list[period]; - acl_node_q = &acl->acl_node_q; - - _enter_critical_bh(&(acl_node_q->lock), &irqL); - - head = get_list_head(acl_node_q); - list = get_next(head); - - while (rtw_end_of_queue_search(head, list) == _FALSE) { - acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list); - list = get_next(list); - - if (is_baddr || _rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) { - if (acl_node->valid == _TRUE) { - acl_node->valid = _FALSE; - rtw_list_delete(&acl_node->list); - acl->num--; - match = 1; - } - } - } - - _exit_critical_bh(&(acl_node_q->lock), &irqL); - - RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n" - , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr) - , is_baddr ? "clear all" : (match ? "match" : "no found") - , acl->num); - -exit: - return ret; -} -#endif /* CONFIG_RTW_MACADDR_ACL */ - -u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk) -{ - struct cmd_priv *cmdpriv = &adapter->cmdpriv; - struct cmd_obj *cmd; - struct set_stakey_parm *param; - u8 res = _SUCCESS; - - cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (cmd == NULL) { - res = _FAIL; - goto exit; - } - - param = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm)); - if (param == NULL) { - rtw_mfree((u8 *) cmd, sizeof(struct cmd_obj)); - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(cmd, param, _SetStaKey_CMD_); - - _rtw_memcpy(param->addr, addr, ETH_ALEN); - param->algorithm = alg; - param->keyid = keyid; - _rtw_memcpy(param->key, key, 16); - param->gk = gk; - - res = rtw_enqueue_cmd(cmdpriv, cmd); - -exit: - return res; -} - -u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta) -{ - return rtw_ap_set_sta_key(padapter - , psta->cmn.mac_addr - , psta->dot118021XPrivacy - , psta->dot118021x_UncstKey.skey - , 0 - , 0 - ); -} - -static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx) -{ - u8 keylen; - struct cmd_obj *pcmd; - struct setkey_parm *psetkeyparm; - struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); - int res = _SUCCESS; - - /* RTW_INFO("%s\n", __FUNCTION__); */ - - pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd == NULL) { - res = _FAIL; - goto exit; - } - psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm)); - if (psetkeyparm == NULL) { - rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj)); - res = _FAIL; - goto exit; - } - - _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm)); - - psetkeyparm->keyid = (u8)keyid; - if (is_wep_enc(alg)) - padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid); - - psetkeyparm->algorithm = alg; - - psetkeyparm->set_tx = set_tx; - - switch (alg) { - case _WEP40_: - keylen = 5; - break; - case _WEP104_: - keylen = 13; - break; - case _TKIP_: - case _TKIP_WTMIC_: - case _AES_: - default: - keylen = 16; - } - - _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen); - - 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); - - res = rtw_enqueue_cmd(pcmdpriv, pcmd); - -exit: - - return res; -} - -int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid) -{ - RTW_INFO("%s\n", __FUNCTION__); - - return rtw_ap_set_key(padapter, key, alg, keyid, 1); -} - -int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx) -{ - u8 alg; - - switch (keylen) { - case 5: - alg = _WEP40_; - break; - case 13: - alg = _WEP104_; - break; - default: - alg = _NO_PRIVACY_; - } - - RTW_INFO("%s\n", __FUNCTION__); - - return rtw_ap_set_key(padapter, key, alg, keyid, set_tx); -} - -u8 rtw_ap_bmc_frames_hdl(_adapter *padapter) -{ -#define HIQ_XMIT_COUNTS (6) - _irqL irqL; - struct sta_info *psta_bmc; - _list *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - bool update_tim = _FALSE; - - - if (padapter->registrypriv.wifi_spec != 1) - return H2C_SUCCESS; - - - psta_bmc = rtw_get_bcmc_stainfo(padapter); - if (!psta_bmc) - return H2C_SUCCESS; - - - _enter_critical_bh(&pxmitpriv->lock, &irqL); - - if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) { - int tx_counts = 0; - - _update_beacon(padapter, _TIM_IE_, NULL, _FALSE, "update TIM with TIB=1"); - - RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len); - - xmitframe_phead = get_list_head(&psta_bmc->sleep_q); - xmitframe_plist = get_next(xmitframe_phead); - - 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); - - psta_bmc->sleepq_len--; - tx_counts++; - - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - if (tx_counts == HIQ_XMIT_COUNTS) - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - if (xmitframe_hiq_filter(pxmitframe) == _TRUE) - pxmitframe->attrib.qsel = QSLT_HIGH;/*HIQ*/ - - rtw_hal_xmitframe_enqueue(padapter, pxmitframe); - - if (tx_counts == HIQ_XMIT_COUNTS) - break; - - } - - } else { - if (psta_bmc->sleepq_len == 0) { - - /*RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);*/ - - if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) - update_tim = _TRUE; - - rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0); - rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0); - - if (update_tim == _TRUE) { - RTW_INFO("clear TIB\n"); - _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "bmc sleepq and HIQ empty"); - } - } - } - - _exit_critical_bh(&pxmitpriv->lock, &irqL); - -#if 0 - /* HIQ Check */ - rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); - - while (_FALSE == empty && rtw_get_passing_time_ms(start) < 3000) { - rtw_msleep_os(100); - rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty); - } - - - printk("check if hiq empty=%d\n", empty); -#endif - - return H2C_SUCCESS; -} - -#ifdef CONFIG_NATIVEAP_MLME - -static void associated_stainfo_update(_adapter *padapter, struct sta_info *psta, u32 sta_info_type) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - RTW_INFO("%s: "MAC_FMT", updated_type=0x%x\n", __func__, MAC_ARG(psta->cmn.mac_addr), sta_info_type); -#ifdef CONFIG_80211N_HT - if (sta_info_type & STA_INFO_UPDATE_BW) { - - if ((psta->flags & WLAN_STA_HT) && !psta->ht_20mhz_set) { - if (pmlmepriv->sw_to_20mhz) { - psta->cmn.bw_mode = CHANNEL_WIDTH_20; - /*psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;*/ - psta->htpriv.sgi_40m = _FALSE; - } else { - /*TODO: Switch back to 40MHZ?80MHZ*/ - } - } - } -#endif /* CONFIG_80211N_HT */ - /* - if (sta_info_type & STA_INFO_UPDATE_RATE) { - - } - */ - - if (sta_info_type & STA_INFO_UPDATE_PROTECTION_MODE) - VCS_update(padapter, psta); - - /* - if (sta_info_type & STA_INFO_UPDATE_CAP) { - - } - - if (sta_info_type & STA_INFO_UPDATE_HT_CAP) { - - } - - if (sta_info_type & STA_INFO_UPDATE_VHT_CAP) { - - } - */ - -} - -static void update_bcn_ext_capab_ie(_adapter *padapter) -{ - sint ie_len = 0; - unsigned char *pbuf; - 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); - u8 *ie = pnetwork->IEs; - u8 null_extcap_data[8] = {0}; - - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) - rtw_remove_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_); - - if ((pmlmepriv->ext_capab_ie_len > 0) && - (_rtw_memcmp(pmlmepriv->ext_capab_ie_data, null_extcap_data, sizeof(null_extcap_data)) == _FALSE)) - rtw_add_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_, pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len); - -} - -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; - - RTW_INFO("%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) -{ - RTW_INFO("%s\n", __FUNCTION__); - -} - -static void update_bcn_htinfo_ie(_adapter *padapter) -{ -#ifdef CONFIG_80211N_HT - /* - u8 beacon_updated = _FALSE; - u32 sta_info_update_type = STA_INFO_UPDATE_NONE; - */ - 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; - - if (pmlmepriv->htpriv.ht_option == _FALSE) - return; - - if (pmlmeinfo->HT_info_enable != 1) - return; - - - RTW_INFO("%s current operation mode=0x%X\n", - __FUNCTION__, pmlmepriv->ht_op_mode); - - RTW_INFO("num_sta_40mhz_intolerant(%d), 20mhz_width_req(%d), intolerant_ch_rpt(%d), olbc(%d)\n", - pmlmepriv->num_sta_40mhz_intolerant, pmlmepriv->ht_20mhz_width_req, pmlmepriv->ht_intolerant_ch_reported, ATOMIC_READ(&pmlmepriv->olbc)); - - /*parsing HT_INFO_IE, currently only update ht_op_mode - pht_info->infos[1] & pht_info->infos[2] for wifi logo test*/ - p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (p && len > 0) { - struct HT_info_element *pht_info = NULL; - - pht_info = (struct HT_info_element *)(p + 2); - - /* for STA Channel Width/Secondary Channel Offset*/ - if ((pmlmepriv->sw_to_20mhz == 0) && (pmlmeext->cur_channel <= 14)) { - if ((pmlmepriv->num_sta_40mhz_intolerant > 0) || (pmlmepriv->ht_20mhz_width_req == _TRUE) - || (pmlmepriv->ht_intolerant_ch_reported == _TRUE) || (ATOMIC_READ(&pmlmepriv->olbc) == _TRUE)) { - SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 0); - SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 0); - - pmlmepriv->sw_to_20mhz = 1; - /* - sta_info_update_type |= STA_INFO_UPDATE_BW; - beacon_updated = _TRUE; - */ - - RTW_INFO("%s:switching to 20Mhz\n", __FUNCTION__); - - /*TODO : cur_bwmode/cur_ch_offset switches to 20Mhz*/ - } - } else { - - if ((pmlmepriv->num_sta_40mhz_intolerant == 0) && (pmlmepriv->ht_20mhz_width_req == _FALSE) - && (pmlmepriv->ht_intolerant_ch_reported == _FALSE) && (ATOMIC_READ(&pmlmepriv->olbc) == _FALSE)) { - - if (pmlmeext->cur_bwmode >= CHANNEL_WIDTH_40) { - - SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 1); - - SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, - (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) ? - HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE : HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW); - - pmlmepriv->sw_to_20mhz = 0; - /* - sta_info_update_type |= STA_INFO_UPDATE_BW; - beacon_updated = _TRUE; - */ - - RTW_INFO("%s:switching back to 40Mhz\n", __FUNCTION__); - } - } - } - - /* to update ht_op_mode*/ - *(u16 *)(pht_info->infos + 1) = cpu_to_le16(pmlmepriv->ht_op_mode); - - } - - /*associated_clients_update(padapter, beacon_updated, sta_info_update_type);*/ -#endif /* CONFIG_80211N_HT */ -} - -static void update_bcn_rsn_ie(_adapter *padapter) -{ - RTW_INFO("%s\n", __FUNCTION__); - -} - -static void update_bcn_wpa_ie(_adapter *padapter) -{ - RTW_INFO("%s\n", __FUNCTION__); - -} - -static void update_bcn_wmm_ie(_adapter *padapter) -{ - RTW_INFO("%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; - - - RTW_INFO("%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; - - pwps_ie_src = pmlmepriv->wps_beacon_ie; - if (pwps_ie_src == NULL) - 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); - } - - 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); - - /* deal with the case without set_tx_beacon_cmd() in update_beacon() */ -#if defined(CONFIG_INTERRUPT_BASED_TXBCN) || defined(CONFIG_PCI_HCI) - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - u8 sr = 0; - rtw_get_wps_attr_content(pwps_ie_src, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); - - if (sr) { - set_fwstate(pmlmepriv, WIFI_UNDER_WPS); - RTW_INFO("%s, set WIFI_UNDER_WPS\n", __func__); - } else { - clr_fwstate(pmlmepriv, WIFI_UNDER_WPS); - RTW_INFO("%s, clr WIFI_UNDER_WPS\n", __func__); - } - } -#endif -} - -static void update_bcn_p2p_ie(_adapter *padapter) -{ - -} - -static void update_bcn_vendor_spec_ie(_adapter *padapter, u8 *oui) -{ - RTW_INFO("%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 - RTW_INFO("unknown OUI type!\n"); - - -} - -void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, const char *tag) -{ - _irqL irqL; - struct mlme_priv *pmlmepriv; - struct mlme_ext_priv *pmlmeext; - bool updated = 1; /* treat as upadated by default */ - - if (!padapter) - return; - - pmlmepriv = &(padapter->mlmepriv); - pmlmeext = &(padapter->mlmeextpriv); - - if (pmlmeext->bstart_bss == _FALSE) - return; - - _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL); - - switch (ie_id) { - 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 _EXT_CAP_IE_: - update_bcn_ext_capab_ie(padapter); - break; - -#ifdef CONFIG_RTW_MESH - case WLAN_EID_MESH_CONFIG: - updated = rtw_mesh_update_bss_peering_status(padapter, &(pmlmeext->mlmext_info.network)); - updated |= rtw_mesh_update_bss_formation_info(padapter, &(pmlmeext->mlmext_info.network)); - updated |= rtw_mesh_update_bss_forwarding_state(padapter, &(pmlmeext->mlmext_info.network)); - break; -#endif - - case _VENDOR_SPECIFIC_IE_: - update_bcn_vendor_spec_ie(padapter, oui); - break; - - case 0xFF: - default: - break; - } - - if (updated) - 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) || defined(CONFIG_PCI_BCN_POLLING) - if (tx && updated) { - /* send_beacon(padapter); */ /* send_beacon must execute on TSR level */ - if (0) - RTW_INFO(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag); - set_tx_beacon_cmd(padapter); - } -#else - { - /* PCI will issue beacon when BCN interrupt occurs. */ - } -#endif -#endif /* !CONFIG_INTERRUPT_BASED_TXBCN */ -} - -#ifdef CONFIG_80211N_HT - -void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len) -{ - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 beacon_updated = _FALSE; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - uint frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr); - u8 category, action; - - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta == NULL) - return; - - - category = frame_body[0]; - action = frame_body[1]; - - if (frame_body_len > 0) { - if ((frame_body[2] == EID_BSSCoexistence) && (frame_body[3] > 0)) { - u8 ie_data = frame_body[4]; - - if (ie_data & RTW_WLAN_20_40_BSS_COEX_40MHZ_INTOL) { - if (psta->ht_40mhz_intolerant == 0) { - psta->ht_40mhz_intolerant = 1; - pmlmepriv->num_sta_40mhz_intolerant++; - beacon_updated = _TRUE; - } - } else if (ie_data & RTW_WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) { - if (pmlmepriv->ht_20mhz_width_req == _FALSE) { - pmlmepriv->ht_20mhz_width_req = _TRUE; - beacon_updated = _TRUE; - } - } else - beacon_updated = _FALSE; - } - } - - if (frame_body_len > 8) { - /* if EID_BSSIntolerantChlReport ie exists */ - if ((frame_body[5] == EID_BSSIntolerantChlReport) && (frame_body[6] > 0)) { - /*todo:*/ - if (pmlmepriv->ht_intolerant_ch_reported == _FALSE) { - pmlmepriv->ht_intolerant_ch_reported = _TRUE; - beacon_updated = _TRUE; - } - } - } - - if (beacon_updated) { - - update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE); - - associated_stainfo_update(padapter, psta, STA_INFO_UPDATE_BW); - } - - - -} - -void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field) -{ - u8 e_field, m_field; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo(pstapriv, ta); - if (psta == NULL) - return; - - e_field = (ctrl_field & BIT(0)) ? 1 : 0; /*SM Power Save Enabled*/ - m_field = (ctrl_field & BIT(1)) ? 1 : 0; /*SM Mode, 0:static SMPS, 1:dynamic SMPS*/ - - if (e_field) { - if (m_field) { /*mode*/ - psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DYNAMIC; - RTW_ERR("Don't support dynamic SMPS\n"); - } - else - psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_STATIC; - } else { - /*disable*/ - psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DISABLED; - } - - if (psta->htpriv.smps_cap != WLAN_HT_CAP_SM_PS_DYNAMIC) - rtw_ssmps_wk_cmd(padapter, psta, e_field, 1); -} - -/* -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) -*/ -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 == _FALSE) - return 0; - - /*if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) - return 0;*/ - - RTW_INFO("%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 || ATOMIC_READ(&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 && !ATOMIC_READ(&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 (ATOMIC_READ(&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++; - } - - RTW_INFO("%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, u32 sta_info_type) -{ - /* 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); - - associated_stainfo_update(padapter, psta, sta_info_type); - } - - _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; - } - } 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; - } - } - -#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, _FALSE); - } - } - - } 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, _FALSE); - } - } - - } - - -#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; - } - } 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; - } - } - -#ifdef CONFIG_80211N_HT - if(padapter->registrypriv.ht_enable && - is_supported_ht(padapter->registrypriv.wireless_mode)) { - if (psta->flags & WLAN_STA_HT) { - u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); - - RTW_INFO("HT: STA " MAC_FMT " HT Capabilities Info: 0x%04x\n", - MAC_ARG(psta->cmn.mac_addr), 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++; - } - RTW_INFO("%s STA " MAC_FMT " - no " - "greenfield, num of non-gf stations %d\n", - __FUNCTION__, MAC_ARG(psta->cmn.mac_addr), - 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++; - } - RTW_INFO("%s STA " MAC_FMT " - 20 MHz HT, " - "num of 20MHz HT STAs %d\n", - __FUNCTION__, MAC_ARG(psta->cmn.mac_addr), - pmlmepriv->num_sta_ht_20mhz); - } - - if (((ht_capab & RTW_IEEE80211_HT_CAP_40MHZ_INTOLERANT) != 0) && - (psta->ht_40mhz_intolerant == 0)) { - psta->ht_40mhz_intolerant = 1; - pmlmepriv->num_sta_40mhz_intolerant++; - RTW_INFO("%s STA " MAC_FMT " - 40MHZ_INTOLERANT, ", - __FUNCTION__, MAC_ARG(psta->cmn.mac_addr)); - } - - } else { - if (!psta->no_ht_set) { - psta->no_ht_set = 1; - pmlmepriv->num_sta_no_ht++; - } - if (pmlmepriv->htpriv.ht_option == _TRUE) { - RTW_INFO("%s STA " MAC_FMT - " - no HT, num of non-HT stations %d\n", - __FUNCTION__, MAC_ARG(psta->cmn.mac_addr), - 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, _FALSE); - beacon_updated = _TRUE; - } - } -#endif /* CONFIG_80211N_HT */ - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) { - struct sta_priv *pstapriv = &padapter->stapriv; - - update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE); - if (pstapriv->asoc_list_cnt == 1) - _set_timer(&padapter->mesh_atlm_param_req_timer, 0); - beacon_updated = _TRUE; - } -#endif - - if (beacon_updated) - update_beacon(padapter, 0xFF, NULL, _TRUE); - - /* update associcated stations cap. */ - associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL); - - RTW_INFO("%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 sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - - if (!psta) - return beacon_updated; - - if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid)) { - rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->cmn.aid); - beacon_updated = _TRUE; - update_beacon(padapter, _TIM_IE_, NULL, _FALSE); - } - - 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; - } - - 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, _FALSE); - } - } - - 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; - } - -#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 (psta->ht_40mhz_intolerant) { - psta->ht_40mhz_intolerant = 0; - if (pmlmepriv->num_sta_40mhz_intolerant > 0) - pmlmepriv->num_sta_40mhz_intolerant--; - else - rtw_warn_on(1); - } - - if (rtw_ht_operation_update(padapter) > 0) { - update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE); - update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE); - } -#endif /* CONFIG_80211N_HT */ - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) { - update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE); - if (pstapriv->asoc_list_cnt == 0) - _cancel_timer_ex(&padapter->mesh_atlm_param_req_timer); - beacon_updated = _TRUE; - } -#endif - - if (beacon_updated == _TRUE) - update_beacon(padapter, 0xFF, NULL, _TRUE); - -#if 0 - /* update associated stations cap. */ - associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL); /* move it to avoid deadlock */ -#endif - - RTW_INFO("%s, updated=%d\n", __func__, beacon_updated); - - return beacon_updated; - -} - -u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue) -{ - _irqL irqL; - u8 beacon_updated = _FALSE; - - if (!psta) - return beacon_updated; - - if (active == _TRUE) { -#ifdef CONFIG_80211N_HT - /* tear down Rx AMPDU */ - send_delba(padapter, 0, psta->cmn.mac_addr);/* recipient */ - - /* tear down TX AMPDU */ - send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */ - -#endif /* CONFIG_80211N_HT */ - - if (!MLME_IS_MESH(padapter)) - issue_deauth(padapter, psta->cmn.mac_addr, reason); - } - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) - rtw_mesh_path_flush_by_nexthop(psta); -#endif - -#ifdef CONFIG_BEAMFORMING - beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_LEAVE, psta->cmn.mac_addr, ETH_ALEN, 1); -#endif - -#ifdef CONFIG_80211N_HT - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ -#endif - - /* clear cam entry / key */ - rtw_clearstakey_cmd(padapter, psta, enqueue); - - - _enter_critical_bh(&psta->lock, &irqL); - psta->state &= ~(_FW_LINKED | WIFI_UNDER_KEY_HANDSHAKE); - - if ((psta->auth_len != 0) && (psta->pauth_frame != NULL)) { - rtw_mfree(psta->pauth_frame, psta->auth_len); - psta->pauth_frame = NULL; - psta->auth_len = 0; - } - _exit_critical_bh(&psta->lock, &irqL); - - if (!MLME_IS_MESH(padapter)) { -#ifdef CONFIG_IOCTL_CFG80211 - #ifdef COMPAT_KERNEL_RELEASE - rtw_cfg80211_indicate_sta_disassoc(padapter, psta->cmn.mac_addr, 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->cmn.mac_addr, 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 - rtw_indicate_sta_disassoc_event(padapter, psta); -#endif - } - - beacon_updated = bss_cap_update_on_sta_leave(padapter, psta); - - report_del_sta_event(padapter, psta->cmn.mac_addr, reason, enqueue, _FALSE); - - 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; - - RTW_INFO(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->cmn.mac_addr, 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, bool enqueue) -{ - _irqL irqL; - _list *phead, *plist; - int ret = 0; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 flush_num = 0; - char flush_list[NUM_STA]; - int i; - - if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter)) - return ret; - - RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); - - /* pick sta from sta asoc_queue */ - _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); - - rtw_list_delete(&psta->asoc_list); - pstapriv->asoc_list_cnt--; - STA_SET_MESH_PLINK(psta, NULL); - - stainfo_offset = rtw_stainfo_offset(pstapriv, psta); - if (stainfo_offset_valid(stainfo_offset)) - flush_list[flush_num++] = stainfo_offset; - else - rtw_warn_on(1); - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - /* call ap_free_sta() for each sta picked */ - for (i = 0; i < flush_num; i++) { - u8 sta_addr[ETH_ALEN]; - - psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]); - _rtw_memcpy(sta_addr, psta->cmn.mac_addr, ETH_ALEN); - - ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, enqueue); - #ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) - rtw_mesh_expire_peer(padapter, sta_addr); - #endif - } - - if (!MLME_IS_MESH(padapter)) - issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING); - - associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_ALL); - - 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; - - psta->htpriv.smps_cap = (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_SM_PS) >> 2; - } else - psta->htpriv.ht_option = _FALSE; - - if (pmlmepriv->htpriv.ht_option == _FALSE) - psta->htpriv.ht_option = _FALSE; -#endif - -#ifdef CONFIG_80211AC_VHT - /* update 802.11AC vht cap. */ - if (WLAN_STA_VHT & flags) - psta->vhtpriv.vht_option = _TRUE; - else - psta->vhtpriv.vht_option = _FALSE; - - if (pmlmepriv->vhtpriv.vht_option == _FALSE) - psta->vhtpriv.vht_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) - rtw_hal_update_ra_mask(psta); /* DM_RATR_STA_INIT */ -} -/* restore hw setting from sw data structures */ -void rtw_ap_restore_network(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - 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 - , MLME_IS_AP(padapter) ? Ndis802_11APMode : Ndis802_11_mesh - , RTW_CMDF_DIRECTLY - ); - - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtw_startbss_cmd(padapter, RTW_CMDF_DIRECTLY); - - 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) - RTW_INFO(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter)); - else if (psta->state & _FW_LINKED) { - rtw_sta_media_status_rpt(padapter, psta, 1); - 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, psta, UNICAST_KEY, _FALSE); - } - } - -} - -void start_ap_mode(_adapter *padapter) -{ - int i; - struct sta_info *psta = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); -#ifdef CONFIG_CONCURRENT_MODE - struct security_priv *psecuritypriv = &padapter->securitypriv; -#endif - - 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 */ - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_enable = 0; - - pmlmepriv->num_sta_ht_20mhz = 0; - pmlmepriv->num_sta_40mhz_intolerant = 0; - ATOMIC_SET(&pmlmepriv->olbc, _FALSE); - ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE); - -#ifdef CONFIG_80211N_HT - pmlmepriv->ht_20mhz_width_req = _FALSE; - pmlmepriv->ht_intolerant_ch_reported = _FALSE; - pmlmepriv->ht_op_mode = 0; - pmlmepriv->sw_to_20mhz = 0; -#endif - - _rtw_memset(pmlmepriv->ext_capab_ie_data, 0, sizeof(pmlmepriv->ext_capab_ie_data)); - pmlmepriv->ext_capab_ie_len = 0; - -#ifdef CONFIG_CONCURRENT_MODE - psecuritypriv->dot118021x_bmc_cam_id = INVALID_SEC_MAC_CAM_ID; -#endif - - for (i = 0 ; i < pstapriv->max_aid; i++) - pstapriv->sta_aid[i] = NULL; - - psta = rtw_get_bcmc_stainfo(padapter); - /*_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/ - if (psta) - rtw_free_stainfo(padapter, psta); - /*_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/ - - rtw_init_bcmc_stainfo(padapter); - - if (rtw_mi_get_ap_num(padapter)) - RTW_SET_SCAN_BAND_SKIP(padapter, BAND_5G); - -} - -void rtw_ap_bcmc_sta_flush(_adapter *padapter) -{ -#ifdef CONFIG_CONCURRENT_MODE - int cam_id = -1; - u8 *addr = adapter_mac_addr(padapter); - - cam_id = rtw_iface_bcmc_id_get(padapter); - if (cam_id != INVALID_SEC_MAC_CAM_ID) { - RTW_PRINT("clear group key for "ADPT_FMT" addr:"MAC_FMT", camid:%d\n", - ADPT_ARG(padapter), MAC_ARG(addr), cam_id); - clear_cam_entry(padapter, cam_id); - rtw_camid_free(padapter, cam_id); - rtw_iface_bcmc_id_set(padapter, INVALID_SEC_MAC_CAM_ID); /*init default value*/ - } -#else - invalidate_cam_all(padapter); -#endif -} - -void stop_ap_mode(_adapter *padapter) -{ - u8 self_action = MLME_ACTION_UNKNOWN; - struct sta_info *psta = NULL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; -#ifdef CONFIG_SUPPORT_MULTI_BCN - struct dvobj_priv *pdvobj = padapter->dvobj; - _irqL irqL; -#endif - - RTW_INFO("%s -"ADPT_FMT"\n", __func__, ADPT_ARG(padapter)); - - if (MLME_IS_AP(padapter)) - self_action = MLME_AP_STOPPED; - else if (MLME_IS_MESH(padapter)) - self_action = MLME_MESH_STOPPED; - else - rtw_warn_on(1); - - pmlmepriv->update_bcn = _FALSE; - /*pmlmeext->bstart_bss = _FALSE;*/ - padapter->netif_up = _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; - -#ifdef CONFIG_DFS_MASTER - rtw_dfs_rd_en_decision(padapter, self_action, 0); -#endif - - /* free scan queue */ - rtw_free_network_queue(padapter, _TRUE); - -#if CONFIG_RTW_MACADDR_ACL - rtw_macaddr_acl_clear(padapter, RTW_ACL_PERIOD_BSS); -#endif - - rtw_sta_flush(padapter, _TRUE); - rtw_ap_bcmc_sta_flush(padapter); - - /* free_assoc_sta_resources */ - rtw_free_all_stainfo(padapter); - - psta = rtw_get_bcmc_stainfo(padapter); - if (psta) { - rtw_sta_mstatus_disc_rpt(padapter, psta->cmn.mac_id); - /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */ - rtw_free_stainfo(padapter, psta); - /*_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/ - } - - rtw_free_mlme_priv_ie_data(pmlmepriv); - -#ifdef CONFIG_SUPPORT_MULTI_BCN - if (pmlmeext->bstart_bss == _TRUE) { - #ifdef CONFIG_FW_HANDLE_TXBCN - u8 free_apid = CONFIG_LIMITED_AP_NUM; - #endif - - _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - pdvobj->nr_ap_if--; - if (pdvobj->nr_ap_if > 0) - pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL / pdvobj->nr_ap_if; - else - pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL; - #ifdef CONFIG_FW_HANDLE_TXBCN - rtw_ap_release_vapid(pdvobj, padapter->vap_id); - free_apid = padapter->vap_id; - padapter->vap_id = CONFIG_LIMITED_AP_NUM; - #endif - rtw_list_delete(&padapter->list); - _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - #ifdef CONFIG_FW_HANDLE_TXBCN - rtw_ap_mbid_bcn_dis(padapter, free_apid); - #endif - - #ifdef CONFIG_SWTIMER_BASED_TXBCN - rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pdvobj->inter_bcn_space)); - - if (pdvobj->nr_ap_if == 0) - _cancel_timer_ex(&pdvobj->txbcn_timer); - #endif - } -#endif - - pmlmeext->bstart_bss = _FALSE; - - rtw_hal_rcr_set_chk_bssid(padapter, self_action); - -#ifdef CONFIG_HW_P0_TSF_SYNC - correct_TSF(padapter, self_action); -#endif - -#ifdef CONFIG_BT_COEXIST - rtw_btcoex_MediaStatusNotify(padapter, 0); /* disconnect */ -#endif - -} - -#endif /* CONFIG_NATIVEAP_MLME */ - -void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset) -{ -#define UPDATE_VHT_CAP 1 -#define UPDATE_HT_CAP 1 -#ifdef CONFIG_80211AC_VHT - struct vht_priv *vhtpriv = &adapter->mlmepriv.vhtpriv; -#endif - { - u8 *p; - int ie_len; - u8 old_ch = bss->Configuration.DSConfig; - bool change_band = _FALSE; - - if ((ch <= 14 && old_ch >= 36) || (ch >= 36 && old_ch <= 14)) - change_band = _TRUE; - - /* update channel in IE */ - p = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs))); - if (p && ie_len > 0) - *(p + 2) = ch; - - bss->Configuration.DSConfig = ch; - - /* band is changed, update ERP, support rate, ext support rate IE */ - if (change_band == _TRUE) - change_band_update_ie(adapter, bss, ch); - } - -#ifdef CONFIG_80211AC_VHT - if (vhtpriv->vht_option == _TRUE) { - u8 *vht_cap_ie, *vht_op_ie; - int vht_cap_ielen, vht_op_ielen; - u8 center_freq; - - vht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTCapability, &vht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs))); - vht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &vht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs))); - center_freq = rtw_get_center_ch(ch, bw, offset); - - /* update vht cap ie */ - if (vht_cap_ie && vht_cap_ielen) { - #if UPDATE_VHT_CAP - /* if ((bw == CHANNEL_WIDTH_160 || bw == CHANNEL_WIDTH_80_80) && pvhtpriv->sgi_160m) - SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvht_cap_ie + 2, 1); - else */ - SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 0); - - if (bw >= CHANNEL_WIDTH_80 && vhtpriv->sgi_80m) - SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 1); - else - SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 0); - #endif - } - - /* update vht op ie */ - if (vht_op_ie && vht_op_ielen) { - if (bw < CHANNEL_WIDTH_80) { - SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0); - SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0); - SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0); - } else if (bw == CHANNEL_WIDTH_80) { - SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 1); - SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, center_freq); - SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0); - } else { - RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw); - rtw_warn_on(1); - } - } - } -#endif /* CONFIG_80211AC_VHT */ -#ifdef CONFIG_80211N_HT - { - struct ht_priv *htpriv = &adapter->mlmepriv.htpriv; - u8 *ht_cap_ie, *ht_op_ie; - int ht_cap_ielen, ht_op_ielen; - - ht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTCapability, &ht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs))); - ht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTInfo, &ht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs))); - - /* update ht cap ie */ - if (ht_cap_ie && ht_cap_ielen) { - #if UPDATE_HT_CAP - if (bw >= CHANNEL_WIDTH_40) - SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 1); - else - SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 0); - - if (bw >= CHANNEL_WIDTH_40 && htpriv->sgi_40m) - SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 1); - else - SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 0); - - if (htpriv->sgi_20m) - SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 1); - else - SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 0); - #endif - } - - /* update ht op ie */ - if (ht_op_ie && ht_op_ielen) { - SET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2, ch); - switch (offset) { - case HAL_PRIME_CHNL_OFFSET_LOWER: - SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCA); - break; - case HAL_PRIME_CHNL_OFFSET_UPPER: - SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCB); - break; - case HAL_PRIME_CHNL_OFFSET_DONT_CARE: - default: - SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCN); - break; - } - - if (bw >= CHANNEL_WIDTH_40) - SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 1); - else - SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 0); - } - } -#endif /* CONFIG_80211N_HT */ -} - -static u8 rtw_ap_update_chbw_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp - , u8 cur_ie_ch[], u8 cur_ie_bw[], u8 cur_ie_offset[] - , u8 dec_ch[], u8 dec_bw[], u8 dec_offset[] - , const char *caller) -{ - _adapter *iface; - struct mlme_ext_priv *mlmeext; - WLAN_BSSID_EX *network; - u8 ifbmp_ch_changed = 0; - int i; - - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters) - continue; - - iface = dvobj->padapters[i]; - mlmeext = &(iface->mlmeextpriv); - - if (MLME_IS_ASOC(iface)) { - RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface) - , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset - , dec_ch[i], dec_bw[i], dec_offset[i] - , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : ""); - } else { - RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface) - , cur_ie_ch[i], cur_ie_bw[i], cur_ie_offset[i] - , dec_ch[i], dec_bw[i], dec_offset[i] - , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : ""); - } - } - - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters) - continue; - - iface = dvobj->padapters[i]; - mlmeext = &(iface->mlmeextpriv); - network = &(mlmeext->mlmext_info.network); - - /* ch setting differs from mlmeext.network IE */ - if (cur_ie_ch[i] != dec_ch[i] - || cur_ie_bw[i] != dec_bw[i] - || cur_ie_offset[i] != dec_offset[i]) - ifbmp_ch_changed |= BIT(i); - - /* ch setting differs from existing one */ - if (MLME_IS_ASOC(iface) - && (mlmeext->cur_channel != dec_ch[i] - || mlmeext->cur_bwmode != dec_bw[i] - || mlmeext->cur_ch_offset != dec_offset[i]) - ) { - if (rtw_linked_check(iface) == _TRUE) { - #ifdef CONFIG_SPCT_CH_SWITCH - if (1) - rtw_ap_inform_ch_switch(iface, dec_ch[i], dec_offset[i]); - else - #endif - rtw_sta_flush(iface, _FALSE); - } - } - - mlmeext->cur_channel = dec_ch[i]; - mlmeext->cur_bwmode = dec_bw[i]; - mlmeext->cur_ch_offset = dec_offset[i]; - - rtw_ap_update_bss_chbw(iface, network, dec_ch[i], dec_bw[i], dec_offset[i]); - } - - return ifbmp_ch_changed; -} - -static u8 rtw_ap_ch_specific_chk(_adapter *adapter, u8 ch, u8 *bw, u8 *offset, const char *caller) -{ - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - RT_CHANNEL_INFO *chset = adapter_to_chset(adapter); - u8 ret = _SUCCESS; - - if (rtw_chset_search_ch(chset, ch) < 0) { - RTW_WARN("%s ch:%u doesn't fit in chplan\n", caller, ch); - ret = _FAIL; - goto exit; - } - - rtw_adjust_chbw(adapter, ch, bw, offset); - - if (!rtw_get_offset_by_chbw(ch, *bw, offset)) { - RTW_WARN("%s %u,%u has no valid offset\n", caller, ch, *bw); - ret = _FAIL; - goto exit; - } - - while (!rtw_chset_is_chbw_valid(chset, ch, *bw, *offset) - || (rtw_odm_dfs_domain_unknown(dvobj) && rtw_is_dfs_chbw(ch, *bw, *offset)) - ) { - if (*bw > CHANNEL_WIDTH_20) - (*bw)--; - if (*bw == CHANNEL_WIDTH_20) { - *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - } - } - - if (rtw_odm_dfs_domain_unknown(dvobj) && rtw_is_dfs_chbw(ch, *bw, *offset)) { - RTW_WARN("%s DFS channel %u can't be used\n", caller, ch); - ret = _FAIL; - goto exit; - } - -exit: - return ret; -} - -static bool rtw_ap_choose_chbw(_adapter *adapter, u8 sel_ch, u8 max_bw, u8 cur_ch - , u8 *ch, u8 *bw, u8 *offset, u8 mesh_only, const char *caller) -{ - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - bool ch_avail = _FALSE; - -#if defined(CONFIG_DFS_MASTER) - if (!rtw_odm_dfs_domain_unknown(dvobj)) { - if (rfctl->radar_detected - && rfctl->dbg_dfs_choose_dfs_ch_first - ) { - ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw - , ch, bw, offset - , RTW_CHF_2G | RTW_CHF_NON_DFS - , cur_ch - , rfctl->ch_sel_same_band_prefer, mesh_only); - if (ch_avail == _TRUE) { - RTW_INFO("%s choose 5G DFS channel for debug\n", caller); - goto exit; - } - } - - if (rfctl->radar_detected - && rfctl->dfs_ch_sel_d_flags - ) { - ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw - , ch, bw, offset - , rfctl->dfs_ch_sel_d_flags - , cur_ch - , rfctl->ch_sel_same_band_prefer, mesh_only); - if (ch_avail == _TRUE) { - RTW_INFO("%s choose with dfs_ch_sel_d_flags:0x%02x for debug\n" - , caller, rfctl->dfs_ch_sel_d_flags); - goto exit; - } - } - - ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw - , ch, bw, offset - , 0 - , cur_ch - , rfctl->ch_sel_same_band_prefer, mesh_only); - } else -#endif /* defined(CONFIG_DFS_MASTER) */ - { - ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw - , ch, bw, offset - , RTW_CHF_DFS - , cur_ch - , rfctl->ch_sel_same_band_prefer, mesh_only); - } - -exit: - if (ch_avail == _FALSE) - RTW_WARN("%s no available channel\n", caller); - - return ch_avail; -} - -u8 rtw_ap_chbw_decision(_adapter *adapter, u8 ifbmp, u8 excl_ifbmp - , s16 req_ch, s8 req_bw, s8 req_offset - , u8 *ch, u8 *bw, u8 *offset, u8 *chbw_allow) -{ - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - RT_CHANNEL_INFO *chset = adapter_to_chset(adapter); - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - bool ch_avail = _FALSE; - u8 cur_ie_ch[CONFIG_IFACE_NUMBER] = {0}; - u8 cur_ie_bw[CONFIG_IFACE_NUMBER] = {0}; - u8 cur_ie_offset[CONFIG_IFACE_NUMBER] = {0}; - u8 dec_ch[CONFIG_IFACE_NUMBER] = {0}; - u8 dec_bw[CONFIG_IFACE_NUMBER] = {0}; - u8 dec_offset[CONFIG_IFACE_NUMBER] = {0}; - u8 u_ch = 0, u_bw = 0, u_offset = 0; - struct mlme_ext_priv *mlmeext; - WLAN_BSSID_EX *network; - struct mi_state mstate; - struct mi_state mstate_others; - bool set_u_ch = _FALSE; - u8 ifbmp_others = 0xFF & ~ifbmp & ~excl_ifbmp; - u8 ifbmp_ch_changed = 0; - bool ifbmp_all_mesh = 0; - _adapter *iface; - int i; - -#ifdef CONFIG_RTW_MESH - for (i = 0; i < dvobj->iface_nums; i++) - if ((ifbmp & BIT(i)) && dvobj->padapters) - if (!MLME_IS_MESH(dvobj->padapters[i])) - break; - ifbmp_all_mesh = i >= dvobj->iface_nums ? 1 : 0; -#endif - - RTW_INFO("%s ifbmp:0x%02x excl_ifbmp:0x%02x req:%d,%d,%d\n", __func__ - , ifbmp, excl_ifbmp, req_ch, req_bw, req_offset); - rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate); - rtw_mi_status_by_ifbmp(dvobj, ifbmp_others, &mstate_others); - RTW_INFO("%s others ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u\n" - , __func__, MSTATE_STA_LD_NUM(&mstate_others), MSTATE_STA_LG_NUM(&mstate_others) - , MSTATE_AP_NUM(&mstate_others), MSTATE_MESH_NUM(&mstate_others)); - - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) - continue; - iface = dvobj->padapters[i]; - mlmeext = &(iface->mlmeextpriv); - network = &(mlmeext->mlmext_info.network); - - /* get current IE channel settings */ - rtw_ies_get_chbw(BSS_EX_TLV_IES(network), BSS_EX_TLV_IES_LEN(network) - , &cur_ie_ch[i], &cur_ie_bw[i], &cur_ie_offset[i], 1, 1); - - /* prepare temporary channel setting decision */ - if (req_ch == 0) { - /* request comes from upper layer, use cur_ie values */ - dec_ch[i] = cur_ie_ch[i]; - dec_bw[i] = cur_ie_bw[i]; - dec_offset[i] = cur_ie_offset[i]; - } else { - /* use chbw of cur_ie updated with specifying req as temporary decision */ - dec_ch[i] = (req_ch <= REQ_CH_NONE) ? cur_ie_ch[i] : req_ch; - if (req_bw <= REQ_BW_NONE) { - if (req_bw == REQ_BW_ORI) - dec_bw[i] = iface->mlmepriv.ori_bw; - else - dec_bw[i] = cur_ie_bw[i]; - } else - dec_bw[i] = req_bw; - dec_offset[i] = (req_offset <= REQ_OFFSET_NONE) ? cur_ie_offset[i] : req_offset; - } - } - - if (MSTATE_STA_LD_NUM(&mstate_others) || MSTATE_STA_LG_NUM(&mstate_others) - || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others) - ) { - /* has linked/linking STA or has AP/Mesh mode */ - rtw_warn_on(!rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp_others, &u_ch, &u_bw, &u_offset)); - RTW_INFO("%s others union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset); - } - -#ifdef CONFIG_MCC_MODE - if (MCC_EN(adapter) && req_ch == 0) { - if (rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) { - u8 if_id = adapter->iface_id; - - mlmeext = &(adapter->mlmeextpriv); - - /* check channel settings are the same */ - if (cur_ie_ch[if_id] == mlmeext->cur_channel - && cur_ie_bw[if_id] == mlmeext->cur_bwmode - && cur_ie_offset[if_id] == mlmeext->cur_ch_offset) { - - RTW_INFO(FUNC_ADPT_FMT"req ch settings are the same as current ch setting, go to exit\n" - , FUNC_ADPT_ARG(adapter)); - - *chbw_allow = _FALSE; - goto exit; - } else { - RTW_INFO(FUNC_ADPT_FMT"request channel settings are not the same as current channel setting(%d,%d,%d,%d,%d,%d), restart MCC\n" - , FUNC_ADPT_ARG(adapter) - , cur_ie_ch[if_id], cur_ie_bw[if_id], cur_ie_offset[if_id] - , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset); - - rtw_hal_set_mcc_setting_disconnect(adapter); - } - } - } -#endif /* CONFIG_MCC_MODE */ - - if (MSTATE_STA_LG_NUM(&mstate_others) && !MSTATE_STA_LD_NUM(&mstate_others)) { - /* has linking STA but no linked STA */ - - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) - continue; - iface = dvobj->padapters[i]; - - rtw_adjust_chbw(iface, dec_ch[i], &dec_bw[i], &dec_offset[i]); - #ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(iface)) - rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]); - #endif - - if (rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) { - rtw_chset_sync_chbw(chset - , &dec_ch[i], &dec_bw[i], &dec_offset[i] - , &u_ch, &u_bw, &u_offset); - set_u_ch = _TRUE; - - /* channel bw offset can be allowed, not need MCC */ - *chbw_allow = _TRUE; - } else { - #ifdef CONFIG_MCC_MODE - if (MCC_EN(iface)) { - mlmeext = &(iface->mlmeextpriv); - mlmeext->cur_channel = *ch = dec_ch[i]; - mlmeext->cur_bwmode = *bw = dec_bw[i]; - mlmeext->cur_ch_offset = *offset = dec_offset[i]; - - /* channel bw offset can not be allowed, need MCC */ - *chbw_allow = _FALSE; - RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface) - , *ch, *bw, *offset); - goto exit; - } - #endif /* CONFIG_MCC_MODE */ - - /* set this for possible ch change when join down*/ - set_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING); - } - } - - } else if (MSTATE_STA_LD_NUM(&mstate_others) - || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others) - ) { - /* has linked STA mode or AP/Mesh mode */ - - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) - continue; - iface = dvobj->padapters[i]; - - rtw_adjust_chbw(iface, u_ch, &dec_bw[i], &dec_offset[i]); - #ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(iface)) - rtw_mesh_adjust_chbw(u_ch, &dec_bw[i], &dec_offset[i]); - #endif - - #ifdef CONFIG_MCC_MODE - if (MCC_EN(iface)) { - if (!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) { - mlmeext = &(iface->mlmeextpriv); - mlmeext->cur_channel = *ch = dec_ch[i] = cur_ie_ch[i]; - mlmeext->cur_bwmode = *bw = dec_bw[i] = cur_ie_bw[i]; - mlmeext->cur_ch_offset = *offset = dec_offset[i] = cur_ie_offset[i]; - /* channel bw offset can not be allowed, need MCC */ - *chbw_allow = _FALSE; - RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface) - , *ch, *bw, *offset); - goto exit; - } else - /* channel bw offset can be allowed, not need MCC */ - *chbw_allow = _TRUE; - } - #endif /* CONFIG_MCC_MODE */ - - if (req_ch == 0 && dec_bw[i] > u_bw - && rtw_is_dfs_chbw(u_ch, u_bw, u_offset) - ) { - /* request comes from upper layer, prevent from additional channel waiting */ - dec_bw[i] = u_bw; - if (dec_bw[i] == CHANNEL_WIDTH_20) - dec_offset[i] = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - } - - /* follow */ - rtw_chset_sync_chbw(chset - , &dec_ch[i], &dec_bw[i], &dec_offset[i] - , &u_ch, &u_bw, &u_offset); - } - - set_u_ch = _TRUE; - - } else { - /* autonomous decision */ - u8 ori_ch = 0; - u8 max_bw; - - /* autonomous decision, not need MCC */ - *chbw_allow = _TRUE; - - if (req_ch <= REQ_CH_NONE) /* channel is not specified */ - goto choose_chbw; - - /* get tmp dec union of ifbmp */ - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) - continue; - if (u_ch == 0) { - u_ch = dec_ch[i]; - u_bw = dec_bw[i]; - u_offset = dec_offset[i]; - rtw_adjust_chbw(adapter, u_ch, &u_bw, &u_offset); - rtw_get_offset_by_chbw(u_ch, u_bw, &u_offset); - } else { - u8 tmp_ch = dec_ch[i]; - u8 tmp_bw = dec_bw[i]; - u8 tmp_offset = dec_offset[i]; - - rtw_adjust_chbw(adapter, tmp_ch, &tmp_bw, &tmp_offset); - rtw_get_offset_by_chbw(tmp_ch, tmp_bw, &tmp_offset); - - rtw_warn_on(!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, tmp_ch, tmp_bw, tmp_offset)); - rtw_sync_chbw(&tmp_ch, &tmp_bw, &tmp_offset, &u_ch, &u_bw, &u_offset); - } - } - - #ifdef CONFIG_RTW_MESH - /* if ifbmp are all mesh, apply bw restriction */ - if (ifbmp_all_mesh) - rtw_mesh_adjust_chbw(u_ch, &u_bw, &u_offset); - #endif - - RTW_INFO("%s ifbmp:0x%02x tmp union:%u,%u,%u\n", __func__, ifbmp, u_ch, u_bw, u_offset); - - /* check if tmp dec union is usable */ - if (rtw_ap_ch_specific_chk(adapter, u_ch, &u_bw, &u_offset, __func__) == _FAIL) { - /* channel can't be used */ - if (req_ch > 0) { - /* specific channel and not from IE => don't change channel setting */ - goto exit; - } - goto choose_chbw; - } else if (rtw_chset_is_chbw_non_ocp(chset, u_ch, u_bw, u_offset)) { - RTW_WARN("%s DFS channel %u,%u under non ocp\n", __func__, u_ch, u_bw); - if (req_ch > 0 && req_bw > REQ_BW_NONE) { - /* change_chbw with specific channel and specific bw, goto update_bss_chbw directly */ - goto update_bss_chbw; - } - } else - goto update_bss_chbw; - -choose_chbw: - req_ch = req_ch > 0 ? req_ch : 0; - max_bw = req_bw > REQ_BW_NONE ? req_bw : CHANNEL_WIDTH_20; - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) - continue; - iface = dvobj->padapters[i]; - mlmeext = &(iface->mlmeextpriv); - - if (req_bw <= REQ_BW_NONE) { - if (req_bw == REQ_BW_ORI) { - if (max_bw < iface->mlmepriv.ori_bw) - max_bw = iface->mlmepriv.ori_bw; - } else { - if (max_bw < cur_ie_bw[i]) - max_bw = cur_ie_bw[i]; - } - } - - if (MSTATE_AP_NUM(&mstate) || MSTATE_MESH_NUM(&mstate)) { - if (ori_ch == 0) - ori_ch = mlmeext->cur_channel; - else if (ori_ch != mlmeext->cur_channel) - rtw_warn_on(1); - } else { - if (ori_ch == 0) - ori_ch = cur_ie_ch[i]; - else if (ori_ch != cur_ie_ch[i]) - rtw_warn_on(1); - } - } - - ch_avail = rtw_ap_choose_chbw(adapter, req_ch, max_bw - , ori_ch, &u_ch, &u_bw, &u_offset, ifbmp_all_mesh, __func__); - if (ch_avail == _FALSE) - goto exit; - -update_bss_chbw: - for (i = 0; i < dvobj->iface_nums; i++) { - if (!(ifbmp & BIT(i)) || !dvobj->padapters[i]) - continue; - iface = dvobj->padapters[i]; - - dec_ch[i] = u_ch; - if (dec_bw[i] > u_bw) - dec_bw[i] = u_bw; - if (dec_bw[i] == CHANNEL_WIDTH_20) - dec_offset[i] = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - else - dec_offset[i] = u_offset; - - #ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(iface)) - rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]); - #endif - } - - set_u_ch = _TRUE; - } - - ifbmp_ch_changed = rtw_ap_update_chbw_by_ifbmp(dvobj, ifbmp - , cur_ie_ch, cur_ie_bw, cur_ie_offset - , dec_ch, dec_bw, dec_offset - , __func__); - - if (u_ch != 0) - RTW_INFO("%s union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset); - - if (rtw_mi_check_fwstate(adapter, _FW_UNDER_SURVEY)) { - /* scanning, leave ch setting to scan state machine */ - set_u_ch = _FALSE; - } - - if (set_u_ch == _TRUE) { - *ch = u_ch; - *bw = u_bw; - *offset = u_offset; - } -exit: - return ifbmp_ch_changed; -} - -u8 rtw_ap_sta_states_check(_adapter *adapter) -{ - struct sta_info *psta; - struct sta_priv *pstapriv = &adapter->stapriv; - _list *plist, *phead; - _irqL irqL; - u8 rst = _FALSE; - - if (!MLME_IS_AP(adapter) && !MLME_IS_MESH(adapter)) - return _FALSE; - - if (pstapriv->auth_list_cnt !=0) - return _TRUE; - - _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) { - - psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - plist = get_next(plist); - - if (!(psta->state & _FW_LINKED)) { - RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under linking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state); - rst = _TRUE; - break; - } else if (psta->state & WIFI_UNDER_KEY_HANDSHAKE) { - RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under key handshaking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state); - rst = _TRUE; - break; - } - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - return rst; -} - -/*#define DBG_SWTIMER_BASED_TXBCN*/ -#ifdef CONFIG_SWTIMER_BASED_TXBCN -void tx_beacon_handlder(struct dvobj_priv *pdvobj) -{ -#define BEACON_EARLY_TIME 20 /* unit:TU*/ - _irqL irqL; - _list *plist, *phead; - u32 timestamp[2]; - u32 bcn_interval_us; /* unit : usec */ - u64 time; - u32 cur_tick, time_offset; /* unit : usec */ - u32 inter_bcn_space_us; /* unit : usec */ - u32 txbcn_timer_ms; /* unit : ms */ - int nr_vap, idx, bcn_idx; - int i; - u8 val8, late = 0; - _adapter *padapter = NULL; - - i = 0; - - /* get first ap mode interface */ - _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - if (rtw_is_list_empty(&pdvobj->ap_if_q.queue) || (pdvobj->nr_ap_if == 0)) { - RTW_INFO("[%s] ERROR: ap_if_q is empty!or nr_ap = %d\n", __func__, pdvobj->nr_ap_if); - _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - return; - } else - padapter = LIST_CONTAINOR(get_next(&(pdvobj->ap_if_q.queue)), struct _ADAPTER, list); - _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - - if (NULL == padapter) { - RTW_INFO("[%s] ERROR: no any ap interface!\n", __func__); - return; - } - - - bcn_interval_us = DEFAULT_BCN_INTERVAL * NET80211_TU_TO_US; - if (0 == bcn_interval_us) { - RTW_INFO("[%s] ERROR: beacon interval = 0\n", __func__); - return; - } - - /* read TSF */ - timestamp[1] = rtw_read32(padapter, 0x560 + 4); - timestamp[0] = rtw_read32(padapter, 0x560); - while (timestamp[1]) { - time = (0xFFFFFFFF % bcn_interval_us + 1) * timestamp[1] + timestamp[0]; - timestamp[0] = (u32)time; - timestamp[1] = (u32)(time >> 32); - } - cur_tick = timestamp[0] % bcn_interval_us; - - - _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - - nr_vap = (pdvobj->nr_ap_if - 1); - if (nr_vap > 0) { - inter_bcn_space_us = pdvobj->inter_bcn_space * NET80211_TU_TO_US; /* beacon_interval / (nr_vap+1); */ - idx = cur_tick / inter_bcn_space_us; - if (idx < nr_vap) /* if (idx < (nr_vap+1))*/ - bcn_idx = idx + 1; /* bcn_idx = (idx + 1) % (nr_vap+1);*/ - else - bcn_idx = 0; - - /* to get padapter based on bcn_idx */ - padapter = NULL; - phead = get_list_head(&pdvobj->ap_if_q); - plist = get_next(phead); - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { - padapter = LIST_CONTAINOR(plist, struct _ADAPTER, list); - - plist = get_next(plist); - - if (i == bcn_idx) - break; - - i++; - } - if ((NULL == padapter) || (i > pdvobj->nr_ap_if)) { - RTW_INFO("[%s] ERROR: nr_ap_if = %d, padapter=%p, bcn_idx=%d, index=%d\n", - __func__, pdvobj->nr_ap_if, padapter, bcn_idx, i); - _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - return; - } -#ifdef DBG_SWTIMER_BASED_TXBCN - RTW_INFO("BCN_IDX=%d, cur_tick=%d, padapter=%p\n", bcn_idx, cur_tick, padapter); -#endif - if (((idx + 2 == nr_vap + 1) && (idx < nr_vap + 1)) || (0 == bcn_idx)) { - time_offset = bcn_interval_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US; - if ((s32)time_offset < 0) - time_offset += inter_bcn_space_us; - - } else { - time_offset = (idx + 2) * inter_bcn_space_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US; - if (time_offset > (inter_bcn_space_us + (inter_bcn_space_us >> 1))) { - time_offset -= inter_bcn_space_us; - late = 1; - } - } - } else - /*#endif*/ { /* MBSSID */ - time_offset = 2 * bcn_interval_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US; - if (time_offset > (bcn_interval_us + (bcn_interval_us >> 1))) { - time_offset -= bcn_interval_us; - late = 1; - } - } - _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL); - -#ifdef DBG_SWTIMER_BASED_TXBCN - RTW_INFO("set sw bcn timer %d us\n", time_offset); -#endif - txbcn_timer_ms = time_offset / NET80211_TU_TO_US; - _set_timer(&pdvobj->txbcn_timer, txbcn_timer_ms); - - if (padapter) { -#ifdef CONFIG_BCN_RECOVERY - rtw_ap_bcn_recovery(padapter); -#endif /*CONFIG_BCN_RECOVERY*/ - -#ifdef CONFIG_BCN_XMIT_PROTECT - rtw_ap_bcn_queue_empty_check(padapter, txbcn_timer_ms); -#endif /*CONFIG_BCN_XMIT_PROTECT*/ - -#ifdef DBG_SWTIMER_BASED_TXBCN - RTW_INFO("padapter=%p, PORT=%d\n", padapter, padapter->hw_port); -#endif - /* bypass TX BCN queue if op ch is switching/waiting */ - if (!check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING) - && !IS_CH_WAITING(adapter_to_rfctl(padapter)) - ) { - /*update_beacon(padapter, _TIM_IE_, NULL, _FALSE);*/ - /*issue_beacon(padapter, 0);*/ - send_beacon(padapter); - } - } - -#if 0 - /* handle any buffered BC/MC frames*/ - /* Don't dynamically change DIS_ATIM due to HW will auto send ACQ after HIQ empty.*/ - val8 = *((unsigned char *)priv->beaconbuf + priv->timoffset + 4); - if (val8 & 0x01) { - process_mcast_dzqueue(priv); - priv->pkt_in_dtimQ = 0; - } -#endif - -} - -void tx_beacon_timer_handlder(void *ctx) -{ - struct dvobj_priv *pdvobj = (struct dvobj_priv *)ctx; - _adapter *padapter = pdvobj->padapters[0]; - - if (padapter) - set_tx_beacon_cmd(padapter); -} -#endif - -void rtw_ap_parse_sta_capability(_adapter *adapter, struct sta_info *sta, u8 *cap) -{ - sta->capability = RTW_GET_LE16(cap); - if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - sta->flags |= WLAN_STA_SHORT_PREAMBLE; - else - sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; -} - -u16 rtw_ap_parse_sta_supported_rates(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len) -{ - u8 rate_set[12]; - u8 rate_num; - int i; - u16 status = _STATS_SUCCESSFUL_; - - rtw_ies_get_supported_rate(tlv_ies, tlv_ies_len, rate_set, &rate_num); - if (rate_num == 0) { - RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" with no supported rate\n" - , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr)); - status = _STATS_FAILURE_; - goto exit; - } - - _rtw_memcpy(sta->bssrateset, rate_set, rate_num); - sta->bssratelen = rate_num; - - if (MLME_IS_AP(adapter)) { - /* this function force only CCK rates to be bassic rate... */ - UpdateBrateTblForSoftAP(sta->bssrateset, sta->bssratelen); - } - - /* if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) */ /* ? */ - sta->flags |= WLAN_STA_NONERP; - for (i = 0; i < sta->bssratelen; i++) { - if ((sta->bssrateset[i] & 0x7f) > 22) { - sta->flags &= ~WLAN_STA_NONERP; - break; - } - } - -exit: - return status; -} - -u16 rtw_ap_parse_sta_security_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems) -{ - struct security_priv *sec = &adapter->securitypriv; - u8 *wpa_ie; - int wpa_ie_len; - int group_cipher = 0, pairwise_cipher = 0; - u32 akm = 0; - u8 mfp_opt = MFP_NO; - u16 status = _STATS_SUCCESSFUL_; - - sta->dot8021xalg = 0; - sta->wpa_psk = 0; - sta->wpa_group_cipher = 0; - sta->wpa2_group_cipher = 0; - sta->wpa_pairwise_cipher = 0; - sta->wpa2_pairwise_cipher = 0; - _rtw_memset(sta->wpa_ie, 0, sizeof(sta->wpa_ie)); - - if ((sec->wpa_psk & BIT(1)) && elems->rsn_ie) { - wpa_ie = elems->rsn_ie; - wpa_ie_len = elems->rsn_ie_len; - - if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, &akm, &mfp_opt) == _SUCCESS) { - sta->dot8021xalg = 1;/* psk, todo:802.1x */ - sta->wpa_psk |= BIT(1); - - sta->wpa2_group_cipher = group_cipher & sec->wpa2_group_cipher; - sta->wpa2_pairwise_cipher = pairwise_cipher & sec->wpa2_pairwise_cipher; - - sta->akm_suite_type = akm; - if ((CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) && (MFP_NO == mfp_opt)) - status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; - - if (!sta->wpa2_group_cipher) - status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - - if (!sta->wpa2_pairwise_cipher) - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - } else - status = WLAN_STATUS_INVALID_IE; - - } - else if ((sec->wpa_psk & BIT(0)) && elems->wpa_ie) { - wpa_ie = elems->wpa_ie; - wpa_ie_len = elems->wpa_ie_len; - - if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { - sta->dot8021xalg = 1;/* psk, todo:802.1x */ - sta->wpa_psk |= BIT(0); - - sta->wpa_group_cipher = group_cipher & sec->wpa_group_cipher; - sta->wpa_pairwise_cipher = pairwise_cipher & sec->wpa_pairwise_cipher; - - if (!sta->wpa_group_cipher) - status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - - if (!sta->wpa_pairwise_cipher) - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - } else - status = WLAN_STATUS_INVALID_IE; - - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(adapter)) { - /* MFP is mandatory for secure mesh */ - if (adapter->mesh_info.mesh_auth_id) - sta->flags |= WLAN_STA_MFP; - } else -#endif - if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt == MFP_NO) || mfp_opt == MFP_INVALID) - status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; - else if (sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL) - sta->flags |= WLAN_STA_MFP; - - if ((sec->auth_type == NL80211_AUTHTYPE_SAE) && - (CHECK_BIT(WLAN_AKM_TYPE_SAE, sta->akm_suite_type)) && - (WLAN_AUTH_OPEN == sta->authalg)) { - /* WPA3-SAE, PMK caching */ - if (rtw_cached_pmkid(adapter, sta->cmn.mac_addr) == -1) { - RTW_INFO("SAE: No PMKSA cache entry found\n"); - status = WLAN_STATUS_INVALID_PMKID; - } else { - RTW_INFO("SAE: PMKSA cache entry found\n"); - } - } - - if (status != _STATS_SUCCESSFUL_) - goto exit; - - if (!MLME_IS_AP(adapter)) - goto exit; - - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - /* if (hapd->conf->wps_state && wpa_ie == NULL) { */ /* todo: to check ap if supporting WPS */ - if (wpa_ie == NULL) { - if (elems->wps_ie) { - RTW_INFO("STA included WPS IE in " - "(Re)Association Request - assume WPS is " - "used\n"); - sta->flags |= WLAN_STA_WPS; - /* wpabuf_free(sta->wps_ie); */ - /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ - /* elems.wps_ie_len - 4); */ - } else { - RTW_INFO("STA did not include WPA/RSN IE " - "in (Re)Association Request - possible WPS " - "use\n"); - sta->flags |= WLAN_STA_MAYBE_WPS; - } - - /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ - /* that the selected registrar of AP is _FLASE */ - if ((sec->wpa_psk > 0) - && (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) - ) { - struct mlme_priv *mlme = &adapter->mlmepriv; - - if (mlme->wps_beacon_ie) { - u8 selected_registrar = 0; - - rtw_get_wps_attr_content(mlme->wps_beacon_ie, mlme->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); - - if (!selected_registrar) { - RTW_INFO("selected_registrar is _FALSE , or AP is not ready to do WPS\n"); - status = _STATS_UNABLE_HANDLE_STA_; - goto exit; - } - } - } - - } else { - int copy_len; - - if (sec->wpa_psk == 0) { - RTW_INFO("STA " MAC_FMT - ": WPA/RSN IE in association request, but AP don't support WPA/RSN\n", - MAC_ARG(sta->cmn.mac_addr)); - status = WLAN_STATUS_INVALID_IE; - goto exit; - } - - if (elems->wps_ie) { - RTW_INFO("STA included WPS IE in " - "(Re)Association Request - WPS is " - "used\n"); - sta->flags |= WLAN_STA_WPS; - copy_len = 0; - } else - copy_len = ((wpa_ie_len + 2) > sizeof(sta->wpa_ie)) ? (sizeof(sta->wpa_ie)) : (wpa_ie_len + 2); - - if (copy_len > 0) - _rtw_memcpy(sta->wpa_ie, wpa_ie - 2, copy_len); - } - -exit: - return status; -} - -void rtw_ap_parse_sta_wmm_ie(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len) -{ - struct mlme_priv *mlme = &adapter->mlmepriv; - unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; - u8 *p; - - sta->flags &= ~WLAN_STA_WME; - sta->qos_option = 0; - sta->qos_info = 0; - sta->has_legacy_ac = _TRUE; - sta->uapsd_vo = 0; - sta->uapsd_vi = 0; - sta->uapsd_be = 0; - sta->uapsd_bk = 0; - - if (!mlme->qospriv.qos_option) - goto exit; - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(adapter)) { - /* QoS is mandatory in mesh */ - sta->flags |= WLAN_STA_WME; - } -#endif - - p = rtw_get_ie_ex(tlv_ies, tlv_ies_len, WLAN_EID_VENDOR_SPECIFIC, WMM_IE, 6, NULL, NULL); - if (!p) - goto exit; - - sta->flags |= WLAN_STA_WME; - sta->qos_option = 1; - sta->qos_info = *(p + 8); - sta->max_sp_len = (sta->qos_info >> 5) & 0x3; - - if ((sta->qos_info & 0xf) != 0xf) - sta->has_legacy_ac = _TRUE; - else - sta->has_legacy_ac = _FALSE; - - if (sta->qos_info & 0xf) { - if (sta->qos_info & BIT(0)) - sta->uapsd_vo = BIT(0) | BIT(1); - else - sta->uapsd_vo = 0; - - if (sta->qos_info & BIT(1)) - sta->uapsd_vi = BIT(0) | BIT(1); - else - sta->uapsd_vi = 0; - - if (sta->qos_info & BIT(2)) - sta->uapsd_bk = BIT(0) | BIT(1); - else - sta->uapsd_bk = 0; - - if (sta->qos_info & BIT(3)) - sta->uapsd_be = BIT(0) | BIT(1); - else - sta->uapsd_be = 0; - } - -exit: - return; -} - -void rtw_ap_parse_sta_ht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems) -{ - struct mlme_priv *mlme = &adapter->mlmepriv; - - sta->flags &= ~WLAN_STA_HT; - -#ifdef CONFIG_80211N_HT - if (mlme->htpriv.ht_option == _FALSE) - goto exit; - - /* save HT capabilities in the sta object */ - _rtw_memset(&sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap)); - if (elems->ht_capabilities && elems->ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) { - sta->flags |= WLAN_STA_HT; - sta->flags |= WLAN_STA_WME; - _rtw_memcpy(&sta->htpriv.ht_cap, elems->ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap)); - - if (elems->ht_operation && elems->ht_operation_len == HT_OP_IE_LEN) { - _rtw_memcpy(sta->htpriv.ht_op, elems->ht_operation, HT_OP_IE_LEN); - sta->htpriv.op_present = 1; - } - } -exit: -#endif - - return; -} - -void rtw_ap_parse_sta_vht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems) -{ - struct mlme_priv *mlme = &adapter->mlmepriv; - - sta->flags &= ~WLAN_STA_VHT; - -#ifdef CONFIG_80211AC_VHT - if (mlme->vhtpriv.vht_option == _FALSE) - goto exit; - - _rtw_memset(&sta->vhtpriv, 0, sizeof(struct vht_priv)); - if (elems->vht_capabilities && elems->vht_capabilities_len == VHT_CAP_IE_LEN) { - sta->flags |= WLAN_STA_VHT; - _rtw_memcpy(sta->vhtpriv.vht_cap, elems->vht_capabilities, VHT_CAP_IE_LEN); - - if (elems->vht_operation && elems->vht_operation_len== VHT_OP_IE_LEN) { - _rtw_memcpy(sta->vhtpriv.vht_op, elems->vht_operation, VHT_OP_IE_LEN); - sta->vhtpriv.op_present = 1; - } - - if (elems->vht_op_mode_notify && elems->vht_op_mode_notify_len == 1) { - _rtw_memcpy(&sta->vhtpriv.vht_op_mode_notify, elems->vht_op_mode_notify, 1); - sta->vhtpriv.notify_present = 1; - } - } -exit: -#endif - - return; -} -#endif /* CONFIG_AP_MODE */ diff --git a/core/rtw_ieee80211.c.orig b/core/rtw_ieee80211.c.orig deleted file mode 100644 index 33b05c4..0000000 --- a/core/rtw_ieee80211.c.orig +++ /dev/null @@ -1,2878 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2017 Realtek Corporation. - * - * 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. - * - *****************************************************************************/ -#define _IEEE80211_C - -#ifdef CONFIG_PLATFORM_INTEL_BYT - #include -#endif -#include - - -u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -u16 RTW_WPA_VERSION = 1; -u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 }; -u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 }; -u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 }; -u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 }; -u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 }; - -u16 RSN_VERSION_BSD = 1; -u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 }; -u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 }; -u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 }; -u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 }; -u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 }; -u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 }; - -u8 WLAN_AKM_8021X[] = {0x00, 0x0f, 0xac, 1}; -u8 WLAN_AKM_PSK[] = {0x00, 0x0f, 0xac, 2}; -u8 WLAN_AKM_FT_8021X[] = {0x00, 0x0f, 0xac, 3}; -u8 WLAN_AKM_FT_PSK[] = {0x00, 0x0f, 0xac, 4}; -u8 WLAN_AKM_8021X_SHA256[] = {0x00, 0x0f, 0xac, 5}; -u8 WLAN_AKM_PSK_SHA256[] = {0x00, 0x0f, 0xac, 6}; -u8 WLAN_AKM_TDLS[] = {0x00, 0x0f, 0xac, 7}; -u8 WLAN_AKM_SAE[] = {0x00, 0x0f, 0xac, 8}; -u8 WLAN_AKM_FT_OVER_SAE[] = {0x00, 0x0f, 0xac, 9}; -u8 WLAN_AKM_8021X_SUITE_B[] = {0x00, 0x0f, 0xac, 11}; -u8 WLAN_AKM_8021X_SUITE_B_192[] = {0x00, 0x0f, 0xac, 12}; -u8 WLAN_AKM_FILS_SHA256[] = {0x00, 0x0f, 0xac, 14}; -u8 WLAN_AKM_FILS_SHA384[] = {0x00, 0x0f, 0xac, 15}; -u8 WLAN_AKM_FT_FILS_SHA256[] = {0x00, 0x0f, 0xac, 16}; -u8 WLAN_AKM_FT_FILS_SHA384[] = {0x00, 0x0f, 0xac, 17}; -/* ----------------------------------------------------------- - * for adhoc-master to generate ie and provide supported-rate to fw - * ----------------------------------------------------------- */ - -static u8 WIFI_CCKRATES[] = { - (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK), - (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK) -}; - -static u8 WIFI_OFDMRATES[] = { - (IEEE80211_OFDM_RATE_6MB), - (IEEE80211_OFDM_RATE_9MB), - (IEEE80211_OFDM_RATE_12MB), - (IEEE80211_OFDM_RATE_18MB), - (IEEE80211_OFDM_RATE_24MB), - IEEE80211_OFDM_RATE_36MB, - IEEE80211_OFDM_RATE_48MB, - IEEE80211_OFDM_RATE_54MB -}; - -u8 mgn_rates_cck[4] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M}; -u8 mgn_rates_ofdm[8] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M}; -u8 mgn_rates_mcs0_7[8] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7}; -u8 mgn_rates_mcs8_15[8] = {MGN_MCS8, MGN_MCS9, MGN_MCS10, MGN_MCS11, MGN_MCS12, MGN_MCS13, MGN_MCS14, MGN_MCS15}; -u8 mgn_rates_mcs16_23[8] = {MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23}; -u8 mgn_rates_mcs24_31[8] = {MGN_MCS24, MGN_MCS25, MGN_MCS26, MGN_MCS27, MGN_MCS28, MGN_MCS29, MGN_MCS30, MGN_MCS31}; -u8 mgn_rates_vht1ss[10] = {MGN_VHT1SS_MCS0, MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4 - , MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9 - }; -u8 mgn_rates_vht2ss[10] = {MGN_VHT2SS_MCS0, MGN_VHT2SS_MCS1, MGN_VHT2SS_MCS2, MGN_VHT2SS_MCS3, MGN_VHT2SS_MCS4 - , MGN_VHT2SS_MCS5, MGN_VHT2SS_MCS6, MGN_VHT2SS_MCS7, MGN_VHT2SS_MCS8, MGN_VHT2SS_MCS9 - }; -u8 mgn_rates_vht3ss[10] = {MGN_VHT3SS_MCS0, MGN_VHT3SS_MCS1, MGN_VHT3SS_MCS2, MGN_VHT3SS_MCS3, MGN_VHT3SS_MCS4 - , MGN_VHT3SS_MCS5, MGN_VHT3SS_MCS6, MGN_VHT3SS_MCS7, MGN_VHT3SS_MCS8, MGN_VHT3SS_MCS9 - }; -u8 mgn_rates_vht4ss[10] = {MGN_VHT4SS_MCS0, MGN_VHT4SS_MCS1, MGN_VHT4SS_MCS2, MGN_VHT4SS_MCS3, MGN_VHT4SS_MCS4 - , MGN_VHT4SS_MCS5, MGN_VHT4SS_MCS6, MGN_VHT4SS_MCS7, MGN_VHT4SS_MCS8, MGN_VHT4SS_MCS9 - }; - -static const char *const _rate_section_str[] = { - "CCK", - "OFDM", - "HT_1SS", - "HT_2SS", - "HT_3SS", - "HT_4SS", - "VHT_1SS", - "VHT_2SS", - "VHT_3SS", - "VHT_4SS", - "RATE_SECTION_UNKNOWN", -}; - -const char *rate_section_str(u8 section) -{ - section = (section >= RATE_SECTION_NUM) ? RATE_SECTION_NUM : section; - return _rate_section_str[section]; -} - -struct rate_section_ent rates_by_sections[RATE_SECTION_NUM] = { - {RF_1TX, 4, mgn_rates_cck}, - {RF_1TX, 8, mgn_rates_ofdm}, - {RF_1TX, 8, mgn_rates_mcs0_7}, - {RF_2TX, 8, mgn_rates_mcs8_15}, - {RF_3TX, 8, mgn_rates_mcs16_23}, - {RF_4TX, 8, mgn_rates_mcs24_31}, - {RF_1TX, 10, mgn_rates_vht1ss}, - {RF_2TX, 10, mgn_rates_vht2ss}, - {RF_3TX, 10, mgn_rates_vht3ss}, - {RF_4TX, 10, mgn_rates_vht4ss}, -}; - -int rtw_get_bit_value_from_ieee_value(u8 val) -{ - unsigned char dot11_rate_table[] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 0}; /* last element must be zero!! */ - - int i = 0; - while (dot11_rate_table[i] != 0) { - if (dot11_rate_table[i] == val) - return BIT(i); - i++; - } - return 0; -} -uint rtw_get_cckrate_size(u8 *rate, u32 rate_length) -{ - int i = 0; - while(i < rate_length){ - RTW_DBG("%s, rate[%d]=%u\n", __FUNCTION__, i, rate[i]); - if (((rate[i] & 0x7f) == 2) || ((rate[i] & 0x7f) == 4) || - ((rate[i] & 0x7f) == 11) || ((rate[i] & 0x7f) == 22)) - i++; - else - break; - } - return i; -} - -uint rtw_is_cckrates_included(u8 *rate) -{ - u32 i = 0; - - while (rate[i] != 0) { - if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) || - (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22)) - return _TRUE; - i++; - } - - return _FALSE; -} - -uint rtw_is_cckratesonly_included(u8 *rate) -{ - u32 i = 0; - - - while (rate[i] != 0) { - if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) && - (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22)) - return _FALSE; - - i++; - } - - return _TRUE; - -} - -int rtw_check_network_type(unsigned char *rate, int ratelen, int channel) -{ - if (channel > 14) { - if ((rtw_is_cckrates_included(rate)) == _TRUE) - return WIRELESS_INVALID; - else - return WIRELESS_11A; - } else { /* could be pure B, pure G, or B/G */ - if ((rtw_is_cckratesonly_included(rate)) == _TRUE) - return WIRELESS_11B; - else if ((rtw_is_cckrates_included(rate)) == _TRUE) - return WIRELESS_11BG; - else - return WIRELESS_11G; - } - -} - -u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source, - unsigned int *frlen) -{ - _rtw_memcpy((void *)pbuf, (void *)source, len); - *frlen = *frlen + len; - return pbuf + len; -} - -/* rtw_set_ie will update frame length */ -u8 *rtw_set_ie -( - u8 *pbuf, - sint index, - uint len, - const u8 *source, - uint *frlen /* frame length */ -) -{ - *pbuf = (u8)index; - - *(pbuf + 1) = (u8)len; - - if (len > 0) - _rtw_memcpy((void *)(pbuf + 2), (void *)source, len); - - if (frlen) - *frlen = *frlen + (len + 2); - - return pbuf + len + 2; -} - -inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode, - u8 new_ch, u8 ch_switch_cnt) -{ - u8 ie_data[3]; - - ie_data[0] = ch_switch_mode; - ie_data[1] = new_ch; - ie_data[2] = ch_switch_cnt; - return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH, 3, ie_data, buf_len); -} - -inline u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset) -{ - if (ch_offset == SCN) - return HAL_PRIME_CHNL_OFFSET_DONT_CARE; - else if (ch_offset == SCA) - return HAL_PRIME_CHNL_OFFSET_LOWER; - else if (ch_offset == SCB) - return HAL_PRIME_CHNL_OFFSET_UPPER; - - return HAL_PRIME_CHNL_OFFSET_DONT_CARE; -} - -inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset) -{ - if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) - return SCN; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) - return SCA; - else if (ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER) - return SCB; - - return SCN; -} - -inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset) -{ - return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET, 1, &secondary_ch_offset, buf_len); -} - -inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl, - u8 flags, u16 reason, u16 precedence) -{ - u8 ie_data[6]; - - ie_data[0] = ttl; - ie_data[1] = flags; - RTW_PUT_LE16((u8 *)&ie_data[2], reason); - RTW_PUT_LE16((u8 *)&ie_data[4], precedence); - - return rtw_set_ie(buf, 0x118, 6, ie_data, buf_len); -} - -/*---------------------------------------------------------------------------- -index: the information element id index, limit is the limit for search ------------------------------------------------------------------------------*/ -u8 *rtw_get_ie(const u8 *pbuf, sint index, sint *len, sint limit) -{ - sint tmp, i; - const u8 *p; - if (limit < 1) { - return NULL; - } - - p = pbuf; - i = 0; - *len = 0; - while (1) { - if (*p == index) { - *len = *(p + 1); - return (u8 *)p; - } else { - tmp = *(p + 1); - p += (tmp + 2); - i += (tmp + 2); - } - if (i >= limit) - break; - } - return NULL; -} - -/** - * rtw_get_ie_ex - Search specific IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE - * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE - * - * Returns: The address of the specific IE found, or NULL - */ -u8 *rtw_get_ie_ex(const u8 *in_ie, uint in_len, u8 eid, const u8 *oui, u8 oui_len, u8 *ie, uint *ielen) -{ - uint cnt; - const u8 *target_ie = NULL; - - - if (ielen) - *ielen = 0; - - if (!in_ie || in_len <= 0) - return (u8 *)target_ie; - - cnt = 0; - - while (cnt < in_len) { - if (eid == in_ie[cnt] - && (!oui || _rtw_memcmp(&in_ie[cnt + 2], oui, oui_len) == _TRUE)) { - target_ie = &in_ie[cnt]; - - if (ie) - _rtw_memcpy(ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (ielen) - *ielen = in_ie[cnt + 1] + 2; - - break; - } else { - cnt += in_ie[cnt + 1] + 2; /* goto next */ - } - - } - - return (u8 *)target_ie; -} - -/** - * rtw_ies_remove_ie - Find matching IEs and remove - * @ies: Address of IEs to search - * @ies_len: Pointer of length of ies, will update to new length - * @offset: The offset to start scarch - * @eid: Element ID to match - * @oui: OUI to match - * @oui_len: OUI length - * - * Returns: _SUCCESS: ies is updated, _FAIL: not updated - */ -int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len) -{ - int ret = _FAIL; - u8 *target_ie; - u32 target_ielen; - u8 *start; - uint search_len; - - if (!ies || !ies_len || *ies_len <= offset) - goto exit; - - start = ies + offset; - search_len = *ies_len - offset; - - while (1) { - target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen); - if (target_ie && target_ielen) { - u8 *remain_ies = target_ie + target_ielen; - uint remain_len = search_len - (remain_ies - start); - - _rtw_memmove(target_ie, remain_ies, remain_len); - *ies_len = *ies_len - target_ielen; - ret = _SUCCESS; - - start = target_ie; - search_len = remain_len; - } else - break; - } -exit: - return ret; -} - - /* Returns: remove size OR _FAIL: not updated*/ -int rtw_remove_ie_g_rate(u8 *ie, uint *ie_len, uint offset, u8 eid) -{ - int ret = _FAIL; - u8 *tem_target_ie; - u8 *target_ie; - u32 target_ielen,temp_target_ielen,cck_rate_size,rm_size; - u8 *start; - uint search_len; - u8 *remain_ies; - uint remain_len; - if (!ie || !ie_len || *ie_len <= offset) - goto exit; - - start = ie + offset; - search_len = *ie_len - offset; - - while (1) { - tem_target_ie=rtw_get_ie(start,eid,&temp_target_ielen,search_len); - - /*if(tem_target_ie) - RTW_INFO("%s, tem_target_ie=%u\n", __FUNCTION__,*tem_target_ie);*/ - if (tem_target_ie && temp_target_ielen) { - cck_rate_size = rtw_get_cckrate_size((tem_target_ie+2), temp_target_ielen); - rm_size = temp_target_ielen - cck_rate_size; - RTW_DBG("%s,cck_rate_size=%u rm_size=%u\n", __FUNCTION__, cck_rate_size, rm_size); - temp_target_ielen=temp_target_ielen + 2;/*org size of Supposrted Rates(include id + length)*/ - /*RTW_INFO("%s, temp_target_ielen=%u\n", __FUNCTION__,temp_target_ielen);*/ - remain_ies = tem_target_ie + temp_target_ielen; - remain_len = search_len - (remain_ies - start); - target_ielen=cck_rate_size;/*discount g mode rate 6, 9 12,18Mbps,id , length*/ - *(tem_target_ie+1)=target_ielen;/*set new length to Supposrted Rates*/ - target_ie=tem_target_ie+target_ielen + 2;/*set target ie to address of rate 6Mbps */ - - _rtw_memmove(target_ie, remain_ies, remain_len); - *ie_len = *ie_len - rm_size; - ret = rm_size; - - start = target_ie; - search_len = remain_len; - } else - break; - } -exit: - return ret; -} -void rtw_set_supported_rate(u8 *SupportedRates, uint mode) -{ - - _rtw_memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); - - switch (mode) { - case WIRELESS_11B: - _rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - break; - - case WIRELESS_11G: - case WIRELESS_11A: - case WIRELESS_11_5N: - case WIRELESS_11A_5N: /* Todo: no basic rate for ofdm ? */ - case WIRELESS_11_5AC: - _rtw_memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); - break; - - case WIRELESS_11BG: - case WIRELESS_11G_24N: - case WIRELESS_11_24N: - case WIRELESS_11BG_24N: - _rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN); - _rtw_memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN); - break; - - } -} - -uint rtw_get_rateset_len(u8 *rateset) -{ - uint i = 0; - while (1) { - if ((rateset[i]) == 0) - break; - - if (i > 12) - break; - - i++; - } - return i; -} - -int rtw_generate_ie(struct registry_priv *pregistrypriv) -{ - u8 wireless_mode; - int sz = 0, rateLen; - WLAN_BSSID_EX *pdev_network = &pregistrypriv->dev_network; - u8 *ie = pdev_network->IEs; - - - /* timestamp will be inserted by hardware */ - sz += 8; - ie += sz; - - /* beacon interval : 2bytes */ - *(u16 *)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod); /* BCN_INTERVAL; */ - sz += 2; - ie += 2; - - /* capability info */ - *(u16 *)ie = 0; - - *(u16 *)ie |= cpu_to_le16(cap_IBSS); - - if (pregistrypriv->preamble == PREAMBLE_SHORT) - *(u16 *)ie |= cpu_to_le16(cap_ShortPremble); - - if (pdev_network->Privacy) - *(u16 *)ie |= cpu_to_le16(cap_Privacy); - - sz += 2; - ie += 2; - - /* SSID */ - ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz); - - /* supported rates */ - if (pregistrypriv->wireless_mode == WIRELESS_11ABGN) { - if (pdev_network->Configuration.DSConfig > 14) - wireless_mode = WIRELESS_11A_5N; - else - wireless_mode = WIRELESS_11BG_24N; - } else if (pregistrypriv->wireless_mode == WIRELESS_MODE_MAX) { /* WIRELESS_11ABGN | WIRELESS_11AC */ - if (pdev_network->Configuration.DSConfig > 14) - wireless_mode = WIRELESS_11_5AC; - else - wireless_mode = WIRELESS_11BG_24N; - } else - wireless_mode = pregistrypriv->wireless_mode; - - rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ; - - rateLen = rtw_get_rateset_len(pdev_network->SupportedRates); - - if (rateLen > 8) { - ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz); - /* ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); */ - } else - ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz); - - /* DS parameter set */ - ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz); - - - /* IBSS Parameter Set */ - - ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz); - - if (rateLen > 8) - ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz); - -#ifdef CONFIG_80211N_HT - /* HT Cap. */ - if (is_supported_ht(pregistrypriv->wireless_mode) - && (pregistrypriv->ht_enable == _TRUE)) { - /* todo: */ - } -#endif /* CONFIG_80211N_HT */ - - /* pdev_network->IELength = sz; */ /* update IELength */ - - - /* return _SUCCESS; */ - - return sz; - -} - -unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit) -{ - int len; - u16 val16; - unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01}; - u8 *pbuf = pie; - int limit_new = limit; - - while (1) { - pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new); - - if (pbuf) { - - /* check if oui matches... */ - if (_rtw_memcmp((pbuf + 2), wpa_oui_type, sizeof(wpa_oui_type)) == _FALSE) - - goto check_next_ie; - - /* check version... */ - _rtw_memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16)); - - val16 = le16_to_cpu(val16); - if (val16 != 0x0001) - goto check_next_ie; - - *wpa_ie_len = *(pbuf + 1); - - return pbuf; - - } else { - - *wpa_ie_len = 0; - return NULL; - } - -check_next_ie: - - limit_new = limit - (pbuf - pie) - 2 - len; - - if (limit_new <= 0) - break; - - pbuf += (2 + len); - - } - - *wpa_ie_len = 0; - - return NULL; - -} - -unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit) -{ - - return rtw_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit); - -} - -int rtw_get_wpa_cipher_suite(u8 *s) -{ - if (_rtw_memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_NONE; - if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_WEP40; - if (_rtw_memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_TKIP; - if (_rtw_memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_CCMP; - if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_WEP104; - - return 0; -} - -int rtw_get_wpa2_cipher_suite(u8 *s) -{ - if (_rtw_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_NONE; - if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_WEP40; - if (_rtw_memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_TKIP; - if (_rtw_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_CCMP; - if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == _TRUE) - return WPA_CIPHER_WEP104; - - return 0; -} - -u32 rtw_get_akm_suite_bitmap(u8 *s) -{ - if (_rtw_memcmp(s, WLAN_AKM_8021X, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_8021X; - if (_rtw_memcmp(s, WLAN_AKM_PSK, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_PSK; - if (_rtw_memcmp(s, WLAN_AKM_FT_8021X, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_FT_8021X; - if (_rtw_memcmp(s, WLAN_AKM_FT_PSK, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_FT_PSK; - if (_rtw_memcmp(s, WLAN_AKM_8021X_SHA256, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_8021X_SHA256; - if (_rtw_memcmp(s, WLAN_AKM_PSK_SHA256, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_PSK_SHA256; - if (_rtw_memcmp(s, WLAN_AKM_TDLS, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_TDLS; - if (_rtw_memcmp(s, WLAN_AKM_SAE, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_SAE; - if (_rtw_memcmp(s, WLAN_AKM_FT_OVER_SAE, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_FT_OVER_SAE; - if (_rtw_memcmp(s, WLAN_AKM_8021X_SUITE_B, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_8021X_SUITE_B; - if (_rtw_memcmp(s, WLAN_AKM_8021X_SUITE_B_192, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_8021X_SUITE_B_192; - if (_rtw_memcmp(s, WLAN_AKM_FILS_SHA256, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_FILS_SHA256; - if (_rtw_memcmp(s, WLAN_AKM_FILS_SHA384, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_FILS_SHA384; - if (_rtw_memcmp(s, WLAN_AKM_FT_FILS_SHA256, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_FT_FILS_SHA256; - if (_rtw_memcmp(s, WLAN_AKM_FT_FILS_SHA384, RSN_SELECTOR_LEN) == _TRUE) - return WLAN_AKM_TYPE_FT_FILS_SHA384; - - return 0; -} - -int rtw_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher, - int *pairwise_cipher, u32 *akm) -{ - int i, ret = _SUCCESS; - int left, count; - u8 *pos; - u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1}; - - if (wpa_ie_len <= 0) { - /* No WPA IE - fail silently */ - return _FAIL; - } - - - if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) || - (_rtw_memcmp(wpa_ie + 2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN) != _TRUE)) - return _FAIL; - - pos = wpa_ie; - - pos += 8; - left = wpa_ie_len - 8; - - - /* group_cipher */ - if (left >= WPA_SELECTOR_LEN) { - - *group_cipher = rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - - } else if (left > 0) { - - return _FAIL; - } - - - /* pairwise_cipher */ - if (left >= 2) { - /* count = le16_to_cpu(*(u16*)pos); */ - count = RTW_GET_LE16(pos); - pos += 2; - left -= 2; - - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - return _FAIL; - } - - for (i = 0; i < count; i++) { - *pairwise_cipher |= rtw_get_wpa_cipher_suite(pos); - - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - - } else if (left == 1) { - return _FAIL; - } - - if (akm) { - if (left >= 6) { - pos += 2; - if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) { - *akm = WLAN_AKM_TYPE_8021X; - } - } - } - - return ret; - -} - -int rtw_rsne_info_parse(const u8 *ie, uint ie_len, struct rsne_info *info) -{ - const u8 *pos = ie; - u16 cnt; - - _rtw_memset(info, 0, sizeof(struct rsne_info)); - - if (ie + ie_len < pos + 4) - goto err; - - if (*ie != WLAN_EID_RSN || *(ie + 1) != ie_len - 2) - goto err; - pos += 2 + 2; - - /* Group CS */ - if (ie + ie_len < pos + 4) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - info->gcs = (u8 *)pos; - pos += 4; - - /* Pairwise CS */ - if (ie + ie_len < pos + 2) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - cnt = RTW_GET_LE16(pos); - pos += 2; - if (ie + ie_len < pos + 4 * cnt) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - info->pcs_cnt = cnt; - info->pcs_list = (u8 *)pos; - pos += 4 * cnt; - - /* AKM */ - if (ie + ie_len < pos + 2) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - cnt = RTW_GET_LE16(pos); - pos += 2; - if (ie + ie_len < pos + 4 * cnt) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - info->akm_cnt = cnt; - info->akm_list = (u8 *)pos; - pos += 4 * cnt; - - /* RSN cap */ - if (ie + ie_len < pos + 2) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - info->cap = (u8 *)pos; - pos += 2; - - /* PMKID */ - if (ie + ie_len < pos + 2) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - cnt = RTW_GET_LE16(pos); - pos += 2; - if (ie + ie_len < pos + 16 * cnt) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - info->pmkid_cnt = cnt; - info->pmkid_list = (u8 *)pos; - pos += 16 * cnt; - - /* Group Mgmt CS */ - if (ie + ie_len < pos + 4) { - if (ie + ie_len != pos) - goto err; - goto exit; - } - info->gmcs = (u8 *)pos; - -exit: - return _SUCCESS; - -err: - info->err = 1; - return _FAIL; -} - -int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, - int *pairwise_cipher, u32 *akm, u8 *mfp_opt) -{ - struct rsne_info info; - int i, ret = _SUCCESS; - - ret = rtw_rsne_info_parse(rsn_ie, rsn_ie_len, &info); - if (ret != _SUCCESS) - goto exit; - - if (group_cipher) { - if (info.gcs) - *group_cipher = rtw_get_wpa2_cipher_suite(info.gcs); - else - *group_cipher = 0; - } - - if (pairwise_cipher) { - *pairwise_cipher = 0; - for (i = 0; i < info.pcs_cnt; i++) - *pairwise_cipher |= rtw_get_wpa2_cipher_suite(info.pcs_list + 4 * i); - } - - if (akm) { - *akm = 0; - for (i = 0; i < info.akm_cnt; i++) - *akm |= rtw_get_akm_suite_bitmap(info.akm_list + 4 * i); - } - - if (mfp_opt) { - *mfp_opt = MFP_NO; - if (info.cap) - *mfp_opt = GET_RSN_CAP_MFP_OPTION(info.cap); - } - -exit: - return ret; -} - -/* #ifdef CONFIG_WAPI_SUPPORT */ -int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len) -{ - int len = 0; - u8 authmode; - uint cnt; - u8 wapi_oui1[4] = {0x0, 0x14, 0x72, 0x01}; - u8 wapi_oui2[4] = {0x0, 0x14, 0x72, 0x02}; - - - if (wapi_len) - *wapi_len = 0; - - if (!in_ie || in_len <= 0) - return len; - - cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_); - - while (cnt < in_len) { - authmode = in_ie[cnt]; - - /* if(authmode==_WAPI_IE_) */ - if (authmode == _WAPI_IE_ && (_rtw_memcmp(&in_ie[cnt + 6], wapi_oui1, 4) == _TRUE || - _rtw_memcmp(&in_ie[cnt + 6], wapi_oui2, 4) == _TRUE)) { - if (wapi_ie) - _rtw_memcpy(wapi_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (wapi_len) - *wapi_len = in_ie[cnt + 1] + 2; - - cnt += in_ie[cnt + 1] + 2; /* get next */ - } else { - cnt += in_ie[cnt + 1] + 2; /* get next */ - } - } - - if (wapi_len) - len = *wapi_len; - - - return len; - -} -/* #endif */ - -int rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len) -{ - u8 authmode, sec_idx; - u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01}; - uint cnt; - - - /* Search required WPA or WPA2 IE and copy to sec_ie[ ] */ - - cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_); - - sec_idx = 0; - - while (cnt < in_len) { - authmode = in_ie[cnt]; - - if ((authmode == _WPA_IE_ID_) && (_rtw_memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4) == _TRUE)) { - - if (wpa_ie) - _rtw_memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - *wpa_len = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; /* get next */ - } else { - if (authmode == _WPA2_IE_ID_) { - - if (rsn_ie) - _rtw_memcpy(rsn_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - *rsn_len = in_ie[cnt + 1] + 2; - cnt += in_ie[cnt + 1] + 2; /* get next */ - } else { - cnt += in_ie[cnt + 1] + 2; /* get next */ - } - } - - } - - - return *rsn_len + *wpa_len; - -} - -u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen) -{ - u8 match = _FALSE; - u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04}; - - if (ie_ptr == NULL) - return match; - - eid = ie_ptr[0]; - - if ((eid == _WPA_IE_ID_) && (_rtw_memcmp(&ie_ptr[2], wps_oui, 4) == _TRUE)) { - /* RTW_INFO("==> found WPS_IE.....\n"); */ - *wps_ielen = ie_ptr[1] + 2; - match = _TRUE; - } - return match; -} - -u8 *rtw_get_wps_ie_from_scan_queue(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen, enum bss_type frame_type) -{ - u8 *wps = NULL; - - RTW_INFO("[%s] frame_type = %d\n", __FUNCTION__, frame_type); - switch (frame_type) { - case BSS_TYPE_BCN: - case BSS_TYPE_PROB_RSP: { - /* 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 BSS_TYPE_PROB_REQ: { - /* Probe Request */ - wps = rtw_get_wps_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , wps_ie, wps_ielen); - break; - } - default: - case BSS_TYPE_UNDEF: - break; - } - return wps; -} - -/** - * rtw_get_wps_ie - Search WPS IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie - * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE - * - * Returns: The address of the WPS IE found, or NULL - */ -u8 *rtw_get_wps_ie(const u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen) -{ - uint cnt; - const u8 *wpsie_ptr = NULL; - u8 eid, wps_oui[4] = {0x00, 0x50, 0xf2, 0x04}; - - if (wps_ielen) - *wps_ielen = 0; - - if (!in_ie) { - rtw_warn_on(1); - return (u8 *)wpsie_ptr; - } - - if (in_len <= 0) - return (u8 *)wpsie_ptr; - - cnt = 0; - - while (cnt + 1 + 4 < in_len) { - eid = in_ie[cnt]; - - if (cnt + 1 + 4 >= MAX_IE_SZ) { - rtw_warn_on(1); - return NULL; - } - - if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], wps_oui, 4) == _TRUE) { - wpsie_ptr = in_ie + cnt; - - if (wps_ie) - _rtw_memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (wps_ielen) - *wps_ielen = in_ie[cnt + 1] + 2; - - break; - } else - cnt += in_ie[cnt + 1] + 2; - - } - - return (u8 *)wpsie_ptr; -} - -/** - * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id , u8 *buf_attr, u32 *len_attr) -{ - u8 *attr_ptr = NULL; - u8 *target_attr_ptr = NULL; - u8 wps_oui[4] = {0x00, 0x50, 0xF2, 0x04}; - - if (len_attr) - *len_attr = 0; - - if ((wps_ie[0] != _VENDOR_SPECIFIC_IE_) || - (_rtw_memcmp(wps_ie + 2, wps_oui , 4) != _TRUE)) - return attr_ptr; - - /* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */ - attr_ptr = wps_ie + 6; /* goto first attr */ - - while (attr_ptr - wps_ie < wps_ielen) { - /* 4 = 2(Attribute ID) + 2(Length) */ - u16 attr_id = RTW_GET_BE16(attr_ptr); - u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2); - u16 attr_len = attr_data_len + 4; - - /* RTW_INFO("%s attr_ptr:%p, id:%u, length:%u\n", __FUNCTION__, attr_ptr, attr_id, attr_data_len); */ - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - - if (buf_attr) - _rtw_memcpy(buf_attr, attr_ptr, attr_len); - - if (len_attr) - *len_attr = attr_len; - - break; - } else { - attr_ptr += attr_len; /* goto next */ - } - - } - - return target_attr_ptr; -} - -/** - * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE - * @wps_ie: Address of WPS IE to search - * @wps_ielen: Length limit from wps_ie - * @target_attr_id: The attribute ID of WPS attribute to search - * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content - * - * Returns: the address of the specific WPS attribute content found, or NULL - */ -u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id , u8 *buf_content, uint *len_content) -{ - u8 *attr_ptr; - u32 attr_len; - - if (len_content) - *len_content = 0; - - attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - _rtw_memcpy(buf_content, attr_ptr + 4, attr_len - 4); - - if (len_content) - *len_content = attr_len - 4; - - return attr_ptr + 4; - } - - return NULL; -} - -static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, - struct rtw_ieee802_11_elems *elems, - int show_errors) -{ - unsigned int oui; - - /* first 3 bytes in vendor specific information element are the IEEE - * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ - if (elen < 4) { - if (show_errors) { - RTW_INFO("short vendor specific " - "information element ignored (len=%lu)\n", - (unsigned long) elen); - } - return -1; - } - - oui = RTW_GET_BE24(pos); - switch (oui) { - case OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ - switch (pos[3]) { - case 1: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ - elems->wpa_ie = pos; - elems->wpa_ie_len = elen; - break; - case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */ - if (elen < 5) { - RTW_DBG("short WME " - "information element ignored " - "(len=%lu)\n", - (unsigned long) elen); - return -1; - } - switch (pos[4]) { - case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: - elems->wme = pos; - elems->wme_len = elen; - break; - case WME_OUI_SUBTYPE_TSPEC_ELEMENT: - elems->wme_tspec = pos; - elems->wme_tspec_len = elen; - break; - default: - RTW_DBG("unknown WME " - "information element ignored " - "(subtype=%d len=%lu)\n", - pos[4], (unsigned long) elen); - return -1; - } - break; - case 4: - /* Wi-Fi Protected Setup (WPS) IE */ - elems->wps_ie = pos; - elems->wps_ie_len = elen; - break; - default: - RTW_DBG("Unknown Microsoft " - "information element ignored " - "(type=%d len=%lu)\n", - pos[3], (unsigned long) elen); - return -1; - } - break; - - case OUI_BROADCOM: - switch (pos[3]) { - case VENDOR_HT_CAPAB_OUI_TYPE: - elems->vendor_ht_cap = pos; - elems->vendor_ht_cap_len = elen; - break; - default: - RTW_DBG("Unknown Broadcom " - "information element ignored " - "(type=%d len=%lu)\n", - pos[3], (unsigned long) elen); - return -1; - } - break; - - default: - RTW_DBG("unknown vendor specific information " - "element ignored (vendor OUI %02x:%02x:%02x " - "len=%lu)\n", - pos[0], pos[1], pos[2], (unsigned long) elen); - return -1; - } - - return 0; - -} - -/** - * ieee802_11_parse_elems - Parse information elements in management frames - * @start: Pointer to the start of IEs - * @len: Length of IE buffer in octets - * @elems: Data structure for parsed elements - * @show_errors: Whether to show parsing errors in debug log - * Returns: Parsing result - */ -ParseRes rtw_ieee802_11_parse_elems(u8 *start, uint len, - struct rtw_ieee802_11_elems *elems, - int show_errors) -{ - uint left = len; - u8 *pos = start; - int unknown = 0; - - _rtw_memset(elems, 0, sizeof(*elems)); - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - if (show_errors) { - RTW_INFO("IEEE 802.11 element " - "parse failed (id=%d elen=%d " - "left=%lu)\n", - id, elen, (unsigned long) left); - } - return ParseFailed; - } - - switch (id) { - case WLAN_EID_SSID: - elems->ssid = pos; - elems->ssid_len = elen; - break; - case WLAN_EID_SUPP_RATES: - elems->supp_rates = pos; - elems->supp_rates_len = elen; - break; - case WLAN_EID_FH_PARAMS: - elems->fh_params = pos; - elems->fh_params_len = elen; - break; - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_CF_PARAMS: - elems->cf_params = pos; - elems->cf_params_len = elen; - break; - case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_CHALLENGE: - elems->challenge = pos; - elems->challenge_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_EXT_SUPP_RATES: - elems->ext_supp_rates = pos; - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_VENDOR_SPECIFIC: - if (rtw_ieee802_11_parse_vendor_specific(pos, elen, - elems, - show_errors)) - unknown++; - break; - case WLAN_EID_RSN: - elems->rsn_ie = pos; - elems->rsn_ie_len = elen; - break; - case WLAN_EID_PWR_CAPABILITY: - elems->power_cap = pos; - elems->power_cap_len = elen; - break; - case WLAN_EID_SUPPORTED_CHANNELS: - elems->supp_channels = pos; - elems->supp_channels_len = elen; - break; - case WLAN_EID_MOBILITY_DOMAIN: - elems->mdie = pos; - elems->mdie_len = elen; - break; - case WLAN_EID_FAST_BSS_TRANSITION: - elems->ftie = pos; - elems->ftie_len = elen; - break; - case WLAN_EID_TIMEOUT_INTERVAL: - elems->timeout_int = pos; - elems->timeout_int_len = elen; - break; - case WLAN_EID_HT_CAP: - elems->ht_capabilities = pos; - elems->ht_capabilities_len = elen; - break; - case WLAN_EID_HT_OPERATION: - elems->ht_operation = pos; - elems->ht_operation_len = elen; - break; - case WLAN_EID_VHT_CAPABILITY: - elems->vht_capabilities = pos; - elems->vht_capabilities_len = elen; - break; - case WLAN_EID_VHT_OPERATION: - elems->vht_operation = pos; - elems->vht_operation_len = elen; - break; - case WLAN_EID_VHT_OP_MODE_NOTIFY: - elems->vht_op_mode_notify = pos; - elems->vht_op_mode_notify_len = elen; - break; - case _EID_RRM_EN_CAP_IE_: - elems->rm_en_cap = pos; - elems->rm_en_cap_len = elen; - break; -#ifdef CONFIG_RTW_MESH - case WLAN_EID_PREQ: - elems->preq = pos; - elems->preq_len = elen; - break; - case WLAN_EID_PREP: - elems->prep = pos; - elems->prep_len = elen; - break; - case WLAN_EID_PERR: - elems->perr = pos; - elems->perr_len = elen; - break; - case WLAN_EID_RANN: - elems->rann = pos; - elems->rann_len = elen; - break; -#endif - default: - unknown++; - if (!show_errors) - break; - RTW_DBG("IEEE 802.11 element parse " - "ignored unknown element (id=%d elen=%d)\n", - id, elen); - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return ParseFailed; - - return unknown ? ParseUnknown : ParseOK; - -} - -static u8 key_char2num(u8 ch); -static u8 key_char2num(u8 ch) -{ - if ((ch >= '0') && (ch <= '9')) - return ch - '0'; - else if ((ch >= 'a') && (ch <= 'f')) - return ch - 'a' + 10; - else if ((ch >= 'A') && (ch <= 'F')) - return ch - 'A' + 10; - else - return 0xff; -} - -u8 str_2char2num(u8 hch, u8 lch); -u8 str_2char2num(u8 hch, u8 lch) -{ - return (key_char2num(hch) * 10) + key_char2num(lch); -} - -u8 key_2char2num(u8 hch, u8 lch); -u8 key_2char2num(u8 hch, u8 lch) -{ - return (key_char2num(hch) << 4) | key_char2num(lch); -} - -void macstr2num(u8 *dst, u8 *src); -void macstr2num(u8 *dst, u8 *src) -{ - int jj, kk; - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - dst[jj] = key_2char2num(src[kk], src[kk + 1]); -} - -u8 convert_ip_addr(u8 hch, u8 mch, u8 lch) -{ - return (key_char2num(hch) * 100) + (key_char2num(mch) * 10) + key_char2num(lch); -} - -#ifdef CONFIG_PLATFORM_INTEL_BYT -#define MAC_ADDRESS_LEN 12 - -int rtw_get_mac_addr_intel(unsigned char *buf) -{ - int ret = 0; - int i; - struct file *fp = NULL; - mm_segment_t oldfs; - unsigned char c_mac[MAC_ADDRESS_LEN]; - char fname[] = "/config/wifi/mac.txt"; - int jj, kk; - - RTW_INFO("%s Enter\n", __FUNCTION__); - - ret = rtw_retrieve_from_file(fname, c_mac, MAC_ADDRESS_LEN); - if (ret < MAC_ADDRESS_LEN) - return -1; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 2) - buf[jj] = key_2char2num(c_mac[kk], c_mac[kk + 1]); - - RTW_INFO("%s: read from file mac address: "MAC_FMT"\n", - __FUNCTION__, MAC_ARG(buf)); - - return 0; -} -#endif /* CONFIG_PLATFORM_INTEL_BYT */ - -/* - * Description: - * rtw_check_invalid_mac_address: - * This is only used for checking mac address valid or not. - * - * Input: - * adapter: mac_address pointer. - * check_local_bit: check locally bit or not. - * - * Output: - * _TRUE: The mac address is invalid. - * _FALSE: The mac address is valid. - * - * Auther: Isaac.Li - */ -u8 rtw_check_invalid_mac_address(u8 *mac_addr, u8 check_local_bit) -{ - u8 null_mac_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - u8 multi_mac_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 res = _FALSE; - - if (_rtw_memcmp(mac_addr, null_mac_addr, ETH_ALEN)) { - res = _TRUE; - goto func_exit; - } - - if (_rtw_memcmp(mac_addr, multi_mac_addr, ETH_ALEN)) { - res = _TRUE; - goto func_exit; - } - - if (mac_addr[0] & BIT0) { - res = _TRUE; - goto func_exit; - } - - if (check_local_bit == _TRUE) { - if (mac_addr[0] & BIT1) { - res = _TRUE; - goto func_exit; - } - } - -func_exit: - return res; -} - -extern char *rtw_initmac; -/** - * rtw_macaddr_cfg - Decide the mac address used - * @out: buf to store mac address decided - * @hw_mac_addr: mac address from efuse/epprom - */ -void rtw_macaddr_cfg(u8 *out, const u8 *hw_mac_addr) -{ -#define DEFAULT_RANDOM_MACADDR 1 - u8 mac[ETH_ALEN]; - - if (out == NULL) { - rtw_warn_on(1); - return; - } - - /* Users specify the mac address */ - if (rtw_initmac) { - int jj, kk; - - for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) - mac[jj] = key_2char2num(rtw_initmac[kk], rtw_initmac[kk + 1]); - - goto err_chk; - } - - /* platform specified */ -#ifdef CONFIG_PLATFORM_INTEL_BYT - if (rtw_get_mac_addr_intel(mac) == 0) - goto err_chk; -#endif - - /* Use the mac address stored in the Efuse */ - if (hw_mac_addr) { - _rtw_memcpy(mac, hw_mac_addr, ETH_ALEN); - goto err_chk; - } - -err_chk: - if (rtw_check_invalid_mac_address(mac, _TRUE) == _TRUE) { -#if DEFAULT_RANDOM_MACADDR - RTW_ERR("invalid mac addr:"MAC_FMT", assign random MAC\n", MAC_ARG(mac)); - *((u32 *)(&mac[2])) = rtw_random32(); - mac[0] = 0x00; - mac[1] = 0xe0; - mac[2] = 0x4c; -#else - RTW_ERR("invalid mac addr:"MAC_FMT", assign default one\n", MAC_ARG(mac)); - mac[0] = 0x00; - mac[1] = 0xe0; - mac[2] = 0x4c; - mac[3] = 0x87; - mac[4] = 0x00; - mac[5] = 0x00; -#endif - } - - _rtw_memcpy(out, mac, ETH_ALEN); - RTW_INFO("%s mac addr:"MAC_FMT"\n", __func__, MAC_ARG(out)); -} - -#ifdef CONFIG_80211N_HT -void dump_ht_cap_ie_content(void *sel, const u8 *buf, u32 buf_len) -{ - if (buf_len != HT_CAP_IE_LEN) { - RTW_PRINT_SEL(sel, "Invalid HT capability IE len:%d != %d\n", buf_len, HT_CAP_IE_LEN); - return; - } - - RTW_PRINT_SEL(sel, "cap_info:%02x%02x:%s\n", *(buf), *(buf + 1) - , GET_HT_CAP_ELE_CHL_WIDTH(buf) ? " 40MHz" : " 20MHz"); - RTW_PRINT_SEL(sel, "A-MPDU Parameters:"HT_AMPDU_PARA_FMT"\n" - , HT_AMPDU_PARA_ARG(HT_CAP_ELE_AMPDU_PARA(buf))); - RTW_PRINT_SEL(sel, "Supported MCS Set:"HT_SUP_MCS_SET_FMT"\n" - , HT_SUP_MCS_SET_ARG(HT_CAP_ELE_SUP_MCS_SET(buf))); -} - -void dump_ht_cap_ie(void *sel, const u8 *ie, u32 ie_len) -{ - const u8 *ht_cap_ie; - sint ht_cap_ielen; - - ht_cap_ie = rtw_get_ie(ie, WLAN_EID_HT_CAP, &ht_cap_ielen, ie_len); - if (!ie || ht_cap_ie != ie) - return; - - dump_ht_cap_ie_content(sel, ht_cap_ie + 2, ht_cap_ielen); -} - -const char *const _ht_sc_offset_str[] = { - "SCN", - "SCA", - "SC-RSVD", - "SCB", -}; - -void dump_ht_op_ie_content(void *sel, const u8 *buf, u32 buf_len) -{ - if (buf_len != HT_OP_IE_LEN) { - RTW_PRINT_SEL(sel, "Invalid HT operation IE len:%d != %d\n", buf_len, HT_OP_IE_LEN); - return; - } - - RTW_PRINT_SEL(sel, "ch:%u%s %s\n" - , GET_HT_OP_ELE_PRI_CHL(buf) - , GET_HT_OP_ELE_STA_CHL_WIDTH(buf) ? "" : " 20MHz only" - , ht_sc_offset_str(GET_HT_OP_ELE_2ND_CHL_OFFSET(buf)) - ); -} - -void dump_ht_op_ie(void *sel, const u8 *ie, u32 ie_len) -{ - const u8 *ht_op_ie; - sint ht_op_ielen; - - ht_op_ie = rtw_get_ie(ie, WLAN_EID_HT_OPERATION, &ht_op_ielen, ie_len); - if (!ie || ht_op_ie != ie) - return; - - dump_ht_op_ie_content(sel, ht_op_ie + 2, ht_op_ielen); -} -#endif /* CONFIG_80211N_HT */ - -void dump_ies(void *sel, const u8 *buf, u32 buf_len) -{ - const u8 *pos = buf; - u8 id, len; - - while (pos - buf + 1 < buf_len) { - id = *pos; - len = *(pos + 1); - - RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u\n", __FUNCTION__, id, len); -#ifdef CONFIG_80211N_HT - dump_ht_cap_ie(sel, pos, len + 2); - dump_ht_op_ie(sel, pos, len + 2); -#endif -#ifdef CONFIG_80211AC_VHT - dump_vht_cap_ie(sel, pos, len + 2); - dump_vht_op_ie(sel, pos, len + 2); -#endif - dump_wps_ie(sel, pos, len + 2); -#ifdef CONFIG_P2P - dump_p2p_ie(sel, pos, len + 2); -#ifdef CONFIG_WFD - dump_wfd_ie(sel, pos, len + 2); -#endif -#endif - - pos += (2 + len); - } -} - -void dump_wps_ie(void *sel, const u8 *ie, u32 ie_len) -{ - const u8 *pos = ie; - u16 id; - u16 len; - - const 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; - - pos += 6; - while (pos - ie + 4 <= ie_len) { - id = RTW_GET_BE16(pos); - len = RTW_GET_BE16(pos + 2); - - RTW_PRINT_SEL(sel, "%s ID:0x%04x, LEN:%u%s\n", __func__, id, len - , ((pos - ie + 4 + len) <= ie_len) ? "" : "(exceed ie_len)"); - - pos += (4 + len); - } -} - -/** - * rtw_ies_get_chbw - get operation ch, bw, offset from IEs of BSS. - * @ies: pointer of the first tlv IE - * @ies_len: length of @ies - * @ch: pointer of ch, used as output - * @bw: pointer of bw, used as output - * @offset: pointer of offset, used as output - * @ht: check HT IEs - * @vht: check VHT IEs, if true imply ht is true - */ -void rtw_ies_get_chbw(u8 *ies, int ies_len, u8 *ch, u8 *bw, u8 *offset, u8 ht, u8 vht) -{ - u8 *p; - int ie_len; - - *ch = 0; - *bw = CHANNEL_WIDTH_20; - *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - p = rtw_get_ie(ies, _DSSET_IE_, &ie_len, ies_len); - if (p && ie_len > 0) - *ch = *(p + 2); - -#ifdef CONFIG_80211N_HT - if (ht || vht) { - u8 *ht_cap_ie, *ht_op_ie; - int ht_cap_ielen, ht_op_ielen; - - ht_cap_ie = rtw_get_ie(ies, EID_HTCapability, &ht_cap_ielen, ies_len); - if (ht_cap_ie && ht_cap_ielen) { - if (GET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2)) - *bw = CHANNEL_WIDTH_40; - } - - ht_op_ie = rtw_get_ie(ies, EID_HTInfo, &ht_op_ielen, ies_len); - if (ht_op_ie && ht_op_ielen) { - if (*ch == 0) - *ch = GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2); - else if (*ch != 0 && *ch != GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2)) { - RTW_INFO("%s ch inconsistent, DSSS:%u, HT primary:%u\n" - , __func__, *ch, GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2)); - } - - if (!GET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2)) - *bw = CHANNEL_WIDTH_20; - - if (*bw == CHANNEL_WIDTH_40) { - switch (GET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2)) { - case SCA: - *offset = HAL_PRIME_CHNL_OFFSET_LOWER; - break; - case SCB: - *offset = HAL_PRIME_CHNL_OFFSET_UPPER; - break; - } - } - } - -#ifdef CONFIG_80211AC_VHT - if (vht) { - u8 *vht_op_ie; - int vht_op_ielen; - - vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &vht_op_ielen, ies_len); - if (vht_op_ie && vht_op_ielen) { - if (GET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2) >= 1) - *bw = CHANNEL_WIDTH_80; - } - } -#endif /* CONFIG_80211AC_VHT */ - - } -#endif /* CONFIG_80211N_HT */ -} - -void rtw_bss_get_chbw(WLAN_BSSID_EX *bss, u8 *ch, u8 *bw, u8 *offset, u8 ht, u8 vht) -{ - rtw_ies_get_chbw(bss->IEs + sizeof(NDIS_802_11_FIXED_IEs) - , bss->IELength - sizeof(NDIS_802_11_FIXED_IEs) - , ch, bw, offset, ht, vht); - - if (*ch == 0) - *ch = bss->Configuration.DSConfig; - else if (*ch != bss->Configuration.DSConfig) { - RTW_INFO("inconsistent ch - ies:%u bss->Configuration.DSConfig:%u\n" - , *ch, bss->Configuration.DSConfig); - *ch = bss->Configuration.DSConfig; - rtw_warn_on(1); - } -} - -/** - * rtw_is_chbw_grouped - test if the two ch settings can be grouped together - * @ch_a: ch of set a - * @bw_a: bw of set a - * @offset_a: offset of set a - * @ch_b: ch of set b - * @bw_b: bw of set b - * @offset_b: offset of set b - */ -bool rtw_is_chbw_grouped(u8 ch_a, u8 bw_a, u8 offset_a - , u8 ch_b, u8 bw_b, u8 offset_b) -{ - bool is_grouped = _FALSE; - - if (ch_a != ch_b) { - /* ch is different */ - goto exit; - } else if ((bw_a == CHANNEL_WIDTH_40 || bw_a == CHANNEL_WIDTH_80) - && (bw_b == CHANNEL_WIDTH_40 || bw_b == CHANNEL_WIDTH_80) - ) { - if (offset_a != offset_b) - goto exit; - } - - is_grouped = _TRUE; - -exit: - return is_grouped; -} - -/** - * rtw_sync_chbw - obey g_ch, adjust g_bw, g_offset, bw, offset - * @req_ch: pointer of the request ch, may be modified further - * @req_bw: pointer of the request bw, may be modified further - * @req_offset: pointer of the request offset, may be modified further - * @g_ch: pointer of the ongoing group ch - * @g_bw: pointer of the ongoing group bw, may be modified further - * @g_offset: pointer of the ongoing group offset, may be modified further - */ -void rtw_sync_chbw(u8 *req_ch, u8 *req_bw, u8 *req_offset - , u8 *g_ch, u8 *g_bw, u8 *g_offset) -{ - - *req_ch = *g_ch; - - if (*req_bw == CHANNEL_WIDTH_80 && *g_ch <= 14) { - /*2.4G ch, downgrade to 40Mhz */ - *req_bw = CHANNEL_WIDTH_40; - } - - switch (*req_bw) { - case CHANNEL_WIDTH_80: - if (*g_bw == CHANNEL_WIDTH_40 || *g_bw == CHANNEL_WIDTH_80) - *req_offset = *g_offset; - else if (*g_bw == CHANNEL_WIDTH_20) - rtw_get_offset_by_chbw(*req_ch, *req_bw, req_offset); - - if (*req_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) { - RTW_ERR("%s req 80MHz BW without offset, down to 20MHz\n", __func__); - rtw_warn_on(1); - *req_bw = CHANNEL_WIDTH_20; - } - break; - case CHANNEL_WIDTH_40: - if (*g_bw == CHANNEL_WIDTH_40 || *g_bw == CHANNEL_WIDTH_80) - *req_offset = *g_offset; - else if (*g_bw == CHANNEL_WIDTH_20) - rtw_get_offset_by_chbw(*req_ch, *req_bw, req_offset); - - if (*req_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) { - RTW_ERR("%s req 40MHz BW without offset, down to 20MHz\n", __func__); - rtw_warn_on(1); - *req_bw = CHANNEL_WIDTH_20; - } - break; - case CHANNEL_WIDTH_20: - *req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - break; - default: - RTW_ERR("%s req unsupported BW:%u\n", __func__, *req_bw); - rtw_warn_on(1); - } - - if (*req_bw > *g_bw) { - *g_bw = *req_bw; - *g_offset = *req_offset; - } -} - -/** - * 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 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(void *sel, const u8 *ie, u32 ie_len) -{ - const u8 *pos = ie; - u8 id; - u16 len; - - const u8 *p2p_ie; - uint p2p_ielen; - - p2p_ie = rtw_get_p2p_ie(ie, ie_len, NULL, &p2p_ielen); - if (p2p_ie != ie || p2p_ielen == 0) - return; - - pos += 6; - while (pos - ie + 3 <= ie_len) { - id = *pos; - len = RTW_GET_LE16(pos + 1); - - RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u%s\n", __func__, id, len - , ((pos - ie + 3 + len) <= ie_len) ? "" : "(exceed ie_len)"); - - pos += (3 + len); - } -} - -/** - * rtw_get_p2p_ie - Search P2P IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie - * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE - * - * Returns: The address of the P2P IE found, or NULL - */ -u8 *rtw_get_p2p_ie(const u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen) -{ - uint cnt; - const u8 *p2p_ie_ptr = NULL; - u8 eid, p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09}; - - if (p2p_ielen) - *p2p_ielen = 0; - - if (!in_ie || in_len < 0) { - rtw_warn_on(1); - return (u8 *)p2p_ie_ptr; - } - - if (in_len <= 0) - return (u8 *)p2p_ie_ptr; - - cnt = 0; - - while (cnt + 1 + 4 < in_len) { - eid = in_ie[cnt]; - - if (cnt + 1 + 4 >= MAX_IE_SZ) { - rtw_warn_on(1); - return NULL; - } - - if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], p2p_oui, 4) == _TRUE) { - p2p_ie_ptr = in_ie + cnt; - - if (p2p_ie) - _rtw_memcpy(p2p_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (p2p_ielen) - *p2p_ielen = in_ie[cnt + 1] + 2; - - break; - } else - cnt += in_ie[cnt + 1] + 2; - - } - - return (u8 *)p2p_ie_ptr; -} - -/** - * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE - * @p2p_ie: Address of P2P IE to search - * @p2p_ielen: Length limit from p2p_ie - * @target_attr_id: The attribute ID of P2P attribute to search - * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id , u8 *buf_attr, u32 *len_attr) -{ - u8 *attr_ptr = NULL; - u8 *target_attr_ptr = NULL; - u8 p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09}; - - if (len_attr) - *len_attr = 0; - - if (!p2p_ie - || p2p_ielen <= 6 - || (p2p_ie[0] != WLAN_EID_VENDOR_SPECIFIC) - || (_rtw_memcmp(p2p_ie + 2, p2p_oui, 4) != _TRUE)) - return attr_ptr; - - /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */ - attr_ptr = p2p_ie + 6; /* goto first attr */ - - while ((attr_ptr - p2p_ie + 3) <= p2p_ielen) { - /* 3 = 1(Attribute ID) + 2(Length) */ - u8 attr_id = *attr_ptr; - u16 attr_data_len = RTW_GET_LE16(attr_ptr + 1); - u16 attr_len = attr_data_len + 3; - - if (0) - RTW_INFO("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); - - if ((attr_ptr - p2p_ie + attr_len) > p2p_ielen) - break; - - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - - if (buf_attr) - _rtw_memcpy(buf_attr, attr_ptr, attr_len); - - if (len_attr) - *len_attr = attr_len; - - break; - } else - attr_ptr += attr_len; - } - - return target_attr_ptr; -} - -/** - * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE - * @p2p_ie: Address of P2P IE to search - * @p2p_ielen: Length limit from p2p_ie - * @target_attr_id: The attribute ID of P2P attribute to search - * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content - * - * Returns: the address of the specific P2P attribute content found, or NULL - */ -u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id , u8 *buf_content, uint *len_content) -{ - u8 *attr_ptr; - u32 attr_len; - - if (len_content) - *len_content = 0; - - attr_ptr = rtw_get_p2p_attr(p2p_ie, p2p_ielen, target_attr_id, NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - _rtw_memcpy(buf_content, attr_ptr + 3, attr_len - 3); - - if (len_content) - *len_content = attr_len - 3; - - return attr_ptr + 3; - } - - return NULL; -} - -u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr) -{ - u32 a_len; - - *pbuf = attr_id; - - /* *(u16*)(pbuf + 1) = cpu_to_le16(attr_len); */ - RTW_PUT_LE16(pbuf + 1, attr_len); - - if (pdata_attr) - _rtw_memcpy(pbuf + 3, pdata_attr, attr_len); - - a_len = attr_len + 3; - - return a_len; -} - -uint rtw_del_p2p_ie(u8 *ies, uint ies_len_ori, const char *msg) -{ -#define DBG_DEL_P2P_IE 0 - - u8 *target_ie; - u32 target_ie_len; - uint ies_len = ies_len_ori; - int index = 0; - - while (1) { - target_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &target_ie_len); - if (target_ie && target_ie_len) { - u8 *next_ie = target_ie + target_ie_len; - uint remain_len = ies_len - (next_ie - ies); - - if (DBG_DEL_P2P_IE && msg) { - RTW_INFO("%s %d before\n", __func__, index); - dump_ies(RTW_DBGDUMP, ies, ies_len); - - RTW_INFO("ies:%p, ies_len:%u\n", ies, ies_len); - RTW_INFO("target_ie:%p, target_ie_len:%u\n", target_ie, target_ie_len); - RTW_INFO("next_ie:%p, remain_len:%u\n", next_ie, remain_len); - } - - _rtw_memmove(target_ie, next_ie, remain_len); - _rtw_memset(target_ie + remain_len, 0, target_ie_len); - ies_len -= target_ie_len; - - if (DBG_DEL_P2P_IE && msg) { - RTW_INFO("%s %d after\n", __func__, index); - dump_ies(RTW_DBGDUMP, ies, ies_len); - } - - index++; - } else - break; - } - - return ies_len; -} - -uint rtw_del_p2p_attr(u8 *ie, uint ielen_ori, u8 attr_id) -{ -#define DBG_DEL_P2P_ATTR 0 - - u8 *target_attr; - u32 target_attr_len; - uint ielen = ielen_ori; - int index = 0; - - while (1) { - target_attr = rtw_get_p2p_attr(ie, ielen, attr_id, NULL, &target_attr_len); - if (target_attr && target_attr_len) { - u8 *next_attr = target_attr + target_attr_len; - uint remain_len = ielen - (next_attr - ie); - - if (DBG_DEL_P2P_ATTR) { - RTW_INFO("%s %d before\n", __func__, index); - dump_ies(RTW_DBGDUMP, ie, ielen); - - RTW_INFO("ie:%p, ielen:%u\n", ie, ielen); - RTW_INFO("target_attr:%p, target_attr_len:%u\n", target_attr, target_attr_len); - RTW_INFO("next_attr:%p, remain_len:%u\n", next_attr, remain_len); - } - - _rtw_memmove(target_attr, next_attr, remain_len); - _rtw_memset(target_attr + remain_len, 0, target_attr_len); - *(ie + 1) -= target_attr_len; - ielen -= target_attr_len; - - if (DBG_DEL_P2P_ATTR) { - RTW_INFO("%s %d after\n", __func__, index); - dump_ies(RTW_DBGDUMP, ie, ielen); - } - - index++; - } else - break; - } - - return ielen; -} - -inline u8 *rtw_bss_ex_get_p2p_ie(WLAN_BSSID_EX *bss_ex, u8 *p2p_ie, uint *p2p_ielen) -{ - return rtw_get_p2p_ie(BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex), p2p_ie, p2p_ielen); -} - -void rtw_bss_ex_del_p2p_ie(WLAN_BSSID_EX *bss_ex) -{ -#define DBG_BSS_EX_DEL_P2P_IE 0 - - u8 *ies = BSS_EX_TLV_IES(bss_ex); - uint ies_len_ori = BSS_EX_TLV_IES_LEN(bss_ex); - uint ies_len; - - ies_len = rtw_del_p2p_ie(ies, ies_len_ori, DBG_BSS_EX_DEL_P2P_IE ? __func__ : NULL); - bss_ex->IELength -= ies_len_ori - ies_len; -} - -void rtw_bss_ex_del_p2p_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id) -{ -#define DBG_BSS_EX_DEL_P2P_ATTR 0 - - u8 *ies = BSS_EX_TLV_IES(bss_ex); - uint ies_len = BSS_EX_TLV_IES_LEN(bss_ex); - - u8 *ie; - uint ie_len, ie_len_ori; - - int index = 0; - - while (1) { - ie = rtw_get_p2p_ie(ies, ies_len, NULL, &ie_len_ori); - if (ie) { - u8 *next_ie_ori = ie + ie_len_ori; - uint remain_len = bss_ex->IELength - (next_ie_ori - bss_ex->IEs); - u8 has_target_attr = 0; - - if (DBG_BSS_EX_DEL_P2P_ATTR) { - if (rtw_get_p2p_attr(ie, ie_len_ori, attr_id, NULL, NULL)) { - RTW_INFO("%s %d before\n", __func__, index); - dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex)); - - RTW_INFO("ies:%p, ies_len:%u\n", ies, ies_len); - RTW_INFO("ie:%p, ie_len_ori:%u\n", ie, ie_len_ori); - RTW_INFO("next_ie_ori:%p, remain_len:%u\n", next_ie_ori, remain_len); - has_target_attr = 1; - } - } - - ie_len = rtw_del_p2p_attr(ie, ie_len_ori, attr_id); - if (ie_len != ie_len_ori) { - u8 *next_ie = ie + ie_len; - - _rtw_memmove(next_ie, next_ie_ori, remain_len); - _rtw_memset(next_ie + remain_len, 0, ie_len_ori - ie_len); - bss_ex->IELength -= ie_len_ori - ie_len; - - ies = next_ie; - } else - ies = next_ie_ori; - - if (DBG_BSS_EX_DEL_P2P_ATTR) { - if (has_target_attr) { - RTW_INFO("%s %d after\n", __func__, index); - dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex)); - } - } - - ies_len = remain_len; - - index++; - } else - break; - } -} - -void dump_wfd_ie(void *sel, const u8 *ie, u32 ie_len) -{ - const u8 *pos = ie; - u8 id; - u16 len; - - const u8 *wfd_ie; - uint wfd_ielen; - - wfd_ie = rtw_get_wfd_ie(ie, ie_len, NULL, &wfd_ielen); - if (wfd_ie != ie || wfd_ielen == 0) - return; - - pos += 6; - while (pos - ie + 3 <= ie_len) { - id = *pos; - len = RTW_GET_BE16(pos + 1); - - RTW_PRINT_SEL(sel, "%s ID:%u, LEN:%u%s\n", __func__, id, len - , ((pos - ie + 3 + len) <= ie_len) ? "" : "(exceed ie_len)"); - - pos += (3 + len); - } -} - -/** - * rtw_get_wfd_ie - Search WFD IE from a series of IEs - * @in_ie: Address of IEs to search - * @in_len: Length limit from in_ie - * @wfd_ie: If not NULL and WFD IE is found, WFD IE will be copied to the buf starting from wfd_ie - * @wfd_ielen: If not NULL and WFD IE is found, will set to the length of the entire WFD IE - * - * Returns: The address of the P2P IE found, or NULL - */ -u8 *rtw_get_wfd_ie(const u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen) -{ - uint cnt; - const u8 *wfd_ie_ptr = NULL; - u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A}; - - if (wfd_ielen) - *wfd_ielen = 0; - - if (!in_ie || in_len < 0) { - rtw_warn_on(1); - return (u8 *)wfd_ie_ptr; - } - - if (in_len <= 0) - return (u8 *)wfd_ie_ptr; - - cnt = 0; - - while (cnt + 1 + 4 < in_len) { - eid = in_ie[cnt]; - - if (cnt + 1 + 4 >= MAX_IE_SZ) { - rtw_warn_on(1); - return NULL; - } - - if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], wfd_oui, 4) == _TRUE) { - wfd_ie_ptr = in_ie + cnt; - - if (wfd_ie) - _rtw_memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - if (wfd_ielen) - *wfd_ielen = in_ie[cnt + 1] + 2; - - break; - } else - cnt += in_ie[cnt + 1] + 2; - - } - - return (u8 *)wfd_ie_ptr; -} - -/** - * rtw_get_wfd_attr - Search a specific WFD attribute from a given WFD IE - * @wfd_ie: Address of WFD IE to search - * @wfd_ielen: Length limit from wfd_ie - * @target_attr_id: The attribute ID of WFD attribute to search - * @buf_attr: If not NULL and the WFD attribute is found, WFD attribute will be copied to the buf starting from buf_attr - * @len_attr: If not NULL and the WFD attribute is found, will set to the length of the entire WFD attribute - * - * Returns: the address of the specific WPS attribute found, or NULL - */ -u8 *rtw_get_wfd_attr(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id, u8 *buf_attr, u32 *len_attr) -{ - u8 *attr_ptr = NULL; - u8 *target_attr_ptr = NULL; - u8 wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A}; - - if (len_attr) - *len_attr = 0; - - if (!wfd_ie - || wfd_ielen <= 6 - || (wfd_ie[0] != WLAN_EID_VENDOR_SPECIFIC) - || (_rtw_memcmp(wfd_ie + 2, wfd_oui, 4) != _TRUE)) - return attr_ptr; - - /* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */ - attr_ptr = wfd_ie + 6; /* goto first attr */ - - while ((attr_ptr - wfd_ie + 3) <= wfd_ielen) { - /* 3 = 1(Attribute ID) + 2(Length) */ - u8 attr_id = *attr_ptr; - u16 attr_data_len = RTW_GET_BE16(attr_ptr + 1); - u16 attr_len = attr_data_len + 3; - - if (0) - RTW_INFO("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len); - - if ((attr_ptr - wfd_ie + attr_len) > wfd_ielen) - break; - - if (attr_id == target_attr_id) { - target_attr_ptr = attr_ptr; - - if (buf_attr) - _rtw_memcpy(buf_attr, attr_ptr, attr_len); - - if (len_attr) - *len_attr = attr_len; - - break; - } else - attr_ptr += attr_len; - } - - return target_attr_ptr; -} - -/** - * rtw_get_wfd_attr_content - Search a specific WFD attribute content from a given WFD IE - * @wfd_ie: Address of WFD IE to search - * @wfd_ielen: Length limit from wfd_ie - * @target_attr_id: The attribute ID of WFD attribute to search - * @buf_content: If not NULL and the WFD attribute is found, WFD attribute content will be copied to the buf starting from buf_content - * @len_content: If not NULL and the WFD attribute is found, will set to the length of the WFD attribute content - * - * Returns: the address of the specific WFD attribute content found, or NULL - */ -u8 *rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id, u8 *buf_content, uint *len_content) -{ - u8 *attr_ptr; - u32 attr_len; - - if (len_content) - *len_content = 0; - - attr_ptr = rtw_get_wfd_attr(wfd_ie, wfd_ielen, target_attr_id, NULL, &attr_len); - - if (attr_ptr && attr_len) { - if (buf_content) - _rtw_memcpy(buf_content, attr_ptr + 3, attr_len - 3); - - if (len_content) - *len_content = attr_len - 3; - - return attr_ptr + 3; - } - - return NULL; -} - -uint rtw_del_wfd_ie(u8 *ies, uint ies_len_ori, const char *msg) -{ -#define DBG_DEL_WFD_IE 0 - - u8 *target_ie; - u32 target_ie_len; - uint ies_len = ies_len_ori; - int index = 0; - - while (1) { - target_ie = rtw_get_wfd_ie(ies, ies_len, NULL, &target_ie_len); - if (target_ie && target_ie_len) { - u8 *next_ie = target_ie + target_ie_len; - uint remain_len = ies_len - (next_ie - ies); - - if (DBG_DEL_WFD_IE && msg) { - RTW_INFO("%s %d before\n", __func__, index); - dump_ies(RTW_DBGDUMP, ies, ies_len); - - RTW_INFO("ies:%p, ies_len:%u\n", ies, ies_len); - RTW_INFO("target_ie:%p, target_ie_len:%u\n", target_ie, target_ie_len); - RTW_INFO("next_ie:%p, remain_len:%u\n", next_ie, remain_len); - } - - _rtw_memmove(target_ie, next_ie, remain_len); - _rtw_memset(target_ie + remain_len, 0, target_ie_len); - ies_len -= target_ie_len; - - if (DBG_DEL_WFD_IE && msg) { - RTW_INFO("%s %d after\n", __func__, index); - dump_ies(RTW_DBGDUMP, ies, ies_len); - } - - index++; - } else - break; - } - - return ies_len; -} - -uint rtw_del_wfd_attr(u8 *ie, uint ielen_ori, u8 attr_id) -{ -#define DBG_DEL_WFD_ATTR 0 - - u8 *target_attr; - u32 target_attr_len; - uint ielen = ielen_ori; - int index = 0; - - while (1) { - target_attr = rtw_get_wfd_attr(ie, ielen, attr_id, NULL, &target_attr_len); - if (target_attr && target_attr_len) { - u8 *next_attr = target_attr + target_attr_len; - uint remain_len = ielen - (next_attr - ie); - - if (DBG_DEL_WFD_ATTR) { - RTW_INFO("%s %d before\n", __func__, index); - dump_ies(RTW_DBGDUMP, ie, ielen); - - RTW_INFO("ie:%p, ielen:%u\n", ie, ielen); - RTW_INFO("target_attr:%p, target_attr_len:%u\n", target_attr, target_attr_len); - RTW_INFO("next_attr:%p, remain_len:%u\n", next_attr, remain_len); - } - - _rtw_memmove(target_attr, next_attr, remain_len); - _rtw_memset(target_attr + remain_len, 0, target_attr_len); - *(ie + 1) -= target_attr_len; - ielen -= target_attr_len; - - if (DBG_DEL_WFD_ATTR) { - RTW_INFO("%s %d after\n", __func__, index); - dump_ies(RTW_DBGDUMP, ie, ielen); - } - - index++; - } else - break; - } - - return ielen; -} - -inline u8 *rtw_bss_ex_get_wfd_ie(WLAN_BSSID_EX *bss_ex, u8 *wfd_ie, uint *wfd_ielen) -{ - return rtw_get_wfd_ie(BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex), wfd_ie, wfd_ielen); -} - -void rtw_bss_ex_del_wfd_ie(WLAN_BSSID_EX *bss_ex) -{ -#define DBG_BSS_EX_DEL_WFD_IE 0 - u8 *ies = BSS_EX_TLV_IES(bss_ex); - uint ies_len_ori = BSS_EX_TLV_IES_LEN(bss_ex); - uint ies_len; - - ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_BSS_EX_DEL_WFD_IE ? __func__ : NULL); - bss_ex->IELength -= ies_len_ori - ies_len; -} - -void rtw_bss_ex_del_wfd_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id) -{ -#define DBG_BSS_EX_DEL_WFD_ATTR 0 - - u8 *ies = BSS_EX_TLV_IES(bss_ex); - uint ies_len = BSS_EX_TLV_IES_LEN(bss_ex); - - u8 *ie; - uint ie_len, ie_len_ori; - - int index = 0; - - while (1) { - ie = rtw_get_wfd_ie(ies, ies_len, NULL, &ie_len_ori); - if (ie) { - u8 *next_ie_ori = ie + ie_len_ori; - uint remain_len = bss_ex->IELength - (next_ie_ori - bss_ex->IEs); - u8 has_target_attr = 0; - - if (DBG_BSS_EX_DEL_WFD_ATTR) { - if (rtw_get_wfd_attr(ie, ie_len_ori, attr_id, NULL, NULL)) { - RTW_INFO("%s %d before\n", __func__, index); - dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex)); - - RTW_INFO("ies:%p, ies_len:%u\n", ies, ies_len); - RTW_INFO("ie:%p, ie_len_ori:%u\n", ie, ie_len_ori); - RTW_INFO("next_ie_ori:%p, remain_len:%u\n", next_ie_ori, remain_len); - has_target_attr = 1; - } - } - - ie_len = rtw_del_wfd_attr(ie, ie_len_ori, attr_id); - if (ie_len != ie_len_ori) { - u8 *next_ie = ie + ie_len; - - _rtw_memmove(next_ie, next_ie_ori, remain_len); - _rtw_memset(next_ie + remain_len, 0, ie_len_ori - ie_len); - bss_ex->IELength -= ie_len_ori - ie_len; - - ies = next_ie; - } else - ies = next_ie_ori; - - if (DBG_BSS_EX_DEL_WFD_ATTR) { - if (has_target_attr) { - RTW_INFO("%s %d after\n", __func__, index); - dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex)); - } - } - - ies_len = remain_len; - - index++; - } else - break; - } -} - -/* Baron adds to avoid FreeBSD warning */ -int ieee80211_is_empty_essid(const char *essid, int essid_len) -{ - /* Single white space is for Linksys APs */ - if (essid_len == 1 && essid[0] == ' ') - return 1; - - /* Otherwise, if the entire essid is 0, we assume it is hidden */ - while (essid_len) { - essid_len--; - if (essid[essid_len] != '\0') - return 0; - } - - return 1; -} - -int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (WLAN_FC_GET_TYPE(fc)) { - case RTW_IEEE80211_FTYPE_DATA: - if (fc & RTW_IEEE80211_STYPE_QOS_DATA) - hdrlen += 2; - if ((fc & RTW_IEEE80211_FCTL_FROMDS) && (fc & RTW_IEEE80211_FCTL_TODS)) - hdrlen += 6; /* Addr4 */ - break; - case RTW_IEEE80211_FTYPE_CTL: - switch (WLAN_FC_GET_STYPE(fc)) { - case RTW_IEEE80211_STYPE_CTS: - case RTW_IEEE80211_STYPE_ACK: - hdrlen = 10; - break; - default: - hdrlen = 16; - break; - } - break; - } - - return hdrlen; -} - -u8 rtw_ht_mcsset_to_nss(u8 *supp_mcs_set) -{ - u8 nss = 1; - - if (supp_mcs_set[3]) - nss = 4; - else if (supp_mcs_set[2]) - nss = 3; - else if (supp_mcs_set[1]) - nss = 2; - else if (supp_mcs_set[0]) - nss = 1; - else - RTW_INFO("%s,%d, warning! supp_mcs_set is zero\n", __func__, __LINE__); - /* RTW_INFO("%s HT: %dSS\n", __FUNCTION__, nss); */ - return nss; -} - -u32 rtw_ht_mcs_set_to_bitmap(u8 *mcs_set, u8 nss) -{ - u8 i; - u32 bitmap = 0; - - for (i = 0; i < nss; i++) - bitmap |= mcs_set[i] << (i * 8); - - RTW_INFO("ht_mcs_set=%02x %02x %02x %02x, nss=%u, bitmap=%08x\n" - , mcs_set[0], mcs_set[1], mcs_set[2], mcs_set[3], nss, bitmap); - - return bitmap; -} - -/* show MCS rate, unit: 100Kbps */ -u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char *MCS_rate) -{ - u16 max_rate = 0; - - if (MCS_rate[3]) { - if (MCS_rate[3] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI) ? 6000 : 5400) : ((short_GI) ? 2889 : 2600); - else if (MCS_rate[3] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI) ? 5400 : 4860) : ((short_GI) ? 2600 : 2340); - else if (MCS_rate[3] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI) ? 4800 : 4320) : ((short_GI) ? 2311 : 2080); - else if (MCS_rate[3] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI) ? 3600 : 3240) : ((short_GI) ? 1733 : 1560); - else if (MCS_rate[3] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI) ? 2400 : 2160) : ((short_GI) ? 1156 : 1040); - else if (MCS_rate[3] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1800 : 1620) : ((short_GI) ? 867 : 780); - else if (MCS_rate[3] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1200 : 1080) : ((short_GI) ? 578 : 520); - else if (MCS_rate[3] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI) ? 600 : 540) : ((short_GI) ? 289 : 260); - } else if (MCS_rate[2]) { - if (MCS_rate[2] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI) ? 4500 : 4050) : ((short_GI) ? 2167 : 1950); - else if (MCS_rate[2] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI) ? 4050 : 3645) : ((short_GI) ? 1950 : 1750); - else if (MCS_rate[2] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI) ? 3600 : 3240) : ((short_GI) ? 1733 : 1560); - else if (MCS_rate[2] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI) ? 2700 : 2430) : ((short_GI) ? 1300 : 1170); - else if (MCS_rate[2] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1800 : 1620) : ((short_GI) ? 867 : 780); - else if (MCS_rate[2] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1350 : 1215) : ((short_GI) ? 650 : 585); - else if (MCS_rate[2] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI) ? 900 : 810) : ((short_GI) ? 433 : 390); - else if (MCS_rate[2] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI) ? 450 : 405) : ((short_GI) ? 217 : 195); - } else if (MCS_rate[1]) { - if (MCS_rate[1] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI) ? 3000 : 2700) : ((short_GI) ? 1444 : 1300); - else if (MCS_rate[1] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI) ? 2700 : 2430) : ((short_GI) ? 1300 : 1170); - else if (MCS_rate[1] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI) ? 2400 : 2160) : ((short_GI) ? 1156 : 1040); - else if (MCS_rate[1] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1800 : 1620) : ((short_GI) ? 867 : 780); - else if (MCS_rate[1] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1200 : 1080) : ((short_GI) ? 578 : 520); - else if (MCS_rate[1] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI) ? 900 : 810) : ((short_GI) ? 433 : 390); - else if (MCS_rate[1] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI) ? 600 : 540) : ((short_GI) ? 289 : 260); - else if (MCS_rate[1] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130); - } else { - if (MCS_rate[0] & BIT(7)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1500 : 1350) : ((short_GI) ? 722 : 650); - else if (MCS_rate[0] & BIT(6)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1350 : 1215) : ((short_GI) ? 650 : 585); - else if (MCS_rate[0] & BIT(5)) - max_rate = (bw_40MHz) ? ((short_GI) ? 1200 : 1080) : ((short_GI) ? 578 : 520); - else if (MCS_rate[0] & BIT(4)) - max_rate = (bw_40MHz) ? ((short_GI) ? 900 : 810) : ((short_GI) ? 433 : 390); - else if (MCS_rate[0] & BIT(3)) - max_rate = (bw_40MHz) ? ((short_GI) ? 600 : 540) : ((short_GI) ? 289 : 260); - else if (MCS_rate[0] & BIT(2)) - max_rate = (bw_40MHz) ? ((short_GI) ? 450 : 405) : ((short_GI) ? 217 : 195); - else if (MCS_rate[0] & BIT(1)) - max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) : ((short_GI) ? 144 : 130); - else if (MCS_rate[0] & BIT(0)) - max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) : ((short_GI) ? 72 : 65); - } - - return max_rate; -} - -int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8 *category, u8 *action) -{ - const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr); - u16 fc; - u8 c; - u8 a = ACT_PUBLIC_MAX; - - fc = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)frame)->frame_ctl); - - if ((fc & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE)) - != (RTW_IEEE80211_FTYPE_MGMT | RTW_IEEE80211_STYPE_ACTION) - ) - return _FALSE; - - c = frame_body[0]; - - switch (c) { - case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */ - break; - default: - a = frame_body[1]; - } - - if (category) - *category = c; - if (action) - *action = a; - - return _TRUE; -} - -static const char *_action_public_str[] = { - "ACT_PUB_BSSCOEXIST", - "ACT_PUB_DSE_ENABLE", - "ACT_PUB_DSE_DEENABLE", - "ACT_PUB_DSE_REG_LOCATION", - "ACT_PUB_EXT_CHL_SWITCH", - "ACT_PUB_DSE_MSR_REQ", - "ACT_PUB_DSE_MSR_RPRT", - "ACT_PUB_MP", - "ACT_PUB_DSE_PWR_CONSTRAINT", - "ACT_PUB_VENDOR", - "ACT_PUB_GAS_INITIAL_REQ", - "ACT_PUB_GAS_INITIAL_RSP", - "ACT_PUB_GAS_COMEBACK_REQ", - "ACT_PUB_GAS_COMEBACK_RSP", - "ACT_PUB_TDLS_DISCOVERY_RSP", - "ACT_PUB_LOCATION_TRACK", - "ACT_PUB_RSVD", -}; - -const char *action_public_str(u8 action) -{ - action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action; - return _action_public_str[action]; -} - diff --git a/core/rtw_mlme_ext.c b/core/rtw_mlme_ext.c old mode 100755 new mode 100644 diff --git a/core/rtw_mlme_ext.c.orig b/core/rtw_mlme_ext.c.orig deleted file mode 100755 index 3715889..0000000 --- a/core/rtw_mlme_ext.c.orig +++ /dev/null @@ -1,16784 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2017 Realtek Corporation. - * - * 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. - * - *****************************************************************************/ -#define _RTW_MLME_EXT_C_ - -#include -#ifdef CONFIG_IOCTL_CFG80211 - #include -#endif /* CONFIG_IOCTL_CFG80211 */ -#include - - -struct mlme_handler mlme_sta_tbl[] = { - {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, - {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, - {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, - {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, - {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, - {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, - - /*---------------------------------------------------------- - below 2 are reserved - -----------------------------------------------------------*/ - {0, "DoReserved", &DoReserved}, - {0, "DoReserved", &DoReserved}, - {WIFI_BEACON, "OnBeacon", &OnBeacon}, - {WIFI_ATIM, "OnATIM", &OnAtim}, - {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, - {WIFI_AUTH, "OnAuth", &OnAuthClient}, - {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, - {WIFI_ACTION, "OnAction", &OnAction}, - {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction}, -}; - -#ifdef _CONFIG_NATIVEAP_MLME_ -struct mlme_handler mlme_ap_tbl[] = { - {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, - {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, - {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, - {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, - {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, - {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, - - /*---------------------------------------------------------- - below 2 are reserved - -----------------------------------------------------------*/ - {0, "DoReserved", &DoReserved}, - {0, "DoReserved", &DoReserved}, - {WIFI_BEACON, "OnBeacon", &OnBeacon}, - {WIFI_ATIM, "OnATIM", &OnAtim}, - {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, - {WIFI_AUTH, "OnAuth", &OnAuth}, - {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, - {WIFI_ACTION, "OnAction", &OnAction}, - {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction}, -}; -#endif - -struct action_handler OnAction_tbl[] = { - {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct}, - {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos}, - {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls}, - {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back}, - {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public}, - {RTW_WLAN_CATEGORY_RADIO_MEAS, "ACTION_RADIO_MEAS", &on_action_rm}, - {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &OnAction_ft}, - {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 */ -#ifdef CONFIG_RTW_WNM - {RTW_WLAN_CATEGORY_WNM, "ACTION_WNM", &on_action_wnm}, -#endif - {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved}, -#ifdef CONFIG_RTW_MESH - {RTW_WLAN_CATEGORY_MESH, "ACTION_MESH", &on_action_mesh}, - {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &on_action_self_protected}, -#endif - {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm}, - {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &OnAction_vht}, - {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p}, -}; - - -u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; - -/************************************************** -OUI definitions for the vendor specific IE -***************************************************/ -unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; -unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02}; -unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; -unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09}; -unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A}; - -unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; -unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - -unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02}; -unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02}; - -extern unsigned char REALTEK_96B_IE[]; - -static void init_channel_list(_adapter *padapter, RT_CHANNEL_INFO *channel_set - , struct p2p_channels *channel_list) -{ - struct registry_priv *regsty = adapter_to_regsty(padapter); - - struct p2p_oper_class_map op_class[] = { - { IEEE80211G, 81, 1, 13, 1, BW20 }, - { IEEE80211G, 82, 14, 14, 1, BW20 }, -#if 0 /* Do not enable HT40 on 2 GHz */ - { IEEE80211G, 83, 1, 9, 1, BW40PLUS }, - { IEEE80211G, 84, 5, 13, 1, BW40MINUS }, -#endif - { IEEE80211A, 115, 36, 48, 4, BW20 }, - { IEEE80211A, 116, 36, 44, 8, BW40PLUS }, - { IEEE80211A, 117, 40, 48, 8, BW40MINUS }, - { IEEE80211A, 124, 149, 161, 4, BW20 }, - { IEEE80211A, 125, 149, 169, 4, BW20 }, - { IEEE80211A, 126, 149, 157, 8, BW40PLUS }, - { IEEE80211A, 127, 153, 161, 8, BW40MINUS }, - { -1, 0, 0, 0, 0, BW20 } - }; - - int cla, op; - - cla = 0; - - for (op = 0; op_class[op].op_class; op++) { - u8 ch; - struct p2p_oper_class_map *o = &op_class[op]; - struct p2p_reg_class *reg = NULL; - - for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { - if (rtw_chset_search_ch(channel_set, ch) == -1) - continue; -#if defined(CONFIG_80211N_HT) || defined(CONFIG_80211AC_VHT) - if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8)) - continue; - - if ((REGSTY_IS_BW_5G_SUPPORT(regsty, CHANNEL_WIDTH_40)) && - ((o->bw == BW40MINUS) || (o->bw == BW40PLUS))) - continue; -#endif - if (reg == NULL) { - reg = &channel_list->reg_class[cla]; - cla++; - reg->reg_class = o->op_class; - reg->channels = 0; - } - reg->channel[reg->channels] = ch; - reg->channels++; - } - } - channel_list->reg_classes = cla; - -} - -#if CONFIG_TXPWR_LIMIT -void rtw_txpwr_init_regd(struct rf_ctl_t *rfctl) -{ - u8 regd; - struct regd_exc_ent *exc; - struct txpwr_lmt_ent *ent; - _irqL irqL; - - _enter_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL); - - rfctl->regd_name = NULL; - - if (rfctl->txpwr_regd_num == 0) { - RTW_PRINT("there is no any txpwr_regd\n"); - goto release_lock; - } - - /* search from exception mapping */ - exc = _rtw_regd_exc_search(rfctl - , rfctl->country_ent ? rfctl->country_ent->alpha2 : NULL - , rfctl->ChannelPlan); - if (exc) { - u8 has_country = (exc->country[0] == '\0' && exc->country[1] == '\0') ? 0 : 1; - - if (strcmp(exc->regd_name, regd_str(TXPWR_LMT_NONE)) == 0) - rfctl->regd_name = regd_str(TXPWR_LMT_NONE); - else if (strcmp(exc->regd_name, regd_str(TXPWR_LMT_WW)) == 0) - rfctl->regd_name = regd_str(TXPWR_LMT_WW); - else { - ent = _rtw_txpwr_lmt_get_by_name(rfctl, exc->regd_name); - if (ent) - rfctl->regd_name = ent->regd_name; - } - - RTW_PRINT("exception mapping country:%c%c domain:0x%02x to%s regd_name:%s\n" - , has_country ? exc->country[0] : '0' - , has_country ? exc->country[1] : '0' - , exc->domain - , rfctl->regd_name ? "" : " unknown" - , exc->regd_name - ); - if (rfctl->regd_name) - goto release_lock; - } - - /* follow default channel plan mapping */ - regd = rtw_chplan_get_default_regd(rfctl->ChannelPlan); - if (regd == TXPWR_LMT_NONE) - rfctl->regd_name = regd_str(TXPWR_LMT_NONE); - else if (regd == TXPWR_LMT_WW) - rfctl->regd_name = regd_str(TXPWR_LMT_WW); - else { - ent = _rtw_txpwr_lmt_get_by_name(rfctl, regd_str(regd)); - if (ent) - rfctl->regd_name = ent->regd_name; - } - - RTW_PRINT("default mapping domain:0x%02x to%s regd_name:%s\n" - , rfctl->ChannelPlan - , rfctl->regd_name ? "" : " unknown" - , regd_str(regd) - ); - if (rfctl->regd_name) - goto release_lock; - - switch (regd) { - /* - * To support older chips without new predefined regd: - * - use FCC if IC or CHILE not found - * - use ETSI if KCC or ACMA not found - */ - case TXPWR_LMT_IC: - case TXPWR_LMT_KCC: - case TXPWR_LMT_ACMA: - case TXPWR_LMT_CHILE: - if (regd == TXPWR_LMT_IC || regd == TXPWR_LMT_CHILE) - regd = TXPWR_LMT_FCC; - else if (regd == TXPWR_LMT_KCC || regd == TXPWR_LMT_ACMA) - regd = TXPWR_LMT_ETSI; - ent = _rtw_txpwr_lmt_get_by_name(rfctl, regd_str(regd)); - if (ent) - rfctl->regd_name = ent->regd_name; - RTW_PRINT("alternate regd_name:%s %s\n" - , regd_str(regd) - , rfctl->regd_name ? "is used" : "not found" - ); - if (rfctl->regd_name) - break; - default: - rfctl->regd_name = regd_str(TXPWR_LMT_WW); - RTW_PRINT("assign %s for default case\n", regd_str(TXPWR_LMT_WW)); - break; - }; - -release_lock: - _exit_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL); -} -#endif /* CONFIG_TXPWR_LIMIT */ - -void rtw_rfctl_init(_adapter *adapter) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - - rfctl->max_chan_nums = init_channel_set(adapter, rfctl->ChannelPlan, rfctl->channel_set); - init_channel_list(adapter, rfctl->channel_set, &rfctl->channel_list); - - _rtw_mutex_init(&rfctl->offch_mutex); - -#if CONFIG_TXPWR_LIMIT - _rtw_mutex_init(&rfctl->txpwr_lmt_mutex); - _rtw_init_listhead(&rfctl->reg_exc_list); - _rtw_init_listhead(&rfctl->txpwr_lmt_list); -#endif - - rfctl->ch_sel_same_band_prefer = 1; - -#ifdef CONFIG_DFS_MASTER - rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED; - rtw_init_timer(&(rfctl->radar_detect_timer), adapter, rtw_dfs_rd_timer_hdl, rfctl); -#endif -#ifdef CONFIG_DFS_SLAVE_WITH_RADAR_DETECT - rfctl->dfs_slave_with_rd = 1; -#endif -} - -void rtw_rfctl_deinit(_adapter *adapter) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - - _rtw_mutex_free(&rfctl->offch_mutex); - -#if CONFIG_TXPWR_LIMIT - rtw_regd_exc_list_free(rfctl); - rtw_txpwr_lmt_list_free(rfctl); - _rtw_mutex_free(&rfctl->txpwr_lmt_mutex); -#endif -} - -#ifdef CONFIG_DFS_MASTER -/* -* called in rtw_dfs_rd_enable() -* assume the request channel coverage is DFS range -* base on the current status and the request channel coverage to check if need to reset complete CAC time -*/ -bool rtw_is_cac_reset_needed(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset) -{ - bool needed = _FALSE; - u32 cur_hi, cur_lo, hi, lo; - - if (rfctl->radar_detected == 1) { - needed = _TRUE; - goto exit; - } - - if (rfctl->radar_detect_ch == 0) { - needed = _TRUE; - goto exit; - } - - if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) { - RTW_ERR("request detection range ch:%u, bw:%u, offset:%u\n", ch, bw, offset); - rtw_warn_on(1); - } - - if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset, &cur_hi, &cur_lo) == _FALSE) { - RTW_ERR("cur detection range ch:%u, bw:%u, offset:%u\n", rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset); - rtw_warn_on(1); - } - - if (hi <= lo || cur_hi <= cur_lo) { - RTW_ERR("hi:%u, lo:%u, cur_hi:%u, cur_lo:%u\n", hi, lo, cur_hi, cur_lo); - rtw_warn_on(1); - } - - if (rtw_is_range_a_in_b(hi, lo, cur_hi, cur_lo)) { - /* request is in current detect range */ - goto exit; - } - - /* check if request channel coverage has new range and the new range is in DFS range */ - if (!rtw_is_range_overlap(hi, lo, cur_hi, cur_lo)) { - /* request has no overlap with current */ - needed = _TRUE; - } else if (rtw_is_range_a_in_b(cur_hi, cur_lo, hi, lo)) { - /* request is supper set of current */ - if ((hi != cur_hi && rtw_is_dfs_range(hi, cur_hi)) || (lo != cur_lo && rtw_is_dfs_range(cur_lo, lo))) - needed = _TRUE; - } else { - /* request is not supper set of current, but has overlap */ - if ((lo < cur_lo && rtw_is_dfs_range(cur_lo, lo)) || (hi > cur_hi && rtw_is_dfs_range(hi, cur_hi))) - needed = _TRUE; - } - -exit: - return needed; -} - -bool _rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset) -{ - bool ret = _FALSE; - u32 hi = 0, lo = 0; - u32 r_hi = 0, r_lo = 0; - int i; - - if (rfctl->radar_detect_by_others) - goto exit; - - if (rfctl->radar_detect_ch == 0) - goto exit; - - if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) { - rtw_warn_on(1); - goto exit; - } - - if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch - , rfctl->radar_detect_bw, rfctl->radar_detect_offset - , &r_hi, &r_lo) == _FALSE) { - rtw_warn_on(1); - goto exit; - } - - if (rtw_is_range_overlap(hi, lo, r_hi, r_lo)) - ret = _TRUE; - -exit: - return ret; -} - -bool rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl) -{ - return _rtw_rfctl_overlap_radar_detect_ch(rfctl - , rfctl_to_dvobj(rfctl)->oper_channel - , rfctl_to_dvobj(rfctl)->oper_bwmode - , rfctl_to_dvobj(rfctl)->oper_ch_offset); -} - -bool rtw_rfctl_is_tx_blocked_by_ch_waiting(struct rf_ctl_t *rfctl) -{ - return rtw_rfctl_overlap_radar_detect_ch(rfctl) && IS_CH_WAITING(rfctl); -} - -bool rtw_chset_is_chbw_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset) -{ - bool ret = _FALSE; - u32 hi = 0, lo = 0; - int i; - - if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) - goto exit; - - for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) { - if (!rtw_ch2freq(ch_set[i].ChannelNum)) { - rtw_warn_on(1); - continue; - } - - if (!CH_IS_NON_OCP(&ch_set[i])) - continue; - - if (lo <= rtw_ch2freq(ch_set[i].ChannelNum) - && rtw_ch2freq(ch_set[i].ChannelNum) <= hi - ) { - ret = _TRUE; - break; - } - } - -exit: - return ret; -} - -bool rtw_chset_is_ch_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch) -{ - return rtw_chset_is_chbw_non_ocp(ch_set, ch, CHANNEL_WIDTH_20, HAL_PRIME_CHNL_OFFSET_DONT_CARE); -} - -u32 rtw_chset_get_ch_non_ocp_ms(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset) -{ - int ms = 0; - systime current_time; - u32 hi = 0, lo = 0; - int i; - - if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) - goto exit; - - current_time = rtw_get_current_time(); - - for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) { - if (!rtw_ch2freq(ch_set[i].ChannelNum)) { - rtw_warn_on(1); - continue; - } - - if (!CH_IS_NON_OCP(&ch_set[i])) - continue; - - if (lo <= rtw_ch2freq(ch_set[i].ChannelNum) - && rtw_ch2freq(ch_set[i].ChannelNum) <= hi - ) { - if (rtw_systime_to_ms(ch_set[i].non_ocp_end_time - current_time) > ms) - ms = rtw_systime_to_ms(ch_set[i].non_ocp_end_time - current_time); - } - } - -exit: - return ms; -} - -/** - * rtw_chset_update_non_ocp - update non_ocp_end_time according to the given @ch, @bw, @offset into @ch_set - * @ch_set: the given channel set - * @ch: channel number on which radar is detected - * @bw: bandwidth on which radar is detected - * @offset: bandwidth offset on which radar is detected - * @ms: ms to add from now to update non_ocp_end_time, ms < 0 means use NON_OCP_TIME_MS - */ -static void _rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms) -{ - u32 hi = 0, lo = 0; - int i; - - if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) - goto exit; - - for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) { - if (!rtw_ch2freq(ch_set[i].ChannelNum)) { - rtw_warn_on(1); - continue; - } - - if (lo <= rtw_ch2freq(ch_set[i].ChannelNum) - && rtw_ch2freq(ch_set[i].ChannelNum) <= hi - ) { - if (ms >= 0) - ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(ms); - else - ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(NON_OCP_TIME_MS); - } - } - -exit: - return; -} - -inline void rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset) -{ - _rtw_chset_update_non_ocp(ch_set, ch, bw, offset, -1); -} - -inline void rtw_chset_update_non_ocp_ms(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms) -{ - _rtw_chset_update_non_ocp(ch_set, ch, bw, offset, ms); -} - -u32 rtw_get_ch_waiting_ms(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, u32 *r_non_ocp_ms, u32 *r_cac_ms) -{ - struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); - u32 non_ocp_ms; - u32 cac_ms; - u8 in_rd_range = 0; /* if in current radar detection range*/ - - if (rtw_chset_is_chbw_non_ocp(rfctl->channel_set, ch, bw, offset)) - non_ocp_ms = rtw_chset_get_ch_non_ocp_ms(rfctl->channel_set, ch, bw, offset); - else - non_ocp_ms = 0; - - if (rfctl->radar_detect_enabled) { - u32 cur_hi, cur_lo, hi, lo; - - if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) { - RTW_ERR("input range ch:%u, bw:%u, offset:%u\n", ch, bw, offset); - rtw_warn_on(1); - } - - if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset, &cur_hi, &cur_lo) == _FALSE) { - RTW_ERR("cur detection range ch:%u, bw:%u, offset:%u\n", rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset); - rtw_warn_on(1); - } - - if (rtw_is_range_a_in_b(hi, lo, cur_hi, cur_lo)) - in_rd_range = 1; - } - - if (!rtw_is_dfs_chbw(ch, bw, offset)) - cac_ms = 0; - else if (in_rd_range && !non_ocp_ms) { - if (IS_CH_WAITING(rfctl)) - cac_ms = rtw_systime_to_ms(rfctl->cac_end_time - rtw_get_current_time()); - else - cac_ms = 0; - } else if (rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj))) - cac_ms = CAC_TIME_CE_MS; - else - cac_ms = CAC_TIME_MS; - - if (r_non_ocp_ms) - *r_non_ocp_ms = non_ocp_ms; - if (r_cac_ms) - *r_cac_ms = cac_ms; - - return non_ocp_ms + cac_ms; -} - -void rtw_reset_cac(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset) -{ - u32 non_ocp_ms; - u32 cac_ms; - - rtw_get_ch_waiting_ms(rfctl - , ch - , bw - , offset - , &non_ocp_ms - , &cac_ms - ); - - rfctl->cac_start_time = rtw_get_current_time() + rtw_ms_to_systime(non_ocp_ms); - rfctl->cac_end_time = rfctl->cac_start_time + rtw_ms_to_systime(cac_ms); - - /* skip special value */ - if (rfctl->cac_start_time == RTW_CAC_STOPPED) { - rfctl->cac_start_time++; - rfctl->cac_end_time++; - } - if (rfctl->cac_end_time == RTW_CAC_STOPPED) - rfctl->cac_end_time++; -} - -u32 rtw_force_stop_cac(struct rf_ctl_t *rfctl, u32 timeout_ms) -{ - struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); - systime start; - u32 pass_ms; - - start = rtw_get_current_time(); - - rfctl->cac_force_stop = 1; - - while (rtw_get_passing_time_ms(start) <= timeout_ms - && IS_UNDER_CAC(rfctl) - ) { - if (dev_is_surprise_removed(dvobj) || dev_is_drv_stopped(dvobj)) - break; - rtw_msleep_os(20); - } - - if (IS_UNDER_CAC(rfctl)) { - if (!dev_is_surprise_removed(dvobj) && !dev_is_drv_stopped(dvobj)) - RTW_INFO("%s waiting for cac stop timeout!\n", __func__); - } - - rfctl->cac_force_stop = 0; - - pass_ms = rtw_get_passing_time_ms(start); - - return pass_ms; -} -#endif /* CONFIG_DFS_MASTER */ - -/* choose channel with shortest waiting (non ocp + cac) time */ -bool rtw_choose_shortest_waiting_ch(struct rf_ctl_t *rfctl, u8 sel_ch, u8 max_bw - , u8 *dec_ch, u8 *dec_bw, u8 *dec_offset - , u8 d_flags, u8 cur_ch, u8 same_band_prefer, u8 mesh_only) -{ -#ifndef DBG_CHOOSE_SHORTEST_WAITING_CH -#define DBG_CHOOSE_SHORTEST_WAITING_CH 0 -#endif - struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); - struct registry_priv *regsty = dvobj_to_regsty(dvobj); - u8 ch, bw, offset; - u8 ch_c = 0, bw_c = 0, offset_c = 0; - int i; - u32 min_waiting_ms = 0; - - if (!dec_ch || !dec_bw || !dec_offset) { - rtw_warn_on(1); - return _FALSE; - } - - /* full search and narrow bw judegement first to avoid potetial judegement timing issue */ - for (bw = CHANNEL_WIDTH_20; bw <= max_bw; bw++) { - if (!hal_is_bw_support(dvobj_get_primary_adapter(dvobj), bw)) - continue; - - for (i = 0; i < rfctl->max_chan_nums; i++) { - u32 non_ocp_ms = 0; - u32 cac_ms = 0; - u32 waiting_ms = 0; - - ch = rfctl->channel_set[i].ChannelNum; - if (sel_ch > 0 && ch != sel_ch) - continue; - - if ((d_flags & RTW_CHF_2G) && ch <= 14) - continue; - - if ((d_flags & RTW_CHF_5G) && ch > 14) - continue; - - if (ch > 14) { - if (bw > REGSTY_BW_5G(regsty)) - continue; - } else { - if (bw > REGSTY_BW_2G(regsty)) - continue; - } - - if (mesh_only && ch >= 5 && ch <= 9 && bw > CHANNEL_WIDTH_20) - continue; - - if (!rtw_get_offset_by_chbw(ch, bw, &offset)) - continue; - - if (!rtw_chset_is_chbw_valid(rfctl->channel_set, ch, bw, offset)) - continue; - - if ((d_flags & RTW_CHF_NON_OCP) && rtw_chset_is_chbw_non_ocp(rfctl->channel_set, ch, bw, offset)) - continue; - - if ((d_flags & RTW_CHF_DFS) && rtw_is_dfs_chbw(ch, bw, offset)) - continue; - - if ((d_flags & RTW_CHF_LONG_CAC) && rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj))) - continue; - - if ((d_flags & RTW_CHF_NON_DFS) && !rtw_is_dfs_chbw(ch, bw, offset)) - continue; - - if ((d_flags & RTW_CHF_NON_LONG_CAC) && !rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj))) - continue; - - #ifdef CONFIG_DFS_MASTER - waiting_ms = rtw_get_ch_waiting_ms(rfctl, ch, bw, offset, &non_ocp_ms, &cac_ms); - #endif - - if (DBG_CHOOSE_SHORTEST_WAITING_CH) - RTW_INFO("%s:%u,%u,%u %u(non_ocp:%u, cac:%u)\n" - , __func__, ch, bw, offset, waiting_ms, non_ocp_ms, cac_ms); - - if (ch_c == 0 - /* first: smaller wating time */ - || min_waiting_ms > waiting_ms - /* then: wider bw */ - || (min_waiting_ms == waiting_ms && bw > bw_c) - /* then: same band if requested */ - || (same_band_prefer && min_waiting_ms == waiting_ms && bw == bw_c - && !rtw_is_same_band(cur_ch, ch_c) && rtw_is_same_band(cur_ch, ch)) - ) { - ch_c = ch; - bw_c = bw; - offset_c = offset; - min_waiting_ms = waiting_ms; - } - } - } - - if (ch_c != 0) { - RTW_INFO("%s: d_flags:0x%02x cur_ch:%u sb_prefer:%u%s %u,%u,%u waiting_ms:%u\n" - , __func__, d_flags, cur_ch, same_band_prefer - , mesh_only ? " mesh_only" : "" - , ch_c, bw_c, offset_c, min_waiting_ms); - - *dec_ch = ch_c; - *dec_bw = bw_c; - *dec_offset = offset_c; - return _TRUE; - } - - if (d_flags == 0) { - RTW_INFO("%s: sel_ch:%u max_bw:%u d_flags:0x%02x cur_ch:%u sb_prefer:%u%s\n" - , __func__, sel_ch, max_bw, d_flags, cur_ch, same_band_prefer - , mesh_only ? " mesh_only" : ""); - rtw_warn_on(1); - } - - return _FALSE; -} - -void dump_chset(void *sel, RT_CHANNEL_INFO *ch_set) -{ - u8 i; - - for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) { - RTW_PRINT_SEL(sel, "ch:%3u, freq:%u, scan_type:%d" - , ch_set[i].ChannelNum, rtw_ch2freq(ch_set[i].ChannelNum), ch_set[i].ScanType); - -#ifdef CONFIG_FIND_BEST_CHANNEL - _RTW_PRINT_SEL(sel, ", rx_count:%u", ch_set[i].rx_count); -#endif - -#ifdef CONFIG_DFS_MASTER - if (rtw_is_dfs_ch(ch_set[i].ChannelNum)) { - if (CH_IS_NON_OCP(&ch_set[i])) - _RTW_PRINT_SEL(sel, ", non_ocp:%d" - , rtw_systime_to_ms(ch_set[i].non_ocp_end_time - rtw_get_current_time())); - else - _RTW_PRINT_SEL(sel, ", non_ocp:N/A"); - } -#endif - - _RTW_PRINT_SEL(sel, "\n"); - } - - RTW_PRINT_SEL(sel, "total ch number:%d\n", i); -} - -void dump_cur_chset(void *sel, struct rf_ctl_t *rfctl) -{ - struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl); - struct registry_priv *regsty = dvobj_to_regsty(dvobj); - int i; - - if (rfctl->country_ent) - dump_country_chplan(sel, rfctl->country_ent); - else - RTW_PRINT_SEL(sel, "chplan:0x%02X\n", rfctl->ChannelPlan); - -#if CONFIG_TXPWR_LIMIT - RTW_PRINT_SEL(sel, "PLS regd:%s\n", rfctl->regd_name); -#endif - -#ifdef CONFIG_DFS_MASTER - RTW_PRINT_SEL(sel, "dfs_domain:%u\n", rtw_odm_get_dfs_domain(dvobj)); -#endif - - for (i = 0; i < MAX_CHANNEL_NUM; i++) - if (regsty->excl_chs[i] != 0) - break; - - if (i < MAX_CHANNEL_NUM) { - RTW_PRINT_SEL(sel, "excl_chs:"); - for (i = 0; i < MAX_CHANNEL_NUM; i++) { - if (regsty->excl_chs[i] == 0) - break; - _RTW_PRINT_SEL(sel, "%u ", regsty->excl_chs[i]); - } - _RTW_PRINT_SEL(sel, "\n"); - } - - dump_chset(sel, rfctl->channel_set); -} - -/* - * Search the @param ch in given @param ch_set - * @ch_set: the given channel set - * @ch: the given channel number - * - * return the index of channel_num in channel_set, -1 if not found - */ -int rtw_chset_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch) -{ - int i; - - if (ch == 0) - return -1; - - for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) { - if (ch == ch_set[i].ChannelNum) - return i; - } - - return -1; -} - -/* - * Check if the @param ch, bw, offset is valid for the given @param ch_set - * @ch_set: the given channel set - * @ch: the given channel number - * @bw: the given bandwidth - * @offset: the given channel offset - * - * return valid (1) or not (0) - */ -u8 rtw_chset_is_chbw_valid(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset) -{ - u8 cch; - u8 *op_chs; - u8 op_ch_num; - u8 valid = 0; - int i; - - cch = rtw_get_center_ch(ch, bw, offset); - - if (!rtw_get_op_chs_by_cch_bw(cch, bw, &op_chs, &op_ch_num)) - goto exit; - - for (i = 0; i < op_ch_num; i++) { - if (0) - RTW_INFO("%u,%u,%u - cch:%u, bw:%u, op_ch:%u\n", ch, bw, offset, cch, bw, *(op_chs + i)); - if (rtw_chset_search_ch(ch_set, *(op_chs + i)) == -1) - break; - } - - if (op_ch_num != 0 && i == op_ch_num) - valid = 1; - -exit: - return valid; -} - -/** - * rtw_chset_sync_chbw - obey g_ch, adjust g_bw, g_offset, bw, offset to fit in channel plan - * @ch_set: channel plan to check - * @req_ch: pointer of the request ch, may be modified further - * @req_bw: pointer of the request bw, may be modified further - * @req_offset: pointer of the request offset, may be modified further - * @g_ch: pointer of the ongoing group ch - * @g_bw: pointer of the ongoing group bw, may be modified further - * @g_offset: pointer of the ongoing group offset, may be modified further - */ -void rtw_chset_sync_chbw(RT_CHANNEL_INFO *ch_set, u8 *req_ch, u8 *req_bw, u8 *req_offset - , u8 *g_ch, u8 *g_bw, u8 *g_offset) -{ - u8 r_ch, r_bw, r_offset; - u8 u_ch, u_bw, u_offset; - u8 cur_bw = *req_bw; - - while (1) { - r_ch = *req_ch; - r_bw = cur_bw; - r_offset = *req_offset; - u_ch = *g_ch; - u_bw = *g_bw; - u_offset = *g_offset; - - rtw_sync_chbw(&r_ch, &r_bw, &r_offset, &u_ch, &u_bw, &u_offset); - - if (rtw_chset_is_chbw_valid(ch_set, r_ch, r_bw, r_offset)) - break; - if (cur_bw == CHANNEL_WIDTH_20) { - rtw_warn_on(1); - break; - } - cur_bw--; - }; - - *req_ch = r_ch; - *req_bw = r_bw; - *req_offset = r_offset; - *g_ch = u_ch; - *g_bw = u_bw; - *g_offset = u_offset; -} - -/* - * Check the @param ch is fit with setband setting of @param adapter - * @adapter: the given adapter - * @ch: the given channel number - * - * return _TRUE when check valid, _FALSE not valid - */ -bool rtw_mlme_band_check(_adapter *adapter, const u32 ch) -{ - if (adapter->setband == WIFI_FREQUENCY_BAND_AUTO /* 2.4G and 5G */ - || (adapter->setband == WIFI_FREQUENCY_BAND_2GHZ && ch < 35) /* 2.4G only */ - || (adapter->setband == WIFI_FREQUENCY_BAND_5GHZ && ch > 35) /* 5G only */ - ) - return _TRUE; - return _FALSE; -} -inline void RTW_SET_SCAN_BAND_SKIP(_adapter *padapter, int skip_band) -{ - int bs = ATOMIC_READ(&padapter->bandskip); - - bs |= skip_band; - ATOMIC_SET(&padapter->bandskip, bs); -} - -inline void RTW_CLR_SCAN_BAND_SKIP(_adapter *padapter, int skip_band) -{ - int bs = ATOMIC_READ(&padapter->bandskip); - - bs &= ~(skip_band); - ATOMIC_SET(&padapter->bandskip, bs); -} -inline int RTW_GET_SCAN_BAND_SKIP(_adapter *padapter) -{ - return ATOMIC_READ(&padapter->bandskip); -} - -#define RTW_IS_SCAN_BAND_SKIP(padapter, skip_band) (ATOMIC_READ(&padapter->bandskip) & (skip_band)) - -bool rtw_mlme_ignore_chan(_adapter *adapter, const u32 ch) -{ - if (RTW_IS_SCAN_BAND_SKIP(adapter, BAND_24G) && ch < 35) /* SKIP 2.4G Band channel */ - return _TRUE; - if (RTW_IS_SCAN_BAND_SKIP(adapter, BAND_5G) && ch > 35) /* SKIP 5G Band channel */ - return _TRUE; - - return _FALSE; -} - - -/**************************************************************************** - -Following are the initialization functions for WiFi MLME - -*****************************************************************************/ - -int init_hw_mlme_ext(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - u8 rx_bar_enble = _TRUE; - - /* - * Sync driver status and hardware setting - */ - - /* Modify to make sure first time change channel(band) would be done properly */ - pHalData->current_channel = 0; - pHalData->current_channel_bw = CHANNEL_WIDTH_MAX; - pHalData->current_band_type = BAND_MAX; - - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ /* removed */ - rtw_hal_set_hwreg(padapter, HW_VAR_ENABLE_RX_BAR, &rx_bar_enble); - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - return _SUCCESS; -} - -void init_mlme_default_rate_set(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - unsigned char end_set[1] = {0xff}; - u8 offset_datarate = 0; - u8 offset_basicrate = 0; -#ifdef CONFIG_80211N_HT - unsigned char supported_mcs_set[16] = {0xff, 0xff, 0xff, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; -#endif - - if (IsSupportedTxCCK(padapter->registrypriv.wireless_mode)) { - - unsigned char datarate_b[B_MODE_RATE_NUM] ={_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_}; - _rtw_memcpy(pmlmeext->datarate, datarate_b, B_MODE_RATE_NUM); - _rtw_memcpy(pmlmeext->basicrate, datarate_b, B_MODE_RATE_NUM); - offset_datarate += B_MODE_RATE_NUM; - offset_basicrate += B_MODE_RATE_NUM; - RTW_INFO("%s: support CCK\n", __func__); - } - if(IsSupportedTxOFDM(padapter->registrypriv.wireless_mode)) { - unsigned char datarate_g[G_MODE_RATE_NUM] ={_6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_,_24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_}; - unsigned char basicrate_g[G_MODE_BASIC_RATE_NUM] = {_6M_RATE_, _12M_RATE_, _24M_RATE_}; - _rtw_memcpy(pmlmeext->datarate + offset_datarate, datarate_g, G_MODE_RATE_NUM); - _rtw_memcpy(pmlmeext->basicrate + offset_basicrate,basicrate_g, G_MODE_BASIC_RATE_NUM); - offset_datarate += G_MODE_RATE_NUM; - offset_basicrate += G_MODE_BASIC_RATE_NUM; - RTW_INFO("%s: support OFDM\n", __func__); - - } - _rtw_memcpy(pmlmeext->datarate + offset_datarate, end_set, 1); - _rtw_memcpy(pmlmeext->basicrate + offset_basicrate, end_set, 1); - -#ifdef CONFIG_80211N_HT - if( padapter->registrypriv.ht_enable && is_supported_ht(padapter->registrypriv.wireless_mode)) - _rtw_memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set)); -#endif -} - -static void init_mlme_ext_priv_value(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - 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; -#endif - pmlmeext->cur_channel = padapter->registrypriv.channel; - pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - - pmlmeext->retry = 0; - - pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; - init_mlme_default_rate_set(padapter); - - if (pmlmeext->cur_channel > 14) - pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB; - else - pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; - - mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE); - pmlmeext->sitesurvey_res.channel_idx = 0; - pmlmeext->sitesurvey_res.bss_cnt = 0; - pmlmeext->sitesurvey_res.scan_ch_ms = SURVEY_TO; - pmlmeext->sitesurvey_res.rx_ampdu_accept = RX_AMPDU_ACCEPT_INVALID; - pmlmeext->sitesurvey_res.rx_ampdu_size = RX_AMPDU_SIZE_INVALID; -#ifdef CONFIG_SCAN_BACKOP - mlmeext_assign_scan_backop_flags_sta(pmlmeext, /*SS_BACKOP_EN|*/SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME); - #ifdef CONFIG_AP_MODE - mlmeext_assign_scan_backop_flags_ap(pmlmeext, SS_BACKOP_EN | SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME); - #endif - #ifdef CONFIG_RTW_MESH - mlmeext_assign_scan_backop_flags_mesh(pmlmeext, /*SS_BACKOP_EN | */SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME); - #endif - pmlmeext->sitesurvey_res.scan_cnt = 0; - pmlmeext->sitesurvey_res.scan_cnt_max = RTW_SCAN_NUM_OF_CH; - pmlmeext->sitesurvey_res.backop_ms = RTW_BACK_OP_CH_MS; -#endif -#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL) - pmlmeext->sitesurvey_res.is_sw_antdiv_bl_scan = 0; -#endif - pmlmeext->scan_abort = _FALSE; - - pmlmeinfo->state = WIFI_FW_NULL_STATE; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeinfo->auth_seq = 0; - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - pmlmeinfo->key_index = 0; - pmlmeinfo->iv = 0; - - pmlmeinfo->enc_algo = _NO_PRIVACY_; - pmlmeinfo->authModeToggle = 0; - - _rtw_memset(pmlmeinfo->chg_txt, 0, 128); - - pmlmeinfo->slotTime = SHORT_SLOT_TIME; - pmlmeinfo->preamble_mode = PREAMBLE_AUTO; - - pmlmeinfo->dialogToken = 0; - - pmlmeext->action_public_rxseq = 0xffff; - pmlmeext->action_public_dialog_token = 0xff; -#ifdef ROKU_PRIVATE -/*infra mode, used to store AP's info*/ - _rtw_memset(pmlmeinfo->SupportedRates_infra_ap, 0, NDIS_802_11_LENGTH_RATES_EX); - pmlmeinfo->ht_vht_received = 0; -#endif /* ROKU_PRIVATE */ -} - -void init_mlme_ext_timer(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - rtw_init_timer(&pmlmeext->survey_timer, padapter, survey_timer_hdl, padapter); - rtw_init_timer(&pmlmeext->link_timer, padapter, link_timer_hdl, padapter); -#ifdef CONFIG_RTW_80211R - rtw_init_timer(&pmlmeext->ft_link_timer, padapter, rtw_ft_link_timer_hdl, padapter); - rtw_init_timer(&pmlmeext->ft_roam_timer, padapter, rtw_ft_roam_timer_hdl, padapter); -#endif - -#ifdef CONFIG_RTW_REPEATER_SON - rtw_init_timer(&pmlmeext->rson_scan_timer, padapter, rson_timer_hdl, padapter); -#endif -} - -int init_mlme_ext_priv(_adapter *padapter) -{ - int res = _SUCCESS; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - /* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */ - /* _rtw_memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv)); */ - - pmlmeext->padapter = padapter; - - /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */ - - init_mlme_ext_priv_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; - - init_mlme_ext_timer(padapter); - -#ifdef CONFIG_AP_MODE - init_mlme_ap_info(padapter); -#endif - - pmlmeext->last_scan_time = 0; - pmlmeext->mlmeext_init = _TRUE; - - -#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - pmlmeext->active_keep_alive_check = _TRUE; -#else - pmlmeext->active_keep_alive_check = _FALSE; -#endif - -#ifdef DBG_FIXED_CHAN - pmlmeext->fixed_chan = 0xFF; -#endif - - pmlmeext->tsf_update_pause_factor = pregistrypriv->tsf_update_pause_factor; - pmlmeext->tsf_update_restore_factor = pregistrypriv->tsf_update_restore_factor; - -#ifdef CONFIG_SUPPORT_STATIC_SMPS - pmlmeext->ssmps_en = _FALSE; - pmlmeext->ssmps_tx_tp_th = SSMPS_TX_TP_TH;/*Mbps*/ - pmlmeext->ssmps_rx_tp_th = SSMPS_RX_TP_TH;/*Mbps*/ - #ifdef DBG_STATIC_SMPS - pmlmeext->ssmps_test = _FALSE; - #endif -#endif - -#ifdef CONFIG_CTRL_TXSS_BY_TP - pmlmeext->txss_ctrl_en = _TRUE; - pmlmeext->txss_tp_th = TXSS_TP_TH; - pmlmeext->txss_tp_chk_cnt = TXSS_TP_CHK_CNT; -#endif - - return res; - -} - -void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) -{ - _adapter *padapter = pmlmeext->padapter; - - if (!padapter) - return; - - if (rtw_is_drv_stopped(padapter)) { - _cancel_timer_ex(&pmlmeext->survey_timer); - _cancel_timer_ex(&pmlmeext->link_timer); - } -} - -#ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL -static u8 cmp_pkt_chnl_diff(_adapter *padapter, u8 *pframe, uint packet_len) -{ - /* if the channel is same, return 0. else return channel differential */ - uint len; - u8 channel; - u8 *p; - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, packet_len - _BEACON_IE_OFFSET_); - if (p) { - channel = *(p + 2); - if (padapter->mlmeextpriv.cur_channel >= channel) - return padapter->mlmeextpriv.cur_channel - channel; - else - return channel - padapter->mlmeextpriv.cur_channel; - } else - return 0; -} -#endif /* CONFIG_PATCH_JOIN_WRONG_CHANNEL */ - -static void _mgt_dispatcher(_adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame) -{ - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 *pframe = precv_frame->u.hdr.rx_data; - - if (ptable->func) { - /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ - if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) && - !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - { - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); - - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) != _TRUE) - return; - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE) - return; - - if ( pwdev_priv->pno_mac_addr[0] == 0xFF) - return; - - if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_pno_mac_addr(padapter), ETH_ALEN)) - return; - } -#else - return; -#endif - - ptable->func(padapter, precv_frame); - } - -} - -void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame) -{ - int index; - struct mlme_handler *ptable; - u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 *pframe = precv_frame->u.hdr.rx_data; - struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, get_addr2_ptr(pframe)); - struct recv_priv *precvpriv = &padapter->recvpriv; - - -#if 0 - { - u8 *pbuf; - pbuf = GetAddr1Ptr(pframe); - RTW_INFO("A1-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5)); - pbuf = get_addr2_ptr(pframe); - RTW_INFO("A2-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5)); - pbuf = GetAddr3Ptr(pframe); - RTW_INFO("A3-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5)); - } -#endif - - if (GetFrameType(pframe) != WIFI_MGT_TYPE) { - return; - } - - /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ - if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) && - !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - { - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); - - if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) != _TRUE) - return; - - if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE) - return; - - if ( pwdev_priv->pno_mac_addr[0] == 0xFF) - return; - - if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_pno_mac_addr(padapter), ETH_ALEN)) - return; - } -#else - return; -#endif - - ptable = mlme_sta_tbl; - - index = get_frame_sub_type(pframe) >> 4; - -#ifdef CONFIG_TDLS - if ((index << 4) == WIFI_ACTION) { - /* category==public (4), action==TDLS_DISCOVERY_RESPONSE */ - if (*(pframe + 24) == RTW_WLAN_CATEGORY_PUBLIC && *(pframe + 25) == TDLS_DISCOVERY_RESPONSE) { - RTW_INFO("[TDLS] Recv %s from "MAC_FMT"\n", rtw_tdls_action_txt(TDLS_DISCOVERY_RESPONSE), MAC_ARG(get_addr2_ptr(pframe))); - On_TDLS_Dis_Rsp(padapter, precv_frame); - } - } -#endif /* CONFIG_TDLS */ - - if (index >= (sizeof(mlme_sta_tbl) / sizeof(struct mlme_handler))) { - return; - } - ptable += index; - -#if 1 - if (psta != NULL) { - if (GetRetry(pframe)) { - if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) { - /* drop the duplicate management frame */ - precvpriv->dbg_rx_dup_mgt_frame_drop_count++; - RTW_INFO("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num); - return; - } - } - psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num; - } -#else - - if (GetRetry(pframe)) { - /* return; */ - } -#endif - -#ifdef CONFIG_AP_MODE - switch (get_frame_sub_type(pframe)) { - case WIFI_AUTH: - if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) { - ptable->func = &OnAuth; - } else - ptable->func = &OnAuthClient; - /* Intentional fallthrough */ - case WIFI_ASSOCREQ: - case WIFI_REASSOCREQ: - _mgt_dispatcher(padapter, ptable, precv_frame); - #ifdef CONFIG_HOSTAPD_MLME - if (MLME_IS_AP(padapter)) - rtw_hostapd_mlme_rx(padapter, precv_frame); - #endif - break; - case WIFI_PROBEREQ: - _mgt_dispatcher(padapter, ptable, precv_frame); - #ifdef CONFIG_HOSTAPD_MLME - if (MLME_IS_AP(padapter)) - rtw_hostapd_mlme_rx(padapter, precv_frame); - #endif - break; - case WIFI_BEACON: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; - case WIFI_ACTION: - _mgt_dispatcher(padapter, ptable, precv_frame); - break; - default: - _mgt_dispatcher(padapter, ptable, precv_frame); - #ifdef CONFIG_HOSTAPD_MLME - if (MLME_IS_AP(padapter)) - rtw_hostapd_mlme_rx(padapter, precv_frame); - #endif - break; - } -#else - - _mgt_dispatcher(padapter, ptable, precv_frame); - -#endif - -} - -#ifdef CONFIG_P2P -u32 p2p_listen_state_process(_adapter *padapter, unsigned char *da) -{ - bool response = _TRUE; - -#ifdef CONFIG_IOCTL_CFG80211 - if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) { - if (rtw_cfg80211_get_is_roch(padapter) == _FALSE - || rtw_get_oper_ch(padapter) != padapter->wdinfo.listen_channel - || adapter_wdev_data(padapter)->p2p_enabled == _FALSE - || padapter->mlmepriv.wps_probe_resp_ie == NULL - || padapter->mlmepriv.p2p_probe_resp_ie == NULL - ) { -#ifdef CONFIG_DEBUG_CFG80211 - RTW_INFO(ADPT_FMT" DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n" - , ADPT_ARG(padapter) - , adapter_wdev_data(padapter)->p2p_enabled - , padapter->mlmepriv.wps_probe_resp_ie - , padapter->mlmepriv.p2p_probe_resp_ie); - RTW_INFO(ADPT_FMT" DON'T issue_probersp_p2p: is_ro_ch:%d, op_ch:%d, p2p_listen_channel:%d\n" - , ADPT_ARG(padapter) - , rtw_cfg80211_get_is_roch(padapter) - , rtw_get_oper_ch(padapter) - , padapter->wdinfo.listen_channel); -#endif - response = _FALSE; - } - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - if (padapter->wdinfo.driver_interface == DRIVER_WEXT) { - /* do nothing if the device name is empty */ - if (!padapter->wdinfo.device_name_len) - response = _FALSE; - } - - if (response == _TRUE) - issue_probersp_p2p(padapter, da); - - return _SUCCESS; -} -#endif /* CONFIG_P2P */ - - -/**************************************************************************** - -Following are the callback functions for each subtype of the management frames - -*****************************************************************************/ - -unsigned int OnProbeReq(_adapter *padapter, union recv_frame *precv_frame) -{ - unsigned int ielen; - unsigned char *p; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *cur = &(pmlmeinfo->network); - u8 *pframe = precv_frame->u.hdr.rx_data; - uint len = precv_frame->u.hdr.len; - u8 is_valid_p2p_probereq = _FALSE; - -#ifdef CONFIG_ATMEL_RC_PATCH - u8 *target_ie = NULL, *wps_ie = NULL; - u8 *start; - uint search_len = 0, wps_ielen = 0, target_ielen = 0; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; -#endif - - -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; - u8 wifi_test_chk_rate = 1; - -#ifdef CONFIG_IOCTL_CFG80211 - if ((pwdinfo->driver_interface == DRIVER_CFG80211) - && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) - && (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_PROBE_REQ) == _TRUE) - ) { - rtw_cfg80211_rx_probe_request(padapter, precv_frame); - return _SUCCESS; - } -#endif /* CONFIG_IOCTL_CFG80211 */ - - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && - !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) && - !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && - !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) && - !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) - ) { - /* Commented by Albert 2011/03/17 */ - /* mcs_rate = 0->CCK 1M rate */ - /* mcs_rate = 1->CCK 2M rate */ - /* mcs_rate = 2->CCK 5.5M rate */ - /* mcs_rate = 3->CCK 11M rate */ - /* In the P2P mode, the driver should not support the CCK rate */ - - /* Commented by Kurt 2012/10/16 */ - /* IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */ - if (padapter->registrypriv.wifi_spec == 1) { - if (pattrib->data_rate <= DESC_RATE11M) - wifi_test_chk_rate = 0; - } - - if (wifi_test_chk_rate == 1) { - is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len); - if (is_valid_p2p_probereq == _TRUE) { - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) { - /* FIXME */ - if (padapter->wdinfo.driver_interface == DRIVER_WEXT) - report_survey_event(padapter, precv_frame); - - p2p_listen_state_process(padapter, get_sa(pframe)); - - return _SUCCESS; - } - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) - goto _continue; - } - } - } - -_continue: -#endif /* CONFIG_P2P */ - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) - return _SUCCESS; - - if (check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE && - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE | WIFI_MESH_STATE) == _FALSE) - return _SUCCESS; - - - /* RTW_INFO("+OnProbeReq\n"); */ - - -#ifdef CONFIG_ATMEL_RC_PATCH - wps_ie = rtw_get_wps_ie( - pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_, - NULL, &wps_ielen); - if (wps_ie) - target_ie = rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_MANUFACTURER, NULL, &target_ielen); - if ((target_ie && (target_ielen == 4)) && (_TRUE == _rtw_memcmp((void *)target_ie, "Ozmo", 4))) { - /* psta->flag_atmel_rc = 1; */ - unsigned char *sa_addr = get_sa(pframe); - printk("%s: Find Ozmo RC -- %02x:%02x:%02x:%02x:%02x:%02x \n\n", - __func__, *sa_addr, *(sa_addr + 1), *(sa_addr + 2), *(sa_addr + 3), *(sa_addr + 4), *(sa_addr + 5)); - _rtw_memcpy(pstapriv->atmel_rc_pattern, get_sa(pframe), ETH_ALEN); - } -#endif - - -#ifdef CONFIG_AUTO_AP_MODE - if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE && - pmlmepriv->cur_network.join_res == _TRUE) { - _irqL irqL; - struct sta_info *psta; - u8 *mac_addr, *peer_addr; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A}; - /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */ - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); - - if (!p || ielen != 14) - goto _non_rc_device; - - if (!_rtw_memcmp(p + 2, RC_OUI, sizeof(RC_OUI))) - goto _non_rc_device; - - if (!_rtw_memcmp(p + 6, get_sa(pframe), ETH_ALEN)) { - RTW_INFO("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __FUNCTION__, - MAC_ARG(get_sa(pframe)), MAC_ARG(p + 6)); - - goto _non_rc_device; - } - - RTW_INFO("%s, got the pairing device("MAC_FMT")\n", __FUNCTION__, MAC_ARG(get_sa(pframe))); - - /* new a station */ - psta = rtw_get_stainfo(pstapriv, get_sa(pframe)); - if (psta == NULL) { - /* allocate a new one */ - RTW_INFO("going to alloc stainfo for rc="MAC_FMT"\n", MAC_ARG(get_sa(pframe))); - psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe)); - if (psta == NULL) { - /* TODO: */ - RTW_INFO(" Exceed the upper limit of supported clients...\n"); - return _SUCCESS; - } - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - if (rtw_is_list_empty(&psta->asoc_list)) { - psta->expire_to = pstapriv->expire_to; - rtw_list_insert_tail(&psta->asoc_list, &pstapriv->asoc_list); - pstapriv->asoc_list_cnt++; - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - /* generate pairing ID */ - mac_addr = adapter_mac_addr(padapter); - peer_addr = psta->cmn.mac_addr; - psta->pid = (u16)(((mac_addr[4] << 8) + mac_addr[5]) + ((peer_addr[4] << 8) + peer_addr[5])); - - /* update peer stainfo */ - psta->isrc = _TRUE; - - /* AID assignment */ - if (psta->cmn.aid > 0) - RTW_INFO(FUNC_ADPT_FMT" old AID=%d\n", FUNC_ADPT_ARG(padapter), psta->cmn.aid); - else { - if (!rtw_aid_alloc(padapter, psta)) { - RTW_INFO(FUNC_ADPT_FMT" no room for more AIDs\n", FUNC_ADPT_ARG(padapter)); - return _SUCCESS; - } - RTW_INFO(FUNC_ADPT_FMT" allocate new AID=%d\n", FUNC_ADPT_ARG(padapter), psta->cmn.aid); - } - - psta->qos_option = 1; - psta->cmn.bw_mode = CHANNEL_WIDTH_20; - psta->ieee8021x_blocked = _FALSE; -#ifdef CONFIG_80211N_HT - if(padapter->registrypriv.ht_enable && - is_supported_ht(padapter->registrypriv.wireless_mode)) { - psta->htpriv.ht_option = _TRUE; - psta->htpriv.ampdu_enable = _FALSE; - psta->htpriv.sgi_20m = _FALSE; - psta->htpriv.sgi_40m = _FALSE; - psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ - } -#endif - - rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE); - - _rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - - _enter_critical_bh(&psta->lock, &irqL); - psta->state |= _FW_LINKED; - _exit_critical_bh(&psta->lock, &irqL); - - report_add_sta_event(padapter, psta->cmn.mac_addr); - - } - - issue_probersp(padapter, get_sa(pframe), _FALSE); - - return _SUCCESS; - - } - -_non_rc_device: - - return _SUCCESS; - -#endif /* CONFIG_AUTO_AP_MODE */ - - -#ifdef CONFIG_CONCURRENT_MODE - if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) && - rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) { - /* don't process probe req */ - return _SUCCESS; - } -#endif - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); - - - /* check (wildcard) SSID */ - if (p != NULL) { - if (is_valid_p2p_probereq == _TRUE) - goto _issue_probersp; - - if ((ielen != 0 && _FALSE == _rtw_memcmp((void *)(p + 2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) - || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)) - goto exit; - - #ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) { - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_MESH_ID, (int *)&ielen, - len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); - - if (!p) - goto exit; - if (ielen != 0 && _rtw_memcmp((void *)(p + 2), (void *)cur->mesh_id.Ssid, cur->mesh_id.SsidLength) == _FALSE) - goto exit; - } - #endif - -_issue_probersp: - if (((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE && - pmlmepriv->cur_network.join_res == _TRUE)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - /* RTW_INFO("+issue_probersp during ap mode\n"); */ - issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); - } - - } - -exit: - return _SUCCESS; - -} - -unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - u8 *pframe = precv_frame->u.hdr.rx_data; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; -#endif - - -#ifdef CONFIG_P2P - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) { - if (_TRUE == pwdinfo->tx_prov_disc_info.benable) { - if (_rtw_memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, get_addr2_ptr(pframe), ETH_ALEN)) { - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { - pwdinfo->tx_prov_disc_info.benable = _FALSE; - issue_p2p_provision_request(padapter, - pwdinfo->tx_prov_disc_info.ssid.Ssid, - pwdinfo->tx_prov_disc_info.ssid.SsidLength, - pwdinfo->tx_prov_disc_info.peerDevAddr); - } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - pwdinfo->tx_prov_disc_info.benable = _FALSE; - issue_p2p_provision_request(padapter, - NULL, - 0, - pwdinfo->tx_prov_disc_info.peerDevAddr); - } - } - } - return _SUCCESS; - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) { - if (_TRUE == pwdinfo->nego_req_info.benable) { - RTW_INFO("[%s] P2P State is GONEGO ING!\n", __FUNCTION__); - if (_rtw_memcmp(pwdinfo->nego_req_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN)) { - pwdinfo->nego_req_info.benable = _FALSE; - issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr); - } - } - } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) { - if (_TRUE == pwdinfo->invitereq_info.benable) { - RTW_INFO("[%s] P2P_STATE_TX_INVITE_REQ!\n", __FUNCTION__); - if (_rtw_memcmp(pwdinfo->invitereq_info.peer_macaddr, get_addr2_ptr(pframe), ETH_ALEN)) { - pwdinfo->invitereq_info.benable = _FALSE; - issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr); - } - } - } -#endif - - - if ((mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS)) - || (MLME_IS_MESH(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) - #ifdef CONFIG_RTW_REPEATER_SON - || (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS) - #endif - ) { - rtw_mi_report_survey_event(padapter, precv_frame); - return _SUCCESS; - } - -#if 0 /* move to validate_recv_mgnt_frame */ - if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta != NULL) - psta->sta_stats.rx_mgnt_pkts++; - } - } -#endif - - return _SUCCESS; - -} - -/* for 11n Logo 4.2.31/4.2.32 */ -static void rtw_check_legacy_ap(_adapter *padapter, u8 *pframe, u32 len) -{ - - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (!padapter->registrypriv.wifi_spec) - return; - - if(!MLME_IS_AP(padapter)) - return; - - - if (pmlmeext->bstart_bss == _TRUE) { - int left; - unsigned char *pos; - struct rtw_ieee802_11_elems elems; -#ifdef CONFIG_80211N_HT - u16 cur_op_mode; -#endif - /* checking IEs */ - left = len - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_; - pos = pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_; - if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) { - RTW_INFO("%s: parse fail for "MAC_FMT"\n", __func__, MAC_ARG(GetAddr3Ptr(pframe))); - return; - } -#ifdef CONFIG_80211N_HT - cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; -#endif - /* for legacy ap */ - if (elems.ht_capabilities == NULL && elems.ht_capabilities_len == 0) { - - if (0) - RTW_INFO("%s: "MAC_FMT" is legacy ap\n", __func__, MAC_ARG(GetAddr3Ptr(pframe))); - - ATOMIC_SET(&pmlmepriv->olbc, _TRUE); - ATOMIC_SET(&pmlmepriv->olbc_ht, _TRUE); - } - - } -} - -unsigned int OnBeacon(_adapter *padapter, union recv_frame *precv_frame) -{ - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->u.hdr.rx_data; - uint len = precv_frame->u.hdr.len; - WLAN_BSSID_EX *pbss; - int ret = _SUCCESS; -#ifdef CONFIG_TDLS - struct sta_info *ptdls_sta; - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; -#ifdef CONFIG_TDLS_CH_SW - struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info; -#endif -#endif /* CONFIG_TDLS */ - - if (validate_beacon_len(pframe, len) == _FALSE) - return _SUCCESS; - - if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS) - || (MLME_IS_MESH(padapter) && check_fwstate(pmlmepriv, WIFI_ASOC_STATE)) - ) { - rtw_mi_report_survey_event(padapter, precv_frame); - return _SUCCESS; - } -#ifdef CONFIG_RTW_REPEATER_SON - if (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS) - rtw_mi_report_survey_event(padapter, precv_frame); -#endif - - rtw_check_legacy_ap(padapter, pframe, len); - - if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { - if ((pmlmeinfo->state & WIFI_FW_AUTH_NULL) - && (rtw_sta_linking_test_wait_done() || pmlmeext->join_abort) - ) { - if (rtw_sta_linking_test_force_fail() || pmlmeext->join_abort) { - set_link_timer(pmlmeext, 1); - return _SUCCESS; - } - - /* we should update current network before auth, or some IE is wrong */ - pbss = (WLAN_BSSID_EX *)rtw_malloc(sizeof(WLAN_BSSID_EX)); - if (pbss) { - if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { - struct beacon_keys recv_beacon; - - update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE); - - /* update bcn keys */ - if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) { - RTW_INFO("%s: beacon keys ready\n", __func__); - _rtw_memcpy(&pmlmepriv->cur_beacon_keys, - &recv_beacon, sizeof(recv_beacon)); - } else { - RTW_ERR("%s: get beacon keys failed\n", __func__); - _rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon)); - } - #ifdef CONFIG_BCN_CNT_CONFIRM_HDL - pmlmepriv->new_beacon_cnts = 0; - #endif - } - rtw_mfree((u8 *)pbss, sizeof(WLAN_BSSID_EX)); - } - - /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct rtw_ieee80211_hdr_3addr), len - sizeof(struct rtw_ieee80211_hdr_3addr)); - - /* update TSF Value */ - update_TSF(pmlmeext, pframe, len); - pmlmeext->bcn_cnt = 0; - pmlmeext->last_bcn_cnt = 0; - -#ifdef CONFIG_P2P_PS - /* Comment by YiWei , in wifi p2p spec the "3.3 P2P Power Management" , "These mechanisms are available in a P2P Group in which only P2P Devices are associated." */ - /* process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)); */ -#endif /* CONFIG_P2P_PS */ - -#if defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE) - if (padapter->registrypriv.wifi_spec) { - if (process_p2p_cross_connect_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)) == _FALSE) { - if (rtw_mi_buddy_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) { - RTW_PRINT("no issue auth, P2P cross-connect does not permit\n "); - return _SUCCESS; - } - } - } -#endif /* CONFIG_P2P CONFIG_P2P and CONFIG_CONCURRENT_MODE */ - - /* start auth */ - start_clnt_auth(padapter); - - return _SUCCESS; - } - - if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta != NULL) { -#ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL - /* Merge from 8712 FW code */ - if (cmp_pkt_chnl_diff(padapter, pframe, len) != 0) { - /* join wrong channel, deauth and reconnect */ - issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING); - - report_del_sta_event(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_JOIN_WRONG_CHANNEL, _TRUE, _FALSE); - pmlmeinfo->state &= (~WIFI_FW_ASSOC_SUCCESS); - return _SUCCESS; - } -#endif /* CONFIG_PATCH_JOIN_WRONG_CHANNEL */ -#ifdef CONFIG_RTW_80211R - rtw_ft_update_bcn(padapter, precv_frame); -#endif - ret = rtw_check_bcn_info(padapter, pframe, len); - if (!ret) { - RTW_PRINT("ap has changed, disconnect now\n "); - receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 0, _FALSE); - return _SUCCESS; - } - /* update WMM, ERP in the beacon */ - /* todo: the timer is used instead of the number of the beacon received */ - if ((sta_rx_pkts(psta) & 0xf) == 0) { - /* RTW_INFO("update_bcn_info\n"); */ - update_beacon_info(padapter, pframe, len, psta); - } - - pmlmepriv->cur_network_scanned->network.Rssi = precv_frame->u.hdr.attrib.phy_info.recv_signal_power; - pmlmeext->bcn_cnt++; -#ifdef CONFIG_BCN_RECV_TIME - rtw_rx_bcn_time_update(padapter, len, precv_frame->u.hdr.attrib.data_rate); -#endif -#ifdef CONFIG_TDLS -#ifdef CONFIG_TDLS_CH_SW - if (rtw_tdls_is_chsw_allowed(padapter) == _TRUE) { - /* Send TDLS Channel Switch Request when receiving Beacon */ - if ((padapter->tdlsinfo.chsw_info.ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) && (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) - && (pmlmeext->cur_channel == rtw_get_oper_ch(padapter))) { - ptdls_sta = rtw_get_stainfo(&padapter->stapriv, padapter->tdlsinfo.chsw_info.addr); - if (ptdls_sta != NULL) { - if (ptdls_sta->tdls_sta_state | TDLS_LINKED_STATE) - _set_timer(&ptdls_sta->stay_on_base_chnl_timer, TDLS_CH_SW_STAY_ON_BASE_CHNL_TIMEOUT); - } - } - } -#endif -#endif /* CONFIG_TDLS */ - - #ifdef CONFIG_DFS - process_csa_ie(padapter - , pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_ - , len - (WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_)); - #endif - -#ifdef CONFIG_P2P_PS - process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)); -#endif /* CONFIG_P2P_PS */ - - if (pmlmeext->tsf_update_required && pmlmeext->en_hw_update_tsf) - rtw_enable_hw_update_tsf_cmd(padapter); - -#if 0 /* move to validate_recv_mgnt_frame */ - psta->sta_stats.rx_mgnt_pkts++; -#endif - } - - } else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - u8 rate_set[16]; - u8 rate_num = 0; - - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta != NULL) { - /* - * update WMM, ERP in the beacon - * todo: the timer is used instead of the number of the beacon received - */ - if ((sta_rx_pkts(psta) & 0xf) == 0) - update_beacon_info(padapter, pframe, len, psta); - - if (pmlmeext->tsf_update_required && pmlmeext->en_hw_update_tsf) - rtw_enable_hw_update_tsf_cmd(padapter); - } else { - rtw_ies_get_supported_rate(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_, rate_set, &rate_num); - if (rate_num == 0) { - RTW_INFO(FUNC_ADPT_FMT" RX beacon with no supported rate\n", FUNC_ADPT_ARG(padapter)); - goto _END_ONBEACON_; - } - - psta = rtw_alloc_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta == NULL) { - RTW_INFO(FUNC_ADPT_FMT" Exceed the upper limit of supported clients\n", FUNC_ADPT_ARG(padapter)); - goto _END_ONBEACON_; - } - - psta->expire_to = pstapriv->adhoc_expire_to; - - _rtw_memcpy(psta->bssrateset, rate_set, rate_num); - psta->bssratelen = rate_num; - - /* update TSF Value */ - update_TSF(pmlmeext, pframe, len); - - /* report sta add event */ - report_add_sta_event(padapter, get_addr2_ptr(pframe)); - } - } - } - -_END_ONBEACON_: - - return _SUCCESS; - -} - -unsigned int OnAuth(_adapter *padapter, union recv_frame *precv_frame) -{ -#ifdef CONFIG_AP_MODE - _irqL irqL; - unsigned int auth_mode, seq, ie_len; - unsigned char *sa, *p; - u16 algorithm; - int status; - static struct sta_info stat; - struct sta_info *pstat = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->u.hdr.rx_data; - uint len = precv_frame->u.hdr.len; - u8 offset = 0; - - -#ifdef CONFIG_CONCURRENT_MODE - if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) && - rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) { - /* don't process auth request; */ - return _SUCCESS; - } -#endif /* CONFIG_CONCURRENT_MODE */ - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - return _FAIL; - - if (!MLME_IS_ASOC(padapter)) - return _SUCCESS; - -#if defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_RTW_MESH) - if (MLME_IS_MESH(padapter)) - return rtw_mesh_on_auth(padapter, precv_frame); -#endif - - RTW_INFO("+OnAuth\n"); - - sa = get_addr2_ptr(pframe); - - auth_mode = psecuritypriv->dot11AuthAlgrthm; - - if (GetPrivacy(pframe)) { - u8 *iv; - struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib); - - prxattrib->hdrlen = WLAN_HDR_A3_LEN; - prxattrib->encrypt = _WEP40_; - - iv = pframe + prxattrib->hdrlen; - prxattrib->key_index = ((iv[3] >> 6) & 0x3); - - prxattrib->iv_len = 4; - prxattrib->icv_len = 4; - - rtw_wep_decrypt(padapter, (u8 *)precv_frame); - - offset = 4; - } - - algorithm = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset)); - seq = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); - - RTW_INFO("auth alg=%x, seq=%X\n", algorithm, seq); - - if (rtw_ap_linking_test_force_auth_fail()) { - status = rtw_ap_linking_test_force_auth_fail(); - RTW_INFO(FUNC_ADPT_FMT" force auth fail with status:%u\n" - , FUNC_ADPT_ARG(padapter), status); - goto auth_fail; - } - - if ((auth_mode == 2) && (algorithm != WLAN_AUTH_SAE) && - (psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && - (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)) - auth_mode = 0; - - if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ - (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ - RTW_INFO("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n", - algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); - - status = _STATS_NO_SUPP_ALG_; - - goto auth_fail; - } - -#if CONFIG_RTW_MACADDR_ACL - if (rtw_access_ctrl(padapter, sa) == _FALSE) { - status = _STATS_UNABLE_HANDLE_STA_; - goto auth_fail; - } -#endif - - pstat = rtw_get_stainfo(pstapriv, sa); - if (pstat == NULL) { - - /* allocate a new one */ - RTW_INFO("going to alloc stainfo for sa="MAC_FMT"\n", MAC_ARG(sa)); - pstat = rtw_alloc_stainfo(pstapriv, sa); - if (pstat == NULL) { - RTW_INFO(" Exceed the upper limit of supported clients...\n"); - status = _STATS_UNABLE_HANDLE_STA_; - goto auth_fail; - } - - pstat->state = WIFI_FW_AUTH_NULL; - pstat->auth_seq = 0; - - /* pstat->flags = 0; */ - /* pstat->capability = 0; */ - } else { -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) -#endif /* CONFIG_IEEE80211W */ - { - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - if (rtw_is_list_empty(&pstat->asoc_list) == _FALSE) { - rtw_list_delete(&pstat->asoc_list); - pstapriv->asoc_list_cnt--; - if (pstat->expire_to > 0) - ;/* TODO: STA re_auth within expire_to */ - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - if (seq == 1) { - ; /* TODO: STA re_auth and auth timeout */ - - } - } - } - -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) -#endif /* CONFIG_IEEE80211W */ - { - _enter_critical_bh(&pstapriv->auth_list_lock, &irqL); - if (rtw_is_list_empty(&pstat->auth_list)) { - - rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list); - pstapriv->auth_list_cnt++; - } - _exit_critical_bh(&pstapriv->auth_list_lock, &irqL); - } - - if (pstat->auth_seq == 0) - pstat->expire_to = pstapriv->auth_to; - -#ifdef CONFIG_IOCTL_CFG80211 - if (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_AUTH) == _TRUE) { - if ((algorithm == WLAN_AUTH_SAE) && - (auth_mode == dot11AuthAlgrthm_8021X)) { - pstat->authalg = algorithm; - - rtw_cfg80211_rx_mframe(padapter, precv_frame, NULL); - return _SUCCESS; - } - } -#endif /* CONFIG_IOCTL_CFG80211 */ - - if ((pstat->auth_seq + 1) != seq) { - RTW_INFO("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq + 1); - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - - if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) { - if (seq == 1) { -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) -#endif /* CONFIG_IEEE80211W */ - { - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_SUCCESS; - pstat->expire_to = pstapriv->assoc_to; - } - pstat->authalg = algorithm; - } else { - RTW_INFO("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq + 1); - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - } else { /* shared system or auto authentication */ - if (seq == 1) { - /* prepare for the challenging txt... */ - - /* get_random_bytes((void *)pstat->chg_txt, 128); */ /* TODO: */ - _rtw_memset((void *)pstat->chg_txt, 78, 128); -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) -#endif /* CONFIG_IEEE80211W */ - { - pstat->state &= ~WIFI_FW_AUTH_NULL; - pstat->state |= WIFI_FW_AUTH_STATE; - } - pstat->authalg = algorithm; - pstat->auth_seq = 2; - } else if (seq == 3) { - /* checking for challenging txt... */ - RTW_INFO("checking for challenging txt...\n"); - - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len, - len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); - - if ((p == NULL) || (ie_len <= 0)) { - RTW_INFO("auth rejected because challenge failure!(1)\n"); - status = _STATS_CHALLENGE_FAIL_; - goto auth_fail; - } - - if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128)) { -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) -#endif /* CONFIG_IEEE80211W */ - { - pstat->state &= (~WIFI_FW_AUTH_STATE); - pstat->state |= WIFI_FW_AUTH_SUCCESS; - /* challenging txt is correct... */ - pstat->expire_to = pstapriv->assoc_to; - } - } else { - RTW_INFO("auth rejected because challenge failure!\n"); - status = _STATS_CHALLENGE_FAIL_; - goto auth_fail; - } - } else { - RTW_INFO("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n", - seq, pstat->auth_seq + 1); - status = _STATS_OUT_OF_AUTH_SEQ_; - goto auth_fail; - } - } - - - /* Now, we are going to issue_auth... */ - pstat->auth_seq = seq + 1; - -#ifdef CONFIG_NATIVEAP_MLME - issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_)); -#endif - - if ((pstat->state & WIFI_FW_AUTH_SUCCESS) || (pstat->state & WIFI_FW_ASSOC_SUCCESS)) - pstat->auth_seq = 0; - - - return _SUCCESS; - -auth_fail: - - if (pstat) - rtw_free_stainfo(padapter , pstat); - - pstat = &stat; - _rtw_memset((char *)pstat, '\0', sizeof(stat)); - pstat->auth_seq = 2; - _rtw_memcpy(pstat->cmn.mac_addr, sa, ETH_ALEN); - -#ifdef CONFIG_NATIVEAP_MLME - issue_auth(padapter, pstat, (unsigned short)status); -#endif - -#endif - return _FAIL; - -} - -unsigned int OnAuthClient(_adapter *padapter, union recv_frame *precv_frame) -{ - unsigned int seq, len, status, algthm, offset; - unsigned char *p; - unsigned int go2asoc = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->u.hdr.rx_data; - uint pkt_len = precv_frame->u.hdr.len; - - RTW_INFO("%s\n", __FUNCTION__); - -#ifdef CONFIG_IOCTL_CFG80211 - if (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_AUTH) == _TRUE) { - if (rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE)) { - if (rtw_cached_pmkid(padapter, get_my_bssid(&pmlmeinfo->network)) != -1) { - RTW_INFO("SAE: PMKSA cache entry found\n"); - goto normal; - } - rtw_cfg80211_rx_mframe(padapter, precv_frame, NULL); - return _SUCCESS; - } - } - -normal: -#endif /* CONFIG_IOCTL_CFG80211 */ - - /* check A1 matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN)) - return _SUCCESS; - - if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE) || pmlmeext->join_abort) - return _SUCCESS; - - offset = (GetPrivacy(pframe)) ? 4 : 0; - - algthm = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset)); - seq = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); - status = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4)); - - if (status != 0) { - RTW_INFO("clnt auth fail, status: %d\n", status); - if (status == 13) { /* && pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; - else - pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; - /* pmlmeinfo->reauth_count = 0; */ - } - - pmlmeinfo->auth_status = status; - set_link_timer(pmlmeext, 1); - goto authclnt_fail; - } - - if (seq == 2) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { - /* legendary shared system */ - p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, - pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); - - if (p == NULL) { - /* RTW_INFO("marc: no challenge text?\n"); */ - goto authclnt_fail; - } - - _rtw_memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); - pmlmeinfo->auth_seq = 3; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - - return _SUCCESS; - } else { - /* open, or 802.11r FTAA system */ - go2asoc = 1; - } - } else if (seq == 4) { - if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) - go2asoc = 1; - else - goto authclnt_fail; - } else { - /* this is also illegal */ - /* RTW_INFO("marc: clnt auth failed due to illegal seq=%x\n", seq); */ - goto authclnt_fail; - } - - if (go2asoc) { -#ifdef CONFIG_RTW_80211R - if (rtw_ft_update_auth_rsp_ies(padapter, pframe, pkt_len)) - return _SUCCESS; -#endif - RTW_PRINT("auth success, start assoc\n"); - start_clnt_assoc(padapter); - return _SUCCESS; - } - -authclnt_fail: - - /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */ - - return _FAIL; - -} - -unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame) -{ -#ifdef CONFIG_AP_MODE - _irqL irqL; - u16 listen_interval; - struct rtw_ieee802_11_elems elems; - struct sta_info *pstat; - unsigned char reassoc, *pos; - int left; - unsigned short status = _STATS_SUCCESSFUL_; - unsigned short frame_type, ie_offset = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *cur = &(pmlmeinfo->network); - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->u.hdr.rx_data; - uint pkt_len = precv_frame->u.hdr.len; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - u8 p2p_status_code = P2P_STATUS_SUCCESS; - u8 *p2pie; - u32 p2pielen = 0; -#endif /* CONFIG_P2P */ - -#ifdef CONFIG_CONCURRENT_MODE - if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) && - rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) { - /* don't process assoc request; */ - return _SUCCESS; - } -#endif /* CONFIG_CONCURRENT_MODE */ - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - return _FAIL; - - frame_type = get_frame_sub_type(pframe); - if (frame_type == WIFI_ASSOCREQ) { - reassoc = 0; - ie_offset = _ASOCREQ_IE_OFFSET_; - } else { /* WIFI_REASSOCREQ */ - reassoc = 1; - ie_offset = _REASOCREQ_IE_OFFSET_; - } - - - if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) { - RTW_INFO("handle_assoc(reassoc=%d) - too short payload (len=%lu)" - "\n", reassoc, (unsigned long)pkt_len); - return _FAIL; - } - - pstat = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (pstat == (struct sta_info *)NULL) { - status = _RSON_CLS2_; - goto asoc_class2_error; - } - - RTW_INFO("%s\n", __FUNCTION__); - - if (pstat->authalg == WLAN_AUTH_SAE) { - /* WPA3-SAE */ - if (((pstat->state) & WIFI_FW_AUTH_NULL)) { - /* TODO: - Queue AssocReq and Proccess - by external auth trigger. */ - RTW_INFO("%s: wait external auth trigger\n", __func__); - return _SUCCESS; - } - } - - /* check if this stat has been successfully authenticated/assocated */ - if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { - if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { - status = _RSON_CLS2_; - goto asoc_class2_error; - } else { - pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - } else { - pstat->state &= (~WIFI_FW_AUTH_SUCCESS); - pstat->state |= WIFI_FW_ASSOC_STATE; - } - -#if 0/* todo:tkip_countermeasures */ - if (hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } -#endif - - if (rtw_ap_linking_test_force_asoc_fail()) { - status = rtw_ap_linking_test_force_asoc_fail(); - RTW_INFO(FUNC_ADPT_FMT" force asoc fail with status:%u\n" - , FUNC_ADPT_ARG(padapter), status); - goto OnAssocReqFail; - } - - /* now parse all ieee802_11 ie to point to elems */ - left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset); - pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset); - if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) { - RTW_INFO("STA " MAC_FMT " sent invalid association request\n", - MAC_ARG(pstat->cmn.mac_addr)); - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } - - rtw_ap_parse_sta_capability(padapter, pstat, pframe + WLAN_HDR_A3_LEN); - - listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN + 2); -#if 0/* todo: */ - /* check listen_interval */ - if (listen_interval > hapd->conf->max_listen_interval) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Too large Listen Interval (%d)", - listen_interval); - resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE; - goto fail; - } - - pstat->listen_interval = listen_interval; -#endif - - /* now we should check all the fields... */ - /* checking SSID */ - if (elems.ssid == NULL - || elems.ssid_len == 0 - || elems.ssid_len != cur->Ssid.SsidLength - || _rtw_memcmp(elems.ssid, cur->Ssid.Ssid, cur->Ssid.SsidLength) == _FALSE - ) { - status = _STATS_FAILURE_; - goto OnAssocReqFail; - } - - /* (Extended) Supported rates */ - status = rtw_ap_parse_sta_supported_rates(padapter, pstat - , pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - if (status != _STATS_SUCCESSFUL_) - goto OnAssocReqFail; - - /* check RSN/WPA/WPS */ - status = rtw_ap_parse_sta_security_ie(padapter, pstat, &elems); - if (status != _STATS_SUCCESSFUL_) - goto OnAssocReqFail; - - /* check if there is WMM IE & support WWM-PS */ - rtw_ap_parse_sta_wmm_ie(padapter, pstat - , pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset); - -#ifdef CONFIG_RTS_FULL_BW - /*check vendor IE*/ - rtw_parse_sta_vendor_ie_8812(padapter, pstat - , pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset); -#endif/*CONFIG_RTS_FULL_BW*/ - - rtw_ap_parse_sta_ht_ie(padapter, pstat, &elems); - rtw_ap_parse_sta_vht_ie(padapter, pstat, &elems); - - if (((pstat->flags & WLAN_STA_HT) || (pstat->flags & WLAN_STA_VHT)) && - ((pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || - (pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP))) { - - RTW_INFO("(V)HT: " MAC_FMT " tried to use TKIP with (V)HT association\n", MAC_ARG(pstat->cmn.mac_addr)); - - pstat->flags &= ~WLAN_STA_HT; - pstat->flags &= ~WLAN_STA_VHT; - /*status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - * goto OnAssocReqFail; - */ - } - - if (status != _STATS_SUCCESSFUL_) - goto OnAssocReqFail; - -#ifdef CONFIG_P2P - pstat->is_p2p_device = _FALSE; - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen); - if (p2pie) { - pstat->is_p2p_device = _TRUE; - p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat); - if (p2p_status_code > 0) { - pstat->p2p_status_code = p2p_status_code; - status = _STATS_CAP_FAIL_; - goto OnAssocReqFail; - } - } -#ifdef CONFIG_WFD - rtw_process_wfd_ies(padapter, pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, __func__); -#endif - } - pstat->p2p_status_code = p2p_status_code; -#endif /* CONFIG_P2P */ - -#ifdef CONFIG_RTW_REPEATER_SON - if (rtw_rson_ap_check_sta(padapter, pframe, pkt_len, ie_offset)) - goto OnAssocReqFail; -#endif - - /* TODO: identify_proprietary_vendor_ie(); */ - /* Realtek proprietary IE */ - /* identify if this is Broadcom sta */ - /* identify if this is ralink sta */ - /* Customer proprietary IE */ - -#ifdef CONFIG_RTW_80211K - rtw_ap_parse_sta_rm_en_cap(padapter, pstat, &elems); -#endif - - /* AID assignment */ - if (pstat->cmn.aid > 0) - RTW_INFO(FUNC_ADPT_FMT" old AID=%d\n", FUNC_ADPT_ARG(padapter), pstat->cmn.aid); - else { - if (!rtw_aid_alloc(padapter, pstat)) { - RTW_INFO(FUNC_ADPT_FMT" no room for more AIDs\n", FUNC_ADPT_ARG(padapter)); - status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - goto OnAssocReqFail; - } - RTW_INFO(FUNC_ADPT_FMT" allocate new AID=%d\n", FUNC_ADPT_ARG(padapter), pstat->cmn.aid); - } - - pstat->state &= (~WIFI_FW_ASSOC_STATE); - pstat->state |= WIFI_FW_ASSOC_SUCCESS; - /* RTW_INFO("==================%s, %d, (%x), bpairwise_key_installed=%d, MAC:"MAC_FMT"\n" - , __func__, __LINE__, pstat->state, pstat->bpairwise_key_installed, MAC_ARG(pstat->cmn.mac_addr)); */ -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE) -#endif /* CONFIG_IEEE80211W */ - { - _enter_critical_bh(&pstapriv->auth_list_lock, &irqL); - if (!rtw_is_list_empty(&pstat->auth_list)) { - rtw_list_delete(&pstat->auth_list); - pstapriv->auth_list_cnt--; - } - _exit_critical_bh(&pstapriv->auth_list_lock, &irqL); - - _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); - if (rtw_is_list_empty(&pstat->asoc_list)) { - pstat->expire_to = pstapriv->expire_to; - rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list); - pstapriv->asoc_list_cnt++; - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - } - - /* now the station is qualified to join our BSS... */ - if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) { -#ifdef CONFIG_NATIVEAP_MLME -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE) -#endif /* CONFIG_IEEE80211W */ - { - /* .1 bss_cap_update & sta_info_update */ - bss_cap_update_on_sta_join(padapter, pstat); - sta_info_update(padapter, pstat); - } -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed == _TRUE) - status = _STATS_REFUSED_TEMPORARILY_; -#endif /* CONFIG_IEEE80211W */ - /* .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); - -#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; - } - - 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 /* CONFIG_IOCTL_CFG80211 */ -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed != _TRUE) -#endif /* CONFIG_IEEE80211W */ - { - /* .3-(1) report sta add event */ - report_add_sta_event(padapter, pstat->cmn.mac_addr); - } -#ifdef CONFIG_IEEE80211W - if (pstat->bpairwise_key_installed == _TRUE && SEC_IS_BIP_KEY_INSTALLED(&padapter->securitypriv) == _TRUE) { - RTW_INFO(MAC_FMT"\n", MAC_ARG(pstat->cmn.mac_addr)); - issue_action_SA_Query(padapter, pstat->cmn.mac_addr, 0, 0, IEEE80211W_RIGHT_KEY); - } -#endif /* CONFIG_IEEE80211W */ -#endif /* CONFIG_NATIVEAP_MLME */ - } - - return _SUCCESS; - -asoc_class2_error: - -#ifdef CONFIG_NATIVEAP_MLME - issue_deauth(padapter, (void *)get_addr2_ptr(pframe), status); -#endif - - return _FAIL; - -OnAssocReqFail: - - -#ifdef CONFIG_NATIVEAP_MLME - pstat->cmn.aid = 0; - if (frame_type == WIFI_ASSOCREQ) - issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); - else - issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); -#endif - - -#endif /* CONFIG_AP_MODE */ - - return _FAIL; - -} - -#if defined(CONFIG_LAYER2_ROAMING) && defined(CONFIG_RTW_80211K) -void rtw_roam_nb_discover(_adapter *padapter, u8 bfroce) -{ - struct mlme_priv *pmlmepriv = &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; - u8 nb_req_issue = _FALSE; - - if (!check_fwstate(pmlmepriv, _FW_LINKED)) - return; - - if (!rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE)) - return; - - psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); - if (!psta) - return; - - if (bfroce || (!pmlmepriv->nb_info.nb_rpt_is_same)) - nb_req_issue = _TRUE; - - if (nb_req_issue && (psta->rm_en_cap[0] & RTW_RRM_NB_RPT_EN)) - rm_add_nb_req(padapter, psta); -} -#endif - -unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame) -{ - uint i; - int res; - unsigned short status; - PNDIS_802_11_VARIABLE_IEs pIE; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - /* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */ - u8 *pframe = precv_frame->u.hdr.rx_data; - uint pkt_len = precv_frame->u.hdr.len; -#ifdef CONFIG_WAPI_SUPPORT - PNDIS_802_11_VARIABLE_IEs pWapiIE = NULL; -#endif - - RTW_INFO("%s\n", __FUNCTION__); - - /* check A1 matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN)) - return _SUCCESS; - - if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)) || pmlmeext->join_abort) - return _SUCCESS; - - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - return _SUCCESS; - - _cancel_timer_ex(&pmlmeext->link_timer); - - /* status */ - status = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 2)); - if (status > 0) { - RTW_INFO("assoc reject, status code: %d\n", status); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - res = -4; - goto report_assoc_result; - } - - /* get capabilities */ - pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); - - /* set slot time */ - pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; - - /* AID */ - res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 4)) & 0x3fff); - - /* check aid value */ - if (res < 1 || res > 2007) { - RTW_INFO("assoc reject, aid: %d\n", res); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - res = -4; - goto report_assoc_result; - } - - /* following are moved to join event callback function */ - /* to handle HT, WMM, rate adaptive, update MAC reg */ - /* for not to handle the synchronous IO in the tasklet */ - for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { - pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: - if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ - WMM_param_handler(padapter, pIE); -#if defined(CONFIG_P2P) && defined(CONFIG_WFD) - else if (_rtw_memcmp(pIE->data, WFD_OUI, 4)) /* WFD */ - rtw_process_wfd_ie(padapter, (u8 *)pIE, pIE->Length, __func__); -#endif - break; - -#ifdef CONFIG_WAPI_SUPPORT - case _WAPI_IE_: - pWapiIE = pIE; - break; -#endif - - case _HT_CAPABILITY_IE_: /* HT caps */ - HT_caps_handler(padapter, pIE); -#ifdef ROKU_PRIVATE - HT_caps_handler_infra_ap(padapter, pIE); -#endif /* ROKU_PRIVATE */ - break; - - case _HT_EXTRA_INFO_IE_: /* HT info */ - HT_info_handler(padapter, pIE); - break; - -#ifdef CONFIG_80211AC_VHT - case EID_VHTCapability: - VHT_caps_handler(padapter, pIE); -#ifdef ROKU_PRIVATE - VHT_caps_handler_infra_ap(padapter, pIE); -#endif /* ROKU_PRIVATE */ - break; - - case EID_VHTOperation: - VHT_operation_handler(padapter, pIE); - break; -#endif - - case _ERPINFO_IE_: - ERP_IE_handler(padapter, pIE); - break; -#ifdef CONFIG_TDLS - case _EXT_CAP_IE_: - if (check_ap_tdls_prohibited(pIE->data, pIE->Length) == _TRUE) - padapter->tdlsinfo.ap_prohibited = _TRUE; - if (check_ap_tdls_ch_switching_prohibited(pIE->data, pIE->Length) == _TRUE) - padapter->tdlsinfo.ch_switch_prohibited = _TRUE; - break; -#endif /* CONFIG_TDLS */ - -#ifdef CONFIG_RTW_80211K - case _EID_RRM_EN_CAP_IE_: - RM_IE_handler(padapter, pIE); - break; -#endif - -#ifdef ROKU_PRIVATE - /* Infra mode, used to store AP's info , Parse the supported rates from AssocRsp */ - case _SUPPORTEDRATES_IE_: - Supported_rate_infra_ap(padapter, pIE); - break; - - case _EXT_SUPPORTEDRATES_IE_: - Extended_Supported_rate_infra_ap(padapter, pIE); - break; -#endif /* ROKU_PRIVATE */ - default: - break; - } - - i += (pIE->Length + 2); - } - -#ifdef CONFIG_WAPI_SUPPORT - rtw_wapi_on_assoc_ok(padapter, pIE); -#endif - - pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - - /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ - UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates); - -report_assoc_result: - if (res > 0) - rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len); - else - rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len); - - report_join_res(padapter, res, status); - -#if defined(CONFIG_LAYER2_ROAMING) && defined(CONFIG_RTW_80211K) - rtw_roam_nb_discover(padapter, _TRUE); -#endif - return _SUCCESS; -} - -unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->u.hdr.rx_data; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif /* CONFIG_P2P */ - - /* check A3 */ - if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) - return _SUCCESS; - - RTW_INFO(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter)); - -#ifdef CONFIG_P2P - if (pwdinfo->rx_invitereq_info.scan_op_ch_only) { - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - _set_timer(&pwdinfo->reset_ch_sitesurvey, 10); - } -#endif /* CONFIG_P2P */ - - reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); - -#ifdef CONFIG_AP_MODE - if (MLME_IS_AP(padapter)) { - _irqL irqL; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */ - /* rtw_free_stainfo(padapter, psta); */ - /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */ - - RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n" - , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe)); - - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta) { - u8 updated = _FALSE; - - _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, reason, _TRUE); - - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL); - } - - - return _SUCCESS; - } else -#endif - if (!MLME_IS_MESH(padapter)) { - 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; - } - } - - RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM, ignore=%d\n" - , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe), ignore_received_deauth); - - if (0 == ignore_received_deauth) - receive_disconnect(padapter, get_addr2_ptr(pframe), reason, _FALSE); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE; - return _SUCCESS; - -} - -unsigned int OnDisassoc(_adapter *padapter, union recv_frame *precv_frame) -{ - unsigned short reason; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->u.hdr.rx_data; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif /* CONFIG_P2P */ - - /* check A3 */ - if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) - return _SUCCESS; - - RTW_INFO(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter)); - -#ifdef CONFIG_P2P - if (pwdinfo->rx_invitereq_info.scan_op_ch_only) { - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - _set_timer(&pwdinfo->reset_ch_sitesurvey, 10); - } -#endif /* CONFIG_P2P */ - - reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); - -#ifdef CONFIG_AP_MODE - if (MLME_IS_AP(padapter)) { - _irqL irqL; - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */ - /* rtw_free_stainfo(padapter, psta); */ - /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */ - - RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n" - , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe)); - - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta) { - u8 updated = _FALSE; - - _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, reason, _TRUE); - - } - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL); - } - - return _SUCCESS; - } else -#endif - if (!MLME_IS_MESH(padapter)) { - RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n" - , FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe)); - - receive_disconnect(padapter, get_addr2_ptr(pframe), reason, _FALSE); - } - pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE; - return _SUCCESS; - -} - -unsigned int OnAtim(_adapter *padapter, union recv_frame *precv_frame) -{ - RTW_INFO("%s\n", __FUNCTION__); - return _SUCCESS; -} - -unsigned int on_action_spct_ch_switch(_adapter *padapter, struct sta_info *psta, u8 *ies, uint ies_len) -{ - unsigned int ret = _FAIL; - struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(mlmeext->mlmext_info); - - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { - ret = _SUCCESS; - goto exit; - } - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) { - - int ch_switch_mode = -1, ch = -1, ch_switch_cnt = -1; - int ch_offset = -1; - u8 bwmode; - struct ieee80211_info_element *ie; - - RTW_INFO(FUNC_NDEV_FMT" from "MAC_FMT"\n", - FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(psta->cmn.mac_addr)); - - for_each_ie(ie, ies, ies_len) { - if (ie->id == WLAN_EID_CHANNEL_SWITCH) { - ch_switch_mode = ie->data[0]; - ch = ie->data[1]; - ch_switch_cnt = ie->data[2]; - RTW_INFO("ch_switch_mode:%d, ch:%d, ch_switch_cnt:%d\n", - ch_switch_mode, ch, ch_switch_cnt); - } else if (ie->id == WLAN_EID_SECONDARY_CHANNEL_OFFSET) { - ch_offset = secondary_ch_offset_to_hal_ch_offset(ie->data[0]); - RTW_INFO("ch_offset:%d\n", ch_offset); - } - } - - if (ch == -1) - return _SUCCESS; - - if (ch_offset == -1) - bwmode = mlmeext->cur_bwmode; - else - bwmode = (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) ? - CHANNEL_WIDTH_20 : CHANNEL_WIDTH_40; - - ch_offset = (ch_offset == -1) ? mlmeext->cur_ch_offset : ch_offset; - - /* todo: - * 1. the decision of channel switching - * 2. things after channel switching - */ - - ret = rtw_set_chbw_cmd(padapter, ch, bwmode, ch_offset, 0); - } - -exit: - return ret; -} - -unsigned int on_action_spct(_adapter *padapter, union recv_frame *precv_frame) -{ - unsigned int ret = _FAIL; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - u8 *pframe = precv_frame->u.hdr.rx_data; - uint frame_len = precv_frame->u.hdr.len; - u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - u8 category; - u8 action; - - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - - if (!psta) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) - goto exit; - - action = frame_body[1]; - - RTW_INFO(FUNC_ADPT_FMT" action:%u\n", FUNC_ADPT_ARG(padapter), action); - - switch (action) { - case RTW_WLAN_ACTION_SPCT_MSR_REQ: - case RTW_WLAN_ACTION_SPCT_MSR_RPRT: - case RTW_WLAN_ACTION_SPCT_TPC_REQ: - case RTW_WLAN_ACTION_SPCT_TPC_RPRT: - break; - case RTW_WLAN_ACTION_SPCT_CHL_SWITCH: -#ifdef CONFIG_SPCT_CH_SWITCH - ret = on_action_spct_ch_switch(padapter, psta - , frame_body + 2, frame_len - (frame_body - pframe) - 2); -#elif defined(CONFIG_DFS) - if (MLME_IS_STA(padapter) && MLME_IS_ASOC(padapter)) { - process_csa_ie(padapter - , frame_body + 2, frame_len - (frame_body - pframe) - 2); - } -#endif - break; - default: - break; - } - -exit: - return ret; -} - -unsigned int OnAction_qos(_adapter *padapter, union recv_frame *precv_frame) -{ - return _SUCCESS; -} - -unsigned int OnAction_dls(_adapter *padapter, union recv_frame *precv_frame) -{ - return _SUCCESS; -} - -#ifdef CONFIG_RTW_WNM -unsigned int on_action_wnm(_adapter *adapter, union recv_frame *rframe) -{ - unsigned int ret = _FAIL; - struct sta_info *sta = NULL; - struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); - struct sta_priv *stapriv = &(adapter->stapriv); - u8 *frame = rframe->u.hdr.rx_data; - u32 frame_len = rframe->u.hdr.len; - u8 *frame_body = (u8 *)(frame + sizeof(struct rtw_ieee80211_hdr_3addr)); - u32 frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr); - u8 category, action; - int cnt = 0; - char msg[16]; - - sta = rtw_get_stainfo(stapriv, get_addr2_ptr(frame)); - if (!sta) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_WNM) - goto exit; - - action = frame_body[1]; - - switch (action) { -#ifdef CONFIG_RTW_80211R - case RTW_WLAN_ACTION_WNM_BTM_REQ: - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) { - RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_REQ recv.\n"); - rtw_wnm_process_btm_req(adapter, frame_body, frame_body_len); - } - ret = _SUCCESS; - break; -#endif - default: - #ifdef CONFIG_IOCTL_CFG80211 - cnt += sprintf((msg + cnt), "ACT_WNM %u", action); - rtw_cfg80211_rx_action(adapter, rframe, msg); - #endif - ret = _SUCCESS; - break; - } - -exit: - return ret; -} -#endif /* CONFIG_RTW_WNM */ - -/** - * rtw_rx_ampdu_size - Get the target RX AMPDU buffer size for the specific @adapter - * @adapter: the adapter to get target RX AMPDU buffer size - * - * Returns: the target RX AMPDU buffer size - */ -u8 rtw_rx_ampdu_size(_adapter *adapter) -{ - u8 size; - HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor; - -#ifdef CONFIG_BT_COEXIST - if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(adapter) == _TRUE) { - size = rtw_btcoex_GetAMPDUSize(adapter); - goto exit; - } -#endif - - /* for scan */ - if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE) - && !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE) - && adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size != RX_AMPDU_SIZE_INVALID - ) { - size = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size; - goto exit; - } - - /* default value based on max_rx_ampdu_factor */ - if (adapter->driver_rx_ampdu_factor != 0xFF) - max_rx_ampdu_factor = (HT_CAP_AMPDU_FACTOR)adapter->driver_rx_ampdu_factor; - else - rtw_hal_get_def_var(adapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); - - /* In Maximum A-MPDU Length Exponent subfield of A-MPDU Parameters field of HT Capabilities element, - the unit of max_rx_ampdu_factor are octets. 8K, 16K, 32K, 64K is right. - But the buffer size subfield of Block Ack Parameter Set field in ADDBA action frame indicates - the number of buffers available for this particular TID. Each buffer is equal to max. size of - MSDU or AMSDU. - The size variable means how many MSDUs or AMSDUs, it's not Kbytes. - */ - if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor) - size = 64; - else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor) - size = 32; - else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor) - size = 16; - else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor) - size = 8; - else - size = 64; - -exit: - - if (size > 127) - size = 127; - - return size; -} - -/** - * rtw_rx_ampdu_is_accept - Get the permission if RX AMPDU should be set up for the specific @adapter - * @adapter: the adapter to get the permission if RX AMPDU should be set up - * - * Returns: accept or not - */ -bool rtw_rx_ampdu_is_accept(_adapter *adapter) -{ - bool accept; - - if (adapter->fix_rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID) { - accept = adapter->fix_rx_ampdu_accept; - goto exit; - } - -#ifdef CONFIG_BT_COEXIST - if (rtw_btcoex_IsBTCoexRejectAMPDU(adapter) == _TRUE) { - accept = _FALSE; - goto exit; - } -#endif - - /* for scan */ - if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE) - && !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE) - && adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID - ) { - accept = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept; - goto exit; - } - - /* default value for other cases */ - accept = adapter->mlmeextpriv.mlmext_info.bAcceptAddbaReq; - -exit: - return accept; -} - -/** - * rtw_rx_ampdu_set_size - Set the target RX AMPDU buffer size for the specific @adapter and specific @reason - * @adapter: the adapter to set target RX AMPDU buffer size - * @size: the target RX AMPDU buffer size to set - * @reason: reason for the target RX AMPDU buffer size setting - * - * Returns: whether the target RX AMPDU buffer size is changed - */ -bool rtw_rx_ampdu_set_size(_adapter *adapter, u8 size, u8 reason) -{ - bool is_adj = _FALSE; - struct mlme_ext_priv *mlmeext; - struct mlme_ext_info *mlmeinfo; - - mlmeext = &adapter->mlmeextpriv; - mlmeinfo = &mlmeext->mlmext_info; - - if (reason == RX_AMPDU_DRV_FIXED) { - if (adapter->fix_rx_ampdu_size != size) { - adapter->fix_rx_ampdu_size = size; - is_adj = _TRUE; - RTW_INFO(FUNC_ADPT_FMT" fix_rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size); - } - } else if (reason == RX_AMPDU_DRV_SCAN) { - struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res; - - if (ss->rx_ampdu_size != size) { - ss->rx_ampdu_size = size; - is_adj = _TRUE; - RTW_INFO(FUNC_ADPT_FMT" ss.rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size); - } - } - - return is_adj; -} - -/** - * rtw_rx_ampdu_set_accept - Set the permission if RX AMPDU should be set up for the specific @adapter and specific @reason - * @adapter: the adapter to set if RX AMPDU should be set up - * @accept: if RX AMPDU should be set up - * @reason: reason for the permission if RX AMPDU should be set up - * - * Returns: whether the permission if RX AMPDU should be set up is changed - */ -bool rtw_rx_ampdu_set_accept(_adapter *adapter, u8 accept, u8 reason) -{ - bool is_adj = _FALSE; - struct mlme_ext_priv *mlmeext; - struct mlme_ext_info *mlmeinfo; - - mlmeext = &adapter->mlmeextpriv; - mlmeinfo = &mlmeext->mlmext_info; - - if (reason == RX_AMPDU_DRV_FIXED) { - if (adapter->fix_rx_ampdu_accept != accept) { - adapter->fix_rx_ampdu_accept = accept; - is_adj = _TRUE; - RTW_INFO(FUNC_ADPT_FMT" fix_rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept); - } - } else if (reason == RX_AMPDU_DRV_SCAN) { - if (adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != accept) { - adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept = accept; - is_adj = _TRUE; - RTW_INFO(FUNC_ADPT_FMT" ss.rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept); - } - } - - return is_adj; -} - -/** - * rx_ampdu_apply_sta_tid - Apply RX AMPDU setting to the specific @sta and @tid - * @adapter: the adapter to which @sta belongs - * @sta: the sta to be checked - * @tid: the tid to be checked - * @accept: the target permission if RX AMPDU should be set up - * @size: the target RX AMPDU buffer size - * - * Returns: - * 0: no canceled - * 1: canceled by no permission - * 2: canceled by different buffer size - * 3: canceled by potential mismatched status - * - * Blocking function, may sleep - */ -u8 rx_ampdu_apply_sta_tid(_adapter *adapter, struct sta_info *sta, u8 tid, u8 accept, u8 size) -{ - u8 ret = 0; - struct recv_reorder_ctrl *reorder_ctl = &sta->recvreorder_ctrl[tid]; - - if (reorder_ctl->enable == _FALSE) { - if (reorder_ctl->ampdu_size != RX_AMPDU_SIZE_INVALID) { - send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 1); - ret = 3; - } - goto exit; - } - - if (accept == _FALSE) { - send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0); - ret = 1; - } else if (reorder_ctl->ampdu_size != size) { - send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0); - ret = 2; - } - -exit: - return ret; -} - -u8 rx_ampdu_size_sta_limit(_adapter *adapter, struct sta_info *sta) -{ - u8 sz_limit = 0xFF; - -#ifdef CONFIG_80211N_HT - struct registry_priv *regsty = adapter_to_regsty(adapter); - struct mlme_priv *mlme = &adapter->mlmepriv; - struct mlme_ext_info *mlmeinfo = &adapter->mlmeextpriv.mlmext_info; - s8 nss = -1; - u8 bw = rtw_min(sta->cmn.bw_mode, adapter->mlmeextpriv.cur_bwmode); - - #ifdef CONFIG_80211AC_VHT - if (is_supported_vht(sta->wireless_mode)) { - nss = rtw_min(rtw_vht_mcsmap_to_nss(mlme->vhtpriv.vht_mcs_map) - , rtw_vht_mcsmap_to_nss(sta->vhtpriv.vht_mcs_map)); - } else - #endif - if (is_supported_ht(sta->wireless_mode)) { - nss = rtw_min(rtw_ht_mcsset_to_nss(mlmeinfo->HT_caps.u.HT_cap_element.MCS_rate) - , rtw_ht_mcsset_to_nss(sta->htpriv.ht_cap.supp_mcs_set)); - } - - if (nss >= 1) - sz_limit = regsty->rx_ampdu_sz_limit_by_nss_bw[nss - 1][bw]; -#endif /* CONFIG_80211N_HT */ - - return sz_limit; -} - -/** - * rx_ampdu_apply_sta - Apply RX AMPDU setting to the specific @sta - * @adapter: the adapter to which @sta belongs - * @sta: the sta to be checked - * @accept: the target permission if RX AMPDU should be set up - * @size: the target RX AMPDU buffer size - * - * Returns: number of the RX AMPDU assciation canceled for applying current target setting - * - * Blocking function, may sleep - */ -u8 rx_ampdu_apply_sta(_adapter *adapter, struct sta_info *sta, u8 accept, u8 size) -{ - u8 change_cnt = 0; - int i; - - for (i = 0; i < TID_NUM; i++) { - if (rx_ampdu_apply_sta_tid(adapter, sta, i, accept, size) != 0) - change_cnt++; - } - - return change_cnt; -} - -/** - * rtw_rx_ampdu_apply - Apply the current target RX AMPDU setting for the specific @adapter - * @adapter: the adapter to be applied - * - * Returns: number of the RX AMPDU assciation canceled for applying current target setting - */ -u16 rtw_rx_ampdu_apply(_adapter *adapter) -{ - u16 adj_cnt = 0; - struct sta_info *sta; - u8 accept = rtw_rx_ampdu_is_accept(adapter); - u8 size; - - if (adapter->fix_rx_ampdu_size != RX_AMPDU_SIZE_INVALID) - size = adapter->fix_rx_ampdu_size; - else - size = rtw_rx_ampdu_size(adapter); - - if (MLME_IS_STA(adapter)) { - sta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv)); - if (sta) { - u8 sta_size = size; - - if (adapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID) - sta_size = rtw_min(size, rx_ampdu_size_sta_limit(adapter, sta)); - adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, sta_size); - } - /* TODO: TDLS peer */ - - } else if (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) { - _irqL irqL; - _list *phead, *plist; - u8 peer_num = 0; - char peers[NUM_STA]; - struct sta_priv *pstapriv = &adapter->stapriv; - int i; - - _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; - - sta = LIST_CONTAINOR(plist, struct sta_info, asoc_list); - plist = get_next(plist); - - stainfo_offset = rtw_stainfo_offset(pstapriv, sta); - if (stainfo_offset_valid(stainfo_offset)) - peers[peer_num++] = stainfo_offset; - } - - _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); - - for (i = 0; i < peer_num; i++) { - sta = rtw_get_stainfo_by_offset(pstapriv, peers[i]); - if (sta) { - u8 sta_size = size; - - if (adapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID) - sta_size = rtw_min(size, rx_ampdu_size_sta_limit(adapter, sta)); - adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, sta_size); - } - } - } - - /* TODO: ADHOC */ - - return adj_cnt; -} - -unsigned int OnAction_back(_adapter *padapter, union recv_frame *precv_frame) -{ - u8 *addr; - struct sta_info *psta = NULL; - struct recv_reorder_ctrl *preorder_ctrl; - unsigned char *frame_body; - unsigned char category, action; - unsigned short tid, status, reason_code = 0; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 *pframe = precv_frame->u.hdr.rx_data; - struct sta_priv *pstapriv = &padapter->stapriv; - struct registry_priv *pregpriv = &padapter->registrypriv; - -#ifdef CONFIG_80211N_HT - - RTW_INFO("%s\n", __FUNCTION__); - - /* check RA matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN)) - return _SUCCESS; - -#if 0 - /* check A1 matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN)) - return _SUCCESS; -#endif - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - addr = get_addr2_ptr(pframe); - psta = rtw_get_stainfo(pstapriv, addr); - - if (psta == NULL) - return _SUCCESS; - - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - - category = frame_body[0]; - if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */ -#ifdef CONFIG_TDLS - if ((psta->tdls_sta_state & TDLS_LINKED_STATE) && - (psta->htpriv.ht_option == _TRUE) && - (psta->htpriv.ampdu_enable == _TRUE)) - RTW_INFO("Recv [%s] from direc link\n", __FUNCTION__); - else -#endif /* CONFIG_TDLS */ - if (!pmlmeinfo->HT_enable) - return _SUCCESS; - - action = frame_body[1]; - RTW_INFO("%s, action=%d\n", __FUNCTION__, action); - switch (action) { - case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ - - _rtw_memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); - /* process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */ - process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); - - break; - - case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ - - /* status = frame_body[3] | (frame_body[4] << 8); */ /* endian issue */ - status = RTW_GET_LE16(&frame_body[3]); - tid = ((frame_body[5] >> 2) & 0x7); - if (status == 0) { - /* successful */ - RTW_INFO("agg_enable for TID=%d\n", tid); - psta->htpriv.agg_enable_bitmap |= 1 << tid; - psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - /* amsdu in ampdu */ - if (pregpriv->tx_ampdu_amsdu == 0) - psta->htpriv.tx_amsdu_enable = _FALSE; - else if (pregpriv->tx_ampdu_amsdu == 1) - psta->htpriv.tx_amsdu_enable = _TRUE; - else { - if (frame_body[5] & 1) - psta->htpriv.tx_amsdu_enable = _TRUE; - } - } else - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - RTW_INFO("%s alive check - rx ADDBA response\n", __func__); - psta->htpriv.agg_enable_bitmap &= ~BIT(tid); - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - /* RTW_INFO("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */ - break; - - case RTW_WLAN_ACTION_DELBA: /* DELBA */ - if ((frame_body[3] & BIT(3)) == 0) { - psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); - psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf)); - - /* reason_code = frame_body[4] | (frame_body[5] << 8); */ - reason_code = RTW_GET_LE16(&frame_body[4]); - } else if ((frame_body[3] & BIT(3)) == BIT(3)) { - tid = (frame_body[3] >> 4) & 0x0F; - - preorder_ctrl = &psta->recvreorder_ctrl[tid]; - preorder_ctrl->enable = _FALSE; - preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID; - } - - RTW_INFO("%s(): DELBA: %x(%x)\n", __FUNCTION__, pmlmeinfo->agg_enable_bitmap, reason_code); - /* todo: how to notify the host while receiving DELETE BA */ - break; - - default: - break; - } - } -#endif /* CONFIG_80211N_HT */ - return _SUCCESS; -} - -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE -u32 rtw_build_vendor_ie(_adapter *padapter , unsigned char **pframe , u8 mgmt_frame_tyte) -{ - int vendor_ie_num = 0; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u32 len = 0; - - for (vendor_ie_num = 0 ; vendor_ie_num < WLAN_MAX_VENDOR_IE_NUM ; vendor_ie_num++) { - if (pmlmepriv->vendor_ielen[vendor_ie_num] > 0 && pmlmepriv->vendor_ie_mask[vendor_ie_num] & mgmt_frame_tyte) { - _rtw_memcpy(*pframe , pmlmepriv->vendor_ie[vendor_ie_num] , pmlmepriv->vendor_ielen[vendor_ie_num]); - *pframe += pmlmepriv->vendor_ielen[vendor_ie_num]; - len += pmlmepriv->vendor_ielen[vendor_ie_num]; - } - } - - return len; -} -#endif - -#ifdef CONFIG_P2P -int get_reg_classes_full_count(struct p2p_channels *channel_list) -{ - int cnt = 0; - int i; - - for (i = 0; i < channel_list->reg_classes; i++) - cnt += channel_list->reg_class[i].channels; - - return cnt; -} - -void issue_p2p_GO_request(_adapter *padapter, u8 *raddr) -{ - struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list); - unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_GO_NEGO_REQ; - u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 }; - u8 wpsielen = 0, p2pielen = 0; - u16 len_channellist_attr = 0; -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - - 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 wifidirect_info *pwdinfo = &(padapter->wdinfo); - - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - RTW_INFO("[%s] In\n", __FUNCTION__); - /* 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; - - _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); - pwdinfo->negotiation_dialog_token = 1; /* Initialize the dialog value */ - pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen)); - - - - /* WPS Section */ - wpsielen = 0; - /* WPS OUI */ - *(u32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - /* Device Password ID */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - - if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC); - else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN) - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); - else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC) - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC); - - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen); - - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20110306 */ - /* According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */ - /* 1. P2P Capability */ - /* 2. Group Owner Intent */ - /* 3. Configuration Timeout */ - /* 4. Listen Channel */ - /* 5. Extended Listen Timing */ - /* 6. Intended P2P Interface Address */ - /* 7. Channel List */ - /* 8. P2P Device Info */ - /* 9. Operating Channel */ - - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP; - else - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN; - - - /* Group Owner Intent */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GO_INTENT; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - /* Todo the tie breaker bit. */ - p2pie[p2pielen++] = ((pwdinfo->intent << 1) & 0xFE); - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - - /* Listen Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */ - - - /* Extended Listen Timing ATTR */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004); - p2pielen += 2; - - /* Value: */ - /* Availability Period */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Availability Interval */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - - /* Intended P2P Interface Address */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); - p2pielen += ETH_ALEN; - - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Length: */ - /* Country String(3) */ - /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)(ch_list->reg_classes) - + get_reg_classes_full_count(ch_list); - -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1); - else - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); -#else - - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); - -#endif - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Channel Entry List */ - -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) { - u8 union_ch = rtw_mi_get_union_chan(padapter); - - /* Operating Class */ - if (union_ch > 14) { - if (union_ch >= 149) - p2pie[p2pielen++] = 0x7c; - else - p2pie[p2pielen++] = 0x73; - } else - p2pie[p2pielen++] = 0x51; - - - /* Number of Channels */ - /* Just support 1 channel and this channel is AP's channel */ - p2pie[p2pielen++] = 1; - - /* Channel List */ - p2pie[p2pielen++] = union_ch; - } else -#endif /* CONFIG_CONCURRENT_MODE */ - { - int i, j; - for (j = 0; j < ch_list->reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = ch_list->reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = ch_list->reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < ch_list->reg_class[j].channels; i++) - p2pie[p2pielen++] = ch_list->reg_class[j].channel[i]; - } - } - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + 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); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Operating Class */ - 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++] = pwdinfo->operating_channel; /* operating channel number */ - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen); - -#ifdef CONFIG_WFD - wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - - -void issue_p2p_GO_response(_adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result) -{ - struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list); - unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_GO_NEGO_RESP; - u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - uint wpsielen = 0; - u16 wps_devicepassword_id = 0x0000; - uint wps_devicepassword_id_len = 0; - u16 len_channellist_attr = 0; - - 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 wifidirect_info *pwdinfo = &(padapter->wdinfo); - -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - RTW_INFO("[%s] In, result = %d\n", __FUNCTION__, result); - /* 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; - - _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); - pwdinfo->negotiation_dialog_token = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */ - pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen)); - - /* Commented by Albert 20110328 */ - /* Try to get the device password ID from the WPS IE of group negotiation request frame */ - /* WiFi Direct test plan 5.1.15 */ - rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen); - rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len); - wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id); - - _rtw_memset(wpsie, 0x00, 255); - wpsielen = 0; - - /* WPS Section */ - wpsielen = 0; - /* WPS OUI */ - *(u32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - /* Device Password ID */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - if (wps_devicepassword_id == WPS_DPID_USER_SPEC) - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); - else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC); - else - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC); - wpsielen += 2; - - /* Commented by Kurt 20120113 */ - /* If some device wants to do p2p handshake without sending prov_disc_req */ - /* We have to get peer_req_cm from here. */ - if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) { - if (wps_devicepassword_id == WPS_DPID_USER_SPEC) - _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3); - else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) - _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3); - else - _rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3); - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen); - - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20100908 */ - /* According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */ - /* 1. Status */ - /* 2. P2P Capability */ - /* 3. Group Owner Intent */ - /* 4. Configuration Timeout */ - /* 5. Operating Channel */ - /* 6. Intended P2P Interface Address */ - /* 7. Channel List */ - /* 8. Device Info */ - /* 9. Group ID ( Only GO ) */ - - - /* ToDo: */ - - /* P2P Status */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_STATUS; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = result; - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) { - /* Commented by Albert 2011/03/08 */ - /* According to the P2P specification */ - /* if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */ - p2pie[p2pielen++] = 0; - } else { - /* Be group owner or meet the error case */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - } - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP; - else - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN; - - /* Group Owner Intent */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GO_INTENT; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - if (pwdinfo->peer_intent & 0x01) { - /* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */ - p2pie[p2pielen++] = (pwdinfo->intent << 1); - } else { - /* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */ - p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0)); - } - - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Operating Class */ - 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++] = pwdinfo->operating_channel; /* operating channel number */ - - /* Intended P2P Interface Address */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Country String(3) */ - /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)ch_list->reg_classes - + get_reg_classes_full_count(ch_list); - -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1); - else - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); -#else - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); - -#endif - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Channel Entry List */ - -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) { - - u8 union_chan = rtw_mi_get_union_chan(padapter); - - /*Operating Class*/ - if (union_chan > 14) { - if (union_chan >= 149) - p2pie[p2pielen++] = 0x7c; - else - p2pie[p2pielen++] = 0x73; - - } else - p2pie[p2pielen++] = 0x51; - - /* Number of Channels - Just support 1 channel and this channel is AP's channel*/ - p2pie[p2pielen++] = 1; - - /*Channel List*/ - p2pie[p2pielen++] = union_chan; - } else -#endif /* CONFIG_CONCURRENT_MODE */ - { - int i, j; - for (j = 0; j < ch_list->reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = ch_list->reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = ch_list->reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < ch_list->reg_class[j].channels; i++) - p2pie[p2pielen++] = ch_list->reg_class[j].channel[i]; - } - } - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + 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); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* Group ID Attribute */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen); - p2pielen += 2; - - /* Value: */ - /* p2P Device Address */ - _rtw_memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* SSID */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen); - p2pielen += pwdinfo->nego_ssidlen; - - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen); - -#ifdef CONFIG_WFD - wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - -void issue_p2p_GO_confirm(_adapter *padapter, u8 *raddr, u8 result) -{ - - unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_GO_NEGO_CONF; - u8 p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - - 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 wifidirect_info *pwdinfo = &(padapter->wdinfo); -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - RTW_INFO("[%s] In\n", __FUNCTION__); - /* 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; - - _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen)); - - - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20110306 */ - /* According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */ - /* 1. Status */ - /* 2. P2P Capability */ - /* 3. Operating Channel */ - /* 4. Channel List */ - /* 5. Group ID ( if this WiFi is GO ) */ - - /* P2P Status */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_STATUS; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = result; - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP; - else - p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN; - - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - - 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++] = 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++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */ - } - - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - *(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: */ - 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)) { - /* Group ID Attribute */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen); - p2pielen += 2; - - /* Value: */ - /* p2P Device Address */ - _rtw_memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* SSID */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen); - p2pielen += pwdinfo->nego_ssidlen; - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen); - -#ifdef CONFIG_WFD - wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - -void issue_p2p_invitation_request(_adapter *padapter, u8 *raddr) -{ - struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list); - unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_INVIT_REQ; - u8 p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - u8 dialogToken = 3; - u16 len_channellist_attr = 0; -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - - 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 wifidirect_info *pwdinfo = &(padapter->wdinfo); - - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == 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; - - _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, raddr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen)); - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20101011 */ - /* According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */ - /* 1. Configuration Timeout */ - /* 2. Invitation Flags */ - /* 3. Operating Channel ( Only GO ) */ - /* 4. P2P Group BSSID ( Should be included if I am the GO ) */ - /* 5. Channel List */ - /* 6. P2P Group ID */ - /* 7. P2P Device Info */ - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - /* Invitation Flags */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT; - - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Operating Class */ - if (pwdinfo->invitereq_info.operating_ch <= 14) - p2pie[p2pielen++] = 0x51; - else if ((pwdinfo->invitereq_info.operating_ch >= 36) && (pwdinfo->invitereq_info.operating_ch <= 48)) - p2pie[p2pielen++] = 0x73; - else - p2pie[p2pielen++] = 0x7c; - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch; /* operating channel number */ - - if (_rtw_memcmp(adapter_mac_addr(padapter), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) { - /* P2P Group BSSID */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address for GO */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN); - p2pielen += ETH_ALEN; - } - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - - /* Length: */ - /* Country String(3) */ - /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)ch_list->reg_classes - + get_reg_classes_full_count(ch_list); - -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1); - else - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); -#else - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); -#endif - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Channel Entry List */ -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) { - u8 union_ch = rtw_mi_get_union_chan(padapter); - - /* Operating Class */ - if (union_ch > 14) { - if (union_ch >= 149) - p2pie[p2pielen++] = 0x7c; - else - p2pie[p2pielen++] = 0x73; - } else - p2pie[p2pielen++] = 0x51; - - - /* Number of Channels */ - /* Just support 1 channel and this channel is AP's channel */ - p2pie[p2pielen++] = 1; - - /* Channel List */ - p2pie[p2pielen++] = union_ch; - } else -#endif /* CONFIG_CONCURRENT_MODE */ - { - int i, j; - for (j = 0; j < ch_list->reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = ch_list->reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = ch_list->reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < ch_list->reg_class[j].channels; i++) - p2pie[p2pielen++] = ch_list->reg_class[j].channel[i]; - } - } - - - /* P2P Group ID */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_ID; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address for GO */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN); - p2pielen += ETH_ALEN; - - /* SSID */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen); - p2pielen += pwdinfo->invitereq_info.ssidlen; - - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + 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); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen); - -#ifdef CONFIG_WFD - wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - -void issue_p2p_invitation_response(_adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code) -{ - struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list); - unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_INVIT_RESP; - u8 p2pie[255] = { 0x00 }; - u8 p2pielen = 0; - u16 len_channellist_attr = 0; -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - - 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 wifidirect_info *pwdinfo = &(padapter->wdinfo); - - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == 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; - - _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, raddr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen)); - - /* P2P IE Section. */ - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20101005 */ - /* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */ - /* 1. Status */ - /* 2. Configuration Timeout */ - /* 3. Operating Channel ( Only GO ) */ - /* 4. P2P Group BSSID ( Only GO ) */ - /* 5. Channel List */ - - /* P2P Status */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_STATUS; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001); - p2pielen += 2; - - /* Value: */ - /* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */ - /* Sent the event receiving the P2P Invitation Req frame to DMP UI. */ - /* DMP had to compare the MAC address to find out the profile. */ - /* So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */ - /* If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */ - /* to NB to rebuild the persistent group. */ - p2pie[p2pielen++] = status_code; - - /* Configuration Timeout */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */ - p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */ - - if (status_code == P2P_STATUS_SUCCESS) { - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */ - /* In this case, the P2P Invitation response frame should carry the two more P2P attributes. */ - /* First one is operating channel attribute. */ - /* Second one is P2P Group BSSID attribute. */ - - /* Operating Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */ - - - /* P2P Group BSSID */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address for GO */ - _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); - p2pielen += ETH_ALEN; - - } - - /* Channel List */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CH_LIST; - - /* Length: */ - /* Country String(3) */ - /* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */ - /* + number of channels in all classes */ - len_channellist_attr = 3 - + (1 + 1) * (u16)ch_list->reg_classes - + get_reg_classes_full_count(ch_list); - -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1); - else - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); -#else - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr); -#endif - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Channel Entry List */ -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) { - u8 union_ch = rtw_mi_get_union_chan(padapter); - - /* Operating Class */ - if (union_ch > 14) { - if (union_ch >= 149) - p2pie[p2pielen++] = 0x7c; - else - p2pie[p2pielen++] = 0x73; - } else - p2pie[p2pielen++] = 0x51; - - - /* Number of Channels */ - /* Just support 1 channel and this channel is AP's channel */ - p2pie[p2pielen++] = 1; - - /* Channel List */ - p2pie[p2pielen++] = union_ch; - } else -#endif /* CONFIG_CONCURRENT_MODE */ - { - int i, j; - for (j = 0; j < ch_list->reg_classes; j++) { - /* Operating Class */ - p2pie[p2pielen++] = ch_list->reg_class[j].reg_class; - - /* Number of Channels */ - p2pie[p2pielen++] = ch_list->reg_class[j].channels; - - /* Channel List */ - for (i = 0; i < ch_list->reg_class[j].channels; i++) - p2pie[p2pielen++] = ch_list->reg_class[j].channel[i]; - } - } - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen); - -#ifdef CONFIG_WFD - wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - -void issue_p2p_provision_request(_adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr) -{ - unsigned char category = RTW_WLAN_CATEGORY_PUBLIC; - u8 action = P2P_PUB_ACTION_ACTION; - u8 dialogToken = 1; - u32 p2poui = cpu_to_be32(P2POUI); - u8 oui_subtype = P2P_PROVISION_DISC_REQ; - u8 wpsie[100] = { 0x00 }; - u8 wpsielen = 0; - u32 p2pielen = 0; -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - - 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 wifidirect_info *pwdinfo = &(padapter->wdinfo); - - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - RTW_INFO("[%s] In\n", __FUNCTION__); - /* 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; - - _rtw_memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen)); - - p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr); - - pframe += p2pielen; - pattrib->pktlen += p2pielen; - - wpsielen = 0; - /* WPS OUI */ - *(u32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - /* Config Method */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request); - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen); - - -#ifdef CONFIG_WFD - wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - - -u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo) -{ - u8 i, match_result = 0; - - RTW_INFO("[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__, - peermacaddr[0], peermacaddr[1], peermacaddr[2], peermacaddr[3], peermacaddr[4], peermacaddr[5]); - - for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) { - RTW_INFO("[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__, - profileinfo->peermac[0], profileinfo->peermac[1], profileinfo->peermac[2], profileinfo->peermac[3], profileinfo->peermac[4], profileinfo->peermac[5]); - if (_rtw_memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) { - match_result = 1; - RTW_INFO("[%s] Match!\n", __FUNCTION__); - break; - } - } - - return match_result ; -} - -void issue_probersp_p2p(_adapter *padapter, unsigned char *da) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - unsigned char *mac; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - /* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */ - u16 beacon_interval = 100; - u16 capInfo = 0; - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - u8 wpsie[255] = { 0x00 }; - u32 wpsielen = 0, p2pielen = 0; -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif -#ifdef CONFIG_INTEL_WIDI - u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 }; -#endif /* CONFIG_INTEL_WIDI */ - - /* RTW_INFO("%s\n", __FUNCTION__); */ - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - if (IS_CCK_RATE(pattrib->rate)) { - /* force OFDM 6M rate */ - pattrib->rate = MGN_6M; - pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G); - } - - _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; - - mac = adapter_mac_addr(padapter); - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - - /* Use the device address for BSSID field. */ - _rtw_memcpy(pwlanhdr->addr3, mac, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(fctrl, WIFI_PROBERSP); - - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = pattrib->hdrlen; - pframe += pattrib->hdrlen; - - /* timestamp will be inserted by hardware */ - pframe += 8; - pattrib->pktlen += 8; - - /* beacon interval: 2 bytes */ - _rtw_memcpy(pframe, (unsigned char *) &beacon_interval, 2); - pframe += 2; - pattrib->pktlen += 2; - - /* capability info: 2 bytes */ - /* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */ - capInfo |= cap_ShortPremble; - capInfo |= cap_ShortSlot; - - _rtw_memcpy(pframe, (unsigned char *) &capInfo, 2); - pframe += 2; - pattrib->pktlen += 2; - - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen); - - /* supported rates... */ - /* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */ - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen); - -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) { - if (pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL) { - /* WPS IE */ - _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len); - pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len; - pframe += pmlmepriv->wps_probe_resp_ie_len; - - /* P2P IE */ - _rtw_memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len); - pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len; - pframe += pmlmepriv->p2p_probe_resp_ie_len; - } - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - - /* Todo: WPS IE */ - /* Noted by Albert 20100907 */ - /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */ - - wpsielen = 0; - /* WPS OUI */ - *(u32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - -#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 - || pmlmepriv->num_p2p_sdt != 0) { - /* Sec dev type */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SEC_DEV_TYPE_LIST); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008); - wpsielen += 2; - - /* Value: */ - /* Category ID */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_DISPLAYS); - wpsielen += 2; - - /* OUI */ - *(u32 *)(wpsie + wpsielen) = cpu_to_be32(INTEL_DEV_TYPE_OUI); - wpsielen += 4; - - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_WIDI_CONSUMER_SINK); - wpsielen += 2; - - 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 */ - - /* WiFi Simple Config State */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */ - - /* Response Type */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X; - - /* UUID-E */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010); - wpsielen += 2; - - /* Value: */ - if (pwdinfo->external_uuid == 0) { - _rtw_memset(wpsie + wpsielen, 0x0, 16); - _rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN); - } else - _rtw_memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10); - wpsielen += 0x10; - - /* Manufacturer */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007); - wpsielen += 2; - - /* Value: */ - _rtw_memcpy(wpsie + wpsielen, "Realtek", 7); - wpsielen += 7; - - /* Model Name */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006); - wpsielen += 2; - - /* Value: */ - _rtw_memcpy(wpsie + wpsielen, "8192CU", 6); - wpsielen += 6; - - /* Model Number */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = 0x31; /* character 1 */ - - /* Serial Number */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN); - wpsielen += 2; - - /* Value: */ - _rtw_memcpy(wpsie + wpsielen, "123456" , ETH_ALEN); - wpsielen += ETH_ALEN; - - /* Primary Device Type */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008); - wpsielen += 2; - - /* Value: */ - /* Category ID */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - wpsielen += 2; - - /* OUI */ - *(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* Sub Category ID */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - wpsielen += 2; - - /* Device Name */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len); - wpsielen += 2; - - /* Value: */ - _rtw_memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len); - wpsielen += pwdinfo->device_name_len; - - /* Config Method */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - wpsielen += 2; - - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen); - - - p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe); - pframe += p2pielen; - pattrib->pktlen += p2pielen; - } - -#ifdef CONFIG_WFD - wfdielen = rtw_append_probe_resp_wfd_ie(padapter, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - -/* Vendor Specific IE */ -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE - pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_P2P_PROBERESP_VENDOR_IE_BIT); -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - -int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - unsigned char *mac; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 }; - u16 wpsielen = 0, p2pielen = 0; -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - if (IS_CCK_RATE(pattrib->rate)) { - /* force OFDM 6M rate */ - pattrib->rate = MGN_6M; - pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G); - } - - _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; - - mac = adapter_mac_addr(padapter); - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; - - if (da) { - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN); - } else { - if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) { - /* This two flags will be set when this is only the P2P client mode. */ - _rtw_memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN); - } else { - /* broadcast probe request frame */ - _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); - } - } - _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_PROBEREQ); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) - pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen)); - else - pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen)); - /* Use the OFDM rate in the P2P probe request frame. ( 6(B), 9(B), 12(B), 24(B), 36, 48, 54 ) */ - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen); - -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) { - if (pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL) { - /* WPS IE */ - _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); - pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; - pframe += pmlmepriv->wps_probe_req_ie_len; - - /* P2P IE */ - _rtw_memcpy(pframe, pmlmepriv->p2p_probe_req_ie, pmlmepriv->p2p_probe_req_ie_len); - pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len; - pframe += pmlmepriv->p2p_probe_req_ie_len; - } - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - - /* WPS IE */ - /* Noted by Albert 20110221 */ - /* According to the WPS specification, all the WPS attribute is presented by Big Endian. */ - - wpsielen = 0; - /* WPS OUI */ - *(u32 *)(wpsie) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* WPS version */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001); - wpsielen += 2; - - /* Value: */ - wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */ - - if (pmlmepriv->wps_probe_req_ie == NULL) { - /* UUID-E */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010); - wpsielen += 2; - - /* Value: */ - if (pwdinfo->external_uuid == 0) { - _rtw_memset(wpsie + wpsielen, 0x0, 16); - _rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN); - } else - _rtw_memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10); - wpsielen += 0x10; - - /* Config Method */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm); - wpsielen += 2; - } - - /* Device Name */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len); - wpsielen += 2; - - /* Value: */ - _rtw_memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len); - wpsielen += pwdinfo->device_name_len; - - /* Primary Device Type */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008); - wpsielen += 2; - - /* Value: */ - /* Category ID */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI); - wpsielen += 2; - - /* OUI */ - *(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI); - wpsielen += 4; - - /* Sub Category ID */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP); - wpsielen += 2; - - /* Device Password ID */ - /* Type: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID); - wpsielen += 2; - - /* Length: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002); - wpsielen += 2; - - /* Value: */ - *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); /* Registrar-specified */ - wpsielen += 2; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen); - - /* P2P OUI */ - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20110221 */ - /* According to the P2P Specification, the probe request frame should contain 5 P2P attributes */ - /* 1. P2P Capability */ - /* 2. P2P Device ID if this probe request wants to find the specific P2P device */ - /* 3. Listen Channel */ - /* 4. Extended Listen Timing */ - /* 5. Operating Channel if this WiFi is working as the group owner now */ - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT; - else - p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT; - - /* Listen Channel */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->listen_channel; /* listen channel */ - - - /* Extended Listen Timing */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004); - p2pielen += 2; - - /* Value: */ - /* Availability Period */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Availability Interval */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - /* Operating Channel (if this WiFi is working as the group owner now) */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005); - p2pielen += 2; - - /* Value: */ - /* 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; - - /* Operating Class */ - p2pie[p2pielen++] = 0x51; /* Copy from SD7 */ - - /* Channel Number */ - p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */ - - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen); - - } - -#ifdef CONFIG_WFD - wfdielen = rtw_append_probe_req_wfd_ie(padapter, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif - -/* Vendor Specific IE */ -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE - pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_P2P_PROBEREQ_VENDOR_IE_BIT); -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - - - if (wait_ack) - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -inline void issue_probereq_p2p(_adapter *adapter, u8 *da) -{ - _issue_probereq_p2p(adapter, da, _FALSE); -} - -/* - * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - * try_cnt means the maximal TX count to try - */ -int issue_probereq_p2p_ex(_adapter *adapter, u8 *da, int try_cnt, int wait_ms) -{ - int ret; - int i = 0; - systime start = rtw_get_current_time(); - - do { - ret = _issue_probereq_p2p(adapter, da, wait_ms > 0 ? _TRUE : _FALSE); - - i++; - - if (RTW_CANNOT_RUN(adapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - goto exit; -#endif - } - - if (try_cnt && wait_ms) { - if (da) - RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(adapter), MAC_ARG(da), rtw_get_oper_ch(adapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - else - RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } -exit: - return ret; -} - -#endif /* CONFIG_P2P */ - -s32 rtw_action_public_decache(union recv_frame *rframe, u8 token_offset) -{ - _adapter *adapter = rframe->u.hdr.adapter; - struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); - u8 *frame = rframe->u.hdr.rx_data; - u16 seq_ctrl = ((rframe->u.hdr.attrib.seq_num & 0xffff) << 4) | (rframe->u.hdr.attrib.frag_num & 0xf); - u8 token = *(rframe->u.hdr.rx_data + sizeof(struct rtw_ieee80211_hdr_3addr) + token_offset); - - if (GetRetry(frame)) { - if ((seq_ctrl == mlmeext->action_public_rxseq) - && (token == mlmeext->action_public_dialog_token) - ) { - RTW_INFO(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x, token:%d\n", - FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token); - return _FAIL; - } - } - - /* TODO: per sta seq & token */ - mlmeext->action_public_rxseq = seq_ctrl; - mlmeext->action_public_dialog_token = token; - - return _SUCCESS; -} - -unsigned int on_action_public_p2p(union recv_frame *precv_frame) -{ - _adapter *padapter = precv_frame->u.hdr.adapter; - u8 *pframe = precv_frame->u.hdr.rx_data; - uint len = precv_frame->u.hdr.len; - u8 *frame_body; -#ifdef CONFIG_P2P - u8 *p2p_ie; - u32 p2p_ielen; - 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)); - -#ifdef CONFIG_P2P - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) - rtw_cfg80211_rx_p2p_action_public(padapter, precv_frame); - else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - /* Do nothing if the driver doesn't enable the P2P function. */ - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) - return _SUCCESS; - - len -= sizeof(struct rtw_ieee80211_hdr_3addr); - - switch (frame_body[6]) { /* OUI Subtype */ - case P2P_GO_NEGO_REQ: { - RTW_INFO("[%s] Got GO Nego Req Frame\n", __FUNCTION__); - _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info)); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) { - /* Commented by Albert 20110526 */ - /* In this case, this means the previous nego fail doesn't be reset yet. */ - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - /* Restore the previous p2p state */ - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); - RTW_INFO("[%s] Restore the previous p2p state to %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo)); - } -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_buddy_check_fwstate(padapter, _FW_LINKED)) - _cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer); -#endif /* CONFIG_CONCURRENT_MODE */ - - /* Commented by Kurt 20110902 */ - /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - - /* Commented by Kurt 20120113 */ - /* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */ - if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN)) - _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN); - - result = process_p2p_group_negotation_req(pwdinfo, frame_body, len); - issue_p2p_GO_response(padapter, get_addr2_ptr(pframe), frame_body, len, result); -#ifdef CONFIG_INTEL_WIDI - if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) { - 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, 0); - } -#endif /* CONFIG_INTEL_WIDI */ - - /* Commented by Albert 20110718 */ - /* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */ -#ifdef CONFIG_CONCURRENT_MODE - /* Commented by Albert 20120107 */ - _set_timer(&pwdinfo->restore_p2p_state_timer, 3000); -#else /* CONFIG_CONCURRENT_MODE */ - _set_timer(&pwdinfo->restore_p2p_state_timer, 5000); -#endif /* CONFIG_CONCURRENT_MODE */ - break; - } - case P2P_GO_NEGO_RESP: { - RTW_INFO("[%s] Got GO Nego Resp Frame\n", __FUNCTION__); - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) { - /* Commented by Albert 20110425 */ - /* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */ - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - pwdinfo->nego_req_info.benable = _FALSE; - result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len); - issue_p2p_GO_confirm(pwdinfo->padapter, get_addr2_ptr(pframe), result); - if (P2P_STATUS_SUCCESS == result) { - if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) { - pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch; -#ifdef CONFIG_P2P_OP_CHK_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 /* CONFIG_P2P_OP_CHK_SOCIAL_CH */ - pwdinfo->p2p_info.scan_op_ch_only = 1; - _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH); - } - } - - /* Reset the dialog token for group negotiation frames. */ - pwdinfo->negotiation_dialog_token = 1; - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) - _set_timer(&pwdinfo->restore_p2p_state_timer, 5000); - } else - RTW_INFO("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __FUNCTION__); - - break; - } - case P2P_GO_NEGO_CONF: { - RTW_INFO("[%s] Got GO Nego Confirm Frame\n", __FUNCTION__); - result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len); - if (P2P_STATUS_SUCCESS == result) { - if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) { - pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch; -#ifdef CONFIG_P2P_OP_CHK_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 /* CONFIG_P2P_OP_CHK_SOCIAL_CH */ - pwdinfo->p2p_info.scan_op_ch_only = 1; - _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH); - } - } - break; - } - case P2P_INVIT_REQ: { - /* Added by Albert 2010/10/05 */ - /* Received the P2P Invite Request frame. */ - - RTW_INFO("[%s] Got invite request frame!\n", __FUNCTION__); - p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen); - if (p2p_ie) { - /* Parse the necessary information from the P2P Invitation Request frame. */ - /* For example: The MAC address of sending this P2P Invitation Request frame. */ - u32 attr_contentlen = 0; - u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - struct group_id_info group_id; - u8 invitation_flag = 0; - - merged_p2p_ielen = rtw_get_p2p_merged_ies_len(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_); - - merged_p2pie = rtw_zmalloc(merged_p2p_ielen + 2); /* 2 is for EID and Length */ - if (merged_p2pie == NULL) { - RTW_INFO("[%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(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. */ - /* #> iwpriv wlan0 p2p_get peer_ifa */ - /* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */ - - if (attr_contentlen) { - RTW_INFO("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__, - pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], - pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3], - pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]); - } - - if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) { - /* Re-invoke the persistent group. */ - - _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info)); - 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, adapter_mac_addr(padapter), ETH_ALEN)) { - /* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - status_code = P2P_STATUS_SUCCESS; - } else { - /* The p2p device sending this p2p invitation request wants to be the persistent GO. */ - if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) { - u8 operatingch_info[5] = { 0x00 }; - if (rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, - &attr_contentlen)) { - if (rtw_chset_search_ch(adapter_to_chset(padapter), (u32)operatingch_info[4]) >= 0) { - /* The operating channel is acceptable for this device. */ - pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4]; -#ifdef CONFIG_P2P_OP_CHK_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 /* CONFIG_P2P_OP_CHK_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. */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - status_code = P2P_STATUS_FAIL_NO_COMMON_CH; - _set_timer(&pwdinfo->restore_p2p_state_timer, 3000); - } - } else { - /* Commented by Albert 20121130 */ - /* Intel will use the different P2P IE to store the operating channel information */ - /* Workaround for Intel WiDi 3.5 */ - 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 { - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH); -#ifdef CONFIG_INTEL_WIDI - _rtw_memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); -#endif /* CONFIG_INTEL_WIDI */ - - status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP; - } - } - } else { - RTW_INFO("[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__); - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } - } else { - /* Received the invitation to join a P2P group. */ - - _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info)); - 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, adapter_mac_addr(padapter), ETH_ALEN)) { - /* In this case, the GO can't be myself. */ - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH); - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } else { - /* The p2p device sending this p2p invitation request wants to join an existing P2P group */ - /* Commented by Albert 2012/06/28 */ - /* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */ - /* The peer device address should be the destination address for the provisioning discovery request. */ - /* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */ - /* The peer interface address should be the address for WPS mac address */ - _rtw_memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN); - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN); - status_code = P2P_STATUS_SUCCESS; - } - } else { - RTW_INFO("[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__); - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } - } - } else { - RTW_INFO("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __FUNCTION__); - status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE; - } - - RTW_INFO("[%s] status_code = %d\n", __FUNCTION__, status_code); - - pwdinfo->inviteresp_info.token = frame_body[7]; - issue_p2p_invitation_response(padapter, get_addr2_ptr(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; - _cancel_timer_ex(&(padapter->mlmepriv.listen_timer)); - intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0); - } -#endif /* CONFIG_INTEL_WIDI */ - break; - } - case P2P_INVIT_RESP: { - u8 attr_content = 0x00; - u32 attr_contentlen = 0; - - RTW_INFO("[%s] Got invite response frame!\n", __FUNCTION__); - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen); - if (p2p_ie) { - rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen); - - if (attr_contentlen == 1) { - RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content); - pwdinfo->invitereq_info.benable = _FALSE; - - if (attr_content == P2P_STATUS_SUCCESS) { - if (_rtw_memcmp(pwdinfo->invitereq_info.go_bssid, adapter_mac_addr(padapter), ETH_ALEN)) - rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO); - else - rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT); - - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK); - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL); - } - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL); - } - } else { - rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL); - } - - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL)) - _set_timer(&pwdinfo->restore_p2p_state_timer, 5000); - break; - } - case P2P_DEVDISC_REQ: - - process_p2p_devdisc_req(pwdinfo, pframe, len); - - break; - - case P2P_DEVDISC_RESP: - - process_p2p_devdisc_resp(pwdinfo, pframe, len); - - break; - - case P2P_PROVISION_DISC_REQ: - RTW_INFO("[%s] Got Provisioning Discovery Request Frame\n", __FUNCTION__); - process_p2p_provdisc_req(pwdinfo, pframe, len); - _rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN); - - /* 20110902 Kurt */ - /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) - rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo)); - - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ); - _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT); -#ifdef CONFIG_INTEL_WIDI - if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) { - 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, 0); - } -#endif /* CONFIG_INTEL_WIDI */ - break; - - case P2P_PROVISION_DISC_RESP: - /* Commented by Albert 20110707 */ - /* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */ - RTW_INFO("[%s] Got Provisioning Discovery Response Frame\n", __FUNCTION__); - /* Commented by Albert 20110426 */ - /* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */ - _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer); - rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP); - process_p2p_provdisc_resp(pwdinfo, pframe); - _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT); - break; - - } - } - - -exit: - - if (merged_p2pie) - rtw_mfree(merged_p2pie, merged_p2p_ielen + 2); -#endif /* CONFIG_P2P */ - return _SUCCESS; -} - -unsigned int on_action_public_vendor(union recv_frame *precv_frame) -{ - unsigned int ret = _FAIL; - u8 *pframe = precv_frame->u.hdr.rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - - if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE) { - if (rtw_action_public_decache(precv_frame, 7) == _FAIL) - goto exit; - - if (!hal_chk_wl_func(precv_frame->u.hdr.adapter, WL_FUNC_MIRACAST)) - rtw_rframe_del_wfd_ie(precv_frame, 8); - - ret = on_action_public_p2p(precv_frame); - } - -exit: - return ret; -} - -unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action) -{ - unsigned int ret = _FAIL; - u8 *pframe = precv_frame->u.hdr.rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - u8 token; - _adapter *adapter = precv_frame->u.hdr.adapter; - int cnt = 0; - char msg[64]; - - token = frame_body[2]; - - if (rtw_action_public_decache(precv_frame, 2) == _FAIL) - goto exit; - -#ifdef CONFIG_IOCTL_CFG80211 - cnt += sprintf((msg + cnt), "%s(token:%u)", action_public_str(action), token); - rtw_cfg80211_rx_action(adapter, precv_frame, msg); -#endif - - ret = _SUCCESS; - -exit: - return ret; -} - -unsigned int on_action_public(_adapter *padapter, union recv_frame *precv_frame) -{ - unsigned int ret = _FAIL; - u8 *pframe = precv_frame->u.hdr.rx_data; - uint frame_len = precv_frame->u.hdr.len; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - u8 category, action; - - /* check RA matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN)) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_PUBLIC) - goto exit; - - action = frame_body[1]; - switch (action) { - case ACT_PUBLIC_BSSCOEXIST: -#ifdef CONFIG_80211N_HT -#ifdef CONFIG_AP_MODE - /*20/40 BSS Coexistence Management frame is a Public Action frame*/ - if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) - rtw_process_public_act_bsscoex(padapter, pframe, frame_len); -#endif /*CONFIG_AP_MODE*/ -#endif /*CONFIG_80211N_HT*/ - break; - case ACT_PUBLIC_VENDOR: - ret = on_action_public_vendor(precv_frame); - break; - default: - ret = on_action_public_default(precv_frame, action); - break; - } - -exit: - return ret; -} - -#if defined(CONFIG_RTW_WNM) || defined(CONFIG_RTW_80211K) -static u8 rtw_wnm_nb_elem_parsing( - u8* pdata, u32 data_len, u8 from_btm, - u32 *nb_rpt_num, u8 *nb_rpt_is_same, - struct roam_nb_info *pnb, struct wnm_btm_cant *pcandidates) -{ - u8 bfound = _FALSE, ret = _SUCCESS; - u8 *ptr, *pend, *op; - u32 elem_len, subelem_len, op_len; - u32 i, nb_rpt_entries = 0; - struct nb_rpt_hdr *pie; - struct wnm_btm_cant *pcandidate; - - if ((!pdata) || (!pnb)) - return _FAIL; - - if ((from_btm) && (!pcandidates)) - return _FAIL; - - ptr = pdata; - pend = ptr + data_len; - elem_len = data_len; - subelem_len = (u32)*(pdata+1); - - for (i=0; i < RTW_MAX_NB_RPT_NUM; i++) { - if (((ptr + 7) > pend) || (elem_len < subelem_len)) - break; - - if (*ptr != 0x34) { - RTW_ERR("WNM: invalid data(0x%2x)!\n", *ptr); - ret = _FAIL; - break; - } - - pie = (struct nb_rpt_hdr *)ptr; - if (from_btm) { - op = rtw_get_ie((u8 *)(ptr+15), - WNM_BTM_CAND_PREF_SUBEID, - &op_len, (subelem_len - 15)); - } - - ptr = (u8 *)(ptr + subelem_len + 2); - elem_len -= (subelem_len +2); - subelem_len = *(ptr+1); - if (from_btm) { - pcandidate = (pcandidates + i); - _rtw_memcpy(&pcandidate->nb_rpt, pie, sizeof(struct nb_rpt_hdr)); - if (op && (op_len !=0)) { - pcandidate->preference = *(op + 2); - bfound = _TRUE; - } else - pcandidate->preference = 0; - - RTW_DBG("WNM: preference check bssid("MAC_FMT - ") ,bss_info(0x%04X), reg_class(0x%02X), ch(%d)," - " phy_type(0x%02X), preference(0x%02X)\n", - MAC_ARG(pcandidate->nb_rpt.bssid), pcandidate->nb_rpt.bss_info, - pcandidate->nb_rpt.reg_class, pcandidate->nb_rpt.ch_num, - pcandidate->nb_rpt.phy_type, pcandidate->preference); - } else { - if (_rtw_memcmp(&pnb->nb_rpt[i], pie, sizeof(struct nb_rpt_hdr)) == _FALSE) - *nb_rpt_is_same = _FALSE; - _rtw_memcpy(&pnb->nb_rpt[i], pie, sizeof(struct nb_rpt_hdr)); - } - nb_rpt_entries++; - } - - if (from_btm) - pnb->preference_en = (bfound)?_TRUE:_FALSE; - - *nb_rpt_num = nb_rpt_entries; - return ret; -} - -/* selection sorting based on preference value - * IN : nb_rpt_entries - candidate num - * IN/OUT : pcandidates - candidate list - * return : TRUE - means pcandidates is updated. - */ -static u8 rtw_wnm_candidates_sorting( - u32 nb_rpt_entries, struct wnm_btm_cant *pcandidates) -{ - u8 updated = _FALSE; - u32 i, j, pos; - struct wnm_btm_cant swap; - struct wnm_btm_cant *pcant_1, *pcant_2; - - if ((!nb_rpt_entries) || (!pcandidates)) - return updated; - - for (i=0; i < (nb_rpt_entries - 1); i++) { - pos = i; - for (j=(i + 1); j < nb_rpt_entries; j++) { - pcant_1 = pcandidates+pos; - pcant_2 = pcandidates+j; - if ((pcant_1->preference) < (pcant_2->preference)) - pos = j; - } - - if (pos != i) { - updated = _TRUE; - _rtw_memcpy(&swap, (pcandidates+i), sizeof(struct wnm_btm_cant)); - _rtw_memcpy((pcandidates+i), (pcandidates+pos), sizeof(struct wnm_btm_cant)); - _rtw_memcpy((pcandidates+pos), &swap, sizeof(struct wnm_btm_cant)); - } - } - return updated; -} - -static void rtw_wnm_nb_info_update( - u32 nb_rpt_entries, u8 from_btm, - struct roam_nb_info *pnb, struct wnm_btm_cant *pcandidates, - u8 *nb_rpt_is_same) -{ - u8 is_found; - u32 i, j; - struct wnm_btm_cant *pcand; - - if (!pnb) - return; - - pnb->nb_rpt_ch_list_num = 0; - for (i=0; inb_rpt[i], &pcand->nb_rpt, - sizeof(struct nb_rpt_hdr)) == _FALSE) - *nb_rpt_is_same = _FALSE; - _rtw_memcpy(&pnb->nb_rpt[i], &pcand->nb_rpt, sizeof(struct nb_rpt_hdr)); - } - - RTW_DBG("WNM: bssid(" MAC_FMT - ") , bss_info(0x%04X), reg_class(0x%02X), ch_num(%d), phy_type(0x%02X)\n", - MAC_ARG(pnb->nb_rpt[i].bssid), pnb->nb_rpt[i].bss_info, - pnb->nb_rpt[i].reg_class, pnb->nb_rpt[i].ch_num, - pnb->nb_rpt[i].phy_type); - - if (pnb->nb_rpt[i].ch_num == 0) - continue; - - for (j=0; jnb_rpt[i].ch_num == pnb->nb_rpt_ch_list[j].hw_value) { - is_found = _TRUE; - break; - } - } - - if (!is_found) { - pnb->nb_rpt_ch_list[pnb->nb_rpt_ch_list_num].hw_value = pnb->nb_rpt[i].ch_num; - pnb->nb_rpt_ch_list_num++; - } - } -} - -static void rtw_wnm_btm_candidate_select(_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info); - struct wlan_network *pnetwork; - u8 bfound = _FALSE; - u32 i; - - for (i = 0; i < pnb->last_nb_rpt_entries; i++) { - pnetwork = rtw_find_network( - &(pmlmepriv->scanned_queue), - pnb->nb_rpt[i].bssid); - - if (pnetwork) { - bfound = _TRUE; - break; - } - } - - if (bfound) { - _rtw_memcpy(pnb->roam_target_addr, pnb->nb_rpt[i].bssid, ETH_ALEN); - RTW_INFO("WNM : select btm entry(%d) - %s("MAC_FMT", ch%u) rssi:%d\n" - , i - , pnetwork->network.Ssid.Ssid - , MAC_ARG(pnetwork->network.MacAddress) - , pnetwork->network.Configuration.DSConfig - , (int)pnetwork->network.Rssi); - } else - _rtw_memset(pnb->roam_target_addr,0, ETH_ALEN); -} - -u32 rtw_wnm_btm_candidates_survey( - _adapter *padapter, u8* pframe, u32 elem_len, u8 from_btm) -{ - struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info); - struct wnm_btm_cant *pcandidate_list = NULL; - u8 nb_rpt_is_same = _TRUE; - u32 ret = _FAIL; - u32 nb_rpt_entries = 0; - - if (from_btm) { - u32 mlen = sizeof(struct wnm_btm_cant) * RTW_MAX_NB_RPT_NUM; - pcandidate_list = (struct wnm_btm_cant *)rtw_malloc(mlen); - if (pcandidate_list == NULL) - goto exit; - } - - /*clean the status set last time*/ - _rtw_memset(&pnb->nb_rpt_ch_list, 0, sizeof(pnb->nb_rpt_ch_list)); - pnb->nb_rpt_valid = _FALSE; - if (!rtw_wnm_nb_elem_parsing( - pframe, elem_len, from_btm, - &nb_rpt_entries, &nb_rpt_is_same, - pnb, pcandidate_list)) - goto exit; - - if (nb_rpt_entries != 0) { - if ((from_btm) && (rtw_wnm_btm_preference_cap(padapter))) - rtw_wnm_candidates_sorting(nb_rpt_entries, pcandidate_list); - - rtw_wnm_nb_info_update( - nb_rpt_entries, from_btm, - pnb, pcandidate_list, &nb_rpt_is_same); - } - - RTW_INFO("nb_rpt_is_same = %d, nb_rpt_entries = %d, last_nb_rpt_entries = %d\n", - nb_rpt_is_same, nb_rpt_entries, pnb->last_nb_rpt_entries); - if ((nb_rpt_is_same == _TRUE) && (nb_rpt_entries == pnb->last_nb_rpt_entries)) - pnb->nb_rpt_is_same = _TRUE; - else { - pnb->nb_rpt_is_same = _FALSE; - pnb->last_nb_rpt_entries = nb_rpt_entries; - } - - if ((from_btm) && (nb_rpt_entries != 0)) - rtw_wnm_btm_candidate_select(padapter); - - pnb->nb_rpt_valid = _TRUE; - ret = _SUCCESS; - -exit: - if (from_btm && pcandidate_list) - rtw_mfree((u8 *)pcandidate_list, sizeof(struct wnm_btm_cant) * RTW_MAX_NB_RPT_NUM); - - return ret; -} -#endif - -unsigned int OnAction_ft(_adapter *padapter, union recv_frame *precv_frame) -{ -#ifdef CONFIG_RTW_80211R - u32 ret = _FAIL; - u32 frame_len = 0; - u8 action_code = 0; - u8 category = 0; - u8 *pframe = NULL; - u8 *pframe_body = NULL; - u8 sta_addr[ETH_ALEN] = {0}; - u8 *pie = NULL; - u32 ft_ie_len = 0; - u32 status_code = 0; - struct mlme_ext_priv *pmlmeext = NULL; - struct mlme_ext_info *pmlmeinfo = NULL; - struct mlme_priv *pmlmepriv = NULL; - struct wlan_network *proam_target = NULL; - struct ft_roam_info *pft_roam = NULL; - _irqL irqL; - - pmlmeext = &(padapter->mlmeextpriv); - pmlmeinfo = &(pmlmeext->mlmext_info); - pmlmepriv = &(padapter->mlmepriv); - pft_roam = &(pmlmepriv->ft_roam); - pframe = precv_frame->u.hdr.rx_data; - frame_len = precv_frame->u.hdr.len; - pframe_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - category = pframe_body[0]; - - if (category != RTW_WLAN_CATEGORY_FT) - goto exit; - - action_code = pframe_body[1]; - switch (action_code) { - case RTW_WLAN_ACTION_FT_RSP: - RTW_INFO("FT: RTW_WLAN_ACTION_FT_RSP recv.\n"); - if (!_rtw_memcmp(adapter_mac_addr(padapter), &pframe_body[2], ETH_ALEN)) { - RTW_ERR("FT: Unmatched STA MAC Address "MAC_FMT"\n", MAC_ARG(&pframe_body[2])); - goto exit; - } - - status_code = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + 14)); - if (status_code != 0) { - RTW_ERR("FT: WLAN ACTION FT RESPONSE fail, status: %d\n", status_code); - goto exit; - } - - if (is_zero_mac_addr(&pframe_body[8]) || is_broadcast_mac_addr(&pframe_body[8])) { - RTW_ERR("FT: Invalid Target MAC Address "MAC_FMT"\n", MAC_ARG(padapter->mlmepriv.roam_tgt_addr)); - goto exit; - } - - pie = rtw_get_ie(pframe_body, _MDIE_, &ft_ie_len, frame_len); - if (pie) { - if (!_rtw_memcmp(&pft_roam->mdid, pie+2, 2)) { - RTW_ERR("FT: Invalid MDID\n"); - goto exit; - } - } - - rtw_ft_set_status(padapter, RTW_FT_REQUESTED_STA); - _cancel_timer_ex(&pmlmeext->ft_link_timer); - - /*Disconnect current AP*/ - receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress, WLAN_REASON_ACTIVE_ROAM, _FALSE); - - pft_roam->ft_action_len = frame_len; - _rtw_memcpy(pft_roam->ft_action, pframe, rtw_min(frame_len, RTW_FT_MAX_IE_SZ)); - ret = _SUCCESS; - break; - case RTW_WLAN_ACTION_FT_REQ: - case RTW_WLAN_ACTION_FT_CONF: - case RTW_WLAN_ACTION_FT_ACK: - default: - RTW_ERR("FT: Unsupported FT Action!\n"); - break; - } - -exit: - return ret; -#else - return _SUCCESS; -#endif -} - -#ifdef CONFIG_RTW_WNM -u8 rtw_wmn_btm_rsp_reason_decision(_adapter *padapter, u8* req_mode) -{ - struct recv_priv *precvpriv = &padapter->recvpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 reason = 0; - - if (!rtw_wnm_btm_diff_bss(padapter)) { - /* Reject - No suitable BSS transition candidates */ - reason = 7; - goto candidate_remove; - } - -#ifdef CONFIG_RTW_80211R - if (rtw_ft_chk_flags(padapter, RTW_FT_BTM_ROAM)) { - /* Accept */ - reason = 0; - goto under_survey; - } -#endif - - if (((*req_mode) & DISASSOC_IMMINENT) == 0) { - /* Reject - Unspecified reject reason */ - reason = 1; - goto candidate_remove; - } - - if (precvpriv->signal_strength_data.avg_val >= pmlmepriv->roam_rssi_threshold) { - reason = 1; - goto candidate_remove; - } - -under_survey: - if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) { - RTW_INFO("%s reject due to _FW_UNDER_SURVEY\n", __func__); - reason = 1; - } - -candidate_remove: - if (reason !=0) - rtw_wnm_reset_btm_candidate(&padapter->mlmepriv.nb_info); - - return reason; -} - -static u32 rtw_wnm_btm_candidates_offset_get(u8* pframe) -{ - u8 *pos = pframe; - u32 offset = 0; - - if (!pframe) - return 0; - - offset += 7; - pos += offset; - - /* BSS Termination Duration check */ - if (wnm_btm_bss_term_inc(pframe)) { - offset += 12; - pos += offset; - } - - /* Session Information URL check*/ - if (wnm_btm_ess_disassoc_im(pframe)) { - /*URL length field + URL variable length*/ - offset = 1 + *(pframe + offset); - pos += offset; - } - - offset = (pos - pframe); - return offset; -} - -static void rtw_wnm_btm_req_hdr_parsing(u8* pframe, struct btm_req_hdr *phdr) -{ - u8 *pos = pframe; - u32 offset = 0; - - if (!pframe || !phdr) - return; - - _rtw_memset(phdr, 0, sizeof(struct btm_req_hdr)); - phdr->req_mode = wnm_btm_req_mode(pframe); - phdr->disassoc_timer = wnm_btm_disassoc_timer(pframe); - phdr->validity_interval = wnm_btm_valid_interval(pframe); - if (wnm_btm_bss_term_inc(pframe)) { - _rtw_memcpy(&phdr->term_duration, - wnm_btm_term_duration_offset(pframe), - sizeof(struct btm_term_duration)); - } - - RTW_DBG("WNM: req_mode(%1x), disassoc_timer(%02x), interval(%x)\n", - phdr->req_mode, phdr->disassoc_timer, phdr->validity_interval); - if (wnm_btm_bss_term_inc(pframe)) - RTW_INFO("WNM: tsf(%llx), duration(%2x)\n", - phdr->term_duration.tsf, phdr->term_duration.duration); -} - -void rtw_wnm_roam_scan_hdl(void *ctx) -{ - _adapter *padapter = (_adapter *)ctx; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - if (rtw_is_scan_deny(padapter)) - RTW_INFO("WNM: roam scan would abort by scan_deny!\n"); - - pmlmepriv->need_to_roam = _TRUE; - rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM); -} - -static void rtw_wnm_roam_scan(_adapter *padapter) -{ - struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info); - - if (rtw_is_scan_deny(padapter)) { - _cancel_timer_ex(&pnb->roam_scan_timer); - _set_timer(&pnb->roam_scan_timer, 1000); - } else - rtw_wnm_roam_scan_hdl((void *)padapter); -} - -void rtw_wnm_process_btm_req(_adapter *padapter, u8* pframe, u32 frame_len) -{ - struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info); - struct btm_req_hdr req_hdr; - u8 *ptr, reason; - u32 elem_len, offset; - - rtw_wnm_btm_req_hdr_parsing(pframe, &req_hdr); - offset = rtw_wnm_btm_candidates_offset_get(pframe); - if ((offset == 0) || ((frame_len - offset) <= 15)) - return; - - ptr = (pframe + offset); - elem_len = (frame_len - offset); - rtw_wnm_btm_candidates_survey(padapter, ptr, elem_len, _TRUE); - reason = rtw_wmn_btm_rsp_reason_decision(padapter, &pframe[3]); - rtw_wnm_issue_action(padapter, - RTW_WLAN_ACTION_WNM_BTM_RSP, reason); - - if (reason == 0) - rtw_wnm_roam_scan(padapter); -} - -void rtw_wnm_reset_btm_candidate(struct roam_nb_info *pnb) -{ - pnb->preference_en = _FALSE; - _rtw_memset(pnb->roam_target_addr, 0, ETH_ALEN); -} - -void rtw_wnm_reset_btm_state(_adapter *padapter) -{ - struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info); - - pnb->last_nb_rpt_entries = 0; - pnb->nb_rpt_is_same = _TRUE; - pnb->nb_rpt_valid = _FALSE; - pnb->nb_rpt_ch_list_num = 0; - rtw_wnm_reset_btm_candidate(pnb); - _rtw_memset(&pnb->nb_rpt, 0, sizeof(pnb->nb_rpt)); - _rtw_memset(&pnb->nb_rpt_ch_list, 0, sizeof(pnb->nb_rpt_ch_list)); -} - -void rtw_wnm_issue_action(_adapter *padapter, u8 action, u8 reason) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct xmit_frame *pmgntframe; - struct rtw_ieee80211_hdr *pwlanhdr; - struct pkt_attrib *pattrib; - u8 category, dialog_token, termination_delay, *pframe; - u16 *fctrl; - - if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL) - return ; - - 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; - - _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_ACTION); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - category = RTW_WLAN_CATEGORY_WNM; - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - - switch (action) { - case RTW_WLAN_ACTION_WNM_BTM_QUERY: - pframe = rtw_set_fixed_ie(pframe, 1, &(dialog_token), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(reason), &(pattrib->pktlen)); - RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_QUERY sent.\n"); - break; - case RTW_WLAN_ACTION_WNM_BTM_RSP: - termination_delay = 0; - pframe = rtw_set_fixed_ie(pframe, 1, &(dialog_token), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(reason), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(termination_delay), &(pattrib->pktlen)); - if (!is_zero_mac_addr(pmlmepriv->nb_info.roam_target_addr)) { - pframe = rtw_set_fixed_ie(pframe, 6, - pmlmepriv->nb_info.roam_target_addr, &(pattrib->pktlen)); - } - RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_RSP sent. reason = %d\n", reason); - break; - default: - goto exit; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe(padapter, pmgntframe); - -exit: - return; -} -#endif - -unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame) -{ - u8 *pframe = precv_frame->u.hdr.rx_data; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - u8 category, action; - - /* check RA matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN)) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_HT) - goto exit; - - action = frame_body[1]; - switch (action) { - case RTW_WLAN_ACTION_HT_SM_PS: -#ifdef CONFIG_80211N_HT -#ifdef CONFIG_AP_MODE - if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) - rtw_process_ht_action_smps(padapter, get_addr2_ptr(pframe), frame_body[2]); -#endif /*CONFIG_AP_MODE*/ -#endif /*CONFIG_80211N_HT*/ - break; - case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING: -#ifdef CONFIG_BEAMFORMING - /*RTW_INFO("RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING\n");*/ - rtw_beamforming_get_report_frame(padapter, precv_frame); -#endif /*CONFIG_BEAMFORMING*/ - break; - default: - break; - } - -exit: - - 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); - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - u16 tid; - /* Baron */ - - RTW_INFO("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(u16)); - RTW_INFO("OnAction_sa_query request,action=%d, tid=%04x, pframe=%02x-%02x\n" - , pframe[WLAN_HDR_A3_LEN + 1], tid, pframe[WLAN_HDR_A3_LEN + 2], pframe[WLAN_HDR_A3_LEN + 3]); - issue_action_SA_Query(padapter, get_addr2_ptr(pframe), 1, tid, IEEE80211W_RIGHT_KEY); - break; - - case 1: /* SA Query rsp */ - psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe)); - if (psta != NULL) - _cancel_timer_ex(&psta->dot11w_expire_timer); - - _rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN + 2], sizeof(u16)); - RTW_INFO("OnAction_sa_query response,action=%d, tid=%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN + 1], tid); - 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 on_action_rm(_adapter *padapter, union recv_frame *precv_frame) -{ -#ifdef CONFIG_RTW_80211K - return rm_on_action(padapter, precv_frame); -#else - return _SUCCESS; -#endif /* CONFIG_RTW_80211K */ -} - -unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame) -{ - return _SUCCESS; -} - -unsigned int OnAction_vht(_adapter *padapter, union recv_frame *precv_frame) -{ -#ifdef CONFIG_80211AC_VHT - u8 *pframe = precv_frame->u.hdr.rx_data; - struct rtw_ieee80211_hdr_3addr *whdr = (struct rtw_ieee80211_hdr_3addr *)pframe; - u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); - u8 category, action; - struct sta_info *psta = NULL; - - /* check RA matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN)) - goto exit; - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_VHT) - goto exit; - - action = frame_body[1]; - switch (action) { - case RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING: -#ifdef CONFIG_BEAMFORMING - /*RTW_INFO("RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING\n");*/ - rtw_beamforming_get_report_frame(padapter, precv_frame); -#endif /*CONFIG_BEAMFORMING*/ - break; - case RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION: - /* CategoryCode(1) + ActionCode(1) + OpModeNotification(1) */ - /* RTW_INFO("RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION\n"); */ - psta = rtw_get_stainfo(&padapter->stapriv, whdr->addr2); - if (psta) - rtw_process_vht_op_mode_notify(padapter, &frame_body[2], psta); - break; - case RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT: -#ifdef CONFIG_BEAMFORMING -#ifdef RTW_BEAMFORMING_VERSION_2 - rtw_beamforming_get_vht_gid_mgnt_frame(padapter, precv_frame); -#endif /* RTW_BEAMFORMING_VERSION_2 */ -#endif /* CONFIG_BEAMFORMING */ - break; - default: - break; - } - -exit: -#endif /* CONFIG_80211AC_VHT */ - - return _SUCCESS; -} - -unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame) -{ -#ifdef CONFIG_P2P - u8 *frame_body; - u8 category, OUI_Subtype, dialogToken = 0; - u8 *pframe = precv_frame->u.hdr.rx_data; - uint len = precv_frame->u.hdr.len; - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - - /* check RA matches or not */ - if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN)) - return _SUCCESS; - - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - - category = frame_body[0]; - if (category != RTW_WLAN_CATEGORY_P2P) - return _SUCCESS; - - if (cpu_to_be32(*((u32 *)(frame_body + 1))) != P2POUI) - return _SUCCESS; - -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->p2p_enabled - && pwdinfo->driver_interface == DRIVER_CFG80211 - ) { - rtw_cfg80211_rx_action_p2p(padapter, precv_frame); - return _SUCCESS; - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - len -= sizeof(struct rtw_ieee80211_hdr_3addr); - OUI_Subtype = frame_body[5]; - dialogToken = frame_body[6]; - - switch (OUI_Subtype) { - case P2P_NOTICE_OF_ABSENCE: - - break; - - case P2P_PRESENCE_REQUEST: - - process_p2p_presence_req(pwdinfo, pframe, len); - - break; - - case P2P_PRESENCE_RESPONSE: - - break; - - case P2P_GO_DISC_REQUEST: - - break; - - default: - break; - - } - } -#endif /* CONFIG_P2P */ - - return _SUCCESS; - -} - -unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame) -{ - int i; - unsigned char category; - struct action_handler *ptable; - unsigned char *frame_body; - u8 *pframe = precv_frame->u.hdr.rx_data; - - frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); - - category = frame_body[0]; - - for (i = 0; i < sizeof(OnAction_tbl) / sizeof(struct action_handler); i++) { - ptable = &OnAction_tbl[i]; - - if (category == ptable->num) - ptable->func(padapter, precv_frame); - - } - - return _SUCCESS; - -} - -unsigned int DoReserved(_adapter *padapter, union recv_frame *precv_frame) -{ - - /* RTW_INFO("rcvd mgt frame(%x, %x)\n", (get_frame_sub_type(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */ - return _SUCCESS; -} - -struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once) -{ - struct xmit_frame *pmgntframe; - struct xmit_buf *pxmitbuf; - - if (once) - pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv); - else - pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv); - - if (pmgntframe == NULL) { - RTW_INFO(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once); - goto exit; - } - - pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); - if (pxmitbuf == NULL) { - RTW_INFO(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter)); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - pmgntframe = NULL; - goto exit; - } - - pmgntframe->frame_tag = MGNT_FRAMETAG; - pmgntframe->pxmitbuf = pxmitbuf; - pmgntframe->buf_addr = pxmitbuf->pbuf; - pxmitbuf->priv_data = pmgntframe; - -exit: - return pmgntframe; - -} - -inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) -{ - return _alloc_mgtxmitframe(pxmitpriv, _FALSE); -} - -inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv) -{ - return _alloc_mgtxmitframe(pxmitpriv, _TRUE); -} - - -/**************************************************************************** - -Following are some TX fuctions for WiFi MLME - -*****************************************************************************/ - -void update_mgnt_tx_rate(_adapter *padapter, u8 rate) -{ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - - pmlmeext->tx_rate = rate; - /* RTW_INFO("%s(): rate = %x\n",__FUNCTION__, rate); */ -} - - -void update_monitor_frame_attrib(_adapter *padapter, struct pkt_attrib *pattrib) -{ - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - u8 wireless_mode; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - - psta = rtw_get_stainfo(pstapriv, pattrib->ra); - - pattrib->hdrlen = 24; - pattrib->nr_frags = 1; - pattrib->priority = 7; - pattrib->mac_id = RTW_DEFAULT_MGMT_MACID; - pattrib->qsel = QSLT_MGNT; - - pattrib->pktlen = 0; - - if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB) - wireless_mode = WIRELESS_11B; - else - wireless_mode = WIRELESS_11G; - - pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode); -#ifdef CONFIG_80211AC_VHT - if (pHalData->rf_type == RF_1T1R) - pattrib->raid = RATEID_IDX_VHT_1SS; - else if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_2T4R) - pattrib->raid = RATEID_IDX_VHT_2SS; - else if (pHalData->rf_type == RF_3T3R) - pattrib->raid = RATEID_IDX_VHT_3SS; - else - pattrib->raid = RATEID_IDX_BGN_40M_1SS; -#endif - -#ifdef CONFIG_80211AC_VHT - pattrib->rate = MGN_VHT1SS_MCS9; -#else - pattrib->rate = MGN_MCS7; -#endif - - pattrib->encrypt = _NO_PRIVACY_; - pattrib->bswenc = _FALSE; - - pattrib->qos_en = _FALSE; - pattrib->ht_en = 1; - pattrib->bwmode = CHANNEL_WIDTH_20; - pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pattrib->sgi = _FALSE; - - pattrib->seqnum = pmlmeext->mgnt_seq; - - pattrib->retry_ctrl = _TRUE; - - pattrib->mbssid = 0; - pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no; - -} - - -void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib) -{ - u8 wireless_mode; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - -#ifdef CONFIG_P2P_PS_NOA_USE_MACID_SLEEP - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif /* CONFIG_P2P_PS_NOA_USE_MACID_SLEEP */ - - /* _rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */ - - pattrib->hdrlen = 24; - pattrib->nr_frags = 1; - pattrib->priority = 7; - pattrib->mac_id = RTW_DEFAULT_MGMT_MACID; - pattrib->qsel = QSLT_MGNT; - -#ifdef CONFIG_MCC_MODE - update_mcc_mgntframe_attrib(padapter, pattrib); -#endif - - -#ifdef CONFIG_P2P_PS_NOA_USE_MACID_SLEEP -#ifdef CONFIG_CONCURRENT_MODE - if (rtw_mi_buddy_check_fwstate(padapter, WIFI_ASOC_STATE)) -#endif /* CONFIG_CONCURRENT_MODE */ - if (MLME_IS_GC(padapter)) { - if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) { - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); - if (psta) { - /* use macid sleep during NoA, mgmt frame use ac queue & ap macid */ - pattrib->mac_id = psta->cmn.mac_id; - pattrib->qsel = QSLT_VO; - } else { - if (pwdinfo->p2p_ps_state != P2P_PS_DISABLE) - RTW_ERR("%s , psta was NULL\n", __func__); - } - } - } -#endif /* CONFIG_P2P_PS_NOA_USE_MACID_SLEEP */ - - - pattrib->pktlen = 0; - - if (IS_CCK_RATE(pmlmeext->tx_rate)) - wireless_mode = WIRELESS_11B; - else - wireless_mode = WIRELESS_11G; - pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode); - pattrib->rate = pmlmeext->tx_rate; - - pattrib->encrypt = _NO_PRIVACY_; - pattrib->bswenc = _FALSE; - - pattrib->qos_en = _FALSE; - pattrib->ht_en = _FALSE; - pattrib->bwmode = CHANNEL_WIDTH_20; - pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pattrib->sgi = _FALSE; - - pattrib->seqnum = pmlmeext->mgnt_seq; - - pattrib->retry_ctrl = _TRUE; - - pattrib->mbssid = 0; - pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no; -} - -void update_mgntframe_attrib_addr(_adapter *padapter, struct xmit_frame *pmgntframe) -{ - u8 *pframe; - struct pkt_attrib *pattrib = &pmgntframe->attrib; -#if defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY) - struct sta_info *sta = NULL; -#endif - - pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; - - _rtw_memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN); - _rtw_memcpy(pattrib->ta, get_addr2_ptr(pframe), ETH_ALEN); - -#if defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY) - sta = pattrib->psta; - if (!sta) { - sta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); - pattrib->psta = sta; - } - #ifdef CONFIG_BEAMFORMING - if (sta) - update_attrib_txbf_info(padapter, pattrib, sta); - #endif -#endif /* defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY) */ -} - -void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe) -{ - if (RTW_CANNOT_RUN(padapter)) { - rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); - return; - } - - rtw_hal_mgnt_xmit(padapter, pmgntframe); -} - -s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms) -{ - s32 ret = _FAIL; - _irqL irqL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; - struct submit_ctx sctx; - - if (RTW_CANNOT_RUN(padapter)) { - rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); - return ret; - } - - rtw_sctx_init(&sctx, timeout_ms); - pxmitbuf->sctx = &sctx; - - ret = rtw_hal_mgnt_xmit(padapter, pmgntframe); - - if (ret == _SUCCESS) - ret = rtw_sctx_wait(&sctx, __func__); - - _enter_critical(&pxmitpriv->lock_sctx, &irqL); - pxmitbuf->sctx = NULL; - _exit_critical(&pxmitpriv->lock_sctx, &irqL); - - return ret; -} - -s32 dump_mgntframe_and_wait_ack_timeout(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms) -{ -#ifdef CONFIG_XMIT_ACK - static u8 seq_no = 0; - s32 ret = _FAIL; - struct xmit_priv *pxmitpriv = &(GET_PRIMARY_ADAPTER(padapter))->xmitpriv; - - if (RTW_CANNOT_RUN(padapter)) { - 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; - pxmitpriv->seq_no = seq_no++; - pmgntframe->ack_report = 1; - rtw_sctx_init(&(pxmitpriv->ack_tx_ops), timeout_ms); - if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) - ret = rtw_sctx_wait(&(pxmitpriv->ack_tx_ops), __func__); - - pxmitpriv->ack_tx = _FALSE; - _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL); - - return ret; -#else /* !CONFIG_XMIT_ACK */ - dump_mgntframe(padapter, pmgntframe); - rtw_msleep_os(50); - return _SUCCESS; -#endif /* !CONFIG_XMIT_ACK */ -} - -s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntframe) -{ - /* In this case, use 500 ms as the default wait_ack timeout */ - return dump_mgntframe_and_wait_ack_timeout(padapter, pmgntframe, 500); -} - - -int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) -{ - u8 *ssid_ie; - sint ssid_len_ori; - int len_diff = 0; - - ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); - - /* RTW_INFO("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */ - - if (ssid_ie && ssid_len_ori > 0) { - switch (hidden_ssid_mode) { - case 1: { - u8 *next_ie = ssid_ie + 2 + ssid_len_ori; - u32 remain_len = 0; - - remain_len = ies_len - (next_ie - ies); - - ssid_ie[1] = 0; - _rtw_memcpy(ssid_ie + 2, next_ie, remain_len); - len_diff -= ssid_len_ori; - - break; - } - case 2: - _rtw_memset(&ssid_ie[2], 0, ssid_len_ori); - break; - default: - break; - } - } - - return len_diff; -} - -void issue_beacon(_adapter *padapter, int timeout_ms) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - unsigned int rate_len; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); -#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) - _irqL irqL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); -#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif /* CONFIG_P2P */ - - - /* RTW_INFO("%s\n", __FUNCTION__); */ - -#ifdef CONFIG_BCN_ICF - pmgntframe = rtw_alloc_bcnxmitframe(pxmitpriv); - if (pmgntframe == NULL) -#else - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) -#endif - { - RTW_INFO("%s, alloc mgnt frame fail\n", __FUNCTION__); - return; - } -#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) - _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL); -#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - pattrib->qsel = QSLT_BEACON; - -#if defined(CONFIG_CONCURRENT_MODE) && (!defined(CONFIG_SWTIMER_BASED_TXBCN)) - if (padapter->hw_port == HW_PORT1) - pattrib->mbssid = 1; -#endif -#ifdef CONFIG_FW_HANDLE_TXBCN - if (padapter->vap_id != CONFIG_LIMITED_AP_NUM) - pattrib->mbssid = padapter->vap_id; -#endif - - _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; - - _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); - - SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); - /* pmlmeext->mgnt_seq++; */ - set_frame_sub_type(pframe, WIFI_BEACON); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) { - /* RTW_INFO("ie len=%d\n", cur_network->IELength); */ -#ifdef CONFIG_P2P - /* for P2P : Primary Device Type & Device Name */ - u32 wpsielen = 0, insert_len = 0; - u8 *wpsie = NULL; - wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen); - - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) { - uint wps_offset, remainder_ielen; - u8 *premainder_ie, *pframe_wscie; - - wps_offset = (uint)(wpsie - cur_network->IEs); - - premainder_ie = wpsie + wpsielen; - - remainder_ielen = cur_network->IELength - wps_offset - wpsielen; - -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) { - if (pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len > 0) { - _rtw_memcpy(pframe, cur_network->IEs, wps_offset); - pframe += wps_offset; - pattrib->pktlen += wps_offset; - - _rtw_memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len); - pframe += pmlmepriv->wps_beacon_ie_len; - pattrib->pktlen += pmlmepriv->wps_beacon_ie_len; - - /* copy remainder_ie to pframe */ - _rtw_memcpy(pframe, premainder_ie, remainder_ielen); - pframe += remainder_ielen; - pattrib->pktlen += remainder_ielen; - } else { - _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength); - pframe += cur_network->IELength; - pattrib->pktlen += cur_network->IELength; - } - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - pframe_wscie = pframe + wps_offset; - _rtw_memcpy(pframe, cur_network->IEs, wps_offset + wpsielen); - pframe += (wps_offset + wpsielen); - pattrib->pktlen += (wps_offset + wpsielen); - - /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */ - /* Primary Device Type */ - /* Type: */ - *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE); - insert_len += 2; - - /* Length: */ - *(u16 *)(pframe + insert_len) = cpu_to_be16(0x0008); - insert_len += 2; - - /* Value: */ - /* Category ID */ - *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - insert_len += 2; - - /* OUI */ - *(u32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI); - insert_len += 4; - - /* Sub Category ID */ - *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - insert_len += 2; - - - /* Device Name */ - /* Type: */ - *(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - insert_len += 2; - - /* Length: */ - *(u16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len); - insert_len += 2; - - /* Value: */ - _rtw_memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len); - insert_len += pwdinfo->device_name_len; - - - /* update wsc ie length */ - *(pframe_wscie + 1) = (wpsielen - 2) + insert_len; - - /* pframe move to end */ - pframe += insert_len; - pattrib->pktlen += insert_len; - - /* copy remainder_ie to pframe */ - _rtw_memcpy(pframe, premainder_ie, remainder_ielen); - pframe += remainder_ielen; - pattrib->pktlen += remainder_ielen; - } - } else -#endif /* CONFIG_P2P */ - { - int len_diff; - _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength); - len_diff = update_hidden_ssid( - pframe + _BEACON_IE_OFFSET_ - , cur_network->IELength - _BEACON_IE_OFFSET_ - , pmlmeinfo->hidden_ssid_mode - ); - pframe += (cur_network->IELength + len_diff); - pattrib->pktlen += (cur_network->IELength + len_diff); - } - - { - u8 *wps_ie; - uint wps_ielen; - u8 sr = 0; - wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, - pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen); - if (wps_ie && wps_ielen > 0) - rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); - if (sr != 0) - set_fwstate(pmlmepriv, WIFI_UNDER_WPS); - else - _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); - } - -#ifdef CONFIG_RTW_80211K - pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_, - sizeof(padapter->rmpriv.rm_en_cap_def), - padapter->rmpriv.rm_en_cap_def, &pattrib->pktlen); -#endif - -#ifdef CONFIG_P2P - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - u32 len; -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) { - len = pmlmepriv->p2p_beacon_ie_len; - if (pmlmepriv->p2p_beacon_ie && len > 0) - _rtw_memcpy(pframe, pmlmepriv->p2p_beacon_ie, len); - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - len = build_beacon_p2p_ie(pwdinfo, pframe); - } - - pframe += len; - pattrib->pktlen += len; - -#ifdef CONFIG_MCC_MODE - pframe = rtw_hal_mcc_append_go_p2p_ie(padapter, pframe, &pattrib->pktlen); -#endif /* CONFIG_MCC_MODE*/ - -#ifdef CONFIG_WFD - len = rtw_append_beacon_wfd_ie(padapter, pframe); - pframe += len; - pattrib->pktlen += len; -#endif - } -#endif /* CONFIG_P2P */ -#ifdef CONFIG_RTW_REPEATER_SON - rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen); -#endif -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE - pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_BEACON_VENDOR_IE_BIT); -#endif - -#ifdef CONFIG_RTL8812A - pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen ); -#endif/*CONFIG_RTL8812A*/ - - goto _issue_bcn; - - } - - /* below for ad-hoc mode */ - - /* timestamp will be inserted by hardware */ - pframe += 8; - pattrib->pktlen += 8; - - /* beacon interval: 2 bytes */ - - _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* capability info: 2 bytes */ - - _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len(cur_network->SupportedRates); - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); - - /* if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */ - { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->Configuration.ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); - } - - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); - - - /* todo:HT for adhoc */ - -_issue_bcn: - -#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) - pmlmepriv->update_bcn = _FALSE; - - _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL); -#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ - - if ((pattrib->pktlen + TXDESC_SIZE) > MAX_BEACON_LEN) { - RTW_ERR("beacon frame too large ,len(%d,%d)\n", - (pattrib->pktlen + TXDESC_SIZE), MAX_BEACON_LEN); - rtw_warn_on(1); - return; - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - /* RTW_INFO("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */ - if (timeout_ms > 0) - dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms); - else - dump_mgntframe(padapter, pmgntframe); - -} - -void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - unsigned char *mac, *bssid; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); -#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) - u8 *pwps_ie; - uint wps_ielen; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; -#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); - unsigned int rate_len; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif /* CONFIG_P2P */ - - /* RTW_INFO("%s\n", __FUNCTION__); */ - - if (da == NULL) - return; - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - return; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) { - RTW_INFO("%s, alloc mgnt frame 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; - - mac = adapter_mac_addr(padapter); - bssid = cur_network->MacAddress; - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(fctrl, WIFI_PROBERSP); - - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = pattrib->hdrlen; - pframe += pattrib->hdrlen; - - - if (cur_network->IELength > MAX_IE_SZ) - return; - -#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) - if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen); - - /* inerset & update wps_probe_resp_ie */ - if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) { - uint wps_offset, remainder_ielen; - u8 *premainder_ie; - - wps_offset = (uint)(pwps_ie - cur_network->IEs); - - premainder_ie = pwps_ie + wps_ielen; - - remainder_ielen = cur_network->IELength - wps_offset - wps_ielen; - - _rtw_memcpy(pframe, cur_network->IEs, wps_offset); - pframe += wps_offset; - pattrib->pktlen += wps_offset; - - wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */ - if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) { - _rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2); - pframe += wps_ielen + 2; - pattrib->pktlen += wps_ielen + 2; - } - - if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { - _rtw_memcpy(pframe, premainder_ie, remainder_ielen); - pframe += remainder_ielen; - pattrib->pktlen += remainder_ielen; - } - } else { - _rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength); - pframe += cur_network->IELength; - pattrib->pktlen += cur_network->IELength; - } - - /* retrieve SSID IE from cur_network->Ssid */ - { - u8 *ssid_ie; - sint ssid_ielen; - sint ssid_ielen_diff; - u8 buf[MAX_IE_SZ]; - u8 *ies = pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr); - - ssid_ie = rtw_get_ie(ies + _FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen, - (pframe - ies) - _FIXED_IE_LENGTH_); - - ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen; - - if (ssid_ie && cur_network->Ssid.SsidLength) { - uint remainder_ielen; - u8 *remainder_ie; - remainder_ie = ssid_ie + 2; - remainder_ielen = (pframe - remainder_ie); - - if (remainder_ielen > MAX_IE_SZ) { - RTW_WARN(FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter)); - remainder_ielen = MAX_IE_SZ; - } - - _rtw_memcpy(buf, remainder_ie, remainder_ielen); - _rtw_memcpy(remainder_ie + ssid_ielen_diff, buf, remainder_ielen); - *(ssid_ie + 1) = cur_network->Ssid.SsidLength; - _rtw_memcpy(ssid_ie + 2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength); - - pframe += ssid_ielen_diff; - pattrib->pktlen += ssid_ielen_diff; - } - } -#ifdef CONFIG_RTW_REPEATER_SON - rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen); -#endif -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE - pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_PROBERESP_VENDOR_IE_BIT); -#endif - } else -#endif - { - - /* timestamp will be inserted by hardware */ - pframe += 8; - pattrib->pktlen += 8; - - /* beacon interval: 2 bytes */ - - _rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* capability info: 2 bytes */ - - _rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); - - pframe += 2; - pattrib->pktlen += 2; - - /* below for ad-hoc mode */ - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); - - /* supported rates... */ - rate_len = rtw_get_rateset_len(cur_network->SupportedRates); - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); - - /* DS parameter set */ - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - u8 erpinfo = 0; - u32 ATIMWindow; - /* IBSS Parameter Set... */ - /* ATIMWindow = cur->Configuration.ATIMWindow; */ - ATIMWindow = 0; - pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); - - /* ERP IE */ - pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); - } - - - /* EXTERNDED SUPPORTED RATE */ - if (rate_len > 8) - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); - - - /* todo:HT for adhoc */ - - } - -#ifdef CONFIG_RTW_80211K - pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_, - sizeof(padapter->rmpriv.rm_en_cap_def), - padapter->rmpriv.rm_en_cap_def, &pattrib->pktlen); -#endif - -#ifdef CONFIG_P2P - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) - /* IOT issue, When wifi_spec is not set, send probe_resp with P2P IE even if probe_req has no P2P IE */ - && (is_valid_p2p_probereq || !padapter->registrypriv.wifi_spec)) { - u32 len; -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->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; - if (pmlmepriv->p2p_go_probe_resp_ie && len > 0) - _rtw_memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len); - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - len = build_probe_resp_p2p_ie(pwdinfo, pframe); - } - - pframe += len; - pattrib->pktlen += len; - -#ifdef CONFIG_MCC_MODE - pframe = rtw_hal_mcc_append_go_p2p_ie(padapter, pframe, &pattrib->pktlen); -#endif /* CONFIG_MCC_MODE*/ - -#ifdef CONFIG_WFD - len = rtw_append_probe_resp_wfd_ie(padapter, pframe); - pframe += len; - pattrib->pktlen += len; -#endif - } -#endif /* CONFIG_P2P */ - - -#ifdef CONFIG_AUTO_AP_MODE - { - struct sta_info *psta; - struct sta_priv *pstapriv = &padapter->stapriv; - - RTW_INFO("(%s)\n", __FUNCTION__); - - /* check rc station */ - psta = rtw_get_stainfo(pstapriv, da); - if (psta && psta->isrc && psta->pid > 0) { - u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A}; - u8 RC_INFO[14] = {0}; - /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */ - u16 cu_ch = (u16)cur_network->Configuration.DSConfig; - - RTW_INFO("%s, reply rc(pid=0x%x) device "MAC_FMT" in ch=%d\n", __FUNCTION__, - psta->pid, MAC_ARG(psta->cmn.mac_addr), cu_ch); - - /* append vendor specific ie */ - _rtw_memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI)); - _rtw_memcpy(&RC_INFO[4], mac, ETH_ALEN); - _rtw_memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2); - _rtw_memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2); - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen); - } - } -#endif /* CONFIG_AUTO_AP_MODE */ - -#ifdef CONFIG_RTL8812A - pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen); -#endif/*CONFIG_RTL8812A*/ - - pattrib->last_txcmdsz = pattrib->pktlen; - - - dump_mgntframe(padapter, pmgntframe); - - return; - -} - -int _issue_probereq(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da, u8 ch, bool append_wps, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - unsigned char *mac; - unsigned char bssrate[NumRates]; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - int bssrate_len = 0; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); -#endif - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* 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; - -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - if ((pwdev_priv->pno_mac_addr[0] != 0xFF) - && (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE) - && (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) - mac = pwdev_priv->pno_mac_addr; - else -#endif - mac = adapter_mac_addr(padapter); - - fctrl = &(pwlanhdr->frame_ctl); - *(fctrl) = 0; - - if (da) { - /* unicast probe request frame */ - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN); - } else { - /* broadcast probe request frame */ - _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); - } - - _rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN); - -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - if ((pwdev_priv->pno_mac_addr[0] != 0xFF) - && (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE) - && (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) { -#ifdef CONFIG_RTW_DEBUG - RTW_DBG("%s pno_scan_seq_num: %d\n", __func__, - pwdev_priv->pno_scan_seq_num); -#endif - SetSeqNum(pwlanhdr, pwdev_priv->pno_scan_seq_num); - pattrib->seqnum = pwdev_priv->pno_scan_seq_num; - pattrib->qos_en = 1; - pwdev_priv->pno_scan_seq_num++; - } else -#endif - { - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - } - set_frame_sub_type(pframe, WIFI_PROBEREQ); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - if (pssid && !MLME_IS_MESH(padapter)) - pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen)); - else - pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen)); - - get_rate_set(padapter, bssrate, &bssrate_len); - - if (bssrate_len > 8) { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen)); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); - } else - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen)); - - if (ch) - pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen); - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(padapter)) { - if (pssid) - pframe = rtw_set_ie_mesh_id(pframe, &pattrib->pktlen, pssid->Ssid, pssid->SsidLength); - else - pframe = rtw_set_ie_mesh_id(pframe, &pattrib->pktlen, NULL, 0); - } -#endif - - if (append_wps) { - /* add wps_ie for wps2.0 */ - if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) { - _rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); - pframe += pmlmepriv->wps_probe_req_ie_len; - pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; - /* pmlmepriv->wps_probe_req_ie_len = 0 ; */ /* reset to zero */ - } - } -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE - pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_PROBEREQ_VENDOR_IE_BIT); -#endif - -#ifdef CONFIG_RTL8812A - pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen ); -#endif/*CONFIG_RTL8812A*/ - - - pattrib->last_txcmdsz = pattrib->pktlen; - - - if (wait_ack) - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -inline void issue_probereq(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da) -{ - _issue_probereq(padapter, pssid, da, 0, 1, _FALSE); -} - -/* - * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - * try_cnt means the maximal TX count to try - */ -int issue_probereq_ex(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da, u8 ch, bool append_wps, - int try_cnt, int wait_ms) -{ - int ret = _FAIL; - int i = 0; - systime start = rtw_get_current_time(); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - do { - ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms > 0 ? _TRUE : _FALSE); - - i++; - - if (RTW_CANNOT_RUN(padapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - goto exit; -#endif - } - - if (try_cnt && wait_ms) { - if (da) - RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - else - RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } -exit: - return ret; -} - -/* if psta == NULL, indiate we are station(client) now... */ -void issue_auth(_adapter *padapter, struct sta_info *psta, unsigned short status) -{ - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - unsigned int val32; - unsigned short val16; - int use_shared_key = 0; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - return; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == 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; - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_AUTH); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - - if (psta) { /* for AP mode */ -#ifdef CONFIG_NATIVEAP_MLME - - _rtw_memcpy(pwlanhdr->addr1, psta->cmn.mac_addr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN); - - - /* setting auth algo number */ - val16 = (u16)psta->authalg; - - if (status != _STATS_SUCCESSFUL_) - val16 = 0; - - if (val16) { - val16 = cpu_to_le16(val16); - use_shared_key = 1; - } - - pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen)); - - /* setting auth seq number */ - val16 = (u16)psta->auth_seq; - val16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen)); - - /* setting status code... */ - val16 = status; - val16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen)); - - /* added challenging text... */ - if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) - pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen)); -#endif - } else { - _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - -#ifdef CONFIG_RTW_80211R - if (rtw_ft_roam(padapter)) { - /* 2: 802.11R FTAA */ - val16 = cpu_to_le16(2); - } else -#endif - { - /* setting auth algo number */ - val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0; /* 0:OPEN System, 1:Shared key */ - if (val16) { - val16 = cpu_to_le16(val16); - use_shared_key = 1; - } - } - - /* RTW_INFO("%s auth_algo= %s auth_seq=%d\n",__FUNCTION__,(pmlmeinfo->auth_algo==0)?"OPEN":"SHARED",pmlmeinfo->auth_seq); */ - - /* setting IV for auth seq #3 */ - if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { - /* RTW_INFO("==> iv(%d),key_index(%d)\n",pmlmeinfo->iv,pmlmeinfo->key_index); */ - val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30)); - val32 = cpu_to_le32(val32); - pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&val32, &(pattrib->pktlen)); - - pattrib->iv_len = 4; - } - - pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen)); - - /* setting auth seq number */ - val16 = pmlmeinfo->auth_seq; - val16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen)); - - - /* setting status code... */ - val16 = status; - val16 = cpu_to_le16(val16); - pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen)); - -#ifdef CONFIG_RTW_80211R - rtw_ft_build_auth_req_ies(padapter, pattrib, &pframe); -#endif - - /* then checking to see if sending challenging text... */ - if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { - pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen)); - - SetPrivacy(fctrl); - - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - pattrib->encrypt = _WEP40_; - - pattrib->icv_len = 4; - - pattrib->pktlen += pattrib->icv_len; - - } - - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - rtw_wep_encrypt(padapter, (u8 *)pmgntframe); - RTW_INFO("%s\n", __FUNCTION__); - dump_mgntframe(padapter, pmgntframe); - - return; -} - - -void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) -{ -#ifdef CONFIG_AP_MODE - struct xmit_frame *pmgntframe; - struct rtw_ieee80211_hdr *pwlanhdr; - struct pkt_attrib *pattrib; - unsigned char *pbuf, *pframe; - unsigned short val, ie_status; - unsigned short *fctrl; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - 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); - u8 *ie = pnetwork->IEs; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif - -#endif /* CONFIG_P2P */ - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - return; - - RTW_INFO("%s\n", __FUNCTION__); - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == 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; - - _rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->cmn.mac_addr, ETH_ALEN); - _rtw_memcpy((void *)get_addr2_ptr(pwlanhdr), adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) - set_frame_sub_type(pwlanhdr, pkt_type); - else - return; - - pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen += pattrib->hdrlen; - pframe += pattrib->hdrlen; - - /* capability */ - val = *(unsigned short *)rtw_get_capability_from_ie(ie); - - pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen)); - - ie_status = cpu_to_le16(status); - pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&ie_status, &(pattrib->pktlen)); - - val = cpu_to_le16(pstat->cmn.aid | BIT(14) | BIT(15)); - pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&val, &(pattrib->pktlen)); - - if (pstat->bssratelen <= 8) - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen)); - else { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen)); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen - 8), pstat->bssrateset + 8, &(pattrib->pktlen)); - } - -#ifdef CONFIG_IEEE80211W - if (status == _STATS_REFUSED_TEMPORARILY_) { - u8 timeout_itvl[5]; - u32 timeout_interval = 3000; - /* Association Comeback time */ - timeout_itvl[0] = 0x03; - timeout_interval = cpu_to_le32(timeout_interval); - _rtw_memcpy(timeout_itvl + 1, &timeout_interval, 4); - pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen)); - } -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_80211N_HT - if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) { - uint ie_len = 0; - - /* FILL HT CAP INFO IE */ - /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) { - _rtw_memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - } - - /* FILL HT ADD INFO IE */ - /* p = hostapd_eid_ht_operation(hapd, p); */ - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) { - _rtw_memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - } - - } -#endif - - /*adding EXT_CAPAB_IE */ - if (pmlmepriv->ext_capab_ie_len > 0) { - uint ie_len = 0; - - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) { - _rtw_memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - } - } - -#ifdef CONFIG_80211AC_VHT - if ((pstat->flags & WLAN_STA_VHT) && (pmlmepriv->vhtpriv.vht_option) - && (pstat->wpa_pairwise_cipher != WPA_CIPHER_TKIP) - && (pstat->wpa2_pairwise_cipher != WPA_CIPHER_TKIP)) { - u32 ie_len = 0; - - /* FILL VHT CAP IE */ - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) { - _rtw_memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - } - - /* FILL VHT OPERATION IE */ - pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTOperation, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); - if (pbuf && ie_len > 0) { - _rtw_memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - } - } -#endif /* CONFIG_80211AC_VHT */ - - /* FILL WMM IE */ - if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) { - uint ie_len = 0; - unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; - - for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) { - pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); - if (pbuf && _rtw_memcmp(pbuf + 2, WMM_PARA_IE, 6)) { - _rtw_memcpy(pframe, pbuf, ie_len + 2); - pframe += (ie_len + 2); - pattrib->pktlen += (ie_len + 2); - - break; - } - - if ((pbuf == NULL) || (ie_len == 0)) - break; - } - - } - - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen)); - - /* add WPS IE ie for wps 2.0 */ - if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) { - _rtw_memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len); - - pframe += pmlmepriv->wps_assoc_resp_ie_len; - pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len; - } - -#ifdef CONFIG_P2P - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE)) { - u32 len; - - if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) { - len = 0; - if (pmlmepriv->p2p_assoc_resp_ie && pmlmepriv->p2p_assoc_resp_ie_len > 0) { - len = pmlmepriv->p2p_assoc_resp_ie_len; - _rtw_memcpy(pframe, pmlmepriv->p2p_assoc_resp_ie, len); - } - } else - len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code); - pframe += len; - pattrib->pktlen += len; - } - -#ifdef CONFIG_WFD - if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) { - wfdielen = rtw_append_assoc_resp_wfd_ie(padapter, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; - } -#endif - -#endif /* CONFIG_P2P */ -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE - pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_ASSOCRESP_VENDOR_IE_BIT); -#endif - -#ifdef CONFIG_RTL8812A - pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen ); -#endif/*CONFIG_RTL8812A*/ - - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - -#endif -} - -void _issue_assocreq(_adapter *padapter, u8 is_reassoc) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - unsigned short val16; - unsigned int i, j, index = 0; - unsigned char bssrate[NumRates], sta_bssrate[NumRates]; - PNDIS_802_11_VARIABLE_IEs pIE; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - int bssrate_len = 0, sta_bssrate_len = 0; - u8 vs_ie_length = 0; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - u8 p2pie[255] = { 0x00 }; - u16 p2pielen = 0; -#ifdef CONFIG_WFD - u32 wfdielen = 0; -#endif -#endif /* CONFIG_P2P */ - -#ifdef CONFIG_DFS - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - u16 cap; - - /* Dot H */ - u8 pow_cap_ele[2] = { 0x00 }; - u8 sup_ch[30 * 2] = {0x00 }, sup_ch_idx = 0, idx_5g = 2; /* For supported channel */ -#endif /* CONFIG_DFS */ - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* 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; - _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - if (is_reassoc == _TRUE) - set_frame_sub_type(pframe, WIFI_REASSOCREQ); - else - set_frame_sub_type(pframe, WIFI_ASSOCREQ); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - /* caps */ - -#ifdef CONFIG_DFS - _rtw_memcpy(&cap, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); - cap |= cap_SpecMgmt; - _rtw_memcpy(pframe, &cap, 2); -#else - _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); -#endif /* CONFIG_DFS */ - - pframe += 2; - pattrib->pktlen += 2; - - /* listen interval */ - /* todo: listen interval for power saving */ - val16 = cpu_to_le16(3); - _rtw_memcpy(pframe , (unsigned char *)&val16, 2); - pframe += 2; - pattrib->pktlen += 2; - - /*Construct Current AP Field for Reassoc-Req only*/ - if (is_reassoc == _TRUE) { - _rtw_memcpy(pframe, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - pframe += ETH_ALEN; - pattrib->pktlen += ETH_ALEN; - } - - /* SSID */ - pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen)); - -#ifdef CONFIG_DFS - /* Dot H */ - if (pmlmeext->cur_channel > 14) { - pow_cap_ele[0] = 13; /* Minimum transmit power capability */ - pow_cap_ele[1] = 21; /* Maximum transmit power capability */ - pframe = rtw_set_ie(pframe, EID_PowerCap, 2, pow_cap_ele, &(pattrib->pktlen)); - - /* supported channels */ - while (sup_ch_idx < rfctl->max_chan_nums && rfctl->channel_set[sup_ch_idx].ChannelNum != 0) { - if (rfctl->channel_set[sup_ch_idx].ChannelNum <= 14) { - /* TODO: fix 2.4G supported channel when channel doesn't start from 1 and continuous */ - sup_ch[0] = 1; /* First channel number */ - sup_ch[1] = rfctl->channel_set[sup_ch_idx].ChannelNum; /* Number of channel */ - } else { - sup_ch[idx_5g++] = rfctl->channel_set[sup_ch_idx].ChannelNum; - sup_ch[idx_5g++] = 1; - } - sup_ch_idx++; - } - pframe = rtw_set_ie(pframe, EID_SupportedChannels, idx_5g, sup_ch, &(pattrib->pktlen)); - } -#endif /* CONFIG_DFS */ - - /* supported rate & extended supported rate */ - -#if 1 /* Check if the AP's supported rates are also supported by STA. */ - get_rate_set(padapter, sta_bssrate, &sta_bssrate_len); - /* RTW_INFO("sta_bssrate_len=%d\n", sta_bssrate_len); */ - - if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */ - sta_bssrate_len = 4; - - - /* for (i = 0; i < sta_bssrate_len; i++) { */ - /* RTW_INFO("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */ - /* } */ - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - RTW_INFO("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]); - } - - - for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { - if (pmlmeinfo->network.SupportedRates[i] == 0) - break; - - - /* Check if the AP's supported rates are also supported by STA. */ - for (j = 0; j < sta_bssrate_len; j++) { - /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ - if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK) - == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) { - /* RTW_INFO("match i = %d, j=%d\n", i, j); */ - break; - } else { - /* RTW_INFO("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */ - } - } - - if (j == sta_bssrate_len) { - /* the rate is not supported by STA */ - RTW_INFO("%s(): the rate[%d]=%02X is not supported by STA!\n", __FUNCTION__, i, pmlmeinfo->network.SupportedRates[i]); - } else { - /* the rate is supported by STA */ - bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; - } - } - - bssrate_len = index; - RTW_INFO("bssrate_len = %d\n", bssrate_len); - -#else /* Check if the AP's supported rates are also supported by STA. */ -#if 0 - get_rate_set(padapter, bssrate, &bssrate_len); -#else - for (bssrate_len = 0; bssrate_len < NumRates; bssrate_len++) { - if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0) - break; - - if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0x2C) /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ - break; - - bssrate[bssrate_len] = pmlmeinfo->network.SupportedRates[bssrate_len]; - } -#endif -#endif /* Check if the AP's supported rates are also supported by STA. */ - - if ((bssrate_len == 0) && (pmlmeinfo->network.SupportedRates[0] != 0)) { - rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); - rtw_free_xmitframe(pxmitpriv, pmgntframe); - goto exit; /* don't connect to AP if no joint supported rate */ - } - - - if (bssrate_len > 8) { - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen)); - pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); - } else if (bssrate_len > 0) - pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen)); - else - RTW_INFO("%s: Connect to AP without 11b and 11g data rate!\n", __FUNCTION__); - -#ifdef CONFIG_RTW_80211K - if (pmlmeinfo->network.PhyInfo.rm_en_cap[0] /* RM Enabled Capabilities */ - | pmlmeinfo->network.PhyInfo.rm_en_cap[1] - | pmlmeinfo->network.PhyInfo.rm_en_cap[2] - | pmlmeinfo->network.PhyInfo.rm_en_cap[3] - | pmlmeinfo->network.PhyInfo.rm_en_cap[4]) - pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_, 5, - (u8 *)padapter->rmpriv.rm_en_cap_def, &(pattrib->pktlen)); -#endif /* CONFIG_RTW_80211K */ - - /* vendor specific IE, such as WPA, WMM, WPS */ - for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;) { - pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: - if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) || - (_rtw_memcmp(pIE->data, WMM_OUI, 4)) || - (_rtw_memcmp(pIE->data, WPS_OUI, 4))) { - vs_ie_length = pIE->Length; - if ((!padapter->registrypriv.wifi_spec) && (_rtw_memcmp(pIE->data, WPS_OUI, 4))) { - /* Commented by Kurt 20110629 */ - /* In some older APs, WPS handshake */ - /* would be fail if we append vender extensions informations to AP */ - - vs_ie_length = 14; - } - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen)); - } - break; - - case EID_WPA2: -#ifdef CONFIG_RTW_80211R - if ((is_reassoc) && (rtw_ft_roam(padapter))) { - rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe); - } else -#endif - { -#ifdef CONFIG_IOCTL_CFG80211 - if (rtw_sec_chk_auth_alg(padapter, WLAN_AUTH_OPEN) && - rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE)) { - s32 entry = rtw_cached_pmkid(padapter, pmlmepriv->assoc_bssid); - - rtw_rsn_sync_pmkid(padapter, (u8 *)pIE, (pIE->Length + 2), entry); - } -#endif /* CONFIG_IOCTL_CFG80211 */ - - pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen)); - } - break; -#ifdef CONFIG_80211N_HT - case EID_HTCapability: - if (padapter->mlmepriv.htpriv.ht_option == _TRUE) { - if (!(is_ap_in_tkip(padapter))) { - _rtw_memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element)); - - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info); - - pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); - } - } - break; - - case EID_EXTCapability: - if (padapter->mlmepriv.htpriv.ht_option == _TRUE) - pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen)); - break; -#endif /* CONFIG_80211N_HT */ -#ifdef CONFIG_80211AC_VHT - case EID_VHTCapability: - if (padapter->mlmepriv.vhtpriv.vht_option == _TRUE) - pframe = rtw_set_ie(pframe, EID_VHTCapability, pIE->Length, pIE->data, &(pattrib->pktlen)); - break; - - case EID_OpModeNotification: - if (padapter->mlmepriv.vhtpriv.vht_option == _TRUE) - pframe = rtw_set_ie(pframe, EID_OpModeNotification, pIE->Length, pIE->data, &(pattrib->pktlen)); - break; -#endif /* CONFIG_80211AC_VHT */ - default: - break; - } - - i += (pIE->Length + 2); - } - - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen)); - - -#ifdef CONFIG_WAPI_SUPPORT - rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib); -#endif - - -#ifdef CONFIG_P2P - -#ifdef CONFIG_IOCTL_CFG80211 - if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) { - if (pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len > 0) { - _rtw_memcpy(pframe, pmlmepriv->p2p_assoc_req_ie, pmlmepriv->p2p_assoc_req_ie_len); - pframe += pmlmepriv->p2p_assoc_req_ie_len; - pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len; - } - } else -#endif /* CONFIG_IOCTL_CFG80211 */ - { - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) { - /* Should add the P2P IE in the association request frame. */ - /* P2P OUI */ - - p2pielen = 0; - p2pie[p2pielen++] = 0x50; - p2pie[p2pielen++] = 0x6F; - p2pie[p2pielen++] = 0x9A; - p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */ - - /* Commented by Albert 20101109 */ - /* According to the P2P Specification, the association request frame should contain 3 P2P attributes */ - /* 1. P2P Capability */ - /* 2. Extended Listen Timing */ - /* 3. Device Info */ - /* Commented by Albert 20110516 */ - /* 4. P2P Interface */ - - /* P2P Capability */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_CAPABILITY; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002); - p2pielen += 2; - - /* Value: */ - /* Device Capability Bitmap, 1 byte */ - p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT; - - /* Group Capability Bitmap, 1 byte */ - if (pwdinfo->persistent_supported) - p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT; - else - p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT; - - /* Extended Listen Timing */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004); - p2pielen += 2; - - /* Value: */ - /* Availability Period */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Availability Interval */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF); - p2pielen += 2; - - /* Device Info */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO; - - /* Length: */ - /* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */ - /* + 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); - p2pielen += 2; - - /* Value: */ - /* P2P Device Address */ - _rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN); - p2pielen += ETH_ALEN; - - /* Config Method */ - /* This field should be big endian. Noted by P2P specification. */ - if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) || - (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)) - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY); - else - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC); - - p2pielen += 2; - - /* Primary Device Type */ - /* Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA); - p2pielen += 2; - - /* OUI */ - *(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI); - p2pielen += 4; - - /* Sub Category ID */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER); - p2pielen += 2; - - /* Number of Secondary Device Types */ - p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */ - - /* Device Name */ - /* Type: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME); - p2pielen += 2; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len); - p2pielen += 2; - - /* Value: */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len); - p2pielen += pwdinfo->device_name_len; - - /* P2P Interface */ - /* Type: */ - p2pie[p2pielen++] = P2P_ATTR_INTERFACE; - - /* Length: */ - *(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D); - p2pielen += 2; - - /* Value: */ - _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Device Address */ - p2pielen += ETH_ALEN; - - p2pie[p2pielen++] = 1; /* P2P Interface Address Count */ - - _rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Interface Address List */ - p2pielen += ETH_ALEN; - - pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen); - } - } - -#ifdef CONFIG_WFD - wfdielen = rtw_append_assoc_req_wfd_ie(padapter, pframe); - pframe += wfdielen; - pattrib->pktlen += wfdielen; -#endif -#endif /* CONFIG_P2P */ - -#ifdef CONFIG_RTW_REPEATER_SON - rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen); -#endif -#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE - pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_ASSOCREQ_VENDOR_IE_BIT); -#endif - -#ifdef CONFIG_RTL8812A - pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen ); -#endif/*CONFIG_RTL8812A*/ - -#ifdef CONFIG_RTW_80211R - rtw_ft_build_assoc_req_ies(padapter, is_reassoc, pattrib, &pframe); -#endif - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe(padapter, pmgntframe); - - ret = _SUCCESS; - -exit: - if (ret == _SUCCESS) - rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen); - else - rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len); - - return; -} - -void issue_assocreq(_adapter *padapter) -{ - _issue_assocreq(padapter, _FALSE); -} - -void issue_reassocreq(_adapter *padapter) -{ - _issue_assocreq(padapter, _TRUE); -} - -/* when wait_ack is ture, this function shoule be called at process context */ -static int _issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - struct xmit_priv *pxmitpriv; - struct mlme_ext_priv *pmlmeext; - struct mlme_ext_info *pmlmeinfo; - u8 a4_shift; - - /* RTW_INFO("%s:%d\n", __FUNCTION__, power_mode); */ - - if (!padapter) - goto exit; - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - pxmitpriv = &(padapter->xmitpriv); - pmlmeext = &(padapter->mlmeextpriv); - pmlmeinfo = &(pmlmeext->mlmext_info); - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - pattrib->retry_ctrl = _FALSE; - - _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 (MLME_IS_AP(padapter)) - SetFrDs(fctrl); - else if (MLME_IS_STA(padapter)) - SetToDs(fctrl); - else if (MLME_IS_MESH(padapter)) { - SetToDs(fctrl); - SetFrDs(fctrl); - } - - if (power_mode) - SetPwrMgt(fctrl); - - if (get_tofr_ds(fctrl) == 3) { - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr4, adapter_mac_addr(padapter), ETH_ALEN); - a4_shift = ETH_ALEN; - pattrib->hdrlen += ETH_ALEN; - } else { - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - a4_shift = 0; - } - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_DATA_NULL); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr) + a4_shift; - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr) + a4_shift; - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* - * When wait_ms > 0, this function should be called at process context - * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - * try_cnt means the maximal TX count to try - * da == NULL for station mode - */ -int issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) -{ - int ret = _FAIL; - int i = 0; - systime start = rtw_get_current_time(); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - /* da == NULL, assum it's null data for sta to ap */ - if (da == NULL) - da = get_my_bssid(&(pmlmeinfo->network)); - - do { - ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? _TRUE : _FALSE); - - i++; - - if (RTW_CANNOT_RUN(padapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - goto exit; -#endif - } - - if (try_cnt && wait_ms) { - if (da) - RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - else - RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } -exit: - return ret; -} - -/* when wait_ack is ture, this function shoule be called at process context */ -static int _issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, u8 ps, int wait_ack) -{ - int ret = _FAIL; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl, *qc; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 a4_shift; - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - /* RTW_INFO("%s\n", __FUNCTION__); */ - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - - pattrib->hdrlen += 2; - pattrib->qos_en = _TRUE; - pattrib->eosp = 1; - pattrib->ack_policy = 0; - pattrib->mdata = 0; - - _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 (MLME_IS_AP(padapter)) - SetFrDs(fctrl); - else if (MLME_IS_STA(padapter)) - SetToDs(fctrl); - else if (MLME_IS_MESH(padapter)) { - SetToDs(fctrl); - SetFrDs(fctrl); - } - - if (ps) - SetPwrMgt(fctrl); - - if (pattrib->mdata) - SetMData(fctrl); - - if (get_tofr_ds(fctrl) == 3) { - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr4, adapter_mac_addr(padapter), ETH_ALEN); - a4_shift = ETH_ALEN; - pattrib->hdrlen += ETH_ALEN; - } else { - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - a4_shift = 0; - } - - qc = (unsigned short *)(pframe + pattrib->hdrlen - 2); - - SetPriority(qc, tid); - - SetEOSP(qc, pattrib->eosp); - - SetAckpolicy(qc, pattrib->ack_policy); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos) + a4_shift; - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos) + a4_shift; - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -/* - * when wait_ms >0 , this function should be called at process context - * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - * try_cnt means the maximal TX count to try - * da == NULL for station mode - */ -int issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, u8 ps, int try_cnt, int wait_ms) -{ - int ret = _FAIL; - int i = 0; - systime start = rtw_get_current_time(); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - /* da == NULL, assum it's null data for sta to ap*/ - if (da == NULL) - da = get_my_bssid(&(pmlmeinfo->network)); - - do { - ret = _issue_qos_nulldata(padapter, da, tid, ps, wait_ms > 0 ? _TRUE : _FALSE); - - i++; - - if (RTW_CANNOT_RUN(padapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - goto exit; -#endif - } - - if (try_cnt && wait_ms) { - if (da) - RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - else - RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } -exit: - return ret; -} - -static int _issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack, u8 key_type) -{ - 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); - int ret = _FAIL; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif /* CONFIG_P2P */ - - /* RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */ - -#ifdef CONFIG_P2P - if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) { - _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey); - _set_timer(&pwdinfo->reset_ch_sitesurvey, 10); - } -#endif /* CONFIG_P2P */ - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - pattrib->retry_ctrl = _FALSE; - pattrib->key_type = key_type; - _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; - - _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_DEAUTH); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - reason = cpu_to_le16(reason); - pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&reason, &(pattrib->pktlen)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - - if (wait_ack) - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: - return ret; -} - -int issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason) -{ - RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); - return _issue_deauth(padapter, da, reason, _FALSE, IEEE80211W_RIGHT_KEY); -} - -#ifdef CONFIG_IEEE80211W -int issue_deauth_11w(_adapter *padapter, unsigned char *da, unsigned short reason, u8 key_type) -{ - RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); - return _issue_deauth(padapter, da, reason, _FALSE, key_type); -} -#endif /* CONFIG_IEEE80211W */ - -/* - * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - * try_cnt means the maximal TX count to try - */ -int issue_deauth_ex(_adapter *padapter, u8 *da, unsigned short reason, int try_cnt, - int wait_ms) -{ - int ret = _FAIL; - int i = 0; - systime start = rtw_get_current_time(); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - do { - ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? _TRUE : _FALSE, IEEE80211W_RIGHT_KEY); - - i++; - - if (RTW_CANNOT_RUN(padapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - goto exit; -#endif - } - - if (try_cnt && wait_ms) { - if (da) - RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - else - RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } -exit: - return ret; -} - -void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset) -{ - 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); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - return; - - RTW_INFO(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset); - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == 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; - - _rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */ - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */ - _rtw_memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */ - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_ACTION); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - /* category, action */ - { - u8 category, action; - category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT; - action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH; - - pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); - } - - pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0); - pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen), - hal_ch_offset_to_secondary_ch_offset(ch_offset)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); - -} - -#ifdef CONFIG_IEEE80211W -void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid, u8 key_type) -{ - 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; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - return; - - RTW_INFO("%s, %04x\n", __FUNCTION__, tid); - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) { - RTW_INFO("%s: alloc_mgtxmitframe fail\n", __FUNCTION__); - return; - } - - /* update attribute */ - pattrib = &pmgntframe->attrib; - update_mgntframe_attrib(padapter, pattrib); - pattrib->key_type = key_type; - _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, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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 */ - if (pattrib->key_type == IEEE80211W_RIGHT_KEY) { - psta = rtw_get_stainfo(pstapriv, pwlanhdr->addr1); - if (psta != NULL) { - /* RTW_INFO("%s, %d, set dot11w_expire_timer\n", __func__, __LINE__); */ - _set_timer(&psta->dot11w_expire_timer, 1000); - } - } - break; - - case 1: /* SA Query rsp */ - tid = cpu_to_le16(tid); - /* RTW_INFO("rtw_set_fixed_ie, %04x\n", 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 */ - -/** - * issue_action_ba - internal function to TX Block Ack action frame - * @padapter: the adapter to TX - * @raddr: receiver address - * @action: Block Ack Action - * @tid: tid - * @size: the announced AMPDU buffer size. used by ADDBA_RESP - * @status: status/reason code. used by ADDBA_RESP, DELBA - * @initiator: if we are the initiator of AMPDU association. used by DELBA - * @wait_ack: used xmit ack - * - * Returns: - * _SUCCESS: No xmit ack is used or acked - * _FAIL: not acked when using xmit ack - */ -static int issue_action_ba(_adapter *padapter, unsigned char *raddr, unsigned char action - , u8 tid, u8 size, u16 status, u8 initiator, int wait_ack) -{ - int ret = _FAIL; - u8 category = RTW_WLAN_CATEGORY_BACK; - u16 start_seq; - u16 BA_para_set; - u16 BA_timeout_value; - u16 BA_starting_seqctrl; - 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; - -#ifdef CONFIG_80211N_HT - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - goto exit; - - /* 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; - - /* _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ - _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - - if (category == 3) { - switch (action) { - case RTW_WLAN_ACTION_ADDBA_REQ: - do { - pmlmeinfo->dialogToken++; - } while (pmlmeinfo->dialogToken == 0); - pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen)); - -#if defined(CONFIG_RTL8188E) && defined(CONFIG_SDIO_HCI) - BA_para_set = (0x0802 | ((tid & 0xf) << 2)); /* immediate ack & 16 buffer size */ -#else - BA_para_set = (0x1002 | ((tid & 0xf) << 2)); /* immediate ack & 64 buffer size */ -#endif - -#ifdef CONFIG_TX_AMSDU - if (padapter->tx_amsdu >= 1) /* TX AMSDU enabled */ - BA_para_set |= BIT(0); - else /* TX AMSDU disabled */ - BA_para_set &= ~BIT(0); -#endif - BA_para_set = cpu_to_le16(BA_para_set); - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen)); - - /* BA_timeout_value = 0xffff; */ /* max: 65535 TUs(~ 65 ms) */ - BA_timeout_value = 5000;/* ~ 5ms */ - BA_timeout_value = cpu_to_le16(BA_timeout_value); - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_timeout_value)), &(pattrib->pktlen)); - - /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */ - psta = rtw_get_stainfo(pstapriv, raddr); - if (psta != NULL) { - start_seq = (psta->sta_xmitpriv.txseq_tid[tid & 0x07] & 0xfff) + 1; - - RTW_INFO("BA_starting_seqctrl = %d for TID=%d\n", start_seq, tid & 0x07); - - psta->BA_starting_seqctrl[tid & 0x07] = start_seq; - - BA_starting_seqctrl = start_seq << 4; - } - - BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl); - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_starting_seqctrl)), &(pattrib->pktlen)); - break; - - case RTW_WLAN_ACTION_ADDBA_RESP: - pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen)); - status = cpu_to_le16(status); - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen)); - - BA_para_set = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set); - - BA_para_set &= ~IEEE80211_ADDBA_PARAM_TID_MASK; - BA_para_set |= (tid << 2) & IEEE80211_ADDBA_PARAM_TID_MASK; - - BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - BA_para_set |= (size << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - - if (!padapter->registrypriv.wifi_spec) { - if (pregpriv->rx_ampdu_amsdu == 0) /* disabled */ - BA_para_set &= ~BIT(0); - else if (pregpriv->rx_ampdu_amsdu == 1) /* enabled */ - BA_para_set |= BIT(0); - } - - BA_para_set = cpu_to_le16(BA_para_set); - - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen)); - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen)); - break; - - case RTW_WLAN_ACTION_DELBA: - BA_para_set = 0; - BA_para_set |= (tid << 12) & IEEE80211_DELBA_PARAM_TID_MASK; - BA_para_set |= (initiator << 11) & IEEE80211_DELBA_PARAM_INITIATOR_MASK; - - BA_para_set = cpu_to_le16(BA_para_set); - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen)); - status = cpu_to_le16(status); - pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(status)), &(pattrib->pktlen)); - break; - default: - break; - } - } - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - -exit: -#endif /* CONFIG_80211N_HT */ - return ret; -} - -/** - * issue_addba_req - TX ADDBA_REQ - * @adapter: the adapter to TX - * @ra: receiver address - * @tid: tid - */ -inline void issue_addba_req(_adapter *adapter, unsigned char *ra, u8 tid) -{ - issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_REQ - , tid - , 0 /* unused */ - , 0 /* unused */ - , 0 /* unused */ - , _FALSE - ); - RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" tid=%u\n" - , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), tid); - -} - -/** - * issue_addba_rsp - TX ADDBA_RESP - * @adapter: the adapter to TX - * @ra: receiver address - * @tid: tid - * @status: status code - * @size: the announced AMPDU buffer size - */ -inline void issue_addba_rsp(_adapter *adapter, unsigned char *ra, u8 tid, u16 status, u8 size) -{ - issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_RESP - , tid - , size - , status - , 0 /* unused */ - , _FALSE - ); - RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" status=%u, tid=%u, size=%u\n" - , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), status, tid, size); -} - -/** - * issue_addba_rsp_wait_ack - TX ADDBA_RESP and wait ack - * @adapter: the adapter to TX - * @ra: receiver address - * @tid: tid - * @status: status code - * @size: the announced AMPDU buffer size - * @try_cnt: the maximal TX count to try - * @wait_ms: == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - */ -inline u8 issue_addba_rsp_wait_ack(_adapter *adapter, unsigned char *ra, u8 tid, u16 status, u8 size, int try_cnt, int wait_ms) -{ - int ret = _FAIL; - int i = 0; - systime start = rtw_get_current_time(); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(adapter))) - goto exit; - - do { - ret = issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_RESP - , tid - , size - , status - , 0 /* unused */ - , _TRUE - ); - - i++; - - if (RTW_CANNOT_RUN(adapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - /* goto exit; */ -#endif - } - - if (try_cnt && wait_ms) { - RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" status:=%u tid=%u size:%u%s, %d/%d in %u ms\n" - , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), status, tid, size - , ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } - -exit: - return ret; -} - -/** - * issue_del_ba - TX DELBA - * @adapter: the adapter to TX - * @ra: receiver address - * @tid: tid - * @reason: reason code - * @initiator: if we are the initiator of AMPDU association. used by DELBA - */ -inline void issue_del_ba(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator) -{ - issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA - , tid - , 0 /* unused */ - , reason - , initiator - , _FALSE - ); - RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u\n" - , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator); -} - -/** - * issue_del_ba_ex - TX DELBA with xmit ack options - * @adapter: the adapter to TX - * @ra: receiver address - * @tid: tid - * @reason: reason code - * @initiator: if we are the initiator of AMPDU association. used by DELBA - * @try_cnt: the maximal TX count to try - * @wait_ms: == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - */ -int issue_del_ba_ex(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator - , int try_cnt, int wait_ms) -{ - int ret = _FAIL; - int i = 0; - systime start = rtw_get_current_time(); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(adapter))) - goto exit; - - do { - ret = issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA - , tid - , 0 /* unused */ - , reason - , initiator - , wait_ms > 0 ? _TRUE : _FALSE - ); - - i++; - - if (RTW_CANNOT_RUN(adapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - /* goto exit; */ -#endif - } - - if (try_cnt && wait_ms) { - RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u%s, %d/%d in %u ms\n" - , FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator - , ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } -exit: - return ret; -} - -void issue_action_BSSCoexistPacket(_adapter *padapter) -{ - _irqL irqL; - _list *plist, *phead; - unsigned char category, action; - struct xmit_frame *pmgntframe; - struct pkt_attrib *pattrib; - unsigned char *pframe; - struct rtw_ieee80211_hdr *pwlanhdr; - unsigned short *fctrl; - struct wlan_network *pnetwork = NULL; - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - _queue *queue = &(pmlmepriv->scanned_queue); - u8 InfoContent[16] = {0}; - u8 ICS[8][15]; -#ifdef CONFIG_80211N_HT - if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) - return; - - if (_TRUE == pmlmeinfo->bwmode_updated) - return; - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - return; - - RTW_INFO("%s\n", __FUNCTION__); - - - category = RTW_WLAN_CATEGORY_PUBLIC; - action = ACT_PUBLIC_BSSCOEXIST; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == 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; - - _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - - - /* */ - if (pmlmepriv->num_FortyMHzIntolerant > 0) { - u8 iedata = 0; - - iedata |= BIT(2);/* 20 MHz BSS Width Request */ - - pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen)); - - } - - - /* */ - _rtw_memset(ICS, 0, sizeof(ICS)); - if (pmlmepriv->num_sta_no_ht > 0) { - int i; - - _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); - - phead = get_list_head(queue); - plist = get_next(phead); - - while (1) { - int len; - u8 *p; - WLAN_BSSID_EX *pbss_network; - - if (rtw_end_of_queue_search(phead, plist) == _TRUE) - break; - - pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list); - - plist = get_next(plist); - - pbss_network = (WLAN_BSSID_EX *)&pnetwork->network; - - p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); - if ((p == NULL) || (len == 0)) { /* non-HT */ - if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) - continue; - - ICS[0][pbss_network->Configuration.DSConfig] = 1; - - if (ICS[0][0] == 0) - ICS[0][0] = 1; - } - - } - - _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL); - - - for (i = 0; i < 8; i++) { - if (ICS[i][0] == 1) { - int j, k = 0; - - InfoContent[k] = i; - /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i); */ - k++; - - for (j = 1; j <= 14; j++) { - if (ICS[i][j] == 1) { - if (k < 16) { - InfoContent[k] = j; /* channel number */ - /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */ - k++; - } - } - } - - pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen)); - - } - - } - - - } - - - pattrib->last_txcmdsz = pattrib->pktlen; - - dump_mgntframe(padapter, pmgntframe); -#endif /* CONFIG_80211N_HT */ -} - -/* Spatial Multiplexing Powersave (SMPS) action frame */ -int _issue_action_SM_PS(_adapter *padapter , unsigned char *raddr , u8 NewMimoPsMode , u8 wait_ack) -{ - - int ret = _FAIL; - unsigned char category = RTW_WLAN_CATEGORY_HT; - u8 action = RTW_WLAN_ACTION_HT_SM_PS; - u8 sm_power_control = 0; - 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 (NewMimoPsMode == WLAN_HT_CAP_SM_PS_DISABLED) { - sm_power_control = sm_power_control & ~(BIT(0)); /* SM Power Save Enable = 0 SM Power Save Disable */ - } else if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_STATIC) { - sm_power_control = sm_power_control | BIT(0); /* SM Power Save Enable = 1 SM Power Save Enable */ - sm_power_control = sm_power_control & ~(BIT(1)); /* SM Mode = 0 Static Mode */ - } else if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_DYNAMIC) { - sm_power_control = sm_power_control | BIT(0); /* SM Power Save Enable = 1 SM Power Save Enable */ - sm_power_control = sm_power_control | BIT(1); /* SM Mode = 1 Dynamic Mode */ - } else - return ret; - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - return ret; - - RTW_INFO("%s, sm_power_control=%u, NewMimoPsMode=%u\n", __FUNCTION__ , sm_power_control , NewMimoPsMode); - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return ret; - - /* 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; - - _rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); /* RA */ - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */ - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); /* DA = RA */ - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(pframe, WIFI_ACTION); - - pframe += sizeof(struct rtw_ieee80211_hdr_3addr); - pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr); - - /* category, action */ - 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, &(sm_power_control), &(pattrib->pktlen)); - - pattrib->last_txcmdsz = pattrib->pktlen; - - if (wait_ack) - ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); - else { - dump_mgntframe(padapter, pmgntframe); - ret = _SUCCESS; - } - - if (ret != _SUCCESS) - RTW_INFO("%s, ack to\n", __func__); - - return ret; -} - -/* - * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT - * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX - * try_cnt means the maximal TX count to try - */ -int issue_action_SM_PS_wait_ack(_adapter *padapter, unsigned char *raddr, u8 NewMimoPsMode, int try_cnt, int wait_ms) -{ - int ret = _FAIL; - int i = 0; - systime start = rtw_get_current_time(); - - if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter))) - goto exit; - - do { - ret = _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , wait_ms > 0 ? _TRUE : _FALSE); - - i++; - - if (RTW_CANNOT_RUN(padapter)) - break; - - if (i < try_cnt && wait_ms > 0 && ret == _FAIL) - rtw_msleep_os(wait_ms); - - } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); - - if (ret != _FAIL) { - ret = _SUCCESS; -#ifndef DBG_XMIT_ACK - goto exit; -#endif - } - - if (try_cnt && wait_ms) { - if (raddr) - RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", %s , %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), MAC_ARG(raddr), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - else - RTW_INFO(FUNC_ADPT_FMT", %s , %d/%d in %u ms\n", - FUNC_ADPT_ARG(padapter), - ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start)); - } -exit: - - return ret; -} - -int issue_action_SM_PS(_adapter *padapter , unsigned char *raddr , u8 NewMimoPsMode) -{ - RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(raddr)); - return _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , _FALSE); -} - -/** - * _send_delba_sta_tid - Cancel the AMPDU association for the specific @sta, @tid - * @adapter: the adapter to which @sta belongs - * @initiator: if we are the initiator of AMPDU association - * @sta: the sta to be checked - * @tid: the tid to be checked - * @force: cancel and send DELBA even when no AMPDU association is setup - * @wait_ack: send delba with xmit ack (valid when initiator == 0) - * - * Returns: - * _FAIL if sta is NULL - * when initiator is 1, always _SUCCESS - * when initiator is 0, _SUCCESS if DELBA is acked - */ -static unsigned int _send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid - , u8 force, int wait_ack) -{ - int ret = _SUCCESS; - - if (sta == NULL) { - ret = _FAIL; - goto exit; - } - - if (initiator == 0) { - /* recipient */ - if (force || sta->recvreorder_ctrl[tid].enable == _TRUE) { - u8 ampdu_size_bak = sta->recvreorder_ctrl[tid].ampdu_size; - - sta->recvreorder_ctrl[tid].enable = _FALSE; - sta->recvreorder_ctrl[tid].ampdu_size = RX_AMPDU_SIZE_INVALID; - - if (rtw_del_rx_ampdu_test_trigger_no_tx_fail()) - ret = _FAIL; - else if (wait_ack) - ret = issue_del_ba_ex(adapter, sta->cmn.mac_addr, tid, 37, initiator, 3, 1); - else - issue_del_ba(adapter, sta->cmn.mac_addr, tid, 37, initiator); - - if (ret == _FAIL && sta->recvreorder_ctrl[tid].enable == _FALSE) - sta->recvreorder_ctrl[tid].ampdu_size = ampdu_size_bak; - } - } else if (initiator == 1) { - /* originator */ -#ifdef CONFIG_80211N_HT - if (force || sta->htpriv.agg_enable_bitmap & BIT(tid)) { - sta->htpriv.agg_enable_bitmap &= ~BIT(tid); - sta->htpriv.candidate_tid_bitmap &= ~BIT(tid); - issue_del_ba(adapter, sta->cmn.mac_addr, tid, 37, initiator); - } -#endif - } - -exit: - return ret; -} - -inline unsigned int send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid - , u8 force) -{ - return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 0); -} - -inline unsigned int send_delba_sta_tid_wait_ack(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid - , u8 force) -{ - return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 1); -} - -unsigned int send_delba(_adapter *padapter, u8 initiator, u8 *addr) -{ - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u16 tid; - - if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) - return _SUCCESS; - - psta = rtw_get_stainfo(pstapriv, addr); - if (psta == NULL) - return _SUCCESS; - -#if 0 - RTW_INFO("%s:%s\n", __func__, (initiator == 0) ? "RX_DIR" : "TX_DIR"); - if (initiator == 1) /* originator */ - RTW_INFO("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap); -#endif - - for (tid = 0; tid < TID_NUM; tid++) - send_delba_sta_tid(padapter, initiator, psta, tid, 0); - - return _SUCCESS; -} - -unsigned int send_beacon(_adapter *padapter) -{ -#if defined(CONFIG_PCI_HCI) && !defined(CONFIG_PCI_BCN_POLLING) - #ifdef CONFIG_FW_HANDLE_TXBCN - u8 vap_id = padapter->vap_id; - - /* bypass TX BCN because vap_id is invalid*/ - if (vap_id == CONFIG_LIMITED_AP_NUM) - return _SUCCESS; - #endif - - /* bypass TX BCN queue because op ch is switching/waiting */ - if (check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING) - || IS_CH_WAITING(adapter_to_rfctl(padapter)) - ) - return _SUCCESS; - - /* RTW_INFO("%s\n", __FUNCTION__); */ - - rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); - - /* 8192EE Port select for Beacon DL */ - rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); - #ifdef CONFIG_FW_HANDLE_TXBCN - rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id); - #endif - - issue_beacon(padapter, 0); - - #ifdef CONFIG_FW_HANDLE_TXBCN - vap_id = 0xFF; - rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id); - #endif - - #ifdef RTL8814AE_SW_BCN - if (GET_HAL_DATA(padapter)->bCorrectBCN != 0) - RTW_INFO("%s, line%d, Warnning, pHalData->bCorrectBCN != 0\n", __func__, __LINE__); - GET_HAL_DATA(padapter)->bCorrectBCN = 1; - #endif - - return _SUCCESS; -#endif - -/* CONFIG_PCI_BCN_POLLING is for pci interface beacon polling mode */ -#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)|| defined(CONFIG_PCI_BCN_POLLING) - u8 bxmitok = _FALSE; - int issue = 0; - int poll = 0; - systime start = rtw_get_current_time(); - #ifdef CONFIG_FW_HANDLE_TXBCN - u8 vap_id = padapter->vap_id; - - /* bypass TX BCN because vap_id is invalid*/ - if (vap_id == CONFIG_LIMITED_AP_NUM) - return _SUCCESS; - #endif - - /* bypass TX BCN queue because op ch is switching/waiting */ - if (check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING) - || IS_CH_WAITING(adapter_to_rfctl(padapter)) - ) - return _SUCCESS; - - #if defined(CONFIG_USB_HCI) - #if defined(CONFIG_RTL8812A) - if (IS_FULL_SPEED_USB(padapter)) { - issue_beacon(padapter, 300); - bxmitok = _TRUE; - } else - #endif - #endif - { - rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); - rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); - #ifdef CONFIG_FW_HANDLE_TXBCN - rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id); - #endif - do { - #if defined(CONFIG_PCI_BCN_POLLING) - issue_beacon(padapter, 0); - #else - issue_beacon(padapter, 100); - #endif - issue++; - do { - #if defined(CONFIG_PCI_BCN_POLLING) - rtw_msleep_os(1); - #else - rtw_yield_os(); - #endif - rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok)); - poll++; - } while ((poll % 10) != 0 && _FALSE == bxmitok && !RTW_CANNOT_RUN(padapter)); - #if defined(CONFIG_PCI_BCN_POLLING) - rtw_hal_unmap_beacon_icf(padapter); - #endif - } while (bxmitok == _FALSE && (issue < 100) && !RTW_CANNOT_RUN(padapter)); - #ifdef CONFIG_FW_HANDLE_TXBCN - vap_id = 0xFF; - rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id); - #endif - } - if (RTW_CANNOT_RUN(padapter)) - return _FAIL; - - - if (_FALSE == bxmitok) { - RTW_INFO("%s fail! %u ms\n", __FUNCTION__, rtw_get_passing_time_ms(start)); - #ifdef CONFIG_BCN_RECOVERY - GET_HAL_DATA(padapter)->issue_bcn_fail++; - #endif /*CONFIG_BCN_RECOVERY*/ - return _FAIL; - } else { - u32 passing_time = rtw_get_passing_time_ms(start); - - if (passing_time > 100 || issue > 3) - RTW_INFO("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start)); - else if (0) - RTW_INFO("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start)); - - #ifdef CONFIG_FW_CORRECT_BCN - rtw_hal_fw_correct_bcn(padapter); - #endif - return _SUCCESS; - } - -#endif /*defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)*/ - -} - -/**************************************************************************** - -Following are some utitity fuctions for WiFi MLME - -*****************************************************************************/ - -BOOLEAN IsLegal5GChannel( - IN PADAPTER Adapter, - IN u8 channel) -{ - - int i = 0; - u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, - 124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, - 161, 163, 165 - }; - for (i = 0; i < sizeof(Channel_5G); i++) - if (channel == Channel_5G[i]) - return _TRUE; - return _FALSE; -} - -/* collect bss info from Beacon and Probe request/response frames. */ -u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSID_EX *bssid) -{ - int i; - sint len; - u8 *p; - u8 rf_path; - u16 val16, subtype; - u8 *pframe = precv_frame->u.hdr.rx_data; - u32 packet_len = precv_frame->u.hdr.len; - u8 ie_offset; - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - struct registry_priv *pregistrypriv = &padapter->registrypriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - - len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr); - - if (len > MAX_IE_SZ) { - /* RTW_INFO("IE too long for survey event\n"); */ - return _FAIL; - } - - _rtw_memset(bssid, 0, sizeof(WLAN_BSSID_EX)); - - subtype = get_frame_sub_type(pframe); - - if (subtype == WIFI_BEACON) { - bssid->Reserved[0] = BSS_TYPE_BCN; - ie_offset = _BEACON_IE_OFFSET_; - } else { - /* FIXME : more type */ - if (subtype == WIFI_PROBERSP) { - ie_offset = _PROBERSP_IE_OFFSET_; - bssid->Reserved[0] = BSS_TYPE_PROB_RSP; - } else if (subtype == WIFI_PROBEREQ) { - ie_offset = _PROBEREQ_IE_OFFSET_; - bssid->Reserved[0] = BSS_TYPE_PROB_REQ; - } else { - bssid->Reserved[0] = BSS_TYPE_UNDEF; - ie_offset = _FIXED_IE_LENGTH_; - } - } - - bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len; - - /* below is to copy the information element */ - bssid->IELength = len; - _rtw_memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength); - - /* get the signal strength */ - /* bssid->Rssi = precv_frame->u.hdr.attrib.SignalStrength; */ /* 0-100 index. */ - bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.recv_signal_power; /* in dBM.raw data */ - bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.signal_quality;/* in percentage */ - bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.signal_strength;/* in percentage */ - - /* get rx_snr */ - if (precv_frame->u.hdr.attrib.data_rate >= DESC_RATE11M) { - bssid->PhyInfo.is_cck_rate = 0; - for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) - bssid->PhyInfo.rx_snr[rf_path] = - precv_frame->u.hdr.attrib.phy_info.rx_snr[rf_path]; - } else - bssid->PhyInfo.is_cck_rate = 1; - -#ifdef CONFIG_ANTENNA_DIVERSITY - rtw_hal_get_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &(bssid->PhyInfo.Optimum_antenna), NULL); -#endif - - /* checking SSID */ - p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset); - if (p == NULL) { - RTW_INFO("marc: cannot find SSID for survey event\n"); - return _FAIL; - } - - if (*(p + 1)) { - if (len > NDIS_802_11_LENGTH_SSID) { - RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len); - return _FAIL; - } - _rtw_memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); - bssid->Ssid.SsidLength = *(p + 1); - } else - bssid->Ssid.SsidLength = 0; - - _rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); - - /* checking rate info... */ - i = 0; - p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset); - if (p != NULL) { - if (len > NDIS_802_11_LENGTH_RATES_EX) { - RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len); - return _FAIL; - } - if (rtw_validate_value(_SUPPORTEDRATES_IE_, p+2, len) == _FALSE) { - rtw_absorb_ssid_ifneed(padapter, bssid, pframe); - RTW_DBG_DUMP("Invalidated Support Rate IE --", p, len+2); - return _FAIL; - } - _rtw_memcpy(bssid->SupportedRates, (p + 2), len); - i = len; - } - - p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset); - if (p != NULL) { - if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) { - RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len); - return _FAIL; - } - if (rtw_validate_value(_EXT_SUPPORTEDRATES_IE_, p+2, len) == _FALSE) { - rtw_absorb_ssid_ifneed(padapter, bssid, pframe); - RTW_DBG_DUMP("Invalidated EXT Support Rate IE --", p, len+2); - return _FAIL; - } - _rtw_memcpy(bssid->SupportedRates + i, (p + 2), len); - } - - /* todo: */ -#if 0 - if (judge_network_type(bssid->SupportedRates, (len + i)) == WIRELESS_11B) - bssid->NetworkTypeInUse = Ndis802_11DS; - else -#endif - { - bssid->NetworkTypeInUse = Ndis802_11OFDM24; - } - -#ifdef CONFIG_P2P - if (subtype == WIFI_PROBEREQ) { - u8 *p2p_ie; - u32 p2p_ielen; - /* Set Listion Channel */ - p2p_ie = rtw_get_p2p_ie(bssid->IEs, bssid->IELength, NULL, &p2p_ielen); - if (p2p_ie) { - 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 = padapter->mlmeextpriv.cur_channel; - RTW_INFO("%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, get_addr2_ptr(pframe), ETH_ALEN); - bssid->Privacy = 1; - return _SUCCESS; - } -#endif /* CONFIG_P2P */ - - if (bssid->IELength < 12) - return _FAIL; - - /* Checking for DSConfig */ - p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset); - - bssid->Configuration.DSConfig = 0; - bssid->Configuration.Length = 0; - - if (p) - bssid->Configuration.DSConfig = *(p + 2); - else { - /* In 5G, some ap do not have DSSET IE */ - /* checking HT info for channel */ - p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset); - if (p) { - struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2); - bssid->Configuration.DSConfig = HT_info->primary_channel; - } else { - /* use current channel */ - bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter); - } - } - - _rtw_memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2); - bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod); - - val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid); - - if ((val16 & 0x03) == cap_ESS) { - bssid->InfrastructureMode = Ndis802_11Infrastructure; - _rtw_memcpy(bssid->MacAddress, get_addr2_ptr(pframe), ETH_ALEN); - } else if ((val16 & 0x03) == cap_IBSS){ - bssid->InfrastructureMode = Ndis802_11IBSS; - _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); - } else if ((val16 & 0x03) == 0x00){ - u8 *mesh_id_ie, *mesh_conf_ie; - sint mesh_id_ie_len, mesh_conf_ie_len; - - mesh_id_ie = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_MESH_ID, &mesh_id_ie_len, bssid->IELength - ie_offset); - mesh_conf_ie = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_MESH_CONFIG, &mesh_conf_ie_len, bssid->IELength - ie_offset); - if (mesh_id_ie || mesh_conf_ie) { - if (!mesh_id_ie) { - RTW_INFO("cannot find Mesh ID for survey event\n"); - return _FAIL; - } - if (mesh_id_ie_len) { - if (mesh_id_ie_len > NDIS_802_11_LENGTH_SSID) { - RTW_INFO("Mesh ID too long (%d) for survey event\n", mesh_id_ie_len); - return _FAIL; - } - _rtw_memcpy(bssid->mesh_id.Ssid, (mesh_id_ie + 2), mesh_id_ie_len); - bssid->mesh_id.SsidLength = mesh_id_ie_len; - } else - bssid->mesh_id.SsidLength = 0; - - if (!mesh_conf_ie) { - RTW_INFO("cannot find Mesh config for survey event\n"); - return _FAIL; - } - if (mesh_conf_ie_len != 7) { - RTW_INFO("invalid Mesh conf IE len (%d) for survey event\n", mesh_conf_ie_len); - return _FAIL; - } - - bssid->InfrastructureMode = Ndis802_11_mesh; - _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); - } else { - /* default cases */ - bssid->InfrastructureMode = Ndis802_11IBSS; - _rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); - } - } - - if (val16 & BIT(4)) - bssid->Privacy = 1; - else - bssid->Privacy = 0; - - bssid->Configuration.ATIMWindow = 0; - - /* 20/40 BSS Coexistence check */ - if ((pregistrypriv->wifi_spec == 1) && (_FALSE == pmlmeinfo->bwmode_updated)) { - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; -#ifdef CONFIG_80211N_HT - p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset); - if (p && len > 0) { - struct HT_caps_element *pHT_caps; - pHT_caps = (struct HT_caps_element *)(p + 2); - - if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14)) - pmlmepriv->num_FortyMHzIntolerant++; - } else - pmlmepriv->num_sta_no_ht++; -#endif /* CONFIG_80211N_HT */ - - } - -#ifdef CONFIG_INTEL_WIDI - /* process_intel_widi_query_or_tigger(padapter, bssid); */ - if (process_intel_widi_query_or_tigger(padapter, bssid)) - return _FAIL; -#endif /* CONFIG_INTEL_WIDI */ - -#if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1 - if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) { - RTW_INFO("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 - , rtw_get_oper_ch(padapter) - , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi - ); - } -#endif - - /* mark bss info receving from nearby channel as SignalQuality 101 */ - if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter)) - bssid->PhyInfo.SignalQuality = 101; - -#ifdef CONFIG_RTW_80211K - p = rtw_get_ie(bssid->IEs + ie_offset, _EID_RRM_EN_CAP_IE_, &len, bssid->IELength - ie_offset); - if (p) - _rtw_memcpy(bssid->PhyInfo.rm_en_cap, (p + 2), *(p + 1)); - - /* save freerun counter */ - bssid->PhyInfo.free_cnt = precv_frame->u.hdr.attrib.free_cnt; -#endif - return _SUCCESS; -} - -void start_create_ibss(_adapter *padapter) -{ - unsigned short caps; - u8 val8; - u8 join_type; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network)); - u8 doiqk = _FALSE; - pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; - pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); - - /* update wireless mode */ - update_wireless_mode(padapter); - - /* udpate capability */ - caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork); - update_capinfo(padapter, caps); - if (caps & cap_IBSS) { /* adhoc master */ - /* set_opmode_cmd(padapter, adhoc); */ /* removed */ - - val8 = 0xcf; - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); - - doiqk = _TRUE; - rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk); - - /* switch channel */ - set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - - doiqk = _FALSE; - rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk); - - beacon_timing_control(padapter); - - /* set msr to WIFI_FW_ADHOC_STATE */ - pmlmeinfo->state = WIFI_FW_ADHOC_STATE; - Set_MSR(padapter, (pmlmeinfo->state & 0x3)); - - /* issue beacon */ - if (send_beacon(padapter) == _FAIL) { - - report_join_res(padapter, -1, WLAN_STATUS_UNSPECIFIED_FAILURE); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - } else { - rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress); - rtw_hal_rcr_set_chk_bssid(padapter, MLME_ADHOC_STARTED); - join_type = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); - - report_join_res(padapter, 1, WLAN_STATUS_SUCCESS); - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - rtw_indicate_connect(padapter); - } - } else { - RTW_INFO("start_create_ibss, invalid cap:%x\n", caps); - return; - } - /* update bc/mc sta_info */ - update_bmc_sta(padapter); - -} - -void start_clnt_join(_adapter *padapter) -{ - unsigned short caps; - u8 val8; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network)); - int beacon_timeout; - u8 ASIX_ID[] = {0x00, 0x0E, 0xC6}; - - /* update wireless mode */ - update_wireless_mode(padapter); - - /* udpate capability */ - caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork); - update_capinfo(padapter, caps); - - /* check if sta is ASIX peer and fix IOT issue if it is. */ - if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) , ASIX_ID , 3)) { - u8 iot_flag = _TRUE; - rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag)); - } - - if (caps & cap_ESS) { - Set_MSR(padapter, WIFI_FW_STATION_STATE); - - val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; - -#ifdef CONFIG_WAPI_SUPPORT - if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI) { - /* Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey. */ - val8 = 0x4c; - } -#endif - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); - -#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 (_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] == BSS_TYPE_PROB_REQ ? 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 */ - /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */ - issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); - } -#endif /* CONFIG_DEAUTH_BEFORE_CONNECT */ - - /* here wait for receiving the beacon to start auth */ - /* and enable a timer */ - beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval); - set_link_timer(pmlmeext, beacon_timeout); - _set_timer(&padapter->mlmepriv.assoc_timer, - (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout); - -#ifdef CONFIG_RTW_80211R - if (rtw_ft_roam(padapter)) { - rtw_ft_start_clnt_join(padapter); - } else -#endif - { - rtw_sta_linking_test_set_start(); - pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; - } - } else if (caps & cap_IBSS) { /* adhoc client */ - Set_MSR(padapter, WIFI_FW_ADHOC_STATE); - - val8 = 0xcf; - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); - - beacon_timing_control(padapter); - - pmlmeinfo->state = WIFI_FW_ADHOC_STATE; - - report_join_res(padapter, 1, WLAN_STATUS_SUCCESS); - } else { - /* RTW_INFO("marc: invalid cap:%x\n", caps); */ - return; - } - -} - -void start_clnt_auth(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - - _cancel_timer_ex(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); - pmlmeinfo->state |= WIFI_FW_AUTH_STATE; - - pmlmeinfo->auth_seq = 1; - pmlmeinfo->reauth_count = 0; - pmlmeinfo->reassoc_count = 0; - pmlmeinfo->link_count = 0; - pmlmeext->retry = 0; - -#ifdef CONFIG_RTW_80211R - if (rtw_ft_roam(padapter)) { - rtw_ft_set_status(padapter, RTW_FT_AUTHENTICATING_STA); - RTW_PRINT("start ft auth\n"); - } else -#endif - RTW_PRINT("start auth\n"); - -#ifdef CONFIG_IOCTL_CFG80211 - if (rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE)) { - if (rtw_cached_pmkid(padapter, get_my_bssid(&pmlmeinfo->network)) != -1) { - RTW_INFO("SAE: PMKSA cache entry found\n"); - padapter->securitypriv.auth_alg = WLAN_AUTH_OPEN; - goto no_external_auth; - } - - RTW_PRINT("SAE: start external auth\n"); - rtw_cfg80211_external_auth_request(padapter, NULL); - return; - } -no_external_auth: -#endif /* CONFIG_IOCTL_CFG80211 */ - - issue_auth(padapter, NULL, 0); - - set_link_timer(pmlmeext, REAUTH_TO); - -} - - -void start_clnt_assoc(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - _cancel_timer_ex(&pmlmeext->link_timer); - - pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); - pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); - -#ifdef CONFIG_RTW_80211R - if (rtw_ft_roam(padapter)) - issue_reassocreq(padapter); - else -#endif - issue_assocreq(padapter); - - set_link_timer(pmlmeext, REASSOC_TO); -} - -unsigned int receive_disconnect(_adapter *padapter, unsigned char *MacAddr, unsigned short reason, u8 locally_generated) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) - return _SUCCESS; - - RTW_INFO("%s\n", __FUNCTION__); - -#ifdef CONFIG_RTW_REPEATER_SON - rtw_rson_do_disconnect(padapter); -#endif - if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - if (report_del_sta_event(padapter, MacAddr, reason, _TRUE, locally_generated) != _FAIL) - pmlmeinfo->state = WIFI_FW_NULL_STATE; - } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { - if (report_join_res(padapter, -2, reason) != _FAIL) - pmlmeinfo->state = WIFI_FW_NULL_STATE; - } else - RTW_INFO(FUNC_ADPT_FMT" - End to Disconnect\n", FUNC_ADPT_ARG(padapter)); -#ifdef CONFIG_RTW_80211R - rtw_ft_roam_status_reset(padapter); -#endif -#ifdef CONFIG_RTW_WNM - rtw_wnm_reset_btm_state(padapter); -#endif - } - - return _SUCCESS; -} - -#ifdef CONFIG_80211D -static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - struct registry_priv *pregistrypriv; - struct mlme_ext_priv *pmlmeext; - RT_CHANNEL_INFO *chplan_new; - u8 channel; - u8 i; - - - pregistrypriv = &padapter->registrypriv; - pmlmeext = &padapter->mlmeextpriv; - - /* Adjust channel plan by AP Country IE */ - if (pregistrypriv->enable80211d - && (!pmlmeext->update_channel_plan_by_ap_done)) { - u8 *ie, *p; - u32 len; - RT_CHANNEL_PLAN chplan_ap; - RT_CHANNEL_INFO *chplan_sta = NULL; - u8 country[4]; - u8 fcn; /* first channel number */ - u8 noc; /* number of channel */ - u8 j, k; - - ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_); - if (!ie) - return; - if (len < 6) - return; - - ie += 2; - p = ie; - ie += len; - - _rtw_memset(country, 0, 4); - _rtw_memcpy(country, p, 3); - p += 3; - RTW_INFO("%s: 802.11d country=%s\n", __FUNCTION__, country); - - i = 0; - while ((ie - p) >= 3) { - fcn = *(p++); - noc = *(p++); - p++; - - for (j = 0; j < noc; j++) { - if (fcn <= 14) - channel = fcn + j; /* 2.4 GHz */ - else - channel = fcn + j * 4; /* 5 GHz */ - - chplan_ap.Channel[i++] = channel; - } - } - chplan_ap.Len = i; - -#ifdef CONFIG_RTW_DEBUG - i = 0; - RTW_INFO("%s: AP[%s] channel plan {", __FUNCTION__, bssid->Ssid.Ssid); - while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) { - _RTW_INFO("%02d,", chplan_ap.Channel[i]); - i++; - } - _RTW_INFO("}\n"); -#endif - - chplan_sta = rtw_malloc(sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM); - if (!chplan_sta) - goto done_update_chplan_from_ap; - - _rtw_memcpy(chplan_sta, rfctl->channel_set, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM); -#ifdef CONFIG_RTW_DEBUG - i = 0; - RTW_INFO("%s: STA channel plan {", __FUNCTION__); - while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { - _RTW_INFO("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE ? 'p' : 'a'); - i++; - } - _RTW_INFO("}\n"); -#endif - - _rtw_memset(rfctl->channel_set, 0, sizeof(rfctl->channel_set)); - chplan_new = rfctl->channel_set; - - i = j = k = 0; - if (pregistrypriv->wireless_mode & WIRELESS_11G) { - do { - if ((i == MAX_CHANNEL_NUM) - || (chplan_sta[i].ChannelNum == 0) - || (chplan_sta[i].ChannelNum > 14)) - break; - - if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14)) - break; - - if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; -#if 0 - chplan_new[k].ScanType = chplan_sta[i].ScanType; -#else - chplan_new[k].ScanType = SCAN_PASSIVE; -#endif - i++; - k++; - } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while ((i < MAX_CHANNEL_NUM) - && (chplan_sta[i].ChannelNum != 0) - && (chplan_sta[i].ChannelNum <= 14)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; -#if 0 - chplan_new[k].ScanType = chplan_sta[i].ScanType; -#else - chplan_new[k].ScanType = SCAN_PASSIVE; -#endif - i++; - k++; - } - - /* add channel AP supported */ - while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 2.4G channel plan */ - while ((i < MAX_CHANNEL_NUM) - && (chplan_sta[i].ChannelNum != 0) - && (chplan_sta[i].ChannelNum <= 14)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - - /* skip AP 2.4G channel plan */ - while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) - j++; - } - - if (pregistrypriv->wireless_mode & WIRELESS_11A) { - do { - if ((i >= MAX_CHANNEL_NUM) - || (chplan_sta[i].ChannelNum == 0)) - break; - - if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0)) - break; - - if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - i++; - j++; - k++; - } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; -#if 0 - chplan_new[k].ScanType = chplan_sta[i].ScanType; -#else - chplan_new[k].ScanType = SCAN_PASSIVE; -#endif - i++; - k++; - } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } while (1); - - /* change AP not support channel to Passive scan */ - while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; -#if 0 - chplan_new[k].ScanType = chplan_sta[i].ScanType; -#else - chplan_new[k].ScanType = SCAN_PASSIVE; -#endif - i++; - k++; - } - - /* add channel AP supported */ - while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) { - chplan_new[k].ChannelNum = chplan_ap.Channel[j]; - chplan_new[k].ScanType = SCAN_ACTIVE; - j++; - k++; - } - } else { - /* keep original STA 5G channel plan */ - while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { - chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; - chplan_new[k].ScanType = chplan_sta[i].ScanType; - i++; - k++; - } - } - - pmlmeext->update_channel_plan_by_ap_done = 1; - -#ifdef CONFIG_RTW_DEBUG - k = 0; - RTW_INFO("%s: new STA channel plan {", __FUNCTION__); - while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) { - _RTW_INFO("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE ? 'p' : 'c'); - k++; - } - _RTW_INFO("}\n"); -#endif - -#if 0 - /* recover the right channel index */ - channel = chplan_sta[pmlmeext->sitesurvey_res.channel_idx].ChannelNum; - k = 0; - while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) { - if (chplan_new[k].ChannelNum == channel) { - RTW_INFO("%s: change mlme_ext sitesurvey channel index from %d to %d\n", - __FUNCTION__, pmlmeext->sitesurvey_res.channel_idx, k); - pmlmeext->sitesurvey_res.channel_idx = k; - break; - } - k++; - } -#endif - -done_update_chplan_from_ap: - if (chplan_sta) - rtw_mfree(chplan_sta, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM); - } -} -#endif - -/**************************************************************************** - -Following are the functions to report events - -*****************************************************************************/ - -void report_survey_event(_adapter *padapter, union recv_frame *precv_frame) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct survey_event *psurvey_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext; - struct cmd_priv *pcmdpriv; - /* u8 *pframe = precv_frame->u.hdr.rx_data; */ - /* uint len = precv_frame->u.hdr.len; */ - RT_CHANNEL_INFO *chset = adapter_to_chset(padapter); - int ch_set_idx = -1; - - if (!padapter) - return; - - pmlmeext = &padapter->mlmeextpriv; - pcmdpriv = &padapter->cmdpriv; - - - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) - return; - - cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - return; - } - - _rtw_init_listhead(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct survey_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - - if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - rtw_mfree((u8 *)pevtcmd, cmdsz); - return; - } - -#ifdef CONFIG_80211D - process_80211d(padapter, &psurvey_evt->bss); -#endif - - ch_set_idx = rtw_chset_search_ch(chset, psurvey_evt->bss.Configuration.DSConfig); - if (ch_set_idx >= 0) { - if (psurvey_evt->bss.InfrastructureMode == Ndis802_11Infrastructure) { - if (chset[ch_set_idx].ScanType == SCAN_PASSIVE - && !rtw_is_dfs_ch(psurvey_evt->bss.Configuration.DSConfig) - ) { - RTW_INFO("%s: change ch:%d to active\n", __func__, psurvey_evt->bss.Configuration.DSConfig); - chset[ch_set_idx].ScanType = SCAN_ACTIVE; - } - #ifdef CONFIG_DFS - if (hidden_ssid_ap(&psurvey_evt->bss)) - chset[ch_set_idx].hidden_bss_cnt++; - #endif - } - } - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - pmlmeext->sitesurvey_res.bss_cnt++; - - return; - -} - -void report_surveydone_event(_adapter *padapter) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct surveydone_event *psurveydone_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) - return; - - cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - return; - } - - _rtw_init_listhead(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct surveydone_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; - - RTW_INFO("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter)); - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; - -} - -u32 report_join_res(_adapter *padapter, int aid_res, u16 status) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct joinbss_event *pjoinbss_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u32 ret = _FAIL; - - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) - goto exit; - - cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - goto exit; - } - - _rtw_init_listhead(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct joinbss_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - _rtw_memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX)); - pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = aid_res; - - RTW_INFO("report_join_res(%d, %u)\n", aid_res, status); - - - rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network, status); - - - ret = rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - -exit: - return ret; -} - -void report_wmm_edca_update(_adapter *padapter) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct wmm_event *pwmm_event; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) - return; - - cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - return; - } - - _rtw_init_listhead(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct wmm_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - pwmm_event->wmm = 0; - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; - -} - -u32 report_del_sta_event(_adapter *padapter, unsigned char *MacAddr, unsigned short reason, bool enqueue, u8 locally_generated) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct sta_info *psta; - int mac_id = -1; - struct stadel_event *pdel_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - u8 res = _SUCCESS; - - /* prepare cmd parameter */ - cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - res = _FAIL; - goto exit; - } - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - _rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); - _rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); - psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); - if (psta) - mac_id = (int)psta->cmn.mac_id; - else - mac_id = (-1); - pdel_sta_evt->mac_id = mac_id; - pdel_sta_evt->locally_generated = locally_generated; - - if (!enqueue) { - /* do directly */ - rtw_stadel_event_callback(padapter, (u8 *)pdel_sta_evt); - rtw_mfree(pevtcmd, cmdsz); - } else { - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) { - rtw_mfree(pevtcmd, cmdsz); - res = _FAIL; - goto exit; - } - - _rtw_init_listhead(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - res = rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - } - -exit: - - RTW_INFO(FUNC_ADPT_FMT" "MAC_FMT" mac_id=%d, enqueue:%d, res:%u\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(MacAddr), mac_id, enqueue, res); - - return res; -} - -void report_add_sta_event(_adapter *padapter, unsigned char *MacAddr) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct stassoc_event *padd_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) - return; - - cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - return; - } - - _rtw_init_listhead(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - _rtw_memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN); - - RTW_INFO("report_add_sta_event: add STA\n"); - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; -} - - -bool rtw_port_switch_chk(_adapter *adapter) -{ - bool switch_needed = _FALSE; -#ifdef CONFIG_CONCURRENT_MODE -#ifdef CONFIG_RUNTIME_PORT_SWITCH - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj); - _adapter *if_port0 = NULL; - _adapter *if_port1 = NULL; - struct mlme_ext_info *if_port0_mlmeinfo = NULL; - struct mlme_ext_info *if_port1_mlmeinfo = NULL; - int i; - - for (i = 0; i < dvobj->iface_nums; i++) { - if (get_hw_port(dvobj->padapters[i]) == HW_PORT0) { - if_port0 = dvobj->padapters[i]; - if_port0_mlmeinfo = &(if_port0->mlmeextpriv.mlmext_info); - } else if (get_hw_port(dvobj->padapters[i]) == HW_PORT1) { - if_port1 = dvobj->padapters[i]; - if_port1_mlmeinfo = &(if_port1->mlmeextpriv.mlmext_info); - } - } - - if (if_port0 == NULL) { - rtw_warn_on(1); - goto exit; - } - - if (if_port1 == NULL) { - rtw_warn_on(1); - goto exit; - } - -#ifdef DBG_RUNTIME_PORT_SWITCH - RTW_INFO(FUNC_ADPT_FMT" wowlan_mode:%u\n" - ADPT_FMT", port0, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n" - ADPT_FMT", port1, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n", - FUNC_ADPT_ARG(adapter), pwrctl->wowlan_mode, - ADPT_ARG(if_port0), if_port0_mlmeinfo->state, rtw_p2p_state(&if_port0->wdinfo), rtw_p2p_chk_state(&if_port0->wdinfo, P2P_STATE_NONE), - ADPT_ARG(if_port1), if_port1_mlmeinfo->state, rtw_p2p_state(&if_port1->wdinfo), rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE)); -#endif /* DBG_RUNTIME_PORT_SWITCH */ - -#ifdef CONFIG_WOWLAN - /* WOWLAN interface(primary, for now) should be port0 */ - if (pwrctl->wowlan_mode == _TRUE) { - if (!is_primary_adapter(if_port0)) { - RTW_INFO("%s "ADPT_FMT" enable WOWLAN\n", __func__, ADPT_ARG(if_port1)); - switch_needed = _TRUE; - } - goto exit; - } -#endif /* CONFIG_WOWLAN */ - - /* AP/Mesh should use port0 for ctl frame's ack */ - if ((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) { - RTW_INFO("%s "ADPT_FMT" is AP/GO/Mesh\n", __func__, ADPT_ARG(if_port1)); - switch_needed = _TRUE; - goto exit; - } - - /* GC should use port0 for p2p ps */ - if (((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) - && (if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) -#ifdef CONFIG_P2P - && !rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE) -#endif - && !check_fwstate(&if_port1->mlmepriv, WIFI_UNDER_WPS) - ) { - RTW_INFO("%s "ADPT_FMT" is GC\n", __func__, ADPT_ARG(if_port1)); - switch_needed = _TRUE; - goto exit; - } - - /* port1 linked, but port0 not linked */ - if ((if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - && !(if_port0_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - && ((if_port0_mlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) - ) { - RTW_INFO("%s "ADPT_FMT" is SINGLE_LINK\n", __func__, ADPT_ARG(if_port1)); - switch_needed = _TRUE; - goto exit; - } - -exit: -#ifdef DBG_RUNTIME_PORT_SWITCH - RTW_INFO(FUNC_ADPT_FMT" ret:%d\n", FUNC_ADPT_ARG(adapter), switch_needed); -#endif /* DBG_RUNTIME_PORT_SWITCH */ -#endif /* CONFIG_RUNTIME_PORT_SWITCH */ -#endif /* CONFIG_CONCURRENT_MODE */ - return switch_needed; -} - -/**************************************************************************** - -Following are the event callback functions - -*****************************************************************************/ - -/* for sta/adhoc mode */ -void update_sta_info(_adapter *padapter, struct sta_info *psta) -{ - _irqL irqL; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - /* ERP */ - VCS_update(padapter, psta); - -#ifdef CONFIG_80211N_HT - /* HT */ - if (pmlmepriv->htpriv.ht_option) { - psta->htpriv.ht_option = _TRUE; - - psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; - - psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; - - if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20)) - psta->htpriv.sgi_20m = _TRUE; - - if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40)) - psta->htpriv.sgi_40m = _TRUE; - - psta->qos_option = _TRUE; - - psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap; - psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap; - psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap; - - _rtw_memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap)); - #ifdef CONFIG_BEAMFORMING - psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap; - psta->cmn.bf_info.ht_beamform_cap = pmlmepriv->htpriv.beamform_cap; - #endif - } else -#endif /* CONFIG_80211N_HT */ - { -#ifdef CONFIG_80211N_HT - psta->htpriv.ht_option = _FALSE; - psta->htpriv.ampdu_enable = _FALSE; - psta->htpriv.tx_amsdu_enable = _FALSE; - psta->htpriv.sgi_20m = _FALSE; - psta->htpriv.sgi_40m = _FALSE; -#endif /* CONFIG_80211N_HT */ - psta->qos_option = _FALSE; - - } - -#ifdef CONFIG_80211N_HT - psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; - - psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ - psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ -#endif /* CONFIG_80211N_HT */ - - psta->cmn.bw_mode = pmlmeext->cur_bwmode; - - /* QoS */ - if (pmlmepriv->qospriv.qos_option) - psta->qos_option = _TRUE; - -#ifdef CONFIG_80211AC_VHT - _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv)); - if (psta->vhtpriv.vht_option) { - psta->cmn.ra_info.is_vht_enable = _TRUE; - #ifdef CONFIG_BEAMFORMING - psta->vhtpriv.beamform_cap = pmlmepriv->vhtpriv.beamform_cap; - psta->cmn.bf_info.vht_beamform_cap = pmlmepriv->vhtpriv.beamform_cap; - #endif /*CONFIG_BEAMFORMING*/ - } -#endif /* CONFIG_80211AC_VHT */ - psta->cmn.ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta)); - update_ldpc_stbc_cap(psta); - - _enter_critical_bh(&psta->lock, &irqL); - psta->state = _FW_LINKED; - _exit_critical_bh(&psta->lock, &irqL); - -} - -static void rtw_mlmeext_disconnect(_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 self_action = MLME_ACTION_UNKNOWN; - u8 state_backup = (pmlmeinfo->state & 0x03); - u8 ASIX_ID[] = {0x00, 0x0E, 0xC6}; - - if (MLME_IS_AP(padapter)) - self_action = MLME_AP_STOPPED; - else if (MLME_IS_MESH(padapter)) - self_action = MLME_MESH_STOPPED; - else if (MLME_IS_STA(padapter)) - self_action = MLME_STA_DISCONNECTED; - else if (MLME_IS_ADHOC(padapter) || MLME_IS_ADHOC_MASTER(padapter)) - self_action = MLME_ADHOC_STOPPED; - else { - RTW_INFO("state:0x%x\n", MLME_STATE(padapter)); - rtw_warn_on(1); - } - - /* set_opmode_cmd(padapter, infra_client_with_mlme); */ -#ifdef CONFIG_HW_P0_TSF_SYNC - if (self_action == MLME_STA_DISCONNECTED) - correct_TSF(padapter, self_action); -#endif - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0); - rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); - if (self_action == MLME_STA_DISCONNECTED) - rtw_hal_rcr_set_chk_bssid(padapter, self_action); - - /* set MSR to no link state->infra. mode */ - Set_MSR(padapter, _HW_STATE_STATION_); - - /* check if sta is ASIX peer and fix IOT issue if it is. */ - if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) , ASIX_ID , 3)) { - u8 iot_flag = _FALSE; - rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag)); - } - pmlmeinfo->state = WIFI_FW_NULL_STATE; - -#ifdef CONFIG_MCC_MODE - /* mcc disconnect setting before download LPS rsvd page */ - rtw_hal_set_mcc_setting_disconnect(padapter); -#endif /* CONFIG_MCC_MODE */ - - if (state_backup == WIFI_FW_STATION_STATE) { - if (rtw_port_switch_chk(padapter) == _TRUE) { - rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL); -#ifdef CONFIG_LPS - { - _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter)); - if (port0_iface) - rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0); - } -#endif - } - } - - /* switch to the 20M Hz mode after disconnect */ - pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; -#ifdef CONFIG_CTRL_TXSS_BY_TP - pmlmeext->txss_1ss = _FALSE; -#endif - -#ifdef CONFIG_FCS_MODE - if (EN_FCS(padapter)) - rtw_hal_set_hwreg(padapter, HW_VAR_STOP_FCS_MODE, NULL); -#endif - - if (!(MLME_IS_STA(padapter) && MLME_IS_OPCH_SW(padapter))) { - /* DFS and channel status no need to check here for STA under OPCH_SW */ - u8 ch, bw, offset; - - #ifdef CONFIG_DFS_MASTER - rtw_dfs_rd_en_decision(padapter, self_action, 0); - #endif - - if (rtw_mi_get_ch_setting_union_no_self(padapter, &ch, &bw, &offset) != 0) { - set_channel_bwmode(padapter, ch, offset, bw); - rtw_mi_update_union_chan_inf(padapter, ch, offset, bw); - } - } - - flush_all_cam_entry(padapter); - - _cancel_timer_ex(&pmlmeext->link_timer); - - /* pmlmepriv->LinkDetectInfo.TrafficBusyState = _FALSE; */ - pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; - pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0; - -#ifdef CONFIG_TDLS - padapter->tdlsinfo.ap_prohibited = _FALSE; - - /* For TDLS channel switch, currently we only allow it to work in wifi logo test mode */ - if (padapter->registrypriv.wifi_spec == 1) - padapter->tdlsinfo.ch_switch_prohibited = _FALSE; -#endif /* CONFIG_TDLS */ - -#ifdef CONFIG_WMMPS_STA - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* reset currently related uapsd setting when the connection has broken */ - pmlmepriv->qospriv.uapsd_max_sp_len = 0; - pmlmepriv->qospriv.uapsd_tid = 0; - pmlmepriv->qospriv.uapsd_tid_delivery_enabled = 0; - pmlmepriv->qospriv.uapsd_tid_trigger_enabled = 0; - pmlmepriv->qospriv.uapsd_ap_supported = 0; - } -#endif /* CONFIG_WMMPS_STA */ -#ifdef CONFIG_RTS_FULL_BW - rtw_set_rts_bw(padapter); -#endif/*CONFIG_RTS_FULL_BW*/ - -} - -void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res) -{ - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); - struct sta_priv *pstapriv = &padapter->stapriv; - u8 join_type; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - -#ifndef CONFIG_IOCTL_CFG80211 - struct security_priv *psecuritypriv = &padapter->securitypriv; -#endif - - if (pmlmepriv->wpa_phase == _TRUE) - pmlmepriv->wpa_phase = _FALSE; - - if (join_res < 0) { - join_type = 1; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); - rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); - if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) - rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_DISCONNECTED); - - goto exit_mlmeext_joinbss_event_callback; - } - -#ifdef CONFIG_ARP_KEEP_ALIVE - pmlmepriv->bGetGateway = 1; - pmlmepriv->GetGatewayTryCnt = 0; -#endif - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - /* update bc/mc sta_info */ - update_bmc_sta(padapter); - } - - - /* turn on dynamic functions */ - /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE); */ - - /* update IOT-releated issue */ - update_IOT_info(padapter); - - #ifdef CONFIG_RTS_FULL_BW - rtw_set_rts_bw(padapter); - #endif/*CONFIG_RTS_FULL_BW*/ - - rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates); - - /* BCN interval */ - rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval)); - - /* udpate capability */ - update_capinfo(padapter, pmlmeinfo->capability); - - /* WMM, Update EDCA param */ - WMMOnAssocRsp(padapter); -#ifdef CONFIG_80211N_HT - /* HT */ - HTOnAssocRsp(padapter); -#endif /* CONFIG_80211N_HT */ -#ifdef CONFIG_80211AC_VHT - /* VHT */ - VHTOnAssocRsp(padapter); -#endif - - psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); - if (psta) { /* only for infra. mode */ - psta->wireless_mode = pmlmeext->cur_wireless_mode; - - /* set per sta rate after updating HT cap. */ - set_sta_rate(padapter, psta); - - rtw_sta_media_status_rpt(padapter, psta, 1); - - /* wakeup macid after join bss successfully to ensure - the subsequent data frames can be sent out normally */ - rtw_hal_macid_wakeup(padapter, psta->cmn.mac_id); - } - -#ifndef CONFIG_IOCTL_CFG80211 - if (is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm)) - rtw_sec_restore_wep_key(padapter); -#endif /* CONFIG_IOCTL_CFG80211 */ - - if (rtw_port_switch_chk(padapter) == _TRUE) - rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL); - - join_type = 2; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) { - rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_CONNECTED); - - /* correcting TSF */ - correct_TSF(padapter, MLME_STA_CONNECTED); - - /* set_link_timer(pmlmeext, DISCONNECT_TO); */ - } - -#ifdef CONFIG_LPS - #ifndef CONFIG_FW_MULTI_PORT_SUPPORT - if (get_hw_port(padapter) == HW_PORT0) - #endif - rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); -#endif - -#ifdef CONFIG_BEAMFORMING - if (psta) - beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_ENTER, (u8 *)psta, sizeof(struct sta_info), 0); -#endif/*CONFIG_BEAMFORMING*/ - -exit_mlmeext_joinbss_event_callback: - - rtw_join_done_chk_ch(padapter, join_res); -#ifdef CONFIG_RTW_REPEATER_SON - rtw_rson_join_done(padapter); -#endif - RTW_INFO("=>%s - End to Connection without 4-way\n", __FUNCTION__); -} - -/* currently only adhoc mode will go here */ -void mlmeext_sta_add_event_callback(_adapter *padapter, struct sta_info *psta) -{ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 join_type; - - RTW_INFO("%s\n", __FUNCTION__); - - if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) { - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */ - /* nothing to do */ - } else { /* adhoc client */ - /* update TSF Value */ - /* update_TSF(pmlmeext, pframe, len); */ - - /* correcting TSF */ - correct_TSF(padapter, MLME_ADHOC_STARTED); - - /* start beacon */ - if (send_beacon(padapter) == _FAIL) - rtw_warn_on(1); - - pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; - } - - join_type = 2; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); - } - - /* update adhoc sta_info */ - update_sta_info(padapter, psta); - - rtw_hal_update_sta_ra_info(padapter, psta); - - /* ToDo: HT for Ad-hoc */ - psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel); - rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE); - - /* rate radaptive */ - Update_RA_Entry(padapter, psta); -} - -void mlmeext_sta_del_event_callback(_adapter *padapter) -{ - if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) - rtw_mlmeext_disconnect(padapter); -} - -/**************************************************************************** - -Following are the functions for the timer handlers - -*****************************************************************************/ -void _linked_info_dump(_adapter *padapter) -{ - if (padapter->bLinkInfoDump) { - rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, RTW_DBGDUMP); - rtw_hal_set_odm_var(padapter, HAL_ODM_RX_INFO_DUMP, RTW_DBGDUMP, _FALSE); - } -} -/******************************************************************** - -When station does not receive any packet in MAX_CONTINUAL_NORXPACKET_COUNT*2 seconds, -recipient station will teardown the block ack by issuing DELBA frame. - -*********************************************************************/ -void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer) -{ - int i = 0; - int ret = _SUCCESS; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - /* - IOT issue,occur Broadcom ap(Buffalo WZR-D1800H,Netgear R6300). - AP is originator.AP does not transmit unicast packets when STA response its BAR. - This case probably occur ap issue BAR after AP builds BA. - - Follow 802.11 spec, STA shall maintain an inactivity timer for every negotiated Block Ack setup. - The inactivity timer is not reset when MPDUs corresponding to other TIDs are received. - */ - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM) { - for (i = 0; i < TID_NUM ; i++) { - if ((psta->recvreorder_ctrl[i].enable) && - (sta_rx_data_qos_pkts(psta, i) == sta_last_rx_data_qos_pkts(psta, i)) ) { - if (_TRUE == rtw_inc_and_chk_continual_no_rx_packet(psta, i)) { - /* send a DELBA frame to the peer STA with the Reason Code field set to TIMEOUT */ - if (!from_timer) - ret = issue_del_ba_ex(padapter, psta->cmn.mac_addr, i, 39, 0, 3, 1); - else - issue_del_ba(padapter, psta->cmn.mac_addr, i, 39, 0); - psta->recvreorder_ctrl[i].enable = _FALSE; - if (ret != _FAIL) - psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID; - rtw_reset_continual_no_rx_packet(psta, i); - } - } else { - /* The inactivity timer is reset when MPDUs to the TID is received. */ - rtw_reset_continual_no_rx_packet(psta, i); - } - } - } -} - -u8 chk_ap_is_alive(_adapter *padapter, struct sta_info *psta) -{ - u8 ret = _FALSE; -#ifdef DBG_EXPIRATION_CHK - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - RTW_INFO(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu" - /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/ - ", retry:%u\n" - , FUNC_ADPT_ARG(padapter) - , STA_RX_PKTS_DIFF_ARG(psta) - , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts - , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts - /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts - , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts - , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts - , pmlmeinfo->bcn_interval*/ - , pmlmeext->retry - ); - - RTW_INFO(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter) - , sta_tx_pkts(psta) - , pmlmeinfo->link_count - ); -#endif - - if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) - && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) - && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta) - ) - ret = _FALSE; - else - ret = _TRUE; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -u8 chk_adhoc_peer_is_alive(struct sta_info *psta) -{ - u8 ret = _TRUE; - -#ifdef DBG_EXPIRATION_CHK - RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu" - /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/ - ", expire_to:%u\n" - , MAC_ARG(psta->cmn.mac_addr) - , psta->cmn.rssi_stat.rssi - , STA_RX_PKTS_DIFF_ARG(psta) - , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts - , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts - /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts - , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts - , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts - , pmlmeinfo->bcn_interval*/ - , psta->expire_to - ); -#endif - - if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta) - && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) - && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)) - ret = _FALSE; - - sta_update_last_rx_pkts(psta); - - return ret; -} - -#ifdef CONFIG_TDLS -u8 chk_tdls_peer_sta_is_alive(_adapter *padapter, struct sta_info *psta) -{ - if ((psta->sta_stats.rx_data_pkts == psta->sta_stats.last_rx_data_pkts) - && (psta->sta_stats.rx_tdls_disc_rsp_pkts == psta->sta_stats.last_rx_tdls_disc_rsp_pkts)) - return _FALSE; - - return _TRUE; -} - -void linked_status_chk_tdls(_adapter *padapter) -{ - struct candidate_pool { - struct sta_info *psta; - u8 addr[ETH_ALEN]; - }; - struct sta_priv *pstapriv = &padapter->stapriv; - _irqL irqL; - u8 ack_chk; - struct sta_info *psta; - int i, num_teardown = 0, num_checkalive = 0; - _list *plist, *phead; - struct tdls_txmgmt txmgmt; - struct candidate_pool checkalive[MAX_ALLOWED_TDLS_STA_NUM]; - struct candidate_pool teardown[MAX_ALLOWED_TDLS_STA_NUM]; - u8 tdls_sta_max = _FALSE; - -#define ALIVE_MIN 2 -#define ALIVE_MAX 5 - - _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt)); - _rtw_memset(checkalive, 0x00, sizeof(checkalive)); - _rtw_memset(teardown, 0x00, sizeof(teardown)); - - if ((padapter->tdlsinfo.link_established == _TRUE)) { - _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); - for (i = 0; i < NUM_STA; i++) { - phead = &(pstapriv->sta_hash[i]); - plist = get_next(phead); - - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { - psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); - plist = get_next(plist); - - if (psta->tdls_sta_state & TDLS_LINKED_STATE) { - psta->alive_count++; - if (psta->alive_count >= ALIVE_MIN) { - if (chk_tdls_peer_sta_is_alive(padapter, psta) == _FALSE) { - if (psta->alive_count < ALIVE_MAX) { - _rtw_memcpy(checkalive[num_checkalive].addr, psta->cmn.mac_addr, ETH_ALEN); - checkalive[num_checkalive].psta = psta; - num_checkalive++; - } else { - _rtw_memcpy(teardown[num_teardown].addr, psta->cmn.mac_addr, ETH_ALEN); - teardown[num_teardown].psta = psta; - num_teardown++; - } - } else - psta->alive_count = 0; - } - psta->sta_stats.last_rx_data_pkts = psta->sta_stats.rx_data_pkts; - psta->sta_stats.last_rx_tdls_disc_rsp_pkts = psta->sta_stats.rx_tdls_disc_rsp_pkts; - - if ((num_checkalive >= MAX_ALLOWED_TDLS_STA_NUM) || (num_teardown >= MAX_ALLOWED_TDLS_STA_NUM)) { - tdls_sta_max = _TRUE; - break; - } - } - } - - if (tdls_sta_max == _TRUE) - break; - } - _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); - - if (num_checkalive > 0) { - for (i = 0; i < num_checkalive; i++) { - _rtw_memcpy(txmgmt.peer, checkalive[i].addr, ETH_ALEN); - issue_tdls_dis_req(padapter, &txmgmt); - issue_tdls_dis_req(padapter, &txmgmt); - issue_tdls_dis_req(padapter, &txmgmt); - } - } - - if (num_teardown > 0) { - for (i = 0; i < num_teardown; i++) { - RTW_INFO("[%s %d] Send teardown to "MAC_FMT"\n", __FUNCTION__, __LINE__, MAC_ARG(teardown[i].addr)); - txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_; - _rtw_memcpy(txmgmt.peer, teardown[i].addr, ETH_ALEN); - issue_tdls_teardown(padapter, &txmgmt, _FALSE); - } - } - } - -} -#endif /* CONFIG_TDLS */ - -/* from_timer == 1 means driver is in LPS */ -void linked_status_chk(_adapter *padapter, u8 from_timer) -{ - u32 i; - struct sta_info *psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct sta_priv *pstapriv = &padapter->stapriv; -#if defined(CONFIG_ARP_KEEP_ALIVE) || defined(CONFIG_LAYER2_ROAMING) - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; -#endif -#ifdef CONFIG_LAYER2_ROAMING - struct recv_priv *precvpriv = &padapter->recvpriv; -#endif - - if (padapter->registrypriv.mp_mode == _TRUE) - return; - - if (is_client_associated_to_ap(padapter)) { - /* linked infrastructure client mode */ - - int tx_chk = _SUCCESS, rx_chk = _SUCCESS; - int rx_chk_limit; - int link_count_limit; - -#if defined(CONFIG_RTW_REPEATER_SON) - rtw_rson_scan_wk_cmd(padapter, RSON_SCAN_PROCESS); -#elif defined(CONFIG_LAYER2_ROAMING) - if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE)) { - RTW_INFO("signal_strength_data.avg_val = %d\n", precvpriv->signal_strength_data.avg_val); - if ((precvpriv->signal_strength_data.avg_val < pmlmepriv->roam_rssi_threshold) - && (rtw_get_passing_time_ms(pmlmepriv->last_roaming) >= pmlmepriv->roam_scan_int*2000)) { -#ifdef CONFIG_RTW_80211K - rtw_roam_nb_discover(padapter, _FALSE); -#endif - pmlmepriv->need_to_roam = _TRUE; - rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM); - pmlmepriv->last_roaming = rtw_get_current_time(); - } else - pmlmepriv->need_to_roam = _FALSE; - } -#endif -#ifdef CONFIG_MCC_MODE - /* - * due to tx ps null date to ao, so ap doest not tx pkt to driver - * we may check chk_ap_is_alive fail, and may issue_probereq to wrong channel under sitesurvey - * don't keep alive check under MCC - */ - if (rtw_hal_mcc_link_status_chk(padapter, __func__) == _FALSE) - return; -#endif - -#if defined(DBG_ROAMING_TEST) || defined(CONFIG_RTW_REPEATER_SON) - rx_chk_limit = 1; -#elif defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER) - rx_chk_limit = 4; -#else - rx_chk_limit = 8; -#endif -#ifdef CONFIG_ARP_KEEP_ALIVE - if (!from_timer && pmlmepriv->bGetGateway == 1 && pmlmepriv->GetGatewayTryCnt < 3) { - RTW_INFO("do rtw_gw_addr_query() : %d\n", pmlmepriv->GetGatewayTryCnt); - pmlmepriv->GetGatewayTryCnt++; - if (rtw_gw_addr_query(padapter) == 0) - pmlmepriv->bGetGateway = 0; - else { - _rtw_memset(pmlmepriv->gw_ip, 0, 4); - _rtw_memset(pmlmepriv->gw_mac_addr, 0, ETH_ALEN); - } - } -#endif -#ifdef CONFIG_P2P - if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) { - if (!from_timer) - link_count_limit = 3; /* 8 sec */ - else - link_count_limit = 15; /* 32 sec */ - } else -#endif /* CONFIG_P2P */ - { - if (!from_timer) - link_count_limit = 7; /* 16 sec */ - else - link_count_limit = 29; /* 60 sec */ - } - -#ifdef CONFIG_TDLS -#ifdef CONFIG_TDLS_CH_SW - if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) == _TRUE) - return; -#endif /* CONFIG_TDLS_CH_SW */ - -#ifdef CONFIG_TDLS_AUTOCHECKALIVE - linked_status_chk_tdls(padapter); -#endif /* CONFIG_TDLS_AUTOCHECKALIVE */ -#endif /* CONFIG_TDLS */ - - psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); - if (psta != NULL) { - bool is_p2p_enable = _FALSE; -#ifdef CONFIG_P2P - is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE); -#endif - -#ifdef CONFIG_ISSUE_DELBA_WHEN_NO_TRAFFIC - /*issue delba when ap does not tx data packet that is Broadcom ap */ - rtw_delba_check(padapter, psta, from_timer); -#endif - if (chk_ap_is_alive(padapter, psta) == _FALSE) - rx_chk = _FAIL; - - if (sta_last_tx_pkts(psta) == sta_tx_pkts(psta)) - tx_chk = _FAIL; - -#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK - if (!from_timer && pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL) - ) { - u8 backup_ch = 0, backup_bw = 0, backup_offset = 0; - u8 union_ch = 0, union_bw = 0, union_offset = 0; - u8 switch_channel_by_drv = _TRUE; - - -#ifdef CONFIG_MCC_MODE - if (MCC_EN(padapter)) { - /* driver doesn't switch channel under MCC */ - if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) - switch_channel_by_drv = _FALSE; - } -#endif - if (switch_channel_by_drv) { - if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset) - || pmlmeext->cur_channel != union_ch) - goto bypass_active_keep_alive; - - /* switch to correct channel of current network before issue keep-alive frames */ - if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) { - backup_ch = rtw_get_oper_ch(padapter); - backup_bw = rtw_get_oper_bw(padapter); - backup_offset = rtw_get_oper_choffset(padapter); - set_channel_bwmode(padapter, union_ch, union_offset, union_bw); - } - } - - if (rx_chk != _SUCCESS) - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->cmn.mac_addr, 0, 0, 3, 1); - - if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) || rx_chk != _SUCCESS) { - if (rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY)) - tx_chk = issue_nulldata(padapter, psta->cmn.mac_addr, 1, 3, 1); - else - tx_chk = issue_nulldata(padapter, psta->cmn.mac_addr, 0, 3, 1); - /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */ - if (tx_chk == _SUCCESS && !is_p2p_enable) - rx_chk = _SUCCESS; - } - - /* back to the original operation channel */ - if (backup_ch > 0 && switch_channel_by_drv) - set_channel_bwmode(padapter, backup_ch, backup_offset, backup_bw); - -bypass_active_keep_alive: - ; - } else -#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */ - { - if (rx_chk != _SUCCESS) { - if (pmlmeext->retry == 0) { -#ifdef DBG_EXPIRATION_CHK - RTW_INFO("issue_probereq to trigger probersp, retry=%d\n", pmlmeext->retry); -#endif - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1)); - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1)); - issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1)); - } - } - - if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit -#ifdef CONFIG_MCC_MODE - /* FW tx nulldata under MCC mode, we just check ap is alive */ - && (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) -#endif /* CONFIG_MCC_MODE */ - ) { - #ifdef DBG_EXPIRATION_CHK - RTW_INFO("%s issue_nulldata(%d)\n", __FUNCTION__, from_timer ? 1 : 0); - #endif - if (from_timer || rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY)) - tx_chk = issue_nulldata(padapter, NULL, 1, 0, 0); - else - tx_chk = issue_nulldata(padapter, NULL, 0, 1, 1); - } - } - - if (rx_chk == _FAIL) { - pmlmeext->retry++; - if (pmlmeext->retry > rx_chk_limit) { - RTW_PRINT(FUNC_ADPT_FMT" disconnect or roaming\n", - FUNC_ADPT_ARG(padapter)); - receive_disconnect(padapter, pmlmeinfo->network.MacAddress - , WLAN_REASON_EXPIRATION_CHK, _FALSE); - return; - } - } else - pmlmeext->retry = 0; - - if (tx_chk == _FAIL) - pmlmeinfo->link_count %= (link_count_limit + 1); - else { - psta->sta_stats.last_tx_pkts = psta->sta_stats.tx_pkts; - pmlmeinfo->link_count = 0; - } - - } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */ - - } else if (is_client_associated_to_ibss(padapter)) { - _irqL irqL; - _list *phead, *plist, dlist; - - _rtw_init_listhead(&dlist); - - _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); - - for (i = 0; i < NUM_STA; i++) { - - phead = &(pstapriv->sta_hash[i]); - plist = get_next(phead); - while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) { - psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); - plist = get_next(plist); - - if (is_broadcast_mac_addr(psta->cmn.mac_addr)) - continue; - - if (chk_adhoc_peer_is_alive(psta) || !psta->expire_to) - psta->expire_to = pstapriv->adhoc_expire_to; - else - psta->expire_to--; - - if (psta->expire_to <= 0) { - rtw_list_delete(&psta->list); - rtw_list_insert_tail(&psta->list, &dlist); - } - } - } - - _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); - - plist = get_next(&dlist); - while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) { - psta = LIST_CONTAINOR(plist, struct sta_info, list); - plist = get_next(plist); - rtw_list_delete(&psta->list); - RTW_INFO(FUNC_ADPT_FMT" ibss expire "MAC_FMT"\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)); - report_del_sta_event(padapter, psta->cmn.mac_addr, WLAN_REASON_EXPIRATION_CHK, from_timer ? _TRUE : _FALSE, _FALSE); - } - } - -} - -void survey_timer_hdl(void *ctx) -{ - _adapter *padapter = (_adapter *)ctx; - struct cmd_obj *cmd; - struct sitesurvey_parm *psurveyPara; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (mlmeext_scan_state(pmlmeext) > SCAN_DISABLE) { - cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (cmd == NULL) { - rtw_warn_on(1); - goto exit; - } - - psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm)); - if (psurveyPara == NULL) { - rtw_warn_on(1); - rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj)); - goto exit; - } - - init_h2fwcmd_w_parm_no_rsp(cmd, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); - rtw_enqueue_cmd(pcmdpriv, cmd); - } - -exit: - return; -} - -#ifdef CONFIG_RTW_REPEATER_SON -/* 100ms pass, stop rson_scan */ -void rson_timer_hdl(void *ctx) -{ - _adapter *padapter = (_adapter *)ctx; - - rtw_rson_scan_wk_cmd(padapter, RSON_SCAN_DISABLE); -} - -#endif - -void link_timer_hdl(void *ctx) -{ - _adapter *padapter = (_adapter *)ctx; - /* static unsigned int rx_pkt = 0; */ - /* static u64 tx_cnt = 0; */ - /* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - /* struct sta_priv *pstapriv = &padapter->stapriv; */ -#ifdef CONFIG_RTW_80211R - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta = NULL; - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network)); -#endif - - if (rtw_sta_linking_test_force_fail()) - RTW_INFO("rtw_sta_linking_test_force_fail\n"); - - if (pmlmeext->join_abort && pmlmeinfo->state != WIFI_FW_NULL_STATE) { - RTW_INFO(FUNC_ADPT_FMT" join abort\n", FUNC_ADPT_ARG(padapter)); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - report_join_res(padapter, -4, WLAN_STATUS_UNSPECIFIED_FAILURE); - goto exit; - } - - if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { - RTW_INFO("link_timer_hdl:no beacon while connecting\n"); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - report_join_res(padapter, -3, WLAN_STATUS_UNSPECIFIED_FAILURE); - } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { - -#ifdef CONFIG_IOCTL_CFG80211 - if (rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE)) - return; -#endif /* CONFIG_IOCTL_CFG80211 */ - - /* re-auth timer */ - if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { - /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ - /* { */ - pmlmeinfo->state = 0; - if (pmlmeinfo->auth_status) { - report_join_res(padapter, -1, pmlmeinfo->auth_status); - pmlmeinfo->auth_status = 0; /* reset */ - } else - report_join_res(padapter, -1, WLAN_STATUS_UNSPECIFIED_FAILURE); - return; - /* } */ - /* else */ - /* { */ - /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ - /* pmlmeinfo->reauth_count = 0; */ - /* } */ - } - - RTW_INFO("link_timer_hdl: auth timeout and try again\n"); - pmlmeinfo->auth_seq = 1; - issue_auth(padapter, NULL, 0); - set_link_timer(pmlmeext, REAUTH_TO); - } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { - /* re-assoc timer */ - if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { - pmlmeinfo->state = WIFI_FW_NULL_STATE; -#ifdef CONFIG_RTW_80211R - if (rtw_ft_roam(padapter)) { - psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); - if (psta) - rtw_free_stainfo(padapter, psta); - } -#endif - report_join_res(padapter, -2, WLAN_STATUS_UNSPECIFIED_FAILURE); - return; - } - -#ifdef CONFIG_RTW_80211R - if (rtw_ft_roam(padapter)) { - RTW_INFO("link_timer_hdl: reassoc timeout and try again\n"); - issue_reassocreq(padapter); - } else -#endif - { - RTW_INFO("link_timer_hdl: assoc timeout and try again\n"); - issue_assocreq(padapter); - } - - set_link_timer(pmlmeext, REASSOC_TO); - } - -exit: - return; -} - -void addba_timer_hdl(void *ctx) -{ - struct sta_info *psta = (struct sta_info *)ctx; - -#ifdef CONFIG_80211N_HT - struct ht_priv *phtpriv; - - if (!psta) - return; - - phtpriv = &psta->htpriv; - - if ((phtpriv->ht_option == _TRUE) && (phtpriv->ampdu_enable == _TRUE)) { - if (phtpriv->candidate_tid_bitmap) - phtpriv->candidate_tid_bitmap = 0x0; - - } -#endif /* CONFIG_80211N_HT */ -} - -#ifdef CONFIG_IEEE80211W -void report_sta_timeout_event(_adapter *padapter, u8 *MacAddr, unsigned short reason) -{ - struct cmd_obj *pcmd_obj; - u8 *pevtcmd; - u32 cmdsz; - struct sta_info *psta; - int mac_id; - struct stadel_event *pdel_sta_evt; - struct C2HEvent_Header *pc2h_evt_hdr; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct cmd_priv *pcmdpriv = &padapter->cmdpriv; - - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) - return; - - cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - return; - } - - _rtw_init_listhead(&pcmd_obj->list); - - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stadel_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_TimeoutSTA); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - _rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); - _rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); - - - psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); - if (psta) - mac_id = (int)psta->cmn.mac_id; - else - mac_id = (-1); - - pdel_sta_evt->mac_id = mac_id; - - RTW_INFO("report_del_sta_event: delete STA, mac_id=%d\n", mac_id); - - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); - - return; -} - -void clnt_sa_query_timeout(_adapter *padapter) -{ - struct mlme_ext_priv *mlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info); - - RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter)); - receive_disconnect(padapter, get_my_bssid(&(mlmeinfo->network)), WLAN_REASON_SA_QUERY_TIMEOUT, _FALSE); -} - -void sa_query_timer_hdl(void *ctx) -{ - struct sta_info *psta = (struct sta_info *)ctx; - _adapter *padapter = psta->padapter; - _irqL irqL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE && - check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) - clnt_sa_query_timeout(padapter); - else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) - report_sta_timeout_event(padapter, psta->cmn.mac_addr, WLAN_REASON_PREV_AUTH_NOT_VALID); -} - -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_RTW_80211R -void rtw_ft_update_bcn(_adapter *padapter, union recv_frame *precv_frame) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 *pframe = precv_frame->u.hdr.rx_data; - uint len = precv_frame->u.hdr.len; - WLAN_BSSID_EX *pbss; - - if (rtw_ft_chk_status(padapter,RTW_FT_ASSOCIATED_STA) - && (pmlmepriv->ft_roam.ft_updated_bcn == _FALSE)) { - pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX)); - if (pbss) { - if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { - struct beacon_keys recv_beacon; - - update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE); - - /* update bcn keys */ - if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) { - RTW_INFO("%s: beacon keys ready\n", __func__); - _rtw_memcpy(&pmlmepriv->cur_beacon_keys, - &recv_beacon, sizeof(recv_beacon)); - } else { - RTW_ERR("%s: get beacon keys failed\n", __func__); - _rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon)); - } - #ifdef CONFIG_BCN_CNT_CONFIRM_HDL - pmlmepriv->new_beacon_cnts = 0; - #endif - } - rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX)); - } - - /* check the vendor of the assoc AP */ - pmlmeinfo->assoc_AP_vendor = - check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), - (len - sizeof(struct rtw_ieee80211_hdr_3addr))); - - /* update TSF Value */ - update_TSF(pmlmeext, pframe, len); - pmlmeext->bcn_cnt = 0; - pmlmeext->last_bcn_cnt = 0; - pmlmepriv->ft_roam.ft_updated_bcn = _TRUE; - } -} - -void rtw_ft_start_clnt_join(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam); - - if (rtw_ft_otd_roam(padapter)) { - pmlmeinfo->state = WIFI_FW_AUTH_SUCCESS | WIFI_FW_STATION_STATE; - pft_roam->ft_event.ies = - (pft_roam->ft_action + sizeof(struct rtw_ieee80211_hdr_3addr) + 16); - pft_roam->ft_event.ies_len = - (pft_roam->ft_action_len - sizeof(struct rtw_ieee80211_hdr_3addr)); - - /*Not support RIC*/ - pft_roam->ft_event.ric_ies = NULL; - pft_roam->ft_event.ric_ies_len = 0; - rtw_ft_report_evt(padapter); - return; - } - - pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; - start_clnt_auth(padapter); -} - -u8 rtw_ft_update_rsnie( - _adapter *padapter, u8 bwrite, - struct pkt_attrib *pattrib, u8 **pframe) -{ - struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam); - u8 *pie; - u32 len; - - pie = rtw_get_ie(pft_roam->updated_ft_ies, EID_WPA2, &len, - pft_roam->updated_ft_ies_len); - - if (!bwrite) - return (pie)?_SUCCESS:_FAIL; - - if (pie) { - *pframe = rtw_set_ie(((u8 *)*pframe), EID_WPA2, len, - pie+2, &(pattrib->pktlen)); - } else - return _FAIL; - - return _SUCCESS; -} - -static u8 rtw_ft_update_mdie( - _adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe) -{ - struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam); - u8 *pie, mdie[3]; - u32 len = 3; - - if (rtw_ft_roam(padapter)) { - if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _MDIE_, - &len, pft_roam->updated_ft_ies_len))) { - pie = (pie + 2); /* ignore md-id & length */ - } else - return _FAIL; - } else { - *((u16 *)&mdie[0]) = pft_roam->mdid; - mdie[2] = pft_roam->ft_cap; - pie = &mdie[0]; - } - - *pframe = rtw_set_ie(((u8 *)*pframe), _MDIE_, len , pie, &(pattrib->pktlen)); - return _SUCCESS; -} - -static u8 rtw_ft_update_ftie( - _adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe) -{ - struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam); - u8 *pie; - u32 len; - - if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _FTIE_, &len, - pft_roam->updated_ft_ies_len)) != NULL) { - *pframe = rtw_set_ie(*pframe, _FTIE_, len , - (pie+2), &(pattrib->pktlen)); - } else - return _FAIL; - - return _SUCCESS; -} - -void rtw_ft_build_auth_req_ies(_adapter *padapter, - struct pkt_attrib *pattrib, u8 **pframe) -{ - u8 ftie_append = _TRUE; - - if (!pattrib || !(*pframe)) - return; - - if (!rtw_ft_roam(padapter)) - return; - - ftie_append = rtw_ft_update_rsnie(padapter, _TRUE, pattrib, pframe); - rtw_ft_update_mdie(padapter, pattrib, pframe); - if (ftie_append) - rtw_ft_update_ftie(padapter, pattrib, pframe); -} - -void rtw_ft_build_assoc_req_ies(_adapter *padapter, - u8 is_reassoc, struct pkt_attrib *pattrib, u8 **pframe) -{ - if (!pattrib || !(*pframe)) - return; - - if (rtw_ft_chk_flags(padapter, RTW_FT_PEER_EN)) - rtw_ft_update_mdie(padapter, pattrib, pframe); - - if ((!is_reassoc) || (!rtw_ft_roam(padapter))) - return; - - if (rtw_ft_update_rsnie(padapter, _FALSE, pattrib, pframe)) - rtw_ft_update_ftie(padapter, pattrib, pframe); -} - -u8 rtw_ft_update_auth_rsp_ies(_adapter *padapter, u8 *pframe, u32 len) -{ - u8 ret = _SUCCESS; - u8 target_ap_addr[ETH_ALEN] = {0}; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam); - - if (!rtw_ft_roam(padapter)) - return _FAIL; - - /*rtw_ft_report_reassoc_evt already, - * and waiting for cfg80211_rtw_update_ft_ies */ - if (rtw_ft_authed_sta(padapter)) - return ret; - - if (!pframe || !len) - return _FAIL; - - rtw_buf_update(&pmlmepriv->auth_rsp, - &pmlmepriv->auth_rsp_len, pframe, len); - pft_roam->ft_event.ies = - (pmlmepriv->auth_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6); - pft_roam->ft_event.ies_len = - (pmlmepriv->auth_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6); - - /*Not support RIC*/ - pft_roam->ft_event.ric_ies = NULL; - pft_roam->ft_event.ric_ies_len = 0; - _rtw_memcpy(target_ap_addr, pmlmepriv->assoc_bssid, ETH_ALEN); - rtw_ft_report_reassoc_evt(padapter, target_ap_addr); - - return ret; -} - -static void rtw_ft_start_clnt_action(_adapter *padapter, u8 *pTargetAddr) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - rtw_ft_set_status(padapter, RTW_FT_REQUESTING_STA); - rtw_ft_issue_action_req(padapter, pTargetAddr); - _set_timer(&pmlmeext->ft_link_timer, REASSOC_TO); -} - -void rtw_ft_start_roam(_adapter *padapter, u8 *pTargetAddr) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (rtw_ft_otd_roam(padapter)) { - rtw_ft_start_clnt_action(padapter, pTargetAddr); - } else { - /*wait a little time to retrieve packets buffered in the current ap while scan*/ - _set_timer(&pmlmeext->ft_roam_timer, 30); - } -} - -void rtw_ft_issue_action_req(_adapter *padapter, u8 *pTargetAddr) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct xmit_frame *pmgntframe; - struct rtw_ieee80211_hdr *pwlanhdr; - struct pkt_attrib *pattrib; - u8 *pframe; - u8 category = RTW_WLAN_CATEGORY_FT; - u8 action = RTW_WLAN_ACTION_FT_REQ; - - pmgntframe = alloc_mgtxmitframe(pxmitpriv); - if (pmgntframe == NULL) - return; - - 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; - pwlanhdr->frame_ctl = 0; - - _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); - _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); - - SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); - pmlmeext->mgnt_seq++; - set_frame_sub_type(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)); - - _rtw_memcpy(pframe, adapter_mac_addr(padapter), ETH_ALEN); - pframe += ETH_ALEN; - pattrib->pktlen += ETH_ALEN; - - _rtw_memcpy(pframe, pTargetAddr, ETH_ALEN); - pframe += ETH_ALEN; - pattrib->pktlen += ETH_ALEN; - - rtw_ft_update_mdie(padapter, pattrib, &pframe); - if (rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe)) - rtw_ft_update_ftie(padapter, pattrib, &pframe); - - pattrib->last_txcmdsz = pattrib->pktlen; - dump_mgntframe(padapter, pmgntframe); -} - -void rtw_ft_report_evt(_adapter *padapter) -{ - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam); - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network); - struct cfg80211_ft_event_params ft_evt_parms; - _irqL irqL; - - _rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms)); - rtw_ft_update_stainfo(padapter, pnetwork); - - if (!pnetwork) - goto err_2; - - ft_evt_parms.ies_len = pft_roam->ft_event.ies_len; - ft_evt_parms.ies = rtw_zmalloc(ft_evt_parms.ies_len); - if (ft_evt_parms.ies) - _rtw_memcpy((void *)ft_evt_parms.ies, pft_roam->ft_event.ies, ft_evt_parms.ies_len); - else - goto err_2; - - ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN); - if (ft_evt_parms.target_ap) - _rtw_memcpy((void *)ft_evt_parms.target_ap, pnetwork->MacAddress, ETH_ALEN); - else - goto err_1; - - ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies; - ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len; - - rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA, &irqL); - rtw_cfg80211_ft_event(padapter, &ft_evt_parms); - RTW_INFO("FT: rtw_ft_report_evt\n"); - rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN); -err_1: - rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len); -err_2: - return; -} - -void rtw_ft_report_reassoc_evt(_adapter *padapter, u8 *pMacAddr) -{ - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); - struct cmd_obj *pcmd_obj = NULL; - struct stassoc_event *passoc_sta_evt = NULL; - struct C2HEvent_Header *pc2h_evt_hdr = NULL; - u8 *pevtcmd = NULL; - u32 cmdsz = 0; - - pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (pcmd_obj == NULL) - return; - - cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); - pevtcmd = (u8 *)rtw_zmalloc(cmdsz); - if (pevtcmd == NULL) { - rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj)); - return; - } - - _rtw_init_listhead(&pcmd_obj->list); - pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); - pcmd_obj->cmdsz = cmdsz; - pcmd_obj->parmbuf = pevtcmd; - pcmd_obj->rsp = NULL; - pcmd_obj->rspsz = 0; - - pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); - pc2h_evt_hdr->len = sizeof(struct stassoc_event); - pc2h_evt_hdr->ID = GEN_EVT_CODE(_FT_REASSOC); - pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq); - - passoc_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); - _rtw_memcpy((unsigned char *)(&(passoc_sta_evt->macaddr)), pMacAddr, ETH_ALEN); - rtw_enqueue_cmd(pcmdpriv, pcmd_obj); -} - -void rtw_ft_link_timer_hdl(void *ctx) -{ - _adapter *padapter = (_adapter *)ctx; - struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam); - - if (rtw_ft_chk_status(padapter, RTW_FT_REQUESTING_STA)) { - if (pft_roam->ft_req_retry_cnt < RTW_FT_ACTION_REQ_LMT) { - pft_roam->ft_req_retry_cnt++; - rtw_ft_issue_action_req(padapter, (u8 *)pmlmepriv->roam_network->network.MacAddress); - _set_timer(&pmlmeext->ft_link_timer, REASSOC_TO); - } else { - pft_roam->ft_req_retry_cnt = 0; - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) - rtw_ft_set_status(padapter, RTW_FT_ASSOCIATED_STA); - else - rtw_ft_reset_status(padapter); - } - } -} - -void rtw_ft_roam_timer_hdl(void *ctx) -{ - _adapter *padapter = (_adapter *)ctx; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - - receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress - , WLAN_REASON_ACTIVE_ROAM, _FALSE); -} - -void rtw_ft_roam_status_reset(_adapter *padapter) -{ - struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam); - - if ((rtw_to_roam(padapter) > 0) && - (!rtw_ft_chk_status(padapter, RTW_FT_REQUESTED_STA))) { - rtw_ft_reset_status(padapter); - } - - padapter->mlmepriv.ft_roam.ft_updated_bcn = _FALSE; -} -#endif - -u8 NULL_hdl(_adapter *padapter, u8 *pbuf) -{ - return H2C_SUCCESS; -} - -#ifdef CONFIG_AUTO_AP_MODE -void rtw_auto_ap_rx_msg_dump(_adapter *padapter, union recv_frame *precv_frame, u8 *ehdr_pos) -{ - struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; - struct sta_info *psta = precv_frame->u.hdr.psta; - struct ethhdr *ehdr = (struct ethhdr *)ehdr_pos; - - RTW_INFO("eth rx: got eth_type=0x%x\n", ntohs(ehdr->h_proto)); - - if (psta && psta->isrc && psta->pid > 0) { - u16 rx_pid; - - rx_pid = *(u16 *)(ehdr_pos + ETH_HLEN); - - RTW_INFO("eth rx(pid=0x%x): sta("MAC_FMT") pid=0x%x\n", - rx_pid, MAC_ARG(psta->cmn.mac_addr), psta->pid); - - if (rx_pid == psta->pid) { - int i; - u16 len = *(u16 *)(ehdr_pos + ETH_HLEN + 2); - /* u16 ctrl_type = *(u16 *)(ehdr_pos + ETH_HLEN + 4); */ - - /* RTW_INFO("eth, RC: len=0x%x, ctrl_type=0x%x\n", len, ctrl_type); */ - RTW_INFO("eth, RC: len=0x%x\n", len); - - for (i = 0; i < len; i++) - RTW_INFO("0x%x\n", *(ehdr_pos + ETH_HLEN + 4 + i)); - /* RTW_INFO("0x%x\n", *(ehdr_pos + ETH_HLEN + 6 + i)); */ - - RTW_INFO("eth, RC-end\n"); - } - } - -} - -void rtw_start_auto_ap(_adapter *adapter) -{ - RTW_INFO("%s\n", __FUNCTION__); - - rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11APMode, 0); - - rtw_setopmode_cmd(adapter, Ndis802_11APMode, RTW_CMDF_WAIT_ACK); -} - -static int rtw_auto_ap_start_beacon(_adapter *adapter) -{ - int ret = 0; - u8 *pbuf = NULL; - uint len; - u8 supportRate[16]; - int sz = 0, rateLen; - u8 *ie; - u8 wireless_mode, oper_channel; - u8 ssid[3] = {0}; /* hidden ssid */ - u32 ssid_len = sizeof(ssid); - struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); - - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE) - return -EINVAL; - - - len = 128; - pbuf = rtw_zmalloc(len); - if (!pbuf) - return -ENOMEM; - - - /* generate beacon */ - ie = pbuf; - - /* timestamp will be inserted by hardware */ - sz += 8; - ie += sz; - - /* beacon interval : 2bytes */ - *(u16 *)ie = cpu_to_le16((u16)100); /* BCN_INTERVAL=100; */ - sz += 2; - ie += 2; - - /* capability info */ - *(u16 *)ie = 0; - *(u16 *)ie |= cpu_to_le16(cap_ESS); - *(u16 *)ie |= cpu_to_le16(cap_ShortPremble); - /* *(u16*)ie |= cpu_to_le16(cap_Privacy); */ - sz += 2; - ie += 2; - - /* SSID */ - ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz); - - /* supported rates */ - wireless_mode = WIRELESS_11BG_24N; - rtw_set_supported_rate(supportRate, wireless_mode) ; - rateLen = rtw_get_rateset_len(supportRate); - if (rateLen > 8) - ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz); - else - ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz); - - - /* DS parameter set */ - if (rtw_mi_check_status(adapter, MI_LINKED)) - oper_channel = rtw_mi_get_union_chan(adapter); - else - oper_channel = adapter_to_dvobj(adapter)->oper_channel; - - ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz); - - /* ext supported rates */ - if (rateLen > 8) - ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz); - - RTW_INFO("%s, start auto ap beacon sz=%d\n", __FUNCTION__, sz); - - /* lunch ap mode & start to issue beacon */ - if (rtw_check_beacon_data(adapter, pbuf, sz) == _SUCCESS) { - - } else - ret = -EINVAL; - - - rtw_mfree(pbuf, len); - - return ret; - -} -#endif/* CONFIG_AUTO_AP_MODE */ - -#ifdef CONFIG_AP_MODE -u8 stop_ap_hdl(_adapter *adapter) -{ - RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter)); - - rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11Infrastructure, RTW_CMDF_DIRECTLY); - rtw_setopmode_cmd(adapter, Ndis802_11Infrastructure, RTW_CMDF_DIRECTLY); - - return H2C_SUCCESS; -} -#endif - -u8 setopmode_hdl(_adapter *padapter, u8 *pbuf) -{ - u8 type; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; - - if (psetop->mode == Ndis802_11APMode - || psetop->mode == Ndis802_11_mesh - ) { - pmlmeinfo->state = WIFI_FW_AP_STATE; - type = _HW_STATE_AP_; - } else if (psetop->mode == Ndis802_11Infrastructure) { - pmlmeinfo->state &= ~(BIT(0) | BIT(1)); /* clear state */ - pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */ - type = _HW_STATE_STATION_; - } else if (psetop->mode == Ndis802_11IBSS) - type = _HW_STATE_ADHOC_; - else if (psetop->mode == Ndis802_11Monitor) - type = _HW_STATE_MONITOR_; - else - type = _HW_STATE_NOLINK_; - -#ifdef CONFIG_AP_PORT_SWAP - rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, (u8 *)(&type)); -#endif - - rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); - -#ifdef CONFIG_AUTO_AP_MODE - if (psetop->mode == Ndis802_11APMode) - rtw_auto_ap_start_beacon(padapter); -#endif - - if (rtw_port_switch_chk(padapter) == _TRUE) { - rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL); - - if (psetop->mode == Ndis802_11APMode) - adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; /* ap mode won't dowload rsvd pages */ - else if (psetop->mode == Ndis802_11Infrastructure) { -#ifdef CONFIG_LPS - _adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter)); - if (port0_iface) - rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0); -#endif - } - } - -#ifdef CONFIG_BT_COEXIST - if (psetop->mode == Ndis802_11APMode - || psetop->mode == Ndis802_11_mesh - || psetop->mode == Ndis802_11Monitor - ) { - /* Do this after port switch to */ - /* prevent from downloading rsvd page to wrong port */ - rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */ - } -#endif /* CONFIG_BT_COEXIST */ - - return H2C_SUCCESS; - -} - -u8 createbss_hdl(_adapter *padapter, u8 *pbuf) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network)); - WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network; - struct createbss_parm *parm = (struct createbss_parm *)pbuf; - u8 ret = H2C_SUCCESS; - /* u8 initialgain; */ - -#ifdef CONFIG_AP_MODE - if ((parm->req_ch == 0 && pmlmeinfo->state == WIFI_FW_AP_STATE) - || parm->req_ch != 0 - ) { - start_bss_network(padapter, parm); - goto exit; - } -#endif - - /* below is for ad-hoc master */ - if (parm->adhoc) { - rtw_warn_on(pdev_network->InfrastructureMode != Ndis802_11IBSS); - rtw_joinbss_reset(padapter); - - pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; - pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->agg_enable_bitmap = 0; - pmlmeinfo->candidate_tid_bitmap = 0; - - /* cancel link timer */ - _cancel_timer_ex(&pmlmeext->link_timer); - - /* clear CAM */ - flush_all_cam_entry(padapter); - - pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network); - _rtw_memcpy(pnetwork, pdev_network, FIELD_OFFSET(WLAN_BSSID_EX, IELength)); - pnetwork->IELength = pdev_network->IELength; - - if (pnetwork->IELength > MAX_IE_SZ) { - ret = H2C_PARAMETERS_ERROR; - goto ibss_post_hdl; - } - - _rtw_memcpy(pnetwork->IEs, pdev_network->IEs, pnetwork->IELength); - start_create_ibss(padapter); - } else { - rtw_warn_on(1); - ret = H2C_PARAMETERS_ERROR; - } - -ibss_post_hdl: - rtw_create_ibss_post_hdl(padapter, ret); - -exit: - return ret; -} - -u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf) -{ - u8 join_type; - PNDIS_802_11_VARIABLE_IEs pIE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network)); -#ifdef CONFIG_ANTENNA_DIVERSITY - struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf; -#endif /* CONFIG_ANTENNA_DIVERSITY */ - u32 i; - /* u8 initialgain; */ - /* u32 acparm; */ - u8 u_ch, u_bw, u_offset; - u8 doiqk = _FALSE; - - /* check already connecting to AP or not */ - if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { - if (pmlmeinfo->state & WIFI_FW_STATION_STATE) - issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); - pmlmeinfo->state = WIFI_FW_NULL_STATE; - - /* clear CAM */ - flush_all_cam_entry(padapter); - - _cancel_timer_ex(&pmlmeext->link_timer); - - /* set MSR to nolink->infra. mode */ - /* Set_MSR(padapter, _HW_STATE_NOLINK_); */ - Set_MSR(padapter, _HW_STATE_STATION_); - - - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0); - if (pmlmeinfo->state & WIFI_FW_STATION_STATE) - rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_DISCONNECTED); - } - -#ifdef CONFIG_ANTENNA_DIVERSITY - rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, _FALSE); -#endif - -#ifdef CONFIG_WAPI_SUPPORT - rtw_wapi_clear_all_cam_entry(padapter); -#endif - - rtw_joinbss_reset(padapter); - - pmlmeinfo->ERP_enable = 0; - pmlmeinfo->WMM_enable = 0; - pmlmeinfo->HT_enable = 0; - pmlmeinfo->HT_caps_enable = 0; - pmlmeinfo->HT_info_enable = 0; - pmlmeinfo->agg_enable_bitmap = 0; - pmlmeinfo->candidate_tid_bitmap = 0; - pmlmeinfo->bwmode_updated = _FALSE; - /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ - pmlmeinfo->VHT_enable = 0; -#ifdef ROKU_PRIVATE - pmlmeinfo->ht_vht_received = 0; - _rtw_memset(pmlmeinfo->SupportedRates_infra_ap, 0, NDIS_802_11_LENGTH_RATES_EX); -#endif /* ROKU_PRIVATE */ - _rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength)); - pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength; - - if (pnetwork->IELength > MAX_IE_SZ) /* Check pbuf->IELength */ - return H2C_PARAMETERS_ERROR; - - if (pnetwork->IELength < 2) { - report_join_res(padapter, (-4), WLAN_STATUS_UNSPECIFIED_FAILURE); - return H2C_SUCCESS; - } - _rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength); - - 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); */ - - /* sizeof(NDIS_802_11_FIXED_IEs) */ - for (i = _FIXED_IE_LENGTH_ ; i < pnetwork->IELength - 2 ;) { - pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i); - - switch (pIE->ElementID) { - case _VENDOR_SPECIFIC_IE_: /* Get WMM IE. */ - if (_rtw_memcmp(pIE->data, WMM_OUI, 4)) - WMM_param_handler(padapter, pIE); - break; - -#ifdef CONFIG_80211N_HT - case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */ - pmlmeinfo->HT_caps_enable = 1; - break; - - case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */ - pmlmeinfo->HT_info_enable = 1; - break; -#endif /* CONFIG_80211N_HT */ - -#ifdef CONFIG_80211AC_VHT - case EID_VHTCapability: /* Get VHT Cap IE. */ - pmlmeinfo->VHT_enable = 1; - break; - - case EID_VHTOperation: /* Get VHT Operation IE. */ - break; -#endif /* CONFIG_80211AC_VHT */ - default: - break; - } - - i += (pIE->Length + 2); - } - - rtw_bss_get_chbw(pnetwork - , &pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset, 1, 1); - - rtw_adjust_chbw(padapter, pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset); - -#if 0 - if (padapter->registrypriv.wifi_spec) { - /* for WiFi test, follow WMM test plan spec */ - acparm = 0x002F431C; /* VO */ - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm)); - acparm = 0x005E541C; /* VI */ - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm)); - acparm = 0x0000A525; /* BE */ - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm)); - acparm = 0x0000A549; /* BK */ - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm)); - - /* for WiFi test, mixed mode with intel STA under bg mode throughput issue */ - if (padapter->mlmepriv.htpriv.ht_option == _FALSE) { - acparm = 0x00004320; - rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm)); - } - } else { - acparm = 0x002F3217; /* VO */ - 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 */ - 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)); - } -#endif - - /* check channel, bandwidth, offset and switch */ - if (rtw_chk_start_clnt_join(padapter, &u_ch, &u_bw, &u_offset) == _FAIL) { - report_join_res(padapter, (-4), WLAN_STATUS_UNSPECIFIED_FAILURE); - return H2C_SUCCESS; - } - - /* disable dynamic functions, such as high power, DIG */ - /*rtw_phydm_func_disable_all(padapter);*/ - - /* config the initial gain under linking, need to write the BB registers */ - /* initialgain = 0x1E; */ - /*rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);*/ - - rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress); - if (MLME_IS_STA(padapter)) - rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_CONNECTING); - else - rtw_hal_rcr_set_chk_bssid(padapter, MLME_ADHOC_STARTED); - - join_type = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); - - doiqk = _TRUE; - rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk); - - set_channel_bwmode(padapter, u_ch, u_offset, u_bw); - rtw_mi_update_union_chan_inf(padapter, u_ch, u_offset, u_bw); - - doiqk = _FALSE; - rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk); - - /* cancel link timer */ - _cancel_timer_ex(&pmlmeext->link_timer); - - start_clnt_join(padapter); - - return H2C_SUCCESS; - -} - -u8 disconnect_hdl(_adapter *padapter, unsigned char *pbuf) -{ -#ifdef CONFIG_DFS - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); -#endif - struct disconnect_parm *param = (struct disconnect_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network)); - u8 val8; - - if (is_client_associated_to_ap(padapter) - #ifdef CONFIG_DFS - && !IS_RADAR_DETECTED(rfctl) && !rfctl->csa_ch - #endif - ) { - #ifdef CONFIG_PLATFORM_ROCKCHIPS - /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */ - issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); - #else - issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100); - #endif /* CONFIG_PLATFORM_ROCKCHIPS */ - } - -#ifndef CONFIG_SUPPORT_MULTI_BCN - if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) { - /* Stop BCN */ - val8 = 0; - rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8)); - } -#endif - - rtw_mlmeext_disconnect(padapter); - - rtw_free_uc_swdec_pending_queue(padapter); - - rtw_sta_mstatus_report(padapter); - - return H2C_SUCCESS; -} - -static const char *const _scan_state_str[] = { - "SCAN_DISABLE", - "SCAN_START", - "SCAN_PS_ANNC_WAIT", - "SCAN_ENTER", - "SCAN_PROCESS", - "SCAN_BACKING_OP", - "SCAN_BACK_OP", - "SCAN_LEAVING_OP", - "SCAN_LEAVE_OP", - "SCAN_SW_ANTDIV_BL", - "SCAN_TO_P2P_LISTEN", - "SCAN_P2P_LISTEN", - "SCAN_COMPLETE", - "SCAN_STATE_MAX", -}; - -const char *scan_state_str(u8 state) -{ - state = (state >= SCAN_STATE_MAX) ? SCAN_STATE_MAX : state; - return _scan_state_str[state]; -} - -static bool scan_abort_hdl(_adapter *adapter) -{ - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct ss_res *ss = &pmlmeext->sitesurvey_res; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &adapter->wdinfo; -#endif - bool ret = _FALSE; - - if (pmlmeext->scan_abort == _TRUE) { -#ifdef CONFIG_P2P - if (!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE)) { - rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX); - ss->channel_idx = 3; - RTW_INFO("%s idx:%d, cnt:%u\n", __FUNCTION__ - , ss->channel_idx - , pwdinfo->find_phase_state_exchange_cnt - ); - } else -#endif - { - ss->channel_idx = ss->ch_num; - RTW_INFO("%s idx:%d\n", __FUNCTION__ - , ss->channel_idx - ); - } - pmlmeext->scan_abort = _FALSE; - ret = _TRUE; - } - - return ret; -} - -u8 rtw_scan_sparse(_adapter *adapter, struct rtw_ieee80211_channel *ch, u8 ch_num) -{ - /* interval larger than this is treated as backgroud scan */ -#ifndef RTW_SCAN_SPARSE_BG_INTERVAL_MS -#define RTW_SCAN_SPARSE_BG_INTERVAL_MS 12000 -#endif - -#ifndef RTW_SCAN_SPARSE_CH_NUM_MIRACAST -#define RTW_SCAN_SPARSE_CH_NUM_MIRACAST 1 -#endif -#ifndef RTW_SCAN_SPARSE_CH_NUM_BG -#define RTW_SCAN_SPARSE_CH_NUM_BG 4 -#endif -#ifdef CONFIG_LAYER2_ROAMING -#ifndef RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE -#define RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE 1 -#endif -#endif - -#define SCAN_SPARSE_CH_NUM_INVALID 255 - - static u8 token = 255; - u32 interval; - bool busy_traffic = _FALSE; - bool miracast_enabled = _FALSE; - bool bg_scan = _FALSE; - u8 max_allow_ch = SCAN_SPARSE_CH_NUM_INVALID; - u8 scan_division_num; - u8 ret_num = ch_num; - struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter)); - struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; - - if (regsty->wifi_spec) - goto exit; - - /* assume ch_num > 6 is normal scan */ - if (ch_num <= 6) - goto exit; - - if (mlmeext->last_scan_time == 0) - mlmeext->last_scan_time = rtw_get_current_time(); - - interval = rtw_get_passing_time_ms(mlmeext->last_scan_time); - - - if (rtw_mi_busy_traffic_check(adapter, _FALSE)) - busy_traffic = _TRUE; - - if (rtw_mi_check_miracast_enabled(adapter)) - miracast_enabled = _TRUE; - - if (interval > RTW_SCAN_SPARSE_BG_INTERVAL_MS) - bg_scan = _TRUE; - - /* max_allow_ch by conditions*/ - -#if RTW_SCAN_SPARSE_MIRACAST - if (miracast_enabled == _TRUE && busy_traffic == _TRUE) - max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_MIRACAST); -#endif - -#if RTW_SCAN_SPARSE_BG - if (bg_scan == _TRUE) - max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_BG); -#endif - -#if defined(CONFIG_LAYER2_ROAMING) && defined(RTW_SCAN_SPARSE_ROAMING_ACTIVE) - if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) { - if (busy_traffic == _TRUE && adapter->mlmepriv.need_to_roam == _TRUE) - max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE); - } -#endif - - - if (max_allow_ch != SCAN_SPARSE_CH_NUM_INVALID) { - int i; - int k = 0; - - scan_division_num = (ch_num / max_allow_ch) + ((ch_num % max_allow_ch) ? 1 : 0); - token = (token + 1) % scan_division_num; - - if (0) - RTW_INFO("scan_division_num:%u, token:%u\n", scan_division_num, token); - - for (i = 0; i < ch_num; i++) { - if (ch[i].hw_value && (i % scan_division_num) == token - ) { - if (i != k) - _rtw_memcpy(&ch[k], &ch[i], sizeof(struct rtw_ieee80211_channel)); - k++; - } - } - - _rtw_memset(&ch[k], 0, sizeof(struct rtw_ieee80211_channel)); - - ret_num = k; - mlmeext->last_scan_time = rtw_get_current_time(); - } - -exit: - return ret_num; -} - -#ifdef CONFIG_SCAN_BACKOP -u8 rtw_scan_backop_decision(_adapter *adapter) -{ - struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; - struct mi_state mstate; - u8 backop_flags = 0; - - rtw_mi_status(adapter, &mstate); - - if ((MSTATE_STA_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN)) - || (MSTATE_STA_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN_NL))) - backop_flags |= mlmeext_scan_backop_flags_sta(mlmeext); - -#ifdef CONFIG_AP_MODE - if ((MSTATE_AP_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN)) - || (MSTATE_AP_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN_NL))) - backop_flags |= mlmeext_scan_backop_flags_ap(mlmeext); -#endif - -#ifdef CONFIG_RTW_MESH - if ((MSTATE_MESH_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN)) - || (MSTATE_MESH_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN_NL))) - backop_flags |= mlmeext_scan_backop_flags_mesh(mlmeext); -#endif - - return backop_flags; -} -#endif - -#define SCANNING_TIMEOUT_EX 2000 -u32 rtw_scan_timeout_decision(_adapter *padapter) -{ - u32 back_op_times= 0; - u8 max_chan_num; - u16 scan_ms; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ss_res *ss = &pmlmeext->sitesurvey_res; - - if (is_supported_5g(padapter->registrypriv.wireless_mode) - && IsSupported24G(padapter->registrypriv.wireless_mode)) - max_chan_num = MAX_CHANNEL_NUM;/* dual band */ - else - max_chan_num = MAX_CHANNEL_NUM_2G;/*single band*/ - - #ifdef CONFIG_SCAN_BACKOP - if (rtw_scan_backop_decision(padapter)) - back_op_times = (max_chan_num / ss->scan_cnt_max) * ss->backop_ms; - #endif - - if (ss->duration) - scan_ms = ss->duration; - else - #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG) - if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter)) - scan_ms = rtw_acs_get_adv_st(padapter); - else - #endif /*CONFIG_RTW_ACS*/ - scan_ms = ss->scan_ch_ms; - - ss->scan_timeout_ms = (scan_ms * max_chan_num) + back_op_times + SCANNING_TIMEOUT_EX; - #ifdef DBG_SITESURVEY - RTW_INFO("%s , scan_timeout_ms = %d (ms)\n", __func__, ss->scan_timeout_ms); - #endif /*DBG_SITESURVEY*/ - return ss->scan_timeout_ms; -} - -static int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out, - u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num) -{ - int i, j; - int set_idx; - u8 chan; - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - - /* clear first */ - _rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num); - - /* acquire channels from in */ - j = 0; - for (i = 0; i < in_num; i++) { - - if (0) - RTW_INFO(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i])); - - if (!in[i].hw_value || (in[i].flags & RTW_IEEE80211_CHAN_DISABLED)) - continue; - if (rtw_mlme_band_check(padapter, in[i].hw_value) == _FALSE) - continue; - - set_idx = rtw_chset_search_ch(rfctl->channel_set, in[i].hw_value); - if (set_idx >= 0) { - if (j >= out_num) { - RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n", - FUNC_ADPT_ARG(padapter), out_num); - break; - } - - _rtw_memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel)); - - if (rfctl->channel_set[set_idx].ScanType == SCAN_PASSIVE) - out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; - - j++; - } - if (j >= out_num) - break; - } - - /* if out is empty, use channel_set as default */ - if (j == 0) { - for (i = 0; i < rfctl->max_chan_nums; i++) { - chan = rfctl->channel_set[i].ChannelNum; - if (rtw_mlme_band_check(padapter, chan) == _TRUE) { - if (rtw_mlme_ignore_chan(padapter, chan) == _TRUE) - continue; - - if (0) - RTW_INFO(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), chan); - - if (j >= out_num) { - RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n", - FUNC_ADPT_ARG(padapter), out_num); - break; - } - - out[j].hw_value = chan; - - if (rfctl->channel_set[i].ScanType == SCAN_PASSIVE) - out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; - - j++; - } - } - } - - /* scan_sparse */ - j = rtw_scan_sparse(padapter, out, j); - - return j; -} - -static void sitesurvey_res_reset(_adapter *adapter, struct sitesurvey_parm *parm) -{ - struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res; - RT_CHANNEL_INFO *chset = adapter_to_chset(adapter); - int i; - - ss->bss_cnt = 0; - ss->channel_idx = 0; -#ifdef CONFIG_DFS - ss->dfs_ch_ssid_scan = 0; -#endif - ss->igi_scan = 0; - ss->igi_before_scan = 0; -#ifdef CONFIG_SCAN_BACKOP - ss->scan_cnt = 0; -#endif -#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL) - ss->is_sw_antdiv_bl_scan = 0; -#endif - ss->ssid_num = 0; - for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (parm->ssid[i].SsidLength) { - _rtw_memcpy(ss->ssid[i].Ssid, parm->ssid[i].Ssid, IW_ESSID_MAX_SIZE); - ss->ssid[i].SsidLength = parm->ssid[i].SsidLength; - ss->ssid_num++; - } else - ss->ssid[i].SsidLength = 0; - } - - ss->ch_num = rtw_scan_ch_decision(adapter - , ss->ch, RTW_CHANNEL_SCAN_AMOUNT - , parm->ch, parm->ch_num - ); - -#ifdef CONFIG_DFS - for (i = 0; i < MAX_CHANNEL_NUM; i++) - chset[i].hidden_bss_cnt = 0; -#endif - - ss->bw = parm->bw; - ss->igi = parm->igi; - ss->token = parm->token; - ss->duration = parm->duration; - ss->scan_mode = parm->scan_mode; - ss->token = parm->token; -} - -static u8 sitesurvey_pick_ch_behavior(_adapter *padapter, u8 *ch, RT_SCAN_TYPE *type) -{ - u8 next_state; - u8 scan_ch = 0; - RT_SCAN_TYPE scan_type = SCAN_PASSIVE; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ss_res *ss = &pmlmeext->sitesurvey_res; - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - int ch_set_idx; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; -#endif -#ifdef CONFIG_SCAN_BACKOP - u8 backop_flags = 0; -#endif - - /* handle scan abort request */ - scan_abort_hdl(padapter); - -#ifdef CONFIG_P2P - if (pwdinfo->rx_invitereq_info.scan_op_ch_only || pwdinfo->p2p_info.scan_op_ch_only) { - if (pwdinfo->rx_invitereq_info.scan_op_ch_only) - scan_ch = pwdinfo->rx_invitereq_info.operation_ch[ss->channel_idx]; - else - scan_ch = pwdinfo->p2p_info.operation_ch[ss->channel_idx]; - scan_type = SCAN_ACTIVE; - } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) { - /* - * Commented by Albert 2011/06/03 - * The driver is in the find phase, it should go through the social channel. - */ - scan_ch = pwdinfo->social_chan[ss->channel_idx]; - ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, scan_ch); - if (ch_set_idx >= 0) - scan_type = rfctl->channel_set[ch_set_idx].ScanType; - else - scan_type = SCAN_ACTIVE; - } else -#endif /* CONFIG_P2P */ - { - struct rtw_ieee80211_channel *ch; - - #ifdef CONFIG_SCAN_BACKOP - backop_flags = rtw_scan_backop_decision(padapter); - #endif - -#ifdef CONFIG_DFS - #ifdef CONFIG_SCAN_BACKOP - if (!(backop_flags && ss->scan_cnt >= ss->scan_cnt_max)) - #endif - { - #ifdef CONFIG_RTW_WIFI_HAL - if (adapter_to_dvobj(padapter)->nodfs) { - while ( ss->channel_idx < ss->ch_num && rtw_is_dfs_ch(ss->ch[ss->channel_idx].hw_value)) - ss->channel_idx++; - } else - #endif - if (ss->channel_idx != 0 && ss->dfs_ch_ssid_scan == 0 - && pmlmeext->sitesurvey_res.ssid_num - && rtw_is_dfs_ch(ss->ch[ss->channel_idx - 1].hw_value) - ) { - ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, ss->ch[ss->channel_idx - 1].hw_value); - if (ch_set_idx != -1 && rfctl->channel_set[ch_set_idx].hidden_bss_cnt - && (!IS_DFS_SLAVE_WITH_RD(rfctl) - || rtw_odm_dfs_domain_unknown(rfctl_to_dvobj(rfctl)) - || !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx])) - ) { - ss->channel_idx--; - ss->dfs_ch_ssid_scan = 1; - } - } else - ss->dfs_ch_ssid_scan = 0; - } -#endif /* CONFIG_DFS */ - - if (ss->channel_idx < ss->ch_num) { - ch = &ss->ch[ss->channel_idx]; - scan_ch = ch->hw_value; - - #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG) - if (IS_ACS_ENABLE(padapter) && rtw_is_acs_passiv_scan(padapter)) - scan_type = SCAN_PASSIVE; - else - #endif /*CONFIG_RTW_ACS*/ - scan_type = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE; - } - } - - if (scan_ch != 0) { - next_state = SCAN_PROCESS; - - #ifdef CONFIG_SCAN_BACKOP - if (backop_flags) { - if (ss->scan_cnt < ss->scan_cnt_max) - ss->scan_cnt++; - else { - mlmeext_assign_scan_backop_flags(pmlmeext, backop_flags); - next_state = SCAN_BACKING_OP; - } - } - #endif - - } else if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) { - /* go p2p listen */ - next_state = SCAN_TO_P2P_LISTEN; - -#ifdef CONFIG_ANTENNA_DIVERSITY - } else if (rtw_hal_antdiv_before_linked(padapter)) { - /* go sw antdiv before link */ - next_state = SCAN_SW_ANTDIV_BL; -#endif - } else { - next_state = SCAN_COMPLETE; - -#if defined(DBG_SCAN_SW_ANTDIV_BL) - { - /* for SCAN_SW_ANTDIV_BL state testing */ - struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - int i; - bool is_linked = _FALSE; - - for (i = 0; i < dvobj->iface_nums; i++) { - if (rtw_linked_check(dvobj->padapters[i])) - is_linked = _TRUE; - } - - if (!is_linked) { - static bool fake_sw_antdiv_bl_state = 0; - - if (fake_sw_antdiv_bl_state == 0) { - next_state = SCAN_SW_ANTDIV_BL; - fake_sw_antdiv_bl_state = 1; - } else - fake_sw_antdiv_bl_state = 0; - } - } -#endif /* defined(DBG_SCAN_SW_ANTDIV_BL) */ - } - -#ifdef CONFIG_SCAN_BACKOP - if (next_state != SCAN_PROCESS) - ss->scan_cnt = 0; -#endif - - -#ifdef DBG_FIXED_CHAN - if (pmlmeext->fixed_chan != 0xff && next_state == SCAN_PROCESS) - scan_ch = pmlmeext->fixed_chan; -#endif - - if (ch) - *ch = scan_ch; - if (type) - *type = scan_type; - - return next_state; -} - -void site_survey(_adapter *padapter, u8 survey_channel, RT_SCAN_TYPE ScanType) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ss_res *ss = &pmlmeext->sitesurvey_res; - u8 ssid_scan = 0; - -#ifdef CONFIG_P2P -#ifndef CONFIG_IOCTL_CFG80211 - struct wifidirect_info *pwdinfo = &(padapter->wdinfo); -#endif -#endif - - if (survey_channel != 0) { - set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - -#ifdef CONFIG_DFS - if (ScanType == SCAN_PASSIVE && ss->dfs_ch_ssid_scan) - ssid_scan = 1; - else -#endif - if (ScanType == SCAN_ACTIVE) { -#ifdef CONFIG_P2P - #ifdef CONFIG_IOCTL_CFG80211 - if (rtw_cfg80211_is_p2p_scan(padapter)) - #else - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) - || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) - #endif - { - issue_probereq_p2p(padapter, NULL); - issue_probereq_p2p(padapter, NULL); - issue_probereq_p2p(padapter, NULL); - } else -#endif /* CONFIG_P2P */ - { - if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { - /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ - if (padapter->registrypriv.wifi_spec) - issue_probereq(padapter, NULL, NULL); - else - issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0); - issue_probereq(padapter, NULL, NULL); - } - - ssid_scan = 1; - } - } - - if (ssid_scan) { - int i; - - for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { - if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) { - /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ - if (padapter->registrypriv.wifi_spec) - issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); - else - issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0); - issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); - } - } - } - } else { - /* channel number is 0 or this channel is not valid. */ - rtw_warn_on(1); - } - - return; -} - -void survey_done_set_ch_bw(_adapter *padapter) -{ - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - u8 cur_channel = 0; - u8 cur_bwmode; - u8 cur_ch_offset; - -#ifdef CONFIG_MCC_MODE - if (!rtw_hal_mcc_change_scan_flag(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset)) { - if (0) - RTW_INFO(FUNC_ADPT_FMT" back to AP channel - ch:%u, bw:%u, offset:%u\n", - FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset); - goto exit; - } -#endif - - if (rtw_mi_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0) { - if (0) - RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n", - FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset); - } else { -#ifdef CONFIG_P2P - struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); - _adapter *iface; - int i; - - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - if (!iface) - continue; - -#ifdef CONFIG_IOCTL_CFG80211 - if (iface->wdinfo.driver_interface == DRIVER_CFG80211 && !adapter_wdev_data(iface)->p2p_enabled) - continue; -#endif - - if (rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_LISTEN)) { - cur_channel = iface->wdinfo.listen_channel; - cur_bwmode = CHANNEL_WIDTH_20; - cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - if (0) - RTW_INFO(FUNC_ADPT_FMT" back to "ADPT_FMT"'s listen ch - ch:%u, bw:%u, offset:%u\n", - FUNC_ADPT_ARG(padapter), ADPT_ARG(iface), cur_channel, cur_bwmode, cur_ch_offset); - break; - } - } -#endif /* CONFIG_P2P */ - - if (cur_channel == 0) { - cur_channel = pmlmeext->cur_channel; - cur_bwmode = pmlmeext->cur_bwmode; - cur_ch_offset = pmlmeext->cur_ch_offset; - if (0) - RTW_INFO(FUNC_ADPT_FMT" back to ch:%u, bw:%u, offset:%u\n", - FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset); - } - } -#ifdef CONFIG_MCC_MODE -exit: -#endif - set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode); -} - -/** - * rtw_ps_annc - check and doing ps announcement for all the adapters - * @adapter: the requesting adapter - * @ps: power saving or not - * - * Returns: 0: no ps announcement is doing. 1: ps announcement is doing - */ -u8 rtw_ps_annc(_adapter *adapter, bool ps) -{ - struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); - _adapter *iface; - int i; - u8 ps_anc = 0; - - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - if (!iface) - continue; - - if (MLME_IS_STA(iface)) { - if (is_client_associated_to_ap(iface) == _TRUE) { - /* TODO: TDLS peers */ - #ifdef CONFIG_MCC_MODE - /* for two station case */ - if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_NEED_MCC)) { - u8 ch = iface->mlmeextpriv.cur_channel; - u8 offset = iface->mlmeextpriv.cur_ch_offset; - u8 bw = iface->mlmeextpriv.cur_bwmode; - - set_channel_bwmode(iface, ch, offset, bw); - } - #endif /* CONFIG_MCC_MODE */ - issue_nulldata(iface, NULL, ps, 3, 500); - ps_anc = 1; - } - #ifdef CONFIG_RTW_MESH - } else if (MLME_IS_MESH(iface)) { - if (rtw_mesh_ps_annc(iface, ps)) - ps_anc = 1; - #endif - } - } - return ps_anc; -} - -void rtw_leave_opch(_adapter *adapter) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - -#ifdef CONFIG_MCC_MODE - if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) - return; -#endif - - _enter_critical_mutex(&rfctl->offch_mutex, NULL); - - if (rfctl->offch_state == OFFCHS_NONE) { - /* prepare to leave operating channel */ - rfctl->offch_state = OFFCHS_LEAVING_OP; - - /* clear HW TX queue */ - rtw_hal_set_hwreg(adapter, HW_VAR_CHECK_TXBUF, 0); - - rtw_hal_macid_sleep_all_used(adapter); - - rtw_ps_annc(adapter, 1); - - rfctl->offch_state = OFFCHS_LEAVE_OP; - } - - _exit_critical_mutex(&rfctl->offch_mutex, NULL); -} - -void rtw_back_opch(_adapter *adapter) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - -#ifdef CONFIG_MCC_MODE - if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) - return; -#endif - - _enter_critical_mutex(&rfctl->offch_mutex, NULL); - - if (rfctl->offch_state != OFFCHS_NONE) { - rfctl->offch_state = OFFCHS_BACKING_OP; - rtw_hal_macid_wakeup_all_used(adapter); - rtw_ps_annc(adapter, 0); - - rfctl->offch_state = OFFCHS_NONE; - rtw_mi_os_xmit_schedule(adapter); - } - - _exit_critical_mutex(&rfctl->offch_mutex, NULL); -} - -void sitesurvey_set_igi(_adapter *adapter) -{ - struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; - struct ss_res *ss = &mlmeext->sitesurvey_res; - u8 igi; -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &adapter->wdinfo; -#endif - - switch (mlmeext_scan_state(mlmeext)) { - case SCAN_ENTER: - #ifdef CONFIG_P2P - #ifdef CONFIG_IOCTL_CFG80211 - if (pwdinfo->driver_interface == DRIVER_CFG80211 && rtw_cfg80211_is_p2p_scan(adapter)) - igi = 0x30; - else - #endif /* CONFIG_IOCTL_CFG80211 */ - if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) - igi = 0x28; - else - #endif /* CONFIG_P2P */ - - if (ss->igi) - igi = ss->igi; - else - #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG) - if (IS_ACS_ENABLE(adapter) && rtw_is_acs_igi_valid(adapter)) - igi = rtw_acs_get_adv_igi(adapter); - else - #endif /*CONFIG_RTW_ACS*/ - igi = 0x1e; - - /* record IGI status */ - ss->igi_scan = igi; - rtw_hal_get_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &ss->igi_before_scan, NULL); - - /* disable DIG and set IGI for scan */ - rtw_hal_set_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &igi, _FALSE); - break; - case SCAN_COMPLETE: - case SCAN_TO_P2P_LISTEN: - /* enable DIG and restore IGI */ - igi = 0xff; - rtw_hal_set_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &igi, _FALSE); - break; -#ifdef CONFIG_SCAN_BACKOP - case SCAN_BACKING_OP: - /* write IGI for op channel when DIG is not enabled */ - odm_write_dig(adapter_to_phydm(adapter), ss->igi_before_scan); - break; - case SCAN_LEAVE_OP: - /* write IGI for scan when DIG is not enabled */ - odm_write_dig(adapter_to_phydm(adapter), ss->igi_scan); - break; -#endif /* CONFIG_SCAN_BACKOP */ - default: - rtw_warn_on(1); - break; - } -} -void sitesurvey_set_msr(_adapter *adapter, bool enter) -{ - u8 network_type; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (enter) { -#ifdef CONFIG_MI_WITH_MBSSID_CAM - rtw_hal_get_hwreg(adapter, HW_VAR_MEDIA_STATUS, (u8 *)(&pmlmeinfo->hw_media_state)); -#endif - /* set MSR to no link state */ - network_type = _HW_STATE_NOLINK_; - } else { -#ifdef CONFIG_MI_WITH_MBSSID_CAM - network_type = pmlmeinfo->hw_media_state; -#else - network_type = pmlmeinfo->state & 0x3; -#endif - } - Set_MSR(adapter, network_type); -} - -void sitesurvey_set_offch_state(_adapter *adapter, u8 scan_state) -{ - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - - _enter_critical_mutex(&rfctl->offch_mutex, NULL); - - switch (scan_state) { - case SCAN_DISABLE: - case SCAN_BACK_OP: - rfctl->offch_state = OFFCHS_NONE; - break; - case SCAN_START: - case SCAN_LEAVING_OP: - rfctl->offch_state = OFFCHS_LEAVING_OP; - break; - case SCAN_ENTER: - case SCAN_LEAVE_OP: - rfctl->offch_state = OFFCHS_LEAVE_OP; - break; - case SCAN_COMPLETE: - case SCAN_BACKING_OP: - rfctl->offch_state = OFFCHS_BACKING_OP; - break; - default: - break; - } - - _exit_critical_mutex(&rfctl->offch_mutex, NULL); -} - -u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf) -{ - struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; -#ifdef DBG_CHECK_FW_PS_STATE - struct dvobj_priv *dvobj = padapter->dvobj; - struct debug_priv *pdbgpriv = &dvobj->drv_dbg; -#endif - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct ss_res *ss = &pmlmeext->sitesurvey_res; -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); -#endif - u8 val8; - -#ifdef CONFIG_P2P - struct wifidirect_info *pwdinfo = &padapter->wdinfo; -#endif - -#ifdef DBG_CHECK_FW_PS_STATE - if (rtw_fw_ps_state(padapter) == _FAIL) { - RTW_INFO("scan without leave 32k\n"); - pdbgpriv->dbg_scan_pwr_state_cnt++; - } -#endif /* DBG_CHECK_FW_PS_STATE */ - - /* increase channel idx */ - if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS)) - ss->channel_idx++; - - /* update scan state to next state (assigned by previous cmd hdl) */ - if (mlmeext_scan_state(pmlmeext) != mlmeext_scan_next_state(pmlmeext)) - mlmeext_set_scan_state(pmlmeext, mlmeext_scan_next_state(pmlmeext)); - -operation_by_state: - switch (mlmeext_scan_state(pmlmeext)) { - - case SCAN_DISABLE: - /* - * SW parameter initialization - */ - - sitesurvey_res_reset(padapter, pparm); - mlmeext_set_scan_state(pmlmeext, SCAN_START); - goto operation_by_state; - - case SCAN_START: -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - if ((pwdev_priv->pno_mac_addr[0] != 0xFF) - && (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE) - && (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) { - u16 seq_num; - - rtw_hal_pno_random_gen_mac_addr(padapter); - rtw_hal_set_hw_mac_addr(padapter, pwdev_priv->pno_mac_addr); - get_random_bytes(&seq_num, 2); - pwdev_priv->pno_scan_seq_num = seq_num & 0xFFF; - RTW_INFO("%s pno_scan_seq_num %d\n", __func__, - pwdev_priv->pno_scan_seq_num); - } -#endif - - /* - * prepare to leave operating channel - */ - -#ifdef CONFIG_MCC_MODE - rtw_hal_set_mcc_setting_scan_start(padapter); -#endif /* CONFIG_MCC_MODE */ - - /* apply rx ampdu setting */ - if (ss->rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID - || ss->rx_ampdu_size != RX_AMPDU_SIZE_INVALID) - rtw_rx_ampdu_apply(padapter); - - /* clear HW TX queue before scan */ - rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0); - - rtw_hal_macid_sleep_all_used(padapter); - - /* power save state announcement */ - if (rtw_ps_annc(padapter, 1)) { - mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT); - mlmeext_set_scan_next_state(pmlmeext, SCAN_ENTER); - set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */ - } else { - mlmeext_set_scan_state(pmlmeext, SCAN_ENTER); - goto operation_by_state; - } - - break; - - case SCAN_ENTER: - /* - * HW register and DM setting for enter scan - */ - - rtw_phydm_ability_backup(padapter); - - sitesurvey_set_igi(padapter); - - /* config dynamic functions for off channel */ - rtw_phydm_func_for_offchannel(padapter); - /* set MSR to no link state */ - sitesurvey_set_msr(padapter, _TRUE); - - val8 = 1; /* under site survey */ - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - - mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS); - goto operation_by_state; - - case SCAN_PROCESS: { - u8 scan_ch; - RT_SCAN_TYPE scan_type; - u8 next_state; - u32 scan_ms; - -#ifdef CONFIG_RTW_ACS - if (IS_ACS_ENABLE(padapter)) - rtw_acs_get_rst(padapter); -#endif - - next_state = sitesurvey_pick_ch_behavior(padapter, &scan_ch, &scan_type); - - if (next_state != SCAN_PROCESS) { - mlmeext_set_scan_state(pmlmeext, next_state); - goto operation_by_state; - } - - /* still SCAN_PROCESS state */ - #ifdef DBG_SITESURVEY - #ifdef CONFIG_P2P - RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c%c\n" - , FUNC_ADPT_ARG(padapter) - , mlmeext_scan_state_str(pmlmeext) - , scan_ch - , pwdinfo->find_phase_state_exchange_cnt, ss->channel_idx - , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time) - , scan_type ? 'A' : 'P', ss->scan_mode ? 'A' : 'P' - , ss->ssid[0].SsidLength ? 'S' : ' ' - , ss->dfs_ch_ssid_scan ? 'D' : ' ' - ); - #else - RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (idx:%d) at %dms, %c%c%c%c\n" - , FUNC_ADPT_ARG(padapter) - , mlmeext_scan_state_str(pmlmeext) - , scan_ch - , ss->channel_idx - , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time) - , scan_type ? 'A' : 'P', ss->scan_mode ? 'A' : 'P' - , ss->ssid[0].SsidLength ? 'S' : ' ' - , ss->dfs_ch_ssid_scan ? 'D' : ' ' - ); - #endif /* CONFIG_P2P */ - #endif /*DBG_SITESURVEY*/ -#ifdef DBG_FIXED_CHAN - if (pmlmeext->fixed_chan != 0xff) - RTW_INFO(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan); -#endif - - site_survey(padapter, scan_ch, scan_type); - -#if defined(CONFIG_ATMEL_RC_PATCH) - if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) - scan_ms = 20; - else - scan_ms = 40; -#else - #if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG) - if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter)) - scan_ms = rtw_acs_get_adv_st(padapter); - else - #endif /*CONFIG_RTW_ACS*/ - scan_ms = ss->scan_ch_ms; -#endif - -#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL) - if (ss->is_sw_antdiv_bl_scan) - scan_ms = scan_ms / 2; -#endif - -#ifdef CONFIG_RTW_ACS - if (IS_ACS_ENABLE(padapter)) { - if (pparm->token) - rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_IEEE_11K_HIGH); - else - rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_ACS); - } -#endif - -#ifdef CONFIG_BACKGROUND_NOISE_MONITOR - if (IS_NM_ENABLE(padapter)) - rtw_noise_measure(padapter, scan_ch, _FALSE, 0, scan_ms / 2); -#endif - set_survey_timer(pmlmeext, scan_ms); - break; - } - -#ifdef CONFIG_SCAN_BACKOP - case SCAN_BACKING_OP: { - u8 back_ch, back_bw, back_ch_offset; - u8 need_ch_setting_union = _TRUE; - -#ifdef CONFIG_MCC_MODE - need_ch_setting_union = rtw_hal_mcc_change_scan_flag(padapter, - &back_ch, &back_bw, &back_ch_offset); -#endif /* CONFIG_MCC_MODE */ - - if (need_ch_setting_union) { - if (rtw_mi_get_ch_setting_union(padapter, &back_ch, &back_bw, &back_ch_offset) == 0) - rtw_warn_on(1); - } - - #ifdef DBG_SITESURVEY - RTW_INFO(FUNC_ADPT_FMT" %s ch:%u, bw:%u, offset:%u at %dms\n" - , FUNC_ADPT_ARG(padapter) - , mlmeext_scan_state_str(pmlmeext) - , back_ch, back_bw, back_ch_offset - , rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time) - ); - #endif /*DBG_SITESURVEY*/ - set_channel_bwmode(padapter, back_ch, back_ch_offset, back_bw); - - sitesurvey_set_msr(padapter, _FALSE); - - val8 = 0; /* survey done */ - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - - if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) { - sitesurvey_set_igi(padapter); - rtw_hal_macid_wakeup_all_used(padapter); - rtw_ps_annc(padapter, 0); - } - - mlmeext_set_scan_state(pmlmeext, SCAN_BACK_OP); - ss->backop_time = rtw_get_current_time(); - - if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_TX_RESUME)) - rtw_mi_os_xmit_schedule(padapter); - - - goto operation_by_state; - } - - case SCAN_BACK_OP: - if (rtw_get_passing_time_ms(ss->backop_time) >= ss->backop_ms - || pmlmeext->scan_abort - ) { - mlmeext_set_scan_state(pmlmeext, SCAN_LEAVING_OP); - goto operation_by_state; - } - set_survey_timer(pmlmeext, 50); - break; - - case SCAN_LEAVING_OP: - /* - * prepare to leave operating channel - */ - - /* clear HW TX queue before scan */ - rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0); - - rtw_hal_macid_sleep_all_used(padapter); - if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC) - && rtw_ps_annc(padapter, 1) - ) { - mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT); - mlmeext_set_scan_next_state(pmlmeext, SCAN_LEAVE_OP); - set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */ - } else { - mlmeext_set_scan_state(pmlmeext, SCAN_LEAVE_OP); - goto operation_by_state; - } - - break; - - case SCAN_LEAVE_OP: - /* - * HW register and DM setting for enter scan - */ - - if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) - sitesurvey_set_igi(padapter); - - sitesurvey_set_msr(padapter, _TRUE); - - val8 = 1; /* under site survey */ - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - - mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS); - goto operation_by_state; - -#endif /* CONFIG_SCAN_BACKOP */ - -#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL) - case SCAN_SW_ANTDIV_BL: - /* - * 20100721 - * For SW antenna diversity before link, it needs to switch to another antenna and scan again. - * It compares the scan result and select better one to do connection. - */ - ss->bss_cnt = 0; - ss->channel_idx = 0; - ss->is_sw_antdiv_bl_scan = 1; - - mlmeext_set_scan_next_state(pmlmeext, SCAN_PROCESS); - set_survey_timer(pmlmeext, ss->scan_ch_ms); - break; -#endif - -#ifdef CONFIG_P2P - case SCAN_TO_P2P_LISTEN: - /* - * Set the P2P State to the listen state of find phase - * and set the current channel to the listen channel - */ - set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); - rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN); - - /* turn on phy-dynamic functions */ - rtw_phydm_ability_restore(padapter); - - sitesurvey_set_igi(padapter); - - mlmeext_set_scan_state(pmlmeext, SCAN_P2P_LISTEN); - _set_timer(&pwdinfo->find_phase_timer, (u32)((u32)pwdinfo->listen_dwell * 100)); - break; - - case SCAN_P2P_LISTEN: - mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS); - ss->channel_idx = 0; - goto operation_by_state; -#endif /* CONFIG_P2P */ - - case SCAN_COMPLETE: -#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI - rtw_hal_set_hw_mac_addr(padapter, adapter_mac_addr(padapter)); -#endif -#ifdef CONFIG_P2P - if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) - || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) - ) { -#ifdef CONFIG_CONCURRENT_MODE - if (pwdinfo->driver_interface == DRIVER_WEXT) { - if (rtw_mi_check_status(padapter, MI_LINKED)) - _set_timer(&pwdinfo->ap_p2p_switch_timer, 500); - } -#endif - - rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo)); - } - rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE); -#endif /* CONFIG_P2P */ - - /* switch channel */ - survey_done_set_ch_bw(padapter); - - sitesurvey_set_msr(padapter, _FALSE); - - val8 = 0; /* survey done */ - rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); - - /* turn on phy-dynamic functions */ - rtw_phydm_ability_restore(padapter); - - sitesurvey_set_igi(padapter); - -#ifdef CONFIG_MCC_MODE - /* start MCC fail, then tx null data */ - if (!rtw_hal_set_mcc_setting_scan_complete(padapter)) -#endif - { - rtw_hal_macid_wakeup_all_used(padapter); - rtw_ps_annc(padapter, 0); - } - - /* apply rx ampdu setting */ - rtw_rx_ampdu_apply(padapter); - - mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE); - - report_surveydone_event(padapter); -#ifdef CONFIG_RTW_ACS - if (IS_ACS_ENABLE(padapter)) - rtw_acs_select_best_chan(padapter); -#endif - -#if defined(CONFIG_BACKGROUND_NOISE_MONITOR) && defined(DBG_NOISE_MONITOR) - if (IS_NM_ENABLE(padapter)) - rtw_noise_info_dump(RTW_DBGDUMP, padapter); -#endif - issue_action_BSSCoexistPacket(padapter); - issue_action_BSSCoexistPacket(padapter); - issue_action_BSSCoexistPacket(padapter); - -#ifdef CONFIG_RTW_80211K - if (ss->token) - rm_post_event(padapter, ss->token, RM_EV_survey_done); -#endif /* CONFIG_RTW_80211K */ - - break; - } - - return H2C_SUCCESS; -} - -u8 setauth_hdl(_adapter *padapter, unsigned char *pbuf) -{ - struct setauth_parm *pparm = (struct setauth_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - if (pparm->mode < 4) - pmlmeinfo->auth_algo = pparm->mode; - - return H2C_SUCCESS; -} - -/* -SEC CAM Entry format (32 bytes) -DW0 - MAC_ADDR[15:0] | Valid[15] | MFB[14:8] | RSVD[7] | GK[6] | MIC_KEY[5] | SEC_TYPE[4:2] | KID[1:0] -DW0 - MAC_ADDR[15:0] | Valid[15] |RSVD[14:9] | RPT_MODE[8] | SPP_MODE[7] | GK[6] | MIC_KEY[5] | SEC_TYPE[4:2] | KID[1:0] (92E/8812A/8814A) -DW1 - MAC_ADDR[47:16] -DW2 - KEY[31:0] -DW3 - KEY[63:32] -DW4 - KEY[95:64] -DW5 - KEY[127:96] -DW6 - RSVD -DW7 - RSVD -*/ - -/*Set WEP key or Group Key*/ -u8 setkey_hdl(_adapter *padapter, u8 *pbuf) -{ - u16 ctrl = 0; - s16 cam_id = 0; - struct setkey_parm *pparm = (struct setkey_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - u8 *addr; - bool used = _FALSE; - - /* main tx key for wep. */ - if (pparm->set_tx) - pmlmeinfo->key_index = pparm->keyid; - -#ifdef CONFIG_CONCURRENT_MODE - if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) - cam_id = rtw_iface_bcmc_id_get(padapter); - else -#endif - cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid, 1, &used); - - if (cam_id < 0) - goto enable_mc; - -#ifndef CONFIG_CONCURRENT_MODE - if (cam_id >= 0 && cam_id <= 3) { - /* default key camid */ - addr = null_addr; - } else -#endif - { - /* not default key camid */ - if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) { - /* group TX, force sec cam entry_id */ - addr = adapter_mac_addr(padapter); - } else { - /* group RX, searched by A2 (TA) */ - addr = get_bssid(&padapter->mlmepriv); - } - } - - /* cam entry searched is pairwise key */ - if (used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _FALSE) { - s16 camid_clr; - - RTW_PRINT(FUNC_ADPT_FMT" group key with "MAC_FMT" id:%u the same key id as pairwise key\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(addr), pparm->keyid); - - /* HW has problem to distinguish this group key with existing pairwise key, stop HW enc and dec for BMC */ - rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH); - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL); - - /* clear group key */ - while ((camid_clr = rtw_camid_search(padapter, addr, -1, 1)) >= 0) { - RTW_PRINT("clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(addr), camid_clr); - clear_cam_entry(padapter, camid_clr); - rtw_camid_free(padapter, camid_clr); - } - - goto enable_mc; - } - - ctrl = BIT(15) | BIT(6) | ((pparm->algorithm) << 2) | pparm->keyid; - - RTW_PRINT("set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n" - , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm)); - - write_cam(padapter, cam_id, ctrl, addr, pparm->key); - - /* if ((cam_id > 3) && (((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)))*/ -#ifdef CONFIG_CONCURRENT_MODE - if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) { - if (is_wep_enc(pparm->algorithm)) { - padapter->securitypriv.dot11Def_camid[pparm->keyid] = cam_id; - padapter->securitypriv.dot118021x_bmc_cam_id = - padapter->securitypriv.dot11Def_camid[padapter->securitypriv.dot11PrivacyKeyIndex]; - RTW_PRINT("wep group key - force camid:%d\n", padapter->securitypriv.dot118021x_bmc_cam_id); - } else { - /*u8 org_cam_id = padapter->securitypriv.dot118021x_bmc_cam_id;*/ - - /*force GK's cam id*/ - padapter->securitypriv.dot118021x_bmc_cam_id = cam_id; - - /* for GTK rekey - if ((org_cam_id != INVALID_SEC_MAC_CAM_ID) && - (org_cam_id != cam_id)) { - RTW_PRINT("clear group key for addr:"MAC_FMT", org_camid:%d new_camid:%d\n", MAC_ARG(addr), org_cam_id, cam_id); - clear_cam_entry(padapter, org_cam_id); - rtw_camid_free(padapter, org_cam_id); - }*/ - } - } -#endif - - -#ifndef CONFIG_CONCURRENT_MODE - if (cam_id >= 0 && cam_id <= 3) - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)_TRUE); -#endif - - /* 8814au should set both broadcast and unicast CAM entry for WEP key in STA mode */ - if (is_wep_enc(pparm->algorithm) && check_mlmeinfo_state(pmlmeext, WIFI_FW_STATION_STATE) && - _rtw_camctl_chk_cap(padapter, SEC_CAP_CHK_BMC)) { - struct set_stakey_parm sta_pparm; - - _rtw_memset(&sta_pparm, 0, sizeof(struct set_stakey_parm)); - sta_pparm.algorithm = pparm->algorithm; - sta_pparm.keyid = pparm->keyid; - _rtw_memcpy(sta_pparm.key, pparm->key, 16); - _rtw_memcpy(sta_pparm.addr, get_bssid(&padapter->mlmepriv), ETH_ALEN); - set_stakey_hdl(padapter, (u8 *)&sta_pparm); - } - -enable_mc: - /* allow multicast packets to driver */ - rtw_hal_set_hwreg(padapter, HW_VAR_ON_RCR_AM, null_addr); - - return H2C_SUCCESS; -} - -void rtw_ap_wep_pk_setting(_adapter *adapter, struct sta_info *psta) -{ - struct security_priv *psecuritypriv = &(adapter->securitypriv); - struct set_stakey_parm sta_pparm; - sint keyid; - - if (!is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm)) - return; - - for (keyid = 0; keyid < 4; keyid++) { - if ((psecuritypriv->key_mask & BIT(keyid)) && (keyid == psecuritypriv->dot11PrivacyKeyIndex)) { - sta_pparm.algorithm = psecuritypriv->dot11PrivacyAlgrthm; - sta_pparm.keyid = keyid; - sta_pparm.gk = 0; - _rtw_memcpy(sta_pparm.key, &(psecuritypriv->dot11DefKey[keyid].skey[0]), 16); - _rtw_memcpy(sta_pparm.addr, psta->cmn.mac_addr, ETH_ALEN); - - RTW_PRINT(FUNC_ADPT_FMT"set WEP - PK with "MAC_FMT" keyid:%u\n" - , FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr), keyid); - - set_stakey_hdl(adapter, (u8 *)&sta_pparm); - } - } -} - -u8 set_stakey_hdl(_adapter *padapter, u8 *pbuf) -{ - u16 ctrl = 0; - s16 cam_id = 0; - bool used; - u8 ret = H2C_SUCCESS; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - - if (pparm->algorithm == _NO_PRIVACY_) - goto write_to_cam; - - psta = rtw_get_stainfo(pstapriv, pparm->addr); - if (!psta) { - RTW_PRINT("%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr)); - ret = H2C_REJECTED; - goto exit; - } - - pmlmeinfo->enc_algo = pparm->algorithm; - - cam_id = rtw_camid_alloc(padapter, psta, pparm->keyid, pparm->gk, &used); - if (cam_id < 0) - goto exit; - - /* cam entry searched is group key when setting pariwise key */ - if (!pparm->gk && used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _TRUE) { - s16 camid_clr; - - RTW_PRINT(FUNC_ADPT_FMT" pairwise key with "MAC_FMT" id:%u the same key id as group key\n" - , FUNC_ADPT_ARG(padapter), MAC_ARG(pparm->addr), pparm->keyid); - - /* HW has problem to distinguish this pairwise key with existing group key, stop HW enc and dec for BMC */ - rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH); - rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL); - - /* clear group key */ - while ((camid_clr = rtw_camid_search(padapter, pparm->addr, -1, 1)) >= 0) { - RTW_PRINT("clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), camid_clr); - clear_cam_entry(padapter, camid_clr); - rtw_camid_free(padapter, camid_clr); - } - } - -write_to_cam: - if (pparm->algorithm == _NO_PRIVACY_) { - while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1, -1)) >= 0) { - RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id); - clear_cam_entry(padapter, cam_id); - rtw_camid_free(padapter, cam_id); - } - } else { - RTW_PRINT("set %s key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n" - , pparm->gk ? "group" : "pairwise" - , cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm)); - ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid; - if (pparm->gk) - ctrl |= BIT(6); - write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); - } - ret = H2C_SUCCESS_RSP; - -exit: - return ret; -} - -u8 add_ba_hdl(_adapter *padapter, unsigned char *pbuf) -{ - struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - - struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr); - - if (!psta) - return H2C_SUCCESS; - -#ifdef CONFIG_80211N_HT - if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) || - ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) { - /* pmlmeinfo->ADDBA_retry_count = 0; */ - /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */ - /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */ - issue_addba_req(padapter, pparm->addr, (u8)pparm->tid); - _set_timer(&psta->addba_retry_timer, ADDBA_TO); - } -#ifdef CONFIG_TDLS - else if ((psta->tdls_sta_state & TDLS_LINKED_STATE) && - (psta->htpriv.ht_option == _TRUE) && - (psta->htpriv.ampdu_enable == _TRUE)) { - issue_addba_req(padapter, pparm->addr, (u8)pparm->tid); - _set_timer(&psta->addba_retry_timer, ADDBA_TO); - } -#endif /* CONFIG */ - else - psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); -#endif /* CONFIG_80211N_HT */ - return H2C_SUCCESS; -} - - -u8 add_ba_rsp_hdl(_adapter *padapter, unsigned char *pbuf) -{ - struct addBaRsp_parm *pparm = (struct addBaRsp_parm *)pbuf; - struct recv_reorder_ctrl *preorder_ctrl; - struct sta_priv *pstapriv = &padapter->stapriv; - struct sta_info *psta; - u8 ret = _TRUE; - - psta = rtw_get_stainfo(pstapriv, pparm->addr); - if (!psta) - goto exit; - - preorder_ctrl = &psta->recvreorder_ctrl[pparm->tid]; - ret = issue_addba_rsp_wait_ack(padapter, pparm->addr, pparm->tid, pparm->status, pparm->size, 3, 50); - -#ifdef CONFIG_UPDATE_INDICATE_SEQ_WHILE_PROCESS_ADDBA_REQ - /* status = 0 means accept this addba req, so update indicate seq = start_seq under this compile flag */ - if (pparm->status == 0) { - preorder_ctrl->indicate_seq = pparm->start_seq; - #ifdef DBG_RX_SEQ - RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_UPDATE indicate_seq:%d, start_seq:%d\n" - , FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, pparm->start_seq); - #endif - } -#else - preorder_ctrl->indicate_seq = 0xffff; - #ifdef DBG_RX_SEQ - RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_CLEAR indicate_seq:%d, start_seq:%d\n" - , FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, pparm->start_seq); - #endif -#endif - - /* - * status = 0 means accept this addba req - * status = 37 means reject this addba req - */ - if (pparm->status == 0) { - preorder_ctrl->enable = _TRUE; - preorder_ctrl->ampdu_size = pparm->size; - } else if (pparm->status == 37) - preorder_ctrl->enable = _FALSE; - -exit: - return H2C_SUCCESS; -} - -u8 chk_bmc_sleepq_cmd(_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); - u8 res = _SUCCESS; - - - ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (ph2c == NULL) { - res = _FAIL; - goto exit; - } - - init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - -exit: - - - return res; -} - -u8 set_tx_beacon_cmd(_adapter *padapter) -{ - struct cmd_obj *ph2c; - struct Tx_Beacon_param *ptxBeacon_parm; - struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); - u8 res = _SUCCESS; - int len_diff = 0; - - - ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj)); - if (ph2c == NULL) { - res = _FAIL; - goto exit; - } - - ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param)); - if (ptxBeacon_parm == NULL) { - rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj)); - res = _FAIL; - goto exit; - } - - _rtw_memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX)); - - len_diff = update_hidden_ssid( - ptxBeacon_parm->network.IEs + _BEACON_IE_OFFSET_ - , ptxBeacon_parm->network.IELength - _BEACON_IE_OFFSET_ - , pmlmeinfo->hidden_ssid_mode - ); - ptxBeacon_parm->network.IELength += len_diff; - - init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); - - res = rtw_enqueue_cmd(pcmdpriv, ph2c); - - -exit: - - - return res; -} - - -u8 mlme_evt_hdl(_adapter *padapter, unsigned char *pbuf) -{ - u8 evt_code, evt_seq; - u16 evt_sz; - uint *peventbuf; - void (*event_callback)(_adapter *dev, u8 *pbuf); - struct evt_priv *pevt_priv = &(padapter->evtpriv); - - if (pbuf == NULL) - goto _abort_event_; - - peventbuf = (uint *)pbuf; - evt_sz = (u16)(*peventbuf & 0xffff); - evt_seq = (u8)((*peventbuf >> 24) & 0x7f); - evt_code = (u8)((*peventbuf >> 16) & 0xff); - - -#ifdef CHECK_EVENT_SEQ - /* checking event sequence... */ - if (evt_seq != (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f)) { - - pevt_priv->event_seq = (evt_seq + 1) & 0x7f; - - goto _abort_event_; - } -#endif - - /* checking if event code is valid */ - if (evt_code >= MAX_C2HEVT) { - goto _abort_event_; - } - - /* checking if event size match the event parm size */ - if ((wlanevents[evt_code].parmsize != 0) && - (wlanevents[evt_code].parmsize != evt_sz)) { - - goto _abort_event_; - - } - - ATOMIC_INC(&pevt_priv->event_seq); - - peventbuf += 2; - - if (peventbuf) { - event_callback = wlanevents[evt_code].event_callback; - event_callback(padapter, (u8 *)peventbuf); - - pevt_priv->evt_done_cnt++; - } - - -_abort_event_: - - - return H2C_SUCCESS; - -} - -u8 h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf) -{ - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - return H2C_SUCCESS; -} - -u8 chk_bmc_sleepq_hdl(_adapter *padapter, unsigned char *pbuf) -{ -#ifdef CONFIG_AP_MODE - _irqL irqL; - struct sta_info *psta_bmc; - _list *xmitframe_plist, *xmitframe_phead; - struct xmit_frame *pxmitframe = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo(padapter); - if (!psta_bmc) - return H2C_SUCCESS; - - if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) { -#ifndef CONFIG_PCI_HCI - rtw_msleep_os(10);/* 10ms, ATIM(HIQ) Windows */ -#endif - /* _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); - - 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); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - - if (xmitframe_hiq_filter(pxmitframe) == _TRUE) - pxmitframe->attrib.qsel = QSLT_HIGH;/* HIQ */ - -#if 0 - _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL); - if (rtw_hal_xmit(padapter, pxmitframe) == _TRUE) - rtw_os_xmit_complete(padapter, pxmitframe); - _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL); -#endif - rtw_hal_xmitframe_enqueue(padapter, pxmitframe); - } - - /* _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL); */ - _exit_critical_bh(&pxmitpriv->lock, &irqL); - - if (rtw_get_intf_type(padapter) != RTW_PCIE) { - /* check hi queue and bmc_sleepq */ - rtw_chk_hi_queue_cmd(padapter); - } - } -#endif - - return H2C_SUCCESS; -} - -u8 tx_beacon_hdl(_adapter *padapter, unsigned char *pbuf) -{ - /*RTW_INFO(FUNC_ADPT_FMT, FUNC_ADPT_ARG(padapter));*/ -#ifdef CONFIG_SWTIMER_BASED_TXBCN - - tx_beacon_handlder(padapter->dvobj); - -#else - - if (send_beacon(padapter) == _FAIL) { - RTW_INFO("issue_beacon, fail!\n"); - return H2C_PARAMETERS_ERROR; - } - - /* tx bc/mc frames after update TIM */ - chk_bmc_sleepq_hdl(padapter, NULL); -#endif - - return H2C_SUCCESS; -} - -/* -* according to channel -* add/remove WLAN_BSSID_EX.IEs's ERP ie -* set WLAN_BSSID_EX.SupportedRates -* update WLAN_BSSID_EX.IEs's Supported Rate and Extended Supported Rate ie -*/ -void change_band_update_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 ch) -{ - u8 network_type, rate_len, total_rate_len, remainder_rate_len; - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - u8 erpinfo = 0x4; - - if (ch >= 36) { - network_type = WIRELESS_11A; - total_rate_len = IEEE80211_NUM_OFDM_RATESLEN; - rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_); - #ifdef CONFIG_80211AC_VHT - /* if channel in 5G band, then add vht ie . */ - if ((pmlmepriv->htpriv.ht_option == _TRUE) - && REGSTY_IS_11AC_ENABLE(&padapter->registrypriv) - && is_supported_vht(padapter->registrypriv.wireless_mode) - && (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent)) - ) { - if (REGSTY_IS_11AC_AUTO(&padapter->registrypriv) - || pmlmepriv->ori_vht_en) - rtw_vht_ies_attach(padapter, pnetwork); - } - #endif - } else { - network_type = WIRELESS_11BG; - total_rate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN; - rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1); - #ifdef CONFIG_80211AC_VHT - rtw_vht_ies_detach(padapter, pnetwork); - #endif - } - - rtw_set_supported_rate(pnetwork->SupportedRates, network_type); - - UpdateBrateTbl(padapter, pnetwork->SupportedRates); - - if (total_rate_len > 8) { - rate_len = 8; - remainder_rate_len = total_rate_len - 8; - } else { - rate_len = total_rate_len; - remainder_rate_len = 0; - } - - rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len); - - if (remainder_rate_len) - rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates + 8), remainder_rate_len); - else - rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_); - - pnetwork->Length = get_WLAN_BSSID_EX_sz(pnetwork); -} - -void rtw_join_done_chk_ch(_adapter *adapter, int join_res) -{ -#define DUMP_ADAPTERS_STATUS 0 - - struct dvobj_priv *dvobj; - _adapter *iface; - struct mlme_priv *mlme; - struct mlme_ext_priv *mlmeext; - u8 u_ch, u_offset, u_bw; - int i; - - dvobj = adapter_to_dvobj(adapter); - - if (DUMP_ADAPTERS_STATUS) { - RTW_INFO(FUNC_ADPT_FMT" enter\n", FUNC_ADPT_ARG(adapter)); - dump_adapters_status(RTW_DBGDUMP , dvobj); - } - - if (join_res >= 0) { - -#ifdef CONFIG_MCC_MODE - /* MCC setting success, don't go to ch union process */ - if (rtw_hal_set_mcc_setting_join_done_chk_ch(adapter)) - return; -#endif /* CONFIG_MCC_MODE */ - - if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset) <= 0) { - dump_adapters_status(RTW_DBGDUMP , dvobj); - rtw_warn_on(1); - } - - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - mlme = &iface->mlmepriv; - mlmeext = &iface->mlmeextpriv; - - if (!iface || iface == adapter) - continue; - - if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface)) - && check_fwstate(mlme, WIFI_ASOC_STATE) - ) { - u8 ori_ch, ori_bw, ori_offset; - bool is_grouped = rtw_is_chbw_grouped(u_ch, u_bw, u_offset - , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset); - - if (is_grouped == _FALSE) { - /* handle AP which need to switch ch setting */ - - ori_ch = mlmeext->cur_channel; - ori_bw = mlmeext->cur_bwmode; - ori_offset = mlmeext->cur_ch_offset; - - /* restore original bw, adjust bw by registry setting on target ch */ - mlmeext->cur_bwmode = mlme->ori_bw; - mlmeext->cur_channel = u_ch; - rtw_adjust_chbw(iface, mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset); - #ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(iface)) - rtw_mesh_adjust_chbw(mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset); - #endif - - rtw_chset_sync_chbw(adapter_to_chset(adapter) - , &mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset - , &u_ch, &u_bw, &u_offset); - - RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u\n", FUNC_ADPT_ARG(iface) - , ori_ch, ori_bw, ori_offset - , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset); - - rtw_ap_update_bss_chbw(iface, &(mlmeext->mlmext_info.network) - , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset); - - _rtw_memcpy(&(mlme->cur_network.network), &(mlmeext->mlmext_info.network), sizeof(WLAN_BSSID_EX)); - - rtw_start_bss_hdl_after_chbw_decided(iface); - - if (MLME_IS_GO(iface) || MLME_IS_MESH(iface)) { /* pure AP is not needed*/ - #if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) - u8 ht_option = 0; - - #ifdef CONFIG_80211N_HT - ht_option = mlme->htpriv.ht_option; - #endif - - rtw_cfg80211_ch_switch_notify(iface - , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset - , ht_option); - #endif - } - } - - clr_fwstate(mlme, WIFI_OP_CH_SWITCHING); - update_beacon(iface, 0xFF, NULL, _TRUE); - } - } - -#ifdef CONFIG_DFS_MASTER - rtw_dfs_rd_en_decision(adapter, MLME_STA_CONNECTED, 0); -#endif - } else { - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - mlme = &iface->mlmepriv; - mlmeext = &iface->mlmeextpriv; - - if (!iface || iface == adapter) - continue; - - if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface)) - && check_fwstate(mlme, WIFI_ASOC_STATE) - ) { - clr_fwstate(mlme, WIFI_OP_CH_SWITCHING); - update_beacon(iface, 0xFF, NULL, _TRUE); - } - } -#ifdef CONFIG_DFS_MASTER - rtw_dfs_rd_en_decision(adapter, MLME_STA_DISCONNECTED, 0); -#endif - } - - if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset)) { - RTW_INFO(FUNC_ADPT_FMT" union:%u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset); - set_channel_bwmode(adapter, u_ch, u_offset, u_bw); - rtw_mi_update_union_chan_inf(adapter, u_ch, u_offset, u_bw); - } - - if (DUMP_ADAPTERS_STATUS) { - RTW_INFO(FUNC_ADPT_FMT" exit\n", FUNC_ADPT_ARG(adapter)); - dump_adapters_status(RTW_DBGDUMP , dvobj); - } -} - -int rtw_chk_start_clnt_join(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset) -{ -#ifdef CONFIG_CONCURRENT_MODE - bool chbw_allow = _TRUE; -#endif - bool connect_allow = _TRUE; - struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; - u8 cur_ch, cur_bw, cur_ch_offset; - u8 u_ch, u_offset, u_bw; - - u_ch = cur_ch = pmlmeext->cur_channel; - u_bw = cur_bw = pmlmeext->cur_bwmode; - u_offset = cur_ch_offset = pmlmeext->cur_ch_offset; - - if (!ch || !bw || !offset) { - connect_allow = _FALSE; - rtw_warn_on(1); - goto exit; - } - - if (cur_ch == 0) { - connect_allow = _FALSE; - RTW_ERR(FUNC_ADPT_FMT" cur_ch:%u\n" - , FUNC_ADPT_ARG(adapter), cur_ch); - rtw_warn_on(1); - goto exit; - } - RTW_INFO(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset); - -#ifdef CONFIG_CONCURRENT_MODE - { - struct dvobj_priv *dvobj; - _adapter *iface; - struct mlme_priv *mlme; - struct mlme_ext_priv *mlmeext; - struct mi_state mstate; - int i; - - dvobj = adapter_to_dvobj(adapter); - - rtw_mi_status_no_self(adapter, &mstate); - RTW_INFO(FUNC_ADPT_FMT" others ld_sta_num:%u, ap_num:%u, mesh_num:%u\n" - , FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate) - , MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate)); - - if (!MSTATE_STA_LD_NUM(&mstate) && !MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) { - /* consider linking STA? */ - goto connect_allow_hdl; - } - - if (rtw_mi_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset) <= 0) { - dump_adapters_status(RTW_DBGDUMP , dvobj); - rtw_warn_on(1); - } - RTW_INFO(FUNC_ADPT_FMT" others union:%u,%u,%u\n" - , FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset); - - /* chbw_allow? */ - chbw_allow = rtw_is_chbw_grouped(pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset - , u_ch, u_bw, u_offset); - - RTW_INFO(FUNC_ADPT_FMT" chbw_allow:%d\n" - , FUNC_ADPT_ARG(adapter), chbw_allow); - -#ifdef CONFIG_MCC_MODE - /* check setting success, don't go to ch union process */ - if (rtw_hal_set_mcc_setting_chk_start_clnt_join(adapter, &u_ch, &u_bw, &u_offset, chbw_allow)) - goto exit; -#endif - - if (chbw_allow == _TRUE) { - rtw_sync_chbw(&cur_ch, &cur_bw, &cur_ch_offset, &u_ch, &u_bw, &u_offset); - rtw_warn_on(cur_ch != pmlmeext->cur_channel); - rtw_warn_on(cur_bw != pmlmeext->cur_bwmode); - rtw_warn_on(cur_ch_offset != pmlmeext->cur_ch_offset); - goto connect_allow_hdl; - } - -#ifdef CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT - /* chbw_allow is _FALSE, connect allow? */ - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - mlme = &iface->mlmepriv; - mlmeext = &iface->mlmeextpriv; - - if (check_fwstate(mlme, WIFI_STATION_STATE) - && check_fwstate(mlme, WIFI_ASOC_STATE) -#if defined(CONFIG_P2P) - && rtw_p2p_chk_state(&(iface->wdinfo), P2P_STATE_NONE) -#endif - ) { - connect_allow = _FALSE; - break; - } - } -#endif /* CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT */ - - if (MSTATE_STA_LD_NUM(&mstate) + MSTATE_AP_LD_NUM(&mstate) + MSTATE_MESH_LD_NUM(&mstate) >= 4) - connect_allow = _FALSE; - - RTW_INFO(FUNC_ADPT_FMT" connect_allow:%d\n" - , FUNC_ADPT_ARG(adapter), connect_allow); - - if (connect_allow == _FALSE) - goto exit; - -connect_allow_hdl: - /* connect_allow == _TRUE */ - - if (chbw_allow == _FALSE) { - u_ch = cur_ch; - u_bw = cur_bw; - u_offset = cur_ch_offset; - - for (i = 0; i < dvobj->iface_nums; i++) { - iface = dvobj->padapters[i]; - mlme = &iface->mlmepriv; - mlmeext = &iface->mlmeextpriv; - - if (!iface || iface == adapter) - continue; - - if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface)) - && check_fwstate(mlme, WIFI_ASOC_STATE) - ) { - #ifdef CONFIG_SPCT_CH_SWITCH - if (1) - rtw_ap_inform_ch_switch(iface, pmlmeext->cur_channel , pmlmeext->cur_ch_offset); - else - #endif - rtw_sta_flush(iface, _FALSE); - - rtw_hal_set_hwreg(iface, HW_VAR_CHECK_TXBUF, 0); - set_fwstate(mlme, WIFI_OP_CH_SWITCHING); - - } else if (check_fwstate(mlme, WIFI_STATION_STATE) - && check_fwstate(mlme, WIFI_ASOC_STATE) - ) { - rtw_disassoc_cmd(iface, 500, RTW_CMDF_DIRECTLY); - rtw_indicate_disconnect(iface, 0, _FALSE); - rtw_free_assoc_resources(iface, _TRUE); - } - } - } - - #ifdef CONFIG_DFS_MASTER - rtw_dfs_rd_en_decision(adapter, MLME_STA_CONNECTING, 0); - #endif - } -#endif /* CONFIG_CONCURRENT_MODE */ - -exit: - - if (connect_allow == _TRUE) { - RTW_INFO(FUNC_ADPT_FMT" union: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset); - *ch = u_ch; - *bw = u_bw; - *offset = u_offset; - -#if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) - { - u8 ht_option = 0; - -#ifdef CONFIG_80211N_HT - ht_option = adapter->mlmepriv.htpriv.ht_option; -#endif /* CONFIG_80211N_HT */ - - /* - when supplicant send the mlme frame, - the bss freq is updated by channel switch event. - */ - rtw_cfg80211_ch_switch_notify(adapter, - cur_ch, cur_bw, cur_ch_offset, ht_option); - } -#endif - } - - return connect_allow == _TRUE ? _SUCCESS : _FAIL; -} - -void rtw_set_external_auth_status(_adapter *padapter, - const void *data, int len) -{ -#ifdef CONFIG_IOCTL_CFG80211 - struct net_device *dev = padapter->pnetdev; - struct wiphy *wiphy = adapter_to_wiphy(padapter); - struct rtw_external_auth_params params; - - /* convert data to external_auth_params */ - params.action = RTW_GET_BE32((u8 *)data); - _rtw_memcpy(¶ms.bssid, (u8 *)data + 4, ETH_ALEN); - _rtw_memcpy(¶ms.ssid.ssid, (u8 *)data + 10, WLAN_SSID_MAXLEN); - params.ssid.ssid_len = RTW_GET_BE64((u8 *)data + 42); - params.key_mgmt_suite = RTW_GET_BE32((u8 *)data + 58); - params.status = RTW_GET_BE16((u8 *)data + 62); - _rtw_memcpy(¶ms.pmkid, (u8 *)data + 64, PMKID_LEN); - - rtw_cfg80211_external_auth_status(wiphy, dev, ¶ms); -#endif /* CONFIG_IOCTL_CFG80211 */ -} - -u8 rtw_set_chbw_hdl(_adapter *padapter, u8 *pbuf) -{ - struct set_ch_parm *set_ch_parm; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - set_ch_parm = (struct set_ch_parm *)pbuf; - - RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n", - FUNC_NDEV_ARG(padapter->pnetdev), - set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset); - - pmlmeext->cur_channel = set_ch_parm->ch; - pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; - pmlmeext->cur_bwmode = set_ch_parm->bw; - - set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw); - - return H2C_SUCCESS; -} - -u8 set_chplan_hdl(_adapter *padapter, unsigned char *pbuf) -{ - struct SetChannelPlan_param *setChannelPlan_param; - struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter); - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; - - if (!rtw_is_channel_plan_valid(setChannelPlan_param->channel_plan)) - return H2C_PARAMETERS_ERROR; - - rfctl->country_ent = setChannelPlan_param->country_ent; - rfctl->ChannelPlan = setChannelPlan_param->channel_plan; - - rfctl->max_chan_nums = init_channel_set(padapter, rfctl->ChannelPlan, rfctl->channel_set); - init_channel_list(padapter, rfctl->channel_set, &rfctl->channel_list); -#if CONFIG_TXPWR_LIMIT - rtw_txpwr_init_regd(rfctl); -#endif - - rtw_hal_set_odm_var(padapter, HAL_ODM_REGULATION, NULL, _TRUE); - -#ifdef CONFIG_IOCTL_CFG80211 - rtw_regd_apply_flags(adapter_to_wiphy(padapter)); -#endif - - return H2C_SUCCESS; -} - -u8 led_blink_hdl(_adapter *padapter, unsigned char *pbuf) -{ - struct LedBlink_param *ledBlink_param; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - ledBlink_param = (struct LedBlink_param *)pbuf; - -#ifdef CONFIG_RTW_LED_HANDLED_BY_CMD_THREAD - BlinkHandler((PLED_DATA)ledBlink_param->pLed); -#endif - - return H2C_SUCCESS; -} - -u8 set_csa_hdl(_adapter *adapter, unsigned char *pbuf) -{ -#ifdef CONFIG_DFS - struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter); - - if (rfctl->csa_ch) - rtw_dfs_ch_switch_hdl(adapter_to_dvobj(adapter)); -#endif - return H2C_SUCCESS; -} - -u8 tdls_hdl(_adapter *padapter, unsigned char *pbuf) -{ -#ifdef CONFIG_TDLS - _irqL irqL; - HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter); - struct tdls_info *ptdlsinfo = &padapter->tdlsinfo; -#ifdef CONFIG_TDLS_CH_SW - struct tdls_ch_switch *pchsw_info = &ptdlsinfo->chsw_info; -#endif - struct TDLSoption_param *TDLSoption; - struct sta_info *ptdls_sta = NULL; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - struct sta_info *ap_sta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(&(pmlmeinfo->network))); - u8 survey_channel, i, min, option; - struct tdls_txmgmt txmgmt; - u32 setchtime, resp_sleep = 0, wait_time; - u8 zaddr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - u8 ret; - u8 doiqk; - u64 tx_ra_bitmap = 0; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - TDLSoption = (struct TDLSoption_param *)pbuf; - option = TDLSoption->option; - - if (!_rtw_memcmp(TDLSoption->addr, zaddr, ETH_ALEN)) { - ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), TDLSoption->addr); - if (ptdls_sta == NULL) - return H2C_REJECTED; - } else { - if (!(option == TDLS_RS_RCR)) - return H2C_REJECTED; - } - - /* _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); */ - /* RTW_INFO("[%s] option:%d\n", __FUNCTION__, option); */ - - switch (option) { - case TDLS_ESTABLISHED: { - /* As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0 */ - /* So we can receive all kinds of data frames. */ - u8 sta_band = 0; - - /* leave ALL PS when TDLS is established */ - rtw_pwr_wakeup(padapter); - - rtw_hal_rcr_set_chk_bssid(padapter, MLME_TDLS_LINKED); - RTW_INFO("Created Direct Link with "MAC_FMT"\n", MAC_ARG(ptdls_sta->cmn.mac_addr)); - - /* Set TDLS sta rate. */ - /* Update station supportRate */ - rtw_hal_update_sta_ra_info(padapter, ptdls_sta); - tx_ra_bitmap = ptdls_sta->cmn.ra_info.ramask; - - if (pmlmeext->cur_channel > 14) { - if (tx_ra_bitmap & 0xffff000) - sta_band |= WIRELESS_11_5N ; - - if (tx_ra_bitmap & 0xff0) - sta_band |= WIRELESS_11A; - - /* 5G band */ -#ifdef CONFIG_80211AC_VHT - if (ptdls_sta->vhtpriv.vht_option) - sta_band = WIRELESS_11_5AC; -#endif - - } 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; - } - ptdls_sta->wireless_mode = sta_band; - rtw_hal_update_sta_wset(padapter, ptdls_sta); - /* Sta mode */ - rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, ptdls_sta, _TRUE); - - set_sta_rate(padapter, ptdls_sta); - rtw_sta_media_status_rpt(padapter, ptdls_sta, 1); - break; - } - case TDLS_ISSUE_PTI: - ptdls_sta->tdls_sta_state |= TDLS_WAIT_PTR_STATE; - issue_tdls_peer_traffic_indication(padapter, ptdls_sta); - _set_timer(&ptdls_sta->pti_timer, TDLS_PTI_TIME); - break; -#ifdef CONFIG_TDLS_CH_SW - case TDLS_CH_SW_RESP: - _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt)); - txmgmt.status_code = 0; - _rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN); - - if (ap_sta) - rtw_hal_macid_sleep(padapter, ap_sta->cmn.mac_id); - issue_nulldata(padapter, NULL, 1, 3, 3); - - RTW_INFO("[TDLS ] issue tdls channel switch response\n"); - ret = issue_tdls_ch_switch_rsp(padapter, &txmgmt, _TRUE); - - /* If we receive TDLS_CH_SW_REQ at off channel which it's target is AP's channel */ - /* then we just switch to AP's channel*/ - if (padapter->mlmeextpriv.cur_channel == pchsw_info->off_ch_num) { - rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_END_TO_BASE_CHNL); - break; - } - - if (ret == _SUCCESS) - rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_OFF_CHNL); - else - RTW_INFO("[TDLS] issue_tdls_ch_switch_rsp wait ack fail !!!!!!!!!!\n"); - - break; - case TDLS_CH_SW_PREPARE: - pchsw_info->ch_sw_state |= TDLS_CH_SWITCH_PREPARE_STATE; - - /* to collect IQK info of off-chnl */ - doiqk = _TRUE; - rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk); - set_channel_bwmode(padapter, pchsw_info->off_ch_num, pchsw_info->ch_offset, (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20); - doiqk = _FALSE; - rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk); - - /* switch back to base-chnl */ - set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); - - rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_START); - - pchsw_info->ch_sw_state &= ~(TDLS_CH_SWITCH_PREPARE_STATE); - - break; - case TDLS_CH_SW_START: - rtw_tdls_set_ch_sw_oper_control(padapter, _TRUE); - break; - case TDLS_CH_SW_TO_OFF_CHNL: - if (ap_sta) - rtw_hal_macid_sleep(padapter, ap_sta->cmn.mac_id); - issue_nulldata(padapter, NULL, 1, 3, 3); - - if (padapter->registrypriv.wifi_spec == 0) { - if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE)) - _set_timer(&ptdls_sta->ch_sw_timer, (u32)(ptdls_sta->ch_switch_timeout) / 1000); - } - - if (rtw_tdls_do_ch_sw(padapter, ptdls_sta, TDLS_CH_SW_OFF_CHNL, pchsw_info->off_ch_num, - pchsw_info->ch_offset, (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20, ptdls_sta->ch_switch_time) == _SUCCESS) { - pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE); - if (pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) { - if (issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta->cmn.mac_addr, 0, 1, - (padapter->registrypriv.wifi_spec == 0) ? 3 : 0) == _FAIL) - rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_BASE_CHNL); - } - } else { - if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE)) - _cancel_timer_ex(&ptdls_sta->ch_sw_timer); - } - - - break; - case TDLS_CH_SW_END: - case TDLS_CH_SW_END_TO_BASE_CHNL: - rtw_tdls_set_ch_sw_oper_control(padapter, _FALSE); - _cancel_timer_ex(&ptdls_sta->ch_sw_timer); - _cancel_timer_ex(&ptdls_sta->stay_on_base_chnl_timer); - _cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer); -#if 0 - _rtw_memset(pHalData->tdls_ch_sw_iqk_info_base_chnl, 0x00, sizeof(pHalData->tdls_ch_sw_iqk_info_base_chnl)); - _rtw_memset(pHalData->tdls_ch_sw_iqk_info_off_chnl, 0x00, sizeof(pHalData->tdls_ch_sw_iqk_info_off_chnl)); -#endif - - if (option == TDLS_CH_SW_END_TO_BASE_CHNL) - rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_BASE_CHNL); - - break; - case TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED: - case TDLS_CH_SW_TO_BASE_CHNL: - pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE | TDLS_WAIT_CH_RSP_STATE); - - if (option == TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED) { - if (ptdls_sta != NULL) { - /* Send unsolicited channel switch rsp. to peer */ - _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt)); - txmgmt.status_code = 0; - _rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN); - issue_tdls_ch_switch_rsp(padapter, &txmgmt, _FALSE); - } - } - - if (rtw_tdls_do_ch_sw(padapter, ptdls_sta, TDLS_CH_SW_BASE_CHNL, pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode, ptdls_sta->ch_switch_time) == _SUCCESS) { - if (ap_sta) - rtw_hal_macid_wakeup(padapter, ap_sta->cmn.mac_id); - issue_nulldata(padapter, NULL, 0, 3, 3); - /* set ch sw monitor timer for responder */ - if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE)) - _set_timer(&ptdls_sta->ch_sw_monitor_timer, TDLS_CH_SW_MONITOR_TIMEOUT); - } - - break; -#endif - case TDLS_RS_RCR: - rtw_hal_rcr_set_chk_bssid(padapter, MLME_TDLS_NOLINK); - break; - case TDLS_TEARDOWN_STA: - case TDLS_TEARDOWN_STA_NO_WAIT: - _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt)); - txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_; - _rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN); - - issue_tdls_teardown(padapter, &txmgmt, (option == TDLS_TEARDOWN_STA) ? _TRUE : _FALSE); - - break; - case TDLS_TEARDOWN_STA_LOCALLY: - case TDLS_TEARDOWN_STA_LOCALLY_POST: -#ifdef CONFIG_TDLS_CH_SW - if (_rtw_memcmp(TDLSoption->addr, pchsw_info->addr, ETH_ALEN) == _TRUE) { - pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE | - TDLS_CH_SWITCH_ON_STATE | - TDLS_PEER_AT_OFF_STATE); - rtw_tdls_set_ch_sw_oper_control(padapter, _FALSE); - _rtw_memset(pchsw_info->addr, 0x00, ETH_ALEN); - } -#endif - - if (option == TDLS_TEARDOWN_STA_LOCALLY) - rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta); - - rtw_tdls_teardown_post_hdl(padapter, ptdls_sta, _FALSE); - - if (ptdlsinfo->tdls_sctx != NULL) - rtw_sctx_done(&(ptdlsinfo->tdls_sctx)); - - break; - } - - /* _exit_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); */ - - return H2C_SUCCESS; -#else - return H2C_REJECTED; -#endif /* CONFIG_TDLS */ - -} - -u8 run_in_thread_hdl(_adapter *padapter, u8 *pbuf) -{ - struct RunInThread_param *p; - - - if (NULL == pbuf) - return H2C_PARAMETERS_ERROR; - p = (struct RunInThread_param *)pbuf; - - if (p->func) - p->func(p->context); - - return H2C_SUCCESS; -} - -u8 rtw_getmacreg_hdl(_adapter *padapter, u8 *pbuf) -{ - - struct readMAC_parm *preadmacparm = NULL; - u8 sz = 0; - u32 addr = 0; - u32 value = 0; - - if (!pbuf) - return H2C_PARAMETERS_ERROR; - - preadmacparm = (struct readMAC_parm *) pbuf; - sz = preadmacparm->len; - addr = preadmacparm->addr; - value = 0; - - switch (sz) { - case 1: - value = rtw_read8(padapter, addr); - break; - case 2: - value = rtw_read16(padapter, addr); - break; - case 4: - value = rtw_read32(padapter, addr); - break; - default: - RTW_INFO("%s: Unknown size\n", __func__); - break; - } - RTW_INFO("%s: addr:0x%02x valeu:0x%02x\n", __func__, addr, value); - - return H2C_SUCCESS; -} - -int rtw_sae_preprocess(_adapter *adapter, const u8 *buf, u32 len, u8 tx) -{ -#ifdef CONFIG_IOCTL_CFG80211 - const u8 *frame_body = buf + sizeof(struct rtw_ieee80211_hdr_3addr); - u16 alg; - u16 seq; - u16 status; - int ret = _FAIL; - - alg = RTW_GET_LE16(frame_body); - if (alg != WLAN_AUTH_SAE) - goto exit; - - seq = RTW_GET_LE16(frame_body + 2); - status = RTW_GET_LE16(frame_body + 4); - - RTW_INFO("RTW_%s:AUTH alg:0x%04x, seq:0x%04x, status:0x%04x, mesg:%s\n", - (tx == _TRUE) ? "Tx" : "Rx", alg, seq, status, - (seq == 1) ? "Commit" : "Confirm"); - - ret = _SUCCESS; - -#ifdef CONFIG_RTW_MESH - if (MLME_IS_MESH(adapter)) { - rtw_mesh_sae_check_frames(adapter, buf, len, tx, alg, seq, status); - goto exit; - } -#endif - - if (tx && (seq == 2) && (status == 0)) { - /* quere commit frame until external auth statue update */ - struct sta_priv *pstapriv = &adapter->stapriv; - struct sta_info *psta = NULL; - _irqL irqL; - - psta = rtw_get_stainfo(pstapriv, GetAddr1Ptr(buf)); - if (psta) { - _enter_critical_bh(&psta->lock, &irqL); - if (psta->pauth_frame) { - rtw_mfree(psta->pauth_frame, psta->auth_len); - psta->pauth_frame = NULL; - psta->auth_len = 0; - } - - psta->pauth_frame = rtw_zmalloc(len); - if (psta->pauth_frame) { - _rtw_memcpy(psta->pauth_frame, buf, len); - psta->auth_len = len; - } - _exit_critical_bh(&psta->lock, &irqL); - - ret = 2; - } - } -exit: - return ret; -#else - return _SUCCESS; -#endif /* CONFIG_IOCTL_CFG80211 */ -} - diff --git a/core/rtw_recv.c b/core/rtw_recv.c old mode 100755 new mode 100644