wlan: Add support for VOWIFIMODE driver command

Add support for sending VOWIFIMODE command in the case when
STA is connected to 2.4GHz band.

Change-Id: Ifce7705ebf578f8ce49fff53b7a5df10b3ab3355
CRs-Fixed: 2203715
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index d62ec5e..07e1a34 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -249,6 +249,7 @@
 #endif /* WLAN_FEATURE_RMC */
 void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
 void hdd_set_wlan_suspend_mode(bool suspend);
+void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable);
 
 v_U16_t hdd_select_queue(struct net_device *dev,
     struct sk_buff *skb
@@ -865,6 +866,26 @@
 
     return 0;
 }
+/*
+ * hdd_set_vowifi_mode() - Process the VOWIFI command and invoke the SME api
+ *
+ * @hHal: context handler
+ * @enable: Value to be sent as a part of the VOWIFI command
+ *
+ * Return: void
+ */
+void hdd_set_vowifi_mode(hdd_context_t *hdd_ctx, bool enable)
+{
+    tANI_U8 sta_chan;
+
+    sta_chan = hdd_get_operating_channel(hdd_ctx, WLAN_HDD_INFRA_STATION);
+
+    if (CSR_IS_CHANNEL_24GHZ(sta_chan))
+        sme_set_vowifi_mode(hdd_ctx->hHal, enable);
+    else
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+               "VoWiFi command rejected as not connected in 2.4GHz");
+}
 
 /* Function header left blank Intentionally */
 static int hdd_parse_setrmcrate_command(tANI_U8 *pValue,
@@ -3654,6 +3675,22 @@
 
            ret = sapSetPreferredChannel(ptr);
        }
+
+       else if (strncmp(command, "VOWIFIMODE", 10) == 0)
+       {
+           tANI_U8 *ptr;
+
+           ret = hdd_drv_cmd_validate(command, 10);
+           if (ret)
+               goto exit;
+
+           VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                   "Received Command for VOWIFI mode in %s", __func__);
+
+           ptr = (tANI_U8*)command + 11;
+           hdd_set_vowifi_mode(pHddCtx, *ptr - '0');
+        }
+
        else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
        {
            int suspend = 0;
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index b1bd9c0..5b93620 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -811,6 +811,7 @@
 /* ARP Debug stats */
 #define SIR_HAL_SET_ARP_STATS_REQ          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 303)
 #define SIR_HAL_GET_ARP_STATS_REQ          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 304)
+#define SIR_HAL_VOWIFI_MODE                (SIR_HAL_ITC_MSG_TYPES_BEGIN + 306)
 
 #define SIR_HAL_MSG_TYPES_END              (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 6674053..d253a9f 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -231,6 +231,7 @@
 
 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
 
+void sme_set_vowifi_mode(tpAniSirGlobal pMac, bool enable);
 #ifdef WLAN_FEATURE_EXTSCAN
 /* ---------------------------------------------------------------------------
     \fn sme_GetValidChannelsByBand
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 272a76f..b0de3d8 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -901,6 +901,38 @@
     }
 }
 
+
+/**
+ * sme_set_vowifi_mode() - Set VOWIFI mode
+ * @pMac - context handler
+ * @enable - boolean value that determines the state
+ *
+ * The function sends the VOWIFI to firmware received
+ * via driver command
+ */
+void sme_set_vowifi_mode(tpAniSirGlobal pMac, bool enable)
+{
+    tSirMsgQ msgQ;
+    tSirRetStatus retCode = eSIR_SUCCESS;
+
+    vos_mem_zero(&msgQ, sizeof(tSirMsgQ));
+    msgQ.type = WDA_VOWIFI_MODE;
+    msgQ.reserved = 0;
+    msgQ.bodyval = enable;
+
+    retCode = wdaPostCtrlMsg(pMac, &msgQ);
+    if(eSIR_SUCCESS != retCode)
+    {
+        smsLog(pMac, LOGE,
+           FL("Posting WDA_VOWIFI_MODE to WDA failed, reason=%X"),
+           retCode);
+    }
+    else
+    {
+        smsLog(pMac, LOG1, FL("posted WDA_VOWIFI_MODE command"));
+    }
+}
+
 tANI_BOOLEAN smeProcessCommand( tpAniSirGlobal pMac )
 {
     tANI_BOOLEAN fContinue = eANI_BOOLEAN_FALSE;
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 9a9a765..69a48fd 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1110,6 +1110,7 @@
 #define WDA_EXIT_UAPSD_RSP             SIR_HAL_EXIT_UAPSD_RSP
 #define WDA_LOW_RSSI_IND               SIR_HAL_LOW_RSSI_IND 
 #define WDA_BEACON_FILTER_IND          SIR_HAL_BEACON_FILTER_IND
+#define WDA_VOWIFI_MODE                SIR_HAL_VOWIFI_MODE
 /// PE <-> HAL WOWL messages
 #define WDA_WOWL_ADD_BCAST_PTRN        SIR_HAL_WOWL_ADD_BCAST_PTRN
 #define WDA_WOWL_DEL_BCAST_PTRN        SIR_HAL_WOWL_DEL_BCAST_PTRN
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 33ed775..882dc14 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -12028,6 +12028,28 @@
    }
    return status;
 }
+
+VOS_STATUS WDA_set_vowifi_ind(tWDA_CbContext *pWDA,
+                 tANI_BOOLEAN enable)
+{
+    WDI_Status status;
+
+    VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                   FL("---> %s"), __func__);
+    status = WDI_set_vowifi_mode_ind(enable);
+    if (status == WDI_STATUS_PENDING)
+    {
+       VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                 FL("pending status received "));
+    }
+    else if (status != WDI_STATUS_SUCCESS)
+    {
+       VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+               FL("Failure status %d"), status);
+    }
+    return CONVERT_WDI2VOS_STATUS(status);
+}
+
 /*
  * FUNCTION: WDA_SetRSSIThresholdsRespCallback
  * 
@@ -17058,6 +17080,16 @@
          WDA_SetBeaconFilterReq(pWDA, (tBeaconFilterMsg *)pMsg->bodyptr);
          break;
       }
+
+      case WDA_VOWIFI_MODE :
+      {
+         VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH,
+                           "Handling msg type WDA_VOWIFI_MODE");
+
+         WDA_set_vowifi_ind(pWDA, pMsg->bodyval);
+         break;
+      }
+
       case WDA_BTC_SET_CFG:
       {
          /*TODO: handle this while dealing with BTC */
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index 297fba6..4dae584 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.h
@@ -12292,6 +12292,15 @@
   wpt_uint32 rtsCtsVal
 );
 
+/**
+ * WDI_set_vowifi_mode_ind() - Set VOWIFI mode request
+ *
+ * @enable - boolean value that determines the state
+ *
+ * Return: success if the value is sent
+ */
+WDI_Status WDI_set_vowifi_mode_ind(wpt_boolean enable);
+
 WDI_Status
 WDI_FWLoggingDXEdoneInd
 (
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index 5fb24ba..796a707 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
@@ -573,7 +573,8 @@
 #endif
 
   WDI_SET_AP_FIND_IND = WDI_MAX_REQ + 25,
-  WDI_MAX_UMAC_IND = WDI_MAX_REQ + 26
+  WDI_SET_VOWIFI_IND = WDI_MAX_REQ + 26,
+  WDI_MAX_UMAC_IND = WDI_MAX_REQ + 27,
 
 }WDI_RequestEnumType;
 
@@ -891,8 +892,6 @@
   WDI_CAPTURE_GET_TSF_TSTAMP_RSP                 = 123,
   WDI_FW_ARP_STATS_RSP                           = 124,
   WDI_FW_GET_ARP_STATS_RSP                       = 125,
-
-
   /*-------------------------------------------------------------------------
     Indications
      !! Keep these last in the enum if possible
@@ -1895,6 +1894,21 @@
 
 
 /**
+ * WDI_process_vowifi_request - Sends the vowifi request data to
+ * the firmware when VOWIFI driver command is invoked
+ * @pWDICtx:      pointer to the WLAN DAL context
+ * @pEventData:   pointer to the event information structure
+ *
+ * Return value: status whether the sending is successful or not
+ */
+WDI_Status
+WDI_process_vowifi_request
+(
+  WDI_ControlBlockType*  pWDICtx,
+  WDI_EventInfoType*     pEventData
+);
+
+/**
  @brief Process Finish Scan Request function (called when Main 
         FSM allows it)
  
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index 4b4ebd0..6b7cbeb 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -613,7 +613,11 @@
 #endif
 #ifdef WLAN_FEATURE_APFIND
   WDI_ProcessApFindInd,                 /* WDI_SET_AP_FIND_IND */
+#else
+  NULL,
 #endif
+  WDI_process_vowifi_request,         /* WDI_SET_VOWIFI_IND */
+
 };
 
 
@@ -8988,6 +8992,65 @@
 }/*WDI_ProcessStartScanReq*/
 
 
+WDI_Status
+WDI_process_vowifi_request(WDI_ControlBlockType* pWDICtx,
+                                                WDI_EventInfoType* pEventData)
+{
+  wpt_uint8* pSendBuffer = NULL;
+  wpt_uint16 usDataOffset = 0;
+  wpt_uint16 usSendSize = 0;
+  wpt_boolean *enable;
+  tHalVoWiFiInd hal_vowifi_msg;
+  WDI_Status wdiStatus;
+
+  /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+  WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+               "%s", __func__);
+
+  /*-------------------------------------------------------------------------
+    Sanity check
+  -------------------------------------------------------------------------*/
+  if (( NULL == pEventData ) || ( NULL == pEventData->pEventData ) ) {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL,
+             "%s: Invalid parameters", __func__);
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+  }
+  enable = (wpt_boolean*)pEventData->pEventData;
+
+  /*-----------------------------------------------------------------------
+    Get message buffer
+  -----------------------------------------------------------------------*/
+  if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx,
+                                     WDI_SET_VOWIFI_IND,
+                                      sizeof(tHalVoWiFiIndParams),
+                          &pSendBuffer, &usDataOffset, &usSendSize))||
+       ( usSendSize < (usDataOffset + sizeof(tHalVoWiFiIndParams) )))
+  {
+      WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL,
+              "Unable to get send buffer VOWIFI ind %pK ",
+               pEventData);
+      WDI_ASSERT(0);
+      return WDI_STATUS_E_FAILURE;
+  }
+
+  hal_vowifi_msg.voWiFiIndParams.enable = *enable;
+
+  wpalMemoryCopy( pSendBuffer+usDataOffset,
+                  &hal_vowifi_msg.voWiFiIndParams,
+                  sizeof(hal_vowifi_msg.voWiFiIndParams));
+
+  pWDICtx->pReqStatusUserData = NULL;
+  pWDICtx->pfncRspCB = NULL;
+
+  /*-------------------------------------------------------------------------
+    Send VOWIFI mode Request to HAL
+  -------------------------------------------------------------------------*/
+  wdiStatus =  WDI_SendIndication(pWDICtx, pSendBuffer, usSendSize);
+  return (wdiStatus != WDI_STATUS_SUCCESS) ? wdiStatus:WDI_STATUS_SUCCESS_SYNC;
+}
+
 /**
  @brief Process End Scan Request function (called when Main FSM
         allows it)
@@ -11478,6 +11541,33 @@
 }/*WDI_ProcessUpdateEDCAParamsReq*/
 
 /**
+ * WDI_set_vowifi_mode_ind() - Set VOWIFI mode request
+ *
+ * @enable - boolean value that determins the state
+ *
+ * Return value: status whether the post is successful or not
+ */
+WDI_Status WDI_set_vowifi_mode_ind(wpt_boolean enable)
+{
+    WDI_EventInfoType wdiEventData;
+
+    if (eWLAN_PAL_FALSE == gWDIInitialized )
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                 "WDI API call before module is initialized - Fail request");
+        return WDI_STATUS_E_NOT_ALLOWED;
+    }
+
+    wdiEventData.wdiRequest      = WDI_SET_VOWIFI_IND;
+    wdiEventData.pEventData      = (void *) &enable;
+    wdiEventData.uEventDataSize  = sizeof(wpt_boolean);
+    wdiEventData.pCBfnc          = NULL;
+    wdiEventData.pUserData       = NULL;
+
+    return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+/**
  @brief Process Add BA Request function (called when Main FSM
         allows it)
 
@@ -25145,6 +25235,8 @@
        return WLAN_HAL_NAN_REQ;
   case WDI_SET_RTS_CTS_HTVHT_IND:
        return WLAN_HAL_SET_RTS_CTS_HTVHT_IND;
+  case WDI_SET_VOWIFI_IND:
+       return WLAN_HAL_VOWIFI_IND;
   case WDI_MON_START_REQ:
        return WLAN_HAL_ENABLE_MONITOR_MODE_REQ;
   case WDI_MON_STOP_REQ: