blob: 8068cb7fff0258126f7e923e0ac6dc1b2e755c4a [file] [log] [blame]
/******************************************************************************
*
* This file is provided under a dual license. When you use or
* distribute this software, you may choose to be licensed under
* version 2 of the GNU General Public License ("GPLv2 License")
* or BSD License.
*
* GPLv2 License
*
* Copyright(C) 2016 MediaTek Inc.
*
* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details.
*
* BSD LICENSE
*
* Copyright(C) 2016 MediaTek Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/*
** Id: @(#) gl_p2p_cfg80211.c@@
*/
/*! \file gl_p2p_cfg80211.c
* \brief Main routines of Linux driver interface for Wi-Fi Direct
* using cfg80211 interface
*
* This file contains the main routines of Linux driver for MediaTek Inc. 802.11
* Wireless LAN Adapters.
*/
/*******************************************************************************
* C O M P I L E R F L A G S
********************************************************************************
*/
/*******************************************************************************
* E X T E R N A L R E F E R E N C E S
********************************************************************************
*/
/*******************************************************************************
* C O N S T A N T S
********************************************************************************
*/
/*******************************************************************************
* D A T A T Y P E S
********************************************************************************
*/
/*******************************************************************************
* P U B L I C D A T A
********************************************************************************
*/
/*******************************************************************************
* P R I V A T E D A T A
********************************************************************************
*/
/*******************************************************************************
* M A C R O S
********************************************************************************
*/
/*******************************************************************************
* F U N C T I O N D E C L A R A T I O N S
********************************************************************************
*/
/*******************************************************************************
* F U N C T I O N S
********************************************************************************
*/
#include "precomp.h"
static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend);
static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend);
/*----------------------------------------------------------------------------*/
/*!
* \brief Different concurrent network has itself channel lists, and
* concurrent networks should have been recorded in channel lists.
* If role of active P2P is GO, assume associated AP of AIS will
* record our Beacon for P2P GO because of same channel.
*
* Note: If we have scenario of different channel in the future,
* the internal FW communication channel shall be established.
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend)
{
UINT_8 ucChannelLevel;
ASSERT(prBssInfo);
if (eBand == BAND_2G4) {
ucChannelLevel = rlmObssChnlLevelIn2G4(prBssInfo, ucPriChannel, eExtend);
/* (TBD) If concurrent networks permit different channel, extra
* channel judgement should be added. Please refer to
* previous version of this file.
*/
} else if (eBand == BAND_5G) {
ucChannelLevel = rlmObssChnlLevelIn5G(prBssInfo, ucPriChannel, eExtend);
/* (TBD) If concurrent networks permit different channel, extra
* channel judgement should be added. Please refer to
* previous version of this file.
*/
} else {
ucChannelLevel = CHNL_LEVEL0;
}
return ucChannelLevel;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend)
{
UINT_8 i, ucChannelLevel;
UINT_8 ucSecChannel, ucCenterChannel;
UINT_8 ucAffectedChnl_L, ucAffectedChnl_H;
ASSERT(prBssInfo);
ucChannelLevel = CHNL_LEVEL2;
/* Calculate center channel for 2.4G band */
if (eExtend == CHNL_EXT_SCA) {
ucCenterChannel = ucPriChannel + 2;
ucSecChannel = ucPriChannel + 4;
} else if (eExtend == CHNL_EXT_SCB) {
ucCenterChannel = ucPriChannel - 2;
ucSecChannel = ucPriChannel - 4;
} else {
return CHNL_LEVEL0;
}
ASSERT(ucCenterChannel >= 1 && ucCenterChannel <= 14);
/* Calculated low/upper channels in affected freq range */
ucAffectedChnl_L = (ucCenterChannel <= AFFECTED_CHNL_OFFSET) ? 1 : (ucCenterChannel - AFFECTED_CHNL_OFFSET);
ucAffectedChnl_H = (ucCenterChannel >= (14 - AFFECTED_CHNL_OFFSET)) ?
14 : (ucCenterChannel + AFFECTED_CHNL_OFFSET);
/* Check intolerant (Non-HT) channel list */
ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G);
for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) {
if ((prBssInfo->auc2G_NonHtChnlList[i] >= ucAffectedChnl_L &&
prBssInfo->auc2G_NonHtChnlList[i] <= ucAffectedChnl_H) &&
prBssInfo->auc2G_NonHtChnlList[i] != ucPriChannel) {
ucChannelLevel = CHNL_LEVEL0;
goto L_2G4_level_end;
}
}
/* Check 20M BW request channel list */
ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G);
for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) {
if ((prBssInfo->auc2G_20mReqChnlList[i] >= ucAffectedChnl_L &&
prBssInfo->auc2G_20mReqChnlList[i] <= ucAffectedChnl_H)) {
ucChannelLevel = CHNL_LEVEL0;
goto L_2G4_level_end;
}
}
/* Check 2.4G primary channel list */
ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G);
for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) {
if ((prBssInfo->auc2G_PriChnlList[i] >= ucAffectedChnl_L &&
prBssInfo->auc2G_PriChnlList[i] <= ucAffectedChnl_H) &&
prBssInfo->auc2G_PriChnlList[i] != ucPriChannel) {
ucChannelLevel = CHNL_LEVEL0;
goto L_2G4_level_end;
}
}
/* Check 2.4G secondary channel list */
ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G);
for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) {
if ((prBssInfo->auc2G_SecChnlList[i] >= ucAffectedChnl_L &&
prBssInfo->auc2G_SecChnlList[i] <= ucAffectedChnl_H) &&
prBssInfo->auc2G_SecChnlList[i] != ucSecChannel) {
ucChannelLevel = CHNL_LEVEL0;
goto L_2G4_level_end;
}
}
L_2G4_level_end:
return ucChannelLevel;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend)
{
UINT_8 i, ucChannelLevel;
UINT_8 ucSecChannel;
ASSERT(prBssInfo);
ucChannelLevel = CHNL_LEVEL2;
/* Calculate center channel for 2.4G band */
if (eExtend == CHNL_EXT_SCA)
ucSecChannel = ucPriChannel + 4;
else if (eExtend == CHNL_EXT_SCB)
ucSecChannel = ucPriChannel - 4;
else
return CHNL_LEVEL0;
ASSERT(ucSecChannel >= 36);
/* Check 5G primary channel list */
ASSERT(prBssInfo->auc5G_PriChnlList[0] <= CHNL_LIST_SZ_5G);
for (i = 1; i <= prBssInfo->auc5G_PriChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) {
if (prBssInfo->auc5G_PriChnlList[i] == ucSecChannel) {
ucChannelLevel = CHNL_LEVEL0;
goto L_5G_level_end;
} else if (prBssInfo->auc5G_PriChnlList[i] == ucPriChannel) {
ucChannelLevel = CHNL_LEVEL1;
}
}
/* Check non-HT channel list */
ASSERT(prBssInfo->auc5G_NonHtChnlList[0] <= CHNL_LIST_SZ_5G);
for (i = 1; i <= prBssInfo->auc5G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) {
if (prBssInfo->auc5G_NonHtChnlList[i] == ucSecChannel) {
ucChannelLevel = CHNL_LEVEL0;
goto L_5G_level_end;
} else if (prBssInfo->auc5G_NonHtChnlList[i] == ucPriChannel) {
ucChannelLevel = CHNL_LEVEL1;
}
}
/* Check secondary channel list */
ASSERT(prBssInfo->auc5G_SecChnlList[0] <= CHNL_LIST_SZ_5G);
for (i = 1; i <= prBssInfo->auc5G_SecChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) {
if (prBssInfo->auc5G_SecChnlList[i] == ucPriChannel) {
ucChannelLevel = CHNL_LEVEL0;
goto L_5G_level_end;
}
}
L_5G_level_end:
return ucChannelLevel;
}
/*----------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in]
*
* \return none
*/
/*----------------------------------------------------------------------------*/
VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb)
{
P_MSDU_INFO_T prMsduInfo;
P_ACTION_20_40_COEXIST_FRAME prTxFrame;
/* To do: need an algorithm to do judgement. Now always reject request */
prMsduInfo = (P_MSDU_INFO_T)
cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN);
if (prMsduInfo == NULL)
return;
DBGLOG(RLM, INFO, "Send 20/40 coexistence rsp frame!\n");
prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) prMsduInfo->prPacket;
prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION;
COPY_MAC_ADDR(prTxFrame->aucDestAddr, ((P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader)->aucSrcAddr);
COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr);
COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID);
prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION;
prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST;
/* To do: find correct algorithm */
prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE;
prTxFrame->rBssCoexist.ucLength = 1;
prTxFrame->rBssCoexist.ucData = 0;
ASSERT((WLAN_MAC_HEADER_LEN + 5) <= PUBLIC_ACTION_MAX_LEN);
TX_SET_MMPDU(prAdapter,
prMsduInfo,
prBssInfo->ucBssIndex,
prSwRfb->ucStaRecIdx,
WLAN_MAC_MGMT_HEADER_LEN, WLAN_MAC_MGMT_HEADER_HTC_LEN + 5, NULL, MSDU_RATE_MODE_AUTO);
/* Send them to HW queue */
nicTxEnqueueMsdu(prAdapter, prMsduInfo);
}