wlan: TDLS Integration from Dev32Sta
Support for TDLS discovery, setup and teardown.
Exit BMPS while in active TDLS link and enable back afterwards.
Change-Id: Ic653c5369cb0b61e04e9a8be5e7f625ab7160365
CR-Fixed: 426223
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 5ef6468..bf0dc8a 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -61,6 +61,9 @@
#if defined CONFIG_CFG80211
#include "wlan_hdd_p2p.h"
#endif
+#ifdef FEATURE_WLAN_TDLS
+#include "wlan_hdd_tdls.h"
+#endif
#include "sme_Api.h"
v_BOOL_t mibIsDot11DesiredBssTypeInfrastructure( hdd_adapter_t *pAdapter );
@@ -1737,6 +1740,186 @@
return( eHAL_STATUS_SUCCESS );
}
+#ifdef FEATURE_WLAN_TDLS
+/**============================================================================
+ *
+ @brief hdd_roamRegisterTDLSSTA() - Construct the staDesc and register with
+ TL the new STA. This is called as part of ADD_STA in the TDLS setup
+ Return: VOS_STATUS
+
+ ===========================================================================*/
+static VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter,
+ tCsrRoamInfo *pRoamInfo,
+ v_U8_t tdlsEncryptionEnabled )
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+ VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
+ WLAN_STADescType staDesc = {0};
+
+ if (-1 == wlan_hdd_saveTdlsPeer(pRoamInfo)) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "wlan_hdd_saveTdlsPeer() failed");
+ }
+ /*
+ * TDLS sta in BSS should be set as STA type TDLS and STA MAC should
+ * be peer MAC, here we are wokrking on direct Link
+ */
+ staDesc.ucSTAId = pRoamInfo->staId ;
+
+ staDesc.wSTAType = WLAN_STA_TDLS ;
+
+ vos_mem_copy( staDesc.vSTAMACAddress.bytes, pRoamInfo->peerMac,
+ sizeof(tSirMacAddr) );
+
+ vos_mem_copy(staDesc.vBSSIDforIBSS.bytes, pHddStaCtx->conn_info.bssId,6 );
+ vos_copy_macaddr( &staDesc.vSelfMACAddress, &pAdapter->macAddressCurrent );
+
+ /* set the QoS field appropriately ..*/
+ (hdd_wmm_is_active(pAdapter)) ? (staDesc.ucQosEnabled = 1)
+ : (staDesc.ucQosEnabled = 0) ;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "HDD register \
+ TL QoS_enabled=%d\n", staDesc.ucQosEnabled );
+
+ staDesc.ucProtectedFrame = tdlsEncryptionEnabled;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "HDD register TL Sec_enabled= %d.\n", staDesc.ucProtectedFrame );
+
+ /*
+ * UMA is ready we inform TL to do frame translation.
+ */
+ staDesc.ucSwFrameTXXlation = 1;
+ staDesc.ucSwFrameRXXlation = 1;
+ staDesc.ucAddRmvLLC = 1;
+
+ /* Initialize signatures and state */
+ staDesc.ucUcastSig = pRoamInfo->ucastSig ;
+
+ /* tdls Direct Link do not need bcastSig */
+ staDesc.ucBcastSig = 0 ;
+
+#ifdef VOLANS_ENABLE_SW_REPLAY_CHECK
+ if(staDesc.ucProtectedFrame)
+ staDesc.ucIsReplayCheckValid = VOS_TRUE;
+ else
+ staDesc.ucIsReplayCheckValid = VOS_FALSE;
+#endif
+
+ staDesc.ucInitState = WLANTL_STA_CONNECTED ;
+
+ (WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[pRoamInfo->staId] = pAdapter;
+ /* Register the Station with TL... */
+ vosStatus = WLANTL_RegisterSTAClient( pVosContext,
+ hdd_rx_packet_cbk,
+ hdd_tx_complete_cbk,
+ hdd_tx_fetch_packet_cbk, &staDesc, 0 );
+
+ if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "WLANTL_RegisterSTAClient() failed to register. \
+ Status= %d [0x%08lX]", vosStatus, vosStatus );
+ return vosStatus;
+ }
+
+ return( vosStatus );
+}
+
+/*
+ * HDD interface between SME and TL to ensure TDLS client registration with
+ * TL in case of new TDLS client is added and deregistration at the time
+ * TDLS client is deleted.
+ */
+
+eHalStatus hdd_RoamTdlsStatusUpdateHandler(hdd_adapter_t *pAdapter,
+ tCsrRoamInfo *pRoamInfo,
+ tANI_U32 roamId,
+ eRoamCmdStatus roamStatus,
+ eCsrRoamResult roamResult)
+{
+ hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+ eHalStatus status = eHAL_STATUS_FAILURE ;
+
+ switch( roamResult )
+ {
+ case eCSR_ROAM_RESULT_ADD_TDLS_PEER:
+ {
+ tANI_U8 staIdx = 0 ;
+ /*
+ * check if there is available index for this new TDLS STA
+ * since TDLS is setup in BSS, we need to start from +1
+ */
+ for ( staIdx = 0 ;
+ staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
+ {
+ if (0 == pHddStaCtx->conn_info.staId[staIdx] )
+ {
+ pHddStaCtx->conn_info.staId[staIdx] = pRoamInfo->staId;
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("TDLS: STA IDX at %d \
+ and mac = %d: %02x,%02x, %02x, %02x, %02x, %02x\n"),
+ staIdx, pHddStaCtx->conn_info.staId[staIdx],
+ pRoamInfo->peerMac[0],
+ pRoamInfo->peerMac[1],
+ pRoamInfo->peerMac[2],
+ pRoamInfo->peerMac[3],
+ pRoamInfo->peerMac[4],
+ pRoamInfo->peerMac[5]) ;
+
+ vos_copy_macaddr(
+ &pHddStaCtx->conn_info.peerMacAddress[staIdx],
+ (v_MACADDR_t *)pRoamInfo->peerMac) ;
+ status = eHAL_STATUS_SUCCESS ;
+ break ;
+ }
+ }
+ if(eHAL_STATUS_SUCCESS == status)
+ {
+ /* start TDLS client registration with TL */
+ status = hdd_roamRegisterTDLSSTA( pAdapter, pRoamInfo, 1) ;
+ }
+ break ;
+ }
+ case eCSR_ROAM_RESULT_DELETE_TDLS_PEER:
+ {
+ tANI_U8 staIdx = 0 ;
+ status = eHAL_STATUS_FAILURE ;
+
+ for ( staIdx = 0 ;
+ staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
+ {
+ if (pRoamInfo->staId == pHddStaCtx->conn_info.staId[staIdx] )
+ {
+ pHddStaCtx->conn_info.staId[staIdx] = 0 ;
+ vos_mem_zero(&pHddStaCtx->conn_info.peerMacAddress[staIdx],
+ sizeof(v_MACADDR_t)) ;
+ status = eHAL_STATUS_SUCCESS ;
+
+ break ;
+ }
+ }
+ if(eHAL_STATUS_SUCCESS == status)
+ {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ ("HDD: del STA IDX = %x\n"), pRoamInfo->staId) ;
+ hdd_roamDeregisterSTA( pAdapter, pRoamInfo->staId );
+ (WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[pRoamInfo->staId] = NULL;
+ }
+ break ;
+ }
+ default:
+ {
+ break ;
+ }
+ }
+
+ return status ;
+}
+#endif
+
eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U32 roamId,
eRoamCmdStatus roamStatus, eCsrRoamResult roamResult )
{
@@ -1978,6 +2161,12 @@
(roamResult == eCSR_ROAM_RESULT_NONE) ? TRUE : FALSE );
break;
#endif
+#ifdef FEATURE_WLAN_TDLS
+ case eCSR_ROAM_TDLS_STATUS_UPDATE:
+ halStatus = hdd_RoamTdlsStatusUpdateHandler( pAdapter, pRoamInfo,
+ roamId, roamStatus, roamResult );
+ break ;
+#endif
default:
break;
}
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 26ed4d8..3090c2c 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -1711,6 +1711,14 @@
CFG_ENABLE_RX_STBC_DEFAULT,
CFG_ENABLE_RX_STBC_MIN,
CFG_ENABLE_RX_STBC_MAX ),
+#ifdef FEATURE_WLAN_TDLS
+REG_VARIABLE( CFG_TDLS_SUPPORT_ENABLE, WLAN_PARAM_Integer,
+ hdd_config_t, fEnableTDLSSupport,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_TDLS_SUPPORT_ENABLE_DEFAULT,
+ CFG_TDLS_SUPPORT_ENABLE_MIN,
+ CFG_TDLS_SUPPORT_ENABLE_MAX ),
+#endif
};
/*
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 0cca8f4..44d72bc 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -81,6 +81,9 @@
#include "bap_hdd_misc.h"
#endif
#include <qc_sap_ioctl.h>
+#ifdef FEATURE_WLAN_TDLS
+#include "wlan_hdd_tdls.h"
+#endif
#define g_mode_rates_size (12)
#define a_mode_rates_size (8)
@@ -466,6 +469,11 @@
| WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
| WIPHY_FLAG_OFFCHAN_TX;
#endif
+#ifdef FEATURE_WLAN_TDLS
+ wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
+ | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
+#endif
+
/* even with WIPHY_FLAG_CUSTOM_REGULATORY,
driver can still register regulatory callback and
it will get CRDA setting in wiphy->band[], but
@@ -6000,8 +6008,54 @@
static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
struct net_device *dev, u8 *mac, struct station_parameters *params)
{
- // TODO: Implement this later.
+#ifdef FEATURE_WLAN_TDLS
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+ u32 mask, set;
+ VOS_STATUS status;
ENTER();
+
+ if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid arguments");
+ return -EINVAL;
+ }
+
+ if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
+ FALSE == sme_IsFeatureSupportedByFW(TDLS))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "TDLS Disabled in INI OR not enabled in FW.\
+ Cannot process TDLS commands \n");
+ return -ENOTSUPP;
+ }
+
+ mask = params->sta_flags_mask;
+
+ set = params->sta_flags_set;
+
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
+
+ if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+ if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Add TDLS peer");
+
+
+ status = sme_AddTdlsPeerSta(WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, mac);
+
+ if (VOS_STATUS_SUCCESS != status) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_AddTdlsPeerSta failed!", __func__);
+ }
+ }
+ }
+#endif
+
return 0;
}
@@ -6150,6 +6204,139 @@
}
#endif
+#ifdef FEATURE_WLAN_TDLS
+static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, u8 action_code, u8 dialog_token,
+ u16 status_code, const u8 *buf, size_t len)
+{
+
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+ u8 *buf_1;
+ size_t len_1 = len;
+ u8 peerMac[6];
+ VOS_STATUS status;
+
+ if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid arguments");
+ return -EINVAL;
+ }
+
+ if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
+ FALSE == sme_IsFeatureSupportedByFW(TDLS))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "TDLS Disabled in INI OR not enabled in FW.\
+ Cannot process TDLS commands \n");
+ return -ENOTSUPP;
+ }
+ vos_mem_copy( peerMac, peer, 6);
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Request to send TDLS management: action = %d, status = %d, \
+ len = %d", action_code, status_code, len);
+
+ buf_1 = vos_mem_malloc(len);
+ if(buf_1 == NULL) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: malloc failed!", __func__);
+ return -ENOMEM;
+ }
+ vos_mem_copy(buf_1, buf, len);
+
+ status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
+ peerMac, action_code, dialog_token, status_code, buf_1, len_1);
+
+ if (VOS_STATUS_SUCCESS != status) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: sme_SendTdlsMgmtFrame failed!", __func__);
+ }
+
+ vos_mem_free(buf_1);
+
+ return 0;
+}
+
+static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, enum nl80211_tdls_operation oper)
+{
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *pHddCtx = wiphy_priv(wiphy);
+
+ if( NULL == pHddCtx || NULL == pHddCtx->cfg_ini )
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid arguments");
+ return -EINVAL;
+ }
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Request for TDLS oper: %d", (int)oper);
+
+ if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport ||
+ FALSE == sme_IsFeatureSupportedByFW(TDLS))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "TDLS Disabled in INI OR not enabled in FW.\
+ Cannot process TDLS commands \n");
+ return -ENOTSUPP;
+ }
+
+ switch (oper) {
+ case NL80211_TDLS_ENABLE_LINK:
+ {
+ v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
+ v_U8_t my_peer[6];
+ v_U8_t ucSTAId;
+ VOS_STATUS status;
+
+ if (peer) {
+ vos_mem_copy(my_peer, peer, 6);
+ ucSTAId = wlan_hdd_findTdlsPeer(my_peer);
+
+ hddLog(VOS_TRACE_LEVEL_INFO_HIGH,
+ "%s: set key for peer %2x:%2x:%2x:%2x:%2x:%2x",
+ __func__, peer[0], peer[1],
+ peer[2], peer[3],
+ peer[4], peer[5] );
+
+ if (-1 == ucSTAId ) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "wlan_hdd_findTdlsPeer failed" );
+ return 0;
+ }
+
+ status = WLANTL_ChangeSTAState( pVosContext, ucSTAId,
+ WLANTL_STA_AUTHENTICATED );
+
+ if (0 != status) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ "%s: WLANTL_ChangeSTAState failed, returned %d",
+ __func__, status);
+ return status;
+ }
+ } else {
+ hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
+ }
+ }
+ break;
+ case NL80211_TDLS_DISABLE_LINK:
+ sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, peer );
+ return 0;
+ case NL80211_TDLS_TEARDOWN:
+ case NL80211_TDLS_SETUP:
+ case NL80211_TDLS_DISCOVERY_REQ:
+ /* We don't support in-driver setup/teardown/discovery */
+ return -ENOTSUPP;
+ default:
+ return -ENOTSUPP;
+ }
+ return 0;
+}
+#endif
+
/* cfg80211_ops */
static struct cfg80211_ops wlan_hdd_cfg80211_ops =
{
@@ -6202,6 +6389,10 @@
#if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211)
.update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
#endif
+#ifdef FEATURE_WLAN_TDLS
+ .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
+ .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
+#endif
};
#endif // CONFIG_CFG80211