/* ** Id: tdls.c#1 */ /*! \file tdls.c \brief This file includes IEEE802.11z TDLS support. */ /* ** Log: tdls.c * * 11 13 2013 vend_samp.lin * NULL * Initial version. */ /******************************************************************************* * C O M P I L E R F L A G S ******************************************************************************** */ /******************************************************************************* * E X T E R N A L R E F E R E N C E S ******************************************************************************** */ #include "precomp.h" #if CFG_SUPPORT_TDLS #include "tdls.h" #include "gl_cfg80211.h" #include "queue.h" /******************************************************************************* * C O N S T A N T S ******************************************************************************** */ /* The list of valid data rates. */ /* The list of valid data rates. */ /******************************************************************************* * F U N C T I O N D E C L A R A T I O N S ******************************************************************************** */ /******************************************************************************* * P R I V A T E D A T A ******************************************************************************** */ static BOOLEAN fgIsPtiTimeoutSkip = FALSE; /******************************************************************************* * P R I V A T E F U N C T I O N S ******************************************************************************** */ #define ELEM_ID_LINK_IDENTIFIER_LENGTH 16 #define TDLS_KEY_TIMEOUT_INTERVAL 43200 #define UNREACH_ABLE 25 #define TDLS_REASON_CODE_UNREACHABLE 25 #define TDLS_REASON_CODE_UNSPECIFIED 26 #define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25 #define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26 UINT_8 g_arTdlsLink[MAXNUM_TDLS_PEER] = { 0, 0, 0, 0 }; /*----------------------------------------------------------------------------*/ /*! * \brief This routine is called to hadel TDLS link oper from nl80211. * * \param[in] pvAdapter Pointer to the Adapter structure. * \param[in] * \param[in] * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE * * \retval WLAN_STATUS_SUCCESS * \retval WLAN_STATUS_INVALID_LENGTH */ /*----------------------------------------------------------------------------*/ UINT_32 TdlsexLinkMgt(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) { /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ STA_RECORD_T *prStaRec; P_BSS_INFO_T prBssInfo; TDLS_CMD_LINK_MGT_T *prCmd; prCmd = (TDLS_CMD_LINK_MGT_T *) pvSetBuffer; prBssInfo = prAdapter->prAisBssInfo; #if 1 /* AIS only */ if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { prStaRec = prBssInfo->prStaRecOfAP; if (prStaRec == NULL) return 0; } else { return -EINVAL; } #endif prStaRec = prBssInfo->prStaRecOfAP; switch (prCmd->ucActionCode) { case TDLS_FRM_ACTION_DISCOVERY_REQ: if (prStaRec == NULL) return 0; if (TdlsDataFrameSend_DISCOVERY_REQ(prAdapter, prStaRec, prCmd->aucPeer, prCmd->ucActionCode, prCmd->ucDialogToken, prCmd->u2StatusCode, (UINT_8 *) (prCmd->aucSecBuf), prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { return -1; } break; case TDLS_FRM_ACTION_SETUP_REQ: if (prStaRec == NULL) return 0; prStaRec = cnmGetTdlsPeerByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeer); g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; if (TdlsDataFrameSend_SETUP_REQ(prAdapter, prStaRec, prCmd->aucPeer, prCmd->ucActionCode, prCmd->ucDialogToken, prCmd->u2StatusCode, (UINT_8 *) (prCmd->aucSecBuf), prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { return -1; } break; case TDLS_FRM_ACTION_SETUP_RSP: /* fix sigma bug 5.2.4.2, 5.2.4.7, we sent Status code decline, * but the sigma recogniezis it as scucess, and it will fail */ /* if(prCmd->u2StatusCode != 0) */ if (prBssInfo->fgTdlsIsProhibited) return 0; if (TdlsDataFrameSend_SETUP_RSP(prAdapter, prStaRec, prCmd->aucPeer, prCmd->ucActionCode, prCmd->ucDialogToken, prCmd->u2StatusCode, (UINT_8 *) (prCmd->aucSecBuf), prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { return -1; } break; case TDLS_FRM_ACTION_DISCOVERY_RSP: if (TdlsDataFrameSend_DISCOVERY_RSP(prAdapter, prStaRec, prCmd->aucPeer, prCmd->ucActionCode, prCmd->ucDialogToken, prCmd->u2StatusCode, (UINT_8 *) (prCmd->aucSecBuf), prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { return -1; } break; case TDLS_FRM_ACTION_CONFIRM: if (TdlsDataFrameSend_CONFIRM(prAdapter, prStaRec, prCmd->aucPeer, prCmd->ucActionCode, prCmd->ucDialogToken, prCmd->u2StatusCode, (UINT_8 *) (prCmd->aucSecBuf), prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { return -1; } break; case TDLS_FRM_ACTION_TEARDOWN: prStaRec = cnmGetTdlsPeerByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeer); if (prCmd->u2StatusCode == TDLS_REASON_CODE_UNREACHABLE) g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; if (TdlsDataFrameSend_TearDown(prAdapter, prStaRec, prCmd->aucPeer, prCmd->ucActionCode, prCmd->ucDialogToken, prCmd->u2StatusCode, (UINT_8 *) (prCmd->aucSecBuf), prCmd->u4SecBufLen) != TDLS_STATUS_SUCCESS) { return -1; } break; default: return -EINVAL; } return 0; } /*----------------------------------------------------------------------------*/ /*! * \brief This routine is called to hadel TDLS link mgt from nl80211. * * \param[in] pvAdapter Pointer to the Adapter structure. * \param[in] * \param[in] * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE * * \retval WLAN_STATUS_SUCCESS * \retval WLAN_STATUS_INVALID_LENGTH */ /*----------------------------------------------------------------------------*/ UINT_32 TdlsexLinkOper(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) { /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ UINT_16 i; STA_RECORD_T *prStaRec; TDLS_CMD_LINK_OPER_T *prCmd; prCmd = (TDLS_CMD_LINK_OPER_T *) pvSetBuffer; switch (prCmd->oper) { case TDLS_ENABLE_LINK: for (i = 0; i < MAXNUM_TDLS_PEER; i++) { if (!g_arTdlsLink[i]) { g_arTdlsLink[i] = 1; prStaRec = cnmGetTdlsPeerByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac); prStaRec->ucTdlsIndex = i; break; } } break; case TDLS_DISABLE_LINK: prStaRec = cnmGetTdlsPeerByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prCmd->aucPeerMac); g_arTdlsLink[prStaRec->ucTdlsIndex] = 0; if (IS_DLS_STA(prStaRec)) cnmStaRecFree(prAdapter, prStaRec); break; default: return 0; } return 0; } /*----------------------------------------------------------------------------*/ /*! * \brief This routine is called to append general IEs. * * \param[in] pvAdapter Pointer to the Adapter structure. * \param[in] * * \retval append length */ /*----------------------------------------------------------------------------*/ UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPkt) { GLUE_INFO_T *prGlueInfo; BSS_INFO_T *prBssInfo; PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; UINT_32 u4NonHTPhyType; UINT_16 u2SupportedRateSet; UINT_8 aucAllSupportedRates[RATE_NUM_SW] = { 0 }; /* 6628 RATE_NUM -> 6630 RATE_NUM_SW */ UINT_8 ucAllSupportedRatesLen; UINT_8 ucSupRatesLen; UINT_8 ucExtSupRatesLen; UINT_32 u4PktLen, u4IeLen; /* init */ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; u4PktLen = 0; /* 3. Frame Formation - (5) Supported Rates element */ /* use all sup rate we can support */ u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; rateGetDataRatesFromRateSet(u2SupportedRateSet, 0, aucAllSupportedRates, &ucAllSupportedRatesLen); ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; if (ucSupRatesLen) { SUP_RATES_IE(pPkt)->ucId = ELEM_ID_SUP_RATES; SUP_RATES_IE(pPkt)->ucLength = ucSupRatesLen; kalMemCopy(SUP_RATES_IE(pPkt)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } /* 3. Frame Formation - (7) Extended sup rates element */ if (ucExtSupRatesLen) { EXT_SUP_RATES_IE(pPkt)->ucId = ELEM_ID_EXTENDED_SUP_RATES; EXT_SUP_RATES_IE(pPkt)->ucLength = ucExtSupRatesLen; kalMemCopy(EXT_SUP_RATES_IE(pPkt)->aucExtSupportedRates, &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } /* 3. Frame Formation - (8) Supported channels element */ SUPPORTED_CHANNELS_IE(pPkt)->ucId = ELEM_ID_SUP_CHS; SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 2; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[0] = 1; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[1] = 13; if (prAdapter->fgEnable5GBand == TRUE) { SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 10; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[2] = 36; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[3] = 4; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[4] = 52; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[5] = 4; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[6] = 149; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[7] = 4; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[8] = 165; SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[9] = 1; } u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; return u4PktLen; } /******************************************************************************* * P U B L I C F U N C T I O N S ******************************************************************************** */ /*! * \brief This routine is called to transmit a TDLS data frame. * * \param[in] pvAdapter Pointer to the Adapter structure. * \param[in] * \param[in] * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE * * \retval WLAN_STATUS_SUCCESS * \retval WLAN_STATUS_INVALID_LENGTH */ /*----------------------------------------------------------------------------*/ WLAN_STATUS TdlsDataFrameSend_TearDown(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPeerMac, UINT_8 ucActionCode, UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) { GLUE_INFO_T *prGlueInfo; BSS_INFO_T *prBssInfo; PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; struct sk_buff *prMsduInfo; UINT_8 *pPkt; UINT_32 u4PktLen, u4IeLen; UINT_16 ReasonCode; /* allocate/init packet */ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; u4PktLen = 0; prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); if (prMsduInfo == NULL) return TDLS_STATUS_RESOURCES; prMsduInfo->dev = prGlueInfo->prDevHandler; if (prMsduInfo->dev == NULL) { kalPacketFree(prGlueInfo, prMsduInfo); return TDLS_STATUS_FAIL; } /* make up frame content */ /* 1. 802.3 header */ kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); pPkt += 2; u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; /* 2. payload type */ *pPkt = TDLS_FRM_PAYLOAD_TYPE; pPkt++; u4PktLen++; /* 3. Frame Formation - (1) Category */ *pPkt = TDLS_FRM_CATEGORY; pPkt++; u4PktLen++; /* 3. Frame Formation - (2) Action */ *pPkt = ucActionCode; pPkt++; u4PktLen++; /* 3. Frame Formation - status code */ ReasonCode = u2StatusCode; kalMemCopy(pPkt, &ReasonCode, 2); pPkt = pPkt + 2; u4PktLen = u4PktLen + 2; if (pAppendIe != NULL) { if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && (prStaRec != NULL))) { kalMemCopy(pPkt, pAppendIe, AppendIeLen); LR_TDLS_FME_FIELD_FILL(AppendIeLen); } } /* 7. Append Supported Operating Classes IE */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } /* 3. Frame Formation - (16) Link identifier element */ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pPeerMac, 6); u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* 5. Update packet length */ prMsduInfo->len = u4PktLen; /* if(u2StatusCode == UNREACH_ABLE ){ */ /* g_arTdlsLink[prStaRec->ucTdlsIndex] = FALSE; */ /* } */ /* 5. send the data frame */ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); return TDLS_STATUS_SUCCESS; } /*! * \brief This routine is called to transmit a TDLS data frame. * * \param[in] pvAdapter Pointer to the Adapter structure. * \param[in] * \param[in] * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE * * \retval WLAN_STATUS_SUCCESS * \retval WLAN_STATUS_INVALID_LENGTH */ /*----------------------------------------------------------------------------*/ WLAN_STATUS /* TDLS_STATUS */ TdlsDataFrameSend_SETUP_REQ(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPeerMac, UINT_8 ucActionCode, UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) { GLUE_INFO_T *prGlueInfo; BSS_INFO_T *prBssInfo; PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; struct sk_buff *prMsduInfo; UINT_8 *pPkt; UINT_32 u4PktLen, u4IeLen; BOOLEAN fg40mAllowed; UINT_16 u2CapInfo; /* allocate/init packet */ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; u4PktLen = 0; prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); if (prMsduInfo == NULL) return TDLS_STATUS_RESOURCES; prMsduInfo->dev = prGlueInfo->prDevHandler; if (prMsduInfo->dev == NULL) { kalPacketFree(prGlueInfo, prMsduInfo); return TDLS_STATUS_FAIL; } /* make up frame content */ /* 1. 802.3 header */ kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); pPkt += 2; u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; /* 2. payload type */ *pPkt = TDLS_FRM_PAYLOAD_TYPE; pPkt++; u4PktLen++; /* 3. Frame Formation - (1) Category */ *pPkt = TDLS_FRM_CATEGORY; pPkt++; u4PktLen++; /* 3. Frame Formation - (2) Action */ *pPkt = ucActionCode; pPkt++; u4PktLen++; /* 3. Frame Formation - (3) Dialog token */ *pPkt = ucDialogToken; pPkt++; u4PktLen++; /* 3. Frame Formation - (4) Capability */ u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); WLAN_SET_FIELD_16(pPkt, u2CapInfo); pPkt = pPkt + 2; u4PktLen = u4PktLen + 2; /* 4. Append general IEs */ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* 4. Append extra IEs */ kalMemCopy(pPkt, pAppendIe, AppendIeLen); pPkt += AppendIeLen; u4PktLen += AppendIeLen; /* 3. Frame Formation - (10) Extended capabilities element */ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; EXT_CAP_IE(pPkt)->ucLength = 5; /* 0320 !! */ EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0xFF; /* bit32 ~ bit39 */ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); /* EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; *//* bit24 ~ bit31 */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* HT capability IE append 0122 */ HT_CAP_IE(pPkt)->ucId = ELEM_ID_HT_CAP; HT_CAP_IE(pPkt)->ucLength = 26; /* 3. Frame Formation - (14) HT capabilities element */ if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N)) { /* TODO: prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode */ if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) fg40mAllowed = TRUE; else fg40mAllowed = FALSE; /* Add HT IE *//* try to reuse p2p path */ u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* 0320 !! check newest driver !!! */ } /* check */ /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; /* IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; */ TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* bit0 = 1: The Information Request field is used to indicate that a transmitting STA is requesting the recipient to transmit a 20/40 BSS Coexistence Management frame with the transmitting STA as the recipient. bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP that receives this information or reports of this information from operating a 20/40 MHz BSS. bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit a receiving AP from operating its BSS as a 20/40 MHz BSS. */ BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; LR_TDLS_FME_FIELD_FILL(3); } if (pAppendIe != NULL) { kalMemCopy(pPkt, pAppendIe, AppendIeLen); LR_TDLS_FME_FIELD_FILL(AppendIeLen); } /* 7. Append Supported Operating Classes IE */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } /* 3. Frame Formation - (16) Link identifier element */ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pPeerMac, 6); u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* 3. Frame Formation - (17) WMM Information element */ /* HT WMM IE append */ if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { /* Add WMM IE *//* try to reuse p2p path */ u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } #if CFG_SUPPORT_802_11AC if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { /* Add VHT IE *//* try to reuse p2p path */ u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } #endif /* 5. Update packet length */ prMsduInfo->len = u4PktLen; DBGLOG(TDLS, INFO, "\n\n\n wlanHardStartXmit\n\n\n"); /* 5. send the data frame */ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); /* wlanTx ??? */ return TDLS_STATUS_SUCCESS; } WLAN_STATUS TdlsDataFrameSend_SETUP_RSP(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPeerMac, UINT_8 ucActionCode, UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) { GLUE_INFO_T *prGlueInfo; BSS_INFO_T *prBssInfo; PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; struct sk_buff *prMsduInfo; UINT_8 *pPkt; UINT_32 u4PktLen, u4IeLen; UINT_16 u2CapInfo; UINT_16 StatusCode; BOOLEAN fg40mAllowed; /* allocate/init packet */ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; u4PktLen = 0; prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); if (prMsduInfo == NULL) return TDLS_STATUS_RESOURCES; prMsduInfo->dev = prGlueInfo->prDevHandler; if (prMsduInfo->dev == NULL) { kalPacketFree(prGlueInfo, prMsduInfo); return TDLS_STATUS_FAIL; } /* make up frame content */ /* 1. 802.3 header */ kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); pPkt += 2; u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; /* 2. payload type */ *pPkt = TDLS_FRM_PAYLOAD_TYPE; pPkt++; u4PktLen++; /* 3. Frame Formation - (1) Category */ *pPkt = TDLS_FRM_CATEGORY; pPkt++; u4PktLen++; /* 3. Frame Formation - (2) Action */ *pPkt = ucActionCode; pPkt++; u4PktLen++; /* 3. Frame Formation - status code */ StatusCode = u2StatusCode; kalMemCopy(pPkt, &StatusCode, 2); pPkt = pPkt + 2; u4PktLen = u4PktLen + 2; /* 3. Frame Formation - (3) Dialog token */ *pPkt = ucDialogToken; pPkt++; u4PktLen++; /* 3. Frame Formation - (4) Capability */ u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); WLAN_SET_FIELD_16(pPkt, u2CapInfo); pPkt = pPkt + 2; u4PktLen = u4PktLen + 2; /* 4. Append general IEs */ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* 4. Append extra IEs */ kalMemCopy(pPkt, pAppendIe, AppendIeLen); pPkt += AppendIeLen; u4PktLen += AppendIeLen; /* 3. Frame Formation - (10) Extended capabilities element */ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; EXT_CAP_IE(pPkt)->ucLength = 5; EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0xFF; /* bit32 ~ bit39 */ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); /* EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; *//* bit24 ~ bit31 */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* HT capability IE append */ HT_CAP_IE(pPkt)->ucId = ELEM_ID_HT_CAP; HT_CAP_IE(pPkt)->ucLength = 26; /* 3. Frame Formation - (14) HT capabilities element */ if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N)) { /* TODO: prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode */ if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucBssIndex)) fg40mAllowed = TRUE; else fg40mAllowed = FALSE; /* Add HT IE *//* try to reuse p2p path */ u4IeLen = rlmFillHtCapIEByAdapter(prAdapter, prBssInfo, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; /* IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; */ TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* bit0 = 1: The Information Request field is used to indicate that a transmitting STA is requesting the recipient to transmit a 20/40 BSS Coexistence Management frame with the transmitting STA as the recipient. bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP that receives this information or reports of this information from operating a 20/40 MHz BSS. bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit a receiving AP from operating its BSS as a 20/40 MHz BSS. */ BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; LR_TDLS_FME_FIELD_FILL(3); } if (pAppendIe != NULL) { kalMemCopy(pPkt, pAppendIe, AppendIeLen); LR_TDLS_FME_FIELD_FILL(AppendIeLen); } /* 7. Append Supported Operating Classes IE */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } /* 3. Frame Formation - (16) Link identifier element */ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pPeerMac, 6); /* prAdapter->rMyMacAddr */ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); /* pPeerMac */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* HT WMM IE append */ /* HT WMM IE append */ if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { /* Add WMM IE *//* try to reuse p2p path */ u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } #if CFG_SUPPORT_802_11AC if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { /* Add VHT IE *//* try to reuse p2p path */ u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } #endif /* 5. Update packet length */ prMsduInfo->len = u4PktLen; /* 5. send the data frame */ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); return TDLS_STATUS_SUCCESS; } WLAN_STATUS TdlsDataFrameSend_CONFIRM(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPeerMac, UINT_8 ucActionCode, UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) { GLUE_INFO_T *prGlueInfo; BSS_INFO_T *prBssInfo; PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; struct sk_buff *prMsduInfo; UINT_8 *pPkt; UINT_32 u4PktLen, u4IeLen; UINT_16 StatusCode; /* allocate/init packet */ prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; u4PktLen = 0; prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); if (prMsduInfo == NULL) return TDLS_STATUS_RESOURCES; prMsduInfo->dev = prGlueInfo->prDevHandler; if (prMsduInfo->dev == NULL) { kalPacketFree(prGlueInfo, prMsduInfo); return TDLS_STATUS_FAIL; } /* make up frame content */ /* 1. 802.3 header */ kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); pPkt += TDLS_FME_MAC_ADDR_LEN; *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); pPkt += 2; u4PktLen += TDLS_FME_MAC_ADDR_LEN * 2 + 2; /* 2. payload type */ *pPkt = TDLS_FRM_PAYLOAD_TYPE; pPkt++; u4PktLen++; /* 3. Frame Formation - (1) Category */ *pPkt = TDLS_FRM_CATEGORY; pPkt++; u4PktLen++; /* 3. Frame Formation - (2) Action */ *pPkt = ucActionCode; pPkt++; u4PktLen++; /* 3. Frame Formation - status code */ StatusCode = u2StatusCode; /* 0; //u2StatusCode; //ahiu 0224 */ kalMemCopy(pPkt, &StatusCode, 2); pPkt = pPkt + 2; u4PktLen = u4PktLen + 2; /* 3. Frame Formation - (3) Dialog token */ *pPkt = ucDialogToken; pPkt++; u4PktLen++; /* 4. Append extra IEs */ kalMemCopy(pPkt, pAppendIe, AppendIeLen); pPkt += AppendIeLen; u4PktLen += AppendIeLen; /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* bit0 = 1: The Information Request field is used to indicate that a transmitting STA is requesting the recipient to transmit a 20/40 BSS Coexistence Management frame with the transmitting STA as the recipient. bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP that receives this information or reports of this information from operating a 20/40 MHz BSS. bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit a receiving AP from operating its BSS as a 20/40 MHz BSS. */ BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; LR_TDLS_FME_FIELD_FILL(3); } if (pAppendIe != NULL) { if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && (prStaRec != NULL))) { kalMemCopy(pPkt, pAppendIe, AppendIeLen); LR_TDLS_FME_FIELD_FILL(AppendIeLen); } } /* 7. Append Supported Operating Classes IE */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } /* 3. Frame Formation - (16) Link identifier element */ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pPeerMac, 6); u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* HT WMM IE append */ if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { /* Add WMM IE *//* try to reuse p2p path */ u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } /* 5. Update packet length */ prMsduInfo->len = u4PktLen; /* 5. send the data frame */ wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); return TDLS_STATUS_SUCCESS; } /* * \brief This routine is called to transmit a TDLS data frame. * * \param[in] pvAdapter Pointer to the Adapter structure. * \param[in] * \param[in] * \param[in] buf includes RSN IE + FT IE + Lifetimeout IE * * \retval WLAN_STATUS_SUCCESS * \retval WLAN_STATUS_INVALID_LENGTH */ /*----------------------------------------------------------------------------*/ WLAN_STATUS /* TDLS_STATUS */ TdlsDataFrameSend_DISCOVERY_REQ(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPeerMac, UINT_8 ucActionCode, UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) { GLUE_INFO_T *prGlueInfo; BSS_INFO_T *prBssInfo; PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; struct sk_buff *prMsduInfo; MSDU_INFO_T *prMsduInfoMgmt; UINT_8 *pPkt, *pucInitiator, *pucResponder; UINT_32 u4PktLen, u4IeLen; UINT_16 u2CapInfo; prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; if (prStaRec != NULL) prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ else return TDLS_STATUS_FAIL; /* allocate/init packet */ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; u4PktLen = 0; prMsduInfo = NULL; prMsduInfoMgmt = NULL; /* make up frame content */ if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RSP) { /* TODO: reduce 1600 to correct size */ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); if (prMsduInfo == NULL) return TDLS_STATUS_RESOURCES; prMsduInfo->dev = prGlueInfo->prDevHandler; if (prMsduInfo->dev == NULL) { kalPacketFree(prGlueInfo, prMsduInfo); return TDLS_STATUS_FAIL; } /* 1. 802.3 header */ kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); LR_TDLS_FME_FIELD_FILL(2); /* 2. payload type */ *pPkt = TDLS_FRM_PAYLOAD_TYPE; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - (1) Category */ *pPkt = TDLS_FRM_CATEGORY; LR_TDLS_FME_FIELD_FILL(1); } else { WLAN_MAC_HEADER_T *prHdr; prMsduInfoMgmt = (MSDU_INFO_T *) cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); if (prMsduInfoMgmt == NULL) return TDLS_STATUS_RESOURCES; pPkt = (UINT_8 *) prMsduInfoMgmt->prPacket; prHdr = (WLAN_MAC_HEADER_T *) pPkt; /* 1. 802.11 header */ prHdr->u2FrameCtrl = MAC_FRAME_ACTION; prHdr->u2DurationID = 0; kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); prHdr->u2SeqCtrl = 0; LR_TDLS_FME_FIELD_FILL(sizeof(WLAN_MAC_HEADER_T)); /* Frame Formation - (1) Category */ *pPkt = CATEGORY_PUBLIC_ACTION; LR_TDLS_FME_FIELD_FILL(1); } /* 3. Frame Formation - (2) Action */ *pPkt = ucActionCode; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - Status Code */ switch (ucActionCode) { case TDLS_FRM_ACTION_SETUP_RSP: case TDLS_FRM_ACTION_CONFIRM: case TDLS_FRM_ACTION_TEARDOWN: WLAN_SET_FIELD_16(pPkt, u2StatusCode); LR_TDLS_FME_FIELD_FILL(2); break; } /* 3. Frame Formation - (3) Dialog token */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { *pPkt = ucDialogToken; LR_TDLS_FME_FIELD_FILL(1); } /* Fill elements */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* Capability Support Rates Extended Support Rates Supported Channels HT Capabilities WMM Information Element Extended Capabilities Link Identifier RSNIE FTIE Timeout Interval */ if (ucActionCode != TDLS_FRM_ACTION_CONFIRM) { /* 3. Frame Formation - (4) Capability: 0x31 0x04, privacy bit will be set */ u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); WLAN_SET_FIELD_16(pPkt, u2CapInfo); LR_TDLS_FME_FIELD_FILL(2); /* 4. Append general IEs */ /* TODO check HT: prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode must be CONFIG_BW_20_40M. TODO check HT: HT_CAP_INFO_40M_INTOLERANT must be clear if Tdls 20/40 is enabled. */ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); /* 5. Frame Formation - Extended capabilities element */ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; EXT_CAP_IE(pPkt)->ucLength = 5; EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ /* if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) */ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); /* if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) */ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); /* if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) */ EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); u4IeLen = IE_SIZE(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } else { /* 5. Frame Formation - WMM Information element */ if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { /* Add WMM IE *//* try to reuse p2p path */ u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } } } /* 6. Frame Formation - 20/40 BSS Coexistence */ /* Follow WiFi test plan, add 20/40 element to request/response/confirm. */ #if 0 if (prGlueInfo->fgTdlsIs2040Supported == TRUE) { /* bit0 = 1: The Information Request field is used to indicate that a transmitting STA is requesting the recipient to transmit a 20/40 BSS Coexistence Management frame with the transmitting STA as the recipient. bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP that receives this information or reports of this information from operating a 20/40 MHz BSS. bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit a receiving AP from operating its BSS as a 20/40 MHz BSS. */ BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; LR_TDLS_FME_FIELD_FILL(3); } #endif /* 6. Frame Formation - HT Operation element */ /* u4IeLen = rlmFillHtOpIeBody(prBssInfo, pPkt); */ /* LR_TDLS_FME_FIELD_FILL(u4IeLen); */ /* 7. Frame Formation - Link identifier element */ /* Note: Link ID sequence must be correct; Or the calculated MIC will be error */ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); switch (ucActionCode) { case TDLS_FRM_ACTION_SETUP_REQ: case TDLS_FRM_ACTION_CONFIRM: case TDLS_FRM_ACTION_DISCOVERY_RSP: default: /* we are initiator */ pucInitiator = prBssInfo->aucOwnMacAddr; pucResponder = pPeerMac; if (prStaRec != NULL) prStaRec->flgTdlsIsInitiator = TRUE; break; case TDLS_FRM_ACTION_SETUP_RSP: /* peer is initiator */ pucInitiator = pPeerMac; pucResponder = prBssInfo->aucOwnMacAddr; if (prStaRec != NULL) prStaRec->flgTdlsIsInitiator = FALSE; break; case TDLS_FRM_ACTION_TEARDOWN: if (prStaRec != NULL) { if (prStaRec->flgTdlsIsInitiator == TRUE) { /* we are initiator */ pucInitiator = prBssInfo->aucOwnMacAddr; pucResponder = pPeerMac; } else { /* peer is initiator */ pucInitiator = pPeerMac; pucResponder = prBssInfo->aucOwnMacAddr; } } else { /* peer is initiator */ pucInitiator = pPeerMac; pucResponder = prBssInfo->aucOwnMacAddr; } break; } kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pucInitiator, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pucResponder, 6); u4IeLen = IE_SIZE(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); /* 8. Append security IEs */ if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) && (pAppendIe != NULL)) { kalMemCopy(pPkt, pAppendIe, AppendIeLen); LR_TDLS_FME_FIELD_FILL(AppendIeLen); } /* 10. send the data or management frame */ if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RSP) { /* 9. Update packet length */ prMsduInfo->len = u4PktLen; wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); } else { prMsduInfoMgmt->ucPacketType = TX_PACKET_TYPE_MGMT; prMsduInfoMgmt->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; prMsduInfoMgmt->ucBssIndex = prBssInfo->ucBssIndex; prMsduInfoMgmt->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; prMsduInfoMgmt->fgIs802_1x = FALSE; prMsduInfoMgmt->fgIs802_11 = TRUE; prMsduInfoMgmt->u2FrameLength = u4PktLen; prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); prMsduInfoMgmt->pfTxDoneHandler = NULL; /* Send them to HW queue */ nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); } return TDLS_STATUS_SUCCESS; } WLAN_STATUS TdlsDataFrameSend_DISCOVERY_RSP(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_8 *pPeerMac, UINT_8 ucActionCode, UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) { GLUE_INFO_T *prGlueInfo; BSS_INFO_T *prBssInfo; PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; struct sk_buff *prMsduInfo; MSDU_INFO_T *prMsduInfoMgmt; UINT_8 *pPkt, *pucInitiator, *pucResponder; UINT_32 u4PktLen, u4IeLen; UINT_16 u2CapInfo; prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; /* sanity check */ if (prStaRec != NULL) prBssInfo = prAdapter->prAisBssInfo; /* AIS only */ else return TDLS_STATUS_FAIL; /* allocate/init packet */ prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; u4PktLen = 0; prMsduInfo = NULL; prMsduInfoMgmt = NULL; /* make up frame content */ if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RSP) { /* TODO: reduce 1600 to correct size */ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); if (prMsduInfo == NULL) return TDLS_STATUS_RESOURCES; prMsduInfo->dev = prGlueInfo->prDevHandler; if (prMsduInfo->dev == NULL) { kalPacketFree(prGlueInfo, prMsduInfo); return TDLS_STATUS_FAIL; } /* 1. 802.3 header */ kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); LR_TDLS_FME_FIELD_FILL(2); /* 2. payload type */ *pPkt = TDLS_FRM_PAYLOAD_TYPE; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - (1) Category */ *pPkt = TDLS_FRM_CATEGORY; LR_TDLS_FME_FIELD_FILL(1); } else { WLAN_MAC_HEADER_T *prHdr; prMsduInfoMgmt = (MSDU_INFO_T *) cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); if (prMsduInfoMgmt == NULL) return TDLS_STATUS_RESOURCES; pPkt = (UINT_8 *) prMsduInfoMgmt->prPacket; prHdr = (WLAN_MAC_HEADER_T *) pPkt; /* 1. 802.11 header */ prHdr->u2FrameCtrl = MAC_FRAME_ACTION; prHdr->u2DurationID = 0; kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); prHdr->u2SeqCtrl = 0; LR_TDLS_FME_FIELD_FILL(sizeof(WLAN_MAC_HEADER_T)); /* Frame Formation - (1) Category */ *pPkt = CATEGORY_PUBLIC_ACTION; LR_TDLS_FME_FIELD_FILL(1); } /* 3. Frame Formation - (2) Action */ *pPkt = ucActionCode; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - Status Code */ switch (ucActionCode) { case TDLS_FRM_ACTION_SETUP_RSP: case TDLS_FRM_ACTION_CONFIRM: case TDLS_FRM_ACTION_TEARDOWN: WLAN_SET_FIELD_16(pPkt, u2StatusCode); LR_TDLS_FME_FIELD_FILL(2); break; } /* 3. Frame Formation - (3) Dialog token */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { *pPkt = ucDialogToken; LR_TDLS_FME_FIELD_FILL(1); } /* Fill elements */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* Capability Support Rates Extended Support Rates Supported Channels HT Capabilities WMM Information Element Extended Capabilities Link Identifier RSNIE FTIE Timeout Interval */ if (ucActionCode != TDLS_FRM_ACTION_CONFIRM) { /* 3. Frame Formation - (4) Capability: 0x31 0x04, privacy bit will be set */ u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); WLAN_SET_FIELD_16(pPkt, u2CapInfo); LR_TDLS_FME_FIELD_FILL(2); /* 4. Append general IEs */ /* TODO check HT: prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode must be CONFIG_BW_20_40M. TODO check HT: HT_CAP_INFO_40M_INTOLERANT must be clear if Tdls 20/40 is enabled. */ u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); /* 5. Frame Formation - Extended capabilities element */ EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; EXT_CAP_IE(pPkt)->ucLength = 5; EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ /* if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) */ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); /* if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) */ EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); /* if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) */ EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); u4IeLen = IE_SIZE(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } else { /* 5. Frame Formation - WMM Information element */ if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { /* Add WMM IE *//* try to reuse p2p path */ u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } } } /* 6. Frame Formation - 20/40 BSS Coexistence */ /* Follow WiFi test plan, add 20/40 element to request/response/confirm. */ #if 0 if (prGlueInfo->fgTdlsIs2040Supported == TRUE) { /* bit0 = 1: The Information Request field is used to indicate that a transmitting STA is requesting the recipient to transmit a 20/40 BSS Coexistence Management frame with the transmitting STA as the recipient. bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP that receives this information or reports of this information from operating a 20/40 MHz BSS. bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit a receiving AP from operating its BSS as a 20/40 MHz BSS. */ BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; LR_TDLS_FME_FIELD_FILL(3); } #endif /* 6. Frame Formation - HT Operation element */ /* u4IeLen = rlmFillHtOpIeBody(prBssInfo, pPkt); */ /* LR_TDLS_FME_FIELD_FILL(u4IeLen); */ /* 7. Frame Formation - Link identifier element */ /* Note: Link ID sequence must be correct; Or the calculated MIC will be error */ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); switch (ucActionCode) { case TDLS_FRM_ACTION_SETUP_REQ: case TDLS_FRM_ACTION_CONFIRM: default: /* we are initiator */ pucInitiator = prBssInfo->aucOwnMacAddr; pucResponder = pPeerMac; if (prStaRec != NULL) prStaRec->flgTdlsIsInitiator = TRUE; break; case TDLS_FRM_ACTION_DISCOVERY_RSP: case TDLS_FRM_ACTION_SETUP_RSP: /* peer is initiator */ pucInitiator = pPeerMac; pucResponder = prBssInfo->aucOwnMacAddr; if (prStaRec != NULL) prStaRec->flgTdlsIsInitiator = FALSE; break; case TDLS_FRM_ACTION_TEARDOWN: if (prStaRec != NULL) { if (prStaRec->flgTdlsIsInitiator == TRUE) { /* we are initiator */ pucInitiator = prBssInfo->aucOwnMacAddr; pucResponder = pPeerMac; } else { /* peer is initiator */ pucInitiator = pPeerMac; pucResponder = prBssInfo->aucOwnMacAddr; } } else { /* peer is initiator */ pucInitiator = pPeerMac; pucResponder = prBssInfo->aucOwnMacAddr; } break; } /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; TIMEOUT_INTERVAL_IE(pPkt)->ucType = 2; /* IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; */ TIMEOUT_INTERVAL_IE(pPkt)->u4Value = TDLS_KEY_TIMEOUT_INTERVAL; /* htonl(prCmd->u4Timeout); */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* bit0 = 1: The Information Request field is used to indicate that a transmitting STA is requesting the recipient to transmit a 20/40 BSS Coexistence Management frame with the transmitting STA as the recipient. bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP that receives this information or reports of this information from operating a 20/40 MHz BSS. bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit a receiving AP from operating its BSS as a 20/40 MHz BSS. */ BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; LR_TDLS_FME_FIELD_FILL(3); } if (pAppendIe != NULL) { kalMemCopy(pPkt, pAppendIe, AppendIeLen); LR_TDLS_FME_FIELD_FILL(AppendIeLen); } /* 7. Append Supported Operating Classes IE */ if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } /* 3. Frame Formation - (16) Link identifier element */ TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pPeerMac, 6); /* prAdapter->rMyMacAddr */ kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); /* pPeerMac */ u4IeLen = IE_SIZE(pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; /* HT WMM IE append */ /* HT WMM IE append */ if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { /* Add WMM IE *//* try to reuse p2p path */ u4IeLen = mqmGenerateWmmInfoIEByStaRec(prAdapter, prBssInfo, prStaRec, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } if (IS_FEATURE_ENABLED(prAdapter->rWifiVar.ucQoS)) { u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt); LR_TDLS_FME_FIELD_FILL(u4IeLen); } #if CFG_SUPPORT_802_11AC if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AC) { /* Add VHT IE *//* try to reuse p2p path */ u4IeLen = rlmFillVhtCapIEByAdapter(prAdapter, prBssInfo, pPkt); pPkt += u4IeLen; u4PktLen += u4IeLen; } #endif /* 8. Append security IEs */ if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) && (pAppendIe != NULL)) { kalMemCopy(pPkt, pAppendIe, AppendIeLen); LR_TDLS_FME_FIELD_FILL(AppendIeLen); } prMsduInfoMgmt->ucPacketType = TX_PACKET_TYPE_MGMT; prMsduInfoMgmt->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; prMsduInfoMgmt->ucBssIndex = prBssInfo->ucBssIndex; prMsduInfoMgmt->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; prMsduInfoMgmt->fgIs802_1x = FALSE; prMsduInfoMgmt->fgIs802_11 = TRUE; prMsduInfoMgmt->u2FrameLength = u4PktLen; prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); prMsduInfoMgmt->pfTxDoneHandler = NULL; /* Send them to HW queue */ nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); return TDLS_STATUS_SUCCESS; } /*----------------------------------------------------------------------------*/ /*! \brief This routine is called to send a command to TDLS module. * * \param[in] prGlueInfo Pointer to the Adapter structure * \param[in] prInBuf A pointer to the command string buffer * \param[in] u4InBufLen The length of the buffer * \param[out] None * * \retval None */ /*----------------------------------------------------------------------------*/ VOID TdlsexEventHandle(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) { UINT_32 u4EventId; DBGLOG(TDLS, INFO, "TdlsexEventHandle\n"); /* sanity check */ if ((prGlueInfo == NULL) || (prInBuf == NULL)) return; /* shall not be here */ /* handle */ u4EventId = *(UINT_32 *) prInBuf; u4InBufLen -= 4; switch (u4EventId) { case TDLS_HOST_EVENT_TEAR_DOWN: DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TEAR_DOWN\n"); TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen); break; case TDLS_HOST_EVENT_TX_DONE: break; } } /*----------------------------------------------------------------------------*/ /*! \brief This routine is called to do tear down. * * \param[in] prGlueInfo Pointer to the Adapter structure * \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId * \param[in] u4InBufLen The length of the buffer * \param[out] None * * \retval None * */ /*----------------------------------------------------------------------------*/ VOID TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) { STA_RECORD_T *prStaRec; UINT_16 u2ReasonCode = 0; UINT_32 u4TearDownSubId; UINT_8 *pMac, aucZeroMac[6]; /* init */ u4TearDownSubId = *(UINT_32 *) prInBuf; kalMemZero(aucZeroMac, sizeof(aucZeroMac)); pMac = aucZeroMac; prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *(prInBuf + 4)); if (prStaRec != NULL) pMac = prStaRec->aucMacAddr; /* handle */ /* sanity check */ if (prStaRec == NULL) return; if (fgIsPtiTimeoutSkip == TRUE) { /* skip PTI timeout event */ if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) return; } if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TD_PTI_TIMEOUT TDLS_REASON_CODE_UNSPECIFIED\n"); u2ReasonCode = TDLS_REASON_CODE_UNSPECIFIED; cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, GFP_ATOMIC); } if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) { DBGLOG(TDLS, INFO, "TDLS_HOST_EVENT_TD_AGE_TIMEOUT TDLS_REASON_CODE_UNREACHABLE\n"); u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE; cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE, GFP_ATOMIC); } DBGLOG(TDLS, INFO, "\n\n u2ReasonCode = %u\n\n", u2ReasonCode); /* modify the value when supplicant sends tear down to us in TdlsexMgmtCtrl(), not here we want to send tear down to AP (not peer) if PTI timeout or AGE timeout. */ /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ } #if 0 /*----------------------------------------------------------------------------*/ /*! \brief This routine is called to send a TDLS event to supplicant. * * \param[in] prGlueInfo Pointer to the Adapter structure * \param[in] prInBuf A pointer to the command string buffer * \param[in] u4InBufLen The length of the buffer * \param[out] None * * \retval None * */ /*----------------------------------------------------------------------------*/ VOID tdls_oper_request(struct net_device *dev, const u8 *peer, u16 oper, u16 reason_code, gfp_t gfp) { GLUE_INFO_T *prGlueInfo; ADAPTER_T *prAdapter; struct sk_buff *prMsduInfo; UINT_8 *pPkt; UINT_32 u4PktLen; /* sanity check */ if ((dev == NULL) || (peer == NULL)) return; /* shall not be here */ /* init */ prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); prAdapter = prGlueInfo->prAdapter; u4PktLen = 0; /* allocate/init packet */ prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); if (prMsduInfo == NULL) return; prMsduInfo->dev = dev; /* make up frame content */ /* 1. 802.3 header */ kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); kalMemCopy(pPkt, peer, TDLS_FME_MAC_ADDR_LEN); LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); LR_TDLS_FME_FIELD_FILL(2); /* 2. payload type */ *pPkt = TDLS_FRM_PAYLOAD_TYPE; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - (1) Category */ *pPkt = TDLS_FRM_CATEGORY; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - (2) Action */ *pPkt = TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - (3) Operation */ *pPkt = oper; LR_TDLS_FME_FIELD_FILL(1); /* 3. Frame Formation - (4) Reason Code */ *pPkt = reason_code; *(pPkt + 1) = 0x00; LR_TDLS_FME_FIELD_FILL(2); /* 3. Frame Formation - (5) Peer MAC */ kalMemCopy(pPkt, peer, 6); LR_TDLS_FME_FIELD_FILL(6); /* 4. Update packet length */ prMsduInfo->len = u4PktLen; /* pass to OS */ TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); } /*----------------------------------------------------------------------------*/ /*! * \brief This routine is called to indicate packets to upper layer. * * \param[in] prGlueInfo Pointer to the Adapter structure * \param[in] prSkb A pointer to the received packet * * \retval None * */ /*----------------------------------------------------------------------------*/ VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb) { struct net_device *prNetDev; /* init */ prNetDev = prGlueInfo->prDevHandler; prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; prGlueInfo->rNetDevStats.rx_packets++; /* pass to upper layer */ prNetDev->last_rx = jiffies; prSkb->protocol = eth_type_trans(prSkb, prNetDev); prSkb->dev = prNetDev; if (!in_interrupt()) netif_rx_ni(prSkb); /* only in non-interrupt context */ else netif_rx(prSkb); } #endif VOID TdlsBssExtCapParse(P_STA_RECORD_T prStaRec, P_UINT_8 pucIE) { UINT_8 *pucIeExtCap; /* sanity check */ if ((prStaRec == NULL) || (pucIE == NULL)) return; if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP) return; /* from bit0 ~ bit 38: TDLS Prohibited The TDLS Prohibited subfield indicates whether the use of TDLS is prohibited. The field is set to 1 to indicate that TDLS is prohibited and to 0 to indicate that TDLS is allowed. */ if (IE_LEN(pucIE) < 5) return; /* we need 39/8 = 5 bytes */ /* init */ prStaRec->fgTdlsIsProhibited = FALSE; prStaRec->fgTdlsIsChSwProhibited = FALSE; /* parse */ pucIeExtCap = pucIE + 2; pucIeExtCap += 4; /* shift to the byte we care about */ if ((*pucIeExtCap) && BIT(38 - 32)) prStaRec->fgTdlsIsProhibited = TRUE; if ((*pucIeExtCap) && BIT(39 - 32)) prStaRec->fgTdlsIsChSwProhibited = TRUE; } /*----------------------------------------------------------------------------*/ /*! * \brief Generate CMD_ID_SET_TDLS_CH_SW command * * \param[in] * * \return none */ /*----------------------------------------------------------------------------*/ WLAN_STATUS TdlsSendChSwControlCmd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen) { CMD_TDLS_CH_SW_T rCmdTdlsChSwCtrl; ASSERT(prAdapter); /* send command packet for scan */ kalMemZero(&rCmdTdlsChSwCtrl, sizeof(CMD_TDLS_CH_SW_T)); rCmdTdlsChSwCtrl.fgIsTDLSChSwProhibit = prAdapter->prAisBssInfo->fgTdlsIsChSwProhibited; wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_TDLS_CH_SW, TRUE, FALSE, FALSE, NULL, NULL, sizeof(CMD_TDLS_CH_SW_T), (PUINT_8)&rCmdTdlsChSwCtrl, NULL, 0); return TDLS_STATUS_SUCCESS; } #endif /* CFG_SUPPORT_TDLS */ /* End of tdls.c */