wlan: ccx upload: Support ccx beacon report

This is to provide support for CCX radio measument beacon report.
Summary of changes include:
1. Support for CCXBEACONREQ device private command to receive
   measurement request IE information.
2. Driver initiates scan and return the BSSID information using
   IWEVCUSTOM event supporting 4 BSSID info per channel.
3. Fix for scan type and duration getting over-written with the
   last channel scan type and duration.
4. IWEVCUSTOM has limitation of 256 bytes of event data, hence fill-in
   only the mandatory IEs in the beacon report as per the spec.

Change-Id: If0324b1732ea537f64a48c22c5e702c49356504e
CRs-Fixed: 573479
diff --git a/CORE/SME/src/rrm/sme_rrm.c b/CORE/SME/src/rrm/sme_rrm.c
index 66c99f3..3f25ce7 100644
--- a/CORE/SME/src/rrm/sme_rrm.c
+++ b/CORE/SME/src/rrm/sme_rrm.c
@@ -229,7 +229,6 @@
        pBeaconRep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND;
        pBeaconRep->length = length;
        pBeaconRep->uDialogToken = pSmeRrmContext->token;
-       pBeaconRep->duration = pSmeRrmContext->duration;
        pBeaconRep->regClass = pSmeRrmContext->regClass;
        vos_mem_copy( pBeaconRep->bssId, pSmeRrmContext->sessionBssId, sizeof(tSirMacAddr) );
 
@@ -257,7 +256,7 @@
 
                pBeaconRep->numBssDesc++;
 
-               if (++msgCounter >= SIR_BCN_REPORT_MAX_BSS_DESC_PER_ACTION_FRAME)
+               if (++msgCounter >= SIR_BCN_REPORT_MAX_BSS_DESC)
                    break;
 
                pCurResult = pResultArr[bssCounter + msgCounter];
@@ -296,6 +295,156 @@
    return status;
 }
 
+#if defined(FEATURE_WLAN_CCX_UPLOAD)
+/**---------------------------------------------------------------------------
+
+  \brief sme_CcxSendBeaconReqScanResults()
+
+   This function sends up the scan results received as a part of
+   beacon request scanning.
+   This function is called after receiving the scan results per channel
+   Due to the limitation on the size of the IWEVCUSTOM buffer, we send 3 BSSIDs of
+   beacon report information in one custom event;
+
+  \param  - pMac -      Pointer to the Hal Handle.
+              - sessionId  - Session id
+              - channel     - scan results belongs to this channel
+              - pResultArr - scan result.
+              - measurementDone - flag to indicate that the measurement is done.
+              - bss_count - number of bss found
+  \return - 0 for success, non zero for failure
+
+  --------------------------------------------------------------------------*/
+static eHalStatus sme_CcxSendBeaconReqScanResults(tpAniSirGlobal pMac,
+                                                  tANI_U32       sessionId,
+                                                  tANI_U8        channel,
+                                                  tCsrScanResultInfo **pResultArr,
+                                                  tANI_U8        measurementDone,
+                                                  tANI_U8        bss_count)
+{
+   eHalStatus              status         = eHAL_STATUS_FAILURE;
+   tpSirBssDescription     pBssDesc       = NULL;
+   tANI_U32                ie_len         = 0;
+   tANI_U32                outIeLen       = 0;
+   tANI_U8                 bssCounter     = 0;
+   tCsrScanResultInfo     *pCurResult     = NULL;
+   tANI_U8                 msgCounter     = 0;
+   tpRrmSMEContext         pSmeRrmContext = &pMac->rrm.rrmSmeContext;
+   tCsrRoamInfo            roamInfo;
+   tSirCcxBcnReportRsp     bcnReport;
+   tpSirCcxBcnReportRsp    pBcnReport     = &bcnReport;
+   tpCsrCcxBeaconReqParams pCurMeasReqIe  = NULL;
+   tANI_U8                 i              = 0;
+
+   if (NULL == pSmeRrmContext)
+   {
+       smsLog( pMac, LOGE, "pSmeRrmContext is NULL");
+       return eHAL_STATUS_FAILURE;
+   }
+
+   if (NULL == pResultArr && !measurementDone)
+   {
+      smsLog( pMac, LOGE, "Beacon report xmit Ind to HDD Failed");
+      return eHAL_STATUS_FAILURE;
+   }
+
+   if (pResultArr)
+       pCurResult=pResultArr[bssCounter];
+
+   vos_mem_zero(&bcnReport, sizeof(tSirCcxBcnReportRsp));
+   do
+   {
+       pCurMeasReqIe = NULL;
+       for (i = 0; i < pSmeRrmContext->ccxBcnReqInfo.numBcnReqIe; i++)
+       {
+           if(pSmeRrmContext->ccxBcnReqInfo.bcnReq[i].channel == channel)
+           {
+               pCurMeasReqIe = &pSmeRrmContext->ccxBcnReqInfo.bcnReq[i];
+               break;
+           }
+       }
+       pBcnReport->measurementToken = pCurMeasReqIe->measurementToken;
+       smsLog( pMac, LOG1, "Channel(%d) MeasToken(%d)", channel, pBcnReport->measurementToken);
+
+       msgCounter=0;
+       while (pCurResult)
+       {
+           pBssDesc = &pCurResult->BssDescriptor;
+           if (NULL != pBssDesc)
+           {
+               ie_len = GET_IE_LEN_IN_BSS( pBssDesc->length );
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.ChanNum = pBssDesc->channelId;
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.Spare = 0;
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.MeasDuration = pCurMeasReqIe->measurementDuration;
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.PhyType = pBssDesc->nwType;
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.RecvSigPower = pBssDesc->rssi;
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.ParentTsf = pBssDesc->parentTSF;
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.TargetTsf[0] = pBssDesc->timeStamp[0];
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.TargetTsf[1] = pBssDesc->timeStamp[1];
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.BcnInterval = pBssDesc->beaconInterval;
+               pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.CapabilityInfo = pBssDesc->capabilityInfo;
+               vos_mem_copy(pBcnReport->bcnRepBssInfo[msgCounter].bcnReportFields.Bssid,
+                                      pBssDesc->bssId, sizeof(tSirMacAddr));
+
+               sirFillBeaconMandatoryIEforCcxBcnReport(pMac, (tANI_U8 *)pBssDesc->ieFields, ie_len,
+                                           &(pBcnReport->bcnRepBssInfo[msgCounter].pBuf), &outIeLen);
+               pBcnReport->bcnRepBssInfo[msgCounter].ieLen = outIeLen;
+
+               smsLog( pMac, LOG1,"Bssid(%02X:%02X:%02X:%02X:%02X:%02X) Channel=%d Rssi=%d",
+                       pBssDesc->bssId[0], pBssDesc->bssId[1], pBssDesc->bssId[2],
+                       pBssDesc->bssId[3], pBssDesc->bssId[4], pBssDesc->bssId[5],
+                       pBssDesc->channelId, (-1) * pBssDesc->rssi);
+
+               pBcnReport->numBss++;
+
+               if (++msgCounter >= SIR_BCN_REPORT_MAX_BSS_DESC)
+                   break;
+
+               pCurResult = pResultArr[msgCounter];
+           }
+           else
+           {
+               pCurResult = NULL;
+               break;
+           }
+       }
+
+       bssCounter += msgCounter;
+       if (!pResultArr || !pCurResult || (bssCounter >= SIR_BCN_REPORT_MAX_BSS_DESC))
+       {
+           pCurResult = NULL;
+           smsLog(pMac, LOGE,
+                  "Reached to the max/last BSS in pCurResult list");
+       }
+       else
+       {
+           pCurResult = pResultArr[bssCounter];
+           smsLog(pMac, LOGE,
+                  "Move to the next BSS set in pCurResult list");
+       }
+
+       pBcnReport->flag = (measurementDone << 1)|((pCurResult)?true:false);
+
+       smsLog(pMac, LOG1, "SME Sending BcnRep to HDD numBss(%d)"
+               " msgCounter(%d) bssCounter(%d)",
+                pBcnReport->numBss, msgCounter, bssCounter, pBcnReport->flag);
+
+       roamInfo.pCcxBcnReportRsp = pBcnReport;
+       csrRoamCallCallback(pMac, sessionId, &roamInfo,
+                           0, eCSR_ROAM_CCX_BCN_REPORT_IND, 0);
+
+       /* Free the memory allocated to IE */
+       for (i = 0; i < msgCounter; i++)
+       {
+           if (pBcnReport->bcnRepBssInfo[i].pBuf)
+               vos_mem_free(pBcnReport->bcnRepBssInfo[i].pBuf);
+       }
+   } while (pCurResult);
+   return status;
+}
+
+#endif /* FEATURE_WLAN_CCX_UPLOAD */
+
 /**---------------------------------------------------------------------------
   
   \brief sme_RrmSendScanRequest() - 
@@ -318,7 +467,7 @@
    tCsrScanResultFilter filter;
    tScanResultHandle pResult;
    tCsrScanResultInfo *pScanResult, *pNextResult;
-   tCsrScanResultInfo *pScanResultsArr[SIR_BCN_REPORT_MAX_BSS_PER_CHANNEL];
+   tCsrScanResultInfo *pScanResultsArr[SIR_BCN_REPORT_MAX_BSS_DESC];
    eHalStatus status;
    tANI_U8 counter=0;
    tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
@@ -329,7 +478,7 @@
 #endif
 
    vos_mem_zero( &filter, sizeof(filter) );
-   vos_mem_zero( pScanResultsArr, sizeof(pNextResult)*SIR_BCN_REPORT_MAX_BSS_PER_CHANNEL );
+   vos_mem_zero( pScanResultsArr, sizeof(pNextResult)*SIR_BCN_REPORT_MAX_BSS_DESC );
 
    filter.BSSIDs.numOfBSSIDs = 1;
    filter.BSSIDs.bssid = &pSmeRrmContext->bssId;
@@ -387,7 +536,18 @@
       // send a xmit indication with moreToFollow set to MEASURMENT_DONE
       // so that PE can clean any context allocated.
       if( measurementDone )
-         status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone, 0 );
+      {
+#if defined(FEATURE_WLAN_CCX_UPLOAD)
+         status = sme_CcxSendBeaconReqScanResults(pMac,
+                                                  sessionId,
+                                                  chanList[0],
+                                                  NULL,
+                                                  measurementDone,
+                                                  0);
+#else
+         status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone, 0);
+#endif /*FEATURE_WLAN_CCX_UPLOAD*/
+      }
       return status;
    }
 
@@ -402,18 +562,26 @@
       pNextResult = sme_ScanResultGetNext(pMac, pResult);
       pScanResultsArr[counter++] = pScanResult;
       pScanResult = pNextResult; //sme_ScanResultGetNext(hHal, pResult);
-      if (counter >= SIR_BCN_REPORT_MAX_BSS_PER_CHANNEL)
+      if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC)
          break;
       }
 
    if (counter)
    {
+          smsLog(pMac, LOG1, " Number of BSS Desc with RRM Scan %d ", counter);
+#if defined(FEATURE_WLAN_CCX_UPLOAD)
+       status = sme_CcxSendBeaconReqScanResults(pMac,
+                                                sessionId,
+                                                chanList[0],
+                                                pScanResultsArr,
+                                                measurementDone,
+                                                counter);
+#else
        status = sme_RrmSendBeaconReportXmitInd( pMac,
                                                 pScanResultsArr,
                                                 measurementDone,
                                                 counter);
-       smsLog(pMac, LOG1, " Number of BSS Desc with RRM Scan %d ",
-              counter);
+#endif /*FEATURE_WLAN_CCX_UPLOAD*/
    }
    sme_ScanResultPurge(pMac, pResult); 
 
@@ -485,7 +653,7 @@
   \brief sme_RrmIssueScanReq() - This is called to send a scan request as part 
          of beacon report request .
   
-  \param 
+  \param  pMac  - pMac global pointer
   
   \return eHAL_STATUS_SUCCESS - Validation is successful.
   
@@ -500,67 +668,101 @@
    eHalStatus status = eHAL_STATUS_SUCCESS;
    tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
    tANI_U32 sessionId;
+   tSirScanType scanType;
 
+   if ((pSmeRrmContext->currentIndex) >= pSmeRrmContext->channelList.numOfChannels)
+       return status;
+
+   scanType = pSmeRrmContext->measMode[pSmeRrmContext->currentIndex];
+   if ((eSIR_ACTIVE_SCAN == scanType) || (eSIR_PASSIVE_SCAN == scanType))
+   {
 #if defined WLAN_VOWIFI_DEBUG
    smsLog( pMac, LOGE, "Issue scan request " );
 #endif
 
-   vos_mem_zero( &scanRequest, sizeof(scanRequest));
+       vos_mem_zero( &scanRequest, sizeof(scanRequest));
 
-   /* set scanType, active or passive */
-   scanRequest.bcnRptReqScan = TRUE;
-   scanRequest.scanType = pSmeRrmContext->measMode;
+       /* set scanType, active or passive */
+       scanRequest.bcnRptReqScan = TRUE;
+       scanRequest.scanType = scanType;
 
-   vos_mem_copy(scanRequest.bssid,
-         pSmeRrmContext->bssId, sizeof(scanRequest.bssid) );
+       vos_mem_copy(scanRequest.bssid,
+             pSmeRrmContext->bssId, sizeof(scanRequest.bssid) );
 
-   if( pSmeRrmContext->ssId.length )
-   {
-      scanRequest.SSIDs.numOfSSIDs = 1;
-      scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
-      if( scanRequest.SSIDs.SSIDList == NULL )
-      {
-         smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
-         return eHAL_STATUS_FAILURE;
-      }
+       if (pSmeRrmContext->ssId.length)
+       {
+          scanRequest.SSIDs.numOfSSIDs = 1;
+          scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
+          if (NULL == scanRequest.SSIDs.SSIDList)
+          {
+              smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
+              return eHAL_STATUS_FAILURE;
+          }
 #if defined WLAN_VOWIFI_DEBUG
-      smsLog( pMac, LOGE, FL("Allocated memory for pSSIDList"));
+          smsLog( pMac, LOGE, FL("Allocated memory for pSSIDList"));
 #endif
-      vos_mem_zero( scanRequest.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) );
-      scanRequest.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length;
-      vos_mem_copy(scanRequest.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length);
+          vos_mem_zero( scanRequest.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) );
+          scanRequest.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length;
+          vos_mem_copy(scanRequest.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length);
+       }
+
+       /* set min and max channel time */
+       scanRequest.minChnTime = 0; //pSmeRrmContext->duration; Dont use min timeout.
+       scanRequest.maxChnTime = pSmeRrmContext->duration[pSmeRrmContext->currentIndex];
+       smsLog( pMac, LOG1, "Scan Type(%d) Max Dwell Time(%d)", scanRequest.scanType,
+                  scanRequest.maxChnTime );
+
+#if defined WLAN_VOWIFI_DEBUG
+       smsLog( pMac, LOGE, "For Duration %d ", scanRequest.maxChnTime );
+#endif
+
+       /* set BSSType to default type */
+       scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
+
+       /*Scan all the channels */
+       scanRequest.ChannelInfo.numOfChannels = 1;
+
+       scanRequest.ChannelInfo.ChannelList = &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex];
+#if defined WLAN_VOWIFI_DEBUG
+       smsLog( pMac, LOGE, "On channel %d ", pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex] );
+#endif
+
+       /* set requestType to full scan */
+       scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
+
+       csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid*)pSmeRrmContext->sessionBssId, &sessionId );
+       status = sme_ScanRequest( pMac, (tANI_U8)sessionId, &scanRequest, &scanId, &sme_RrmScanRequestCallback, NULL );
+
+       if ( pSmeRrmContext->ssId.length )
+       {
+           vos_mem_free(scanRequest.SSIDs.SSIDList);
+#if defined WLAN_VOWIFI_DEBUG
+           smsLog( pMac, LOGE, FL("Free memory for SSIDList"));
+#endif
+       }
    }
-
-   /* set min and max channel time */
-   scanRequest.minChnTime = 0; //pSmeRrmContext->duration; Dont use min timeout.
-   scanRequest.maxChnTime = pSmeRrmContext->duration;
-#if defined WLAN_VOWIFI_DEBUG
-   smsLog( pMac, LOGE, "For Duration %d ", pSmeRrmContext->duration );
-#endif
-
-   /* set BSSType to default type */
-   scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
-
-   /*Scan all the channels */
-   scanRequest.ChannelInfo.numOfChannels = 1;
-
-   scanRequest.ChannelInfo.ChannelList = &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex];
-#if defined WLAN_VOWIFI_DEBUG
-   smsLog( pMac, LOGE, "On channel %d ", pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex] );
-#endif
-
-   /* set requestType to full scan */
-   scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
-
-   csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid*)pSmeRrmContext->sessionBssId, &sessionId );
-   status = sme_ScanRequest( pMac, (tANI_U8)sessionId, &scanRequest, &scanId, &sme_RrmScanRequestCallback, NULL ); 
-
-   if ( pSmeRrmContext->ssId.length )
+   else if (2 == scanType)  /* beacon table */
    {
-      vos_mem_free(scanRequest.SSIDs.SSIDList);
-#if defined WLAN_VOWIFI_DEBUG
-      smsLog( pMac, LOGE, FL("Free memory for SSIDList"));
-#endif
+       if ((pSmeRrmContext->currentIndex + 1) < pSmeRrmContext->channelList.numOfChannels)
+       {
+           sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], false );
+           pSmeRrmContext->currentIndex++; //Advance the current index.
+           sme_RrmIssueScanReq(pMac);
+       }
+       else
+       {
+           //Done with the measurement. Clean up all context and send a message to PE with measurement done flag set.
+           sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], true );
+           vos_mem_free( pSmeRrmContext->channelList.ChannelList );
+       }
+   }
+   else
+   {
+       smsLog( pMac, LOGE, "Unknown beacon report request mode(%d)", scanType);
+                /* Indicate measurement completion to PE */
+                /* If this is not done, pCurrentReq pointer will not be freed and
+                   PE will not handle subsequent Beacon requests */
+        sme_RrmSendBeaconReportXmitInd(pMac, NULL, true, 0);
    }
 
    return status;
@@ -583,7 +785,7 @@
 {
    tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf;
    tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
-   tANI_U32 len,i;  
+   tANI_U32 len = 0, i = 0;
 
 #if defined WLAN_VOWIFI_DEBUG
    smsLog( pMac, LOGE, "Received Beacon report request ind Channel = %d", pBeaconReq->channelInfo.channelNum );
@@ -615,7 +817,7 @@
       len = 0;
       pSmeRrmContext->channelList.numOfChannels = 0;
 
-      //If valid channel is present. We firt Measure on the given channel. and
+      //If valid channel is present. We first Measure on the given channel. and
       //if there are additional channels present in APchannelreport, measure on these also.
       if ( pBeaconReq->channelInfo.channelNum != 255 )
          len = 1;
@@ -670,42 +872,12 @@
 
    pSmeRrmContext->token = pBeaconReq->uDialogToken;
    pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass;
-
-   switch( pBeaconReq->fMeasurementtype )
-   {
-      case 0: //Passive
-      case 1: //Active
-         pSmeRrmContext->measMode = pBeaconReq->fMeasurementtype? eSIR_ACTIVE_SCAN : eSIR_PASSIVE_SCAN ;
-         pSmeRrmContext->duration = pBeaconReq->measurementDuration;
          pSmeRrmContext->randnIntvl = VOS_MAX( pBeaconReq->randomizationInterval, pSmeRrmContext->rrmConfig.maxRandnInterval );
          pSmeRrmContext->currentIndex = 0;
-#if defined WLAN_VOWIFI_DEBUG
-         smsLog( pMac, LOGE, "Send beacon report after scan " );
-#endif
-         sme_RrmIssueScanReq( pMac ); 
-         break;
-      case 2: //Table
-         //Get the current scan results for the given channel and send it.
-#if defined WLAN_VOWIFI_DEBUG
-         smsLog( pMac, LOGE, "Send beacon report from table " );
-#endif
-         sme_RrmSendScanResult( pMac, pSmeRrmContext->channelList.numOfChannels, pSmeRrmContext->channelList.ChannelList, true );
-         vos_mem_free( pSmeRrmContext->channelList.ChannelList );
-#if defined WLAN_VOWIFI_DEBUG
-         smsLog( pMac, LOGE, FL("Free memory for ChannelList") );
-#endif
-         break;
-      default:
-#if defined WLAN_VOWIFI_DEBUG
-         smsLog( pMac, LOGE, "Unknown beacon report request mode");
-#endif
-         /* Indicate measurement completion to PE */
-         /* If this is not done, pCurrentReq pointer will not be freed and 
-            PE will not handle subsequent Beacon requests */
-         sme_RrmSendBeaconReportXmitInd(pMac, NULL, true, 0);
-         break;
+   vos_mem_copy((tANI_U8*)&pSmeRrmContext->measMode, (tANI_U8*)&pBeaconReq->fMeasurementtype, SIR_CCX_MAX_MEAS_IE_REQS);
+   vos_mem_copy((tANI_U8*)&pSmeRrmContext->duration, (tANI_U8*)&pBeaconReq->measurementDuration, SIR_CCX_MAX_MEAS_IE_REQS);
 
-   }
+   sme_RrmIssueScanReq( pMac );
 
    return;
 }