P2P: Send P2P Marker Frame on air to debug ROC issues.

Debug Marker frames are sent over air at start and end of remain on
channel. These marker frames helps in debugging scan and connection
issues by indicating DUT remained on channel or not.

Data in vendor specific information element indicates the start and
end of DUT's remain on channel. The data contains channel number,
duration and sequence number. Two sets of Marker frames are sent on
each start and end of remain on channel to make sure any of these
frames are captured in the sniffer.

Example:-
If DUT starts remain on channel on channel 6 for duration 200ms and
sequence number of debug marker frame is 15 then the contents of
vendor specific information element and sequence of marker frames
are as below,
START-REMAIN-ON-CHANNEL1-CHN=6-FOR-DUR=200-SEQ=15
START-REMAIN-ON-CHANNEL2-CHN=6-FOR-DUR=200-SEQ=15

And at end of remain on channel message will be as
CANCEL-REMAIN-ON-CHANNEL1-SEQ=15
CANCEL-REMAIN-ON-CHANNEL2-SEQ=15

Change-Id: I4f6e62c90d36ba2897038d4960e0652dad88e21a
CRs-Fixed: 594906
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index ac91b2f..f0f713c 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -927,6 +927,14 @@
     tANI_U8 gLimIbssStaLimit;
     tANI_U8 probeCounter;
     tANI_U8 maxProbe;
+
+    // Flag to debug remain on channel
+    tANI_BOOLEAN gDebugP2pRemainOnChannel;
+    /* Sequence number to keep track of
+     * start and end of remain on channel
+     * debug marker frame.
+     */
+    tANI_U32 remOnChnSeqNum;
 } tAniSirLim, *tpAniSirLim;
 
 typedef struct sLimMgmtFrameRegistration
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index f75c100..433bedd 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -465,6 +465,15 @@
     tANI_U8  probeRspIe[1];
 }tSirRemainOnChnReq, *tpSirRemainOnChnReq;
 
+/* Structure for vendor specific IE of debug marker frame
+   to debug remain on channel issues */
+typedef struct publicVendorSpecific
+{
+    tANI_U8 category;
+    tANI_U8 elementid;
+    tANI_U8 length;
+} publicVendorSpecific;
+
 typedef struct sSirRegisterMgmtFrame
 {
     tANI_U16 messageType;
diff --git a/CORE/MAC/src/pe/lim/limP2P.c b/CORE/MAC/src/pe/lim/limP2P.c
index e226d74..d31d5c7 100644
--- a/CORE/MAC/src/pe/lim/limP2P.c
+++ b/CORE/MAC/src/pe/lim/limP2P.c
@@ -83,7 +83,11 @@
    received Beacon/Prpbe Resp. */
 #define   MAX_TIME_TO_BE_ACTIVE_CHANNEL 9000
 
-
+#define REMAIN_ON_CHANNEL_UNKNOWN_ACTION_CATEGORY    0x20
+#define VENDOR_SPECIFIC_ELEMENT_ID                   221
+#define REMAIN_ON_CHANNEL_MSG_SIZE                   55
+#define REMAIN_ON_CHANNEL_FIRST_MARKER_FRAME         1
+#define REMAIN_ON_CHANNEL_SECOND_MARKER_FRAME        2
 
 void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status,
                                        tANI_U32 *data);
@@ -99,6 +103,179 @@
 
 static tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession);
 eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess);
+
+/*----------------------------------------------------------------------------
+ *
+ * The function limSendRemainOnChannelDebugMarkerFrame, prepares Marker frame
+ * for Start and End of remain on channel with RemainOnChannelMsg as Vendor
+ * Specific information element of the frame.
+ *
+ *----------------------------------------------------------------------------*/
+tSirRetStatus limSendRemainOnChannelDebugMarkerFrame(tpAniSirGlobal pMac,
+                                                     tANI_U8 *remainOnChannelMsg)
+{
+    tSirMacAddr          magicMacAddr= {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+    tANI_U32             nBytes, nPayload;
+    tSirRetStatus        nSirStatus;
+    tANI_U8              *pFrame;
+    void                 *pPacket;
+    eHalStatus           halstatus;
+    tANI_U8              txFlag = 0;
+    publicVendorSpecific *pPublicVendorSpecific;
+
+    pPublicVendorSpecific = vos_mem_malloc(sizeof(publicVendorSpecific));
+    if( pPublicVendorSpecific == NULL )
+    {
+        limLog( pMac, LOGE,
+                FL( "Unable to allocate memory for Vendor specific information"
+                    " element" ) );
+        return eSIR_MEM_ALLOC_FAILED;
+    }
+    // Assigning Action category code as unknown as this is debug marker frame
+    pPublicVendorSpecific->category = REMAIN_ON_CHANNEL_UNKNOWN_ACTION_CATEGORY;
+    pPublicVendorSpecific->elementid = VENDOR_SPECIFIC_ELEMENT_ID;
+    pPublicVendorSpecific->length = strlen(remainOnChannelMsg);
+
+    nPayload = sizeof(publicVendorSpecific) + pPublicVendorSpecific->length;
+
+    nBytes = nPayload + sizeof( tSirMacMgmtHdr );
+
+    halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+                             ( tANI_U16 )nBytes, ( void** ) &pFrame,
+                             ( void** ) &pPacket );
+    if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+    {
+        limLog( pMac, LOGE, FL("Failed to allocate %d bytes for a Remain"
+                               " on channel action frame."), nBytes );
+        nSirStatus = eSIR_MEM_ALLOC_FAILED;
+        goto end;
+    }
+    vos_mem_zero( pFrame, nBytes );
+
+    // Populate frame with MAC header
+    nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
+                                SIR_MAC_MGMT_ACTION, magicMacAddr,
+                                pMac->lim.gSelfMacAddr);
+    if ( eSIR_SUCCESS != nSirStatus )
+    {
+        limLog( pMac, LOGE, FL("Failed to populate the buffer descriptor for a"
+                               " Action frame for remain on channel.") );
+        palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+                    ( void* ) pFrame, ( void* ) pPacket );
+        goto end;
+    }
+
+    // Copy Public Vendor specific fields to frame's information element
+    vos_mem_copy( (pFrame + (sizeof( tSirMacMgmtHdr ))),
+                   pPublicVendorSpecific, sizeof(publicVendorSpecific) );
+    // Copy Remain On channel message to Vendor Specific information field
+    vos_mem_copy( (pFrame + (nBytes - pPublicVendorSpecific->length)),
+                   remainOnChannelMsg, pPublicVendorSpecific->length );
+
+    halstatus = halTxFrame( pMac, pPacket,
+                            ( tANI_U16 ) sizeof(tSirMacMgmtHdr) + nPayload,
+                            HAL_TXRX_FRM_802_11_MGMT,
+                            ANI_TXDIR_TODS,
+                            7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
+                            limTxComplete, pFrame, txFlag );
+    if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+    {
+        limLog( pMac, LOGE, FL("could not send marker frame for"
+                               " remain on channel!" ));
+        //Pkt will be freed up by the callback
+        nSirStatus = eSIR_FAILURE;
+        goto end;
+    }
+
+    nSirStatus = eSIR_SUCCESS;
+
+end:
+    vos_mem_free( pPublicVendorSpecific );
+    return nSirStatus;
+}
+
+/*-------------------------------------------------------------------------
+ *
+ * This function forms message for start of remain on channel with channel
+ * number, duration and sequence number. This message is added as data of
+ * vendor specific information element of Debug Marker Frame. Message will
+ * be in form "START-REMAIN-ON-CHANNEL<first/second-frame>-CHN=<channel>"
+ * "-FOR-DUR=<duraion>-SEQ=<sequence-num>"
+ *
+ *-------------------------------------------------------------------------*/
+eHalStatus limPrepareAndSendStartRemainOnChannelMsg(tpAniSirGlobal pMac,
+                      tSirRemainOnChnReq *MsgRemainonChannel, tANI_U8 id)
+{
+    tANI_U8 *startRemainOnChannelMsg;
+    eHalStatus status = eHAL_STATUS_SUCCESS;
+
+    startRemainOnChannelMsg = vos_mem_malloc( REMAIN_ON_CHANNEL_MSG_SIZE );
+    if( NULL == startRemainOnChannelMsg )
+    {
+        limLog(pMac, LOGE,
+                FL("Unable to allocate memory for remain on channel message"));
+        return eHAL_STATUS_FAILURE;
+    }
+
+    snprintf(startRemainOnChannelMsg, REMAIN_ON_CHANNEL_MSG_SIZE,
+            "START-REMAIN-ON-CHANNEL%d-CHN=%d-FOR-DUR=%d-SEQ=%d",
+            id, MsgRemainonChannel->chnNum, MsgRemainonChannel->duration,
+            pMac->lim.remOnChnSeqNum);
+
+    if( eSIR_FAILURE == limSendRemainOnChannelDebugMarkerFrame(pMac,
+                                                      startRemainOnChannelMsg) )
+    {
+        limLog( pMac, LOGE,
+                "%s: Could not send %d debug marker frame at start"
+                " of remain on channel", __func__, id);
+        status = eHAL_STATUS_FAILURE;
+    }
+    vos_mem_free( startRemainOnChannelMsg );
+
+    return status;
+
+}
+
+/*----------------------------------------------------------------------------
+ *
+ * This function forms message for cancel of remain on channel. This message
+ * is added as data of Vendor Specific information element of debug marker
+ * frame.Message will be in form "CANCEL-REMAIN-ON-CHANNEL<first/second-frame>"
+ * "-SEQ=<sequence-num>"
+ *
+ *----------------------------------------------------------------------------*/
+eHalStatus limPrepareAndSendCancelRemainOnChannelMsg(tpAniSirGlobal pMac,
+                                                               tANI_U8 id)
+{
+    tANI_U8 *cancelRemainOnChannelMsg;
+    eHalStatus status = eHAL_STATUS_SUCCESS;
+
+    cancelRemainOnChannelMsg = vos_mem_malloc( REMAIN_ON_CHANNEL_MSG_SIZE );
+    if( NULL == cancelRemainOnChannelMsg )
+    {
+        limLog( pMac, LOGE,
+                FL( "Unable to allocate memory for end of"
+                    " remain on channel message" ));
+        return eHAL_STATUS_FAILURE;
+    }
+
+    snprintf(cancelRemainOnChannelMsg, REMAIN_ON_CHANNEL_MSG_SIZE,
+            "CANCEL-REMAIN-ON-CHANNEL%d-SEQ=%d",
+            id, pMac->lim.remOnChnSeqNum);
+    if( eSIR_FAILURE == limSendRemainOnChannelDebugMarkerFrame(pMac,
+                                                 cancelRemainOnChannelMsg) )
+    {
+        limLog( pMac, LOGE,
+                "%s: Could not send %d marker frame to debug cancel"
+                " remain on channel", __func__, id);
+        status = eHAL_STATUS_FAILURE;
+    }
+    vos_mem_free( cancelRemainOnChannelMsg );
+
+    return status;
+
+}
+
 /*------------------------------------------------------------------
  *
  * Below function is callback function, it is called when 
@@ -108,11 +285,26 @@
  *------------------------------------------------------------------*/
 void limSetLinkStateP2PCallback(tpAniSirGlobal pMac, void *callbackArg)
 {
+    tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq;
+
     //Send Ready on channel indication to SME
     if(pMac->lim.gpLimRemainOnChanReq)
     {
         limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RDY_IND, eHAL_STATUS_SUCCESS, 
                      pMac->lim.gpLimRemainOnChanReq->sessionId, 0); 
+        if(pMac->lim.gDebugP2pRemainOnChannel)
+        {
+            if( eHAL_STATUS_SUCCESS == limPrepareAndSendStartRemainOnChannelMsg(
+                                        pMac,
+                                        MsgRemainonChannel,
+                                        REMAIN_ON_CHANNEL_SECOND_MARKER_FRAME) )
+            {
+                limLog( pMac, LOG1,
+                        "%s: Successfully sent 2nd Marker frame "
+                        "seq num = %d on start ROC", __func__,
+                        pMac->lim.remOnChnSeqNum);
+            }
+        }
     }
     else
     {
@@ -378,6 +570,28 @@
         goto error;
     }
 
+    if (eSIR_SUCCESS !=
+        wlan_cfgGetInt(pMac, WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL,
+                       (tANI_U32 *)&pMac->lim.gDebugP2pRemainOnChannel))
+    {
+        limLog( pMac, LOGE,
+                "%s: Couldn't get WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL value",
+                 __func__);
+        pMac->lim.gDebugP2pRemainOnChannel = 0;
+    }
+    if (pMac->lim.gDebugP2pRemainOnChannel)
+    {
+        pMac->lim.remOnChnSeqNum++;
+        if( eHAL_STATUS_SUCCESS == limPrepareAndSendStartRemainOnChannelMsg(
+                                     pMac, MsgRemainonChannel,
+                                     REMAIN_ON_CHANNEL_FIRST_MARKER_FRAME) )
+        {
+            limLog( pMac, LOG1,
+                    "%s: Successfully sent 1st marker frame with seq num = %d"
+                    " on start ROC", __func__, pMac->lim.remOnChnSeqNum);
+        }
+    }
+
     if ((limSetLinkState(pMac, MsgRemainonChannel->isProbeRequestAllowed?
                          eSIR_LINK_LISTEN_STATE:eSIR_LINK_SEND_ACTION_STATE,nullBssid,
                          pMac->lim.gSelfMacAddr, limSetLinkStateP2PCallback, 
@@ -466,6 +680,29 @@
 
 /*------------------------------------------------------------------
  *
+ * limSetLinkState callback function.
+ *
+ *------------------------------------------------------------------*/
+void limSetlinkStateCallback(tpAniSirGlobal pMac, void *callbackArg)
+{
+    if(pMac->lim.gDebugP2pRemainOnChannel)
+    {
+        if (eHAL_STATUS_SUCCESS == limPrepareAndSendCancelRemainOnChannelMsg(
+                                      pMac,
+                                      REMAIN_ON_CHANNEL_SECOND_MARKER_FRAME))
+        {
+            limLog( pMac, LOG1,
+                    "%s: Successfully sent 2nd marker frame with seq num=%d"
+                    " on cancel ROC", __func__, pMac->lim.remOnChnSeqNum);
+        }
+    }
+
+    return;
+
+}
+
+/*------------------------------------------------------------------
+ *
  * limchannelchange callback, on success channel change, set the
  * link_state to LISTEN
  *
@@ -493,9 +730,21 @@
         return;
     }
 
+    if(pMac->lim.gDebugP2pRemainOnChannel)
+    {
+        if (eHAL_STATUS_SUCCESS == limPrepareAndSendCancelRemainOnChannelMsg(
+                                        pMac,
+                                        REMAIN_ON_CHANNEL_FIRST_MARKER_FRAME))
+        {
+            limLog( pMac, LOG1,
+                    "%s: Successfully sent 1st marker frame with seqnum = %d"
+                    " on cancel ROC", __func__, pMac->lim.remOnChnSeqNum);
+        }
+    }
+
     /* get the previous valid LINK state */
     if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
-        pMac->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS)
+        pMac->lim.gSelfMacAddr, limSetlinkStateCallback, NULL) != eSIR_SUCCESS)
     {
         limLog( pMac, LOGE, "Unable to change link state");
         return;