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/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index d74a8de..aab14e1 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -174,6 +174,8 @@
#define TID_MAX_VALUE 15
static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
tAniTrafStrmMetrics* pTsmMetrics);
+static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
+ tCsrCcxBeaconReq *pCcxBcnReq);
#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
/*
@@ -3589,7 +3591,7 @@
/* Output TSM stats is of the format
GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
- len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %lu %d %d %d %d", command,
+ len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
@@ -3638,6 +3640,22 @@
vos_mem_free(cckmIe);
}
}
+ else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
+ {
+ tANI_U8 *value = command;
+ tCsrCcxBeaconReq ccxBcnReq;
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
+ if (eHAL_STATUS_SUCCESS != status)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Failed to parse ccx beacon req", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
+ }
#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
else {
hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
@@ -3656,6 +3674,145 @@
#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
+/**---------------------------------------------------------------------------
+
+ \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
+
+ This function parses the ccx beacon request passed in the format
+ CCXBEACONREQ<space><Number of fields><space><Measurement token>
+ <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
+ <space>Scan Mode N<space>Meas Duration N
+ if the Number of bcn req fields (N) does not match with the actual number of fields passed
+ then take N.
+ <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
+ For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
+ This function does not take care of removing duplicate channels from the list
+
+ \param - pValue Pointer to data
+ \param - pCcxBcnReq output pointer to store parsed ie information
+
+ \return - 0 for success non-zero for failure
+
+ --------------------------------------------------------------------------*/
+static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
+ tCsrCcxBeaconReq *pCcxBcnReq)
+{
+ tANI_U8 *inPtr = pValue;
+ int tempInt = 0;
+ int j = 0, i = 0, v = 0;
+ char buf[32];
+
+ inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
+ /*no argument after the command*/
+ if (NULL == inPtr)
+ {
+ return -EINVAL;
+ }
+ /*no space after the command*/
+ else if (SPACE_ASCII_VALUE != *inPtr)
+ {
+ return -EINVAL;
+ }
+
+ /*removing empty spaces*/
+ while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
+
+ /*no argument followed by spaces*/
+ if ('\0' == *inPtr) return -EINVAL;
+
+ /*getting the first argument ie measurement token*/
+ v = sscanf(inPtr, "%32s ", buf);
+ if (1 != v) return -EINVAL;
+
+ v = kstrtos32(buf, 10, &tempInt);
+ if ( v < 0) return -EINVAL;
+
+ pCcxBcnReq->numBcnReqIe = tempInt;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
+ "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
+
+ for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ /*inPtr pointing to the beginning of first space after number of ie fields*/
+ inPtr = strpbrk( inPtr, " " );
+ /*no ie data after the number of ie fields argument*/
+ if (NULL == inPtr) return -EINVAL;
+
+ /*removing empty space*/
+ while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
+
+ /*no ie data after the number of ie fields argument and spaces*/
+ if ( '\0' == *inPtr ) return -EINVAL;
+
+ v = sscanf(inPtr, "%32s ", buf);
+ if (1 != v) return -EINVAL;
+
+ v = kstrtos32(buf, 10, &tempInt);
+ if (v < 0) return -EINVAL;
+
+ switch (i)
+ {
+ case 0: /* Measurement token */
+ if (tempInt <= 0)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid Measurement Token(%d)", tempInt);
+ return -EINVAL;
+ }
+ pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
+ break;
+
+ case 1: /* Channel number */
+ if ((tempInt <= 0) ||
+ (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid Channel Number(%d)", tempInt);
+ return -EINVAL;
+ }
+ pCcxBcnReq->bcnReq[j].channel = tempInt;
+ break;
+
+ case 2: /* Scan mode */
+ if ((tempInt < 0) || (tempInt > 2))
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
+ return -EINVAL;
+ }
+ pCcxBcnReq->bcnReq[j].scanMode= tempInt;
+ break;
+
+ case 3: /* Measurement duration */
+ if (tempInt <= 0)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "Invalid Measurement Duration(%d)", tempInt);
+ return -EINVAL;
+ }
+ pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
+ break;
+ }
+ }
+ }
+
+ for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
+ j,
+ pCcxBcnReq->bcnReq[j].measurementToken,
+ pCcxBcnReq->bcnReq[j].channel,
+ pCcxBcnReq->bcnReq[j].scanMode,
+ pCcxBcnReq->bcnReq[j].measurementDuration);
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
{
struct statsContext *pStatsContext = NULL;