Send unicast probe request when AP caps change detected.

Some buggy APs not setting privacy bit in capability
field of beacons if hiddne SSID is enabled. With these
APs the STA is always getting disconnected because
of AP capability change event from LIM.
To address this issue the followinge changes are done.
1. If the SSID in beacon is NULL and if the privacy bit
setting is not matching with existing privacy bit
settings, then send directed probe request frame
instead of sending AP caps changed event to SME.
2. After receiving probe response frame compare the
capabilities and if it still not matching then send
the AP caps event to SME.
3. If the capabilities in probe response are matching
with the existing settings then mark this event and
ignore all subsequent false alarms.

Change-Id: I6cd6ba45231b17ed4048dd0cce0a7b59de1b778c
CRs-Fixed: 447997
diff --git a/CORE/MAC/src/pe/include/limSession.h b/CORE/MAC/src/pe/include/limSession.h
index 4638f73..570c35b 100644
--- a/CORE/MAC/src/pe/include/limSession.h
+++ b/CORE/MAC/src/pe/include/limSession.h
@@ -351,7 +351,8 @@
 #ifdef FEATURE_WLAN_TDLS
     tANI_U32  peerAIDBitmap[2];
 #endif
-
+    tANI_BOOLEAN fWaitForProbeRsp;
+    tANI_BOOLEAN fIgnoreCapsChange;
 }tPESession, *tpPESession;
 
 #define LIM_MAX_ACTIVE_SESSIONS 4
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index 98f6272..fde0fef 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -1702,16 +1702,70 @@
     tANI_U8                 len;
     tSirSmeApNewCaps   apNewCaps;
     tANI_U8            newChannel;
+    tSirRetStatus status = eSIR_SUCCESS;
     apNewCaps.capabilityInfo = limGetU16((tANI_U8 *) &pBeacon->capabilityInfo);
     newChannel = (tANI_U8) pBeacon->channelNumber;
 
-    if ((psessionEntry->limSentCapsChangeNtf == false) && 
-        (((!limIsNullSsid(&pBeacon->ssId)) && (limCmpSSid(pMac, &pBeacon->ssId, psessionEntry) == false)) || 
+    /* Some APs are not setting privacy bit when hidden ssid enabled.
+     * So LIM was keep on sending eSIR_SME_AP_CAPS_CHANGED event to SME */
+    if (limIsNullSsid(&pBeacon->ssId) &&
+            (SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) !=
+             SIR_MAC_GET_PRIVACY(psessionEntry->limCurrentBssCaps))
+       )
+    {
+        /* If Hidden SSID and privacy bit is not matching with the current capability,
+         * then send unicast probe request to AP and take decision after
+         * receiving probe response */
+        if (psessionEntry->fIgnoreCapsChange == true)
+        {
+            limLog(pMac, LOGW, FL("Ignoring the Capability change as it is false alarm"));
+            return;
+        }
+        psessionEntry->fWaitForProbeRsp = true;
+        limLog(pMac, LOGW, FL("Hidden SSID and privacy bit is not matching,"
+                    "sending directed probe request.. "));
+        status = limSendProbeReqMgmtFrame(pMac, &psessionEntry->ssId, psessionEntry->bssId,
+                psessionEntry->currentOperChannel,psessionEntry->selfMacAddr,
+                psessionEntry->dot11mode, 0, NULL);
+
+        if ( status != eSIR_SUCCESS)
+        {
+            limLog(pMac, LOGE, FL("send ProbeReq failed"));
+        }
+
+        return;
+    }
+    else
+    {
+        /* The control will come here if the frame is beacon with broadcast ssid
+         * or probe response frame */
+        if (psessionEntry->fWaitForProbeRsp == true)
+        {
+            if (((!limIsNullSsid(&pBeacon->ssId)) &&
+                        (limCmpSSid(pMac, &pBeacon->ssId, psessionEntry) == true)) &&
+                    (SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) ==
+                     SIR_MAC_GET_PRIVACY(psessionEntry->limCurrentBssCaps)))
+            {
+                /* Only for probe response frames the control will come here */
+                /* If beacon with broadcast ssid then fWaitForProbeRsp will be false,
+                   the control wll not come here*/
+                limLog(pMac, LOGW, FL("Privacy bit in probe response is"
+                            "matching with the current setting,"
+                            "Ignoring subsequent privacy bit capability"
+                            "mismatch"));
+                psessionEntry->fIgnoreCapsChange = true;
+                psessionEntry->fWaitForProbeRsp = false;
+            }
+        }
+    }
+
+    if ((psessionEntry->limSentCapsChangeNtf == false) &&
+        (((!limIsNullSsid(&pBeacon->ssId)) && (limCmpSSid(pMac, &pBeacon->ssId, psessionEntry) == false)) ||
         ((SIR_MAC_GET_ESS(apNewCaps.capabilityInfo) != SIR_MAC_GET_ESS(psessionEntry->limCurrentBssCaps)) ||
          (SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) !=   SIR_MAC_GET_PRIVACY(psessionEntry->limCurrentBssCaps)) ||
          (SIR_MAC_GET_SHORT_PREAMBLE(apNewCaps.capabilityInfo) !=  SIR_MAC_GET_SHORT_PREAMBLE(psessionEntry->limCurrentBssCaps)) ||
          (SIR_MAC_GET_QOS(apNewCaps.capabilityInfo) !=   SIR_MAC_GET_QOS(psessionEntry->limCurrentBssCaps)) ||
-         (newChannel !=  psessionEntry->currentOperChannel) 
+         (newChannel !=  psessionEntry->currentOperChannel)
          )))
     {
 
@@ -1758,6 +1812,8 @@
                       (tANI_U8 *) &pBeacon->ssId,
                       pBeacon->ssId.length + 1);
 
+        psessionEntry->fIgnoreCapsChange = false;
+        psessionEntry->fWaitForProbeRsp = false;
         psessionEntry->limSentCapsChangeNtf = true;
         limSendSmeWmStatusChangeNtf(pMac, eSIR_SME_AP_CAPS_CHANGED,
                                     (tANI_U32 *) &apNewCaps,
diff --git a/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c b/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c
index ba900e8..af77b3d 100644
--- a/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c
@@ -311,6 +311,12 @@
                     PELOGE(limLog(pMac, LOGE, FL("Self Entry missing in Hash Table"));)
 
             }
+
+           if (psessionEntry->fWaitForProbeRsp == true)
+           {
+               limLog(pMac, LOGW, FL("Checking probe response for capability change\n") );
+               limDetectChangeInApCapabilities(pMac, pProbeRsp, psessionEntry);
+           }
         }
         else if ((psessionEntry->limSystemRole == eLIM_STA_IN_IBSS_ROLE) &&
                  (psessionEntry->limMlmState == eLIM_MLM_BSS_STARTED_STATE))
diff --git a/CORE/MAC/src/pe/lim/limSession.c b/CORE/MAC/src/pe/lim/limSession.c
index 808b740..805856c 100644
--- a/CORE/MAC/src/pe/lim/limSession.c
+++ b/CORE/MAC/src/pe/lim/limSession.c
@@ -194,6 +194,8 @@
             palZeroMemory(pMac->hHdd, pMac->lim.gpSession[i].peerAIDBitmap,
                   sizeof(pMac->lim.gpSession[i].peerAIDBitmap));
 #endif
+            pMac->lim.gpSession[i].fWaitForProbeRsp = 0;
+            pMac->lim.gpSession[i].fIgnoreCapsChange = 0;
             return(&pMac->lim.gpSession[i]);
         }
     }