blob: 3466b7d564b984cf1d0da263c1dbec7a05169b0a [file] [edit]
/******************************************************************************
*
* 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_kal.c
* \brief
*
*/
/******************************************************************************
* 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
******************************************************************************
*/
#include "net/cfg80211.h"
#include "precomp.h"
#include "gl_wext.h"
/******************************************************************************
* 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
******************************************************************************
*/
struct ieee80211_channel *kalP2pFuncGetChannelEntry(
IN struct GL_P2P_INFO *prP2pInfo,
IN struct RF_CHANNEL_INFO *prChannelInfo);
/******************************************************************************
* F U N C T I O N S
******************************************************************************
*/
/*---------------------------------------------------------------------------*/
/*!
* \brief to retrieve Wi-Fi Direct state from glue layer
*
* \param[in]
* prGlueInfo
* rPeerAddr
* \return
* ENUM_BOW_DEVICE_STATE
*/
/*---------------------------------------------------------------------------*/
#if 0
enum ENUM_PARAM_MEDIA_STATE kalP2PGetState(IN struct GLUE_INFO *prGlueInfo)
{
ASSERT(prGlueInfo);
return prGlueInfo->prP2PInfo[0]->eState;
} /* end of kalP2PGetState() */
#endif
/*---------------------------------------------------------------------------*/
/*!
* \brief to update the assoc req to p2p
*
* \param[in]
* prGlueInfo
* pucFrameBody
* u4FrameBodyLen
* fgReassocRequest
* \return
* none
*/
/*---------------------------------------------------------------------------*/
void
kalP2PUpdateAssocInfo(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t *pucFrameBody,
IN uint32_t u4FrameBodyLen,
IN u_int8_t fgReassocRequest,
IN uint8_t ucBssIndex)
{
struct BSS_INFO *prBssInfo;
union iwreq_data wrqu;
unsigned char *pucExtraInfo = NULL;
unsigned char *pucDesiredIE = NULL;
/* unsigned char aucExtraInfoBuf[200]; */
uint8_t *cp;
struct net_device *prNetdevice = (struct net_device *)NULL;
memset(&wrqu, 0, sizeof(wrqu));
if (fgReassocRequest) {
if (u4FrameBodyLen < 15) {
return;
}
} else {
if (u4FrameBodyLen < 9) {
return;
}
}
cp = pucFrameBody;
if (fgReassocRequest) {
/* Capability information field 2 */
/* Listen interval field 2 */
/* Current AP address 6 */
cp += 10;
u4FrameBodyLen -= 10;
} else {
/* Capability information field 2 */
/* Listen interval field 2 */
cp += 4;
u4FrameBodyLen -= 4;
}
/* do supplicant a favor, parse to the start of WPA/RSN IE */
if (wextSrchDesiredWPSIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) {
/* WPS IE found */
} else if (wextSrchDesiredWPAIE(cp,
u4FrameBodyLen, 0x30, &pucDesiredIE)) {
/* RSN IE found */
} else if (wextSrchDesiredWPAIE(cp,
u4FrameBodyLen, 0xDD, &pucDesiredIE)) {
/* WPA IE found */
} else {
/* no WPA/RSN IE found, skip this event */
return;
}
/* IWEVASSOCREQIE, indicate binary string */
pucExtraInfo = pucDesiredIE;
wrqu.data.length = pucDesiredIE[1] + 2;
prBssInfo = GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter, ucBssIndex);
if (ucBssIndex == prGlueInfo->prAdapter->ucP2PDevBssIdx)
prNetdevice = prGlueInfo->prP2PInfo
[prBssInfo->u4PrivateData]->prDevHandler;
else
prNetdevice = prGlueInfo->prP2PInfo
[prBssInfo->u4PrivateData]->aprRoleHandler;
/* Send event to user space */
wireless_send_event(prNetdevice, IWEVASSOCREQIE, &wrqu, pucExtraInfo);
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to set Wi-Fi Direct state in glue layer
*
* \param[in]
* prGlueInfo
* eBowState
* rPeerAddr
* \return
* none
*/
/*---------------------------------------------------------------------------*/
#if 0
void
kalP2PSetState(IN struct GLUE_INFO *prGlueInfo,
IN enum ENUM_PARAM_MEDIA_STATE eState,
IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN],
IN uint8_t ucRole)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
memset(&evt, 0, sizeof(evt));
if (eState == PARAM_MEDIA_STATE_CONNECTED) {
prGlueInfo->prP2PInfo[0]->eState = PARAM_MEDIA_STATE_CONNECTED;
snprintf(aucBuffer, IW_CUSTOM_MAX - 1,
"P2P_STA_CONNECT=" MACSTR, MAC2STR(rPeerAddr));
evt.data.length = strlen(aucBuffer);
/* indicate in IWECUSTOM event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} else if (eState == PARAM_MEDIA_STATE_DISCONNECTED) {
snprintf(aucBuffer, IW_CUSTOM_MAX - 1,
"P2P_STA_DISCONNECT=" MACSTR, MAC2STR(rPeerAddr));
evt.data.length = strlen(aucBuffer);
/* indicate in IWECUSTOM event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} else {
ASSERT(0);
}
} /* end of kalP2PSetState() */
#endif
/*---------------------------------------------------------------------------*/
/*!
* \brief to retrieve Wi-Fi Direct operating frequency
*
* \param[in]
* prGlueInfo
*
* \return
* in unit of KHz
*/
/*---------------------------------------------------------------------------*/
#if 0
uint32_t kalP2PGetFreqInKHz(IN struct GLUE_INFO *prGlueInfo)
{
ASSERT(prGlueInfo);
return prGlueInfo->prP2PInfo[0]->u4FreqInKHz;
} /* end of kalP2PGetFreqInKHz() */
#endif
/*---------------------------------------------------------------------------*/
/*!
* \brief to retrieve Bluetooth-over-Wi-Fi role
*
* \param[in]
* prGlueInfo
*
* \return
* 0: P2P Device
* 1: Group Client
* 2: Group Owner
*/
/*----------------------------------------------------------------------------*/
uint8_t kalP2PGetRole(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
return prGlueInfo->prP2PInfo[ucRoleIdx]->ucRole;
} /* end of kalP2PGetRole() */
/*---------------------------------------------------------------------------*/
/*!
* \brief to set Wi-Fi Direct role
*
* \param[in]
* prGlueInfo
* ucResult
* 0: successful
* 1: error
* ucRole
* 0: P2P Device
* 1: Group Client
* 2: Group Owner
*
* \return
* none
*/
/*---------------------------------------------------------------------------*/
#if 1
void kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRole, IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(ucRole <= 2);
prGlueInfo->prP2PInfo[ucRoleIdx]->ucRole = ucRole;
/* Remove non-used code */
} /* end of kalP2PSetRole() */
#else
void
kalP2PSetRole(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucResult, IN uint8_t *pucSSID,
IN uint8_t ucSSIDLen, IN uint8_t ucRole)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
ASSERT(ucRole <= 2);
memset(&evt, 0, sizeof(evt));
if (ucResult == 0)
prGlueInfo->prP2PInfo[0]->ucRole = ucRole;
if (pucSSID)
snprintf(aucBuffer, IW_CUSTOM_MAX - 1,
"P2P_FORMATION_RST=%d%d%d%c%c", ucResult,
ucRole, 1 /* persistence or not */,
pucSSID[7], pucSSID[8]);
else
snprintf(aucBuffer, IW_CUSTOM_MAX - 1,
"P2P_FORMATION_RST=%d%d%d%c%c", ucResult,
ucRole, 1 /* persistence or not */, '0', '0');
evt.data.length = strlen(aucBuffer);
/* indicate in IWECUSTOM event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} /* end of kalP2PSetRole() */
#endif
/*---------------------------------------------------------------------------*/
/*!
* \brief to set the cipher for p2p
*
* \param[in]
* prGlueInfo
* u4Cipher
*
* \return
* none
*/
/*---------------------------------------------------------------------------*/
void kalP2PSetCipher(IN struct GLUE_INFO *prGlueInfo,
IN uint32_t u4Cipher, IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]);
/* It can be WEP40 (used to identify cipher is WEP), TKIP and CCMP */
prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise = u4Cipher;
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to get the cipher, return false for security is none
*
* \param[in]
* prGlueInfo
*
* \return
* TRUE: cipher is ccmp
* FALSE: cipher is none
*/
/*---------------------------------------------------------------------------*/
u_int8_t kalP2PGetCipher(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]);
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_CCMP)
return TRUE;
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_TKIP)
return TRUE;
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_WEP40)
return TRUE;
return FALSE;
}
u_int8_t kalP2PGetWepCipher(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]);
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_WEP40)
return TRUE;
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_WEP104)
return TRUE;
return FALSE;
}
#if CFG_SUPPORT_SUITB
u_int8_t kalP2PGetGcmp256Cipher(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]);
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_GCMP256)
return TRUE;
return FALSE;
}
#endif
u_int8_t kalP2PGetCcmpCipher(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]);
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_CCMP)
return TRUE;
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_TKIP)
return FALSE;
return FALSE;
}
u_int8_t kalP2PGetTkipCipher(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[ucRoleIdx]);
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_CCMP)
return FALSE;
if (prGlueInfo->prP2PInfo[ucRoleIdx]->u4CipherPairwise
== IW_AUTH_CIPHER_TKIP)
return TRUE;
return FALSE;
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to set the status of WSC
*
* \param[in]
* prGlueInfo
*
* \return
*/
/*---------------------------------------------------------------------------*/
void kalP2PSetWscMode(IN struct GLUE_INFO *prGlueInfo, IN uint8_t ucWscMode)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PDevInfo);
prGlueInfo->prP2PDevInfo->ucWSCRunning = ucWscMode;
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to get the status of WSC
*
* \param[in]
* prGlueInfo
*
* \return
*/
/*---------------------------------------------------------------------------*/
uint8_t kalP2PGetWscMode(IN struct GLUE_INFO *prGlueInfo)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PDevInfo);
return prGlueInfo->prP2PDevInfo->ucWSCRunning;
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to get the wsc ie length
*
* \param[in]
* prGlueInfo
* ucType : 0 for beacon, 1 for probe req, 2 for probe resp
*
* \return
* The WSC IE length
*/
/*---------------------------------------------------------------------------*/
uint16_t kalP2PCalWSC_IELen(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucType, IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(ucType < 4);
return prGlueInfo->prP2PInfo[ucRoleIdx]->u2WSCIELen[ucType];
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to copy the wsc ie setting from p2p supplicant
*
* \param[in]
* prGlueInfo
*
* \return
* The WPS IE length
*/
/*---------------------------------------------------------------------------*/
void kalP2PGenWSC_IE(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucType, IN uint8_t *pucBuffer, IN uint8_t ucRoleIdx)
{
struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL;
do {
if ((prGlueInfo == NULL)
|| (ucType >= 4) || (pucBuffer == NULL))
break;
prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
kalMemCopy(pucBuffer,
prGlP2pInfo->aucWSCIE[ucType],
prGlP2pInfo->u2WSCIELen[ucType]);
} while (FALSE);
}
void kalP2PUpdateWSC_IE(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucType, IN uint8_t *pucBuffer,
IN uint16_t u2BufferLength, IN uint8_t ucRoleIdx)
{
struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL;
do {
if ((prGlueInfo == NULL) || (ucType >= 4)
|| ((u2BufferLength > 0) && (pucBuffer == NULL)))
break;
if (u2BufferLength > 400) {
log_dbg(P2P, ERROR,
"Buffer length is not enough, GLUE only 400 bytes but %d received\n",
u2BufferLength);
ASSERT(FALSE);
break;
}
prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
kalMemCopy(prGlP2pInfo->aucWSCIE[ucType],
pucBuffer, u2BufferLength);
prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength;
} while (FALSE);
} /* kalP2PUpdateWSC_IE */
uint16_t kalP2PCalP2P_IELen(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucIndex, IN uint8_t ucRoleIdx)
{
ASSERT(prGlueInfo);
ASSERT(ucIndex < MAX_P2P_IE_SIZE);
return prGlueInfo->prP2PInfo[ucRoleIdx]->u2P2PIELen[ucIndex];
}
void kalP2PGenP2P_IE(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucIndex, IN uint8_t *pucBuffer, IN uint8_t ucRoleIdx)
{
struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL;
do {
if ((prGlueInfo == NULL) || (ucIndex >= MAX_P2P_IE_SIZE)
|| (pucBuffer == NULL))
break;
prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
kalMemCopy(pucBuffer,
prGlP2pInfo->aucP2PIE[ucIndex],
prGlP2pInfo->u2P2PIELen[ucIndex]);
} while (FALSE);
}
void kalP2PUpdateP2P_IE(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucIndex, IN uint8_t *pucBuffer,
IN uint16_t u2BufferLength, IN uint8_t ucRoleIdx)
{
struct GL_P2P_INFO *prGlP2pInfo = (struct GL_P2P_INFO *) NULL;
do {
if ((prGlueInfo == NULL) ||
(ucIndex >= MAX_P2P_IE_SIZE) ||
((u2BufferLength > 0) && (pucBuffer == NULL)))
break;
if (u2BufferLength > 400) {
log_dbg(P2P, ERROR,
"kalP2PUpdateP2P_IE > Buffer length is not enough, GLUE only 400 bytes but %d received\n",
u2BufferLength);
ASSERT(FALSE);
break;
}
prGlP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
kalMemCopy(prGlP2pInfo->aucP2PIE[ucIndex],
pucBuffer, u2BufferLength);
prGlP2pInfo->u2P2PIELen[ucIndex] = u2BufferLength;
} while (FALSE);
}
#if 0
/*---------------------------------------------------------------------------*/
/*!
* \brief indicate an event to supplicant for device connection request
*
* \param[in] prGlueInfo Pointer of GLUE_INFO_T
*
* \retval none
*/
/*---------------------------------------------------------------------------*/
void kalP2PIndicateConnReq(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t *pucDevName, IN int32_t u4NameLength,
IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN],
IN uint8_t ucDevType,/* 0: P2P Device / 1: GC / 2: GO */
IN int32_t i4ConfigMethod, IN int32_t i4ActiveConfigMethod
)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
/* buffer peer information
* for later IOC_P2P_GET_REQ_DEVICE_INFO access
*/
prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength =
u4NameLength > 32 ? 32 : u4NameLength;
kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName,
pucDevName,
prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength);
COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr, rPeerAddr);
prGlueInfo->prP2PInfo[0]->ucConnReqDevType = ucDevType;
prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = i4ConfigMethod;
prGlueInfo->prP2PInfo[0]->i4ConnReqActiveConfigMethod =
i4ActiveConfigMethod;
/* prepare event structure */
memset(&evt, 0, sizeof(evt));
snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_REQ");
evt.data.length = strlen(aucBuffer);
/* indicate in IWEVCUSTOM event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} /* end of kalP2PIndicateConnReq() */
/*---------------------------------------------------------------------------*/
/*!
* \brief Indicate an event to supplicant
* for device connection request from other device.
*
* \param[in] prGlueInfo Pointer of GLUE_INFO_T
* \param[in] pucGroupBssid Only valid when invitation Type equals to 0.
*
* \retval none
*/
/*---------------------------------------------------------------------------*/
void
kalP2PInvitationIndication(IN struct GLUE_INFO *prGlueInfo,
IN struct P2P_DEVICE_DESC *prP2pDevDesc,
IN uint8_t *pucSsid,
IN uint8_t ucSsidLen,
IN uint8_t ucOperatingChnl,
IN uint8_t ucInvitationType,
IN uint8_t *pucGroupBssid)
{
#if 1
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
/* buffer peer information for later IOC_P2P_GET_STRUCT access */
prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength =
(uint32_t) ((prP2pDevDesc->u2NameLength > 32)
? 32 : prP2pDevDesc->u2NameLength);
kalMemCopy(prGlueInfo->prP2PInfo[0]->aucConnReqDevName,
prP2pDevDesc->aucName,
prGlueInfo->prP2PInfo[0]->u4ConnReqNameLength);
COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqPeerAddr,
prP2pDevDesc->aucDeviceAddr);
COPY_MAC_ADDR(prGlueInfo->prP2PInfo[0]->rConnReqGroupAddr,
pucGroupBssid);
prGlueInfo->prP2PInfo[0]->i4ConnReqConfigMethod = (int32_t)
(prP2pDevDesc->u2ConfigMethod);
prGlueInfo->prP2PInfo[0]->ucOperatingChnl = ucOperatingChnl;
prGlueInfo->prP2PInfo[0]->ucInvitationType = ucInvitationType;
/* prepare event structure */
memset(&evt, 0, sizeof(evt));
snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_INDICATE");
evt.data.length = strlen(aucBuffer);
/* indicate in IWEVCUSTOM event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
#else
struct MSG_P2P_CONNECTION_REQUEST *prP2pConnReq =
(struct MSG_P2P_CONNECTION_REQUEST *) NULL;
struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo =
(struct P2P_SPECIFIC_BSS_INFO *) NULL;
struct P2P_CONNECTION_SETTINGS *prP2pConnSettings =
(struct P2P_CONNECTION_SETTINGS *) NULL;
do {
ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL));
/* Not a real solution */
prP2pSpecificBssInfo =
prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo;
prP2pConnSettings =
prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings;
prP2pConnReq = (struct MSG_P2P_CONNECTION_REQUEST *)
cnmMemAlloc(prGlueInfo->prAdapter,
RAM_TYPE_MSG,
sizeof(struct MSG_P2P_CONNECTION_REQUEST));
if (prP2pConnReq == NULL)
break;
kalMemZero(prP2pConnReq,
sizeof(struct MSG_P2P_CONNECTION_REQUEST));
prP2pConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ;
prP2pConnReq->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO;
COPY_MAC_ADDR(prP2pConnReq->aucDeviceID,
prP2pDevDesc->aucDeviceAddr);
prP2pConnReq->u2ConfigMethod = prP2pDevDesc->u2ConfigMethod;
if (ucInvitationType == P2P_INVITATION_TYPE_INVITATION) {
prP2pConnReq->fgIsPersistentGroup = FALSE;
prP2pConnReq->fgIsTobeGO = FALSE;
}
else if (ucInvitationType == P2P_INVITATION_TYPE_REINVOKE) {
DBGLOG(P2P, TRACE, "Re-invoke Persistent Group\n");
prP2pConnReq->fgIsPersistentGroup = TRUE;
prP2pConnReq->fgIsTobeGO =
(prGlueInfo->prP2PInfo[0]->ucRole == 2)
? TRUE : FALSE;
}
p2pFsmRunEventDeviceDiscoveryAbort(prGlueInfo->prAdapter, NULL);
if (ucOperatingChnl != 0)
prP2pSpecificBssInfo->ucPreferredChannel =
ucOperatingChnl;
if ((ucSsidLen < 32) && (pucSsid != NULL))
COPY_SSID(prP2pConnSettings->aucSSID,
prP2pConnSettings->ucSSIDLen,
pucSsid, ucSsidLen);
mboxSendMsg(prGlueInfo->prAdapter,
MBOX_ID_0,
(struct MSG_HDR *) prP2pConnReq,
MSG_SEND_METHOD_BUF);
} while (FALSE);
/* frog add. */
/* TODO: Invitation Indication */
#endif
} /* kalP2PInvitationIndication */
#endif
#if 0
/*---------------------------------------------------------------------------*/
/*!
* \brief Indicate an status to supplicant for device invitation status.
*
* \param[in] prGlueInfo Pointer of GLUE_INFO_T
*
* \retval none
*/
/*---------------------------------------------------------------------------*/
void kalP2PInvitationStatus(IN struct GLUE_INFO *prGlueInfo,
IN uint32_t u4InvStatus)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
/* buffer peer information for later IOC_P2P_GET_STRUCT access */
prGlueInfo->prP2PInfo[0]->u4InvStatus = u4InvStatus;
/* prepare event structure */
memset(&evt, 0, sizeof(evt));
snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_STATUS");
evt.data.length = strlen(aucBuffer);
/* indicate in IWEVCUSTOM event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} /* kalP2PInvitationStatus */
#endif
/*---------------------------------------------------------------------------*/
/*!
* \brief Indicate an event to supplicant
* for Service Discovery request from other device.
*
* \param[in] prGlueInfo Pointer of GLUE_INFO_T
*
* \retval none
*/
/*---------------------------------------------------------------------------*/
void kalP2PIndicateSDRequest(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], IN uint8_t ucSeqNum)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
memset(&evt, 0, sizeof(evt));
snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_REQ %d", ucSeqNum);
evt.data.length = strlen(aucBuffer);
/* indicate IWEVP2PSDREQ event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} /* end of kalP2PIndicateSDRequest() */
/*---------------------------------------------------------------------------*/
/*!
* \brief Indicate an event to supplicant for Service Discovery response
* from other device.
*
* \param[in] prGlueInfo Pointer of GLUE_INFO_T
*
* \retval none
*/
/*---------------------------------------------------------------------------*/
void kalP2PIndicateSDResponse(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t rPeerAddr[PARAM_MAC_ADDR_LEN], IN uint8_t ucSeqNum)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
memset(&evt, 0, sizeof(evt));
snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_RESP %d", ucSeqNum);
evt.data.length = strlen(aucBuffer);
/* indicate IWEVP2PSDREQ event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} /* end of kalP2PIndicateSDResponse() */
/*---------------------------------------------------------------------------*/
/*!
* \brief Indicate an event to supplicant for Service Discovery TX Done
* from other device.
*
* \param[in] prGlueInfo Pointer of GLUE_INFO_T
* \param[in] ucSeqNum Sequence number of the frame
* \param[in] ucStatus Status code for TX
*
* \retval none
*/
/*---------------------------------------------------------------------------*/
void kalP2PIndicateTXDone(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucSeqNum, IN uint8_t ucStatus)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
memset(&evt, 0, sizeof(evt));
snprintf(aucBuffer, IW_CUSTOM_MAX - 1,
"P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus);
evt.data.length = strlen(aucBuffer);
/* indicate IWEVP2PSDREQ event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} /* end of kalP2PIndicateSDResponse() */
struct net_device *kalP2PGetDevHdlr(struct GLUE_INFO *prGlueInfo)
{
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[0]);
return prGlueInfo->prP2PInfo[0]->prDevHandler;
}
#if CFG_SUPPORT_ANTI_PIRACY
#if 0
/*---------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in] prAdapter Pointer of ADAPTER_T
*
* \return none
*/
/*---------------------------------------------------------------------------*/
void kalP2PIndicateSecCheckRsp(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t *pucRsp, IN uint16_t u2RspLen)
{
union iwreq_data evt;
uint8_t aucBuffer[IW_CUSTOM_MAX];
ASSERT(prGlueInfo);
memset(&evt, 0, sizeof(evt));
snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SEC_CHECK_RSP=");
kalMemCopy(prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, pucRsp, u2RspLen);
evt.data.length = strlen(aucBuffer);
#if DBG
DBGLOG_MEM8(SEC, LOUD,
prGlueInfo->prP2PInfo[0]->aucSecCheckRsp, u2RspLen);
#endif
/* indicate in IWECUSTOM event */
wireless_send_event(prGlueInfo->prP2PInfo[0]->prDevHandler,
IWEVCUSTOM, &evt, aucBuffer);
} /* p2pFsmRunEventRxDisassociation */
#endif
#endif
/*---------------------------------------------------------------------------*/
/*!
* \brief
*
* \param[in] prAdapter Pointer of ADAPTER_T
*
* \return none
*/
/*---------------------------------------------------------------------------*/
void
kalGetChnlList(IN struct GLUE_INFO *prGlueInfo,
IN enum ENUM_BAND eSpecificBand,
IN uint8_t ucMaxChannelNum,
IN uint8_t *pucNumOfChannel,
IN struct RF_CHANNEL_INFO *paucChannelList)
{
rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand,
FALSE, ucMaxChannelNum, pucNumOfChannel, paucChannelList);
} /* kalGetChnlList */
/* ////////////////////////////ICS SUPPORT////////////////////////////// */
void
kalP2PIndicateChannelReady(IN struct GLUE_INFO *prGlueInfo,
IN uint64_t u8SeqNum,
IN uint32_t u4ChannelNum,
IN enum ENUM_BAND eBand,
IN enum ENUM_CHNL_EXT eSco,
IN uint32_t u4Duration)
{
struct ieee80211_channel *prIEEE80211ChnlStruct =
(struct ieee80211_channel *)NULL;
struct RF_CHANNEL_INFO rChannelInfo;
enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT;
do {
if (prGlueInfo == NULL)
break;
kalMemZero(&rChannelInfo, sizeof(struct RF_CHANNEL_INFO));
rChannelInfo.ucChannelNum = u4ChannelNum;
rChannelInfo.eBand = eBand;
prIEEE80211ChnlStruct =
kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo[0],
&rChannelInfo);
kalP2pFuncGetChannelType(eSco, &eChnlType);
cfg80211_ready_on_channel(
/* struct wireless_dev, */
prGlueInfo->prP2PInfo[0]->prWdev,
/* u64 cookie, */
u8SeqNum,
/* struct ieee80211_channel * chan, */
prIEEE80211ChnlStruct,
/* unsigned int duration, */
u4Duration,
/* gfp_t gfp *//* allocation flags */
GFP_KERNEL);
} while (FALSE);
} /* kalP2PIndicateChannelReady */
void
kalP2PIndicateChannelExpired(IN struct GLUE_INFO *prGlueInfo,
IN uint64_t u8SeqNum,
IN uint32_t u4ChannelNum,
IN enum ENUM_BAND eBand,
IN enum ENUM_CHNL_EXT eSco)
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct ieee80211_channel *prIEEE80211ChnlStruct =
(struct ieee80211_channel *)NULL;
enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT;
struct RF_CHANNEL_INFO rRfChannelInfo;
do {
if (prGlueInfo == NULL) {
ASSERT(FALSE);
break;
}
prGlueP2pInfo = prGlueInfo->prP2PInfo[0];
if (prGlueP2pInfo == NULL) {
ASSERT(FALSE);
break;
}
DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n");
rRfChannelInfo.eBand = eBand;
rRfChannelInfo.ucChannelNum = u4ChannelNum;
prIEEE80211ChnlStruct =
kalP2pFuncGetChannelEntry(prGlueP2pInfo,
&rRfChannelInfo);
kalP2pFuncGetChannelType(eSco, &eChnlType);
/* struct wireless_dev, */
cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev,
u8SeqNum, prIEEE80211ChnlStruct, GFP_KERNEL);
} while (FALSE);
} /* kalP2PIndicateChannelExpired */
void kalP2PIndicateScanDone(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIndex, IN u_int8_t fgIsAbort)
{
struct GL_P2P_DEV_INFO *prP2pGlueDevInfo =
(struct GL_P2P_DEV_INFO *) NULL;
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct cfg80211_scan_request *prScanRequest = NULL;
GLUE_SPIN_LOCK_DECLARATION();
do {
if (prGlueInfo == NULL) {
ASSERT(FALSE);
break;
}
prGlueP2pInfo = prGlueInfo->prP2PInfo[0];
prP2pGlueDevInfo = prGlueInfo->prP2PDevInfo;
if ((prGlueP2pInfo == NULL) || (prP2pGlueDevInfo == NULL)) {
ASSERT(FALSE);
break;
}
DBGLOG(INIT, INFO,
"[p2p] scan complete %p\n",
prP2pGlueDevInfo->prScanRequest);
KAL_ACQUIRE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF);
GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
if (prP2pGlueDevInfo->prScanRequest != NULL) {
prScanRequest = prP2pGlueDevInfo->prScanRequest;
kalCfg80211ScanDone(prScanRequest, fgIsAbort);
prP2pGlueDevInfo->prScanRequest = NULL;
}
GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
if ((prScanRequest != NULL)
&& (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE)) {
/* report all queued beacon/probe response frames
* to upper layer
*/
scanReportBss2Cfg80211(prGlueInfo->prAdapter,
BSS_TYPE_P2P_DEVICE, NULL);
DBGLOG(INIT, TRACE, "DBG:p2p_cfg_scan_done\n");
}
KAL_RELEASE_MUTEX(prGlueInfo->prAdapter, MUTEX_DEL_INF);
} while (FALSE);
} /* kalP2PIndicateScanDone */
void
kalP2PIndicateBssInfo(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t *pucFrameBuf,
IN uint32_t u4BufLen,
IN struct RF_CHANNEL_INFO *prChannelInfo,
IN int32_t i4SignalStrength)
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct ieee80211_channel *prChannelEntry =
(struct ieee80211_channel *)NULL;
struct ieee80211_mgmt *prBcnProbeRspFrame =
(struct ieee80211_mgmt *)pucFrameBuf;
struct cfg80211_bss *prCfg80211Bss = (struct cfg80211_bss *)NULL;
do {
if ((prGlueInfo == NULL) || (pucFrameBuf == NULL)
|| (prChannelInfo == NULL)) {
ASSERT(FALSE);
break;
}
prGlueP2pInfo = prGlueInfo->prP2PInfo[0];
if (prGlueP2pInfo == NULL) {
ASSERT(FALSE);
break;
}
prChannelEntry =
kalP2pFuncGetChannelEntry(prGlueP2pInfo,
prChannelInfo);
if (prChannelEntry == NULL) {
DBGLOG(P2P, TRACE, "Unknown channel info\n");
break;
}
/* rChannelInfo.center_freq =
* nicChannelNum2Freq((UINT_32)prChannelInfo->ucChannelNum)
* / 1000;
*/
if (u4BufLen > 0) {
prCfg80211Bss = cfg80211_inform_bss_frame(
/* struct wiphy * wiphy, */
prGlueP2pInfo->prWdev->wiphy,
prChannelEntry,
prBcnProbeRspFrame,
u4BufLen, i4SignalStrength, GFP_KERNEL);
}
/* Return this structure. */
if (prCfg80211Bss)
cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy,
prCfg80211Bss);
else
DBGLOG(P2P, WARN,
"indicate BSS to cfg80211 failed [" MACSTR
"]: bss channel %d, rcpi %d, frame_len=%d\n",
MAC2STR(prBcnProbeRspFrame->bssid),
prChannelInfo->ucChannelNum,
i4SignalStrength, u4BufLen);
} while (FALSE);
return;
} /* kalP2PIndicateBssInfo */
void kalP2PIndicateMgmtTxStatus(IN struct GLUE_INFO *prGlueInfo,
IN struct MSDU_INFO *prMsduInfo, IN u_int8_t fgIsAck)
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
uint64_t *pu8GlCookie = (uint64_t *) NULL;
struct net_device *prNetdevice = (struct net_device *)NULL;
do {
if ((prGlueInfo == NULL) || (prMsduInfo == NULL)) {
DBGLOG(P2P, WARN,
"Unexpected pointer PARAM. 0x%lx, 0x%lx.\n",
prGlueInfo, prMsduInfo);
ASSERT(FALSE);
break;
}
pu8GlCookie =
(uint64_t *) ((unsigned long) prMsduInfo->prPacket +
(unsigned long) prMsduInfo->u2FrameLength +
MAC_TX_RESERVED_FIELD);
if (prMsduInfo->ucBssIndex
== prGlueInfo->prAdapter->ucP2PDevBssIdx) {
prGlueP2pInfo = prGlueInfo->prP2PInfo[0];
if (prGlueP2pInfo == NULL)
return;
prNetdevice = prGlueP2pInfo->prDevHandler;
} else {
struct BSS_INFO *prP2pBssInfo =
GET_BSS_INFO_BY_INDEX(prGlueInfo->prAdapter,
prMsduInfo->ucBssIndex);
prGlueP2pInfo =
prGlueInfo->prP2PInfo
[prP2pBssInfo->u4PrivateData];
if (prGlueP2pInfo == NULL)
return;
prNetdevice = prGlueP2pInfo->aprRoleHandler;
}
cfg80211_mgmt_tx_status(
/* struct net_device * dev, */
prNetdevice->ieee80211_ptr,
*pu8GlCookie,
(uint8_t *) ((unsigned long) prMsduInfo->prPacket +
MAC_TX_RESERVED_FIELD),
prMsduInfo->u2FrameLength, fgIsAck, GFP_KERNEL);
} while (FALSE);
} /* kalP2PIndicateMgmtTxStatus */
void
kalP2PIndicateRxMgmtFrame(IN struct GLUE_INFO *prGlueInfo,
IN struct SW_RFB *prSwRfb,
IN u_int8_t fgIsDevInterface,
IN uint8_t ucRoleIdx)
{
#define DBG_P2P_MGMT_FRAME_INDICATION 1
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
int32_t i4Freq = 0;
uint8_t ucChnlNum = 0;
#if DBG_P2P_MGMT_FRAME_INDICATION
struct WLAN_MAC_HEADER *prWlanHeader = (struct WLAN_MAC_HEADER *) NULL;
#endif
struct net_device *prNetdevice = (struct net_device *)NULL;
do {
if ((prGlueInfo == NULL) || (prSwRfb == NULL)) {
ASSERT(FALSE);
break;
}
prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIdx];
/* ToDo[6630]: Get the following by channel freq */
/* HAL_RX_STATUS_GET_CHAN_FREQ( prSwRfb->prRxStatus) */
/* ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; */
ucChnlNum = HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus);
#if DBG_P2P_MGMT_FRAME_INDICATION
prWlanHeader = (struct WLAN_MAC_HEADER *) prSwRfb->pvHeader;
switch (prWlanHeader->u2FrameCtrl) {
case MAC_FRAME_PROBE_REQ:
DBGLOG(P2P, TRACE,
"RX Probe Req at channel %d ",
ucChnlNum);
break;
case MAC_FRAME_PROBE_RSP:
DBGLOG(P2P, TRACE,
"RX Probe Rsp at channel %d ",
ucChnlNum);
break;
case MAC_FRAME_ACTION:
DBGLOG(P2P, TRACE,
"RX Action frame at channel %d ",
ucChnlNum);
p2pFuncClassifyAction(prSwRfb);
break;
default:
DBGLOG(P2P, TRACE,
"RX Packet:%d at channel %d ",
prWlanHeader->u2FrameCtrl, ucChnlNum);
break;
}
DBGLOG(P2P, TRACE,
"from: " MACSTR "\n", MAC2STR(prWlanHeader->aucAddr2));
#endif
i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000;
if (fgIsDevInterface)
prNetdevice = prGlueP2pInfo->prDevHandler;
else
prNetdevice = prGlueP2pInfo->aprRoleHandler;
#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE)
cfg80211_rx_mgmt(
/* struct net_device * dev, */
prNetdevice->ieee80211_ptr,
i4Freq,
RCPI_TO_dBm(
nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX,
prSwRfb)),
prSwRfb->pvHeader,
prSwRfb->u2PacketLen,
NL80211_RXMGMT_FLAG_ANSWERED);
#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE)
cfg80211_rx_mgmt(
/* struct net_device * dev, */
prNetdevice->ieee80211_ptr,
i4Freq,
RCPI_TO_dBm(
nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0,
prSwRfb)),
prSwRfb->pvHeader,
prSwRfb->u2PacketLen,
NL80211_RXMGMT_FLAG_ANSWERED,
GFP_ATOMIC);
#else
cfg80211_rx_mgmt(
/* struct net_device * dev, */
prNetdevice->ieee80211_ptr,
i4Freq,
RCPI_TO_dBm(
nicRxGetRcpiValueFromRxv(RCPI_MODE_WF0,
prSwRfb)),
prSwRfb->pvHeader,
prSwRfb->u2PacketLen,
GFP_ATOMIC);
#endif
} while (FALSE);
} /* kalP2PIndicateRxMgmtFrame */
#if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE)
void
kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIndex,
IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo,
IN uint8_t *pucRxIEBuf,
IN uint16_t u2RxIELen,
IN uint16_t u2StatusReason,
IN uint32_t eStatus)
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct ADAPTER *prAdapter = NULL;
do {
if (prGlueInfo == NULL) {
ASSERT(FALSE);
break;
}
prAdapter = prGlueInfo->prAdapter;
prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex];
/* FIXME: This exception occurs at wlanRemove. */
if ((prGlueP2pInfo == NULL) ||
(prGlueP2pInfo->aprRoleHandler == NULL) ||
(prAdapter->rP2PNetRegState !=
ENUM_NET_REG_STATE_REGISTERED) ||
((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 1)) {
break;
}
if (prP2pConnInfo) {
/* switch netif on */
netif_carrier_on(prGlueP2pInfo->aprRoleHandler);
#if !CFG_SUPPORT_CFG80211_AUTH
cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler,
/* struct net_device * dev, */
prP2pConnInfo->aucBssid,
prP2pConnInfo->aucIEBuf,
prP2pConnInfo->u4BufLength,
pucRxIEBuf, u2RxIELen,
u2StatusReason,
/* gfp_t gfp *//* allocation flags */
GFP_KERNEL);
#endif
prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE;
} else {
/* Disconnect, what if u2StatusReason == 0? */
cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler,
/* struct net_device * dev, */
u2StatusReason,
pucRxIEBuf, u2RxIELen,
eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY,
GFP_KERNEL);
}
} while (FALSE);
} /* kalP2PGCIndicateConnectionStatus */
#else
void
kalP2PGCIndicateConnectionStatus(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIndex,
IN struct P2P_CONNECTION_REQ_INFO *prP2pConnInfo,
IN uint8_t *pucRxIEBuf,
IN uint16_t u2RxIELen,
IN uint16_t u2StatusReason)
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct ADAPTER *prAdapter = NULL;
do {
if (prGlueInfo == NULL) {
ASSERT(FALSE);
break;
}
prAdapter = prGlueInfo->prAdapter;
prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex];
/* FIXME: This exception occurs at wlanRemove. */
if ((prGlueP2pInfo == NULL) ||
(prGlueP2pInfo->aprRoleHandler == NULL) ||
(prAdapter->rP2PNetRegState !=
ENUM_NET_REG_STATE_REGISTERED) ||
((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 1)) {
break;
}
if (prP2pConnInfo) {
/* switch netif on */
netif_carrier_on(prGlueP2pInfo->aprRoleHandler);
cfg80211_connect_result(prGlueP2pInfo->aprRoleHandler,
/* struct net_device * dev, */
prP2pConnInfo->aucBssid,
prP2pConnInfo->aucIEBuf,
prP2pConnInfo->u4BufLength,
pucRxIEBuf, u2RxIELen,
u2StatusReason,
/* gfp_t gfp *//* allocation flags */
GFP_KERNEL);
prP2pConnInfo->eConnRequest = P2P_CONNECTION_TYPE_IDLE;
} else {
/* Disconnect, what if u2StatusReason == 0? */
cfg80211_disconnected(prGlueP2pInfo->aprRoleHandler,
/* struct net_device * dev, */
u2StatusReason, pucRxIEBuf,
u2RxIELen, GFP_KERNEL);
}
} while (FALSE);
} /* kalP2PGCIndicateConnectionStatus */
#endif
void
kalP2PGOStationUpdate(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIndex,
IN struct STA_RECORD *prCliStaRec,
IN u_int8_t fgIsNew)
{
struct GL_P2P_INFO *prP2pGlueInfo = (struct GL_P2P_INFO *) NULL;
do {
if ((prGlueInfo == NULL) || (prCliStaRec == NULL)
|| (ucRoleIndex >= 2))
break;
prP2pGlueInfo = prGlueInfo->prP2PInfo[ucRoleIndex];
if ((prP2pGlueInfo == NULL) ||
(prP2pGlueInfo->aprRoleHandler == NULL)) {
/* This case may occur when the usb is unplugged */
break;
}
if (fgIsNew) {
struct station_info rStationInfo;
kalMemZero(&rStationInfo, sizeof(rStationInfo));
#if KERNEL_VERSION(4, 0, 0) > CFG80211_VERSION_CODE
rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES;
#endif
rStationInfo.generation = ++prP2pGlueInfo->i4Generation;
rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe;
rStationInfo.assoc_req_ies_len =
prCliStaRec->u2AssocReqIeLen;
cfg80211_new_sta(prP2pGlueInfo->aprRoleHandler,
/* struct net_device * dev, */
prCliStaRec->aucMacAddr,
&rStationInfo, GFP_KERNEL);
} else {
++prP2pGlueInfo->i4Generation;
/* FIXME: The exception occurs at wlanRemove, and
* check GLUE_FLAG_HALT is the temporarily solution.
*/
if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) == 0) {
cfg80211_del_sta(prP2pGlueInfo->aprRoleHandler,
/* struct net_device * dev, */
prCliStaRec->aucMacAddr, GFP_KERNEL);
}
}
} while (FALSE);
return;
} /* kalP2PGOStationUpdate */
#if (CFG_SUPPORT_DFS_MASTER == 1)
void kalP2PRddDetectUpdate(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIndex)
{
DBGLOG(INIT, INFO, "Radar Detection event\n");
do {
if (prGlueInfo == NULL) {
ASSERT(FALSE);
break;
}
if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL) {
ASSERT(FALSE);
break;
}
/* cac start disable for next cac slot
* if enable in dfs channel
*/
prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->cac_started = FALSE;
DBGLOG(INIT, INFO,
"kalP2PRddDetectUpdate: Update to OS\n");
cfg80211_radar_event(
prGlueInfo->prP2PInfo[ucRoleIndex]->prWdev->wiphy,
prGlueInfo->prP2PInfo[ucRoleIndex]->chandef,
GFP_KERNEL);
DBGLOG(INIT, INFO,
"kalP2PRddDetectUpdate: Update to OS Done\n");
netif_carrier_off(
prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler);
netif_tx_stop_all_queues(
prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler);
} while (FALSE);
} /* kalP2PRddDetectUpdate */
void kalP2PCacFinishedUpdate(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIndex)
{
DBGLOG(INIT, INFO, "CAC Finished event\n");
if (prGlueInfo == NULL)
return;
if (prGlueInfo->prP2PInfo[ucRoleIndex]->chandef == NULL)
return;
DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS\n");
#if KERNEL_VERSION(3, 14, 0) <= CFG80211_VERSION_CODE
cfg80211_cac_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler,
prGlueInfo->prP2PInfo[ucRoleIndex]->chandef,
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
#else
cfg80211_cac_event(prGlueInfo->prP2PInfo[ucRoleIndex]->prDevHandler,
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
#endif
DBGLOG(INIT, INFO, "kalP2PCacFinishedUpdate: Update to OS Done\n");
} /* kalP2PRddDetectUpdate */
#endif
u_int8_t kalP2pFuncGetChannelType(IN enum ENUM_CHNL_EXT rChnlSco,
OUT enum nl80211_channel_type *channel_type)
{
u_int8_t fgIsValid = FALSE;
do {
if (channel_type) {
switch (rChnlSco) {
case CHNL_EXT_SCN:
*channel_type = NL80211_CHAN_NO_HT;
break;
case CHNL_EXT_SCA:
*channel_type = NL80211_CHAN_HT40MINUS;
break;
case CHNL_EXT_SCB:
*channel_type = NL80211_CHAN_HT40PLUS;
break;
default:
ASSERT(FALSE);
*channel_type = NL80211_CHAN_NO_HT;
break;
}
}
fgIsValid = TRUE;
} while (FALSE);
return fgIsValid;
} /* kalP2pFuncGetChannelType */
struct ieee80211_channel *kalP2pFuncGetChannelEntry(
IN struct GL_P2P_INFO *prP2pInfo,
IN struct RF_CHANNEL_INFO *prChannelInfo)
{
struct ieee80211_channel *prTargetChannelEntry =
(struct ieee80211_channel *)NULL;
uint32_t u4TblSize = 0, u4Idx = 0;
struct wiphy *wiphy = NULL;
if ((prP2pInfo == NULL) || (prChannelInfo == NULL))
return NULL;
wiphy = prP2pInfo->prWdev->wiphy;
do {
switch (prChannelInfo->eBand) {
case BAND_2G4:
if (wiphy->bands[KAL_BAND_2GHZ] == NULL)
DBGLOG(P2P, ERROR,
"kalP2pFuncGetChannelEntry 2.4G NULL Bands!!\n");
else {
prTargetChannelEntry =
wiphy->bands[KAL_BAND_2GHZ]->channels;
u4TblSize =
wiphy->bands[KAL_BAND_2GHZ]->n_channels;
}
break;
case BAND_5G:
if (wiphy->bands[KAL_BAND_5GHZ] == NULL)
DBGLOG(P2P, ERROR,
"kalP2pFuncGetChannelEntry 5G NULL Bands!!\n");
else {
prTargetChannelEntry =
wiphy->bands[KAL_BAND_5GHZ]->channels;
u4TblSize =
wiphy->bands[KAL_BAND_5GHZ]->n_channels;
}
break;
default:
break;
}
if (prTargetChannelEntry == NULL)
break;
for (u4Idx = 0; u4Idx < u4TblSize
; u4Idx++, prTargetChannelEntry++) {
if (prTargetChannelEntry->hw_value
== prChannelInfo->ucChannelNum)
break;
}
if (u4Idx == u4TblSize) {
prTargetChannelEntry = NULL;
break;
}
} while (FALSE);
return prTargetChannelEntry;
} /* kalP2pFuncGetChannelEntry */
#if CFG_SUPPORT_HOTSPOT_WPS_MANAGER
/*---------------------------------------------------------------------------*/
/*!
* \brief to set the block list of Hotspot
*
* \param[in]
* prGlueInfo
*
* \return
*/
/*---------------------------------------------------------------------------*/
u_int8_t kalP2PSetBlackList(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t rbssid[PARAM_MAC_ADDR_LEN],
IN u_int8_t fgIsblock,
IN uint8_t ucRoleIndex)
{
uint8_t aucNullAddr[] = NULL_MAC_ADDR;
u_int8_t fgIsValid = FALSE;
uint32_t i;
ASSERT(prGlueInfo);
/*ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]);*/
/*if only one ap mode register, prGlueInfo->prP2PInfo[1] would be null*/
if (!prGlueInfo->prP2PInfo[ucRoleIndex])
return fgIsValid;
#if IS_ENABLED(CFG_CCN7_SAP_EASYMESH)
kalP2PCatBlackList(prGlueInfo, 1);
#endif
if (fgIsblock) {
for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) {
if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) {
if (UNEQUAL_MAC_ADDR(
&(prGlueInfo->prP2PInfo[ucRoleIndex]
->aucblackMACList[i]), rbssid)) {
if (EQUAL_MAC_ADDR(
&(prGlueInfo->prP2PInfo
[ucRoleIndex]
->aucblackMACList[i]),
aucNullAddr)) {
COPY_MAC_ADDR(
&(prGlueInfo->prP2PInfo
[ucRoleIndex]
->aucblackMACList[i]),
rbssid);
fgIsValid = FALSE;
#if IS_ENABLED(CFG_CCN7_SAP_EASYMESH)
kalP2PCatBlackList(
prGlueInfo,
0);
#endif
return fgIsValid;
}
}
}
}
} else {
for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) {
if (EQUAL_MAC_ADDR(
&(prGlueInfo->prP2PInfo[ucRoleIndex]
->aucblackMACList[i]), rbssid)) {
COPY_MAC_ADDR(
&(prGlueInfo->prP2PInfo[ucRoleIndex]
->aucblackMACList[i]), aucNullAddr);
#if IS_ENABLED(CFG_CCN7_SAP_EASYMESH)
kalP2PCatBlackList(prGlueInfo, 0);
#endif
fgIsValid = FALSE;
return fgIsValid;
}
}
}
#if IS_ENABLED(CFG_CCN7_SAP_EASYMESH)
kalP2PCatBlackList(prGlueInfo, 0);
#endif
return fgIsValid;
}
#if IS_ENABLED(CFG_CCN7_SAP_EASYMESH)
void kalP2PCatBlackList(IN struct GLUE_INFO *prGlueInfo, IN bool flag)
{
uint32_t i;
uint8_t ucRoleIndex;
if (flag)
DBGLOG(INIT, ERROR, "Before Set BlackLis\n");
else
DBGLOG(INIT, ERROR, "After Set BlackLis\n");
for (ucRoleIndex = 0; ucRoleIndex < KAL_P2P_NUM; ucRoleIndex++) {
for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) {
DBGLOG(INIT, ERROR,
"ucRoleIndex[%d]-BlackList[%d] MA="MACSTR"\n",
ucRoleIndex, i,
&(prGlueInfo->prP2PInfo[ucRoleIndex]
->aucblackMACList[i]));
}
}
}
#endif
/*---------------------------------------------------------------------------*/
/*!
* \brief to compare the black list of Hotspot
*
* \param[in]
* prGlueInfo
*
* \return
*/
/*---------------------------------------------------------------------------*/
u_int8_t kalP2PCmpBlackList(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t rbssid[PARAM_MAC_ADDR_LEN],
IN uint8_t ucRoleIndex)
{
uint8_t aucNullAddr[] = NULL_MAC_ADDR;
u_int8_t fgIsExsit = FALSE;
uint32_t i;
ASSERT(prGlueInfo);
ASSERT(prGlueInfo->prP2PInfo[ucRoleIndex]);
for (i = 0; i < P2P_MAXIMUM_CLIENT_COUNT; i++) {
if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) {
if (EQUAL_MAC_ADDR(
&(prGlueInfo->prP2PInfo
[ucRoleIndex]->aucblackMACList[i]),
rbssid)) {
fgIsExsit = TRUE;
return fgIsExsit;
}
}
}
return fgIsExsit;
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to return the max clients of Hotspot
*
* \param[in]
* prGlueInfo
*
* \return
*/
/*---------------------------------------------------------------------------*/
void kalP2PSetMaxClients(IN struct GLUE_INFO *prGlueInfo,
IN uint32_t u4MaxClient,
IN uint8_t ucRoleIndex)
{
ASSERT(prGlueInfo);
if (prGlueInfo->prP2PInfo[ucRoleIndex] == NULL)
return;
if (u4MaxClient == 0 ||
u4MaxClient >= P2P_MAXIMUM_CLIENT_COUNT)
prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients =
P2P_MAXIMUM_CLIENT_COUNT;
else
prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients = u4MaxClient;
}
/*---------------------------------------------------------------------------*/
/*!
* \brief to return the max clients of Hotspot
*
* \param[in]
* prGlueInfo
*
* \return
*/
/*---------------------------------------------------------------------------*/
u_int8_t kalP2PMaxClients(IN struct GLUE_INFO *prGlueInfo,
IN uint32_t u4NumClient, IN uint8_t ucRoleIndex)
{
ASSERT(prGlueInfo);
if (prGlueInfo->prP2PInfo[ucRoleIndex] &&
prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients) {
if ((uint8_t) u4NumClient
>= prGlueInfo->prP2PInfo[ucRoleIndex]->ucMaxClients)
return TRUE;
else
return FALSE;
}
return FALSE;
}
#endif
void kalP2pUnlinkBss(IN struct GLUE_INFO *prGlueInfo, IN uint8_t aucBSSID[])
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct cfg80211_bss *bss = NULL;
ASSERT(prGlueInfo);
ASSERT(aucBSSID);
DBGLOG(P2P, INFO, "bssid: " MACSTR "\n", MAC2STR(aucBSSID));
prGlueP2pInfo = prGlueInfo->prP2PInfo[0];
if (prGlueP2pInfo == NULL)
return;
#if (KERNEL_VERSION(4, 1, 0) <= CFG80211_VERSION_CODE)
bss = cfg80211_get_bss(prGlueP2pInfo->prWdev->wiphy,
NULL, /* channel */
aucBSSID,
NULL, /* ssid */
0, /* ssid length */
IEEE80211_BSS_TYPE_ESS,
IEEE80211_PRIVACY_ANY);
#else
bss = cfg80211_get_bss(prGlueP2pInfo->prWdev->wiphy,
NULL, /* channel */
aucBSSID,
NULL, /* ssid */
0, /* ssid length */
WLAN_CAPABILITY_ESS,
WLAN_CAPABILITY_ESS);
#endif
if (bss != NULL) {
cfg80211_unlink_bss(prGlueP2pInfo->prWdev->wiphy, bss);
cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, bss);
}
if (scanSearchBssDescByBssidAndSsid(prGlueInfo->prAdapter,
aucBSSID, FALSE, NULL) != NULL)
scanRemoveBssDescByBssid(prGlueInfo->prAdapter, aucBSSID);
}
void kalP2pIndicateQueuedMgmtFrame(IN struct GLUE_INFO *prGlueInfo,
IN struct P2P_QUEUED_ACTION_FRAME *prFrame)
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct net_device *prNetdevice = (struct net_device *) NULL;
if ((prGlueInfo == NULL) || (prFrame == NULL)) {
ASSERT(FALSE);
return;
}
DBGLOG(P2P, INFO, "Indicate queued p2p action frame.\n");
if (prFrame->prHeader == NULL || prFrame->u2Length == 0) {
DBGLOG(P2P, WARN, "Frame pointer is null or length is 0.\n");
return;
}
prGlueP2pInfo = prGlueInfo->prP2PInfo[prFrame->ucRoleIdx];
prNetdevice = prGlueP2pInfo->prDevHandler;
#if (KERNEL_VERSION(3, 18, 0) <= CFG80211_VERSION_CODE)
cfg80211_rx_mgmt(
/* struct net_device * dev, */
prNetdevice->ieee80211_ptr,
prFrame->u4Freq,
0,
prFrame->prHeader,
prFrame->u2Length,
NL80211_RXMGMT_FLAG_ANSWERED);
#elif (KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE)
cfg80211_rx_mgmt(
/* struct net_device * dev, */
prNetdevice->ieee80211_ptr,
prFrame->u4Freq,
0,
prFrame->prHeader,
prFrame->u2Length,
NL80211_RXMGMT_FLAG_ANSWERED,
GFP_ATOMIC);
#else
cfg80211_rx_mgmt(
/* struct net_device * dev, */
prNetdevice->ieee80211_ptr,
prFrame->u4Freq,
0,
prFrame->prHeader,
prFrame->u2Length,
GFP_ATOMIC);
#endif
}
void kalP2pIndicateAcsResult(IN struct GLUE_INFO *prGlueInfo,
IN uint8_t ucRoleIndex,
IN uint8_t ucPrimaryCh,
IN uint8_t ucSecondCh,
IN uint8_t ucSeg0Ch,
IN uint8_t ucSeg1Ch,
IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw)
{
struct GL_P2P_INFO *prGlueP2pInfo = (struct GL_P2P_INFO *) NULL;
struct sk_buff *vendor_event = NULL;
uint16_t ch_width = MAX_BW_20MHZ;
prGlueP2pInfo = prGlueInfo->prP2PInfo[ucRoleIndex];
if (!prGlueP2pInfo) {
DBGLOG(P2P, ERROR, "p2p glue info null.\n");
return;
}
switch (eChnlBw) {
case MAX_BW_20MHZ:
ch_width = 20;
break;
case MAX_BW_40MHZ:
ch_width = 40;
break;
case MAX_BW_80MHZ:
ch_width = 80;
break;
case MAX_BW_160MHZ:
ch_width = 160;
break;
default:
DBGLOG(P2P, ERROR, "unsupport width: %d.\n", ch_width);
break;
}
DBGLOG(P2P, INFO, "r=%d, c=%d, s=%d, s0=%d, s1=%d, ch_w=%d\n",
ucRoleIndex,
ucPrimaryCh,
ucSecondCh,
ucSeg0Ch,
ucSeg1Ch,
ch_width);
#if KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE
vendor_event = cfg80211_vendor_event_alloc(prGlueP2pInfo->prWdev->wiphy,
#if KERNEL_VERSION(4, 1, 0) <= LINUX_VERSION_CODE
prGlueP2pInfo->prWdev,
#endif
4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
WIFI_EVENT_ACS,
GFP_KERNEL);
#endif
if (!vendor_event) {
DBGLOG(P2P, ERROR, "allocate vendor event fail.\n");
goto nla_put_failure;
}
if (unlikely(nla_put_u8(vendor_event,
WIFI_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
ucPrimaryCh) < 0)) {
DBGLOG(P2P, ERROR, "put primary channel fail.\n");
goto nla_put_failure;
}
if (unlikely(nla_put_u8(vendor_event,
WIFI_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
ucSecondCh) < 0)) {
DBGLOG(P2P, ERROR, "put secondary channel fail.\n");
goto nla_put_failure;
}
if (unlikely(nla_put_u8(vendor_event,
WIFI_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
ucSeg0Ch) < 0)) {
DBGLOG(P2P, ERROR, "put vht seg0 fail.\n");
goto nla_put_failure;
}
if (unlikely(nla_put_u8(vendor_event,
WIFI_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
ucSeg1Ch) < 0)) {
DBGLOG(P2P, ERROR, "put vht seg1 fail.\n");
goto nla_put_failure;
}
if (unlikely(nla_put_u16(vendor_event,
WIFI_VENDOR_ATTR_ACS_CHWIDTH,
ch_width) < 0)) {
DBGLOG(P2P, ERROR, "put ch width fail.\n");
goto nla_put_failure;
}
if (unlikely(nla_put_u8(vendor_event,
WIFI_VENDOR_ATTR_ACS_HW_MODE,
ucPrimaryCh > 14 ?
P2P_VENDOR_ACS_HW_MODE_11A :
P2P_VENDOR_ACS_HW_MODE_11G) < 0)) {
DBGLOG(P2P, ERROR, "put hw mode fail.\n");
goto nla_put_failure;
}
#if KERNEL_VERSION(3, 14, 0) <= LINUX_VERSION_CODE
cfg80211_vendor_event(vendor_event, GFP_KERNEL);
#endif
return;
nla_put_failure:
if (vendor_event)
kfree_skb(vendor_event);
}