wlan : Fast transition (11r)

- Set Key along with the Config BSS command to HAL
  to improve the 11r roam latencies
- Move the TL state to Authenticated to allow TX Data
  when set GTK is received at driver from supplicant
- Optimize the memcpy in hdd_SendFTEvent

Change-Id: Iab9f1fbcc4a11bd1a2e521885a6beaf1f6a9068a
CRs-fixed: 465419
diff --git a/CORE/HDD/inc/wlan_hdd_assoc.h b/CORE/HDD/inc/wlan_hdd_assoc.h
index f6aac61..2463690 100644
--- a/CORE/HDD/inc/wlan_hdd_assoc.h
+++ b/CORE/HDD/inc/wlan_hdd_assoc.h
@@ -140,5 +140,5 @@
 int hdd_set_csr_auth_type( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType );
 VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter,
                                     tANI_U8 *peerMac, tANI_U16 staId, tANI_U8 ucastSig);
-
+void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter);
 #endif
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 3439334..ea514dd 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -185,6 +185,9 @@
 #define GTK_OFFLOAD_DISABLE 1
 #endif
 
+#define HDD_MAC_ADDR_LEN    6
+typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN];
+
 typedef struct hdd_tx_rx_stats_s
 {
    // start_xmit stats
@@ -276,6 +279,12 @@
 {
    HDD_ROAM_STATE roamingState;
    vos_event_t roamingEvent;
+
+   tWlanHddMacAddr bssid;
+   tWlanHddMacAddr peerMac;
+   tANI_U32 roamId;
+   eRoamCmdStatus roamStatus;
+   v_BOOL_t deferKeyComplete;
    
 } roaming_info_t;
 
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index e80e603..b9e1a6f 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -127,6 +127,12 @@
                             tANI_U8 frameType );
 #endif
 
+static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter,
+                                                tCsrRoamInfo *pRoamInfo,
+                                                tANI_U32 roamId,
+                                                eRoamCmdStatus roamStatus,
+                                                eCsrRoamResult roamResult );
+
 v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx,
                                         eConnectionState connState )
 {
@@ -394,7 +400,6 @@
     struct cfg80211_ft_event_params ftEvent;
     v_U8_t ftIe[DOT11F_IE_FTINFO_MAX_LEN];
     v_U8_t ricIe[DOT11F_IE_RICDESCRIPTOR_MAX_LEN];
-    v_U8_t target_ap[SIR_MAC_ADDR_LENGTH];
     struct net_device *dev = pAdapter->dev;
 #else
     char *buff;
@@ -428,9 +433,9 @@
         return;
     }
 
-    vos_mem_copy(target_ap, ftIe, SIR_MAC_ADDR_LENGTH);
+    sme_SetFTPreAuthState(pHddCtx->hHal, TRUE);
 
-    ftEvent.target_ap = target_ap;
+    ftEvent.target_ap = ftIe;
 
     ftEvent.ies = (u8 *)(ftIe + SIR_MAC_ADDR_LENGTH);
     ftEvent.ies_len = auth_resp_len - SIR_MAC_ADDR_LENGTH;
@@ -1082,6 +1087,31 @@
     kfree(rspRsnIe);
 }
 
+void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter)
+{
+    eHalStatus halStatus = eHAL_STATUS_SUCCESS;
+    hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+    tCsrRoamInfo roamInfo;
+    roamInfo.fAuthRequired = FALSE;
+    vos_mem_copy(roamInfo.bssid,
+                 pHddStaCtx->roam_info.bssid,
+                 WNI_CFG_BSSID_LEN);
+    vos_mem_copy(roamInfo.peerMac,
+                 pHddStaCtx->roam_info.peerMac,
+                 WNI_CFG_BSSID_LEN);
+
+    halStatus = hdd_RoamSetKeyCompleteHandler(pAdapter,
+                                  &roamInfo,
+                                  pHddStaCtx->roam_info.roamId,
+                                  pHddStaCtx->roam_info.roamStatus,
+                                  eCSR_ROAM_RESULT_AUTHENTICATED);
+    if (halStatus != eHAL_STATUS_SUCCESS)
+    {
+        hddLog(LOGE, "%s: Set Key complete failure", __func__);
+    }
+    pHddStaCtx->roam_info.deferKeyComplete = FALSE;
+}
+
 static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo,
                                                     tANI_U32 roamId, eRoamCmdStatus roamStatus,
                                                     eCsrRoamResult roamResult )
@@ -1246,6 +1276,21 @@
                     cfg80211_roamed(dev,chan, pRoamInfo->bssid,
                                     pFTAssocReq, assocReqlen, pFTAssocRsp, assocRsplen,
                                     GFP_KERNEL);
+                    if (sme_GetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter)))
+                    {
+                        sme_SetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter), FALSE);
+                        pRoamInfo->fAuthRequired = FALSE;
+
+                        vos_mem_copy(pHddStaCtx->roam_info.bssid,
+                                     pRoamInfo->bssid,
+                                     HDD_MAC_ADDR_LEN);
+                        vos_mem_copy(pHddStaCtx->roam_info.peerMac,
+                                     pRoamInfo->peerMac,
+                                     HDD_MAC_ADDR_LEN);
+                        pHddStaCtx->roam_info.roamId = roamId;
+                        pHddStaCtx->roam_info.roamStatus = roamStatus;
+                        pHddStaCtx->roam_info.deferKeyComplete = TRUE;
+                    }
                 }
                 else
                 {
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 753ded5..278d455 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -3216,6 +3216,22 @@
         hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
         hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
+        if (!pairwise)
+#else
+        if (!mac_addr || is_broadcast_ether_addr(mac_addr))
+#endif
+        {
+            /* set group key*/
+            if (pHddStaCtx->roam_info.deferKeyComplete)
+            {
+                VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                           "%s- %d: Perform Set key Complete",
+                           __func__, __LINE__);
+                hdd_PerformRoamSetKeyComplete(pAdapter);
+            }
+        }
+
         pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
 
         pWextState->roamProfile.Keys.defaultIndex = key_index;
@@ -3224,6 +3240,7 @@
         vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0],
                 params->key, params->key_len);
 
+
         pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
 
         hddLog(VOS_TRACE_LEVEL_INFO_MED,
@@ -3248,11 +3265,20 @@
         }
 
 #ifdef WLAN_FEATURE_VOWIFI_11R
-   /* The supplicant may attempt to set the PTK once pre-authentication is done.
-        Save the key in the UMAC and include it in the ADD BSS request */
+        /* The supplicant may attempt to set the PTK once pre-authentication
+           is done. Save the key in the UMAC and include it in the ADD BSS
+           request */
         halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
-        if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
+        if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
         {
+           hddLog(VOS_TRACE_LEVEL_INFO_MED,
+                  "%s: Update PreAuth Key success", __func__);
+           return 0;
+        }
+        else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
+        {
+           hddLog(VOS_TRACE_LEVEL_ERROR,
+                  "%s: Update PreAuth Key failed", __func__);
            return -EINVAL;
         }
 #endif /* WLAN_FEATURE_VOWIFI_11R */
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index a02d390..632926b 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -3317,12 +3317,21 @@
           ("%s:cipher_alg:%d key_len[%d] *pEncryptionType :%d \n"),__func__,(int)ext->alg,(int)ext->key_len,setKey.encType);
 
 #ifdef WLAN_FEATURE_VOWIFI_11R
-/* The supplicant may attempt to set the PTK once pre-authentication is done.
-   Save the key in the UMAC and include it in the ADD BSS request */
+    /* The supplicant may attempt to set the PTK once pre-authentication
+       is done. Save the key in the UMAC and include it in the ADD
+       BSS request */
     halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey);
-    if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT )
+    if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS )
     {
-       return -EINVAL;
+        hddLog(VOS_TRACE_LEVEL_INFO_MED,
+               "%s: Update PreAuth Key success", __func__);
+        return 0;
+    }
+    else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED )
+    {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               "%s: Update PreAuth Key failed", __func__);
+        return -EINVAL;
     }
 #endif /* WLAN_FEATURE_VOWIFI_11R */
 
diff --git a/CORE/MAC/src/pe/include/limFTDefs.h b/CORE/MAC/src/pe/include/limFTDefs.h
index 2b34866..4912087 100644
--- a/CORE/MAC/src/pe/include/limFTDefs.h
+++ b/CORE/MAC/src/pe/include/limFTDefs.h
@@ -54,6 +54,7 @@
 
 
 #include <palTypes.h>
+#include "halMsgApi.h"
 
 /*-------------------------------------------------------------------------- 
   Preprocessor definitions and constants
@@ -66,8 +67,8 @@
 /*-------------------------------------------------------------------------- 
   Type declarations
   ------------------------------------------------------------------------*/
-/*-------------------------------------------------------------------------- 
-  FT Pre Auth Req SME<->PE 
+/*--------------------------------------------------------------------------
+  FT Pre Auth Req SME<->PE
   ------------------------------------------------------------------------*/
 typedef struct sSirFTPreAuthReq
 {
@@ -84,7 +85,7 @@
 } tSirFTPreAuthReq, *tpSirFTPreAuthReq;
 
 /*-------------------------------------------------------------------------
-  FT Pre Auth Rsp PE<->SME 
+  FT Pre Auth Rsp PE<->SME
   ------------------------------------------------------------------------*/
 typedef struct sSirFTPreAuthRsp
 {
@@ -99,29 +100,39 @@
    tANI_U8          ric_ies[MAX_FTIE_SIZE];
 } tSirFTPreAuthRsp, *tpSirFTPreAuthRsp;
 
-/*-------------------------------------------------------------------------- 
-  FT Pre Auth Req SME<->PE 
+/*--------------------------------------------------------------------------
+  FT Pre Auth Rsp Key SME<->PE
   ------------------------------------------------------------------------*/
 typedef struct sSirFTUpdateKeyInfo
 {
-   tANI_U16          messageType;
-   tANI_U16          length;
-   tSirKeyMaterial   keyMaterial;
+   tANI_U16             messageType;
+   tANI_U16             length;
+   tSirMacAddr          bssId;
+   tSirKeyMaterial      keyMaterial;
 } tSirFTUpdateKeyInfo, *tpSirFTUpdateKeyInfo;
 
+/*--------------------------------------------------------------------------
+  FT Pre Auth Rsp Key SME<->PE
+  ------------------------------------------------------------------------*/
+typedef struct sSirFTPreAuthKeyInfo
+{
+    tANI_U8 extSetStaKeyParamValid; //Ext Bss Config Msg if set
+    tSetStaKeyParams extSetStaKeyParam;  //SetStaKeyParams for ext bss msg
+} tSirFTPreAuthKeyInfo, *tpSirFTPreAuthKeyInfo;
+
 /*-------------------------------------------------------------------------
-  Global FT Information 
+  Global FT Information
   ------------------------------------------------------------------------*/
 typedef struct sFTPEContext
 {
     tpSirFTPreAuthReq pFTPreAuthReq;                      // Saved FT Pre Auth Req
-    void              *psavedsessionEntry;                
+    void              *psavedsessionEntry;
     tSirRetStatus     ftPreAuthStatus;
     tANI_U16          saved_auth_rsp_length;
     tANI_U8           saved_auth_rsp[MAX_FTIE_SIZE];
-
+    tSirFTPreAuthKeyInfo    *pPreAuthKeyInfo;
     // Items created for the new FT, session
-    void              *pftSessionEntry;                   // Saved session created for pre-auth 
+    void              *pftSessionEntry;                   // Saved session created for pre-auth
     void              *pAddBssReq;                        // Save add bss req.
     void              *pAddStaReq;                        // Save add sta req.
 
diff --git a/CORE/MAC/src/pe/lim/limFT.c b/CORE/MAC/src/pe/lim/limFT.c
index 2bb70f5..47fff7a 100644
--- a/CORE/MAC/src/pe/lim/limFT.c
+++ b/CORE/MAC/src/pe/lim/limFT.c
@@ -70,6 +70,7 @@
 #define LIM_FT_RIC_BA_SSN                       1
 #define LIM_FT_RIC_BA_DIALOG_TOKEN_TID_0         248
 #define LIM_FT_RIC_DESCRIPTOR_RESOURCE_TYPE_BA  1
+#define LIM_FT_RIC_DESCRIPTOR_MAX_VAR_DATA_LEN   255
 
 /*--------------------------------------------------------------------------
   Initialize the FT variables. 
@@ -805,6 +806,8 @@
 tSirRetStatus limCreateRICBlockAckIE(tpAniSirGlobal pMac, tANI_U8 tid, tCfgTrafficClass *pTrafficClass, 
                                                                     tANI_U8 *ric_ies, tANI_U32 *ieLength)
 {
+    /* BlockACK + RIC is not supported now, TODO later to support this */
+#if 0
     tDot11fIERICDataDesc ricIe;
     tDot11fFfBAStartingSequenceControl baSsnControl;
     tDot11fFfAddBAParameterSet baParamSet;
@@ -827,23 +830,25 @@
     vos_mem_copy((v_VOID_t *)&baTimeout, (v_VOID_t *)&pTrafficClass->tuTxBAWaitTimeout, sizeof(baTimeout));
     baSsnControl.fragNumber = 0;
     baSsnControl.ssn = LIM_FT_RIC_BA_SSN;
-    if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) {
+    if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) {
         dot11fPackFfAddBAParameterSet(pMac, &baParamSet, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]);
         //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baParamSet, sizeof(tDot11fFfAddBAParameterSet));
         ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfAddBAParameterSet);
     }
-
-    if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) {
+    if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) {
         dot11fPackFfBATimeout(pMac, &baTimeout, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]);
         //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baTimeout, sizeof(tDot11fFfBATimeout));
         ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfBATimeout);
     }
-    if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) {
+    if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) {
         dot11fPackFfBAStartingSequenceControl(pMac, &baSsnControl, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]);
         //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baSsnControl, sizeof(tDot11fFfBAStartingSequenceControl));
         ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfBAStartingSequenceControl);
     }
     return (tSirRetStatus) dot11fPackIeRICDataDesc(pMac, &ricIe, ric_ies, sizeof(tDot11fIERICDataDesc), ieLength);
+#endif
+
+    return eSIR_FAILURE;
 }
 
 tSirRetStatus limFTFillRICBlockAckInfo(tpAniSirGlobal pMac, tANI_U8 *ric_ies, tANI_U32 *ric_ies_length)
@@ -1234,32 +1239,72 @@
  *------------------------------------------------------------------*/
 tANI_BOOLEAN limProcessFTUpdateKey(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf )
 {
-   tAddBssParams * pAddBssParams;
-   tSirFTUpdateKeyInfo * pKeyInfo;
-   tANI_U32 val = 0;
+    tAddBssParams * pAddBssParams;
+    tSirFTUpdateKeyInfo * pKeyInfo;
+    tANI_U32 val = 0;
 
-   /* Sanity Check */
-   if( pMac == NULL || pMsgBuf == NULL )
-   {
-      return TRUE;
-   }
+    /* Sanity Check */
+    if( pMac == NULL || pMsgBuf == NULL )
+    {
+        return TRUE;
+    }
+    if(pMac->ft.ftPEContext.pAddBssReq == NULL)
+    {
+        limLog( pMac, LOGE,
+                FL( "pAddBssReq is NULL" ));
+        return TRUE;
+    }
 
-   pAddBssParams = pMac->ft.ftPEContext.pAddBssReq;
-   pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf;
+    pAddBssParams = pMac->ft.ftPEContext.pAddBssReq;
+    pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf;
 
-   /* Store the key information in the ADD BSS parameters */
-   pAddBssParams->extSetStaKeyParamValid = 1;
-   pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType;
-   palCopyMemory( pMac->hHdd, (tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key,
+    /* Store the key information in the ADD BSS parameters */
+    pAddBssParams->extSetStaKeyParamValid = 1;
+    pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType;
+    palCopyMemory( pMac->hHdd, (tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key,
                   (tANI_U8 *) &pKeyInfo->keyMaterial.key, sizeof( tSirKeys ));
-  if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val))
-  {
-     limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" ));
-  }
+    if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val))
+    {
+        limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" ));
+    }
 
-  pAddBssParams->extSetStaKeyParam.singleTidRc = val;    
+    pAddBssParams->extSetStaKeyParam.singleTidRc = val;
+    PELOG1(limLog(pMac, LOG1, FL("Key valid %d"),
+                pAddBssParams->extSetStaKeyParamValid,
+                pAddBssParams->extSetStaKeyParam.key[0].keyLength);)
 
-  return TRUE;   
+    pAddBssParams->extSetStaKeyParam.staIdx = 0;
+
+    PELOG1(limLog(pMac, LOG1,
+         FL("BSSID = %02X-%02X-%02X-%02X-%02X-%02X"),
+         pKeyInfo->bssId[0], pKeyInfo->bssId[1],
+         pKeyInfo->bssId[2], pKeyInfo->bssId[3],
+         pKeyInfo->bssId[4], pKeyInfo->bssId[5]);)
+
+    if(pAddBssParams->extSetStaKeyParam.key[0].keyLength == 16)
+    {
+        PELOG1(limLog(pMac, LOG1,
+        FL("BSS key = %02X-%02X-%02X-%02X-%02X-%02X-%02X- "
+        "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X"),
+        pAddBssParams->extSetStaKeyParam.key[0].key[0],
+        pAddBssParams->extSetStaKeyParam.key[0].key[1],
+        pAddBssParams->extSetStaKeyParam.key[0].key[2],
+        pAddBssParams->extSetStaKeyParam.key[0].key[3],
+        pAddBssParams->extSetStaKeyParam.key[0].key[4],
+        pAddBssParams->extSetStaKeyParam.key[0].key[5],
+        pAddBssParams->extSetStaKeyParam.key[0].key[6],
+        pAddBssParams->extSetStaKeyParam.key[0].key[7],
+        pAddBssParams->extSetStaKeyParam.key[0].key[8],
+        pAddBssParams->extSetStaKeyParam.key[0].key[9],
+        pAddBssParams->extSetStaKeyParam.key[0].key[10],
+        pAddBssParams->extSetStaKeyParam.key[0].key[11],
+        pAddBssParams->extSetStaKeyParam.key[0].key[12],
+        pAddBssParams->extSetStaKeyParam.key[0].key[13],
+        pAddBssParams->extSetStaKeyParam.key[0].key[14],
+        pAddBssParams->extSetStaKeyParam.key[0].key[15]);)
+    }
+
+    return TRUE;
 }
 
 tSirRetStatus
diff --git a/CORE/SME/inc/sme_FTApi.h b/CORE/SME/inc/sme_FTApi.h
index 115f3f9..1dba737 100644
--- a/CORE/SME/inc/sme_FTApi.h
+++ b/CORE/SME/inc/sme_FTApi.h
@@ -39,6 +39,8 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+
+
 #if !defined( __SME_FTAPI_H )
 #define __SME_FTAPI_H
 
@@ -49,9 +51,9 @@
   
   \brief macros and prototype for SME APIs
   
-   Copyright 2008 (c) Qualcomm, Incorporated.  All Rights Reserved.
+   Copyright 2008 (c) Qualcomm Technologies, Inc.  All Rights Reserved.
    
-   Qualcomm Confidential and Proprietary.
+   Qualcomm Technologies Confidential and Proprietary.
   
   ========================================================================*/
 typedef enum eFTIEState
@@ -82,9 +84,12 @@
 
     // Saved pFTPreAuthRsp
     tpSirFTPreAuthRsp psavedFTPreAuthRsp;
+    v_BOOL_t          setFTPreAuthState;
+    v_BOOL_t          setFTPTKState;
 
     // Time to trigger reassoc once pre-auth is successful
     tPalTimerHandle   preAuthReassocIntvlTimer;
+    tCsrRoamSetKey    *pCsrFTKeyInfo;
 
 } tftSMEContext, *tpftSMEContext;
 
@@ -99,6 +104,10 @@
 void sme_GetFTPreAuthResponse( tHalHandle hHal, tANI_U8 *ft_ies, tANI_U32 ft_ies_ip_len, tANI_U16 *ft_ies_length );
 void sme_GetRICIEs( tHalHandle hHal, tANI_U8 *ric_ies, tANI_U32 ric_ies_ip_len, tANI_U32 *ric_ies_length );
 void sme_PreauthReassocIntvlTimerCallback(void *context);
+void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state);
+v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal);
+v_BOOL_t sme_GetFTPTKState(tHalHandle hHal);
+void sme_SetFTPTKState(tHalHandle hHal, v_BOOL_t state);
 
 
 #endif //#if !defined( __SME_FTAPI_H )
diff --git a/CORE/SME/src/sme_common/sme_FTApi.c b/CORE/SME/src/sme_common/sme_FTApi.c
index 81219f6..929592b 100644
--- a/CORE/SME/src/sme_common/sme_FTApi.c
+++ b/CORE/SME/src/sme_common/sme_FTApi.c
@@ -70,7 +70,8 @@
 
     pMac->ft.ftSmeContext.reassoc_ft_ies = NULL;                        
     pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0;       
-
+    pMac->ft.ftSmeContext.setFTPreAuthState = FALSE;
+    pMac->ft.ftSmeContext.setFTPTKState = FALSE;
     status = palTimerAlloc(pMac->hHdd, &pMac->ft.ftSmeContext.preAuthReassocIntvlTimer, 
                             sme_PreauthReassocIntvlTimerCallback, (void *)pMac);
 
@@ -81,6 +82,7 @@
     }                 
 
     pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL;                        
+    pMac->ft.ftSmeContext.pCsrFTKeyInfo = NULL;
 
     pMac->ft.ftSmeContext.FTState = eFT_START_READY;
 }
@@ -130,6 +132,17 @@
     palTimerFree(pMac->hHdd, pMac->ft.ftSmeContext.preAuthReassocIntvlTimer);
 }
 
+void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state)
+{
+  tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+  pMac->ft.ftSmeContext.setFTPreAuthState = state;
+}
+
+v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal)
+{
+  tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+  return pMac->ft.ftSmeContext.setFTPreAuthState;
+}
 
 /*--------------------------------------------------------------------------
   Each time the supplicant sends down the FT IEs to the driver.
@@ -259,17 +272,17 @@
     tANI_U16 msgLen;
     eHalStatus status = eHAL_STATUS_FAILURE;
     tAniEdType tmpEdType;
-    tAniKeyDirection tmpDirection;
-    //tANI_U8 *pBuf;
-    tANI_U8 *p = NULL;
+    tSirKeyMaterial *keymaterial = NULL;
     tAniEdType edType;
     tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
     int i = 0;
 
-    smsLog(pMac, LOGE, FL("keyLength %d"), pFTKeyInfo->keyLength);
+    smsLog(pMac, LOG1, FL("keyLength %d"), pFTKeyInfo->keyLength);
 
-      for(i=0; i<pFTKeyInfo->keyLength; i++)
-          smsLog(pMac, LOGE, FL("%02x"), pFTKeyInfo->Key[i]);
+    for (i=0; i<pFTKeyInfo->keyLength; i++)
+      smsLog(pMac, LOG1, FL("%02x"), pFTKeyInfo->Key[i]);
+#endif
 
     msgLen  = sizeof( tANI_U16) + sizeof( tANI_U16 ) + 
        sizeof( pMsg->keyMaterial.length ) + sizeof( pMsg->keyMaterial.edType ) + 
@@ -285,66 +298,78 @@
     pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_FT_UPDATE_KEY);
     pMsg->length = pal_cpu_to_be16(msgLen);
 
-    p = (tANI_U8 *)&pMsg->keyMaterial;
+    keymaterial = &pMsg->keyMaterial;
 
-    // Set the pMsg->keyMaterial.length field (this length is defined as all data that follows the edType field
-    // in the tSirKeyMaterial keyMaterial; field).
-    //
-    // !!NOTE:  This keyMaterial.length contains the length of a MAX size key, though the keyLength can be 
-    // shorter than this max size.  Is LIM interpreting this ok ?
-    p = pal_set_U16( p, pal_cpu_to_be16((tANI_U16)( sizeof( pMsg->keyMaterial.numKeys ) + 
-                                                    ( pMsg->keyMaterial.numKeys * sizeof( pMsg->keyMaterial.key ) ) )) );
+    keymaterial->length = pFTKeyInfo->keyLength;
 
-    // set pMsg->keyMaterial.edType
     edType = csrTranslateEncryptTypeToEdType( pFTKeyInfo->encType );
     tmpEdType = pal_cpu_to_be32(edType);
-    palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpEdType, sizeof(tAniEdType) );
-    p += sizeof( pMsg->keyMaterial.edType );
+    keymaterial->edType = tmpEdType;
 
-    // set the pMsg->keyMaterial.numKeys field
-    *p = pMsg->keyMaterial.numKeys;
-    p += sizeof( pMsg->keyMaterial.numKeys );   
+    // Set the pMsg->keyMaterial.length field (this length is defined as all
+    // data that follows the edType field
+    // in the tSirKeyMaterial keyMaterial; field).
+    //
+    // !!NOTE:  This keyMaterial.length contains the length of a MAX size key,
+    // though the keyLength can be
+    // shorter than this max size.  Is LIM interpreting this ok ?
+    keymaterial->numKeys = 1;
+    keymaterial->key[ 0 ].keyId = pFTKeyInfo->keyId;
+    keymaterial->key[ 0 ].unicast = (tANI_U8)eANI_BOOLEAN_TRUE;
+    keymaterial->key[ 0 ].keyDirection = pFTKeyInfo->keyDirection;
 
-    // set pSirKey->keyId = keyId;
-    *p = pMsg->keyMaterial.key[ 0 ].keyId;
-    p += sizeof( pMsg->keyMaterial.key[ 0 ].keyId );
+    palCopyMemory( pMac->hHdd, &keymaterial->key[ 0 ].keyRsc,
+                   pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN );
 
-    // set pSirKey->unicast = (tANI_U8)fUnicast;
-    *p = (tANI_U8)eANI_BOOLEAN_TRUE;
-    p += sizeof( pMsg->keyMaterial.key[ 0 ].unicast );
+    keymaterial->key[ 0 ].paeRole = pFTKeyInfo->paeRole;
 
-    // set pSirKey->keyDirection = aniKeyDirection;
-    tmpDirection = pal_cpu_to_be32(pFTKeyInfo->keyDirection);
-    palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpDirection, sizeof(tAniKeyDirection) );
-    p += sizeof(tAniKeyDirection);
-    //    pSirKey->keyRsc = ;;
-    palCopyMemory( pMac->hHdd, p, pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN );
-    p += sizeof( pMsg->keyMaterial.key[ 0 ].keyRsc );
+    keymaterial->key[ 0 ].keyLength = pFTKeyInfo->keyLength;
 
-    // set pSirKey->paeRole
-    *p = pFTKeyInfo->paeRole;   // 0 is Supplicant
-    p++;
-
-    // set pSirKey->keyLength = keyLength;
-    p = pal_set_U16( p, pal_cpu_to_be16(pFTKeyInfo->keyLength) );
-
-    if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key ) 
-    {   
-        palCopyMemory( pMac->hHdd, p, pFTKeyInfo->Key, pFTKeyInfo->keyLength ); 
+    if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key )
+    {
+        palCopyMemory( pMac->hHdd, &keymaterial->key[ 0 ].key,
+                       pFTKeyInfo->Key, pFTKeyInfo->keyLength );
         if(pFTKeyInfo->keyLength == 16)
         {
-            smsLog(pMac, LOG1, "  SME Set keyIdx (%d) encType(%d) key = %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
-            pFTKeyInfo->keyId, edType, pFTKeyInfo->Key[0], pFTKeyInfo->Key[1], pFTKeyInfo->Key[2], pFTKeyInfo->Key[3], pFTKeyInfo->Key[4],
-            pFTKeyInfo->Key[5], pFTKeyInfo->Key[6], pFTKeyInfo->Key[7], pFTKeyInfo->Key[8],
-            pFTKeyInfo->Key[9], pFTKeyInfo->Key[10], pFTKeyInfo->Key[11], pFTKeyInfo->Key[12], pFTKeyInfo->Key[13], pFTKeyInfo->Key[14], pFTKeyInfo->Key[15]);
+          smsLog(pMac, LOG1, "SME Set Update Ind keyIdx (%d) encType(%d) key = "
+          "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
+          pMsg->keyMaterial.key[0].keyId, (tAniEdType)pMsg->keyMaterial.edType,
+          pMsg->keyMaterial.key[0].key[0], pMsg->keyMaterial.key[0].key[1],
+          pMsg->keyMaterial.key[0].key[2], pMsg->keyMaterial.key[0].key[3],
+          pMsg->keyMaterial.key[0].key[4], pMsg->keyMaterial.key[0].key[5],
+          pMsg->keyMaterial.key[0].key[6], pMsg->keyMaterial.key[0].key[7],
+          pMsg->keyMaterial.key[0].key[8], pMsg->keyMaterial.key[0].key[9],
+          pMsg->keyMaterial.key[0].key[10], pMsg->keyMaterial.key[0].key[11],
+          pMsg->keyMaterial.key[0].key[12], pMsg->keyMaterial.key[0].key[13],
+          pMsg->keyMaterial.key[0].key[14], pMsg->keyMaterial.key[0].key[15]);
         }
     }
 
+    vos_mem_copy( &pMsg->bssId[ 0 ],
+                  &pFTKeyInfo->peerMac[ 0 ],
+                  sizeof(tCsrBssid) );
+
+    smsLog(pMac, LOG1, "BSSID = %02X-%02X-%02X-%02X-%02X-%02X",
+           pMsg->bssId[0], pMsg->bssId[1], pMsg->bssId[2],
+           pMsg->bssId[3], pMsg->bssId[4], pMsg->bssId[5]);
+
     status = palSendMBMessage(pMac->hHdd, pMsg);
 
     return( status );
 }
 
+v_BOOL_t sme_GetFTPTKState(tHalHandle hHal)
+{
+  tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+  return pMac->ft.ftSmeContext.setFTPTKState;
+}
+
+void sme_SetFTPTKState(tHalHandle hHal, v_BOOL_t state)
+{
+  tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
+  pMac->ft.ftSmeContext.setFTPTKState = state;
+}
+
 eHalStatus sme_FTUpdateKey( tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo )
 {
     tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
@@ -372,11 +397,28 @@
     switch(pMac->ft.ftSmeContext.FTState)
     {
     case eFT_SET_KEY_WAIT:
-       status = eHAL_STATUS_FT_PREAUTH_KEY_WAIT;
-       pMac->ft.ftSmeContext.FTState = eFT_START_READY;
+    if (sme_GetFTPreAuthState (hHal) == TRUE)
+      {
+          status = sme_FTSendUpdateKeyInd(pMac, pFTKeyInfo);
+          if (status != 0 )
+          {
+              smsLog( pMac, LOGE, "%s: Key set failure %d", __func__,
+                      status);
+              pMac->ft.ftSmeContext.setFTPTKState = FALSE;
+              status = eHAL_STATUS_FT_PREAUTH_KEY_FAILED;
+          }
+          else
+          {
+              pMac->ft.ftSmeContext.setFTPTKState = TRUE;
+              status = eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS;
+              smsLog( pMac, LOG1, "%s: Key set success", __func__);
+          }
+          sme_SetFTPreAuthState(hHal, FALSE);
+      }
+      pMac->ft.ftSmeContext.FTState = eFT_START_READY;
 #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
-       smsLog( pMac, LOG1, "%s: state changed to %d", __func__,
-               pMac->ft.ftSmeContext.FTState);
+      smsLog( pMac, LOG1, "%s: state changed to %d status %d", __func__,
+              pMac->ft.ftSmeContext.FTState, status);
 #endif
        break;
           
diff --git a/CORE/WDA/inc/legacy/halTypes.h b/CORE/WDA/inc/legacy/halTypes.h
index f3ca8ab..2e72956 100644
--- a/CORE/WDA/inc/legacy/halTypes.h
+++ b/CORE/WDA/inc/legacy/halTypes.h
@@ -39,6 +39,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+
 /** ------------------------------------------------------------------------- *
     ------------------------------------------------------------------------- *
 
@@ -230,7 +231,8 @@
     eHAL_STATUS_SET_CHAN_ALREADY_ON_REQUESTED_CHAN,
 
 #ifdef WLAN_FEATURE_VOWIFI_11R
-    eHAL_STATUS_FT_PREAUTH_KEY_WAIT,
+    eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS,
+    eHAL_STATUS_FT_PREAUTH_KEY_FAILED,
 #endif
 
     // not a real status.  Just a way to mark the maximum in the enum.