| /****************************************************************************** |
| * |
| * 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. |
| * |
| *****************************************************************************/ |
| |
| #include "precomp.h" |
| |
| struct APPEND_VAR_ATTRI_ENTRY txAssocRspAttributesTable[] = { |
| {(P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS), NULL, |
| p2pFuncAppendAttriStatusForAssocRsp} |
| /* 0 *//* Status */ |
| , {(P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING), NULL, |
| p2pFuncAppendAttriExtListenTiming} /* 8 */ |
| }; |
| |
| struct APPEND_VAR_IE_ENTRY txProbeRspIETable[] = { |
| {(ELEM_HDR_LEN + (RATE_NUM_SW - ELEM_MAX_LEN_SUP_RATES)), NULL, |
| bssGenerateExtSuppRate_IE} /* 50 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, |
| rlmRspGenerateErpIE} /* 42 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, |
| rlmRspGenerateHtCapIE} /* 45 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, |
| rlmRspGenerateHtOpIE} /* 61 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, |
| rsnGenerateRSNIE} /* 48 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, |
| rlmRspGenerateObssScanIE} /* 74 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, |
| rlmRspGenerateExtCapIE} /* 127 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, |
| rsnGenerateWpaNoneIE} /* 221 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, |
| mqmGenerateWmmParamIE} /* 221 */ |
| #if CFG_SUPPORT_802_11AC |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_CAP), NULL, |
| rlmRspGenerateVhtCapIE} /*191 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP), NULL, |
| rlmRspGenerateVhtOpIE} /*192 */ |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_VHT_OP_MODE_NOTIFICATION), NULL, |
| rlmRspGenerateVhtOpNotificationIE} /*199 */ |
| #endif |
| #if CFG_SUPPORT_MTK_SYNERGY |
| , {(ELEM_HDR_LEN + ELEM_MIN_LEN_MTK_OUI), NULL, |
| rlmGenerateMTKOuiIE} /* 221 */ |
| #endif |
| , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, |
| rsnGenerateWPAIE} /* 221 */ |
| }; |
| |
| #if (CFG_SUPPORT_DFS_MASTER == 1) |
| u_int8_t g_fgManualCac = FALSE; |
| uint32_t g_u4DriverCacTime; |
| uint32_t g_u4CacStartBootTime; |
| uint8_t g_ucRadarDetectMode = FALSE; |
| struct P2P_RADAR_INFO g_rP2pRadarInfo; |
| uint8_t g_ucDfsState = DFS_STATE_INACTIVE; |
| static uint8_t *apucDfsState[DFS_STATE_NUM] = { |
| (uint8_t *) DISP_STRING("DFS_STATE_INACTIVE"), |
| (uint8_t *) DISP_STRING("DFS_STATE_CHECKING"), |
| (uint8_t *) DISP_STRING("DFS_STATE_ACTIVE"), |
| (uint8_t *) DISP_STRING("DFS_STATE_DETECTED") |
| }; |
| |
| uint8_t *apucW53RadarType[3] = { |
| (uint8_t *) DISP_STRING("Unknown Type"), |
| (uint8_t *) DISP_STRING("Type 1 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 2 (short pulse)") |
| }; |
| uint8_t *apucW56RadarType[12] = { |
| (uint8_t *) DISP_STRING("Unknown Type"), |
| (uint8_t *) DISP_STRING("Type 1 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 2 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 3 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 4 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 5 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 6 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 7 (long pulse)"), |
| (uint8_t *) DISP_STRING("Type 8 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 4 or Type 5 or Type 6 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 5 or Type 6 or Type 8 (short pulse)"), |
| (uint8_t *) DISP_STRING("Type 5 or Type 6 (short pulse)") |
| }; |
| #endif |
| |
| static void |
| p2pFuncParseBeaconVenderId(IN struct ADAPTER *prAdapter, IN uint8_t *pucIE, |
| IN struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo, |
| IN uint8_t ucRoleIndex); |
| #if 0 |
| static void |
| p2pFuncGetAttriListAction(IN struct ADAPTER *prAdapter, |
| IN struct IE_P2P *prIe, |
| IN uint8_t ucOuiType, |
| OUT uint8_t **pucAttriListStart, |
| OUT uint16_t *u2AttriListLen, |
| OUT u_int8_t *fgIsAllocMem, |
| OUT u_int8_t *fgBackupAttributes, |
| OUT uint16_t *u2BufferSize); |
| #endif |
| |
| static void |
| p2pFuncProcessP2pProbeRspAction(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucIEBuf, IN uint8_t ucElemIdType, |
| OUT uint8_t *ucBssIdx, OUT struct BSS_INFO **prP2pBssInfo, |
| OUT u_int8_t *fgIsWSCIE, |
| OUT u_int8_t *fgIsP2PIE, OUT u_int8_t *fgIsWFDIE); |
| |
| static void |
| p2pFuncGetSpecAttriAction(IN struct IE_P2P *prP2pIE, |
| IN uint8_t ucOuiType, |
| IN uint8_t ucAttriID, |
| OUT struct P2P_ATTRIBUTE **prTargetAttri); |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief Function for requesting scan. |
| * There is an option to do ACTIVE or PASSIVE scan. |
| * |
| * @param eScanType - Specify the scan type of the scan request. |
| * It can be an ACTIVE/PASSIVE |
| * Scan. |
| * eChannelSet - Specify the preferred channel set. |
| * A FULL scan would request a legacy |
| * full channel normal scan.(usually ACTIVE). |
| * A P2P_SOCIAL scan would scan |
| * 1+6+11 channels.(usually ACTIVE) |
| * A SPECIFIC scan would |
| * only 1/6/11 channels scan. |
| * (Passive Listen/Specific Search) |
| * ucChannelNum - A specific channel number. |
| * (Only when channel is specified) |
| * eBand - A specific band. (Only when channel is specified) |
| * |
| * |
| * @return (none) |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void p2pFuncRequestScan(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) |
| { |
| struct MSG_SCN_SCAN_REQ_V2 *prScanReqV2 = |
| (struct MSG_SCN_SCAN_REQ_V2 *) NULL; |
| |
| #ifdef CFG_SUPPORT_BEAM_PLUS |
| /*NFC Beam + Indication */ |
| struct P2P_FSM_INFO *prP2pFsmInfo = (struct P2P_FSM_INFO *) NULL; |
| #endif |
| |
| DEBUGFUNC("p2pFuncRequestScan()"); |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); |
| |
| if (prScanReqInfo->eChannelSet == SCAN_CHANNEL_SPECIFIED) { |
| ASSERT_BREAK(prScanReqInfo->ucNumChannelList > 0); |
| DBGLOG(P2P, LOUD, |
| "P2P Scan Request Channel:%d\n", |
| prScanReqInfo->arScanChannelList |
| [0].ucChannelNum); |
| } |
| |
| prScanReqV2 = (struct MSG_SCN_SCAN_REQ_V2 *) |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, |
| (sizeof(struct MSG_SCN_SCAN_REQ_V2) + |
| (sizeof(struct PARAM_SSID) * |
| prScanReqInfo->ucSsidNum))); |
| if (!prScanReqV2) { |
| ASSERT(0); /* Can't trigger SCAN FSM */ |
| DBGLOG(P2P, ERROR, |
| "p2pFuncRequestScan: Memory allocation fail, can not send SCAN MSG to scan module\n"); |
| break; |
| } |
| |
| prScanReqV2->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ_V2; |
| prScanReqV2->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; |
| prScanReqV2->ucBssIndex = ucBssIndex; |
| prScanReqV2->eScanType = prScanReqInfo->eScanType; |
| prScanReqV2->eScanChannel = prScanReqInfo->eChannelSet; |
| prScanReqV2->u2IELen = 0; |
| prScanReqV2->prSsid = (struct PARAM_SSID *) |
| ((unsigned long) prScanReqV2 + |
| sizeof(struct MSG_SCN_SCAN_REQ_V2)); |
| |
| /* Copy IE for Probe Request. */ |
| kalMemCopy(prScanReqV2->aucIE, |
| prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); |
| prScanReqV2->u2IELen = (uint16_t) prScanReqInfo->u4BufLength; |
| |
| prScanReqV2->u2ChannelDwellTime = |
| prScanReqInfo->u2PassiveDewellTime; |
| prScanReqV2->u2ChannelMinDwellTime = |
| SCAN_CHANNEL_DWELL_TIME_MIN_MSEC; |
| COPY_MAC_ADDR(prScanReqV2->aucBSSID, |
| "\xff\xff\xff\xff\xff\xff"); |
| |
| prScanReqV2->u2TimeoutValue = 0; |
| prScanReqV2->u2ProbeDelay = 0; |
| |
| switch (prScanReqInfo->eChannelSet) { |
| case SCAN_CHANNEL_SPECIFIED: |
| { |
| uint32_t u4Idx = 0; |
| struct RF_CHANNEL_INFO *prDomainInfo = |
| (struct RF_CHANNEL_INFO *) |
| prScanReqInfo->arScanChannelList; |
| |
| if (prScanReqInfo->ucNumChannelList |
| > MAXIMUM_OPERATION_CHANNEL_LIST) |
| prScanReqInfo->ucNumChannelList = |
| MAXIMUM_OPERATION_CHANNEL_LIST; |
| |
| for (u4Idx = 0; |
| u4Idx < prScanReqInfo->ucNumChannelList; |
| u4Idx++) { |
| prScanReqV2->arChnlInfoList |
| [u4Idx].ucChannelNum = |
| prDomainInfo->ucChannelNum; |
| prScanReqV2->arChnlInfoList |
| [u4Idx].eBand = |
| prDomainInfo->eBand; |
| prDomainInfo++; |
| } |
| |
| prScanReqV2->ucChannelListNum = |
| prScanReqInfo->ucNumChannelList; |
| } |
| kal_fallthrough; |
| case SCAN_CHANNEL_FULL: |
| kal_fallthrough; |
| case SCAN_CHANNEL_2G4: |
| kal_fallthrough; |
| case SCAN_CHANNEL_P2P_SOCIAL: |
| { |
| /* UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; */ |
| struct PARAM_SSID *prParamSsid = |
| (struct PARAM_SSID *) NULL; |
| |
| prParamSsid = prScanReqV2->prSsid; |
| |
| for (prScanReqV2->ucSSIDNum = 0; |
| prScanReqV2->ucSSIDNum |
| < prScanReqInfo->ucSsidNum; |
| prScanReqV2->ucSSIDNum++) { |
| |
| COPY_SSID(prParamSsid->aucSsid, |
| prParamSsid->u4SsidLen, |
| prScanReqInfo->arSsidStruct |
| [prScanReqV2->ucSSIDNum] |
| .aucSsid, |
| prScanReqInfo->arSsidStruct |
| [prScanReqV2->ucSSIDNum] |
| .ucSsidLen); |
| |
| prParamSsid++; |
| } |
| |
| /* For compatible. (in FW?) need to check. */ |
| if (prScanReqV2->ucSSIDNum == 0) |
| prScanReqV2->ucSSIDType = |
| SCAN_REQ_SSID_P2P_WILDCARD; |
| else |
| prScanReqV2->ucSSIDType = |
| SCAN_REQ_SSID_SPECIFIED; |
| } |
| break; |
| default: |
| /* Currently there is no other scan channel set. */ |
| ASSERT(FALSE); |
| break; |
| } |
| |
| prScanReqInfo->fgIsScanRequest = TRUE; |
| |
| mboxSendMsg(prAdapter, |
| MBOX_ID_0, |
| (struct MSG_HDR *) prScanReqV2, |
| MSG_SEND_METHOD_BUF); |
| |
| } while (FALSE); |
| } /* p2pFuncRequestScan */ |
| |
| void p2pFuncCancelScan(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN struct P2P_SCAN_REQ_INFO *prScanInfo) |
| { |
| struct MSG_SCN_SCAN_CANCEL *prScanCancelMsg = |
| (struct MSG_SCN_SCAN_CANCEL *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prScanInfo != NULL)); |
| |
| if (!prScanInfo->fgIsScanRequest) |
| break; |
| |
| DBGLOG(P2P, TRACE, "P2P Cancel Scan\n"); |
| |
| prScanCancelMsg = (struct MSG_SCN_SCAN_CANCEL *) |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, |
| sizeof(struct MSG_SCN_SCAN_CANCEL)); |
| if (!prScanCancelMsg) { |
| /* Buffer not enough, |
| * can not cancel scan request. |
| */ |
| DBGLOG(P2P, TRACE, |
| "Buffer not enough, can not cancel scan.\n"); |
| ASSERT(FALSE); |
| break; |
| } |
| kalMemZero(prScanCancelMsg, |
| sizeof(struct MSG_SCN_SCAN_CANCEL)); |
| |
| prScanCancelMsg->rMsgHdr.eMsgId = |
| MID_P2P_SCN_SCAN_CANCEL; |
| prScanCancelMsg->ucBssIndex = ucBssIndex; |
| prScanCancelMsg->ucSeqNum = |
| prScanInfo->ucSeqNumOfScnMsg++; |
| prScanCancelMsg->fgIsChannelExt = FALSE; |
| prScanInfo->fgIsScanRequest = FALSE; |
| |
| mboxSendMsg(prAdapter, |
| MBOX_ID_0, |
| (struct MSG_HDR *) prScanCancelMsg, |
| MSG_SEND_METHOD_BUF); |
| } while (FALSE); |
| } /* p2pFuncCancelScan */ |
| |
| void p2pFuncGCJoin(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN struct P2P_JOIN_INFO *prP2pJoinInfo) |
| { |
| struct MSG_SAA_FSM_START *prJoinReqMsg = |
| (struct MSG_SAA_FSM_START *) NULL; |
| struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; |
| struct BSS_DESC *prBssDesc = (struct BSS_DESC *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prP2pBssInfo != NULL) |
| && (prP2pJoinInfo != NULL)); |
| |
| prBssDesc = prP2pJoinInfo->prTargetBssDesc; |
| if ((prBssDesc) == NULL) { |
| DBGLOG(P2P, ERROR, |
| "p2pFuncGCJoin: NO Target BSS Descriptor\n"); |
| ASSERT(FALSE); |
| break; |
| } |
| |
| if (prBssDesc->ucSSIDLen) { |
| COPY_SSID(prP2pBssInfo->aucSSID, |
| prP2pBssInfo->ucSSIDLen, |
| prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen); |
| } |
| |
| /* 2 <1> We are goin to connect to this BSS */ |
| prBssDesc->fgIsConnecting = TRUE; |
| |
| /* 2 <2> Setup corresponding STA_RECORD_T */ |
| prStaRec = bssCreateStaRecFromBssDesc(prAdapter, |
| (prBssDesc->fgIsP2PPresent |
| ? (STA_TYPE_P2P_GO) |
| : (STA_TYPE_LEGACY_AP)), |
| prP2pBssInfo->ucBssIndex, prBssDesc); |
| |
| if (prStaRec == NULL) { |
| DBGLOG(P2P, TRACE, "Create station record fail\n"); |
| ASSERT(FALSE); |
| break; |
| } |
| |
| prP2pJoinInfo->prTargetStaRec = prStaRec; |
| prP2pJoinInfo->fgIsJoinComplete = FALSE; |
| prP2pJoinInfo->u4BufLength = 0; |
| |
| /* 2 <2.1> Sync. to FW domain */ |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); |
| |
| if (prP2pBssInfo->eConnectionState |
| == PARAM_MEDIA_STATE_DISCONNECTED) { |
| prStaRec->fgIsReAssoc = FALSE; |
| prP2pJoinInfo->ucAvailableAuthTypes = |
| (uint8_t) AUTH_TYPE_OPEN_SYSTEM; |
| prStaRec->ucTxAuthAssocRetryLimit = |
| TX_AUTH_ASSOCI_RETRY_LIMIT; |
| } else { |
| DBGLOG(P2P, ERROR, |
| "JOIN INIT: Join Request when connected.\n"); |
| /* TODO: Shall we considering ROAMIN case |
| * for P2P Device?. |
| */ |
| break; |
| } |
| |
| /* 2 <4> Use an appropriate Authentication Algorithm Number |
| * among the ucAvailableAuthTypes. |
| */ |
| if (prP2pJoinInfo->ucAvailableAuthTypes |
| & (uint8_t) AUTH_TYPE_OPEN_SYSTEM) { |
| |
| DBGLOG(P2P, TRACE, |
| "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); |
| |
| prP2pJoinInfo->ucAvailableAuthTypes &= |
| ~(uint8_t) AUTH_TYPE_OPEN_SYSTEM; |
| |
| prStaRec->ucAuthAlgNum = |
| (uint8_t) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; |
| } else { |
| DBGLOG(P2P, ERROR, |
| "JOIN INIT: ucAvailableAuthTypes Error.\n"); |
| ASSERT(FALSE); |
| break; |
| } |
| |
| /* 4 <5> Overwrite Connection Setting |
| * for eConnectionPolicy == ANY (Used by Assoc Req) |
| */ |
| |
| /* 2 <5> Backup desired channel. */ |
| |
| /* 2 <6> Send a Msg to trigger SAA to start JOIN process. */ |
| prJoinReqMsg = (struct MSG_SAA_FSM_START *) |
| cnmMemAlloc(prAdapter, |
| RAM_TYPE_MSG, sizeof(struct MSG_SAA_FSM_START)); |
| |
| if (!prJoinReqMsg) { |
| DBGLOG(P2P, TRACE, "Allocation Join Message Fail\n"); |
| ASSERT(FALSE); |
| return; |
| } |
| |
| prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; |
| prJoinReqMsg->ucSeqNum = ++prP2pJoinInfo->ucSeqNumOfReqMsg; |
| prJoinReqMsg->prStaRec = prStaRec; |
| |
| /* TODO: Consider fragmentation info in station record. */ |
| |
| mboxSendMsg(prAdapter, |
| MBOX_ID_0, |
| (struct MSG_HDR *) prJoinReqMsg, |
| MSG_SEND_METHOD_BUF); |
| |
| } while (FALSE); |
| |
| } /* p2pFuncGCJoin */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will update the contain of BSS_INFO_T |
| * for AIS network once the association was completed. |
| * |
| * @param[in] prStaRec Pointer to the STA_RECORD_T |
| * @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. |
| * |
| * @return (none) |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void |
| p2pFuncUpdateBssInfoForJOIN(IN struct ADAPTER *prAdapter, |
| IN struct BSS_DESC *prBssDesc, |
| IN struct STA_RECORD *prStaRec, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN struct SW_RFB *prAssocRspSwRfb) |
| { |
| struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = |
| (struct WLAN_ASSOC_RSP_FRAME *) NULL; |
| uint16_t u2IELength; |
| uint8_t *pucIE; |
| |
| DEBUGFUNC("p2pUpdateBssInfoForJOIN()"); |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prStaRec != NULL) |
| && (prP2pBssInfo != NULL) |
| && (prAssocRspSwRfb != NULL)); |
| |
| prAssocRspFrame = (struct WLAN_ASSOC_RSP_FRAME *) |
| prAssocRspSwRfb->pvHeader; |
| |
| if (prBssDesc == NULL) { |
| /* Target BSS NULL. */ |
| DBGLOG(P2P, TRACE, "Target BSS NULL\n"); |
| break; |
| } |
| |
| DBGLOG(P2P, INFO, |
| "Update P2P_BSS_INFO_T and apply settings to MAC\n"); |
| |
| /* 3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T |
| * or User Settings |
| */ |
| /* 4 <1.1> Setup Operation Mode */ |
| ASSERT_BREAK(prP2pBssInfo->eCurrentOPMode |
| == OP_MODE_INFRASTRUCTURE); |
| |
| if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, |
| prAssocRspFrame->aucBSSID)) |
| ASSERT(FALSE); |
| /* 4 <1.2> Setup SSID */ |
| COPY_SSID(prP2pBssInfo->aucSSID, |
| prP2pBssInfo->ucSSIDLen, |
| prBssDesc->aucSSID, |
| prBssDesc->ucSSIDLen); |
| |
| /* 4 <1.3> Setup Channel, Band */ |
| prP2pBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; |
| prP2pBssInfo->eBand = prBssDesc->eBand; |
| |
| /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ |
| /* 4 <2.1> Save current AP's STA_RECORD_T and current AID */ |
| prP2pBssInfo->prStaRecOfAP = prStaRec; |
| prP2pBssInfo->u2AssocId = prStaRec->u2AssocId; |
| |
| /* 4 <2.2> Setup Capability */ |
| /* Use AP's Cap Info as BSS Cap Info */ |
| prP2pBssInfo->u2CapInfo = prStaRec->u2CapInfo; |
| |
| if (prP2pBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) |
| prP2pBssInfo->fgIsShortPreambleAllowed = TRUE; |
| else |
| prP2pBssInfo->fgIsShortPreambleAllowed = FALSE; |
| |
| /* 4 <2.3> Setup PHY Attributes and |
| * Basic Rate Set/Operational Rate Set |
| */ |
| prP2pBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; |
| |
| prP2pBssInfo->ucNonHTBasicPhyType = |
| prStaRec->ucNonHTBasicPhyType; |
| |
| prP2pBssInfo->u2OperationalRateSet = |
| prStaRec->u2OperationalRateSet; |
| prP2pBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; |
| |
| nicTxUpdateBssDefaultRate(prP2pBssInfo); |
| |
| /* 3 <3> Update BSS_INFO_T from SW_RFB_T |
| * (Association Resp Frame) |
| */ |
| /* 4 <3.1> Setup BSSID */ |
| COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, |
| prAssocRspFrame->aucBSSID); |
| |
| u2IELength = |
| (uint16_t) ((prAssocRspSwRfb->u2PacketLen - |
| prAssocRspSwRfb->u2HeaderLen) - |
| (OFFSET_OF(struct WLAN_ASSOC_RSP_FRAME, |
| aucInfoElem[0]) - |
| WLAN_MAC_MGMT_HEADER_LEN)); |
| |
| pucIE = prAssocRspFrame->aucInfoElem; |
| |
| /* 4 <3.2> Parse WMM and setup QBSS flag */ |
| /* Parse WMM related IEs and configure HW CRs accordingly */ |
| mqmProcessAssocRsp(prAdapter, |
| prAssocRspSwRfb, pucIE, u2IELength); |
| |
| prP2pBssInfo->fgIsQBSS = prStaRec->fgIsQoS; |
| |
| /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ |
| |
| prBssDesc->fgIsConnecting = FALSE; |
| prBssDesc->fgIsConnected = TRUE; |
| |
| /* 4 <4.1> Setup MIB for current BSS */ |
| prP2pBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; |
| /* NOTE: Defer ucDTIMPeriod updating to |
| * when beacon is received after connection |
| */ |
| prP2pBssInfo->ucDTIMPeriod = 0; |
| prP2pBssInfo->u2ATIMWindow = 0; |
| |
| prP2pBssInfo->ucBeaconTimeoutCount = |
| AIS_BEACON_TIMEOUT_COUNT_INFRA; |
| |
| /* 4 <4.2> Update HT information and set channel */ |
| /* Record HT related parameters in rStaRec and rBssInfo |
| * Note: it shall be called before nicUpdateBss() |
| */ |
| rlmProcessAssocRsp(prAdapter, |
| prAssocRspSwRfb, pucIE, u2IELength); |
| |
| /* 4 <4.3> Sync with firmware for BSS-INFO */ |
| nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); |
| |
| /* 4 <4.4> *DEFER OPERATION* |
| * nicPmIndicateBssConnected() will be invoked |
| * inside scanProcessBeaconAndProbeResp() |
| * after 1st beacon is received |
| */ |
| |
| } while (FALSE); |
| } /* end of p2pUpdateBssInfoForJOIN() */ |
| |
| uint32_t |
| p2pFunMgmtFrameTxDone(IN struct ADAPTER *prAdapter, |
| IN struct MSDU_INFO *prMsduInfo, |
| IN enum ENUM_TX_RESULT_CODE rTxDoneStatus) |
| { |
| u_int8_t fgIsSuccess = FALSE; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); |
| |
| if (rTxDoneStatus != TX_RESULT_SUCCESS) { |
| DBGLOG(P2P, TRACE, |
| "Mgmt Frame TX Fail, Status:%d.\n", |
| rTxDoneStatus); |
| } else { |
| fgIsSuccess = TRUE; |
| DBGLOG(P2P, TRACE, "Mgmt Frame TX Done.\n"); |
| } |
| |
| kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, |
| prMsduInfo, fgIsSuccess); |
| |
| } while (FALSE); |
| |
| return WLAN_STATUS_SUCCESS; |
| |
| } /* p2pFunMgmtFrameTxDone */ |
| const char * |
| p2pToString(enum p2p_action_frame_type eP2pAction) |
| { |
| switch (eP2pAction) { |
| case P2P_GO_NEG_REQ: |
| return "GO_NEG_REQ"; |
| case P2P_GO_NEG_RESP: |
| return "GO_NEG_RESP"; |
| case P2P_GO_NEG_CONF: |
| return "GO_NEG_CONF"; |
| case P2P_INVITATION_REQ: |
| return "INVITATION_REQ"; |
| case P2P_INVITATION_RESP: |
| return "INVITATION_RESP"; |
| case P2P_DEV_DISC_REQ: |
| return "DEV_DISC_REQ"; |
| case P2P_DEV_DISC_RESP: |
| return "DEV_DISC_RESP"; |
| case P2P_PROV_DISC_REQ: |
| return "PROV_DISC_REQ"; |
| case P2P_PROV_DISC_RESP: |
| return "PROV_DISC_RESP"; |
| } |
| |
| return "UNKNOWN P2P Public Action"; |
| } |
| |
| |
| const char * |
| paToString(int32_t u4PaAction) |
| { |
| switch (u4PaAction) { |
| case WLAN_PA_20_40_BSS_COEX: |
| return "PA_20_40_BSS_COEX"; |
| case WLAN_PA_VENDOR_SPECIFIC: |
| return "PA_VENDOR_SPECIFIC"; |
| case WLAN_PA_GAS_INITIAL_REQ: |
| return "PA_GAS_INITIAL_REQ"; |
| case WLAN_PA_GAS_INITIAL_RESP: |
| return "PA_GAS_INITIAL_RESP"; |
| case WLAN_PA_GAS_COMEBACK_REQ: |
| return "PA_GAS_COMEBACK_REQ"; |
| case WLAN_PA_GAS_COMEBACK_RESP: |
| return "PA_GAS_COMEBACK_RESP"; |
| case WLAN_TDLS_DISCOVERY_RESPONSE: |
| return "TDLS_DISCOVERY_RESPONSE"; |
| } |
| |
| return "UNKNOWN Public Action"; |
| } |
| |
| |
| const char * |
| actionToString(int32_t u4WlanAction) |
| { |
| switch (u4WlanAction) { |
| case WLAN_ACTION_SPECTRUM_MGMT: |
| return "SPECTRUM_MGMT"; |
| case WLAN_ACTION_QOS: |
| return "QOS"; |
| case WLAN_ACTION_DLS: |
| return "DLS"; |
| case WLAN_ACTION_BLOCK_ACK: |
| return "BLOCK_ACK"; |
| case WLAN_ACTION_PUBLIC: |
| return "PUBLIC"; |
| case WLAN_ACTION_RADIO_MEASUREMENT: |
| return "RADIO_MEASUREMENT"; |
| case WLAN_ACTION_FT: |
| return "FT"; |
| case WLAN_ACTION_HT: |
| return "HT"; |
| case WLAN_ACTION_SA_QUERY: |
| return "SA_QUERY"; |
| case WLAN_ACTION_PROTECTED_DUAL: |
| return "PROTECTED_DUAL"; |
| case WLAN_ACTION_WNM: |
| return "WNM"; |
| case WLAN_ACTION_UNPROTECTED_WNM: |
| return "UNPROTECTED_WNM"; |
| case WLAN_ACTION_TDLS: |
| return "TDLS"; |
| case WLAN_ACTION_SELF_PROTECTED: |
| return "SELF_PROTECTED"; |
| case WLAN_ACTION_WMM: |
| return "WMM"; |
| case WLAN_ACTION_VENDOR_SPECIFIC: |
| return "VENDOR_SPECIFIC"; |
| } |
| |
| return "UNKNOWN Action Frame"; |
| } |
| |
| |
| enum ENUM_P2P_CONNECT_STATE |
| p2pFuncTagActionActionP2PFrame(IN struct MSDU_INFO *prMgmtTxMsdu, |
| IN struct WLAN_ACTION_FRAME *prActFrame, |
| IN uint8_t ucP2pAction, IN uint64_t u8Cookie) |
| { |
| DBGLOG(P2P, INFO, |
| "Found P2P_%s, SA: " MACSTR |
| " - DA: " MACSTR ", cookie: 0x%llx, SeqNO: %d\n", |
| p2pToString(ucP2pAction), |
| MAC2STR(prActFrame->aucSrcAddr), |
| MAC2STR(prActFrame->aucDestAddr), |
| u8Cookie, |
| prMgmtTxMsdu->ucTxSeqNum); |
| return ucP2pAction + 1; |
| } |
| |
| |
| enum ENUM_P2P_CONNECT_STATE |
| p2pFuncTagActionActionFrame(IN struct MSDU_INFO *prMgmtTxMsdu, |
| IN struct WLAN_ACTION_FRAME *prActFrame, |
| IN uint8_t ucAction, IN uint64_t u8Cookie) |
| { |
| uint8_t *pucVendor = NULL; |
| enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; |
| |
| DBGLOG(P2P, INFO, |
| "Found WLAN_%s, SA: " MACSTR |
| " - DA: " MACSTR ", cookie: 0x%llx, SeqNo: %d\n", |
| paToString(ucAction), |
| MAC2STR(prActFrame->aucSrcAddr), |
| MAC2STR(prActFrame->aucDestAddr), |
| u8Cookie, |
| prMgmtTxMsdu->ucTxSeqNum); |
| |
| if (ucAction != WLAN_PA_VENDOR_SPECIFIC) |
| return P2P_CNN_NORMAL; |
| |
| pucVendor = (uint8_t *)prActFrame + 26; |
| if (*(pucVendor + 0) == 0x50 && |
| *(pucVendor + 1) == 0x6f && |
| *(pucVendor + 2) == 0x9a) { |
| if (*(pucVendor + 3) == 0x09) |
| /* found p2p IE */ |
| eCNNState = p2pFuncTagActionActionP2PFrame(prMgmtTxMsdu, |
| prActFrame, *(pucVendor + 4), u8Cookie); |
| else if (*(pucVendor + 3) == 0x0a) |
| /* found WFD IE */ |
| DBGLOG(P2P, INFO, "Found WFD IE, SA: " MACSTR |
| " - DA: " MACSTR "\n", |
| MAC2STR(prActFrame->aucSrcAddr), |
| MAC2STR(prActFrame->aucDestAddr)); |
| else |
| DBGLOG(P2P, INFO, |
| "Found Other vendor 0x%x, SA: " MACSTR |
| " - DA: " MACSTR "\n", |
| *(pucVendor + 3), |
| MAC2STR(prActFrame->aucSrcAddr), |
| MAC2STR(prActFrame->aucDestAddr)); |
| } |
| return eCNNState; |
| } |
| |
| enum ENUM_P2P_CONNECT_STATE |
| p2pFuncTagActionCategoryFrame(IN struct MSDU_INFO *prMgmtTxMsdu, |
| struct WLAN_ACTION_FRAME *prActFrame, |
| IN uint8_t ucCategory, |
| IN uint64_t u8Cookie) |
| { |
| |
| uint8_t ucAction = 0; |
| enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; |
| |
| DBGLOG(P2P, TRACE, |
| "Found WLAN_ACTION_%s, SA: " MACSTR |
| " BSSID: " MACSTR |
| " DA: " MACSTR ", u8Cookie: 0x%llx, SeqNO: %d\n", |
| actionToString(ucCategory), |
| MAC2STR(prActFrame->aucSrcAddr), |
| MAC2STR(prActFrame->aucBSSID), |
| MAC2STR(prActFrame->aucDestAddr), |
| u8Cookie, |
| prMgmtTxMsdu->ucTxSeqNum); |
| |
| if (ucCategory == WLAN_ACTION_PUBLIC) { |
| ucAction = prActFrame->ucAction; |
| eCNNState = p2pFuncTagActionActionFrame(prMgmtTxMsdu, |
| prActFrame, ucAction, u8Cookie); |
| } |
| return eCNNState; |
| } |
| |
| void p2pProcessActionResponse(IN struct ADAPTER *prAdapter, |
| enum p2p_action_frame_type eType) |
| { |
| u_int8_t fgIdle = FALSE; |
| |
| if (!prAdapter || !prAdapter->prP2pInfo) |
| return; |
| |
| switch (prAdapter->prP2pInfo->eConnState) { |
| case P2P_CNN_GO_NEG_REQ: |
| if (eType == P2P_GO_NEG_RESP) |
| fgIdle = TRUE; |
| break; |
| case P2P_CNN_GO_NEG_RESP: |
| if (eType == P2P_GO_NEG_CONF || eType == P2P_GO_NEG_REQ) |
| fgIdle = TRUE; |
| break; |
| case P2P_CNN_INVITATION_REQ: |
| if (eType == P2P_INVITATION_RESP) |
| fgIdle = TRUE; |
| break; |
| case P2P_CNN_DEV_DISC_REQ: |
| if (eType == P2P_DEV_DISC_RESP) |
| fgIdle = TRUE; |
| break; |
| case P2P_CNN_PROV_DISC_REQ: |
| if (eType == P2P_PROV_DISC_RESP) |
| fgIdle = TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| DBGLOG(P2P, INFO, |
| "eConnState: %d, eType: %d\n", |
| prAdapter->prP2pInfo->eConnState, eType); |
| |
| if (fgIdle) |
| prAdapter->prP2pInfo->eConnState = P2P_CNN_NORMAL; |
| } |
| |
| /* |
| * used to debug p2p mgmt frame: |
| * GO Nego Req |
| * GO Nego Res |
| * GO Nego Confirm |
| * GO Invite Req |
| * GO Invite Res |
| * Device Discoverability Req |
| * Device Discoverability Res |
| * Provision Discovery Req |
| * Provision Discovery Res |
| */ |
| |
| enum ENUM_P2P_CONNECT_STATE |
| p2pFuncTagMgmtFrame(IN struct MSDU_INFO *prMgmtTxMsdu, |
| IN uint64_t u8Cookie) |
| { |
| /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ |
| struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; |
| struct WLAN_BEACON_FRAME *prProbRspHdr = |
| (struct WLAN_BEACON_FRAME *)NULL; |
| uint16_t u2TxFrameCtrl; |
| struct WLAN_ACTION_FRAME *prActFrame; |
| uint8_t ucCategory; |
| enum ENUM_P2P_CONNECT_STATE eCNNState = P2P_CNN_NORMAL; |
| |
| prWlanHdr = (struct WLAN_MAC_HEADER *) |
| ((unsigned long) prMgmtTxMsdu->prPacket + |
| MAC_TX_RESERVED_FIELD); |
| /* |
| * mgmt frame MASK_FC_TYPE = 0 |
| * use MASK_FRAME_TYPE is oK for frame type/subtype judge |
| */ |
| u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; |
| |
| switch (u2TxFrameCtrl) { |
| case MAC_FRAME_PROBE_RSP: |
| prProbRspHdr = (struct WLAN_BEACON_FRAME *) prWlanHdr; |
| DBGLOG(P2P, INFO, |
| "TX Probe Response, SA: " MACSTR |
| " BSSID: " MACSTR |
| " DA: " MACSTR ", cookie: 0x%llx, seqNo: %d\n", |
| MAC2STR(prProbRspHdr->aucSrcAddr), |
| MAC2STR(prProbRspHdr->aucBSSID), |
| MAC2STR(prProbRspHdr->aucDestAddr), |
| u8Cookie, |
| prMgmtTxMsdu->ucTxSeqNum); |
| |
| break; |
| |
| case MAC_FRAME_ACTION: |
| prActFrame = (struct WLAN_ACTION_FRAME *)prWlanHdr; |
| ucCategory = prActFrame->ucCategory; |
| eCNNState = p2pFuncTagActionCategoryFrame(prMgmtTxMsdu, |
| prActFrame, ucCategory, u8Cookie); |
| |
| break; |
| default: |
| DBGLOG(P2P, INFO, |
| "Untagged frame type: 0x%x, A1: " MACSTR |
| ", A2: " MACSTR |
| ", A3: " MACSTR " seqNo: %d\n", |
| u2TxFrameCtrl, |
| MAC2STR(prWlanHdr->aucAddr1), |
| MAC2STR(prWlanHdr->aucAddr2), |
| MAC2STR(prWlanHdr->aucAddr3), |
| prMgmtTxMsdu->ucTxSeqNum); |
| break; |
| } |
| return eCNNState; |
| } |
| |
| uint32_t |
| p2pFuncTxMgmtFrame(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN struct MSDU_INFO *prMgmtTxMsdu, |
| IN u_int8_t fgNonCckRate) |
| { |
| uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; |
| /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ |
| struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; |
| struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; |
| uint8_t ucRetryLimit = 30; /* TX_DESC_TX_COUNT_NO_LIMIT; */ |
| u_int8_t fgDrop = FALSE; |
| struct BSS_INFO *prBssInfo; |
| uint64_t *pu8GlCookie = (uint64_t *) NULL; |
| uint64_t u8GlCookie; |
| |
| do { |
| ASSERT_BREAK(prAdapter != NULL); |
| |
| /* Drop this frame if BSS inactive */ |
| if (!IS_NET_ACTIVE(prAdapter, ucBssIndex)) { |
| p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, |
| prMgmtTxMsdu, TX_RESULT_INACTIVE_BSS); |
| cnmMgtPktFree(prAdapter, prMgmtTxMsdu); |
| fgDrop = TRUE; |
| break; |
| } |
| pu8GlCookie = |
| (uint64_t *) ((unsigned long) prMgmtTxMsdu->prPacket + |
| (unsigned long) prMgmtTxMsdu->u2FrameLength + |
| MAC_TX_RESERVED_FIELD); |
| |
| u8GlCookie = *pu8GlCookie; |
| |
| prWlanHdr = (struct WLAN_MAC_HEADER *) |
| ((unsigned long) prMgmtTxMsdu->prPacket + |
| MAC_TX_RESERVED_FIELD); |
| prStaRec = cnmGetStaRecByAddress(prAdapter, |
| ucBssIndex, prWlanHdr->aucAddr1); |
| /* prMgmtTxMsdu->ucBssIndex = ucBssIndex; */ |
| |
| switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { |
| case MAC_FRAME_PROBE_RSP: |
| DBGLOG(P2P, TRACE, "TX Probe Resposne Frame\n"); |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, |
| ucBssIndex); |
| if ((!nicTxIsMgmtResourceEnough(prAdapter)) |
| || (prBssInfo->fgIsNetAbsent)) { |
| DBGLOG(P2P, INFO, |
| "Drop Tx probe response due to resource issue\n"); |
| fgDrop = TRUE; |
| |
| break; |
| } |
| prMgmtTxMsdu->ucStaRecIndex = |
| (prStaRec != NULL) |
| ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND); |
| /* Modifiy Lie time to 100 mS due |
| * to the STA only wait 30-50mS |
| */ |
| /* and AP do not need send it after STA left */ |
| nicTxSetPktLifeTime(prMgmtTxMsdu, 100); |
| prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, |
| ucBssIndex, prMgmtTxMsdu); |
| |
| /* |
| * Not check prMsduInfo sanity |
| * as p2pFuncProcessP2pProbeRsp will always |
| * return a MsduInfo |
| */ |
| pu8GlCookie = |
| (uint64_t *) ((unsigned long) |
| prMgmtTxMsdu->prPacket + |
| (unsigned long) |
| prMgmtTxMsdu->u2FrameLength + |
| MAC_TX_RESERVED_FIELD); |
| /* Restore cookie as it will be corrupted |
| * in p2pFuncProcessP2pProbeRsp |
| */ |
| *pu8GlCookie = u8GlCookie; |
| ucRetryLimit = 6; |
| break; |
| default: |
| prMgmtTxMsdu->ucBssIndex = ucBssIndex; |
| break; |
| } |
| |
| if (fgDrop) { |
| /* Drop this frame */ |
| p2pDevFsmRunEventMgmtFrameTxDone(prAdapter, |
| prMgmtTxMsdu, TX_RESULT_DROPPED_IN_DRIVER); |
| cnmMgtPktFree(prAdapter, prMgmtTxMsdu); |
| |
| break; |
| } |
| |
| TX_SET_MMPDU(prAdapter, |
| prMgmtTxMsdu, |
| prMgmtTxMsdu->ucBssIndex, |
| (prStaRec != NULL) |
| ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), |
| WLAN_MAC_MGMT_HEADER_LEN, |
| prMgmtTxMsdu->u2FrameLength, |
| p2pDevFsmRunEventMgmtFrameTxDone, |
| MSDU_RATE_MODE_AUTO); |
| |
| nicTxSetPktRetryLimit(prMgmtTxMsdu, ucRetryLimit); |
| |
| /* Bufferable MMPDUs are suggested to be queued */ |
| /* when GC is sleeping according to SPEC, */ |
| /* instead of being sent to ALTX Q. */ |
| |
| /* GO discoverability REQ needs to be sent to GC */ |
| /* when GC is awake due to P2P-6.1.10 cert fail */ |
| if (!p2pFuncIsBufferableMMPDU(prMgmtTxMsdu)) { |
| nicTxConfigPktControlFlag(prMgmtTxMsdu, |
| MSDU_CONTROL_FLAG_FORCE_TX, TRUE); |
| } |
| |
| prAdapter->prP2pInfo->eConnState = |
| p2pFuncTagMgmtFrame(prMgmtTxMsdu, u8GlCookie); |
| |
| nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); |
| |
| |
| } while (FALSE); |
| |
| return rWlanStatus; |
| } /* p2pFuncTxMgmtFrame */ |
| |
| void p2pFuncStopComplete(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo) |
| { |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); |
| |
| DBGLOG(P2P, TRACE, "p2pFuncStopComplete\n"); |
| |
| /* GO: It would stop Beacon TX. |
| * GC: Stop all BSS related PS function. |
| */ |
| nicPmIndicateBssAbort(prAdapter, prP2pBssInfo->ucBssIndex); |
| /* Reset RLM related field of BSSINFO. */ |
| rlmBssAborted(prAdapter, prP2pBssInfo); |
| |
| UNSET_NET_ACTIVE(prAdapter, prP2pBssInfo->ucBssIndex); |
| nicDeactivateNetwork(prAdapter, prP2pBssInfo->ucBssIndex); |
| /* Release CNM channel */ |
| nicUpdateBss(prAdapter, prP2pBssInfo->ucBssIndex); |
| |
| /* Reset current OPMode */ |
| prP2pBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; |
| |
| /* Point StaRecOfAP to NULL when GC role stop Complete */ |
| prP2pBssInfo->prStaRecOfAP = NULL; |
| } while (FALSE); |
| |
| } /* p2pFuncStopComplete */ |
| #if IS_ENABLED(CFG_CCN7_SAP_EASYMESH) |
| static void p2pFunBssStatusNotification(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prBssInfo) |
| { |
| struct T_MULTI_AP_BSS_STATUS_REPORT *prBssReport; |
| struct PARAM_CUSTOM_GET_TX_POWER rGetTxPower; |
| bool fgSGIEnable = false; |
| uint8_t ucMaxBw = 0; |
| uint8_t ucNss = 0; |
| uint8_t ucNssLoop = 0; |
| uint8_t ucOffset = 0; |
| uint8_t ucMcsMap = 0; |
| int32_t i4Ret = 0; |
| |
| fgSGIEnable = IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucRxShortGI); |
| ucMaxBw = cnmGetBssMaxBw(prAdapter, prBssInfo->ucBssIndex); |
| ucNss = wlanGetSupportNss(prAdapter, prBssInfo->ucBssIndex); |
| |
| prBssReport = kalMemAlloc(sizeof(*prBssReport), VIR_MEM_TYPE); |
| if (!prBssReport) { |
| DBGLOG(AAA, ERROR, "mem alloc fail\n"); |
| return; |
| } |
| |
| kalMemZero(prBssReport, sizeof(*prBssReport)); |
| /* Interface Index */ |
| i4Ret = sscanf(prAdapter->prGlueInfo->prP2PInfo[1]->prDevHandler->name, |
| "ap%u", &prBssReport->uIfIndex); |
| if (i4Ret != 1) |
| DBGLOG(P2P, WARN, "read sap index fail: %d\n", i4Ret); |
| |
| /* Bssid */ |
| COPY_MAC_ADDR(prBssReport->mBssid, prBssInfo->aucBSSID); |
| /* Status */ |
| prBssReport->uStatus = prBssInfo->fgIsInUse; |
| /* Channel */ |
| prBssReport->u8Channel = prBssInfo->ucPrimaryChannel; |
| /* Operation Class Table E-4 in IEEE802.11-2016. */ |
| if (prBssInfo->ucPrimaryChannel < 14) |
| prBssReport->u8OperClass = 81; |
| else if (prBssInfo->ucPrimaryChannel >= 36 |
| && prBssInfo->ucPrimaryChannel <= 48) |
| prBssReport->u8OperClass = 115; |
| else if (prBssInfo->ucPrimaryChannel >= 52 |
| && prBssInfo->ucPrimaryChannel <= 64) |
| prBssReport->u8OperClass = 118; |
| else if (prBssInfo->ucPrimaryChannel >= 149 |
| && prBssInfo->ucPrimaryChannel <= 161) |
| prBssReport->u8OperClass = 124; |
| else |
| DBGLOG(P2P, WARN, |
| "unknown CH %d for op-class\n", |
| prBssInfo->ucPrimaryChannel); |
| /* TX Power */ |
| /* |
| * THIS/CMD are both running in main_thread. |
| * Cannot get result by this CMD |
| */ |
| kalMemZero(&rGetTxPower, sizeof(struct PARAM_CUSTOM_GET_TX_POWER)); |
| rGetTxPower.ucCenterChannel = prBssInfo->ucPrimaryChannel; |
| rGetTxPower.ucBand = prBssInfo->eBand; |
| rGetTxPower.ucDbdcIdx = ENUM_BAND_0; |
| prBssReport->u8Txpower = prAdapter->u4GetTxPower/2; |
| /* Band */ |
| prBssReport->uBand = prBssInfo->eBand; |
| /* HT Capability */ |
| if (RLM_NET_IS_11N(prBssInfo)) { |
| prBssReport->uHtCap = ( |
| (ucNss << SAP_HTCAP_TXSTREAMNUM_OFFSET) | |
| (ucNss << SAP_HTCAP_RXSTREAMNUM_OFFSET) | |
| (fgSGIEnable << SAP_HTCAP_SGIFOR20M_OFFSET) | |
| ((prBssInfo->fgAssoc40mBwAllowed |
| ? fgSGIEnable : 0) |
| << SAP_HTCAP_SGIFOR40M_OFFSET) | |
| ((prBssInfo->fgAssoc40mBwAllowed ? 1 : 0) |
| << SAP_HTCAP_HTFOR40M_OFFSET) |
| ); |
| } |
| /* VHT Capability */ |
| if (RLM_NET_IS_11AC(prBssInfo)) { |
| for (ucNssLoop = 1; ucNssLoop <= 8; ucNssLoop++) { |
| ucOffset = (ucNssLoop - 1) * 2; |
| ucMcsMap = (ucNssLoop <= |
| ucNss ? VHT_CAP_INFO_MCS_MAP_MCS9 |
| : VHT_CAP_INFO_MCS_NOT_SUPPORTED); |
| prBssReport->u16VhtTxMcs |= |
| (ucMcsMap << ucOffset); |
| prBssReport->u16VhtRxMcs |= |
| (ucMcsMap << ucOffset); |
| } |
| prBssReport->u16VhtCap = ( |
| (ucNss << SAP_VHTCAP_TXSTREAMNUM_OFFSET) | |
| (ucNss << SAP_VHTCAP_RXSTREAMNUM_OFFSET) | |
| ((ucMaxBw >= MAX_BW_80MHZ ? fgSGIEnable : 0) |
| << SAP_VHTCAP_SGIFOR80M_OFFSET) | |
| ((ucMaxBw >= MAX_BW_160MHZ ? fgSGIEnable : 0) |
| << SAP_VHTCAP_SGIFOR160M_OFFSET) | |
| ((ucMaxBw == MAX_BW_80_80_MHZ) |
| << SAP_VHTCAP_VHTFORDUAL80M_OFFSET) | |
| ((ucMaxBw == MAX_BW_160MHZ) |
| << SAP_VHTCAP_VHTFOR160M_OFFSET) | |
| (IS_FEATURE_ENABLED( |
| prAdapter->rWifiVar.ucStaVhtBfer) |
| << SAP_VHTCAP_SUBEAMFORMER_OFFSET) | |
| (0 << SAP_VHTCAP_MUBEAMFORMER_OFFSET) |
| ); |
| } |
| /* HE Capability (not support) */ |
| prBssReport->u8HeMcsNum = 0; |
| kalMemZero(&prBssReport->u8HeMcs, 16); |
| kalMemZero(&prBssReport->u16HeCap, sizeof(uint16_t)); |
| |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] uIfIndex=%d\n", prBssReport->uIfIndex); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] mBssid=" MACSTR "\n", MAC2STR(prBssReport->mBssid)); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] uStatus=%d\n", prBssReport->uStatus); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u8Channel=%d\n", prBssReport->u8Channel); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u8OperClass=%d\n", prBssReport->u8OperClass); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u8Txpower=%d\n", prBssReport->u8Txpower); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] uBand=%d\n", prBssReport->uBand); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] uHtCap=0x%x\n", prBssReport->uHtCap); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u16VhtTxMcs=0x%x\n", prBssReport->u16VhtTxMcs); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u16VhtRxMcs=0x%x\n", prBssReport->u16VhtRxMcs); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u16VhtCap=0x%x\n", prBssReport->u16VhtCap); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u8HeMcsNum=%d\n", prBssReport->u8HeMcsNum); |
| DBGLOG_MEM8(P2P, WARN, prBssReport->u8HeMcs, 16); |
| DBGLOG(P2P, WARN, |
| "[SAP_Test] u16HeCap=0x%x\n", prBssReport->u16HeCap); |
| |
| i4Ret = MontorSendMsg(EV_WLAN_MULTIAP_BSS_STATUS_REPORT, |
| prBssReport, sizeof(*prBssReport)); |
| if (i4Ret < 0) |
| DBGLOG(AAA, ERROR, |
| "EV_WLAN_MULTIAP_BSS_STATUS_REPORT nl send msg failed!\n"); |
| |
| kalMemFree(prBssReport, VIR_MEM_TYPE, sizeof(*prBssReport)); |
| } |
| #endif /* CFG_CCN7_SAP_EASYMESH */ |
| |
| void |
| p2pFuncParseWmmParam(struct AC_QUE_PARMS *prACQueParms, |
| uint8_t ucAC, |
| uint32_t u4Param) |
| { |
| uint8_t ucEn = |
| (u4Param & BIT(0)); |
| uint8_t ucAifs = |
| (u4Param & BITS(4, 7)) >> 4; |
| uint8_t ucCWmin = |
| (u4Param & BITS(8, 11)) >> 8; |
| uint8_t ucCWmax = |
| (u4Param & BITS(12, 15)) >> 12; |
| uint16_t u2Txop = |
| (u4Param & BITS(16, 31)) >> 16; |
| |
| if (!ucEn) |
| return; |
| |
| prACQueParms[ucAC].u2Aifsn = ucAifs; |
| prACQueParms[ucAC].u2CWmin = (1 << ucCWmin) - 1; |
| prACQueParms[ucAC].u2CWmax = (1 << ucCWmax) - 1; |
| prACQueParms[ucAC].u2TxopLimit = u2Txop; |
| |
| DBGLOG(WMM, TRACE, |
| "AC:%d AIFS:0x%X, CWmin:0x%X, CWmax;0x%X, TXOP:0x%X\n", |
| ucAC, |
| prACQueParms[ucAC].u2Aifsn, |
| prACQueParms[ucAC].u2CWmin, |
| prACQueParms[ucAC].u2CWmax, |
| prACQueParms[ucAC].u2TxopLimit); |
| } |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will start a P2P Group Owner and send Beacon Frames. |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void |
| p2pFuncStartGO(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prBssInfo, |
| IN struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo, |
| IN struct P2P_CHNL_REQ_INFO *prP2pChnlReqInfo) |
| { |
| #if (CFG_SUPPORT_DFS_MASTER == 1) |
| struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; |
| #endif |
| |
| #ifdef CFG_SUPPORT_P2P_OPEN_SECURITY |
| uint8_t fgIsOpenP2P = TRUE; |
| #else |
| uint8_t fgIsOpenP2P = FALSE; |
| #endif |
| |
| #ifdef CFG_SUPPORT_P2P_GO_11B_RATE |
| uint8_t fgIs11bRate = TRUE; |
| #else |
| uint8_t fgIs11bRate = FALSE; |
| #endif |
| |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); |
| |
| if (prBssInfo->ucBssIndex >= prAdapter->ucHwBssIdNum) { |
| DBGLOG(P2P, ERROR, |
| "P2P BSS exceed the number of P2P interface number."); |
| ASSERT(FALSE); |
| break; |
| } |
| |
| DBGLOG(P2P, TRACE, "p2pFuncStartGO:\n"); |
| |
| #if IS_ENABLED(CFG_CCN7_SAP_EASYMESH) |
| INIT_DELAYED_WORK( |
| &(prAdapter->prGlueInfo->rChanNoiseControlWork), |
| aaaChanNoiseInitWorkHandler); |
| INIT_DELAYED_WORK( |
| &(prAdapter->prGlueInfo->rChanNoiseGetInfoWork), |
| aaaChanNoiseCollectionWorkHandler); |
| #endif |
| |
| #if (CFG_SUPPORT_DFS_MASTER == 1) |
| prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, |
| sizeof(*prCmdRddOnOffCtrl)); |
| |
| if (!prCmdRddOnOffCtrl) { |
| ASSERT(FALSE); |
| break; |
| } |
| |
| prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; |
| |
| /* |
| * FIX ME: Mobile driver can't get correct band. |
| * There is only 5G in DFS channel, |
| * which is on band_0. So it assigned to ENUM_BAND_0 |
| * as temp solution. |
| * Remember to fix it when driver could get |
| * the correct band from firmware. |
| */ |
| prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncStartGO: Start TXQ - DFS ctrl: %.d\n", |
| prCmdRddOnOffCtrl->ucDfsCtrl); |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_RDD_ON_OFF_CTRL, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, |
| sizeof(*prCmdRddOnOffCtrl), |
| (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); |
| |
| cnmMemFree(prAdapter, prCmdRddOnOffCtrl); |
| #endif |
| |
| /* Re-start AP mode. */ |
| p2pFuncSwitchOPMode(prAdapter, |
| prBssInfo, prBssInfo->eIntendOPMode, FALSE); |
| |
| prBssInfo->eIntendOPMode = OP_MODE_NUM; |
| |
| /* 4 <1.1> Assign SSID */ |
| COPY_SSID(prBssInfo->aucSSID, |
| prBssInfo->ucSSIDLen, |
| prP2pConnReqInfo->rSsidStruct.aucSsid, |
| prP2pConnReqInfo->rSsidStruct.ucSsidLen); |
| |
| DBGLOG(P2P, TRACE, "GO SSID:%s\n", prBssInfo->aucSSID); |
| |
| /* 4 <1.2> Clear current AP's STA_RECORD_T and current AID */ |
| prBssInfo->prStaRecOfAP = (struct STA_RECORD *) NULL; |
| prBssInfo->u2AssocId = 0; |
| |
| /* 4 <1.3> Setup Channel, Band and Phy Attributes */ |
| prBssInfo->ucPrimaryChannel = prP2pChnlReqInfo->ucReqChnlNum; |
| prBssInfo->eBand = prP2pChnlReqInfo->eBand; |
| prBssInfo->eBssSCO = prP2pChnlReqInfo->eChnlSco; |
| |
| DBGLOG(P2P, TRACE, |
| "GO Channel:%d\n", |
| prBssInfo->ucPrimaryChannel); |
| |
| if (prBssInfo->eBand == BAND_5G) { |
| /* Depend on eBand */ |
| prBssInfo->ucPhyTypeSet = |
| (prAdapter->rWifiVar.ucAvailablePhyTypeSet |
| & PHY_TYPE_SET_802_11AN); |
| /* Depend on eCurrentOPMode and ucPhyTypeSet */ |
| prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; |
| } else if ((prP2pConnReqInfo->eConnRequest |
| == P2P_CONNECTION_TYPE_PURE_AP) || |
| fgIs11bRate) { |
| /* Depend on eBand */ |
| prBssInfo->ucPhyTypeSet = |
| (prAdapter->rWifiVar.ucAvailablePhyTypeSet |
| & PHY_TYPE_SET_802_11BGN); |
| /* Depend on eCurrentOPMode and ucPhyTypeSet */ |
| prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; |
| } else { |
| ASSERT(prP2pConnReqInfo->eConnRequest |
| == P2P_CONNECTION_TYPE_GO); |
| /* Depend on eBand */ |
| prBssInfo->ucPhyTypeSet = |
| (prAdapter->rWifiVar.ucAvailablePhyTypeSet |
| & PHY_TYPE_SET_802_11GN); |
| /* Depend on eCurrentOPMode and ucPhyTypeSet */ |
| prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; |
| } |
| |
| /* Overwrite BSS PHY type set by Feature Options */ |
| bssDetermineApBssInfoPhyTypeSet(prAdapter, |
| (prP2pConnReqInfo->eConnRequest == |
| P2P_CONNECTION_TYPE_PURE_AP) ? TRUE : FALSE, prBssInfo); |
| |
| prBssInfo->ucNonHTBasicPhyType = (uint8_t) |
| rNonHTApModeAttributes |
| [prBssInfo->ucConfigAdHocAPMode] |
| .ePhyTypeIndex; |
| prBssInfo->u2BSSBasicRateSet = |
| rNonHTApModeAttributes |
| [prBssInfo->ucConfigAdHocAPMode] |
| .u2BSSBasicRateSet; |
| prBssInfo->u2OperationalRateSet = |
| rNonHTPhyAttributes |
| [prBssInfo->ucNonHTBasicPhyType] |
| .u2SupportedRateSet; |
| |
| if ((prBssInfo->ucAllSupportedRatesLen == 0) |
| || fgIs11bRate) { |
| rateGetDataRatesFromRateSet( |
| prBssInfo->u2OperationalRateSet, |
| prBssInfo->u2BSSBasicRateSet, |
| prBssInfo->aucAllSupportedRates, |
| &prBssInfo->ucAllSupportedRatesLen); |
| } |
| /* 4 <1.5> Setup MIB for current BSS */ |
| prBssInfo->u2ATIMWindow = 0; |
| prBssInfo->ucBeaconTimeoutCount = 0; |
| |
| /* 3 <2> Update BSS_INFO_T common part */ |
| #if CFG_SUPPORT_AAA |
| prBssInfo->fgIsProtection = FALSE; |
| if (prP2pConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GO |
| && (!fgIsOpenP2P)) { |
| /* Always enable protection at P2P GO */ |
| prBssInfo->fgIsProtection = TRUE; |
| } else { |
| if (!fgIsOpenP2P) |
| ASSERT(prP2pConnReqInfo->eConnRequest |
| == P2P_CONNECTION_TYPE_PURE_AP); |
| if (kalP2PGetCipher(prAdapter->prGlueInfo, |
| (uint8_t) prBssInfo->u4PrivateData)) |
| prBssInfo->fgIsProtection = TRUE; |
| } |
| |
| bssInitForAP(prAdapter, prBssInfo, TRUE); |
| |
| #if 0 |
| if (prBssInfo->ucBMCWlanIndex >= WTBL_SIZE) { |
| prBssInfo->ucBMCWlanIndex = |
| secPrivacySeekForBcEntry(prAdapter, |
| prBssInfo->ucBssIndex, |
| prBssInfo->aucBSSID, 0xff, |
| CIPHER_SUITE_NONE, 0xff); |
| } |
| #endif |
| p2pFuncParseWmmParam(prBssInfo->arACQueParms, 0, |
| prAdapter->rWifiVar.u4P2pGoWmmParamAC0); |
| p2pFuncParseWmmParam(prBssInfo->arACQueParms, 1, |
| prAdapter->rWifiVar.u4P2pGoWmmParamAC1); |
| p2pFuncParseWmmParam(prBssInfo->arACQueParms, 2, |
| prAdapter->rWifiVar.u4P2pGoWmmParamAC2); |
| p2pFuncParseWmmParam(prBssInfo->arACQueParms, 3, |
| prAdapter->rWifiVar.u4P2pGoWmmParamAC3); |
| |
| nicQmUpdateWmmParms(prAdapter, prBssInfo->ucBssIndex); |
| #endif /* CFG_SUPPORT_AAA */ |
| |
| /* 3 <3> Set MAC HW */ |
| /* 4 <3.1> Setup channel and bandwidth */ |
| rlmBssInitForAPandIbss(prAdapter, prBssInfo); |
| |
| /* 4 <3.2> Reset HW TSF Update Mode and Beacon Mode */ |
| nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); |
| |
| /* 4 <3.3> Update Beacon again |
| * for network phy type confirmed. |
| */ |
| bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); |
| |
| /* 4 <3.4> Setup BSSID */ |
| nicPmIndicateBssCreated(prAdapter, prBssInfo->ucBssIndex); |
| #if IS_ENABLED(CFG_CCN7_SAP_EASYMESH) |
| /* 7. BSS status notification */ |
| p2pFunBssStatusNotification(prAdapter, prBssInfo); |
| #endif /* CFG_CCN7_SAP_EASYMESH */ |
| |
| } while (FALSE); |
| } /* p2pFuncStartGO() */ |
| |
| void p2pFuncStopGO(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo) |
| { |
| uint32_t u4ClientCount = 0; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); |
| |
| DBGLOG(P2P, TRACE, "p2pFuncStopGO\n"); |
| |
| #if IS_ENABLED(CFG_CCN7_SAP_EASYMESH) |
| cancel_delayed_work_sync( |
| &prAdapter->prGlueInfo->rChanNoiseControlWork); |
| cancel_delayed_work_sync( |
| &prAdapter->prGlueInfo->rChanNoiseGetInfoWork); |
| #endif |
| u4ClientCount = bssGetClientCount(prAdapter, prP2pBssInfo); |
| |
| if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) |
| && (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { |
| /* AP is created, Beacon Updated. */ |
| p2pFuncDissolve(prAdapter, |
| prP2pBssInfo, TRUE, |
| REASON_CODE_DEAUTH_LEAVING_BSS); |
| prP2pBssInfo->eIntendOPMode = OP_MODE_P2P_DEVICE; |
| } |
| |
| /* Do not Deactivate Network if any Client existed, |
| * we'll deactive it after Deauth Tx done |
| */ |
| if (u4ClientCount == 0) { |
| DBGLOG(P2P, INFO, |
| "No client! Deactive GO immediately.\n"); |
| p2pChangeMediaState(prAdapter, |
| prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); |
| p2pFuncStopComplete(prAdapter, prP2pBssInfo); |
| } |
| |
| } while (FALSE); |
| |
| } /* p2pFuncStopGO */ |
| |
| uint32_t p2pFuncRoleToBssIdx(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucRoleIdx, OUT uint8_t *pucBssIdx) |
| { |
| uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (pucBssIdx != NULL)); |
| |
| if (ucRoleIdx >= BSS_P2P_NUM) { |
| rWlanStatus = WLAN_STATUS_FAILURE; |
| break; |
| } |
| if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]) { |
| DBGLOG(P2P, WARN, |
| "%s, invalid aprP2pRoleFsmInfo, ignore\n", |
| __func__); |
| rWlanStatus = WLAN_STATUS_FAILURE; |
| } else |
| *pucBssIdx = prAdapter->rWifiVar |
| .aprP2pRoleFsmInfo[ucRoleIdx]->ucBssIndex; |
| |
| } while (FALSE); |
| |
| return rWlanStatus; |
| } /* p2pFuncRoleToBssIdx */ |
| |
| struct P2P_ROLE_FSM_INFO *p2pFuncGetRoleByBssIdx(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex) |
| { |
| int32_t i = 0; |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| (struct P2P_ROLE_FSM_INFO *)NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL)); |
| |
| for (i = 0 ; i < BSS_P2P_NUM; i++) { |
| if (!prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]) |
| continue; |
| |
| if (prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]->ucBssIndex |
| == ucBssIndex) |
| break; |
| } |
| if (i < BSS_P2P_NUM) |
| prP2pRoleFsmInfo = |
| prAdapter->rWifiVar.aprP2pRoleFsmInfo[i]; |
| |
| } while (FALSE); |
| |
| return prP2pRoleFsmInfo; |
| } |
| |
| |
| void |
| p2pFuncSwitchOPMode(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN enum ENUM_OP_MODE eOpMode, |
| IN u_int8_t fgSyncToFW) |
| { |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prP2pBssInfo != NULL) |
| && (eOpMode < OP_MODE_NUM)); |
| |
| if (prP2pBssInfo->eCurrentOPMode != eOpMode) { |
| DBGLOG(P2P, TRACE, |
| "p2pFuncSwitchOPMode: Switch to from %d, to %d.\n", |
| prP2pBssInfo->eCurrentOPMode, eOpMode); |
| |
| switch (prP2pBssInfo->eCurrentOPMode) { |
| case OP_MODE_ACCESS_POINT: |
| /* p2pFuncDissolve will be done |
| * in p2pFuncStopGO(). |
| */ |
| /* p2pFuncDissolve(prAdapter, |
| * prP2pBssInfo, TRUE, |
| * REASON_CODE_DEAUTH_LEAVING_BSS); |
| */ |
| if (prP2pBssInfo->eIntendOPMode |
| != OP_MODE_P2P_DEVICE) { |
| p2pFuncStopGO(prAdapter, prP2pBssInfo); |
| |
| SET_NET_PWR_STATE_IDLE(prAdapter, |
| prP2pBssInfo->ucBssIndex); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| prP2pBssInfo->eIntendOPMode = eOpMode; |
| |
| /* The state is in disconnecting and |
| * can not change any BSS status |
| */ |
| if (IS_NET_PWR_STATE_IDLE(prAdapter, |
| prP2pBssInfo->ucBssIndex) && |
| IS_NET_ACTIVE(prAdapter, |
| prP2pBssInfo->ucBssIndex)) { |
| DBGLOG(P2P, TRACE, |
| "under deauth procedure, Quit.\n"); |
| break; |
| } |
| |
| prP2pBssInfo->eCurrentOPMode = eOpMode; |
| switch (eOpMode) { |
| case OP_MODE_INFRASTRUCTURE: |
| DBGLOG(P2P, TRACE, |
| "p2pFuncSwitchOPMode: Switch to Client.\n"); |
| kal_fallthrough; |
| case OP_MODE_ACCESS_POINT: |
| /* Change interface address. */ |
| if (eOpMode == OP_MODE_ACCESS_POINT) { |
| DBGLOG(P2P, TRACE, |
| "p2pFuncSwitchOPMode: Switch to AP.\n"); |
| prP2pBssInfo->ucSSIDLen = 0; |
| } |
| |
| #if CFG_DUAL_P2PLIKE_INTERFACE |
| /*avoid ap1 Bss have diff A2 & A3, */ |
| /*ToDo : fix for P2P case*/ |
| |
| #else |
| COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, |
| prAdapter->rWifiVar |
| .aucInterfaceAddress); |
| COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, |
| prAdapter->rWifiVar |
| .aucInterfaceAddress); |
| #endif |
| break; |
| case OP_MODE_P2P_DEVICE: |
| { |
| /* Change device address. */ |
| DBGLOG(P2P, TRACE, |
| "p2pFuncSwitchOPMode: Switch back to P2P Device.\n"); |
| |
| p2pChangeMediaState(prAdapter, |
| prP2pBssInfo, |
| PARAM_MEDIA_STATE_DISCONNECTED); |
| |
| COPY_MAC_ADDR( |
| prP2pBssInfo->aucOwnMacAddr, |
| prAdapter->rWifiVar |
| .aucDeviceAddress); |
| COPY_MAC_ADDR( |
| prP2pBssInfo->aucBSSID, |
| prAdapter->rWifiVar |
| .aucDeviceAddress); |
| |
| } |
| break; |
| default: |
| ASSERT(FALSE); |
| break; |
| } |
| |
| if (1) { |
| struct P2P_DISCONNECT_INFO rP2PDisInfo; |
| |
| rP2PDisInfo.ucRole = 2; |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_P2P_ABORT, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, |
| sizeof(struct P2P_DISCONNECT_INFO), |
| (uint8_t *) &rP2PDisInfo, NULL, 0); |
| } |
| |
| DBGLOG(P2P, TRACE, |
| "The device address is changed to " MACSTR "\n", |
| MAC2STR(prP2pBssInfo->aucOwnMacAddr)); |
| DBGLOG(P2P, TRACE, |
| "The BSSID is changed to " MACSTR "\n", |
| MAC2STR(prP2pBssInfo->aucBSSID)); |
| |
| /* Update BSS INFO to FW. */ |
| if ((fgSyncToFW) && (eOpMode != OP_MODE_ACCESS_POINT)) |
| nicUpdateBss(prAdapter, |
| prP2pBssInfo->ucBssIndex); |
| } else if (prP2pBssInfo->eCurrentOPMode == eOpMode && |
| eOpMode == OP_MODE_INFRASTRUCTURE) { |
| /* |
| * Sometimes the interface is changed from P2P_CLIENT |
| * to STATION, but GC's connection flow is still in |
| * processing. We must force stop previous connection |
| * request to avoid unexpected behavior. |
| */ |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| (struct P2P_ROLE_FSM_INFO *) NULL; |
| struct P2P_CONNECTION_REQ_INFO *prConnReqInfo = |
| (struct P2P_CONNECTION_REQ_INFO *) NULL; |
| |
| prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO( |
| prAdapter, prP2pBssInfo->u4PrivateData); |
| if (prP2pRoleFsmInfo == NULL) |
| break; |
| |
| prConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); |
| if (prConnReqInfo == NULL) |
| break; |
| |
| if (prConnReqInfo->eConnRequest == |
| P2P_CONNECTION_TYPE_GC) { |
| log_dbg(P2P, INFO, "Force stop connection request since mode switch.\n"); |
| prConnReqInfo->eConnRequest = |
| P2P_CONNECTION_TYPE_IDLE; |
| p2pRoleFsmRunEventAbort(prAdapter, |
| prP2pRoleFsmInfo); |
| } |
| } |
| |
| } while (FALSE); |
| } /* p2pFuncSwitchOPMode */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is to inform CNM that channel privilege |
| * has been released |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * |
| * \return none |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void p2pFuncReleaseCh(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIdx, |
| IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) |
| { |
| struct MSG_CH_ABORT *prMsgChRelease = (struct MSG_CH_ABORT *) NULL; |
| |
| DEBUGFUNC("p2pFuncReleaseCh()"); |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); |
| |
| if (!prChnlReqInfo->fgIsChannelRequested) |
| break; |
| DBGLOG(P2P, TRACE, "P2P Release Channel\n"); |
| prChnlReqInfo->fgIsChannelRequested = FALSE; |
| |
| /* 1. return channel privilege to CNM immediately */ |
| prMsgChRelease = (struct MSG_CH_ABORT *) |
| cnmMemAlloc(prAdapter, |
| RAM_TYPE_MSG, sizeof(struct MSG_CH_ABORT)); |
| if (!prMsgChRelease) { |
| ASSERT(0); /* Can't release Channel to CNM */ |
| break; |
| } |
| |
| prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; |
| prMsgChRelease->ucBssIndex = ucBssIdx; |
| prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; |
| #if CFG_SUPPORT_DBDC |
| prMsgChRelease->eDBDCBand = ENUM_BAND_AUTO; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncReleaseCh: P2P abort channel on band %u.\n", |
| prMsgChRelease->eDBDCBand); |
| #endif /*CFG_SUPPORT_DBDC*/ |
| mboxSendMsg(prAdapter, |
| MBOX_ID_0, |
| (struct MSG_HDR *) prMsgChRelease, |
| MSG_SEND_METHOD_BUF); |
| |
| } while (FALSE); |
| } /* p2pFuncReleaseCh */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void p2pFuncAcquireCh(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIdx, IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) |
| { |
| struct MSG_CH_REQ *prMsgChReq = (struct MSG_CH_REQ *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); |
| |
| p2pFuncReleaseCh(prAdapter, ucBssIdx, prChnlReqInfo); |
| |
| /* send message to CNM for acquiring channel */ |
| prMsgChReq = (struct MSG_CH_REQ *) |
| cnmMemAlloc(prAdapter, |
| RAM_TYPE_MSG, sizeof(struct MSG_CH_REQ)); |
| |
| if (!prMsgChReq) { |
| /* Can't indicate CNM for channel acquiring */ |
| ASSERT(0); |
| break; |
| } |
| |
| prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; |
| prMsgChReq->ucBssIndex = ucBssIdx; |
| prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; |
| prMsgChReq->eReqType = prChnlReqInfo->eChnlReqType; |
| prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; |
| prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; |
| prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; |
| prMsgChReq->eRfBand = prChnlReqInfo->eBand; |
| prMsgChReq->eRfChannelWidth = prChnlReqInfo->eChannelWidth; |
| prMsgChReq->ucRfCenterFreqSeg1 = prChnlReqInfo->ucCenterFreqS1; |
| prMsgChReq->ucRfCenterFreqSeg2 = prChnlReqInfo->ucCenterFreqS2; |
| #if CFG_SUPPORT_DBDC |
| prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncAcquireCh: P2P Request channel on band %u, tokenID: %d, cookie: 0x%llx.\n", |
| prMsgChReq->eDBDCBand, |
| prMsgChReq->ucTokenID, |
| prChnlReqInfo->u8Cookie); |
| |
| #endif /*CFG_SUPPORT_DBDC*/ |
| /* Channel request join BSSID. */ |
| |
| mboxSendMsg(prAdapter, |
| MBOX_ID_0, |
| (struct MSG_HDR *) prMsgChReq, |
| MSG_SEND_METHOD_BUF); |
| |
| prChnlReqInfo->fgIsChannelRequested = TRUE; |
| |
| } while (FALSE); |
| } /* p2pFuncAcquireCh */ |
| |
| #if (CFG_SUPPORT_DFS_MASTER == 1) |
| void p2pFuncStartRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) |
| { |
| struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| (struct P2P_ROLE_FSM_INFO *) NULL; |
| uint8_t ucReqChnlNum; |
| |
| DEBUGFUNC("p2pFuncStartRdd()"); |
| |
| |
| prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, |
| prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); |
| |
| ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; |
| |
| prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, |
| sizeof(*prCmdRddOnOffCtrl)); |
| |
| if (!prCmdRddOnOffCtrl) { |
| DBGLOG(P2P, ERROR, |
| "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); |
| return; |
| } |
| |
| prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START; |
| |
| /* |
| * FIX ME: Mobile driver can't get correct band. |
| * There is only 5G in DFS channel, |
| * which is on band_0. So it assigned to ENUM_BAND_0 as temp solution. |
| * Remember to fix it when driver could get |
| * the correct band from firmware. |
| */ |
| prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; |
| |
| if (rlmDomainGetDfsRegion() == NL80211_DFS_JP) { |
| if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) |
| prCmdRddOnOffCtrl->ucSetVal = REG_JP_53; |
| else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) |
| prCmdRddOnOffCtrl->ucSetVal = REG_JP_56; |
| } else { |
| prCmdRddOnOffCtrl->ucSetVal = REG_DEFAULT; |
| } |
| |
| if (prCmdRddOnOffCtrl->ucRddIdx) |
| prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; |
| else |
| prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncStartRdd: Start Radar detection - DFS ctrl: %d, RDD index: %d\n", |
| prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_RDD_ON_OFF_CTRL, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, |
| sizeof(*prCmdRddOnOffCtrl), |
| (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); |
| |
| cnmMemFree(prAdapter, prCmdRddOnOffCtrl); |
| } /* p2pFuncStartRdd */ |
| |
| void p2pFuncStopRdd(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) |
| { |
| struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; |
| |
| DEBUGFUNC("p2pFuncStopRdd()"); |
| |
| prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, |
| sizeof(*prCmdRddOnOffCtrl)); |
| |
| if (!prCmdRddOnOffCtrl) { |
| DBGLOG(P2P, ERROR, |
| "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); |
| return; |
| } |
| |
| prCmdRddOnOffCtrl->ucDfsCtrl = RDD_STOP; |
| |
| /* |
| * FIX ME: Mobile driver can't get correct band. |
| * There is only 5G in DFS channel, |
| * which is on band_0. So it assigned to ENUM_BAND_0 as temp solution. |
| * Remember to fix it when driver could get |
| * the correct band from firmware. |
| */ |
| prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; |
| |
| if (prCmdRddOnOffCtrl->ucRddIdx) |
| prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_1; |
| else |
| prCmdRddOnOffCtrl->ucRddRxSel = RDD_IN_SEL_0; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncStopRdd: Stop Radar detection - DFS ctrl: %d, RDD index: %d\n", |
| prCmdRddOnOffCtrl->ucDfsCtrl, prCmdRddOnOffCtrl->ucRddIdx); |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_RDD_ON_OFF_CTRL, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, |
| sizeof(*prCmdRddOnOffCtrl), |
| (uint8_t *) prCmdRddOnOffCtrl, NULL, 0); |
| |
| cnmMemFree(prAdapter, prCmdRddOnOffCtrl); |
| |
| } /* p2pFuncStopRdd */ |
| |
| |
| void p2pFuncDfsSwitchCh(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prBssInfo, |
| IN struct P2P_CHNL_REQ_INFO rP2pChnlReqInfo) |
| { |
| |
| struct GLUE_INFO *prGlueInfo; |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| (struct P2P_ROLE_FSM_INFO *) NULL; |
| struct CMD_RDD_ON_OFF_CTRL *prCmdRddOnOffCtrl; |
| struct GL_P2P_INFO *prP2PInfo = NULL; |
| |
| DEBUGFUNC("p2pFuncDfsSwitchCh()"); |
| |
| if (!prBssInfo) { |
| DBGLOG(P2P, ERROR, "prBssInfo shouldn't be NULL!\n"); |
| return; |
| } |
| |
| /* Setup Channel, Band */ |
| prBssInfo->ucPrimaryChannel = rP2pChnlReqInfo.ucReqChnlNum; |
| prBssInfo->eBand = rP2pChnlReqInfo.eBand; |
| prBssInfo->eBssSCO = rP2pChnlReqInfo.eChnlSco; |
| |
| /* To Support Cross Band Channel Swtich */ |
| #if CFG_SUPPORT_IDC_CH_SWITCH |
| if (prBssInfo->eBand == BAND_5G) { |
| /* Depend on eBand */ |
| prBssInfo->ucPhyTypeSet = |
| (prAdapter->rWifiVar.ucAvailablePhyTypeSet |
| & PHY_TYPE_SET_802_11AN); |
| /* Depend on eCurrentOPMode and ucPhyTypeSet */ |
| prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; |
| } else { /* Only SAP mode should enter this function */ |
| /* Depend on eBand */ |
| prBssInfo->ucPhyTypeSet = |
| (prAdapter->rWifiVar.ucAvailablePhyTypeSet |
| & PHY_TYPE_SET_802_11BGN); |
| /* Depend on eCurrentOPMode and ucPhyTypeSet */ |
| prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; |
| } |
| |
| /* Overwrite BSS PHY type set by Feature Options */ |
| bssDetermineApBssInfoPhyTypeSet(prAdapter, |
| TRUE, prBssInfo); |
| |
| prBssInfo->ucNonHTBasicPhyType = (uint8_t) |
| rNonHTApModeAttributes |
| [prBssInfo->ucConfigAdHocAPMode] |
| .ePhyTypeIndex; |
| prBssInfo->u2BSSBasicRateSet = |
| rNonHTApModeAttributes |
| [prBssInfo->ucConfigAdHocAPMode] |
| .u2BSSBasicRateSet; |
| prBssInfo->u2OperationalRateSet = |
| rNonHTPhyAttributes |
| [prBssInfo->ucNonHTBasicPhyType] |
| .u2SupportedRateSet; |
| kalMemZero(prBssInfo->aucAllSupportedRates, RATE_NUM_SW); |
| rateGetDataRatesFromRateSet( |
| prBssInfo->u2OperationalRateSet, |
| prBssInfo->u2BSSBasicRateSet, |
| prBssInfo->aucAllSupportedRates, |
| &prBssInfo->ucAllSupportedRatesLen); |
| #endif |
| |
| /* Setup channel and bandwidth */ |
| rlmBssInitForAPandIbss(prAdapter, prBssInfo); |
| |
| /* Update Beacon again for network phy type confirmed. */ |
| bssUpdateBeaconContent(prAdapter, prBssInfo->ucBssIndex); |
| |
| /* Reset HW TSF Update Mode and Beacon Mode */ |
| nicUpdateBss(prAdapter, prBssInfo->ucBssIndex); |
| |
| prCmdRddOnOffCtrl = (struct CMD_RDD_ON_OFF_CTRL *) |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, |
| sizeof(*prCmdRddOnOffCtrl)); |
| |
| if (!prCmdRddOnOffCtrl) { |
| DBGLOG(P2P, ERROR, |
| "cnmMemAlloc for prCmdRddOnOffCtrl failed!\n"); |
| return; |
| } |
| |
| prCmdRddOnOffCtrl->ucDfsCtrl = RDD_START_TXQ; |
| |
| /* |
| * FIX ME: Mobile driver can't get correct band. |
| * There is only 5G in DFS channel, |
| * which is on band_0. So it assigned to ENUM_BAND_0 |
| * as temp solution. |
| * Remember to fix it when driver could get |
| * the correct band from firmware. |
| */ |
| prCmdRddOnOffCtrl->ucRddIdx = ENUM_BAND_0; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncDfsSwitchCh: Start TXQ - DFS ctrl: %.d\n", |
| prCmdRddOnOffCtrl->ucDfsCtrl); |
| |
| wlanSendSetQueryCmd(prAdapter, |
| CMD_ID_RDD_ON_OFF_CTRL, |
| TRUE, |
| FALSE, |
| FALSE, |
| NULL, |
| NULL, |
| sizeof(*prCmdRddOnOffCtrl), |
| (uint8_t *) prCmdRddOnOffCtrl, |
| NULL, 0); |
| |
| cnmMemFree(prAdapter, prCmdRddOnOffCtrl); |
| |
| prP2pRoleFsmInfo = |
| P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, |
| prBssInfo->u4PrivateData); |
| |
| prGlueInfo = prAdapter->prGlueInfo; |
| prP2PInfo = (struct GL_P2P_INFO *)prGlueInfo-> |
| prP2PInfo[prP2pRoleFsmInfo->ucRoleIndex]; |
| |
| if (prP2PInfo->chandef) { |
| if (prP2PInfo->prDevHandler) { |
| DBGLOG(P2P, INFO, "p2pFuncDfsSwitchCh: Update to OS\n"); |
| cfg80211_ch_switch_notify( |
| prP2PInfo->prDevHandler, |
| prP2PInfo->chandef |
| #if (CFG_ADVANCED_80211_MLO == 1) |
| , 0 |
| #if (CFG_KERNEL_AN14_515 == 1) && \ |
| (KERNEL_VERSION(5, 15, 144) <= CFG80211_VERSION_CODE) |
| , 0 |
| #endif |
| #endif |
| ); |
| DBGLOG(P2P, INFO, |
| "p2pFuncDfsSwitchCh: Update to OS Done\n"); |
| } else |
| DBGLOG(P2P, ERROR, "NULL prDevHandler\n"); |
| } else |
| DBGLOG(P2P, ERROR, "NULL chandef\n"); |
| } /* p2pFuncDfsSwitchCh */ |
| |
| u_int8_t p2pFuncCheckWeatherRadarBand( |
| IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo) |
| { |
| uint8_t ucReqChnlNum; |
| uint8_t ucCenterFreqS1; |
| enum ENUM_CHANNEL_WIDTH eChannelWidth; |
| enum ENUM_CHNL_EXT eChnlSco; |
| |
| |
| ucReqChnlNum = prChnlReqInfo->ucReqChnlNum; |
| ucCenterFreqS1 = prChnlReqInfo->ucCenterFreqS1; |
| eChannelWidth = prChnlReqInfo->eChannelWidth; |
| eChnlSco = prChnlReqInfo->eChnlSco; |
| |
| if (rlmDomainGetDfsRegion() == NL80211_DFS_ETSI) { |
| if (eChannelWidth == VHT_OP_CHANNEL_WIDTH_80) { |
| if (ucCenterFreqS1 >= 120 && ucCenterFreqS1 <= 128) |
| return TRUE; |
| } else { |
| if ((ucReqChnlNum >= 120 && ucReqChnlNum <= 128)) |
| return TRUE; |
| else if (ucReqChnlNum == 116 |
| && eChnlSco == CHNL_EXT_SCA) |
| return TRUE; /* ch116, 120 BW40 */ |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| int32_t p2pFuncSetDriverCacTime(IN uint32_t u4CacTime) |
| { |
| uint32_t i4Status = WLAN_STATUS_SUCCESS; |
| |
| g_u4DriverCacTime = u4CacTime; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncSetDriverCacTime: g_u4ManualCacTime = %dsec\n", |
| g_u4DriverCacTime); |
| |
| return i4Status; |
| } |
| |
| void p2pFuncEnableManualCac(void) |
| { |
| g_fgManualCac = TRUE; |
| } |
| |
| uint32_t p2pFuncGetDriverCacTime(void) |
| { |
| return g_u4DriverCacTime; |
| } |
| |
| u_int8_t p2pFuncIsManualCac(void) |
| { |
| return g_fgManualCac; |
| } |
| |
| void p2pFuncRadarInfoInit(void) |
| { |
| kalMemZero(&g_rP2pRadarInfo, sizeof(g_rP2pRadarInfo)); |
| } |
| |
| void p2pFuncShowRadarInfo(IN struct ADAPTER *prAdapter, IN uint8_t ucBssIdx) |
| { |
| uint8_t ucCnt = 0; |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| (struct P2P_ROLE_FSM_INFO *) NULL; |
| uint8_t ucReqChnlNum; |
| |
| if (g_rP2pRadarInfo.ucRadarReportMode == 1) { |
| |
| prP2pRoleFsmInfo = P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, |
| prAdapter->aprBssInfo[ucBssIdx]->u4PrivateData); |
| |
| ucReqChnlNum = prP2pRoleFsmInfo->rChnlReqInfo.ucReqChnlNum; |
| |
| DBGLOG(P2P, INFO, "-----Radar Detected Event-----\n"); |
| DBGLOG(P2P, INFO, |
| "Radar detected in DBDC band%d\n", |
| g_rP2pRadarInfo.ucRddIdx); |
| |
| switch (rlmDomainGetDfsRegion()) { |
| case NL80211_DFS_FCC: |
| DBGLOG(P2P, INFO, "Regulation domain: FCC\n"); |
| break; |
| case NL80211_DFS_ETSI: |
| DBGLOG(P2P, INFO, "Regulation domain: ETSI\n"); |
| break; |
| case NL80211_DFS_JP: |
| DBGLOG(P2P, INFO, "Regulation domain: JP\n"); |
| |
| if (ucReqChnlNum >= 52 && ucReqChnlNum <= 64) |
| DBGLOG(P2P, INFO, |
| "Radar type: W53 - %s\n", |
| p2pFuncJpW53RadarType()); |
| else if (ucReqChnlNum >= 100 && ucReqChnlNum <= 140) |
| DBGLOG(P2P, INFO, |
| "Radar type: W56 - %s\n", |
| p2pFuncJpW56RadarType()); |
| break; |
| default: |
| break; |
| } |
| |
| DBGLOG(P2P, INFO, "Radar Content:\n"); |
| |
| DBGLOG(P2P, INFO, "start time pulse width PRI\n"); |
| |
| if (g_rP2pRadarInfo.ucPeriodicDetected) { |
| DBGLOG(P2P, INFO, "%-10d %-11d -\n" |
| , g_rP2pRadarInfo.arPpbContent |
| [ucCnt].u4PeriodicStartTime |
| , g_rP2pRadarInfo.arPpbContent |
| [ucCnt].u2PeriodicPulseWidth); |
| |
| for (ucCnt = 1; |
| ucCnt < g_rP2pRadarInfo.ucPPBNum; ucCnt++) { |
| DBGLOG(P2P, INFO, "%-10d %-11d %d\n" |
| , g_rP2pRadarInfo.arPpbContent |
| [ucCnt].u4PeriodicStartTime |
| , g_rP2pRadarInfo.arPpbContent |
| [ucCnt].u2PeriodicPulseWidth |
| , (g_rP2pRadarInfo.arPpbContent |
| [ucCnt].u4PeriodicStartTime |
| - g_rP2pRadarInfo.arPpbContent |
| [ucCnt-1].u4PeriodicStartTime) |
| * 2 / 5); |
| } |
| } else if (g_rP2pRadarInfo.ucLongDetected) { |
| DBGLOG(P2P, INFO, "%-10d %-11d -\n" |
| , g_rP2pRadarInfo.arLpbContent |
| [ucCnt].u4LongStartTime |
| , g_rP2pRadarInfo.arLpbContent |
| [ucCnt].u2LongPulseWidth); |
| |
| for (ucCnt = 1; |
| ucCnt < g_rP2pRadarInfo.ucLPBNum; ucCnt++) { |
| DBGLOG(P2P, INFO, "%-10d %-11d %d\n" |
| , g_rP2pRadarInfo.arLpbContent |
| [ucCnt].u4LongStartTime |
| , g_rP2pRadarInfo.arLpbContent |
| [ucCnt].u2LongPulseWidth |
| , (g_rP2pRadarInfo.arLpbContent |
| [ucCnt].u4LongStartTime |
| - g_rP2pRadarInfo.arLpbContent |
| [ucCnt-1].u4LongStartTime) |
| * 2 / 5); |
| } |
| } |
| } |
| } |
| |
| void p2pFuncGetRadarInfo(IN struct P2P_RADAR_INFO *prP2pRadarInfo) |
| { |
| kalMemCopy(prP2pRadarInfo, &g_rP2pRadarInfo, sizeof(*prP2pRadarInfo)); |
| } |
| |
| uint8_t *p2pFuncJpW53RadarType(void) |
| { |
| uint32_t u4Type1Diff; |
| uint32_t u4Type2Diff; |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) |
| u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; |
| else |
| u4Type1Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 3846) |
| u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 3846; |
| else |
| u4Type2Diff = 3846 - g_rP2pRadarInfo.u4PRI1stUs; |
| |
| if (u4Type1Diff < u4Type2Diff) |
| return apucW53RadarType[1]; |
| else |
| return apucW53RadarType[2]; |
| } |
| |
| uint8_t *p2pFuncJpW56RadarType(void) |
| { |
| uint32_t u4Type1Diff; |
| uint32_t u4Type2Diff; |
| |
| if (g_rP2pRadarInfo.ucLongDetected) |
| return apucW56RadarType[7]; |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 3980 |
| && g_rP2pRadarInfo.u4PRI1stUs <= 4020) |
| return apucW56RadarType[3]; |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 1368 |
| && g_rP2pRadarInfo.u4PRI1stUs <= 1448) { |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 1388) |
| u4Type1Diff = g_rP2pRadarInfo.u4PRI1stUs - 1388; |
| else |
| u4Type1Diff = 1388 - g_rP2pRadarInfo.u4PRI1stUs; |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 1428) |
| u4Type2Diff = g_rP2pRadarInfo.u4PRI1stUs - 1428; |
| else |
| u4Type2Diff = 1428 - g_rP2pRadarInfo.u4PRI1stUs; |
| |
| if (u4Type1Diff < u4Type2Diff) |
| return apucW56RadarType[1]; |
| else |
| return apucW56RadarType[2]; |
| |
| } |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 130 |
| && g_rP2pRadarInfo.u4PRI1stUs < 200) |
| return apucW56RadarType[4]; |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 200 |
| && g_rP2pRadarInfo.u4PRI1stUs <= 520) { |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs <= 230) |
| return apucW56RadarType[9]; |
| |
| if (g_rP2pRadarInfo.u4PRI1stUs >= 323 |
| && g_rP2pRadarInfo.u4PRI1stUs <= 343) |
| return apucW56RadarType[10]; |
| |
| return apucW56RadarType[11]; |
| } |
| |
| return apucW56RadarType[0]; |
| } |
| |
| void p2pFuncSetRadarDetectMode(IN uint8_t ucRadarDetectMode) |
| { |
| g_ucRadarDetectMode = ucRadarDetectMode; |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncSetRadarDetectMode: g_ucRadarDetectMode: %d\n", |
| g_ucRadarDetectMode); |
| } |
| |
| uint8_t p2pFuncGetRadarDetectMode(void) |
| { |
| return g_ucRadarDetectMode; |
| } |
| |
| void p2pFuncSetDfsState(IN uint8_t ucDfsState) |
| { |
| DBGLOG(P2P, INFO, |
| "[DFS_STATE] TRANSITION: [%s] -> [%s]\n", |
| apucDfsState[g_ucDfsState], apucDfsState[ucDfsState]); |
| |
| g_ucDfsState = ucDfsState; |
| } |
| |
| uint8_t p2pFuncGetDfsState(void) |
| { |
| return g_ucDfsState; |
| } |
| |
| uint8_t *p2pFuncShowDfsState(void) |
| { |
| return apucDfsState[g_ucDfsState]; |
| } |
| |
| void p2pFuncRecordCacStartBootTime(void) |
| { |
| g_u4CacStartBootTime = kalGetBootTime(); |
| } |
| |
| uint32_t p2pFuncGetCacRemainingTime(void) |
| { |
| uint32_t u4CurrentBootTime; |
| uint32_t u4CacRemainingTime; |
| |
| u4CurrentBootTime = kalGetBootTime(); |
| |
| u4CacRemainingTime = g_u4DriverCacTime - |
| (u4CurrentBootTime - g_u4CacStartBootTime)/1000000; |
| |
| return u4CacRemainingTime; |
| } |
| #endif |
| |
| #if 0 |
| uint32_t |
| p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucBcnHdr, |
| IN uint32_t u4HdrLen, |
| IN uint8_t *pucBcnBody, |
| IN uint32_t u4BodyLen, |
| IN uint32_t u4DtimPeriod, |
| IN uint32_t u4BcnInterval) |
| { |
| uint32_t rResultStatus = WLAN_STATUS_INVALID_DATA; |
| struct WLAN_BEACON_FRAME *prBcnFrame = |
| (struct WLAN_BEACON_FRAME *) NULL; |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| struct MSDU_INFO *prBcnMsduInfo = (struct MSDU_INFO *) NULL; |
| uint8_t *pucTIMBody = (uint8_t *) NULL; |
| uint16_t u2FrameLength = 0, uint16_t u2OldBodyLen = 0; |
| uint8_t aucIEBuf[MAX_IE_LENGTH]; |
| |
| do { |
| ASSERT_BREAK(prAdapter != NULL); |
| |
| prP2pBssInfo = |
| &(prAdapter->rWifiVar |
| .arBssInfo[NETWORK_TYPE_P2P_INDEX]); |
| prBcnMsduInfo = prP2pBssInfo->prBeacon; |
| ASSERT_BREAK(prBcnMsduInfo != NULL); |
| |
| /* TODO: Find TIM IE pointer. */ |
| prBcnFrame = prBcnMsduInfo->prPacket; |
| |
| ASSERT_BREAK(prBcnFrame != NULL); |
| |
| do { |
| /* Ori header. */ |
| uint16_t u2IELength = 0, u2Offset = 0; |
| uint8_t *pucIEBuf = prBcnFrame->aucInfoElem; |
| |
| u2IELength = prBcnMsduInfo->u2FrameLength - |
| prBcnMsduInfo->ucMacHeaderLength; |
| |
| IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { |
| if ((IE_ID(pucIEBuf) == ELEM_ID_TIM) |
| || ((IE_ID(pucIEBuf) |
| > ELEM_ID_IBSS_PARAM_SET))) { |
| pucTIMBody = pucIEBuf; |
| break; |
| } |
| u2FrameLength += IE_SIZE(pucIEBuf); |
| } |
| |
| if (pucTIMBody == NULL) |
| pucTIMBody = pucIEBuf; |
| |
| /* Body not change. */ |
| u2OldBodyLen = (uint16_t) ((uint32_t) pucTIMBody - |
| (uint32_t) prBcnFrame->aucInfoElem); |
| /* Move body. */ |
| kalMemCmp(aucIEBuf, pucTIMBody, u2OldBodyLen); |
| } while (FALSE); |
| if (pucBcnHdr) { |
| kalMemCopy(prBcnMsduInfo->prPacket, |
| pucBcnHdr, u4HdrLen); |
| pucTIMBody = (uint8_t *) |
| ((uint32_t) prBcnMsduInfo->prPacket + u4HdrLen); |
| prBcnMsduInfo->ucMacHeaderLength = |
| (WLAN_MAC_MGMT_HEADER_LEN + |
| (TIMESTAMP_FIELD_LEN + |
| BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); |
| /* Header + Partial Body. */ |
| u2FrameLength = u4HdrLen; |
| } else { |
| /* Header not change. */ |
| u2FrameLength += prBcnMsduInfo->ucMacHeaderLength; |
| } |
| |
| if (pucBcnBody) { |
| kalMemCopy(pucTIMBody, pucBcnBody, u4BodyLen); |
| u2FrameLength += (uint16_t) u4BodyLen; |
| } else { |
| kalMemCopy(pucTIMBody, aucIEBuf, u2OldBodyLen); |
| u2FrameLength += u2OldBodyLen; |
| } |
| |
| /* Frame Length */ |
| prBcnMsduInfo->u2FrameLength = u2FrameLength; |
| prBcnMsduInfo->fgIs802_11 = TRUE; |
| prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; |
| prP2pBssInfo->u2BeaconInterval = (uint16_t) u4BcnInterval; |
| prP2pBssInfo->ucDTIMPeriod = (uint8_t) u4DtimPeriod; |
| prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; |
| prBcnMsduInfo->ucPacketType = 3; |
| rResultStatus = nicUpdateBeaconIETemplate(prAdapter, |
| IE_UPD_METHOD_UPDATE_ALL, |
| NETWORK_TYPE_P2P_INDEX, |
| prP2pBssInfo->u2CapInfo, |
| (uint8_t *) prBcnFrame->aucInfoElem, |
| prBcnMsduInfo->u2FrameLength - |
| OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem)); |
| if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { |
| /* AP is created, Beacon Update. */ |
| nicPmIndicateBssAbort(prAdapter, |
| NETWORK_TYPE_P2P_INDEX); |
| nicPmIndicateBssCreated(prAdapter, |
| NETWORK_TYPE_P2P_INDEX); |
| } |
| |
| } while (FALSE); |
| return rResultStatus; |
| } /* p2pFuncBeaconUpdate */ |
| |
| #else |
| uint32_t |
| p2pFuncBeaconUpdate(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN struct P2P_BEACON_UPDATE_INFO *prBcnUpdateInfo, |
| IN uint8_t *pucNewBcnHdr, |
| IN uint32_t u4NewHdrLen, |
| IN uint8_t *pucNewBcnBody, |
| IN uint32_t u4NewBodyLen) |
| { |
| uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; |
| struct WLAN_BEACON_FRAME *prBcnFrame = |
| (struct WLAN_BEACON_FRAME *) NULL; |
| struct MSDU_INFO *prBcnMsduInfo = (struct MSDU_INFO *) NULL; |
| uint8_t *pucIEBuf = (uint8_t *) NULL; |
| uint8_t aucIEBuf[MAX_IE_LENGTH]; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prP2pBssInfo != NULL) |
| && (prBcnUpdateInfo != NULL)); |
| |
| prBcnMsduInfo = prP2pBssInfo->prBeacon; |
| |
| #if DBG |
| if (prBcnUpdateInfo->pucBcnHdr != NULL) { |
| ASSERT((uint32_t) prBcnUpdateInfo->pucBcnHdr == |
| ((uint32_t) prBcnMsduInfo->prPacket + |
| MAC_TX_RESERVED_FIELD)); |
| } |
| |
| if (prBcnUpdateInfo->pucBcnBody != NULL) { |
| ASSERT((uint32_t) prBcnUpdateInfo->pucBcnBody == |
| ((uint32_t) prBcnUpdateInfo->pucBcnHdr + |
| (uint32_t) prBcnUpdateInfo->u4BcnHdrLen)); |
| } |
| #endif |
| prBcnFrame = (struct WLAN_BEACON_FRAME *) |
| ((unsigned long) prBcnMsduInfo->prPacket + |
| MAC_TX_RESERVED_FIELD); |
| |
| if (!pucNewBcnBody) { |
| /* Old body. */ |
| pucNewBcnBody = prBcnUpdateInfo->pucBcnBody; |
| ASSERT(u4NewBodyLen == 0); |
| u4NewBodyLen = prBcnUpdateInfo->u4BcnBodyLen; |
| } else { |
| prBcnUpdateInfo->u4BcnBodyLen = u4NewBodyLen; |
| } |
| |
| /* Temp buffer body part. */ |
| kalMemCopy(aucIEBuf, pucNewBcnBody, u4NewBodyLen); |
| |
| if (pucNewBcnHdr) { |
| kalMemCopy(prBcnFrame, pucNewBcnHdr, u4NewHdrLen); |
| prBcnUpdateInfo->pucBcnHdr = (uint8_t *) prBcnFrame; |
| prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen; |
| } |
| |
| pucIEBuf = (uint8_t *) |
| ((unsigned long) prBcnUpdateInfo->pucBcnHdr + |
| (unsigned long) prBcnUpdateInfo->u4BcnHdrLen); |
| kalMemCopy(pucIEBuf, aucIEBuf, u4NewBodyLen); |
| prBcnUpdateInfo->pucBcnBody = pucIEBuf; |
| |
| /* Frame Length */ |
| prBcnMsduInfo->u2FrameLength = (uint16_t) |
| (prBcnUpdateInfo->u4BcnHdrLen + |
| prBcnUpdateInfo->u4BcnBodyLen); |
| |
| prBcnMsduInfo->ucPacketType = TX_PACKET_TYPE_MGMT; |
| prBcnMsduInfo->fgIs802_11 = TRUE; |
| prBcnMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; |
| |
| /* Update BSS INFO related information. */ |
| COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, |
| prBcnFrame->aucSrcAddr); |
| COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prBcnFrame->aucBSSID); |
| prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; |
| |
| p2pFuncParseBeaconContent(prAdapter, |
| prP2pBssInfo, |
| (uint8_t *) prBcnFrame->aucInfoElem, |
| (prBcnMsduInfo->u2FrameLength - |
| OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem))); |
| |
| #if 1 |
| /* bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); */ |
| #else |
| nicUpdateBeaconIETemplate(prAdapter, |
| IE_UPD_METHOD_UPDATE_ALL, |
| NETWORK_TYPE_P2P_INDEX, |
| prBcnFrame->u2CapInfo, |
| (uint8_t *) prBcnFrame->aucInfoElem, |
| (prBcnMsduInfo->u2FrameLength - |
| OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem))); |
| #endif |
| } while (FALSE); |
| |
| return rWlanStatus; |
| } /* p2pFuncBeaconUpdate */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is to update extra IEs (ex: WPS) for assoc resp. |
| * Caller should sanity check the params. |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * \param[in] prP2pBssInfo Pointer to BSS_INFO_T structure |
| * \param[in] AssocRespIE Pointer to extra IEs for assoc resp |
| * \param[in] u4AssocRespLen Length of extra IEs for assoc resp |
| * |
| * \return WLAN_STATUS |
| */ |
| /*---------------------------------------------------------------------------*/ |
| |
| uint32_t |
| p2pFuncAssocRespUpdate(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN uint8_t *AssocRespIE, IN uint32_t u4AssocRespLen) |
| { |
| uint8_t ucOuiType = 0; |
| uint16_t u2SubTypeVersion = 0; |
| |
| if (!rsnParseCheckForWFAInfoElem(prAdapter, |
| AssocRespIE, &ucOuiType, &u2SubTypeVersion)) |
| return WLAN_STATUS_FAILURE; |
| |
| if (ucOuiType == VENDOR_OUI_TYPE_WPS) { |
| kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 3, |
| (uint8_t *)AssocRespIE, IE_SIZE(AssocRespIE), |
| (uint8_t) (prP2pBssInfo->u4PrivateData)); |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| #endif |
| |
| #if 0 |
| /* TODO: We do not apply IE in deauth frame set from upper layer now. */ |
| uint32_t |
| p2pFuncDeauth(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucPeerMacAddr, |
| IN uint16_t u2ReasonCode, |
| IN uint8_t *pucIEBuf, |
| IN uint16_t u2IELen, |
| IN u_int8_t fgSendDeauth) |
| { |
| uint32_t rWlanStatus = WLAN_STATUS_FAILURE; |
| struct STA_RECORD *prCliStaRec = (struct STA_RECORD *) NULL; |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| u_int8_t fgIsStaFound = FALSE; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); |
| |
| prP2pBssInfo = |
| &(prAdapter->rWifiVar |
| .arBssInfo[NETWORK_TYPE_P2P_INDEX]); |
| |
| prCliStaRec = cnmGetStaRecByAddress(prAdapter, |
| NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); |
| |
| switch (prP2pBssInfo->eCurrentOPMode) { |
| case OP_MODE_ACCESS_POINT: |
| { |
| struct LINK *prStaRecOfClientList = |
| (struct LINK *) NULL; |
| struct LINK_ENTRY *prLinkEntry = |
| (struct LINK_ENTRY *) NULL; |
| |
| prStaRecOfClientList = |
| &(prP2pBssInfo->rStaRecOfClientList); |
| |
| LINK_FOR_EACH(prLinkEntry, |
| prStaRecOfClientList) { |
| if ((uint32_t) prCliStaRec |
| == (uint32_t) prLinkEntry) { |
| LINK_REMOVE_KNOWN_ENTRY( |
| prStaRecOfClientList, |
| &prCliStaRec->rLinkEntry); |
| fgIsStaFound = TRUE; |
| break; |
| } |
| } |
| |
| } |
| break; |
| case OP_MODE_INFRASTRUCTURE: |
| ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); |
| if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) |
| break; |
| prP2pBssInfo->prStaRecOfAP = NULL; |
| fgIsStaFound = TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| if (fgIsStaFound) |
| p2pFuncDisconnect(prAdapter, |
| prCliStaRec, fgSendDeauth, u2ReasonCode); |
| |
| rWlanStatus = WLAN_STATUS_SUCCESS; |
| } while (FALSE); |
| |
| return rWlanStatus; |
| } /* p2pFuncDeauth */ |
| |
| /* TODO: We do not apply IE in disassoc frame set from upper layer now. */ |
| uint32_t |
| p2pFuncDisassoc(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucPeerMacAddr, |
| IN uint16_t u2ReasonCode, |
| IN uint8_t *pucIEBuf, |
| IN uint16_t u2IELen, |
| IN u_int8_t fgSendDisassoc) |
| { |
| uint32_t rWlanStatus = WLAN_STATUS_FAILURE; |
| struct STA_RECORD *prCliStaRec = (struct STA_RECORD *) NULL; |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| u_int8_t fgIsStaFound = FALSE; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (pucPeerMacAddr != NULL)); |
| |
| prP2pBssInfo = |
| &(prAdapter->rWifiVar |
| .arBssInfo[NETWORK_TYPE_P2P_INDEX]); |
| |
| prCliStaRec = cnmGetStaRecByAddress(prAdapter, |
| NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); |
| |
| switch (prP2pBssInfo->eCurrentOPMode) { |
| case OP_MODE_ACCESS_POINT: |
| { |
| struct LINK *prStaRecOfClientList = |
| (struct LINK *) NULL; |
| struct LINK_ENTRY *prLinkEntry = |
| (struct LINK_ENTRY *) NULL; |
| |
| prStaRecOfClientList = |
| &(prP2pBssInfo->rStaRecOfClientList); |
| |
| LINK_FOR_EACH(prLinkEntry, |
| prStaRecOfClientList) { |
| if ((uint32_t) prCliStaRec |
| == (uint32_t) prLinkEntry) { |
| LINK_REMOVE_KNOWN_ENTRY( |
| prStaRecOfClientList, |
| &prCliStaRec->rLinkEntry); |
| fgIsStaFound = TRUE; |
| /* p2pFuncDisconnect(prAdapter, |
| * prCliStaRec, |
| */ |
| /* fgSendDisassoc, |
| * u2ReasonCode); |
| */ |
| break; |
| } |
| } |
| |
| } |
| break; |
| case OP_MODE_INFRASTRUCTURE: |
| ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); |
| if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) |
| break; |
| /* p2pFuncDisconnect(prAdapter, |
| * prCliStaRec, fgSendDisassoc, u2ReasonCode); |
| */ |
| prP2pBssInfo->prStaRecOfAP = NULL; |
| fgIsStaFound = TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| if (fgIsStaFound) { |
| |
| p2pFuncDisconnect(prAdapter, |
| prCliStaRec, fgSendDisassoc, u2ReasonCode); |
| /* 20120830 moved into p2pFuncDisconnect(). */ |
| /* cnmStaRecFree(prAdapter, prCliStaRec); */ |
| |
| } |
| |
| rWlanStatus = WLAN_STATUS_SUCCESS; |
| } while (FALSE); |
| |
| return rWlanStatus; |
| } /* p2pFuncDisassoc */ |
| |
| #endif |
| |
| #if CFG_SUPPORT_P2P_GO_OFFLOAD_PROBE_RSP |
| uint32_t |
| p2pFuncProbeRespUpdate(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN uint8_t *ProbeRespIE, IN uint32_t u4ProbeRespLen) |
| |
| { |
| struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; |
| uint32_t u4IeArraySize = 0, u4Idx = 0; |
| uint8_t *pucP2pIe = (uint8_t *) NULL; |
| uint8_t *pucWpsIe = (uint8_t *) NULL; |
| uint8_t *pucWfdIe = (uint8_t *) NULL; |
| |
| if (prP2pBssInfo == NULL) |
| return WLAN_STATUS_FAILURE; |
| |
| /* reuse beacon MsduInfo */ |
| prMsduInfo = prP2pBssInfo->prBeacon; |
| |
| /* beacon prMsduInfo will be NULLify |
| * once BSS deactivated, so skip if it is |
| */ |
| if (!prMsduInfo) |
| return WLAN_STATUS_SUCCESS; |
| |
| if (!ProbeRespIE) { |
| DBGLOG(BSS, INFO, |
| "change beacon: has no extra probe response IEs\n"); |
| return WLAN_STATUS_SUCCESS; |
| } |
| if (p2pFuncIsAPMode( |
| prAdapter->rWifiVar |
| .prP2PConnSettings[prP2pBssInfo->u4PrivateData])) { |
| DBGLOG(BSS, INFO, |
| "change beacon: pure Ap mode do not add extra probe response IEs\n"); |
| return WLAN_STATUS_SUCCESS; |
| } |
| prMsduInfo->u2FrameLength = 0; |
| |
| bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, |
| prP2pBssInfo, ProbeRespIE); |
| |
| u4IeArraySize = |
| sizeof(txProbeRspIETable) / sizeof(struct APPEND_VAR_IE_ENTRY); |
| |
| for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { |
| if (txProbeRspIETable[u4Idx].pfnAppendIE) |
| txProbeRspIETable[u4Idx] |
| .pfnAppendIE(prAdapter, prMsduInfo); |
| } |
| |
| /* process probe response IE from supplicant */ |
| pucP2pIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_WFA, |
| WLAN_OUI_TYPE_WFA_P2P, |
| ProbeRespIE, |
| u4ProbeRespLen); |
| |
| pucWfdIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_WFA, |
| WLAN_OUI_TYPE_WFA_P2P + 1, |
| ProbeRespIE, |
| u4ProbeRespLen); |
| |
| pucWpsIe = (uint8_t *) cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, |
| WLAN_OUI_TYPE_MICROSOFT_WPS, |
| ProbeRespIE, |
| u4ProbeRespLen); |
| |
| if (pucP2pIe) { |
| kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, |
| pucP2pIe, IE_SIZE(pucP2pIe)); |
| prMsduInfo->u2FrameLength += IE_SIZE(pucP2pIe); |
| } |
| |
| if (pucWfdIe) { |
| kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, |
| pucWfdIe, IE_SIZE(pucWfdIe)); |
| prMsduInfo->u2FrameLength += IE_SIZE(pucWfdIe); |
| } |
| |
| if (pucWpsIe) { |
| kalMemCopy(prMsduInfo->prPacket + prMsduInfo->u2FrameLength, |
| pucWpsIe, IE_SIZE(pucWpsIe)); |
| prMsduInfo->u2FrameLength += IE_SIZE(pucWpsIe); |
| } |
| |
| DBGLOG(BSS, INFO, |
| "update probe response for bss index: %d, IE len: %d\n", |
| prP2pBssInfo->ucBssIndex, prMsduInfo->u2FrameLength); |
| /* dumpMemory8(prMsduInfo->prPacket, prMsduInfo->u2FrameLength); */ |
| |
| return nicUpdateBeaconIETemplate(prAdapter, |
| IE_UPD_METHOD_UPDATE_PROBE_RSP, |
| prP2pBssInfo->ucBssIndex, |
| prP2pBssInfo->u2CapInfo, |
| prMsduInfo->prPacket, |
| prMsduInfo->u2FrameLength); |
| } |
| #endif |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to dissolve from group or one group. |
| * (Would not change P2P FSM.) |
| * 1. GC: Disconnect from AP. (Send Deauth) |
| * 2. GO: Disconnect all STA |
| * |
| * @param[in] prAdapter Pointer to the adapter structure. |
| * |
| * @return (none) |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void |
| p2pFuncDissolve(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN u_int8_t fgSendDeauth, |
| IN uint16_t u2ReasonCode) |
| { |
| struct STA_RECORD *prCurrStaRec, *prStaRecNext; |
| struct LINK *prClientList; |
| |
| DEBUGFUNC("p2pFuncDissolve()"); |
| |
| do { |
| |
| ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); |
| |
| switch (prP2pBssInfo->eCurrentOPMode) { |
| case OP_MODE_INFRASTRUCTURE: |
| /* Reset station record status. */ |
| if (prP2pBssInfo->prStaRecOfAP) { |
| #if CFG_WPS_DISCONNECT || (KERNEL_VERSION(4, 4, 0) <= CFG80211_VERSION_CODE) |
| kalP2PGCIndicateConnectionStatus( |
| prAdapter->prGlueInfo, |
| (uint8_t) prP2pBssInfo->u4PrivateData, |
| NULL, NULL, 0, |
| REASON_CODE_DEAUTH_LEAVING_BSS, |
| WLAN_STATUS_MEDIA_DISCONNECT); |
| #else |
| kalP2PGCIndicateConnectionStatus( |
| prAdapter->prGlueInfo, |
| (uint8_t) prP2pBssInfo->u4PrivateData, |
| NULL, NULL, 0, |
| REASON_CODE_DEAUTH_LEAVING_BSS); |
| #endif |
| |
| /* 2012/02/14 frog: |
| * After formation before join group, |
| * prStaRecOfAP is NULL. |
| */ |
| p2pFuncDisconnect(prAdapter, |
| prP2pBssInfo, |
| prP2pBssInfo->prStaRecOfAP, |
| fgSendDeauth, |
| u2ReasonCode); |
| } |
| |
| /* Fix possible KE when RX Beacon & |
| * call nicPmIndicateBssConnected(). |
| * hit prStaRecOfAP == NULL. |
| */ |
| p2pChangeMediaState(prAdapter, |
| prP2pBssInfo, |
| PARAM_MEDIA_STATE_DISCONNECTED); |
| |
| prP2pBssInfo->prStaRecOfAP = NULL; |
| |
| break; |
| case OP_MODE_ACCESS_POINT: |
| /* Under AP mode, we would net |
| * send deauthentication frame to each STA. |
| * We only stop the Beacon & let all stations timeout. |
| */ |
| /* Send deauth. */ |
| authSendDeauthFrame(prAdapter, |
| prP2pBssInfo, |
| NULL, (struct SW_RFB *) NULL, |
| u2ReasonCode, (PFN_TX_DONE_HANDLER) NULL); |
| |
| prClientList = &prP2pBssInfo->rStaRecOfClientList; |
| |
| /* This case may let LINK_FOR_EACH_ENTRY_SAFE crash */ |
| if (prClientList == NULL) |
| break; |
| LINK_FOR_EACH_ENTRY_SAFE(prCurrStaRec, prStaRecNext, |
| prClientList, rLinkEntry, struct STA_RECORD) { |
| ASSERT(prCurrStaRec); |
| p2pFuncDisconnect(prAdapter, |
| prP2pBssInfo, prCurrStaRec, |
| TRUE, u2ReasonCode); |
| } |
| break; |
| default: |
| return; /* 20110420 -- alreay in Device Mode. */ |
| } |
| |
| /* Make the deauth frame send to FW ASAP. */ |
| #if !CFG_SUPPORT_MULTITHREAD |
| wlanAcquirePowerControl(prAdapter); |
| #endif |
| wlanProcessCommandQueue(prAdapter, |
| &prAdapter->prGlueInfo->rCmdQueue); |
| #if !CFG_SUPPORT_MULTITHREAD |
| wlanReleasePowerControl(prAdapter); |
| #endif |
| |
| /*kalMdelay(100);*/ |
| |
| /* Change Connection Status. */ |
| /* 20161025, can not set DISCONNECTED if clientcount > 0 */ |
| /*p2pChangeMediaState(prAdapter, |
| * prP2pBssInfo, PARAM_MEDIA_STATE_DISCONNECTED); |
| */ |
| |
| } while (FALSE); |
| } /* p2pFuncDissolve */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is called to dissolve from group or one group. |
| * (Would not change P2P FSM.) |
| * 1. GC: Disconnect from AP. (Send Deauth) |
| * 2. GO: Disconnect all STA |
| * |
| * @param[in] prAdapter Pointer to the adapter structure. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| void |
| p2pFuncDisconnect(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN struct STA_RECORD *prStaRec, |
| IN u_int8_t fgSendDeauth, IN uint16_t u2ReasonCode) |
| { |
| enum ENUM_PARAM_MEDIA_STATE eOriMediaStatus; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prStaRec != NULL) && (prP2pBssInfo != NULL)); |
| |
| ASSERT_BREAK(prP2pBssInfo->eNetworkType == NETWORK_TYPE_P2P); |
| |
| ASSERT_BREAK(prP2pBssInfo->ucBssIndex |
| < prAdapter->ucP2PDevBssIdx); |
| |
| eOriMediaStatus = prP2pBssInfo->eConnectionState; |
| |
| /* Indicate disconnect. */ |
| if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, |
| prP2pBssInfo->u4PrivateData); |
| |
| kalP2PGOStationUpdate(prAdapter->prGlueInfo, |
| prP2pRoleFsmInfo->ucRoleIndex, prStaRec, FALSE); |
| } else { |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, |
| prP2pBssInfo->u4PrivateData); |
| |
| prP2pRoleFsmInfo->rJoinInfo.prTargetBssDesc = NULL; |
| |
| scanRemoveConnFlagOfBssDescByBssid(prAdapter, |
| prP2pBssInfo->aucBSSID); |
| } |
| |
| DBGLOG(P2P, INFO, |
| "p2pFuncDisconnect(): BssMode: %d, reason: %d, SendDeauth %s\n", |
| prP2pBssInfo->eCurrentOPMode, u2ReasonCode, |
| fgSendDeauth == TRUE ? "TRUE" : "FALSE"); |
| |
| if (fgSendDeauth) { |
| /* Send deauth. */ |
| authSendDeauthFrame(prAdapter, |
| prP2pBssInfo, |
| prStaRec, |
| (struct SW_RFB *) NULL, |
| u2ReasonCode, |
| (PFN_TX_DONE_HANDLER) |
| p2pRoleFsmRunEventDeauthTxDone); |
| |
| /* Make the deauth frame send to FW ASAP. */ |
| #if !CFG_SUPPORT_MULTITHREAD |
| wlanAcquirePowerControl(prAdapter); |
| #endif |
| wlanProcessCommandQueue(prAdapter, |
| &prAdapter->prGlueInfo->rCmdQueue); |
| #if !CFG_SUPPORT_MULTITHREAD |
| wlanReleasePowerControl(prAdapter); |
| #endif |
| } else { |
| /* Change station state. */ |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); |
| |
| /* Reset Station Record Status. */ |
| p2pFuncResetStaRecStatus(prAdapter, prStaRec); |
| |
| cnmStaRecFree(prAdapter, prStaRec); |
| |
| if ((prP2pBssInfo->eCurrentOPMode |
| != OP_MODE_ACCESS_POINT) || |
| (bssGetClientCount(prAdapter, prP2pBssInfo) == 0)) { |
| DBGLOG(P2P, TRACE, |
| "No More Client, Media Status DISCONNECTED\n"); |
| p2pChangeMediaState(prAdapter, |
| prP2pBssInfo, |
| PARAM_MEDIA_STATE_DISCONNECTED); |
| } |
| |
| if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { |
| /* Update Disconnected state to FW. */ |
| nicUpdateBss(prAdapter, |
| prP2pBssInfo->ucBssIndex); |
| } |
| |
| } |
| } while (FALSE); |
| |
| return; |
| |
| } /* p2pFuncDisconnect */ |
| |
| void p2pFuncSetChannel(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucRoleIdx, |
| IN struct RF_CHANNEL_INFO *prRfChannelInfo) |
| { |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| (struct P2P_ROLE_FSM_INFO *) NULL; |
| struct P2P_CONNECTION_REQ_INFO *prP2pConnReqInfo = |
| (struct P2P_CONNECTION_REQ_INFO *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prRfChannelInfo != NULL)); |
| |
| prP2pRoleFsmInfo = |
| P2P_ROLE_INDEX_2_ROLE_FSM_INFO(prAdapter, ucRoleIdx); |
| if (!prP2pRoleFsmInfo) |
| break; |
| prP2pConnReqInfo = &(prP2pRoleFsmInfo->rConnReqInfo); |
| |
| prP2pConnReqInfo->rChannelInfo.ucChannelNum = |
| prRfChannelInfo->ucChannelNum; |
| prP2pConnReqInfo->rChannelInfo.eBand = prRfChannelInfo->eBand; |
| prP2pConnReqInfo->eChnlBw = prRfChannelInfo->ucChnlBw; |
| prP2pConnReqInfo->u2PriChnlFreq = |
| prRfChannelInfo->u2PriChnlFreq; |
| prP2pConnReqInfo->u4CenterFreq1 = |
| prRfChannelInfo->u4CenterFreq1; |
| prP2pConnReqInfo->u4CenterFreq2 = |
| prRfChannelInfo->u4CenterFreq2; |
| #if IS_ENABLED(CFG_CCN7_SAP_EASYMESH) |
| /* Update TX-pwr as soon as channel changed */ |
| { |
| struct PARAM_CUSTOM_GET_TX_POWER rGetTxPower; |
| struct BSS_INFO *prP2pRoleBssInfo = |
| (struct BSS_INFO *) NULL; |
| uint32_t rStatus = WLAN_STATUS_SUCCESS; |
| uint32_t u4BufLen = 0; |
| |
| prP2pRoleBssInfo = |
| GET_BSS_INFO_BY_INDEX(prAdapter, |
| prP2pRoleFsmInfo->ucBssIndex); |
| kalMemZero(&rGetTxPower, |
| sizeof(struct PARAM_CUSTOM_GET_TX_POWER)); |
| rGetTxPower.ucCenterChannel = |
| prP2pRoleBssInfo->ucPrimaryChannel; |
| rGetTxPower.ucBand = prP2pRoleBssInfo->eBand; |
| rGetTxPower.ucDbdcIdx = ENUM_BAND_0; |
| |
| rStatus = kalIoctl(prAdapter->prGlueInfo, |
| wlanoidQueryGetTxPower, |
| &rGetTxPower, |
| sizeof(struct PARAM_CUSTOM_GET_TX_POWER), |
| TRUE, TRUE, TRUE, &u4BufLen); |
| |
| if (rStatus != WLAN_STATUS_SUCCESS) |
| DBGLOG(OID, ERROR, |
| "ERR: Get TxPower fail (%x)\r\n", rStatus); |
| } |
| #endif /* CFG_CCN7_SAP_EASYMESH */ |
| |
| } while (FALSE); |
| } /* p2pFuncSetChannel */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH |
| * |
| * @param[in] prStaRec Pointer to the STA_RECORD_T |
| * |
| * @retval TRUE We will retry JOIN |
| * @retval FALSE We will not retry JOIN |
| */ |
| /*---------------------------------------------------------------------------*/ |
| u_int8_t p2pFuncRetryJOIN(IN struct ADAPTER *prAdapter, |
| IN struct STA_RECORD *prStaRec, |
| IN struct P2P_JOIN_INFO *prJoinInfo) |
| { |
| struct MSG_SAA_FSM_START *prJoinReqMsg = |
| (struct MSG_SAA_FSM_START *) NULL; |
| u_int8_t fgRetValue = FALSE; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prStaRec != NULL) |
| && (prJoinInfo != NULL)); |
| |
| /* Retry other AuthType if possible */ |
| if (!prJoinInfo->ucAvailableAuthTypes) |
| break; |
| |
| if (prJoinInfo->ucAvailableAuthTypes |
| & (uint8_t) AUTH_TYPE_SHARED_KEY) { |
| |
| DBGLOG(P2P, INFO, |
| "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); |
| |
| prJoinInfo->ucAvailableAuthTypes &= |
| ~(uint8_t) AUTH_TYPE_SHARED_KEY; |
| |
| prStaRec->ucAuthAlgNum = |
| (uint8_t) AUTH_ALGORITHM_NUM_SHARED_KEY; |
| } else { |
| DBGLOG(P2P, ERROR, |
| "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); |
| ASSERT(0); |
| break; |
| } |
| |
| /* No more available Auth Types */ |
| prJoinInfo->ucAvailableAuthTypes = 0; |
| |
| /* Trigger SAA to start JOIN process. */ |
| prJoinReqMsg = (struct MSG_SAA_FSM_START *) |
| cnmMemAlloc(prAdapter, RAM_TYPE_MSG, |
| sizeof(struct MSG_SAA_FSM_START)); |
| if (!prJoinReqMsg) { |
| ASSERT(0); /* Can't trigger SAA FSM */ |
| break; |
| } |
| |
| prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; |
| prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; |
| prJoinReqMsg->prStaRec = prStaRec; |
| |
| mboxSendMsg(prAdapter, |
| MBOX_ID_0, |
| (struct MSG_HDR *) prJoinReqMsg, |
| MSG_SEND_METHOD_BUF); |
| |
| fgRetValue = TRUE; |
| } while (FALSE); |
| |
| return fgRetValue; |
| |
| } /* end of p2pFuncRetryJOIN() */ |
| |
| struct BSS_INFO *p2pFuncBSSIDFindBssInfo(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucBSSID) |
| { |
| struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; |
| uint8_t ucBssIdx = 0; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (pucBSSID != NULL)); |
| |
| for (ucBssIdx = 0; |
| ucBssIdx < prAdapter->ucHwBssIdNum; ucBssIdx++) { |
| if (!IS_NET_ACTIVE(prAdapter, ucBssIdx)) |
| continue; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); |
| |
| if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, pucBSSID) |
| && IS_BSS_P2P(prBssInfo)) |
| break; |
| |
| prBssInfo = NULL; |
| } |
| |
| } while (FALSE); |
| |
| return prBssInfo; |
| } /* p2pFuncBSSIDFindBssInfo */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will validate the Rx Auth Frame and then return |
| * the status code to AAA to indicate |
| * if need to perform following actions |
| * when the specified conditions were matched. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prSwRfb Pointer to SW RFB data structure. |
| * @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. |
| * @param[out] pu2StatusCode The Status Code of Validation Result |
| * |
| * @retval TRUE Reply the Auth |
| * @retval FALSE Don't reply the Auth |
| */ |
| /*---------------------------------------------------------------------------*/ |
| u_int8_t |
| p2pFuncValidateAuth(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN struct SW_RFB *prSwRfb, |
| IN struct STA_RECORD **pprStaRec, |
| OUT uint16_t *pu2StatusCode) |
| { |
| u_int8_t fgPmfConn = FALSE; |
| struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; |
| struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL; |
| |
| DBGLOG(P2P, TRACE, "p2pValidate Authentication Frame\n"); |
| |
| |
| /* P2P 3.2.8 */ |
| *pu2StatusCode = STATUS_CODE_REQ_DECLINED; |
| prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader; |
| |
| if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || |
| (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { |
| /* We are not under AP Mode yet. */ |
| DBGLOG(P2P, WARN, |
| "Current OP mode is not under AP mode. (%d)\n", |
| prP2pBssInfo->eCurrentOPMode); |
| return FALSE; |
| } |
| |
| prStaRec = cnmGetStaRecByAddress(prAdapter, |
| prP2pBssInfo->ucBssIndex, prAuthFrame->aucSrcAddr); |
| |
| if (!prStaRec) { |
| prStaRec = cnmStaRecAlloc(prAdapter, STA_TYPE_P2P_GC, |
| prP2pBssInfo->ucBssIndex, |
| prAuthFrame->aucSrcAddr); |
| |
| /* TODO(Kevin): Error handling of allocation of |
| * struct STA_RECORD for |
| * exhausted case and do removal of unused struct STA_RECORD. |
| */ |
| /* Sent a message event to clean un-used STA_RECORD_T. */ |
| if (!prStaRec) { |
| /* Error: Too many auth cause lacking the free StaRec. |
| * Response the auth with STATUS_CODE_REQ_DECLINED. |
| */ |
| DBGLOG(P2P, WARN, |
| "StaRec Full. (%d)\n", CFG_STA_REC_NUM); |
| return TRUE; |
| } |
| |
| prSwRfb->ucStaRecIdx = prStaRec->ucIndex; |
| |
| prStaRec->u2BSSBasicRateSet = prP2pBssInfo->u2BSSBasicRateSet; |
| |
| prStaRec->u2DesiredNonHTRateSet = RATE_SET_ERP_P2P; |
| |
| prStaRec->u2OperationalRateSet = RATE_SET_ERP_P2P; |
| prStaRec->ucPhyTypeSet = PHY_TYPE_SET_802_11GN; |
| |
| /* Update default Tx rate */ |
| nicTxUpdateStaRecDefaultRate(prStaRec); |
| |
| /* NOTE(Kevin): Better to change state here, not at TX Done */ |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); |
| } else { |
| #if CFG_SUPPORT_802_11W |
| /* AP PMF. if PMF connection, do not reset state & FSM */ |
| fgPmfConn = rsnCheckBipKeyInstalled(prAdapter, prStaRec); |
| if (fgPmfConn) { |
| DBGLOG(P2P, WARN, "PMF Connction, return false\n"); |
| return FALSE; |
| } |
| #endif |
| |
| prSwRfb->ucStaRecIdx = prStaRec->ucIndex; |
| |
| if ((prStaRec->ucStaState > STA_STATE_1) |
| && (IS_STA_IN_P2P(prStaRec))) { |
| |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); |
| |
| p2pFuncResetStaRecStatus(prAdapter, prStaRec); |
| |
| bssRemoveClient(prAdapter, prP2pBssInfo, prStaRec); |
| } |
| |
| } |
| |
| if (bssGetClientCount(prAdapter, prP2pBssInfo) |
| >= P2P_MAXIMUM_CLIENT_COUNT |
| || !p2pRoleProcessACLInspection(prAdapter, |
| prStaRec->aucMacAddr, prP2pBssInfo->ucBssIndex) |
| #if CFG_SUPPORT_HOTSPOT_WPS_MANAGER |
| || kalP2PMaxClients(prAdapter->prGlueInfo, |
| bssGetClientCount(prAdapter, prP2pBssInfo), |
| (uint8_t) prP2pBssInfo->u4PrivateData) |
| #endif |
| ) { |
| /* GROUP limit full. */ |
| /* P2P 3.2.8 */ |
| DBGLOG(P2P, WARN, |
| "Group Limit Full. (%d)\n", |
| bssGetClientCount(prAdapter, prP2pBssInfo)); |
| cnmStaRecFree(prAdapter, prStaRec); |
| *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD; |
| return TRUE; |
| } |
| #if CFG_SUPPORT_HOTSPOT_WPS_MANAGER |
| else { |
| /* Hotspot Blacklist */ |
| if (kalP2PCmpBlackList(prAdapter->prGlueInfo, |
| prAuthFrame->aucSrcAddr, |
| (uint8_t) prP2pBssInfo->u4PrivateData)) { |
| DBGLOG(P2P, WARN, "in black list.\n"); |
| return FALSE; |
| } |
| |
| } |
| #endif |
| /* prStaRec->eStaType = STA_TYPE_INFRA_CLIENT; */ |
| prStaRec->eStaType = STA_TYPE_P2P_GC; |
| |
| /* Update Station Record - Status/Reason Code */ |
| prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; |
| |
| prStaRec->ucJoinFailureCount = 0; |
| |
| *pprStaRec = prStaRec; |
| |
| *pu2StatusCode = STATUS_CODE_SUCCESSFUL; |
| |
| |
| return TRUE; |
| |
| } /* p2pFuncValidateAuth */ |
| |
| void p2pFuncResetStaRecStatus(IN struct ADAPTER *prAdapter, |
| IN struct STA_RECORD *prStaRec) |
| { |
| do { |
| if ((prAdapter == NULL) || (prStaRec == NULL)) { |
| ASSERT(FALSE); |
| break; |
| } |
| |
| prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; |
| prStaRec->u2ReasonCode = REASON_CODE_RESERVED; |
| prStaRec->ucJoinFailureCount = 0; |
| prStaRec->fgTransmitKeyExist = FALSE; |
| |
| prStaRec->fgSetPwrMgtBit = FALSE; |
| |
| } while (FALSE); |
| } /* p2pFuncResetStaRecStatus */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief The function is used to initialize the value |
| * of the connection settings for P2P network |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void |
| p2pFuncInitConnectionSettings(IN struct ADAPTER *prAdapter, |
| IN struct P2P_CONNECTION_SETTINGS *prP2PConnSettings, |
| IN u_int8_t fgIsApMode) |
| { |
| struct WIFI_VAR *prWifiVar = NULL; |
| |
| ASSERT(prP2PConnSettings); |
| |
| prWifiVar = &(prAdapter->rWifiVar); |
| ASSERT(prWifiVar); |
| |
| prP2PConnSettings->fgIsApMode = fgIsApMode; |
| |
| #if CFG_SUPPORT_HOTSPOT_WPS_MANAGER |
| prP2PConnSettings->fgIsWPSMode = prWifiVar->ucApWpsMode; |
| #endif |
| } /* p2pFuncInitConnectionSettings */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will validate the Rx Assoc Req Frame and then return |
| * the status code to AAA to indicate if need |
| * to perform following actions |
| * when the specified conditions were matched. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prSwRfb Pointer to SW RFB data structure. |
| * @param[out] pu2StatusCode The Status Code of Validation Result |
| * |
| * @retval TRUE Reply the Assoc Resp |
| * @retval FALSE Don't reply the Assoc Resp |
| */ |
| /*---------------------------------------------------------------------------*/ |
| u_int8_t p2pFuncValidateAssocReq(IN struct ADAPTER *prAdapter, |
| IN struct SW_RFB *prSwRfb, |
| OUT uint16_t *pu2StatusCode) |
| { |
| u_int8_t fgReplyAssocResp = TRUE; |
| struct WLAN_ASSOC_REQ_FRAME *prAssocReqFrame = |
| (struct WLAN_ASSOC_REQ_FRAME *) NULL; |
| struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| |
| /* TODO(Kevin): Call P2P functions to check .. |
| * 2. Check we can accept connection from thsi peer |
| * a. If we are in PROVISION state, |
| * only accept the peer we do the GO formation previously. |
| * b. If we are in OPERATION state, only accept |
| * the other peer when P2P_GROUP_LIMIT is 0. |
| * 3. Check Black List here. |
| */ |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prSwRfb != NULL) && (pu2StatusCode != NULL)); |
| |
| *pu2StatusCode = STATUS_CODE_REQ_DECLINED; |
| prAssocReqFrame = |
| (struct WLAN_ASSOC_REQ_FRAME *) prSwRfb->pvHeader; |
| |
| prP2pBssInfo = |
| p2pFuncBSSIDFindBssInfo(prAdapter, |
| prAssocReqFrame->aucBSSID); |
| |
| if (prP2pBssInfo == NULL) { |
| DBGLOG(P2P, ERROR, |
| "RX ASSOC frame without BSS active / BSSID match\n"); |
| ASSERT(FALSE); |
| break; |
| } |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); |
| |
| if (prStaRec == NULL) { |
| /* Station record should be ready |
| * while RX AUTH frame. |
| */ |
| fgReplyAssocResp = FALSE; |
| ASSERT(FALSE); |
| break; |
| } |
| ASSERT(prSwRfb->prRxStatusGroup3); |
| prStaRec->ucRCPI = |
| nicRxGetRcpiValueFromRxv(RCPI_MODE_MAX, prSwRfb); |
| |
| prStaRec->u2DesiredNonHTRateSet &= |
| prP2pBssInfo->u2OperationalRateSet; |
| prStaRec->ucDesiredPhyTypeSet = |
| prStaRec->ucPhyTypeSet & prP2pBssInfo->ucPhyTypeSet; |
| |
| if (prStaRec->ucDesiredPhyTypeSet == 0) { |
| /* The station only support 11B rate. */ |
| *pu2StatusCode = |
| STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; |
| break; |
| } |
| |
| *pu2StatusCode = STATUS_CODE_SUCCESSFUL; |
| |
| } while (FALSE); |
| |
| return fgReplyAssocResp; |
| |
| } /* p2pFuncValidateAssocReq */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to check the TKIP IE |
| * |
| * |
| * @return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| u_int8_t p2pFuncParseCheckForTKIPInfoElem(IN uint8_t *pucBuf) |
| { |
| uint8_t aucWfaOui[] = VENDOR_OUI_WFA; |
| struct WPA_INFO_ELEM *prWpaIE = (struct WPA_INFO_ELEM *) NULL; |
| uint32_t u4GroupKeyCipher = 0; |
| |
| if (pucBuf == NULL) |
| return FALSE; |
| |
| prWpaIE = (struct WPA_INFO_ELEM *) pucBuf; |
| |
| if (prWpaIE->ucLength <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) |
| return FALSE; |
| |
| if (kalMemCmp(prWpaIE->aucOui, aucWfaOui, sizeof(aucWfaOui))) |
| return FALSE; |
| |
| WLAN_GET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, &u4GroupKeyCipher); |
| |
| if (prWpaIE->ucOuiType == VENDOR_OUI_TYPE_WPA && |
| u4GroupKeyCipher == WPA_CIPHER_SUITE_TKIP) |
| return TRUE; |
| else |
| return FALSE; |
| } /* p2pFuncParseCheckForP2PInfoElem */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to check the P2P IE |
| * |
| * |
| * @return none |
| */ |
| /*---------------------------------------------------------------------------*/ |
| u_int8_t p2pFuncParseCheckForP2PInfoElem(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucBuf, OUT uint8_t *pucOuiType) |
| { |
| uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; |
| struct IE_WFA *prWfaIE = (struct IE_WFA *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (pucBuf != NULL) && (pucOuiType != NULL)); |
| |
| prWfaIE = (struct IE_WFA *) pucBuf; |
| |
| if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { |
| break; |
| } else if (prWfaIE->aucOui[0] != aucWfaOui[0] || |
| prWfaIE->aucOui[1] != aucWfaOui[1] || |
| prWfaIE->aucOui[2] != aucWfaOui[2]) { |
| break; |
| } |
| |
| *pucOuiType = prWfaIE->ucOuiType; |
| |
| return TRUE; |
| } while (FALSE); |
| |
| return FALSE; |
| } /* p2pFuncParseCheckForP2PInfoElem */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will validate the Rx Probe Request Frame and then return |
| * result to BSS to indicate if need to send |
| * the corresponding Probe Response Frame |
| * if the specified conditions were matched. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prSwRfb Pointer to SW RFB data structure. |
| * @param[out] pu4ControlFlags Control flags for replying the Probe Response |
| * |
| * @retval TRUE Reply the Probe Response |
| * @retval FALSE Don't reply the Probe Response |
| */ |
| /*---------------------------------------------------------------------------*/ |
| u_int8_t |
| p2pFuncValidateProbeReq(IN struct ADAPTER *prAdapter, |
| IN struct SW_RFB *prSwRfb, |
| OUT uint32_t *pu4ControlFlags, |
| IN u_int8_t fgIsDevInterface, |
| IN uint8_t ucRoleIdx) |
| { |
| u_int8_t fgIsReplyProbeRsp = FALSE; |
| u_int8_t fgApplyp2PDevFilter = FALSE; |
| struct P2P_ROLE_FSM_INFO *prP2pRoleFsmInfo = |
| (struct P2P_ROLE_FSM_INFO *) NULL; |
| |
| DEBUGFUNC("p2pFuncValidateProbeReq"); |
| |
| do { |
| |
| ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); |
| |
| prP2pRoleFsmInfo = |
| prAdapter->rWifiVar.aprP2pRoleFsmInfo[ucRoleIdx]; |
| |
| /* Process both cases that with amd without add p2p interface */ |
| if (fgIsDevInterface) |
| fgApplyp2PDevFilter = TRUE; |
| else { |
| if (prAdapter->prGlueInfo->prP2PInfo[0]->prDevHandler == |
| prAdapter->prGlueInfo->prP2PInfo |
| [ucRoleIdx]->aprRoleHandler) |
| fgApplyp2PDevFilter = TRUE; |
| else |
| fgApplyp2PDevFilter = FALSE; |
| } |
| /* TODO: */ |
| if ((fgApplyp2PDevFilter && |
| (prAdapter->u4OsPacketFilter |
| & PARAM_PACKET_FILTER_PROBE_REQ)) |
| || (!fgApplyp2PDevFilter && |
| (prP2pRoleFsmInfo->u4P2pPacketFilter |
| & PARAM_PACKET_FILTER_PROBE_REQ))) { |
| /* Leave the probe response to p2p_supplicant. */ |
| kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, |
| prSwRfb, fgIsDevInterface, ucRoleIdx); |
| } |
| |
| } while (FALSE); |
| |
| return fgIsReplyProbeRsp; |
| |
| } /* end of p2pFuncValidateProbeReq() */ |
| |
| static void p2pFunBufferP2pActionFrame(IN struct ADAPTER *prAdapter, |
| IN struct SW_RFB *prSwRfb, |
| IN uint8_t ucRoleIdx) |
| { |
| struct P2P_DEV_FSM_INFO *prP2pDevFsmInfo = |
| (struct P2P_DEV_FSM_INFO *) NULL; |
| struct P2P_QUEUED_ACTION_FRAME *prFrame; |
| |
| prP2pDevFsmInfo = prAdapter->rWifiVar.prP2pDevFsmInfo; |
| |
| if (prP2pDevFsmInfo == NULL) |
| return; |
| |
| prFrame = &prP2pDevFsmInfo->rQueuedActionFrame; |
| |
| if (prFrame->u2Length > 0) { |
| DBGLOG(P2P, WARN, "p2p action frames are pending, drop it.\n"); |
| return; |
| } |
| |
| DBGLOG(P2P, INFO, "Buffer the p2p action frame.\n"); |
| prFrame->ucRoleIdx = ucRoleIdx; |
| prFrame->u4Freq = nicChannelNum2Freq( |
| HAL_RX_STATUS_GET_CHNL_NUM(prSwRfb->prRxStatus)) / 1000; |
| prFrame->u2Length = prSwRfb->u2PacketLen; |
| prFrame->prHeader = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, |
| prSwRfb->u2PacketLen); |
| if (prFrame->prHeader == NULL) { |
| DBGLOG(P2P, WARN, "Allocate buffer fail.\n"); |
| p2pFunCleanQueuedMgmtFrame(prAdapter, prFrame); |
| return; |
| } |
| kalMemCopy(prFrame->prHeader, prSwRfb->pvHeader, prSwRfb->u2PacketLen); |
| } |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will validate the Rx Probe Request Frame and then return |
| * result to BSS to indicate if need to send |
| * the corresponding Probe Response |
| * Frame if the specified conditions were matched. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prSwRfb Pointer to SW RFB data structure. |
| * @param[out] pu4ControlFlags Control flags for replying the Probe Response |
| * |
| * @retval TRUE Reply the Probe Response |
| * @retval FALSE Don't reply the Probe Response |
| */ |
| /*--------------------------------------------------------------------------*/ |
| void p2pFuncValidateRxActionFrame(IN struct ADAPTER *prAdapter, |
| IN struct SW_RFB *prSwRfb, IN u_int8_t fgIsDevInterface, |
| IN uint8_t ucRoleIdx) |
| { |
| struct WLAN_ACTION_FRAME *prActFrame; |
| struct WLAN_PUBLIC_VENDOR_ACTION_FRAME *prActPubVenFrame; |
| uint32_t u4OUI; |
| u_int8_t fgBufferFrame = FALSE; |
| |
| DEBUGFUNC("p2pFuncValidateRxActionFrame"); |
| |
| do { |
| |
| ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); |
| prActFrame = (struct WLAN_ACTION_FRAME *) prSwRfb->pvHeader; |
| |
| switch (prActFrame->ucCategory) { |
| case CATEGORY_PUBLIC_ACTION: |
| if (prActFrame->ucAction != 0x9 || |
| prSwRfb->u2PacketLen < |
| sizeof(struct WLAN_PUBLIC_VENDOR_ACTION_FRAME)) |
| break; |
| WLAN_GET_FIELD_BE32( |
| prActFrame->ucActionDetails, &u4OUI); |
| DBGLOG(P2P, TRACE, "Action: oui: 0x%x\n", u4OUI); |
| if (u4OUI != P2P_IE_VENDOR_TYPE) |
| break; |
| |
| prActPubVenFrame = |
| (struct WLAN_PUBLIC_VENDOR_ACTION_FRAME *) |
| prActFrame; |
| p2pProcessActionResponse(prAdapter, |
| prActPubVenFrame->ucPubSubType); |
| if (fgIsDevInterface) { |
| p2pDevFsmNotifyP2pRx(prAdapter, |
| prActPubVenFrame->ucPubSubType, |
| &fgBufferFrame); |
| } |
| default: |
| break; |
| } |
| |
| if (fgBufferFrame) { |
| p2pFunBufferP2pActionFrame(prAdapter, |
| prSwRfb, |
| ucRoleIdx); |
| break; |
| } |
| |
| if (prAdapter->u4OsPacketFilter |
| & PARAM_PACKET_FILTER_ACTION_FRAME) { |
| /* Leave the Action frame to p2p_supplicant. */ |
| kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, |
| prSwRfb, fgIsDevInterface, ucRoleIdx); |
| } else { |
| struct GL_P2P_INFO *prGlueP2pInfo = NULL; |
| struct net_device *prNetdevice = |
| (struct net_device *)NULL; |
| |
| DBGLOG(P2P, TRACE, |
| "do not indicate action frame as filter closed\n"); |
| if (ucRoleIdx >= BSS_P2P_NUM) |
| break; |
| prGlueP2pInfo = |
| prAdapter->prGlueInfo->prP2PInfo[ucRoleIdx]; |
| if (!prGlueP2pInfo) |
| break; |
| if (fgIsDevInterface) |
| prNetdevice = prGlueP2pInfo->prDevHandler; |
| else |
| prNetdevice = prGlueP2pInfo->aprRoleHandler; |
| if (prNetdevice && (*(prNetdevice->name) != '\0')) { |
| DBGLOG(P2P, TRACE, |
| "[%s] unregistered p2p action packet filter 0x%x\n", |
| prNetdevice->name, |
| prAdapter->u4OsPacketFilter); |
| } |
| } |
| |
| } while (FALSE); |
| |
| return; |
| |
| } /* p2pFuncValidateRxMgmtFrame */ |
| |
| u_int8_t p2pFuncIsAPMode(IN struct P2P_CONNECTION_SETTINGS *prP2pConnSettings) |
| { |
| if (prP2pConnSettings) { |
| if (prP2pConnSettings->fgIsWPSMode == 1) |
| return FALSE; |
| return prP2pConnSettings->fgIsApMode; |
| } else { |
| return FALSE; |
| } |
| } |
| |
| /* p2pFuncIsAPMode */ |
| |
| void |
| p2pFuncParseBeaconContent(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN uint8_t *pucIEInfo, IN uint32_t u4IELen) |
| { |
| uint8_t *pucIE = (uint8_t *) NULL; |
| uint16_t u2Offset = 0; |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = |
| (struct P2P_SPECIFIC_BSS_INFO *) NULL; |
| uint8_t i = 0; |
| struct RSN_INFO rRsnIe; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); |
| |
| if (u4IELen == 0) |
| break; |
| |
| prP2pSpecificBssInfo = |
| prAdapter->rWifiVar.prP2pSpecificBssInfo |
| [prP2pBssInfo->u4PrivateData]; |
| prP2pSpecificBssInfo->u2AttributeLen = 0; |
| prP2pSpecificBssInfo->u2WpaIeLen = 0; |
| prP2pSpecificBssInfo->u2RsnIeLen = 0; |
| |
| ASSERT_BREAK(pucIEInfo != NULL); |
| |
| pucIE = pucIEInfo; |
| |
| if (prP2pBssInfo->u2CapInfo & CAP_INFO_PRIVACY) |
| kalP2PSetCipher(prAdapter->prGlueInfo, |
| IW_AUTH_CIPHER_WEP40, |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| else |
| kalP2PSetCipher(prAdapter->prGlueInfo, |
| IW_AUTH_CIPHER_NONE, |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| |
| prP2pBssInfo->ucCountryIELen = 0; |
| |
| IE_FOR_EACH(pucIE, u4IELen, u2Offset) { |
| switch (IE_ID(pucIE)) { |
| case ELEM_ID_SSID: /* 0 *//* V *//* Done */ |
| { |
| |
| /* DBGLOG(P2P, TRACE, ("SSID update\n")); */ |
| /* SSID is saved when start AP/GO */ |
| /* SSID IE set in beacon from supplicant |
| * will not always be |
| * the true since hidden SSID case |
| */ |
| #if 0 |
| COPY_SSID( |
| prP2pBssInfo->aucSSID, |
| prP2pBssInfo->ucSSIDLen, |
| SSID_IE(pucIE)->aucSSID, |
| SSID_IE(pucIE)->ucLength); |
| |
| COPY_SSID( |
| prP2pSpecificBssInfo->aucGroupSsid, |
| prP2pSpecificBssInfo->u2GroupSsidLen, |
| SSID_IE(pucIE)->aucSSID, |
| SSID_IE(pucIE)->ucLength); |
| #endif |
| |
| } |
| break; |
| case ELEM_ID_SUP_RATES: /* 1 *//* V *//* Done */ |
| { |
| #ifndef CFG_SUPPORT_P2P_GO_KEEP_RATE_SETTING |
| DBGLOG(P2P, TRACE, "Support Rate IE\n"); |
| if ((SUP_RATES_IE(pucIE)->ucLength) |
| > ELEM_MAX_LEN_SUP_RATES) |
| SUP_RATES_IE(pucIE)->ucLength = |
| ELEM_MAX_LEN_SUP_RATES; |
| kalMemCopy( |
| prP2pBssInfo->aucAllSupportedRates, |
| SUP_RATES_IE(pucIE)->aucSupportedRates, |
| SUP_RATES_IE(pucIE)->ucLength); |
| prP2pBssInfo->ucAllSupportedRatesLen = |
| SUP_RATES_IE(pucIE)->ucLength; |
| DBGLOG_MEM8(P2P, TRACE, |
| SUP_RATES_IE(pucIE)->aucSupportedRates, |
| SUP_RATES_IE(pucIE)->ucLength); |
| #endif |
| } |
| break; |
| case ELEM_ID_DS_PARAM_SET: /* 3 *//* V *//* Done */ |
| { |
| DBGLOG(P2P, TRACE, |
| "DS PARAM IE: %d.\n", |
| DS_PARAM_IE(pucIE)->ucCurrChnl); |
| |
| /* prP2pBssInfo->ucPrimaryChannel = |
| * DS_PARAM_IE(pucIE)->ucCurrChnl; |
| */ |
| |
| /* prP2pBssInfo->eBand = BAND_2G4; */ |
| } |
| break; |
| case ELEM_ID_TIM: /* 5 *//* V */ |
| TIM_IE(pucIE)->ucDTIMPeriod = |
| prP2pBssInfo->ucDTIMPeriod; |
| DBGLOG(P2P, TRACE, |
| "TIM IE, Len:%d, DTIM:%d\n", |
| IE_LEN(pucIE), |
| TIM_IE(pucIE)->ucDTIMPeriod); |
| break; |
| case ELEM_ID_COUNTRY_INFO: /* 7 */ |
| if (COUNTRY_IE(pucIE)->ucLength |
| >= ELEM_MIN_LEN_COUNTRY_INFO) { |
| prP2pBssInfo->ucCountryIELen = |
| COUNTRY_IE(pucIE)->ucLength; |
| kalMemCopy( |
| prP2pBssInfo->aucCountryStr, |
| COUNTRY_IE(pucIE)->aucCountryStr, 3); |
| kalMemCopy( |
| prP2pBssInfo->aucSubbandTriplet, |
| COUNTRY_IE(pucIE)->arCountryStr, |
| COUNTRY_IE(pucIE)->ucLength - 3); |
| } |
| break; |
| case ELEM_ID_ERP_INFO: /* 42 *//* V */ |
| { |
| #if 1 |
| /* This IE would dynamic change due to |
| * FW detection change is required. |
| */ |
| DBGLOG(P2P, TRACE, |
| "ERP IE will be over write by driver\n"); |
| DBGLOG(P2P, TRACE, |
| " ucERP: %x.\n", |
| ERP_INFO_IE(pucIE)->ucERP); |
| |
| #else |
| /* This IE would dynamic change due to |
| * FW detection change is required. |
| */ |
| DBGLOG(P2P, TRACE, "ERP IE.\n"); |
| |
| prP2pBssInfo->ucPhyTypeSet |= |
| PHY_TYPE_SET_802_11GN; |
| |
| ASSERT(prP2pBssInfo->eBand == BAND_2G4); |
| |
| prP2pBssInfo->fgObssErpProtectMode = |
| ((ERP_INFO_IE(pucIE)->ucERP |
| & ERP_INFO_USE_PROTECTION) |
| ? TRUE : FALSE); |
| |
| prP2pBssInfo->fgErpProtectMode = |
| ((ERP_INFO_IE(pucIE)->ucERP |
| & (ERP_INFO_USE_PROTECTION | |
| ERP_INFO_NON_ERP_PRESENT)) |
| ? TRUE : FALSE); |
| #endif |
| |
| } |
| break; |
| case ELEM_ID_HT_CAP: /* 45 *//* V */ |
| { |
| #if 1 |
| DBGLOG(P2P, TRACE, |
| "HT CAP IE would be overwritten by driver\n"); |
| |
| DBGLOG(P2P, TRACE, |
| "HT Cap Info:%x, AMPDU Param:%x\n", |
| HT_CAP_IE(pucIE)->u2HtCapInfo, |
| HT_CAP_IE(pucIE)->ucAmpduParam); |
| |
| DBGLOG(P2P, TRACE, |
| "HT Extended Cap:%x, TX Beamforming Cap:%x, Ant Selection Cap:%x\n", |
| HT_CAP_IE(pucIE) |
| ->u2HtExtendedCap, |
| HT_CAP_IE(pucIE) |
| ->u4TxBeamformingCap, |
| HT_CAP_IE(pucIE)->ucAselCap); |
| #else |
| prP2pBssInfo->ucPhyTypeSet |= |
| PHY_TYPE_SET_802_11N; |
| |
| /* u2HtCapInfo */ |
| if ((HT_CAP_IE(pucIE)->u2HtCapInfo & |
| (HT_CAP_INFO_SUP_CHNL_WIDTH | |
| HT_CAP_INFO_SHORT_GI_40M | |
| HT_CAP_INFO_DSSS_CCK_IN_40M)) |
| == 0) { |
| prP2pBssInfo |
| ->fgAssoc40mBwAllowed = |
| FALSE; |
| } else { |
| prP2pBssInfo |
| ->fgAssoc40mBwAllowed = |
| TRUE; |
| } |
| |
| if ((HT_CAP_IE(pucIE)->u2HtCapInfo & |
| (HT_CAP_INFO_SHORT_GI_20M | |
| HT_CAP_INFO_SHORT_GI_40M)) |
| == 0) { |
| prAdapter->rWifiVar |
| .rConnSettings |
| .fgRxShortGIDisabled = |
| TRUE; |
| } else { |
| prAdapter->rWifiVar |
| .rConnSettings |
| .fgRxShortGIDisabled = |
| FALSE; |
| } |
| |
| /* ucAmpduParam */ |
| DBGLOG(P2P, TRACE, |
| "AMPDU setting from supplicant:0x%x, & default value:0x%x\n", |
| (uint8_t) |
| HT_CAP_IE(pucIE)->ucAmpduParam, |
| (uint8_t) |
| AMPDU_PARAM_DEFAULT_VAL); |
| |
| /* rSupMcsSet */ |
| /* Can do nothing. |
| * the field is default value |
| * from other configuration. |
| */ |
| /* HT_CAP_IE(pucIE)->rSupMcsSet; */ |
| |
| /* u2HtExtendedCap */ |
| ASSERT( |
| HT_CAP_IE(pucIE)->u2HtExtendedCap == |
| (HT_EXT_CAP_DEFAULT_VAL & |
| ~(HT_EXT_CAP_PCO | |
| HT_EXT_CAP_PCO_TRANS_TIME_NONE))); |
| |
| /* u4TxBeamformingCap */ |
| ASSERT( |
| HT_CAP_IE(pucIE)->u4TxBeamformingCap |
| == TX_BEAMFORMING_CAP_DEFAULT_VAL); |
| |
| /* ucAselCap */ |
| ASSERT( |
| HT_CAP_IE(pucIE)->ucAselCap |
| == ASEL_CAP_DEFAULT_VAL); |
| #endif |
| } |
| break; |
| case ELEM_ID_RSN: /* 48 *//* V */ |
| |
| DBGLOG(P2P, TRACE, "RSN IE\n"); |
| kalP2PSetCipher(prAdapter->prGlueInfo, |
| IW_AUTH_CIPHER_CCMP, |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| if (IE_LEN(pucIE) > ELEM_MAX_LEN_RSN) { |
| DBGLOG(P2P, ERROR, |
| "RSN IE length is unexpected !!\n"); |
| return; |
| } |
| kalMemCopy(prP2pSpecificBssInfo->aucRsnIeBuffer, |
| pucIE, IE_SIZE(pucIE)); |
| prP2pSpecificBssInfo->u2RsnIeLen |
| = IE_SIZE(pucIE); |
| if (rsnParseRsnIE(prAdapter, |
| RSN_IE(pucIE), &rRsnIe)) { |
| prP2pBssInfo->u4RsnSelectedGroupCipher = |
| RSN_CIPHER_SUITE_CCMP; |
| prP2pBssInfo |
| ->u4RsnSelectedPairwiseCipher = |
| RSN_CIPHER_SUITE_CCMP; |
| prP2pBssInfo->u4RsnSelectedAKMSuite = |
| RSN_AKM_SUITE_PSK; |
| prP2pBssInfo->u2RsnSelectedCapInfo = |
| rRsnIe.u2RsnCap; |
| DBGLOG(RSN, TRACE, |
| "RsnIe CAP:0x%x\n", |
| rRsnIe.u2RsnCap); |
| } |
| |
| #if CFG_SUPPORT_802_11W |
| /* AP PMF */ |
| prP2pBssInfo->rApPmfCfg.fgMfpc = |
| (rRsnIe.u2RsnCap |
| & ELEM_WPA_CAP_MFPC) ? 1 : 0; |
| prP2pBssInfo->rApPmfCfg.fgMfpr = |
| (rRsnIe.u2RsnCap |
| & ELEM_WPA_CAP_MFPR) ? 1 : 0; |
| |
| for (i = 0; |
| i < rRsnIe.u4AuthKeyMgtSuiteCount; |
| i++) { |
| if ((rRsnIe.au4AuthKeyMgtSuite[i] |
| == RSN_AKM_SUITE_PSK_SHA256) || |
| (rRsnIe.au4AuthKeyMgtSuite[i] |
| == RSN_AKM_SUITE_802_1X_SHA256)) { |
| DBGLOG(RSN, INFO, |
| "SHA256 support\n"); |
| /* over-write |
| * u4RsnSelectedAKMSuite |
| * by SHA256 AKM |
| */ |
| prP2pBssInfo |
| ->u4RsnSelectedAKMSuite |
| = rRsnIe.au4AuthKeyMgtSuite[i]; |
| prP2pBssInfo |
| ->rApPmfCfg.fgSha256 |
| = TRUE; |
| break; |
| } |
| } |
| DBGLOG(RSN, ERROR, |
| "bcn mfpc:%d, mfpr:%d, sha256:%d\n", |
| prP2pBssInfo->rApPmfCfg.fgMfpc, |
| prP2pBssInfo->rApPmfCfg.fgMfpr, |
| prP2pBssInfo->rApPmfCfg.fgSha256); |
| #endif |
| |
| break; |
| case ELEM_ID_EXTENDED_SUP_RATES: /* 50 *//* V */ |
| /* ELEM_ID_SUP_RATES should be placed |
| * before ELEM_ID_EXTENDED_SUP_RATES. |
| */ |
| #ifndef CFG_SUPPORT_P2P_GO_KEEP_RATE_SETTING |
| DBGLOG(P2P, TRACE, "Ex Support Rate IE\n"); |
| kalMemCopy(& |
| (prP2pBssInfo->aucAllSupportedRates |
| [prP2pBssInfo->ucAllSupportedRatesLen]), |
| EXT_SUP_RATES_IE(pucIE) |
| ->aucExtSupportedRates, |
| EXT_SUP_RATES_IE(pucIE) |
| ->ucLength); |
| |
| DBGLOG_MEM8(P2P, TRACE, |
| EXT_SUP_RATES_IE(pucIE) |
| ->aucExtSupportedRates, |
| EXT_SUP_RATES_IE(pucIE) |
| ->ucLength); |
| |
| prP2pBssInfo->ucAllSupportedRatesLen += |
| EXT_SUP_RATES_IE(pucIE)->ucLength; |
| #endif |
| break; |
| case ELEM_ID_HT_OP: |
| /* 61 *//* V *//* TODO: */ |
| { |
| #if 1 |
| DBGLOG(P2P, TRACE, |
| "HT OP IE would be overwritten by driver\n"); |
| |
| DBGLOG(P2P, TRACE, |
| " Primary Channel: %x, Info1: %x, Info2: %x, Info3: %x\n", |
| HT_OP_IE(pucIE) |
| ->ucPrimaryChannel, |
| HT_OP_IE(pucIE)->ucInfo1, |
| HT_OP_IE(pucIE)->u2Info2, |
| HT_OP_IE(pucIE)->u2Info3); |
| #else |
| uint16_t u2Info2 = 0; |
| |
| prP2pBssInfo->ucPhyTypeSet |= |
| PHY_TYPE_SET_802_11N; |
| |
| DBGLOG(P2P, TRACE, "HT OP IE\n"); |
| |
| /* ucPrimaryChannel. */ |
| ASSERT( |
| HT_OP_IE(pucIE)->ucPrimaryChannel |
| == prP2pBssInfo->ucPrimaryChannel); |
| |
| /* ucInfo1 */ |
| prP2pBssInfo->ucHtOpInfo1 = |
| HT_OP_IE(pucIE)->ucInfo1; |
| |
| /* u2Info2 */ |
| u2Info2 = HT_OP_IE(pucIE)->u2Info2; |
| |
| if (u2Info2 |
| & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) { |
| ASSERT( |
| prP2pBssInfo->eGfOperationMode |
| != GF_MODE_NORMAL); |
| u2Info2 &= |
| ~HT_OP_INFO2_NON_GF_HT_STA_PRESENT; |
| } |
| |
| if (u2Info2 |
| & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) { |
| prP2pBssInfo->eObssHtProtectMode = |
| HT_PROTECT_MODE_NON_MEMBER; |
| u2Info2 &= |
| ~HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; |
| } |
| |
| switch (u2Info2 |
| & HT_OP_INFO2_HT_PROTECTION) { |
| case HT_PROTECT_MODE_NON_HT: |
| prP2pBssInfo->eHtProtectMode = |
| HT_PROTECT_MODE_NON_HT; |
| break; |
| case HT_PROTECT_MODE_NON_MEMBER: |
| prP2pBssInfo->eHtProtectMode = |
| HT_PROTECT_MODE_NONE; |
| prP2pBssInfo |
| ->eObssHtProtectMode = |
| HT_PROTECT_MODE_NON_MEMBER; |
| break; |
| default: |
| prP2pBssInfo->eHtProtectMode = |
| HT_OP_IE(pucIE)->u2Info2; |
| break; |
| } |
| |
| /* u2Info3 */ |
| prP2pBssInfo->u2HtOpInfo3 = |
| HT_OP_IE(pucIE)->u2Info3; |
| |
| /* aucBasicMcsSet */ |
| DBGLOG_MEM8(P2P, TRACE, |
| HT_OP_IE(pucIE)->aucBasicMcsSet, 16); |
| #endif |
| } |
| break; |
| case ELEM_ID_OBSS_SCAN_PARAMS: /* 74 *//* V */ |
| { |
| DBGLOG(P2P, TRACE, |
| "ELEM_ID_OBSS_SCAN_PARAMS IE would be replaced by driver\n"); |
| } |
| break; |
| case ELEM_ID_EXTENDED_CAP: /* 127 *//* V */ |
| { |
| DBGLOG(P2P, TRACE, |
| "ELEM_ID_EXTENDED_CAP IE would be replaced by driver\n"); |
| } |
| break; |
| case ELEM_ID_VENDOR: /* 221 *//* V */ |
| DBGLOG(P2P, TRACE, "Vender Specific IE\n"); |
| { |
| p2pFuncParseBeaconVenderId(prAdapter, |
| pucIE, prP2pSpecificBssInfo, |
| (uint8_t) |
| prP2pBssInfo->u4PrivateData); |
| /* TODO: Store other Vender IE |
| * except for WMM Param. |
| */ |
| } |
| break; |
| default: |
| DBGLOG(P2P, TRACE, |
| "Unprocessed element ID:%d\n", |
| IE_ID(pucIE)); |
| break; |
| } |
| } |
| |
| } while (FALSE); |
| } /* p2pFuncParseBeaconContent */ |
| |
| /* Code refactoring for AOSP */ |
| static void |
| p2pFuncParseBeaconVenderId(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucIE, |
| IN struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo, |
| IN uint8_t ucRoleIndex) |
| { |
| do { |
| uint8_t ucOuiType; |
| uint16_t u2SubTypeVersion; |
| |
| if (rsnParseCheckForWFAInfoElem( |
| prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { |
| if ((ucOuiType == VENDOR_OUI_TYPE_WPA) |
| && (u2SubTypeVersion == VERSION_WPA)) { |
| if (!kalP2PGetCcmpCipher(prAdapter->prGlueInfo, |
| ucRoleIndex)) |
| kalP2PSetCipher(prAdapter->prGlueInfo, |
| IW_AUTH_CIPHER_TKIP, |
| ucRoleIndex); |
| if (IE_LEN(pucIE) > ELEM_MAX_LEN_WPA) { |
| DBGLOG(P2P, ERROR, |
| "WPA IE length is unexpected !!\n"); |
| return; |
| } |
| kalMemCopy( |
| prP2pSpecificBssInfo |
| ->aucWpaIeBuffer, |
| pucIE, IE_SIZE(pucIE)); |
| prP2pSpecificBssInfo->u2WpaIeLen = |
| IE_SIZE(pucIE); |
| DBGLOG(P2P, TRACE, "WPA IE in supplicant\n"); |
| } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { |
| kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, |
| 0, pucIE, IE_SIZE(pucIE), ucRoleIndex); |
| DBGLOG(P2P, TRACE, "WPS IE in supplicant\n"); |
| } else if (ucOuiType == VENDOR_OUI_TYPE_WMM) { |
| DBGLOG(P2P, TRACE, "WMM IE in supplicant\n"); |
| } |
| /* WMM here. */ |
| } else if (p2pFuncParseCheckForP2PInfoElem( |
| prAdapter, pucIE, &ucOuiType)) { |
| /* TODO Store the whole P2P IE & generate later. */ |
| /* Be aware that there may be one or more P2P IE. */ |
| if (ucOuiType == VENDOR_OUI_TYPE_P2P) { |
| kalMemCopy(&prP2pSpecificBssInfo |
| ->aucAttributesCache |
| [prP2pSpecificBssInfo->u2AttributeLen], |
| pucIE, IE_SIZE(pucIE)); |
| prP2pSpecificBssInfo->u2AttributeLen += |
| IE_SIZE(pucIE); |
| DBGLOG(P2P, TRACE, "P2P IE in supplicant\n"); |
| } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { |
| |
| kalMemCopy(&prP2pSpecificBssInfo |
| ->aucAttributesCache |
| [prP2pSpecificBssInfo->u2AttributeLen], |
| pucIE, IE_SIZE(pucIE)); |
| |
| prP2pSpecificBssInfo->u2AttributeLen += |
| IE_SIZE(pucIE); |
| } else { |
| DBGLOG(P2P, TRACE, |
| "Unknown 50-6F-9A-%d IE.\n", |
| ucOuiType); |
| } |
| } else { |
| kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache |
| [prP2pSpecificBssInfo->u2AttributeLen], |
| pucIE, IE_SIZE(pucIE)); |
| |
| prP2pSpecificBssInfo->u2AttributeLen += |
| IE_SIZE(pucIE); |
| DBGLOG(P2P, TRACE, |
| "Driver unprocessed Vender Specific IE\n"); |
| } |
| } while (0); |
| } |
| |
| struct BSS_DESC * |
| p2pFuncKeepOnConnection(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prBssInfo, |
| IN struct P2P_CONNECTION_REQ_INFO *prConnReqInfo, |
| IN struct P2P_CHNL_REQ_INFO *prChnlReqInfo, |
| IN struct P2P_SCAN_REQ_INFO *prScanReqInfo) |
| { |
| struct BSS_DESC *prTargetBss = (struct BSS_DESC *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL) && |
| (prConnReqInfo != NULL) && (prChnlReqInfo != NULL) && |
| (prScanReqInfo != NULL)); |
| |
| if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) |
| break; |
| /* Update connection request information. */ |
| ASSERT(prConnReqInfo->eConnRequest == P2P_CONNECTION_TYPE_GC); |
| |
| /* Find BSS Descriptor first. */ |
| prTargetBss = scanP2pSearchDesc(prAdapter, prConnReqInfo); |
| |
| if (prTargetBss == NULL) { |
| /* Update scan parameter... to scan target device. */ |
| /* TODO: Need refine. */ |
| prScanReqInfo->ucNumChannelList = 1; |
| prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; |
| prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; |
| /* Prevent other P2P ID in IE. */ |
| prScanReqInfo->u4BufLength = 0; |
| prScanReqInfo->fgIsAbort = TRUE; |
| } else { |
| prChnlReqInfo->u8Cookie = 0; |
| prChnlReqInfo->ucReqChnlNum = prTargetBss->ucChannelNum; |
| prChnlReqInfo->eBand = prTargetBss->eBand; |
| prChnlReqInfo->eChnlSco = prTargetBss->eSco; |
| prChnlReqInfo->u4MaxInterval = |
| AIS_JOIN_CH_REQUEST_INTERVAL; |
| prChnlReqInfo->eChnlReqType = CH_REQ_TYPE_JOIN; |
| |
| prChnlReqInfo->eChannelWidth = |
| prTargetBss->eChannelWidth; |
| prChnlReqInfo->ucCenterFreqS1 = |
| prTargetBss->ucCenterFreqS1; |
| prChnlReqInfo->ucCenterFreqS2 = |
| prTargetBss->ucCenterFreqS2; |
| } |
| |
| } while (FALSE); |
| |
| return prTargetBss; |
| } /* p2pFuncKeepOnConnection */ |
| |
| /* Currently Only for ASSOC Response Frame. */ |
| void p2pFuncStoreAssocRspIEBuffer(IN struct ADAPTER *prAdapter, |
| IN struct P2P_JOIN_INFO *prP2pJoinInfo, |
| IN struct SW_RFB *prSwRfb) |
| { |
| struct WLAN_ASSOC_RSP_FRAME *prAssocRspFrame = |
| (struct WLAN_ASSOC_RSP_FRAME *) NULL; |
| int16_t i2IELen = 0; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prP2pJoinInfo != NULL) && (prSwRfb != NULL)); |
| |
| prAssocRspFrame = |
| (struct WLAN_ASSOC_RSP_FRAME *) prSwRfb->pvHeader; |
| |
| if (prAssocRspFrame->u2FrameCtrl != MAC_FRAME_ASSOC_RSP) |
| break; |
| |
| i2IELen = prSwRfb->u2PacketLen - |
| (WLAN_MAC_HEADER_LEN + |
| CAP_INFO_FIELD_LEN + |
| STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); |
| |
| if (i2IELen <= 0) |
| break; |
| |
| prP2pJoinInfo->u4BufLength = (uint32_t) i2IELen; |
| |
| kalMemCopy(prP2pJoinInfo->aucIEBuf, |
| prAssocRspFrame->aucInfoElem, |
| prP2pJoinInfo->u4BufLength); |
| |
| } while (FALSE); |
| } /* p2pFuncStoreAssocRspIEBuffer */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * \brief This routine is called to set Packet Filter. |
| * |
| * \param[in] prAdapter Pointer to the Adapter structure. |
| * \param[in] pvSetBuffer Pointer to the buffer |
| * that holds the data to be set. |
| * \param[in] u4SetBufferLen The length of the set buffer. |
| * \param[out] pu4SetInfoLen If the call is successful, returns the number of |
| * bytes read from the set buffer. If the call failed |
| * due to invalid length of the set buffer, returns |
| * the amount of storage needed. |
| * |
| * \retval WLAN_STATUS_SUCCESS |
| * \retval WLAN_STATUS_INVALID_LENGTH |
| * \retval WLAN_STATUS_NOT_SUPPORTED |
| * \retval WLAN_STATUS_ADAPTER_NOT_READY |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void |
| p2pFuncMgmtFrameRegister(IN struct ADAPTER *prAdapter, |
| IN uint16_t u2FrameType, |
| IN u_int8_t fgIsRegistered, |
| OUT uint32_t *pu4P2pPacketFilter) |
| { |
| uint32_t u4NewPacketFilter = 0; |
| struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; |
| |
| DEBUGFUNC("p2pFuncMgmtFrameRegister"); |
| |
| do { |
| ASSERT_BREAK(prAdapter != NULL); |
| |
| if (pu4P2pPacketFilter) |
| u4NewPacketFilter = *pu4P2pPacketFilter; |
| |
| switch (u2FrameType) { |
| case MAC_FRAME_PROBE_REQ: |
| if (fgIsRegistered) { |
| u4NewPacketFilter |= |
| PARAM_PACKET_FILTER_PROBE_REQ; |
| DBGLOG(P2P, TRACE, |
| "Open packet filer probe request\n"); |
| } else { |
| u4NewPacketFilter &= |
| ~PARAM_PACKET_FILTER_PROBE_REQ; |
| DBGLOG(P2P, TRACE, |
| "Close packet filer probe request\n"); |
| } |
| break; |
| case MAC_FRAME_ACTION: |
| if (fgIsRegistered) { |
| u4NewPacketFilter |= |
| PARAM_PACKET_FILTER_ACTION_FRAME; |
| DBGLOG(P2P, TRACE, |
| "Open packet filer action frame.\n"); |
| } else { |
| u4NewPacketFilter &= |
| ~PARAM_PACKET_FILTER_ACTION_FRAME; |
| DBGLOG(P2P, TRACE, |
| "Close packet filer action frame.\n"); |
| } |
| break; |
| default: |
| DBGLOG(P2P, TRACE, |
| "Ask frog to add code for mgmt:%x\n", |
| u2FrameType); |
| break; |
| } |
| |
| if (pu4P2pPacketFilter) |
| *pu4P2pPacketFilter = u4NewPacketFilter; |
| |
| /* u4NewPacketFilter |= prAdapter->u4OsPacketFilter; */ |
| |
| prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; |
| prAdapter->u4OsPacketFilter |= u4NewPacketFilter; |
| |
| DBGLOG(P2P, TRACE, |
| "P2P Set PACKET filter:0x%x\n", |
| prAdapter->u4OsPacketFilter); |
| |
| kalMemZero(&rSetRxPacketFilter, sizeof(rSetRxPacketFilter)); |
| rSetRxPacketFilter.u4RxPacketFilter = |
| prAdapter->u4OsPacketFilter; |
| wlanoidSetPacketFilter(prAdapter, |
| &rSetRxPacketFilter, |
| FALSE, |
| &u4NewPacketFilter, |
| sizeof(u4NewPacketFilter)); |
| |
| } while (FALSE); |
| } /* p2pFuncMgmtFrameRegister */ |
| |
| void p2pFuncUpdateMgmtFrameRegister(IN struct ADAPTER *prAdapter, |
| IN uint32_t u4OsFilter) |
| { |
| struct CMD_RX_PACKET_FILTER rSetRxPacketFilter; |
| |
| do { |
| |
| /* TODO: Filter need to be done. */ |
| /* prAdapter->rWifiVar |
| * .prP2pFsmInfo->u4P2pPacketFilter = u4OsFilter; |
| */ |
| |
| if ((prAdapter->u4OsPacketFilter |
| & PARAM_PACKET_FILTER_P2P_MASK) ^ u4OsFilter) { |
| |
| prAdapter->u4OsPacketFilter &= |
| ~PARAM_PACKET_FILTER_P2P_MASK; |
| |
| prAdapter->u4OsPacketFilter |= |
| (u4OsFilter & PARAM_PACKET_FILTER_P2P_MASK); |
| |
| kalMemZero(&rSetRxPacketFilter, |
| sizeof(rSetRxPacketFilter)); |
| rSetRxPacketFilter.u4RxPacketFilter = |
| prAdapter->u4OsPacketFilter; |
| wlanoidSetPacketFilter(prAdapter, |
| &rSetRxPacketFilter, |
| FALSE, |
| &u4OsFilter, |
| sizeof(u4OsFilter)); |
| DBGLOG(P2P, TRACE, |
| "P2P Set PACKET filter:0x%x\n", |
| prAdapter->u4OsPacketFilter); |
| } |
| |
| } while (FALSE); |
| } /* p2pFuncUpdateMgmtFrameRegister */ |
| |
| void p2pFuncGetStationInfo(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucMacAddr, |
| OUT struct P2P_STATION_INFO *prStaInfo) |
| { |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (pucMacAddr != NULL) && (prStaInfo != NULL)); |
| |
| prStaInfo->u4InactiveTime = 0; |
| prStaInfo->u4RxBytes = 0; |
| prStaInfo->u4TxBytes = 0; |
| prStaInfo->u4RxPackets = 0; |
| prStaInfo->u4TxPackets = 0; |
| /* TODO: */ |
| |
| } while (FALSE); |
| } /* p2pFuncGetStationInfo */ |
| |
| #if 0 |
| u_int8_t |
| p2pFuncGetAttriList(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucOuiType, |
| IN uint8_t *pucIE, |
| IN uint16_t u2IELength, |
| OUT uint8_t **ppucAttriList, |
| OUT uint16_t *pu2AttriListLen) |
| { |
| u_int8_t fgIsAllocMem = FALSE; |
| uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; |
| uint16_t u2Offset = 0; |
| struct IE_P2P *prIe = (struct IE_P2P *) NULL; |
| uint8_t *pucAttriListStart = (uint8_t *) NULL; |
| uint16_t u2AttriListLen = 0, u2BufferSize; |
| u_int8_t fgBackupAttributes = FALSE; |
| |
| u2BufferSize = 0; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && |
| (pucIE != NULL) && |
| (u2IELength != 0) && |
| (ppucAttriList != NULL) && |
| (pu2AttriListLen != NULL)); |
| |
| if (ppucAttriList) |
| *ppucAttriList = NULL; |
| if (pu2AttriListLen) |
| *pu2AttriListLen = 0; |
| |
| if (ucOuiType == VENDOR_OUI_TYPE_WPS) { |
| aucWfaOui[0] = 0x00; |
| aucWfaOui[1] = 0x50; |
| aucWfaOui[2] = 0xF2; |
| } else if ((ucOuiType != VENDOR_OUI_TYPE_P2P) |
| #if CFG_SUPPORT_WFD |
| && (ucOuiType != VENDOR_OUI_TYPE_WFD) |
| #endif |
| ) { |
| DBGLOG(P2P, INFO, |
| "Not supported OUI Type to parsing 0x%x\n", |
| ucOuiType); |
| break; |
| } |
| |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| if (IE_ID(pucIE) == ELEM_ID_VENDOR) { |
| prIe = (struct IE_P2P *) pucIE; |
| |
| if (prIe->ucLength <= P2P_OUI_TYPE_LEN) |
| continue; |
| |
| if ((prIe->aucOui[0] == aucWfaOui[0]) && |
| (prIe->aucOui[1] == aucWfaOui[1]) && |
| (prIe->aucOui[2] == aucWfaOui[2]) && |
| (ucOuiType == prIe->ucOuiType)) { |
| p2pFuncGetAttriListAction(prAdapter, |
| prIe, ucOuiType, |
| &pucAttriListStart, |
| &u2AttriListLen, |
| &fgIsAllocMem, |
| &fgBackupAttributes, |
| &u2BufferSize); |
| } /* prIe->aucOui */ |
| } /* ELEM_ID_VENDOR */ |
| } /* IE_FOR_EACH */ |
| |
| } while (FALSE); |
| |
| if (pucAttriListStart) { |
| uint8_t *pucAttribute = pucAttriListStart; |
| |
| DBGLOG(P2P, LOUD, "Checking Attribute Length.\n"); |
| if (ucOuiType == VENDOR_OUI_TYPE_P2P) { |
| P2P_ATTRI_FOR_EACH(pucAttribute, |
| u2AttriListLen, u2Offset); |
| } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { |
| /* Todo:: Nothing */ |
| } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { |
| /* Big Endian: WSC, WFD. */ |
| WSC_ATTRI_FOR_EACH(pucAttribute, |
| u2AttriListLen, u2Offset) { |
| DBGLOG(P2P, LOUD, |
| "Attribute ID:%d, Length:%d.\n", |
| WSC_ATTRI_ID(pucAttribute), |
| WSC_ATTRI_LEN(pucAttribute)); |
| } |
| } else { |
| } |
| |
| ASSERT(u2Offset == u2AttriListLen); |
| |
| *ppucAttriList = pucAttriListStart; |
| *pu2AttriListLen = u2AttriListLen; |
| |
| } else { |
| *ppucAttriList = (uint8_t *) NULL; |
| *pu2AttriListLen = 0; |
| } |
| |
| return fgIsAllocMem; |
| } /* p2pFuncGetAttriList */ |
| |
| /* Code refactoring for AOSP */ |
| static void |
| p2pFuncGetAttriListAction(IN struct ADAPTER *prAdapter, |
| IN struct IE_P2P *prIe, |
| IN uint8_t ucOuiType, |
| OUT uint8_t **pucAttriListStart, |
| OUT uint16_t *u2AttriListLen, |
| OUT u_int8_t *fgIsAllocMem, |
| OUT u_int8_t *fgBackupAttributes, |
| OUT uint16_t *u2BufferSize) |
| { |
| do { |
| if (!(*pucAttriListStart)) { |
| *pucAttriListStart = &prIe->aucP2PAttributes[0]; |
| if (prIe->ucLength > P2P_OUI_TYPE_LEN) |
| *u2AttriListLen = |
| (uint16_t) |
| (prIe->ucLength - P2P_OUI_TYPE_LEN); |
| else |
| ASSERT(FALSE); |
| } else { |
| /* More than 2 attributes. */ |
| uint16_t u2CopyLen; |
| |
| if (*fgBackupAttributes == FALSE) { |
| struct P2P_SPECIFIC_BSS_INFO |
| *prP2pSpecificBssInfo = |
| prAdapter->rWifiVar.prP2pSpecificBssInfo; |
| |
| *fgBackupAttributes = TRUE; |
| if (ucOuiType == VENDOR_OUI_TYPE_P2P) { |
| kalMemCopy(&prP2pSpecificBssInfo |
| ->aucAttributesCache[0], |
| *pucAttriListStart, *u2AttriListLen); |
| |
| *pucAttriListStart = |
| &prP2pSpecificBssInfo |
| ->aucAttributesCache[0]; |
| *u2BufferSize = |
| P2P_MAXIMUM_ATTRIBUTE_LEN; |
| } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { |
| kalMemCopy(&prP2pSpecificBssInfo |
| ->aucWscAttributesCache[0], |
| *pucAttriListStart, *u2AttriListLen); |
| *pucAttriListStart = |
| &prP2pSpecificBssInfo |
| ->aucWscAttributesCache[0]; |
| *u2BufferSize = |
| WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; |
| } |
| #if CFG_SUPPORT_WFD |
| else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { |
| uint8_t *pucTmpBuf = (uint8_t *) NULL; |
| |
| pucTmpBuf = (uint8_t *) kalMemAlloc |
| (WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE, |
| VIR_MEM_TYPE); |
| |
| if (pucTmpBuf != NULL) { |
| *fgIsAllocMem = TRUE; |
| } else { |
| /* Can't alloca memory |
| * for WFD IE relocate. |
| */ |
| ASSERT(FALSE); |
| break; |
| } |
| |
| kalMemCopy(pucTmpBuf, |
| *pucAttriListStart, |
| *u2AttriListLen); |
| *pucAttriListStart = pucTmpBuf; |
| *u2BufferSize = |
| WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; |
| } |
| #endif |
| else |
| *fgBackupAttributes = FALSE; |
| } |
| u2CopyLen = |
| (uint16_t) (prIe->ucLength - P2P_OUI_TYPE_LEN); |
| |
| if (((*u2AttriListLen) + u2CopyLen) > (*u2BufferSize)) { |
| u2CopyLen = (*u2BufferSize) - (*u2AttriListLen); |
| DBGLOG(P2P, WARN, |
| "Length of received P2P attributes > maximum cache size.\n"); |
| } |
| |
| if (u2CopyLen) { |
| kalMemCopy((uint8_t *) |
| ((unsigned long) (*pucAttriListStart) + |
| (unsigned long) (*u2AttriListLen)), |
| &prIe->aucP2PAttributes[0], u2CopyLen); |
| *u2AttriListLen += u2CopyLen; |
| } |
| |
| } |
| } while (0); |
| } |
| #endif |
| |
| struct MSDU_INFO *p2pFuncProcessP2pProbeRsp(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIdx, IN struct MSDU_INFO *prMgmtTxMsdu) |
| { |
| struct MSDU_INFO *prRetMsduInfo = prMgmtTxMsdu; |
| struct WLAN_BEACON_FRAME *prProbeRspFrame = |
| (struct WLAN_BEACON_FRAME *) NULL; |
| uint8_t *pucIEBuf = (uint8_t *) NULL; |
| uint16_t u2Offset = 0, u2IELength = 0, u2ProbeRspHdrLen = 0; |
| u_int8_t fgIsWSCIE = FALSE; |
| u_int8_t fgIsWFDIE = FALSE; |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| uint16_t u2EstimateSize = 0, u2EstimatedExtraIELen = 0; |
| uint32_t u4IeArraySize = 0, u4Idx = 0; |
| u_int8_t u4P2PIEIdx = 0; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); |
| |
| prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); |
| |
| /* 3 Make sure this is probe response frame. */ |
| prProbeRspFrame = (struct WLAN_BEACON_FRAME *) |
| ((unsigned long) prMgmtTxMsdu->prPacket + |
| MAC_TX_RESERVED_FIELD); |
| ASSERT_BREAK((prProbeRspFrame->u2FrameCtrl & MASK_FRAME_TYPE) |
| == MAC_FRAME_PROBE_RSP); |
| |
| /* 3 Get the importent P2P IE. */ |
| u2ProbeRspHdrLen = |
| (WLAN_MAC_MGMT_HEADER_LEN + |
| TIMESTAMP_FIELD_LEN + |
| BEACON_INTERVAL_FIELD_LEN + |
| CAP_INFO_FIELD_LEN); |
| pucIEBuf = prProbeRspFrame->aucInfoElem; |
| u2IELength = prMgmtTxMsdu->u2FrameLength - u2ProbeRspHdrLen; |
| |
| #if CFG_SUPPORT_WFD |
| /* prAdapter->prGlueInfo |
| * ->prP2PInfo[0]->u2VenderIELen = 0; |
| */ |
| /* Reset in each time ?? */ |
| prAdapter->prGlueInfo |
| ->prP2PInfo[prP2pBssInfo->u4PrivateData] |
| ->u2WFDIELen = 0; |
| #endif |
| |
| IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { |
| switch (IE_ID(pucIEBuf)) { |
| case ELEM_ID_SSID: |
| { |
| p2pFuncProcessP2pProbeRspAction( |
| prAdapter, |
| pucIEBuf, ELEM_ID_SSID, |
| &ucBssIdx, |
| &prP2pBssInfo, |
| &fgIsWSCIE, |
| &u4P2PIEIdx, |
| &fgIsWFDIE); |
| } |
| break; |
| case ELEM_ID_VENDOR: |
| { |
| p2pFuncProcessP2pProbeRspAction( |
| prAdapter, |
| pucIEBuf, ELEM_ID_VENDOR, |
| &ucBssIdx, |
| &prP2pBssInfo, |
| &fgIsWSCIE, |
| &u4P2PIEIdx, |
| &fgIsWFDIE); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| } |
| |
| /* 3 Check the total size & current frame. */ |
| u2EstimateSize = WLAN_MAC_MGMT_HEADER_LEN + |
| TIMESTAMP_FIELD_LEN + |
| BEACON_INTERVAL_FIELD_LEN + |
| CAP_INFO_FIELD_LEN + |
| (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + |
| (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + |
| (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET); |
| |
| u2EstimatedExtraIELen = 0; |
| |
| u4IeArraySize = |
| sizeof(txProbeRspIETable) / |
| sizeof(struct APPEND_VAR_IE_ENTRY); |
| for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { |
| if (txProbeRspIETable[u4Idx].u2EstimatedFixedIELen) { |
| u2EstimatedExtraIELen += |
| txProbeRspIETable[u4Idx] |
| .u2EstimatedFixedIELen; |
| } |
| |
| else { |
| ASSERT(txProbeRspIETable[u4Idx] |
| .pfnCalculateVariableIELen); |
| |
| u2EstimatedExtraIELen += |
| (uint16_t) ( |
| txProbeRspIETable[u4Idx] |
| .pfnCalculateVariableIELen( |
| prAdapter, |
| ucBssIdx, NULL)); |
| } |
| |
| } |
| |
| if (fgIsWSCIE) |
| u2EstimatedExtraIELen += |
| kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2, |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| |
| if (u4P2PIEIdx > 0) { |
| for (u4Idx = 0; u4Idx < u4P2PIEIdx; u4Idx++) |
| u2EstimatedExtraIELen += |
| kalP2PCalP2P_IELen( |
| prAdapter->prGlueInfo, |
| u4Idx, |
| (uint8_t) |
| prP2pBssInfo->u4PrivateData); |
| u2EstimatedExtraIELen += |
| p2pFuncCalculateP2P_IE_NoA(prAdapter, |
| ucBssIdx, NULL); |
| } |
| #if CFG_SUPPORT_WFD |
| ASSERT(sizeof(prAdapter->prGlueInfo |
| ->prP2PInfo[prP2pBssInfo->u4PrivateData]->aucWFDIE) |
| >= |
| prAdapter->prGlueInfo |
| ->prP2PInfo[prP2pBssInfo->u4PrivateData]->u2WFDIELen); |
| |
| if (fgIsWFDIE) |
| u2EstimatedExtraIELen += |
| prAdapter->prGlueInfo |
| ->prP2PInfo[prP2pBssInfo->u4PrivateData] |
| ->u2WFDIELen; |
| #if 0 |
| u2EstimatedExtraIELen += |
| prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen; |
| #endif |
| #endif |
| |
| u2EstimateSize += u2EstimatedExtraIELen; |
| if ((u2EstimateSize) > (prRetMsduInfo->u2FrameLength)) { |
| /* add sizeof(UINT_64) for Cookie */ |
| prRetMsduInfo = cnmMgtPktAlloc(prAdapter, |
| u2EstimateSize + sizeof(uint64_t)); |
| |
| if (prRetMsduInfo == NULL) { |
| DBGLOG(P2P, WARN, |
| "No packet for sending new probe response, use original one\n"); |
| prRetMsduInfo = prMgmtTxMsdu; |
| break; |
| } |
| |
| } |
| |
| prRetMsduInfo->ucBssIndex = ucBssIdx; |
| |
| /* 3 Compose / Re-compose probe response frame. */ |
| bssComposeBeaconProbeRespFrameHeaderAndFF((uint8_t *) |
| ((unsigned long) (prRetMsduInfo->prPacket) + |
| MAC_TX_RESERVED_FIELD), |
| prProbeRspFrame->aucDestAddr, |
| prProbeRspFrame->aucSrcAddr, |
| prProbeRspFrame->aucBSSID, |
| prProbeRspFrame->u2BeaconInterval, |
| prProbeRspFrame->u2CapInfo); |
| |
| prRetMsduInfo->u2FrameLength = |
| (WLAN_MAC_MGMT_HEADER_LEN + |
| TIMESTAMP_FIELD_LEN + |
| BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); |
| |
| bssBuildBeaconProbeRespFrameCommonIEs(prRetMsduInfo, |
| prP2pBssInfo, prProbeRspFrame->aucDestAddr); |
| |
| prRetMsduInfo->ucStaRecIndex = prMgmtTxMsdu->ucStaRecIndex; |
| |
| for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { |
| if (txProbeRspIETable[u4Idx].pfnAppendIE) |
| txProbeRspIETable[u4Idx] |
| .pfnAppendIE(prAdapter, prRetMsduInfo); |
| |
| } |
| |
| if (fgIsWSCIE) { |
| kalP2PGenWSC_IE(prAdapter->prGlueInfo, |
| 2, |
| (uint8_t *) |
| ((unsigned long) prRetMsduInfo->prPacket + |
| (unsigned long) prRetMsduInfo->u2FrameLength), |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| |
| prRetMsduInfo->u2FrameLength += (uint16_t) |
| kalP2PCalWSC_IELen(prAdapter->prGlueInfo, |
| 2, |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| } |
| |
| if (u4P2PIEIdx > 0) { |
| for (u4Idx = 0; u4Idx < u4P2PIEIdx; u4Idx++) { |
| kalP2PGenP2P_IE(prAdapter->prGlueInfo, |
| u4Idx, |
| (uint8_t *) |
| ((unsigned long) |
| prRetMsduInfo->prPacket + |
| (unsigned long) |
| prRetMsduInfo->u2FrameLength), |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| |
| prRetMsduInfo->u2FrameLength += |
| (uint16_t) |
| kalP2PCalP2P_IELen( |
| prAdapter->prGlueInfo, |
| u4Idx, |
| (uint8_t) prP2pBssInfo->u4PrivateData); |
| } |
| p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo); |
| |
| } |
| #if CFG_SUPPORT_WFD |
| |
| if (fgIsWFDIE > 0) { |
| ASSERT(prAdapter->prGlueInfo |
| ->prP2PInfo[prP2pBssInfo->u4PrivateData] |
| ->u2WFDIELen > 0); |
| kalMemCopy((uint8_t *) |
| ((unsigned long) prRetMsduInfo->prPacket + |
| (unsigned long) prRetMsduInfo->u2FrameLength), |
| prAdapter->prGlueInfo->prP2PInfo |
| [prP2pBssInfo->u4PrivateData]->aucWFDIE, |
| prAdapter->prGlueInfo->prP2PInfo |
| [prP2pBssInfo->u4PrivateData] |
| ->u2WFDIELen); |
| prRetMsduInfo->u2FrameLength += |
| (uint16_t) prAdapter->prGlueInfo |
| ->prP2PInfo[prP2pBssInfo->u4PrivateData] |
| ->u2WFDIELen; |
| |
| } |
| #if 0 |
| if (prAdapter->prGlueInfo->prP2PInfo[0]->u2VenderIELen > 0) { |
| kalMemCopy((uint8_t *) |
| ((uint32_t) prRetMsduInfo->prPacket + |
| (uint32_t) prRetMsduInfo->u2FrameLength), |
| prAdapter->prGlueInfo |
| ->prP2PInfo[0]->aucVenderIE, |
| prAdapter->prGlueInfo |
| ->prP2PInfo[0]->u2VenderIELen); |
| prRetMsduInfo->u2FrameLength += |
| (uint16_t) prAdapter->prGlueInfo |
| ->prP2PInfo[0]->u2VenderIELen; |
| } |
| #endif |
| #endif /* CFG_SUPPORT_WFD */ |
| |
| } while (FALSE); |
| |
| if (prRetMsduInfo != prMgmtTxMsdu) |
| cnmMgtPktFree(prAdapter, prMgmtTxMsdu); |
| |
| return prRetMsduInfo; |
| } /* p2pFuncProcessP2pProbeRsp */ |
| |
| /* Code refactoring for AOSP */ |
| static void |
| p2pFuncProcessP2pProbeRspAction(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucIEBuf, |
| IN uint8_t ucElemIdType, |
| OUT uint8_t *ucBssIdx, |
| OUT struct BSS_INFO **prP2pBssInfo, |
| OUT u_int8_t *fgIsWSCIE, |
| OUT u_int8_t *u4P2PIEIdx, |
| OUT u_int8_t *fgIsWFDIE) |
| { |
| uint8_t ucOuiType = 0; |
| uint16_t u2SubTypeVersion = 0; |
| |
| switch (ucElemIdType) { |
| case ELEM_ID_SSID: |
| { |
| if (SSID_IE(pucIEBuf)->ucLength > 7) { |
| for ((*ucBssIdx) = 0; |
| (*ucBssIdx) < prAdapter->ucHwBssIdNum; |
| (*ucBssIdx)++) { |
| *prP2pBssInfo = |
| GET_BSS_INFO_BY_INDEX( |
| prAdapter, *ucBssIdx); |
| if (!(*prP2pBssInfo)) |
| continue; |
| if (EQUAL_SSID( |
| (*prP2pBssInfo)->aucSSID, |
| (*prP2pBssInfo)->ucSSIDLen, |
| SSID_IE(pucIEBuf)->aucSSID, |
| SSID_IE(pucIEBuf)->ucLength)) { |
| break; |
| } |
| } |
| if ((*ucBssIdx) == prAdapter->ucP2PDevBssIdx) |
| *prP2pBssInfo = |
| GET_BSS_INFO_BY_INDEX( |
| prAdapter, *ucBssIdx); |
| } else { |
| *prP2pBssInfo = |
| GET_BSS_INFO_BY_INDEX( |
| prAdapter, |
| prAdapter->ucP2PDevBssIdx); |
| COPY_SSID( |
| (*prP2pBssInfo)->aucSSID, |
| (*prP2pBssInfo)->ucSSIDLen, |
| SSID_IE(pucIEBuf)->aucSSID, |
| SSID_IE(pucIEBuf)->ucLength); |
| |
| } |
| } |
| break; |
| case ELEM_ID_VENDOR: |
| if (rsnParseCheckForWFAInfoElem(prAdapter, |
| pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { |
| if (ucOuiType == VENDOR_OUI_TYPE_WPS) { |
| kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, |
| 2, pucIEBuf, |
| IE_SIZE(pucIEBuf), |
| (uint8_t) |
| ((struct BSS_INFO *)*prP2pBssInfo) |
| ->u4PrivateData); |
| *fgIsWSCIE = TRUE; |
| } |
| |
| } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, |
| pucIEBuf, &ucOuiType)) { |
| if (ucOuiType == VENDOR_OUI_TYPE_P2P) { |
| /* 2 Note(frog): I use WSC IE buffer |
| * for Probe Request |
| * to store the P2P IE for Probe Response. |
| */ |
| if (*u4P2PIEIdx < MAX_P2P_IE_SIZE) { |
| kalP2PUpdateP2P_IE( |
| prAdapter->prGlueInfo, |
| *u4P2PIEIdx, |
| pucIEBuf, |
| IE_SIZE(pucIEBuf), |
| (uint8_t) |
| ((struct BSS_INFO *) |
| *prP2pBssInfo) |
| ->u4PrivateData); |
| *u4P2PIEIdx = *u4P2PIEIdx + 1; |
| } else |
| DBGLOG(P2P, WARN, |
| "Too much P2P IE for ProbeResp, skip update\n"); |
| } |
| #if CFG_SUPPORT_WFD |
| else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { |
| DBGLOG(P2P, INFO, |
| "WFD IE is found in probe resp (supp). Len %u\n", |
| IE_SIZE(pucIEBuf)); |
| if ((sizeof( |
| prAdapter->prGlueInfo |
| ->prP2PInfo |
| [((struct BSS_INFO *)*prP2pBssInfo) |
| ->u4PrivateData] |
| ->aucWFDIE) |
| >= |
| (prAdapter->prGlueInfo |
| ->prP2PInfo |
| [((struct BSS_INFO *)*prP2pBssInfo) |
| ->u4PrivateData]->u2WFDIELen + |
| IE_SIZE(pucIEBuf)))) { |
| *fgIsWFDIE = TRUE; |
| kalMemCopy(prAdapter->prGlueInfo |
| ->prP2PInfo |
| [((struct BSS_INFO *) |
| *prP2pBssInfo) |
| ->u4PrivateData]->aucWFDIE, |
| pucIEBuf, IE_SIZE(pucIEBuf)); |
| prAdapter->prGlueInfo |
| ->prP2PInfo |
| [((struct BSS_INFO *) |
| *prP2pBssInfo) |
| ->u4PrivateData]->u2WFDIELen += |
| IE_SIZE(pucIEBuf); |
| } |
| } /* VENDOR_OUI_TYPE_WFD */ |
| #endif |
| } else { |
| DBGLOG(P2P, INFO, |
| "Other vender IE is found in probe resp (supp). Len %u\n", |
| IE_SIZE(pucIEBuf)); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| #if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ |
| uint32_t |
| p2pFuncCalculateExtra_IELenForBeacon(IN struct ADAPTER *prAdapter, |
| IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, |
| IN struct STA_RECORD *prStaRec) |
| { |
| |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = |
| (struct P2P_SPECIFIC_BSS_INFO *) NULL; |
| uint32_t u4IELen = 0; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); |
| |
| if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) |
| break; |
| |
| prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; |
| |
| u4IELen = prP2pSpeBssInfo->u2IELenForBCN; |
| |
| } while (FALSE); |
| |
| return u4IELen; |
| } /* p2pFuncCalculateP2p_IELenForBeacon */ |
| |
| void p2pFuncGenerateExtra_IEForBeacon(IN struct ADAPTER *prAdapter, |
| IN struct MSDU_INFO *prMsduInfo) |
| { |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = |
| (struct P2P_SPECIFIC_BSS_INFO *) NULL; |
| uint8_t *pucIEBuf = (uint8_t *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); |
| |
| prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; |
| |
| if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) |
| break; |
| |
| pucIEBuf = (uint8_t *) ((uint32_t) prMsduInfo->prPacket + |
| (uint32_t) prMsduInfo->u2FrameLength); |
| |
| kalMemCopy(pucIEBuf, |
| prP2pSpeBssInfo->aucBeaconIECache, |
| prP2pSpeBssInfo->u2IELenForBCN); |
| |
| prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; |
| |
| } while (FALSE); |
| } /* p2pFuncGenerateExtra_IEForBeacon */ |
| |
| #else |
| uint32_t p2pFuncCalculateP2p_IELenForBeacon(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec) |
| { |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = |
| (struct P2P_SPECIFIC_BSS_INFO *) NULL; |
| uint32_t u4IELen = 0; |
| struct BSS_INFO *prBssInfo; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (ucBssIdx < prAdapter->ucHwBssIdNum)); |
| |
| prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; |
| |
| if (!prAdapter->fgIsP2PRegistered) |
| break; |
| |
| if (p2pFuncIsAPMode( |
| prAdapter->rWifiVar.prP2PConnSettings |
| [prBssInfo->u4PrivateData])) |
| break; |
| |
| prP2pSpeBssInfo = |
| prAdapter->rWifiVar.prP2pSpecificBssInfo |
| [prBssInfo->u4PrivateData]; |
| |
| u4IELen = prP2pSpeBssInfo->u2AttributeLen; |
| |
| } while (FALSE); |
| |
| return u4IELen; |
| } /* p2pFuncCalculateP2p_IELenForBeacon */ |
| |
| void p2pFuncGenerateP2p_IEForBeacon(IN struct ADAPTER *prAdapter, |
| IN struct MSDU_INFO *prMsduInfo) |
| { |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpeBssInfo = |
| (struct P2P_SPECIFIC_BSS_INFO *) NULL; |
| uint8_t *pucIEBuf = (uint8_t *) NULL; |
| struct BSS_INFO *prBssInfo; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); |
| |
| if (!prAdapter->fgIsP2PRegistered) |
| break; |
| |
| prBssInfo = prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| |
| prP2pSpeBssInfo = |
| prAdapter->rWifiVar.prP2pSpecificBssInfo |
| [prBssInfo->u4PrivateData]; |
| |
| if (p2pFuncIsAPMode( |
| prAdapter->rWifiVar.prP2PConnSettings |
| [prBssInfo->u4PrivateData])) |
| break; |
| |
| pucIEBuf = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + |
| (unsigned long) prMsduInfo->u2FrameLength); |
| |
| kalMemCopy(pucIEBuf, |
| prP2pSpeBssInfo->aucAttributesCache, |
| prP2pSpeBssInfo->u2AttributeLen); |
| |
| prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; |
| |
| } while (FALSE); |
| } /* p2pFuncGenerateP2p_IEForBeacon */ |
| |
| uint32_t p2pFuncCalculateWSC_IELenForBeacon(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIdx, IN struct STA_RECORD *prStaRec) |
| { |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| |
| prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx); |
| |
| if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) |
| return 0; |
| |
| return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, |
| 0, (uint8_t) prP2pBssInfo->u4PrivateData); |
| } /* p2pFuncCalculateP2p_IELenForBeacon */ |
| |
| void p2pFuncGenerateWSC_IEForBeacon(IN struct ADAPTER *prAdapter, |
| IN struct MSDU_INFO *prMsduInfo) |
| { |
| uint8_t *pucBuffer; |
| uint16_t u2IELen = 0; |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsduInfo); |
| |
| prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); |
| |
| if (prP2pBssInfo->eNetworkType != NETWORK_TYPE_P2P) |
| return; |
| |
| u2IELen = (uint16_t) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, |
| 0, (uint8_t) prP2pBssInfo->u4PrivateData); |
| |
| pucBuffer = (uint8_t *) ((unsigned long) prMsduInfo->prPacket + |
| (unsigned long) prMsduInfo->u2FrameLength); |
| |
| ASSERT(pucBuffer); |
| |
| /* TODO: Check P2P FSM State. */ |
| kalP2PGenWSC_IE(prAdapter->prGlueInfo, |
| 0, pucBuffer, (uint8_t) prP2pBssInfo->u4PrivateData); |
| |
| prMsduInfo->u2FrameLength += u2IELen; |
| } /* p2pFuncGenerateP2p_IEForBeacon */ |
| |
| #endif |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to calculate P2P IE length for Beacon frame. |
| * |
| * @param[in] eNetTypeIndex Specify which network |
| * @param[in] prStaRec Pointer to the STA_RECORD_T |
| * |
| * @return The length of P2P IE added |
| */ |
| /*---------------------------------------------------------------------------*/ |
| uint32_t p2pFuncCalculateP2p_IELenForAssocRsp(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, IN struct STA_RECORD *prStaRec) |
| { |
| struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) |
| return 0; |
| |
| return p2pFuncCalculateP2P_IELen(prAdapter, |
| ucBssIndex, |
| prStaRec, |
| txAssocRspAttributesTable, |
| sizeof(txAssocRspAttributesTable) / |
| sizeof(struct APPEND_VAR_ATTRI_ENTRY)); |
| |
| } /* p2pFuncCalculateP2p_IELenForAssocRsp */ |
| |
| /*---------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function is used to generate P2P IE for Beacon frame. |
| * |
| * @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. |
| * |
| * @return none |
| */ |
| /*---------------------------------------------------------------------------*/ |
| void p2pFuncGenerateP2p_IEForAssocRsp(IN struct ADAPTER *prAdapter, |
| IN struct MSDU_INFO *prMsduInfo) |
| { |
| struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL; |
| |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| |
| if (!prStaRec) { |
| DBGLOG(P2P, ERROR, "prStaRec of ucStaRecIndex %d is NULL!\n", |
| prMsduInfo->ucStaRecIndex); |
| return; |
| } |
| |
| if (IS_STA_IN_P2P(prStaRec)) { |
| DBGLOG(P2P, TRACE, "Generate NULL P2P IE for Assoc Rsp.\n"); |
| |
| p2pFuncGenerateP2P_IE(prAdapter, |
| prMsduInfo->ucBssIndex, |
| TRUE, |
| &prMsduInfo->u2FrameLength, |
| prMsduInfo->prPacket, |
| 1500, |
| txAssocRspAttributesTable, |
| sizeof(txAssocRspAttributesTable) / |
| sizeof(struct APPEND_VAR_ATTRI_ENTRY)); |
| } else { |
| |
| DBGLOG(P2P, TRACE, "Legacy device, no P2P IE.\n"); |
| } |
| } /* p2pFuncGenerateP2p_IEForAssocRsp */ |
| |
| uint32_t |
| p2pFuncCalculateP2P_IELen(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN struct STA_RECORD *prStaRec, |
| IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], |
| IN uint32_t u4AttriTableSize) |
| { |
| |
| uint32_t u4OverallAttriLen, u4Dummy; |
| uint16_t u2EstimatedFixedAttriLen; |
| uint32_t i; |
| |
| /* Overall length of all Attributes */ |
| u4OverallAttriLen = 0; |
| |
| for (i = 0; i < u4AttriTableSize; i++) { |
| u2EstimatedFixedAttriLen = |
| arAppendAttriTable[i].u2EstimatedFixedAttriLen; |
| |
| if (u2EstimatedFixedAttriLen) { |
| u4OverallAttriLen += u2EstimatedFixedAttriLen; |
| } else { |
| ASSERT(arAppendAttriTable[i] |
| .pfnCalculateVariableAttriLen); |
| |
| u4OverallAttriLen += arAppendAttriTable[i] |
| .pfnCalculateVariableAttriLen |
| (prAdapter, prStaRec); |
| } |
| } |
| |
| u4Dummy = u4OverallAttriLen; |
| u4OverallAttriLen += P2P_IE_OUI_HDR; |
| |
| for (; (u4Dummy > P2P_MAXIMUM_ATTRIBUTE_LEN);) { |
| u4OverallAttriLen += P2P_IE_OUI_HDR; |
| u4Dummy -= P2P_MAXIMUM_ATTRIBUTE_LEN; |
| } |
| |
| return u4OverallAttriLen; |
| } /* p2pFuncCalculateP2P_IELen */ |
| |
| void |
| p2pFuncGenerateP2P_IE(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN u_int8_t fgIsAssocFrame, |
| IN uint16_t *pu2Offset, |
| IN uint8_t *pucBuf, |
| IN uint16_t u2BufSize, |
| IN struct APPEND_VAR_ATTRI_ENTRY arAppendAttriTable[], |
| IN uint32_t u4AttriTableSize) |
| { |
| uint8_t *pucBuffer = (uint8_t *) NULL; |
| struct IE_P2P *prIeP2P = (struct IE_P2P *) NULL; |
| uint32_t u4OverallAttriLen; |
| uint32_t u4AttriLen; |
| uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; |
| uint8_t aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; |
| uint32_t i; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); |
| |
| pucBuffer = (uint8_t *) ((unsigned long) pucBuf + (*pu2Offset)); |
| |
| ASSERT_BREAK(pucBuffer != NULL); |
| |
| /* Check buffer length is still enough. */ |
| ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); |
| |
| prIeP2P = (struct IE_P2P *) pucBuffer; |
| |
| prIeP2P->ucId = ELEM_ID_P2P; |
| |
| prIeP2P->aucOui[0] = aucWfaOui[0]; |
| prIeP2P->aucOui[1] = aucWfaOui[1]; |
| prIeP2P->aucOui[2] = aucWfaOui[2]; |
| prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; |
| |
| (*pu2Offset) += P2P_IE_OUI_HDR; |
| |
| /* Overall length of all Attributes */ |
| u4OverallAttriLen = 0; |
| |
| for (i = 0; i < u4AttriTableSize; i++) { |
| |
| if (arAppendAttriTable[i].pfnAppendAttri) { |
| u4AttriLen = |
| arAppendAttriTable[i] |
| .pfnAppendAttri(prAdapter, |
| ucBssIndex, fgIsAssocFrame, |
| pu2Offset, pucBuf, u2BufSize); |
| |
| u4OverallAttriLen += u4AttriLen; |
| |
| if (u4OverallAttriLen |
| > P2P_MAXIMUM_ATTRIBUTE_LEN) { |
| u4OverallAttriLen -= |
| P2P_MAXIMUM_ATTRIBUTE_LEN; |
| |
| prIeP2P->ucLength = |
| (VENDOR_OUI_TYPE_LEN + |
| P2P_MAXIMUM_ATTRIBUTE_LEN); |
| |
| pucBuffer = (uint8_t *) |
| ((unsigned long) |
| prIeP2P + |
| (VENDOR_OUI_TYPE_LEN + |
| P2P_MAXIMUM_ATTRIBUTE_LEN)); |
| |
| prIeP2P = (struct IE_P2P *) |
| ((unsigned long) prIeP2P + |
| (ELEM_HDR_LEN + |
| (VENDOR_OUI_TYPE_LEN + |
| P2P_MAXIMUM_ATTRIBUTE_LEN))); |
| |
| kalMemCopy(aucTempBuffer, |
| pucBuffer, u4OverallAttriLen); |
| |
| prIeP2P->ucId = ELEM_ID_P2P; |
| |
| prIeP2P->aucOui[0] = aucWfaOui[0]; |
| prIeP2P->aucOui[1] = aucWfaOui[1]; |
| prIeP2P->aucOui[2] = aucWfaOui[2]; |
| prIeP2P->ucOuiType = |
| VENDOR_OUI_TYPE_P2P; |
| |
| kalMemCopy(prIeP2P->aucP2PAttributes, |
| aucTempBuffer, |
| u4OverallAttriLen); |
| |
| (*pu2Offset) += P2P_IE_OUI_HDR; |
| } |
| |
| } |
| |
| } |
| |
| prIeP2P->ucLength = |
| (uint8_t) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); |
| |
| } while (FALSE); |
| } /* p2pFuncGenerateP2P_IE */ |
| |
| uint32_t |
| p2pFuncAppendAttriStatusForAssocRsp(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN u_int8_t fgIsAssocFrame, |
| IN uint16_t *pu2Offset, |
| IN uint8_t *pucBuf, |
| IN uint16_t u2BufSize) |
| { |
| uint8_t *pucBuffer; |
| struct P2P_ATTRI_STATUS *prAttriStatus; |
| uint32_t u4AttriLen = 0; |
| |
| ASSERT(prAdapter); |
| ASSERT(pucBuf); |
| |
| if (fgIsAssocFrame) |
| return u4AttriLen; |
| /* TODO: For assoc request P2P IE check in driver & |
| * return status in P2P IE. |
| */ |
| |
| pucBuffer = (uint8_t *) |
| ((unsigned long) pucBuf + |
| (unsigned long) (*pu2Offset)); |
| |
| ASSERT(pucBuffer); |
| prAttriStatus = (struct P2P_ATTRI_STATUS *) pucBuffer; |
| |
| ASSERT(u2BufSize >= ((*pu2Offset) + (uint16_t) u4AttriLen)); |
| |
| prAttriStatus->ucId = P2P_ATTRI_ID_STATUS; |
| WLAN_SET_FIELD_16(&prAttriStatus->u2Length, P2P_ATTRI_MAX_LEN_STATUS); |
| |
| prAttriStatus->ucStatusCode = P2P_STATUS_SUCCESS; |
| |
| u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS); |
| |
| (*pu2Offset) += (uint16_t) u4AttriLen; |
| |
| return u4AttriLen; |
| } /* p2pFuncAppendAttriStatusForAssocRsp */ |
| |
| uint32_t |
| p2pFuncAppendAttriExtListenTiming(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN u_int8_t fgIsAssocFrame, |
| IN uint16_t *pu2Offset, |
| IN uint8_t *pucBuf, |
| IN uint16_t u2BufSize) |
| { |
| uint32_t u4AttriLen = 0; |
| struct P2P_ATTRI_EXT_LISTEN_TIMING *prP2pExtListenTiming = |
| (struct P2P_ATTRI_EXT_LISTEN_TIMING *) NULL; |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = |
| (struct P2P_SPECIFIC_BSS_INFO *) NULL; |
| uint8_t *pucBuffer = NULL; |
| struct BSS_INFO *prBssInfo = NULL; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| ASSERT(prAdapter); |
| ASSERT(pucBuf); |
| ASSERT(prBssInfo); |
| |
| if (fgIsAssocFrame) |
| return u4AttriLen; |
| /* TODO: For extend listen timing. */ |
| |
| prP2pSpecificBssInfo = |
| prAdapter->rWifiVar.prP2pSpecificBssInfo |
| [prBssInfo->u4PrivateData]; |
| |
| u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); |
| |
| ASSERT(u2BufSize >= ((*pu2Offset) + (uint16_t) u4AttriLen)); |
| |
| pucBuffer = (uint8_t *) |
| ((unsigned long) pucBuf + |
| (unsigned long) (*pu2Offset)); |
| |
| ASSERT(pucBuffer); |
| |
| prP2pExtListenTiming = (struct P2P_ATTRI_EXT_LISTEN_TIMING *) pucBuffer; |
| |
| prP2pExtListenTiming->ucId = P2P_ATTRI_ID_EXT_LISTEN_TIMING; |
| WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2Length, |
| P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); |
| WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailInterval, |
| prP2pSpecificBssInfo->u2AvailabilityInterval); |
| WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailPeriod, |
| prP2pSpecificBssInfo->u2AvailabilityPeriod); |
| |
| (*pu2Offset) += (uint16_t) u4AttriLen; |
| |
| return u4AttriLen; |
| } /* p2pFuncAppendAttriExtListenTiming */ |
| |
| struct IE_HDR * |
| p2pFuncGetSpecIE(IN struct ADAPTER *prAdapter, |
| IN uint8_t *pucIEBuf, |
| IN uint16_t u2BufferLen, |
| IN uint8_t ucElemID, |
| IN u_int8_t *pfgIsMore) |
| { |
| struct IE_HDR *prTargetIE = (struct IE_HDR *) NULL; |
| uint8_t *pucIE = (uint8_t *) NULL; |
| uint16_t u2Offset = 0; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (pucIEBuf != NULL)); |
| |
| pucIE = pucIEBuf; |
| |
| if (pfgIsMore) |
| *pfgIsMore = FALSE; |
| |
| IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { |
| if (IE_ID(pucIE) == ucElemID) { |
| if ((prTargetIE) && (pfgIsMore)) { |
| |
| *pfgIsMore = TRUE; |
| break; |
| } |
| prTargetIE = (struct IE_HDR *) pucIE; |
| |
| if (pfgIsMore == NULL) |
| break; |
| |
| } |
| } |
| |
| } while (FALSE); |
| |
| return prTargetIE; |
| } /* p2pFuncGetSpecIE */ |
| |
| struct P2P_ATTRIBUTE * |
| p2pFuncGetSpecAttri(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucOuiType, |
| IN uint8_t *pucIEBuf, |
| IN uint16_t u2BufferLen, |
| IN uint8_t ucAttriID) |
| { |
| struct IE_P2P *prP2pIE = (struct IE_P2P *) NULL; |
| struct P2P_ATTRIBUTE *prTargetAttri = (struct P2P_ATTRIBUTE *) NULL; |
| u_int8_t fgIsMore = FALSE; |
| uint8_t *pucIE = (uint8_t *) NULL; |
| uint16_t u2BufferLenLeft = 0; |
| |
| DBGLOG(P2P, INFO, |
| "Check AssocReq Oui type %u attri %u for len %u\n", |
| ucOuiType, ucAttriID, u2BufferLen); |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (pucIEBuf != NULL)); |
| |
| u2BufferLenLeft = u2BufferLen; |
| pucIE = pucIEBuf; |
| |
| do { |
| fgIsMore = FALSE; |
| prP2pIE = (struct IE_P2P *) p2pFuncGetSpecIE(prAdapter, |
| pucIE, u2BufferLenLeft, |
| ELEM_ID_VENDOR, &fgIsMore); |
| if (prP2pIE) { |
| ASSERT((unsigned long) prP2pIE |
| >= (unsigned long) pucIE); |
| u2BufferLenLeft = u2BufferLen - |
| (uint16_t) (((unsigned long) prP2pIE) - |
| ((unsigned long) pucIEBuf)); |
| |
| DBGLOG(P2P, INFO, |
| "Find vendor id %u len %u oui %u more %u LeftLen %u\n", |
| IE_ID(prP2pIE), IE_LEN(prP2pIE), |
| prP2pIE->ucOuiType, fgIsMore, |
| u2BufferLenLeft); |
| |
| if (IE_LEN(prP2pIE) > P2P_OUI_TYPE_LEN) |
| p2pFuncGetSpecAttriAction(prP2pIE, |
| ucOuiType, ucAttriID, |
| &prTargetAttri); |
| /* P2P_OUI_TYPE_LEN */ |
| pucIE = (uint8_t *) |
| (((unsigned long) prP2pIE) + |
| IE_SIZE(prP2pIE)); |
| } |
| /* prP2pIE */ |
| } while (prP2pIE && fgIsMore && u2BufferLenLeft); |
| |
| } while (FALSE); |
| |
| return prTargetAttri; |
| } |
| |
| /* p2pFuncGetSpecAttri */ |
| |
| /* Code refactoring for AOSP */ |
| static void |
| p2pFuncGetSpecAttriAction(IN struct IE_P2P *prP2pIE, |
| IN uint8_t ucOuiType, |
| IN uint8_t ucAttriID, |
| OUT struct P2P_ATTRIBUTE **prTargetAttri) |
| { |
| uint8_t *pucAttri = (uint8_t *) NULL; |
| uint16_t u2OffsetAttri = 0; |
| uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; |
| |
| if (prP2pIE->ucOuiType == ucOuiType) { |
| switch (ucOuiType) { |
| case VENDOR_OUI_TYPE_WPS: |
| aucWfaOui[0] = 0x00; |
| aucWfaOui[1] = 0x50; |
| aucWfaOui[2] = 0xF2; |
| break; |
| case VENDOR_OUI_TYPE_P2P: |
| break; |
| case VENDOR_OUI_TYPE_WPA: |
| case VENDOR_OUI_TYPE_WMM: |
| case VENDOR_OUI_TYPE_WFD: |
| default: |
| break; |
| } |
| |
| if ((prP2pIE->aucOui[0] == aucWfaOui[0]) && |
| (prP2pIE->aucOui[1] == aucWfaOui[1]) && |
| (prP2pIE->aucOui[2] == aucWfaOui[2])) { |
| |
| u2OffsetAttri = 0; |
| pucAttri = prP2pIE->aucP2PAttributes; |
| |
| if (ucOuiType == VENDOR_OUI_TYPE_WPS) { |
| WSC_ATTRI_FOR_EACH(pucAttri, |
| (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), |
| u2OffsetAttri) { |
| if (WSC_ATTRI_ID(pucAttri) |
| == ucAttriID) { |
| *prTargetAttri = |
| (struct P2P_ATTRIBUTE *) |
| pucAttri; |
| break; |
| } |
| |
| } |
| |
| } else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { |
| P2P_ATTRI_FOR_EACH(pucAttri, |
| (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), |
| u2OffsetAttri) { |
| if (ATTRI_ID(pucAttri) |
| == ucAttriID) { |
| *prTargetAttri = |
| (struct P2P_ATTRIBUTE *) |
| pucAttri; |
| break; |
| } |
| } |
| |
| } |
| #if CFG_SUPPORT_WFD |
| else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { |
| WFD_ATTRI_FOR_EACH(pucAttri, |
| (IE_LEN(prP2pIE) - P2P_IE_OUI_HDR), |
| u2OffsetAttri) { |
| if (ATTRI_ID(pucAttri) |
| == (uint8_t) ucAttriID) { |
| *prTargetAttri = |
| (struct P2P_ATTRIBUTE *) |
| pucAttri; |
| break; |
| } |
| } |
| } |
| #endif |
| else { |
| /* Todo:: Nothing */ |
| /* Possible or else. */ |
| } |
| } |
| } /* ucOuiType */ |
| } |
| |
| uint32_t |
| p2pFuncGenerateBeaconProbeRsp(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prBssInfo, |
| IN struct MSDU_INFO *prMsduInfo, |
| IN u_int8_t fgIsProbeRsp) |
| { |
| uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; |
| struct WLAN_BEACON_FRAME *prBcnFrame = |
| (struct WLAN_BEACON_FRAME *) NULL; |
| /* P_APPEND_VAR_IE_ENTRY_T prAppendIeTable = |
| * (P_APPEND_VAR_IE_ENTRY_T)NULL; |
| */ |
| |
| do { |
| |
| ASSERT_BREAK((prAdapter != NULL) |
| && (prBssInfo != NULL) |
| && (prMsduInfo != NULL)); |
| |
| /* txBcnIETable */ |
| |
| /* txProbeRspIETable */ |
| |
| prBcnFrame = (struct WLAN_BEACON_FRAME *) prMsduInfo->prPacket; |
| |
| return nicUpdateBeaconIETemplate(prAdapter, |
| IE_UPD_METHOD_UPDATE_ALL, |
| prBssInfo->ucBssIndex, |
| prBssInfo->u2CapInfo, |
| (uint8_t *) prBcnFrame->aucInfoElem, |
| prMsduInfo->u2FrameLength - |
| OFFSET_OF(struct WLAN_BEACON_FRAME, aucInfoElem)); |
| |
| } while (FALSE); |
| |
| return rWlanStatus; |
| } /* p2pFuncGenerateBeaconProbeRsp */ |
| |
| uint32_t |
| p2pFuncComposeBeaconProbeRspTemplate(IN struct ADAPTER *prAdapter, |
| IN struct BSS_INFO *prP2pBssInfo, |
| IN uint8_t *pucBcnBuffer, |
| IN uint32_t u4BcnBufLen, |
| IN u_int8_t fgIsProbeRsp, |
| IN struct P2P_PROBE_RSP_UPDATE_INFO *prP2pProbeRspInfo, |
| IN u_int8_t fgSynToFW) |
| { |
| uint32_t rWlanStatus = WLAN_STATUS_SUCCESS; |
| struct MSDU_INFO *prMsduInfo = (struct MSDU_INFO *) NULL; |
| struct WLAN_MAC_HEADER *prWlanBcnFrame = |
| (struct WLAN_MAC_HEADER *) NULL; |
| |
| uint8_t *pucBuffer = (uint8_t *) NULL; |
| |
| do { |
| ASSERT_BREAK((prAdapter != NULL) |
| && (pucBcnBuffer != NULL) |
| && (prP2pBssInfo != NULL)); |
| |
| prWlanBcnFrame = (struct WLAN_MAC_HEADER *) pucBcnBuffer; |
| |
| if ((prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_BEACON) |
| && (!fgIsProbeRsp)) { |
| rWlanStatus = WLAN_STATUS_INVALID_DATA; |
| break; |
| } |
| |
| else if (prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_PROBE_RSP) { |
| rWlanStatus = WLAN_STATUS_INVALID_DATA; |
| break; |
| } |
| |
| if (fgIsProbeRsp) { |
| ASSERT_BREAK(prP2pProbeRspInfo != NULL); |
| |
| if (!prP2pProbeRspInfo->prProbeRspMsduTemplate) |
| cnmMgtPktFree(prAdapter, |
| prP2pProbeRspInfo->prProbeRspMsduTemplate); |
| |
| prP2pProbeRspInfo->prProbeRspMsduTemplate = |
| cnmMgtPktAlloc(prAdapter, u4BcnBufLen); |
| |
| prMsduInfo = prP2pProbeRspInfo->prProbeRspMsduTemplate; |
| |
| if (prMsduInfo == NULL) { |
| rWlanStatus = WLAN_STATUS_FAILURE; |
| break; |
| } |
| |
| prMsduInfo->eSrc = TX_PACKET_MGMT; |
| prMsduInfo->ucStaRecIndex = 0xFF; |
| prMsduInfo->ucBssIndex = prP2pBssInfo->ucBssIndex; |
| |
| } else { |
| prMsduInfo = prP2pBssInfo->prBeacon; |
| |
| if (prMsduInfo == NULL) { |
| rWlanStatus = WLAN_STATUS_FAILURE; |
| break; |
| } |
| |
| if (u4BcnBufLen > |
| (OFFSET_OF(struct WLAN_BEACON_FRAME, |
| aucInfoElem[0]) + MAX_IE_LENGTH)) { |
| /* Unexpected error, buffer overflow. */ |
| ASSERT(FALSE); |
| break; |
| } |
| |
| } |
| |
| pucBuffer = (uint8_t *) |
| ((unsigned long) (prMsduInfo->prPacket) + |
| MAC_TX_RESERVED_FIELD); |
| |
| kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); |
| |
| prMsduInfo->fgIs802_11 = TRUE; |
| prMsduInfo->u2FrameLength = (uint16_t) u4BcnBufLen; |
| |
| if (fgSynToFW) |
| rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, |
| prP2pBssInfo, prMsduInfo, fgIsProbeRsp); |
| |
| } while (FALSE); |
| |
| return rWlanStatus; |
| |
| } /* p2pFuncComposeBeaconTemplate */ |
| |
| uint32_t wfdFuncCalculateWfdIELenForAssocRsp(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| IN struct STA_RECORD *prStaRec) |
| { |
| |
| #if CFG_SUPPORT_WFD_COMPOSE_IE |
| uint16_t u2EstimatedExtraIELen = 0; |
| struct BSS_INFO *prBssInfo = (struct BSS_INFO *) NULL; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| |
| if (prBssInfo->eNetworkType != NETWORK_TYPE_P2P) |
| return 0; |
| |
| if (!IS_STA_P2P_TYPE(prStaRec)) |
| return 0; |
| |
| u2EstimatedExtraIELen = |
| prAdapter->prGlueInfo->prP2PInfo[0]->u2WFDIELen; |
| |
| if (u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) |
| return u2EstimatedExtraIELen; |
| else |
| return 0; |
| #else |
| return 0; |
| #endif |
| } /* wfdFuncCalculateWfdIELenForAssocRsp */ |
| |
| void wfdFuncGenerateWfdIEForAssocRsp(IN struct ADAPTER *prAdapter, |
| IN struct MSDU_INFO *prMsduInfo) |
| { |
| |
| #if CFG_SUPPORT_WFD_COMPOSE_IE |
| struct STA_RECORD *prStaRec; |
| uint16_t u2EstimatedExtraIELen; |
| struct BSS_INFO *prP2pBssInfo = (struct BSS_INFO *) NULL; |
| struct GLUE_INFO *prGlueInfo; |
| struct GL_P2P_INFO *prP2PInfo; |
| |
| if (!prAdapter) |
| return; |
| |
| if (!prMsduInfo) |
| return; |
| |
| prGlueInfo = prAdapter->prGlueInfo; |
| if (!prGlueInfo) |
| return; |
| |
| prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); |
| if (!prStaRec) |
| return; |
| |
| if (!IS_STA_P2P_TYPE(prStaRec)) |
| return; |
| |
| prP2pBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prMsduInfo->ucBssIndex); |
| prP2PInfo = prGlueInfo->prP2PInfo[prP2pBssInfo->u4PrivateData]; |
| if (!prP2PInfo) |
| return; |
| |
| u2EstimatedExtraIELen = prP2PInfo->u2WFDIELen; |
| if (u2EstimatedExtraIELen > 0 |
| && u2EstimatedExtraIELen < VENDOR_SPECIFIC_IE_LENGTH) { |
| kalMemCopy((prMsduInfo->prPacket + prMsduInfo->u2FrameLength), |
| prP2PInfo->aucWFDIE, u2EstimatedExtraIELen); |
| prMsduInfo->u2FrameLength += u2EstimatedExtraIELen; |
| } |
| |
| return; |
| #else |
| |
| return; |
| #endif |
| } /* wfdFuncGenerateWfdIEForAssocRsp */ |
| |
| void |
| p2pFuncComposeNoaAttribute(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIndex, |
| OUT uint8_t *aucNoaAttrArray, |
| OUT uint32_t *pu4Len) |
| { |
| struct BSS_INFO *prBssInfo = NULL; |
| struct P2P_ATTRI_NOA *prNoaAttr = NULL; |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = NULL; |
| struct NOA_DESCRIPTOR *prNoaDesc = NULL; |
| uint32_t u4NumOfNoaDesc = 0; |
| uint32_t i = 0; |
| |
| prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIndex); |
| prP2pSpecificBssInfo = |
| prAdapter->rWifiVar |
| .prP2pSpecificBssInfo[prBssInfo->u4PrivateData]; |
| |
| prNoaAttr = (struct P2P_ATTRI_NOA *) aucNoaAttrArray; |
| |
| prNoaAttr->ucId = P2P_ATTRI_ID_NOTICE_OF_ABSENCE; |
| prNoaAttr->ucIndex = prP2pSpecificBssInfo->ucNoAIndex; |
| |
| if (prP2pSpecificBssInfo->fgEnableOppPS) { |
| prNoaAttr->ucCTWOppPSParam = |
| P2P_CTW_OPPPS_PARAM_OPPPS_FIELD | |
| (prP2pSpecificBssInfo->u2CTWindow & |
| P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK); |
| } else { |
| prNoaAttr->ucCTWOppPSParam = 0; |
| } |
| |
| for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { |
| if (prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse) { |
| prNoaDesc = (struct NOA_DESCRIPTOR *) |
| &prNoaAttr->aucNoADesc |
| [i * sizeof(struct NOA_DESCRIPTOR)]; |
| |
| prNoaDesc->ucCountType = |
| prP2pSpecificBssInfo->arNoATiming[i].ucCount; |
| prNoaDesc->u4Duration = |
| prP2pSpecificBssInfo->arNoATiming[i].u4Duration; |
| prNoaDesc->u4Interval = |
| prP2pSpecificBssInfo->arNoATiming[i].u4Interval; |
| prNoaDesc->u4StartTime = |
| prP2pSpecificBssInfo->arNoATiming[i] |
| .u4StartTime; |
| |
| u4NumOfNoaDesc++; |
| } |
| } |
| |
| /* include "index" + "OppPs Params" + "NOA descriptors" */ |
| prNoaAttr->u2Length = 2 + |
| u4NumOfNoaDesc * sizeof(struct NOA_DESCRIPTOR); |
| |
| /* include "Attribute ID" + "Length" + "index" + |
| * "OppPs Params" + "NOA descriptors" |
| */ |
| *pu4Len = P2P_ATTRI_HDR_LEN + prNoaAttr->u2Length; |
| } |
| |
| uint32_t p2pFuncCalculateP2P_IE_NoA(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucBssIdx, |
| IN struct STA_RECORD *prStaRec) |
| { |
| struct P2P_SPECIFIC_BSS_INFO *prP2pSpecificBssInfo = NULL; |
| uint8_t ucIdx; |
| uint32_t u4NumOfNoaDesc = 0; |
| struct BSS_INFO *prBssInfo; |
| |
| prBssInfo = prAdapter->aprBssInfo[ucBssIdx]; |
| |
| if (p2pFuncIsAPMode( |
| prAdapter->rWifiVar.prP2PConnSettings |
| [prBssInfo->u4PrivateData])) |
| return 0; |
| |
| prP2pSpecificBssInfo = |
| prAdapter->rWifiVar.prP2pSpecificBssInfo |
| [prBssInfo->u4PrivateData]; |
| |
| for (ucIdx = 0; |
| ucIdx < prP2pSpecificBssInfo->ucNoATimingCount; ucIdx++) { |
| if (prP2pSpecificBssInfo->arNoATiming[ucIdx].fgIsInUse) |
| u4NumOfNoaDesc++; |
| } |
| |
| /* include "index" + "OppPs Params" + "NOA descriptors" */ |
| /* include "Attribute ID" + "Length" + "index" + |
| * "OppPs Params" + "NOA descriptors" |
| */ |
| return P2P_ATTRI_HDR_LEN + 2 + |
| (u4NumOfNoaDesc * sizeof(struct NOA_DESCRIPTOR)); |
| } |
| |
| void p2pFuncGenerateP2P_IE_NoA(IN struct ADAPTER *prAdapter, |
| IN struct MSDU_INFO *prMsduInfo) |
| { |
| struct IE_P2P *prIeP2P; |
| uint8_t aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; |
| uint32_t u4AttributeLen; |
| struct BSS_INFO *prBssInfo; |
| |
| prBssInfo = |
| prAdapter->aprBssInfo[prMsduInfo->ucBssIndex]; |
| |
| if (p2pFuncIsAPMode( |
| prAdapter->rWifiVar.prP2PConnSettings |
| [prBssInfo->u4PrivateData])) |
| return; |
| |
| prIeP2P = (struct IE_P2P *) |
| ((unsigned long) prMsduInfo->prPacket + |
| (uint32_t) prMsduInfo->u2FrameLength); |
| |
| prIeP2P->ucId = ELEM_ID_P2P; |
| prIeP2P->aucOui[0] = aucWfaOui[0]; |
| prIeP2P->aucOui[1] = aucWfaOui[1]; |
| prIeP2P->aucOui[2] = aucWfaOui[2]; |
| prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; |
| |
| /* Compose NoA attribute */ |
| p2pFuncComposeNoaAttribute(prAdapter, |
| prMsduInfo->ucBssIndex, |
| prIeP2P->aucP2PAttributes, |
| &u4AttributeLen); |
| |
| prIeP2P->ucLength = VENDOR_OUI_TYPE_LEN + u4AttributeLen; |
| |
| prMsduInfo->u2FrameLength += (ELEM_HDR_LEN + prIeP2P->ucLength); |
| |
| } |
| |
| void p2pFunCleanQueuedMgmtFrame(IN struct ADAPTER *prAdapter, |
| IN struct P2P_QUEUED_ACTION_FRAME *prFrame) |
| { |
| if (prAdapter == NULL || prFrame == NULL || prFrame->u2Length == 0 || |
| prFrame->prHeader == NULL) |
| return; |
| |
| DBGLOG(P2P, INFO, "Clean queued p2p action frame.\n"); |
| |
| prFrame->ucRoleIdx = 0; |
| prFrame->u4Freq = 0; |
| prFrame->u2Length = 0; |
| cnmMemFree(prAdapter, prFrame->prHeader); |
| prFrame->prHeader = NULL; |
| } |
| |
| void p2pFuncClassifyAction(IN struct SW_RFB *prSwRfb) |
| { |
| struct P2P_PUBLIC_ACTION_FRAME *pFrame = |
| (struct P2P_PUBLIC_ACTION_FRAME *) prSwRfb->pvHeader; |
| |
| if ((pFrame->ucCategory == CATEGORY_PUBLIC_ACTION) && |
| (pFrame->ucAction == ACTION_PUBLIC_WIFI_DIRECT)) { |
| switch (pFrame->ucOuiSubtype) { |
| case P2P_PUBLIC_ACTION_GO_NEGO_REQ: |
| DBGLOG(P2P, WARN, "NEGO Req\n"); |
| break; |
| case P2P_PUBLIC_ACTION_GO_NEGO_RSP: |
| DBGLOG(P2P, WARN, "NEGO Resp\n"); |
| break; |
| case P2P_PUBLIC_ACTION_GO_NEGO_CFM: |
| DBGLOG(P2P, WARN, "NEGO Confirm\n"); |
| break; |
| case P2P_PUBLIC_ACTION_INVITATION_REQ: |
| DBGLOG(P2P, WARN, "Invitation Req\n"); |
| break; |
| case P2P_PUBLIC_ACTION_INVITATION_RSP: |
| DBGLOG(P2P, WARN, "Invitation Resp\n"); |
| break; |
| case P2P_PUBLIC_ACTION_DEV_DISCOVER_REQ: |
| DBGLOG(P2P, WARN, "Discovery Req\n"); |
| break; |
| case P2P_PUBLIC_ACTION_DEV_DISCOVER_RSP: |
| DBGLOG(P2P, WARN, "Discovery Resp\n"); |
| break; |
| case P2P_PUBLIC_ACTION_PROV_DISCOVERY_REQ: |
| DBGLOG(P2P, WARN, "Provision Req\n"); |
| break; |
| case P2P_PUBLIC_ACTION_PROV_DISCOVERY_RSP: |
| DBGLOG(P2P, WARN, "Provision Resp\n"); |
| break; |
| default: |
| DBGLOG(P2P, WARN, "unknown action type %d\n", |
| pFrame->ucOuiSubtype); |
| break; |
| } |
| } |
| } |
| |
| uint32_t |
| p2pFunGetPreferredFreqList(IN struct ADAPTER *prAdapter, |
| IN enum ENUM_IFTYPE eIftype, OUT uint32_t *freq_list, |
| OUT uint32_t *num_freq_list) |
| { |
| struct BSS_INFO *prAisBssInfo; |
| uint8_t ucNumOfChannel; |
| uint32_t i; |
| struct RF_CHANNEL_INFO *aucChannelList; |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| aucChannelList = (struct RF_CHANNEL_INFO *) kalMemAlloc( |
| sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM, |
| VIR_MEM_TYPE); |
| if (!aucChannelList) { |
| DBGLOG(P2P, ERROR, |
| "Allocate buffer for channel list fail\n"); |
| return -ENOMEM; |
| } |
| kalMemZero(aucChannelList, |
| sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM); |
| |
| DBGLOG(P2P, INFO, "iftype: %d, STA connection state: %d\n", |
| eIftype, |
| prAisBssInfo->eConnectionState); |
| |
| if (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED) { |
| /* Prefer 5G p2p channel if STA is NOT connected */ |
| rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, |
| MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); |
| if (ucNumOfChannel == 0) |
| rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, |
| MAX_CHN_NUM, &ucNumOfChannel, aucChannelList); |
| for (i = 0; i < ucNumOfChannel; i++) { |
| freq_list[i] = nicChannelNum2Freq( |
| aucChannelList[i].ucChannelNum) / 1000; |
| (*num_freq_list)++; |
| } |
| } else if (prAdapter->rWifiVar.eDbdcMode == |
| ENUM_DBDC_MODE_DISABLED) { |
| /* DBDC disabled */ |
| DBGLOG(P2P, INFO, |
| "Prefer SCC, STA operating channel: %d, band: %d", |
| prAisBssInfo->ucPrimaryChannel, |
| prAisBssInfo->eBand); |
| freq_list[0] = nicChannelNum2Freq( |
| prAisBssInfo->ucPrimaryChannel) / 1000; |
| (*num_freq_list)++; |
| } else { |
| /* DBDC enabled */ |
| DBGLOG(P2P, INFO, "STA operating channel: %d, band: %d", |
| prAisBssInfo->ucPrimaryChannel, |
| prAisBssInfo->eBand); |
| if (prAisBssInfo->eBand == BAND_2G4) { |
| /* Prefer 5G if STA is connected at 2G band */ |
| rlmDomainGetChnlList(prAdapter, BAND_5G, TRUE, |
| MAX_CHN_NUM, |
| &ucNumOfChannel, |
| aucChannelList); |
| for (i = 0; i < ucNumOfChannel; i++) { |
| freq_list[i] = nicChannelNum2Freq( |
| aucChannelList[i].ucChannelNum) / 1000; |
| (*num_freq_list)++; |
| } |
| |
| /* Add SCC channel */ |
| freq_list[i + 1] = nicChannelNum2Freq( |
| prAisBssInfo->ucPrimaryChannel) / 1000; |
| (*num_freq_list)++; |
| } else { |
| /* Prefer SCC if STA is connected at 5G band */ |
| freq_list[0] = nicChannelNum2Freq( |
| prAisBssInfo->ucPrimaryChannel) / 1000; |
| (*num_freq_list)++; |
| |
| rlmDomainGetChnlList(prAdapter, BAND_2G4, TRUE, |
| MAX_CHN_NUM, |
| &ucNumOfChannel, |
| aucChannelList); |
| for (i = 0; i < ucNumOfChannel; i++) { |
| freq_list[i + 1] = nicChannelNum2Freq( |
| aucChannelList[i].ucChannelNum) / 1000; |
| (*num_freq_list)++; |
| } |
| } |
| } |
| |
| kalMemFree(aucChannelList, VIR_MEM_TYPE, |
| sizeof(struct RF_CHANNEL_INFO) * MAX_CHN_NUM); |
| |
| return WLAN_STATUS_SUCCESS; |
| } |
| |
| uint8_t p2pFunGetAcsBestCh(IN struct ADAPTER *prAdapter, |
| IN enum ENUM_BAND eBand, |
| IN enum ENUM_MAX_BANDWIDTH_SETTING eChnlBw, |
| IN uint32_t u4LteSafeChnMask_2G, |
| IN uint32_t u4LteSafeChnMask_5G_1, |
| IN uint32_t u4LteSafeChnMask_5G_2) |
| { |
| struct RF_CHANNEL_INFO aucChannelList[MAX_PER_BAND_CHN_NUM]; |
| uint8_t ucNumOfChannel; |
| struct PARAM_GET_CHN_INFO *prGetChnLoad; |
| uint8_t i; |
| struct PARAM_PREFER_CHN_INFO rPreferChannel; |
| |
| /* reset */ |
| rPreferChannel.ucChannel = 0; |
| rPreferChannel.u4Dirtiness = 0xFFFFFFFF; |
| |
| kalMemZero(aucChannelList, |
| sizeof(struct RF_CHANNEL_INFO) * MAX_PER_BAND_CHN_NUM); |
| |
| rlmDomainGetChnlList(prAdapter, eBand, TRUE, MAX_PER_BAND_CHN_NUM, |
| &ucNumOfChannel, aucChannelList); |
| |
| /* |
| * 2. Calculate each channel's dirty score |
| */ |
| prGetChnLoad = &(prAdapter->rWifiVar.rChnLoadInfo); |
| |
| DBGLOG(P2P, INFO, "acs chnl mask=[0x%08x][0x%08x][0x%08x]\n", |
| u4LteSafeChnMask_2G, |
| u4LteSafeChnMask_5G_1, |
| u4LteSafeChnMask_5G_2); |
| |
| for (i = 0; i < ucNumOfChannel; i++) { |
| uint8_t ucIdx; |
| |
| ucIdx = wlanGetChannelIndex(aucChannelList[i].ucChannelNum); |
| if (ucIdx >= MAX_PER_BAND_CHN_NUM) |
| continue; |
| |
| DBGLOG(P2P, TRACE, "idx: %u, ch: %u, d: %d\n", |
| ucIdx, |
| aucChannelList[i].ucChannelNum, |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness); |
| |
| if (aucChannelList[i].ucChannelNum <= 14) { |
| if (!(u4LteSafeChnMask_2G & BIT( |
| aucChannelList[i].ucChannelNum))) |
| continue; |
| } else if ((aucChannelList[i].ucChannelNum >= 36) && |
| (aucChannelList[i].ucChannelNum <= 144)) { |
| if (!(u4LteSafeChnMask_5G_1 & BIT( |
| (aucChannelList[i].ucChannelNum - 36) / 4))) |
| continue; |
| } else if ((aucChannelList[i].ucChannelNum >= 149) && |
| (aucChannelList[i].ucChannelNum <= 181)) { |
| if (!(u4LteSafeChnMask_5G_2 & BIT( |
| (aucChannelList[i].ucChannelNum - 149) / 4))) |
| continue; |
| } |
| |
| if (eBand == BAND_5G && eChnlBw >= MAX_BW_80MHZ && |
| nicGetVhtS1(aucChannelList[i].ucChannelNum, |
| VHT_OP_CHANNEL_WIDTH_80) == 0) |
| continue; |
| |
| if (rPreferChannel.u4Dirtiness > |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness) { |
| rPreferChannel.ucChannel = |
| prGetChnLoad->rEachChnLoad[ucIdx].ucChannel; |
| rPreferChannel.u4Dirtiness = |
| prGetChnLoad->rEachChnLoad[ucIdx].u4Dirtiness; |
| } |
| } |
| |
| return rPreferChannel.ucChannel; |
| } |
| |
| void p2pFunProcessAcsReport(IN struct ADAPTER *prAdapter, |
| IN uint8_t ucRoleIndex, |
| IN struct PARAM_GET_CHN_INFO *prLteSafeChnInfo, |
| IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) |
| { |
| enum ENUM_BAND eBand; |
| uint32_t u4LteSafeChnMask_2G = -1; |
| |
| if (!prAdapter || !prAcsReqInfo) |
| return; |
| |
| if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11B || |
| prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11G) |
| eBand = BAND_2G4; |
| else |
| eBand = BAND_5G; |
| |
| if (prLteSafeChnInfo && (eBand == BAND_2G4)) { |
| struct LTE_SAFE_CHN_INFO *prLteSafeChnList; |
| struct RF_CHANNEL_INFO aucChannelList[MAX_2G_BAND_CHN_NUM]; |
| uint8_t ucNumOfChannel; |
| uint8_t i; |
| u_int8_t fgIsMaskValid = FALSE; |
| |
| kalMemZero(aucChannelList, |
| sizeof(struct RF_CHANNEL_INFO) * MAX_2G_BAND_CHN_NUM); |
| |
| rlmDomainGetChnlList(prAdapter, eBand, TRUE, |
| MAX_2G_BAND_CHN_NUM, &ucNumOfChannel, aucChannelList); |
| |
| prLteSafeChnList = &prLteSafeChnInfo->rLteSafeChnList; |
| u4LteSafeChnMask_2G = prLteSafeChnList->au4SafeChannelBitmask[ |
| ENUM_SAFE_CH_MASK_BAND_2G4]; |
| |
| #if CFG_TC1_FEATURE |
| /* Restrict 2.4G band channel selection range |
| * to 1/6/11 per customer's request |
| */ |
| u4LteSafeChnMask_2G &= 0x0842; |
| #elif CFG_TC10_FEATURE |
| /* Restrict 2.4G band channel selection range |
| * to 1~11 per customer's request |
| */ |
| u4LteSafeChnMask_2G &= 0x0FFE; |
| #endif |
| prAcsReqInfo->u4LteSafeChnMask_2G &= u4LteSafeChnMask_2G; |
| for (i = 0; i < ucNumOfChannel; i++) { |
| if ((prAcsReqInfo->u4LteSafeChnMask_2G & |
| BIT(aucChannelList[i].ucChannelNum))) |
| fgIsMaskValid = TRUE; |
| } |
| if (!fgIsMaskValid) { |
| DBGLOG(P2P, WARN, |
| "All mask invalid, mark all as valid\n"); |
| prAcsReqInfo->u4LteSafeChnMask_2G = BITS(1, 14); |
| } |
| } else if (prLteSafeChnInfo && (eBand == BAND_5G)) { |
| /* Add support for 5G FW mask */ |
| struct LTE_SAFE_CHN_INFO *prLteSafeChnList = |
| &prLteSafeChnInfo->rLteSafeChnList; |
| uint32_t u4LteSafeChnMask_5G_1 = |
| prLteSafeChnList->au4SafeChannelBitmask |
| [ENUM_SAFE_CH_MASK_BAND_5G_0]; |
| uint32_t u4LteSafeChnMask_5G_2 = |
| prLteSafeChnList->au4SafeChannelBitmask |
| [ENUM_SAFE_CH_MASK_BAND_5G_1]; |
| |
| prAcsReqInfo->u4LteSafeChnMask_5G_1 &= u4LteSafeChnMask_5G_1; |
| prAcsReqInfo->u4LteSafeChnMask_5G_1 &= u4LteSafeChnMask_5G_2; |
| } |
| |
| prAcsReqInfo->ucPrimaryCh = p2pFunGetAcsBestCh(prAdapter, |
| eBand, |
| prAcsReqInfo->eChnlBw, |
| prAcsReqInfo->u4LteSafeChnMask_2G, |
| prAcsReqInfo->u4LteSafeChnMask_5G_1, |
| prAcsReqInfo->u4LteSafeChnMask_5G_2); |
| |
| p2pFunIndicateAcsResult(prAdapter->prGlueInfo, |
| prAcsReqInfo); |
| } |
| |
| enum ENUM_CHNL_EXT p2pFunGetSco(IN struct ADAPTER *prAdapter, |
| enum ENUM_BAND eBand, uint8_t ucPrimaryCh) { |
| enum ENUM_CHNL_EXT eSCO = CHNL_EXT_SCN; |
| uint8_t ucSecondChannel; |
| |
| if (eBand == BAND_2G4) { |
| if (ucPrimaryCh != 14) |
| eSCO = (ucPrimaryCh > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA; |
| } else { |
| if (regd_is_single_sku_en()) { |
| if (rlmDomainIsLegalChannel(prAdapter, |
| eBand, |
| ucPrimaryCh)) |
| eSCO = rlmSelectSecondaryChannelType(prAdapter, |
| eBand, |
| ucPrimaryCh); |
| } else { |
| struct DOMAIN_INFO_ENTRY *prDomainInfo = |
| rlmDomainGetDomainInfo(prAdapter); |
| struct DOMAIN_SUBBAND_INFO *prSubband; |
| uint8_t i, j; |
| |
| for (i = 0; i < MAX_SUBBAND_NUM; i++) { |
| prSubband = &prDomainInfo->rSubBand[i]; |
| if (prSubband->ucBand != eBand) |
| continue; |
| for (j = 0; j < prSubband->ucNumChannels; j++) { |
| if ((prSubband->ucFirstChannelNum + |
| j * prSubband->ucChannelSpan) == |
| ucPrimaryCh) { |
| eSCO = (j & 1) ? |
| CHNL_EXT_SCB : |
| CHNL_EXT_SCA; |
| break; |
| } |
| } |
| |
| if (j < prSubband->ucNumChannels) |
| break; /* Found */ |
| } |
| } |
| } |
| /* Check if it is boundary channel |
| * and 40MHz BW is permitted |
| */ |
| if (eSCO != CHNL_EXT_SCN) { |
| ucSecondChannel = (eSCO == CHNL_EXT_SCA) |
| ? (ucPrimaryCh + CHNL_SPAN_20) |
| : (ucPrimaryCh - CHNL_SPAN_20); |
| |
| if (!rlmDomainIsLegalChannel(prAdapter, |
| eBand, |
| ucSecondChannel)) |
| eSCO = CHNL_EXT_SCN; |
| } |
| return eSCO; |
| } |
| |
| uint8_t p2pFunGetSecCh(IN struct ADAPTER *prAdapter, |
| IN enum ENUM_BAND eBand, |
| IN enum ENUM_CHNL_EXT eSCO, |
| IN uint8_t ucPrimaryCh) |
| { |
| uint8_t ucSecondCh; |
| |
| if (eSCO == CHNL_EXT_SCN) |
| return 0; |
| |
| if (eSCO == CHNL_EXT_SCA) |
| ucSecondCh = ucPrimaryCh + CHNL_SPAN_20; |
| else |
| ucSecondCh = ucPrimaryCh - CHNL_SPAN_20; |
| |
| if (!rlmDomainIsLegalChannel(prAdapter, eBand, ucSecondCh)) |
| ucSecondCh = 0; |
| |
| return ucSecondCh; |
| } |
| |
| void p2pFunIndicateAcsResult(IN struct GLUE_INFO *prGlueInfo, |
| IN struct P2P_ACS_REQ_INFO *prAcsReqInfo) |
| { |
| uint8_t ucVhtBw = VHT_OP_CHANNEL_WIDTH_20_40; |
| |
| if (prAcsReqInfo->ucPrimaryCh == 0) { |
| if (prAcsReqInfo->eHwMode == P2P_VENDOR_ACS_HW_MODE_11B || |
| prAcsReqInfo->eHwMode == |
| P2P_VENDOR_ACS_HW_MODE_11G) { |
| prAcsReqInfo->ucPrimaryCh = AP_DEFAULT_CHANNEL_2G; |
| } else { |
| prAcsReqInfo->ucPrimaryCh = AP_DEFAULT_CHANNEL_5G; |
| } |
| DBGLOG(P2P, WARN, "No chosed channel, use default channel %d\n", |
| prAcsReqInfo->ucPrimaryCh); |
| } |
| |
| if (prAcsReqInfo->eChnlBw > MAX_BW_20MHZ) { |
| enum ENUM_BAND eBand; |
| enum ENUM_CHNL_EXT eSCO; |
| |
| eBand = prAcsReqInfo->ucPrimaryCh <= 14 ? BAND_2G4 : BAND_5G; |
| eSCO = p2pFunGetSco(prGlueInfo->prAdapter, |
| eBand, |
| prAcsReqInfo->ucPrimaryCh); |
| |
| prAcsReqInfo->ucSecondCh = p2pFunGetSecCh( |
| prGlueInfo->prAdapter, |
| eBand, |
| eSCO, |
| prAcsReqInfo->ucPrimaryCh); |
| } |
| |
| switch (prAcsReqInfo->eChnlBw) { |
| case MAX_BW_20MHZ: |
| case MAX_BW_40MHZ: |
| ucVhtBw = VHT_OP_CHANNEL_WIDTH_20_40; |
| break; |
| case MAX_BW_80MHZ: |
| ucVhtBw = VHT_OP_CHANNEL_WIDTH_80; |
| break; |
| case MAX_BW_160MHZ: |
| ucVhtBw = VHT_OP_CHANNEL_WIDTH_160; |
| break; |
| case MAX_BW_80_80_MHZ: |
| ucVhtBw = VHT_OP_CHANNEL_WIDTH_80P80; |
| break; |
| default: |
| ucVhtBw = VHT_OP_CHANNEL_WIDTH_20_40; |
| break; |
| } |
| prAcsReqInfo->ucCenterFreqS1 = nicGetVhtS1( |
| prAcsReqInfo->ucPrimaryCh, |
| ucVhtBw); |
| |
| if (prAcsReqInfo->eChnlBw != VHT_OP_CHANNEL_WIDTH_80P80) |
| prAcsReqInfo->ucCenterFreqS2 = 0; |
| else |
| DBGLOG(P2P, ERROR, "Not support 80+80 bw.\n"); |
| |
| prAcsReqInfo->fgIsProcessing = FALSE; |
| kalP2pIndicateAcsResult(prGlueInfo, |
| prAcsReqInfo->ucRoleIdx, |
| prAcsReqInfo->ucPrimaryCh, |
| prAcsReqInfo->ucSecondCh, |
| prAcsReqInfo->ucCenterFreqS1, |
| prAcsReqInfo->ucCenterFreqS2, |
| prAcsReqInfo->eChnlBw); |
| } |
| |
| void p2pFunCalAcsChnScores(IN struct ADAPTER *prAdapter) |
| { |
| struct BSS_DESC *prBssDesc = NULL; |
| struct PARAM_GET_CHN_INFO *prChnLoadInfo; |
| struct LINK *prBSSDescList = NULL; |
| struct SCAN_INFO *prgScanInfo = NULL; |
| |
| if (!prAdapter) |
| return; |
| |
| prgScanInfo = &(prAdapter->rWifiVar.rScanInfo); |
| prBSSDescList = &prgScanInfo->rBSSDescList; |
| prChnLoadInfo = &prAdapter->rWifiVar.rChnLoadInfo; |
| |
| /* Clear old ACS data (APNum, Dirtiness, ...) |
| * and initialize the ch number |
| */ |
| kalMemZero(&(prAdapter->rWifiVar.rChnLoadInfo), |
| sizeof(prAdapter->rWifiVar.rChnLoadInfo)); |
| wlanInitChnLoadInfoChannelList(prAdapter); |
| |
| LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, |
| rLinkEntry, struct BSS_DESC) { |
| uint8_t ucIdx = wlanGetChannelIndex( |
| prBssDesc->ucChannelNum); |
| |
| if (ucIdx >= MAX_CHN_NUM) |
| continue; |
| prChnLoadInfo->rEachChnLoad[ucIdx].u2APNum++; |
| } |
| |
| wlanCalculateAllChannelDirtiness(prAdapter); |
| wlanSortChannel(prAdapter); |
| } |
| |
| uint8_t p2pFuncIsBufferableMMPDU(IN struct MSDU_INFO *prMgmtTxMsdu) |
| { |
| struct WLAN_MAC_HEADER *prWlanHdr = (struct WLAN_MAC_HEADER *) NULL; |
| uint16_t u2TxFrameCtrl; |
| uint8_t fgIsBufferableMMPDU; |
| |
| prWlanHdr = (struct WLAN_MAC_HEADER *) |
| ((unsigned long) prMgmtTxMsdu->prPacket + |
| MAC_TX_RESERVED_FIELD); |
| |
| if (!prWlanHdr) { |
| DBGLOG(P2P, ERROR, "prWlanHdr is NULL\n"); |
| return FALSE; |
| } |
| u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; |
| |
| switch (u2TxFrameCtrl) { |
| case MAC_FRAME_ACTION: |
| case MAC_FRAME_DISASSOC: |
| case MAC_FRAME_DEAUTH: |
| DBGLOG(P2P, TRACE, "u2TxFrameCtrl = %u\n", u2TxFrameCtrl); |
| fgIsBufferableMMPDU = TRUE; |
| break; |
| default: |
| fgIsBufferableMMPDU = FALSE; |
| break; |
| } |
| DBGLOG(P2P, TRACE, "fgIsBufferableMMPDU = %u\n", fgIsBufferableMMPDU); |
| return fgIsBufferableMMPDU; |
| } |