/*
==========================================================================
	Description:

	IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_MlmeChannelSwitchRspAction(
    IN PRTMP_ADAPTER pAd,
    IN MLME_QUEUE_ELEM *Elem)
{
    PMLME_TDLS_CH_SWITCH_STRUCT pMlmeChSwitchRsp = NULL;
    NDIS_STATUS	NStatus = NDIS_STATUS_SUCCESS;
    PRT_802_11_TDLS	pTdls = NULL;
    int LinkId = 0xff;

    DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_MlmeChannelSwitchRspAction() \n"));

    pMlmeChSwitchRsp = (PMLME_TDLS_CH_SWITCH_STRUCT)Elem->Msg;

    if (INFRA_ON(pAd))
    {
        // Drop not within my TDLS Table that created before !
        LinkId = TDLS_SearchLinkId(pAd, pMlmeChSwitchRsp->PeerMacAddr);

        if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
        {
            DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_MlmeChannelSwitchRspAction() can not find the LinkId!\n"));
            return;
        }

        /* Point to the current Link ID */
        pTdls = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

        /* Build TDLS channel switch Request Frame */
        NStatus = TDLS_ChannelSwitchRspAction(pAd, pTdls, pTdls->ChSwitchTime, pTdls->ChSwitchTimeout, 0, (RTMP_TDLS_SPECIFIC_CS_RSP_NOACK + RTMP_TDLS_SPECIFIC_HCCA));

        if (NStatus != NDIS_STATUS_SUCCESS)
        {
            DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeChannelSwitchRspAction() Build Channel Switch Response Fail !!!\n"));
        }
        else
        {
            RTMPusecDelay(300);
            NdisGetSystemUpTime(&pAd->StaCfg.TdlsGoBackStartTime);

            RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
            if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
                TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE);
            else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
                TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW);
            else
                TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE);
            TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL);
            RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);

            DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_MlmeChannelSwitchRspAction() \n"));
        }
    }
    else
    {
        DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeChannelSwitchRspAction() TDLS only support infra mode !!!\n"));
    }

    return;
}
示例#2
0
/*
========================================================================
Routine Description:
	Receive a traffic indication frame.

Arguments:
	pAd				- WLAN control block pointer
	pElem			- the frame information

Return Value:
	None

Note:
========================================================================
*/
static VOID TDLS_UAPSD_PeerTrafficIndAction(
    IN	PRTMP_ADAPTER				pAd,
    IN	MLME_QUEUE_ELEM				*pElem)
{
	UCHAR Token;
	UCHAR PeerAddr[6];
	UCHAR PeerAddr1[6];
	ULONG OffsetPuBuff;
	INT LinkId = 0xff;
	PRT_802_11_TDLS	pTDLS = NULL;
	PFRAME_802_11 pFrame = (PFRAME_802_11)pElem->Msg;

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> ====> %s\n", __FUNCTION__));

	/* Not TDLS Capable, ignore it */
	if (!IS_TDLS_SUPPORT(pAd))
		return;

	/* Not BSS mode, ignore it */
	if (!INFRA_ON(pAd))
		return;

	hex_dump("TDLS UAPSD Peer Traffic Ind receive pack", pElem->Msg, pElem->MsgLen);

	/* sanity check */
	if (TDLS_UAPSD_ARE_WE_IN_ACTIVE(pAd))
		return; /* we are not in power-save mode */

	COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr3);
	// Drop not within my TDLS Table that created before !
	LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
	if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
	{
		DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_UAPSD_PeerTrafficIndAction() can not find the LinkId!\n"));
		return;
	}

	// Point to the current Link ID
	pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

	OffsetPuBuff = PeerTdlsBasicSanity(pAd,
									pElem->Msg,
									pElem->MsgLen,
									pTDLS->bInitiator,
									&Token,
									PeerAddr1);
	if (OffsetPuBuff <= 0)
		return;

/*	hex_dump("PeerAddr=", PeerAddr, 6); */
	DBGPRINT(RT_DEBUG_ERROR, ("tdls uapsd> PU Buffer Status = 0x%x\n",
			pElem->Msg[OffsetPuBuff+2])); /* 2: skip ID and length field */

	/* reply a response frame with UP = 5 */
	/* for TDLS UAPSD, all AC will be UAPSD mode */
	TDLS_UAPSD_TrafficRspSend(pAd, PeerAddr, Token);
}
示例#3
0
/*
========================================================================
Routine Description:
	Simulate to receive a TDLS Traffic response from a peer.

Arguments:
	pAd				- WLAN control block pointer
	Argc			- the number of input parameters
	*pArgv			- input parameters

Return Value:
	None

Note:
	1. Command Format:
		iwpriv ra0 set tdls=52_[PEER MAC]

	2. In the actual case, the traffic response frame will be handled in
		STAHandleRxDataFrame() because the traffic response frame is a
		DATA frame, not management action frame.
========================================================================
*/
static VOID TDLS_UAPSD_CmdSimTrafficRspRcv(
	IN	PRTMP_ADAPTER				pAd,
	IN	INT32						Argc,
	IN	CHAR						*pArgv)
{
	MAC_TABLE_ENTRY	*pMacEntry;
	UCHAR PeerMac[6];
	RT_802_11_TDLS *pTDLS = NULL;
	INT32 LinkId;


	/* get MAC address */
	TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac);

	/* get pEntry */
	pMacEntry = MacTableLookup(pAd, PeerMac);

	if (pMacEntry == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("tdls_cmd> ERROR! No such peer!\n"));
		return;
	}

	/* search TDLS entry */
	LinkId = TDLS_SearchLinkId(pAd, PeerMac);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_ERROR,
				("%s: can not find the LinkId!\n", __FUNCTION__));
		TDLS_UAPSD_REBUILD_LINK(pAd, PeerMac);
		return;
	}

	DBGPRINT(RT_DEBUG_ERROR, ("tdls uapsd> LinkId = %d\n", LinkId));

	/* cancel waiting flag to avoid tear down the link */
	pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId);
	pTDLS->FlgIsWaitingUapsdTraRsp = FALSE;

	/* handle UAPSD SP */
	/*
		TDLS uses Ethertype 89-0d frames, as defined in Annex U.
		The TDLS payload contains a TDLS Action frame body as is specified
		in 7.4.11. The UP shall be AC_VI, unless otherwise specified.

		So these TDLS action frames are DATA frame, not management frame.
	*/
	UAPSD_TriggerFrameHandle(pAd, pMacEntry, 5);
}
示例#4
0
/*
========================================================================
Routine Description:
	Send a traffic response frame.

Arguments:
	pAd				- WLAN control block pointer
	pTDLS			- the peer entry

Return Value:
	NDIS_STATUS_SUCCESS
	NDIS_STATUS_FAILURE

Note:
========================================================================
*/
static NDIS_STATUS TDLS_UAPSD_TrafficRspSend(
	IN	PRTMP_ADAPTER				pAd,
	IN	UCHAR						*pPeerMac,
	IN	UCHAR						PeerToken)
{
	MAC_TABLE_ENTRY	*pMacEntry; 
	RT_802_11_TDLS *pTDLS = NULL;
	UCHAR	TDLS_ETHERTYPE[] = {0x89, 0x0d};
	UCHAR	Header802_3[14];
	PUCHAR	pOutBuffer = NULL;
	ULONG	FrameLen = 0;
	ULONG	TempLen;
	INT32	LinkId;
	UCHAR	RemoteFrameType = PROTO_NAME_TDLS;
	NDIS_STATUS	NStatus = NDIS_STATUS_FAILURE;


	DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));

	/* search TDLS entry */
	LinkId = TDLS_SearchLinkId(pAd, pPeerMac);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_TRACE,
				("%s: can not find the LinkId!\n", __FUNCTION__));
		TDLS_UAPSD_REBUILD_LINK(pAd, pPeerMac);
		goto LabelExit;
	}

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> LinkId = %d\n", LinkId));

	pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId);

	/* sanity check */
	if (TDLS_UAPSD_IS_CONN_NOT_BUILT(pTDLS))
	{
		DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> link is not yet built "
				"so we can not send a traffic ind to the peer!!!"));
		goto LabelExit;
	}

	/* init */
	MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr,
						pAd->CurrentAddress, TDLS_ETHERTYPE);

	/* allocate buffer for transmitting message */
	NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
	if (NStatus	!= NDIS_STATUS_SUCCESS)
		goto LabelExit;

	/* build the frame */
	MakeOutgoingFrame(pOutBuffer,		&TempLen,
						1,				&RemoteFrameType,
						END_OF_ARGS);
	FrameLen = FrameLen + TempLen;

	TDLS_UAPSD_TrafficRspBuild(pAd, pOutBuffer, &FrameLen, pTDLS, PeerToken);

	hex_dump("TDLS UAPSD Peer Traffic Response sending packet", pOutBuffer, FrameLen);

	/* need to set the power save mode of the peer to ACTIVE */
	/* we will recover its mode after EOSP frame is received */
	pMacEntry = MacTableLookup(pAd, pTDLS->MacAddr);
	if (pMacEntry == NULL)
		goto LabelExit;

	/* peer can not sleep for a while */
		RTMP_PS_VIRTUAL_WAKEUP_PEER(pMacEntry);

	/* send the frame to the peer without AP's help */
	TDLS_UAPSD_PKT_SEND_TO_PEER(pAd, Header802_3, pOutBuffer, FrameLen, pTDLS);
/*	hex_dump("TDLS traffic response send pack", pOutBuffer, FrameLen); */

	NStatus = NDIS_STATUS_SUCCESS;

	/* free resources */
LabelExit:
	if (pOutBuffer != NULL)
		MlmeFreeMemory(pAd, pOutBuffer);
	return NStatus;
}
示例#5
0
/*
========================================================================
Routine Description:
	Build the traffic indication frame.

Arguments:
	pAd				- WLAN control block pointer
	pPeerMac		- the peer
	pFrameBuf		- frame
	pHeader802_3	- frame header

Return Value:
	Frame Length

Note:
========================================================================
*/
static ULONG TDLS_UAPSD_TrafficIndBuild(
	IN	PRTMP_ADAPTER				pAd,
	IN	UCHAR						*pPeerMac,
	OUT UCHAR						*pFrameBuf,
	OUT UCHAR						*pHeader802_3)
{
	RT_802_11_TDLS *pTDLS = NULL;
	UCHAR	TDLS_ETHERTYPE[] = {0x89, 0x0d};
	ULONG	FrameLen = 0;
	INT32	LinkId;
	BOOLEAN TimerCancelled;


	DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));

	/* search TDLS entry */
	LinkId = TDLS_SearchLinkId(pAd, pPeerMac);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_TRACE,
				("%s: can not find the LinkId!\n", __FUNCTION__));
		TDLS_UAPSD_REBUILD_LINK(pAd, pPeerMac);
		goto LabelExit;
	}

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> LinkId = %d\n", LinkId));

	pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId);

	/* sanity check */
	if (TDLS_UAPSD_IS_CONN_NOT_BUILT(pTDLS))
	{
		DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> link is not yet built "
				"so we can not send a traffic ind to the peer!!!"));
		goto LabelExit;
	}

	if (pTDLS->FlgIsWaitingUapsdTraRsp == TRUE)
	{
		DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> traffic ind was sent before!\n"));
		goto LabelExit; /* has sent it */
	}

	pTDLS->FlgIsWaitingUapsdTraRsp = TRUE;

	/* init packet header */
	MAKE_802_3_HEADER(pHeader802_3, pTDLS->MacAddr,
						pAd->CurrentAddress, TDLS_ETHERTYPE);

	/* build the frame */
	TDLS_UAPSD_TrafficIndPayloadBuild(pAd, pFrameBuf, &FrameLen, pTDLS);

	hex_dump("TDLS UAPSD Peer Traffic Ind sending packet", pFrameBuf, FrameLen);
	/*
		11.2.1.14.1 Peer U-APSD Behavior at the PU buffer STA
		When no corresponding TDLS Peer Traffic Response frame has been
		received within dot11TDLSResponseTimeout after sending a TDLS Peer
		Traffic Indication frame, the STA shall tear down the direct link.

		The default value is 5 seconds.
	*/
	/* set traffic indication timer */
	RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
	RTMPSetTimer(&pTDLS->Timer, TDLS_TIMEOUT);

	/* free resources */
LabelExit:
	return FrameLen;
}
示例#6
0
/*
========================================================================
Routine Description:
	Simulate to receive a TDLS Traffic indication from a peer.

Arguments:
	pAd				- WLAN control block pointer
	Argc			- the number of input parameters
	*pArgv			- input parameters

Return Value:
	None

Note:
	1. Command Format:
		iwpriv ra0 set tdls=53_[PEER MAC]
========================================================================
*/
static VOID TDLS_UAPSD_CmdSimTrafficIndRcv(
	IN	PRTMP_ADAPTER				pAd,
	IN	INT32						Argc,
	IN	CHAR						*pArgv)
{
	UCHAR PeerMac[6];
	MLME_QUEUE_ELEM *pElem = NULL;
	PUCHAR pOutBuffer = NULL;
	ULONG FrameLen = 0;
	INT32 LinkId;
	RT_802_11_TDLS *pTDLS = NULL;
	NDIS_STATUS	NStatus = NDIS_STATUS_SUCCESS;
	UCHAR RemoteFrameType = PROTO_NAME_TDLS;
	ULONG TempLen;
	UCHAR Token;			// Dialog token


	/* get MAC address */
	TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac);

	/* allocate resources */
	NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
	if (NStatus	!= NDIS_STATUS_SUCCESS)
		goto LabelExit;

	/* make up a virtual traffic indication frame */
	/* search TDLS entry */
	LinkId = TDLS_SearchLinkId(pAd, PeerMac);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_ERROR,
				("%s: can not find the LinkId!\n", __FUNCTION__));
		TDLS_UAPSD_REBUILD_LINK(pAd, PeerMac);
		goto LabelExit;
	}
	pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId);

	/* build the frame */
	/* fill remote frame type */
	MakeOutgoingFrame(pOutBuffer,		&TempLen,
						1,				&RemoteFrameType,
						END_OF_ARGS);
	FrameLen = TempLen;

	/* fill action code */
	TDLS_InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
						CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_REQUEST);

	/* fill Dialog Token */
	TDLS_UAPSD_DIALOG_GET(pAd, Token);
	TDLS_InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen,
							Token);

	/* fill link identifier */
	TDLS_InsertLinkIdentifierIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
								pTDLS->MacAddr, pAd->CurrentAddress);

	/* fill PU buffer status */
	TDLS_InsertPuBufferStatus(pAd, (pOutBuffer + FrameLen), &FrameLen,
							pTDLS->MacAddr);

	if (FrameLen <= 0)
		goto LabelExit;

/*	hex_dump("TDLS traffic indication send pack", pOutBuffer, FrameLen); */

	/* allocate resources */
	os_alloc_mem(NULL, (UCHAR **)&pElem, sizeof(MLME_QUEUE_ELEM));
	if (pElem == NULL)
		goto LabelExit;

	/* copy the indication frame */
	FrameLen += LENGTH_802_11 + LENGTH_802_1_H;
	pElem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + FrameLen;

	/* copy payload */
	memcpy(pElem->Msg + LENGTH_802_11 + LENGTH_802_1_H,
			pOutBuffer, FrameLen);

	/* handle it */
	TDLS_UAPSD_PeerTrafficIndAction(pAd, pElem);

	/* free resources */
LabelExit:
	if (pElem != NULL)
		os_free_mem(NULL, pElem);
	if (pOutBuffer != NULL)
		MlmeFreeMemory(pAd, pOutBuffer);
}
示例#7
0
/*
========================================================================
Routine Description:
	Receive a traffic response frame.

Arguments:
	pAd				- WLAN control block pointer
	pElem			- the frame information
Return Value:
	None

Note:
========================================================================
*/
static VOID TDLS_UAPSD_PeerTrafficRspAction(
	IN	PRTMP_ADAPTER				pAd,
    IN	MLME_QUEUE_ELEM				*pElem)
{
	UCHAR Token;
	UCHAR PeerAddr[6];
	UCHAR PeerAddr1[6];
	RT_802_11_TDLS *pTDLS;
	INT32 LinkId = 0xff;
	BOOLEAN TimerCancelled;
	PFRAME_802_11 pFrame = (PFRAME_802_11)pElem->Msg;

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> ====> %s\n", __FUNCTION__));

	/* Not TDLS Capable, ignore it */
	if (!IS_TDLS_SUPPORT(pAd))
		return;
	
	/* Not BSS mode, ignore it */
	if (!INFRA_ON(pAd))
		return;

	hex_dump("TDLS UAPSD Peer Traffic Response receive pack", pElem->Msg, pElem->MsgLen);

	COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr2);
	// Drop not within my TDLS Table that created before !
	LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_ERROR, ("%s: can not find the LinkId!\n", __FUNCTION__));
		return;
	}

	// Point to the current Link ID
	pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

	/* sanity check */
	PeerTdlsBasicSanity(pAd,
						pElem->Msg,
						pElem->MsgLen,
						pTDLS->bInitiator,
						&Token,
						PeerAddr1);

/*	hex_dump("PeerAddr=", PeerAddr, 6); */

	/* search TDLS entry */
	LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
	if (TDLS_UAPSD_IS_LINK_INVALID(LinkId))
	{
		DBGPRINT(RT_DEBUG_TRACE,
				("%s: can not find the LinkId!\n", __FUNCTION__));
		TDLS_UAPSD_REBUILD_LINK(pAd, PeerAddr);
		return;
	}

	DBGPRINT(RT_DEBUG_TRACE, ("tdls uapsd> LinkId = %d\n", LinkId));

	/* cancel waiting flag to avoid tear down the link */
	pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId);
	pTDLS->FlgIsWaitingUapsdTraRsp = FALSE;
	RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);

	/* check if we can sleep if we are sleep mode */
	RtmpAsicSleepHandle(pAd);
}
/*
==========================================================================
	Description:

	IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerChannelSwitchRspAction(
    IN PRTMP_ADAPTER pAd,
    IN MLME_QUEUE_ELEM *Elem)
{
    PRT_802_11_TDLS		pTDLS = NULL;
    int					LinkId = 0xff;
    UCHAR				PeerAddr[MAC_ADDR_LEN];
    //BOOLEAN				IsInitator;
    BOOLEAN				TimerCancelled;
    //UCHAR				RegulatoryClass;
    //UCHAR				NewExtChannelOffset = 0xff;
    UCHAR				LinkIdentLen;
    USHORT				PeerChSwitchTime;
    USHORT				PeerChSwitchTimeOut;
    TDLS_LINK_IDENT_ELEMENT	LinkIdent;
    //NDIS_STATUS			NStatus = NDIS_STATUS_SUCCESS;
    USHORT				StatusCode = MLME_SUCCESS;

    DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_PeerChannelSwitchRspAction() \n"));

    // Not TDLS Capable, ignore it
    if (!IS_TDLS_SUPPORT(pAd))
        return;

    if (!INFRA_ON(pAd))
        return;

    hex_dump("TDLS peer channel switch response receive pack", Elem->Msg, Elem->MsgLen);

    if (!PeerTdlsChannelSwitchRspSanity(pAd,
                                        Elem->Msg,
                                        Elem->MsgLen,
                                        PeerAddr,
                                        &StatusCode,
                                        &PeerChSwitchTime,
                                        &PeerChSwitchTimeOut,
                                        &LinkIdentLen,
                                        &LinkIdent))
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    // Drop not within my TDLS Table that created before !
    LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
    if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    // Point to the current Link ID
    pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

    if ((pTDLS->ChannelSwitchCurrentState == TDLS_CHANNEL_SWITCH_NONE) &&
            (StatusCode == MLME_REQUEST_DECLINED))
    {
        DBGPRINT(RT_DEBUG_OFF,("%s(%d): received a failed StatusCode = %d on Unsolicited response !!!\n",
                               __FUNCTION__, __LINE__, StatusCode));
        return;
    }

    if (StatusCode == MLME_REQUEST_DECLINED)
    {
        if ((pAd->StaCfg.TdlsChannelSwitchRetryCount > 0) &&
                (pTDLS->bDoingPeriodChannelSwitch) &&
                (pAd->StaCfg.bDoingPeriodChannelSwitch))
        {
            pAd->StaCfg.TdlsChannelSwitchRetryCount--;

            DBGPRINT(RT_DEBUG_OFF,("%s(%d): received a failed StatusCode = %d  re-try again !!!\n",
                                   __FUNCTION__, __LINE__, StatusCode));
        }
        else
        {
            pTDLS->bDoingPeriodChannelSwitch = FALSE;
            pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE;
            pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;
            pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE;
            RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE);
        }

        DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_PeerChannelSwitchRspAction() received a failed StatusCode = %d !!!\n", StatusCode ));
        return;
    }

    DBGPRINT(RT_DEBUG_WARN,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x !!!\n",
                            __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));



    if (StatusCode == MLME_SUCCESS)
    {
        if (pTDLS->ChannelSwitchCurrentState == TDLS_CHANNEL_SWITCH_NONE)
        {
            if (pAd->StaCfg.bChannelSwitchInitiator == FALSE)
            {
                RTMPCancelTimer(&pAd->StaCfg.TdlsResponderGoBackBaseChTimer, &TimerCancelled);
                DBGPRINT(RT_DEBUG_WARN,("%s(%d): i am responder!!!\n",  __FUNCTION__,__LINE__));
            }
            else
            {
                RTMPCancelTimer(&pAd->StaCfg.TdlsPeriodGoBackBaseChTimer, &TimerCancelled);
                DBGPRINT(RT_DEBUG_WARN,("%s(%d): i am Initiator !!!\n", __FUNCTION__,__LINE__));
            }

            if (pAd->StaCfg.TdlsCurrentOperateChannel != pAd->CommonCfg.Channel)
            {
                DBGPRINT(RT_DEBUG_ERROR, ("106. %ld !!!\n", (jiffies * 1000) / OS_HZ));

                RTMPusecDelay(300);
                NdisGetSystemUpTime(&pAd->StaCfg.TdlsGoBackStartTime);

                RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE);
                else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW);
                else
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE);
                TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL);
                RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
            }
        }
        else
        {
            if (pAd->StaCfg.TdlsCurrentChannel != pAd->CommonCfg.Channel)
            {
                if (pAd->StaCfg.bChannelSwitchInitiator)
                {
                    UINT16 SwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; //micro seconds
                    UINT16 SwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; // micro seconds

                    pAd->StaCfg.TdlsChannelSwitchPairCount--;
                    pAd->StaCfg.TdlsChannelSwitchRetryCount = 10;
                    //pAd->StaCfg.bDoingPeriodChannelSwitch = TRUE;

                    if (SwitchTime >= PeerChSwitchTime)
                        PeerChSwitchTime = SwitchTime;

                    if (SwitchTimeout >= PeerChSwitchTimeOut)
                        PeerChSwitchTimeOut = SwitchTimeout;

                    pTDLS->ChSwitchTime = PeerChSwitchTime;
                    pAd->StaCfg.TdlsGlobalSwitchTime = PeerChSwitchTime;
                    pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut;
                    pAd->StaCfg.TdlsGlobalSwitchTimeOut = PeerChSwitchTimeOut;
                    pTDLS->ChannelSwitchCurrentState = TDLS_CHANNEL_SWITCH_NONE;

                    RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                    //Cancel the timer since the received packet to me.
#ifdef TDLS_HWTIMER_SUPPORT
                    TDLS_SetChannelSwitchTimer(pAd,  ((PeerChSwitchTime + pAd->StaCfg.TdlsOffChannelDelay) / 1000));
#else
                    RTMPCancelTimer(&pTDLS->ChannelSwitchTimer, &TimerCancelled);
                    pTDLS->bEnableChSwitchTime = TRUE;
                    NdisGetSystemUpTime(&pTDLS->ChannelSwitchTimerStartTime);
                    RTMPSetTimer(&pTDLS->ChannelSwitchTimer, ((PeerChSwitchTime + pAd->StaCfg.TdlsOffChannelDelay) / 1000));
#endif // TDLS_HWTIMER_SUPPORT //

                    if (RTDebugLevel < RT_DEBUG_ERROR)
                        RTMPusecDelay(300);
                    else
                        DBGPRINT(RT_DEBUG_ERROR, ("104. %ld !!!\n", (jiffies * 1000) / OS_HZ));
                    TDLS_InitChannelRelatedValue(pAd, pAd->StaCfg.TdlsCurrentChannel, pAd->StaCfg.TdlsCurrentChannelBW);
                }
            }
            else
            {
                pTDLS->bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE;
                pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;

                if (pAd->StaCfg.bChannelSwitchInitiator == FALSE)
                {
                    DBGPRINT(RT_DEBUG_OFF,("%s(%d): i am channel switch responder!!!\n",  __FUNCTION__,__LINE__));
                }
                else
                {
                    RTMPCancelTimer(&pAd->StaCfg.TdlsDisableChannelSwitchTimer, &TimerCancelled);
                    pAd->StaCfg.bChannelSwitchInitiator = FALSE;
                    DBGPRINT(RT_DEBUG_OFF,("%s(%d): i am channel switch Initiator !!!\n", __FUNCTION__,__LINE__));
                }

                if (pAd->StaCfg.TdlsCurrentOperateChannel != pAd->CommonCfg.Channel)
                {
                    RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                    if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
                        TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE);
                    else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
                        TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW);
                    else
                        TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE);
                    TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL);
                    RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                }

                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE);
            }
        }
    }




    DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_PeerChannelSwitchRspAction() \n"));

    return;
}
/*
==========================================================================
	Description:

	IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerChannelSwitchReqAction(
    IN PRTMP_ADAPTER pAd,
    IN MLME_QUEUE_ELEM *Elem)
{
    PRT_802_11_TDLS		pTDLS = NULL;
    int					LinkId = 0xff;
    UCHAR				PeerAddr[MAC_ADDR_LEN];
    BOOLEAN				IsInitator;
    //BOOLEAN				TimerCancelled;
    UCHAR				TargetChannel;
    UCHAR				RegulatoryClass;
    UCHAR				NewExtChannelOffset = 0xff;
    UCHAR				LinkIdentLen;
    USHORT				PeerChSwitchTime;
    USHORT				PeerChSwitchTimeOut;
    TDLS_LINK_IDENT_ELEMENT	LinkIdent;
    NDIS_STATUS			NStatus = NDIS_STATUS_SUCCESS;
    USHORT				StatusCode = MLME_SUCCESS;
    UINT16				SwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime; //micro seconds
    UINT16				SwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout; // micro seconds

    DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_PeerChannelSwitchReqAction() \n"));

    // Not TDLS Capable, ignore it
    if (!IS_TDLS_SUPPORT(pAd))
        return;

    if (!INFRA_ON(pAd))
        return;

    if (pAd->StaActive.ExtCapInfo.TDLSChSwitchProhibited == TRUE)
    {
        DBGPRINT(RT_DEBUG_OFF,("%s(%d): AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__, __LINE__));
        return;
    }

    tdls_hex_dump("TDLS peer channel switch request receive pack", Elem->Msg, Elem->MsgLen);

    if (!PeerTdlsChannelSwitchReqSanity(pAd,
                                        Elem->Msg,
                                        Elem->MsgLen,
                                        PeerAddr,
                                        &IsInitator,
                                        &TargetChannel,
                                        &RegulatoryClass,
                                        &NewExtChannelOffset,
                                        &PeerChSwitchTime,
                                        &PeerChSwitchTimeOut,
                                        &LinkIdentLen,
                                        &LinkIdent))
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    DBGPRINT(RT_DEBUG_WARN,("%s(%d):  from %02x:%02x:%02x:%02x:%02x:%02x !!!\n",
                            __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));

    DBGPRINT(RT_DEBUG_ERROR, ("300. %ld !!!\n", (jiffies * 1000) / OS_HZ));

    // Drop not within my TDLS Table that created before !
    LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
    if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
    {
        DBGPRINT(RT_DEBUG_ERROR,("%s(%d):  can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n",
                                 __FUNCTION__,__LINE__, PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
        return;
    }

    if (pAd->StaCfg.bChannelSwitchInitiator == FALSE)
    {
        pAd->StaCfg.TdlsForcePowerSaveWithAP = TRUE;

        if (pAd->StaCfg.bTdlsNoticeAPPowerSave == FALSE)
        {
            pAd->StaCfg.TdlsSendNullFrameCount = 0;
            pAd->StaCfg.bTdlsNoticeAPPowerSave = TRUE;
            RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, TRUE);
        }
        else
        {
            pAd->StaCfg.TdlsSendNullFrameCount++;
            if (pAd->StaCfg.TdlsSendNullFrameCount >= 200)
                pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;
        }
    }



    // Point to the current Link ID
    pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

    if (SwitchTime >= PeerChSwitchTime)
        PeerChSwitchTime = SwitchTime;

    if (SwitchTimeout >= PeerChSwitchTimeOut)
        PeerChSwitchTimeOut = SwitchTimeout;

    if (RtmpPktPmBitCheck(pAd))
    {
        RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
        TDLS_SendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, 0);
    }

    {
        UINT32 macCfg, TxCount;
        UINT32 MTxCycle;

        RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg);

        if  (TargetChannel != pAd->CommonCfg.Channel)
            NStatus = TDLS_ChannelSwitchRspAction(pAd, pTDLS, PeerChSwitchTime, PeerChSwitchTimeOut, StatusCode, RTMP_TDLS_SPECIFIC_CS_RSP_WAIT_ACK);
        else
            NStatus = TDLS_ChannelSwitchRspAction(pAd, pTDLS, PeerChSwitchTime, PeerChSwitchTimeOut, StatusCode, (RTMP_TDLS_SPECIFIC_CS_RSP_WAIT_ACK + RTMP_TDLS_SPECIFIC_HCCA));


        for (MTxCycle = 0; MTxCycle < 500; MTxCycle++)
        {
            RTMP_IO_READ32(pAd, TX_REPORT_CNT, &macCfg);
            TxCount = macCfg & 0x0000ffff;
            if (TxCount > 0)
            {
                DBGPRINT(RT_DEBUG_ERROR, ("MTxCycle = %d, %ld !!!\n", MTxCycle, (jiffies * 1000) / OS_HZ));
                break;
            }
            else
                RTMPusecDelay(50);
        }

        if (MTxCycle >= 500)
        {
            NStatus = NDIS_STATUS_FAILURE;
            DBGPRINT(RT_DEBUG_OFF,("TDLS Transmit Channel Switch Response Fail !!!\n"));
        }
    }

    if (NStatus == NDIS_STATUS_SUCCESS)
    {

        {
            if  (TargetChannel != pAd->CommonCfg.Channel)
            {
                BOOLEAN TimerCancelled;
                //ULONG Now, temp1, temp2, temp3;

                pAd->StaCfg.TdlsCurrentChannel = TargetChannel;

                if (NewExtChannelOffset != 0)
                    pAd->StaCfg.TdlsCurrentChannelBW = NewExtChannelOffset;
                else
                    pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_NONE;

                pTDLS->ChSwitchTime = PeerChSwitchTime;
                pAd->StaCfg.TdlsGlobalSwitchTime = PeerChSwitchTime;
                pTDLS->ChSwitchTimeout = PeerChSwitchTimeOut;
                pAd->StaCfg.TdlsGlobalSwitchTimeOut = PeerChSwitchTimeOut;

                RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                //Cancel the timer since the received packet to me.
#ifdef TDLS_HWTIMER_SUPPORT
                TDLS_SetChannelSwitchTimer(pAd,  (PeerChSwitchTimeOut / 1000));
#else
                RTMPCancelTimer(&pTDLS->ChannelSwitchTimeoutTimer, &TimerCancelled);
                NdisGetSystemUpTime(&pTDLS->ChannelSwitchTimerStartTime);
                RTMPSetTimer(&pTDLS->ChannelSwitchTimeoutTimer, (PeerChSwitchTimeOut / 1000));
#endif // TDLS_HWTIMER_SUPPORT //
                RTMPCancelTimer(&pAd->StaCfg.TdlsDisableChannelSwitchTimer, &TimerCancelled);
                pAd->StaCfg.bTdlsCurrentDoingChannelSwitchWaitSuccess = TRUE;
                pAd->StaCfg.bDoingPeriodChannelSwitch = TRUE;

                if (RTDebugLevel < RT_DEBUG_ERROR)
                    RTMPusecDelay(300);
                else
                    DBGPRINT(RT_DEBUG_ERROR, ("1041. %ld !!!\n", (jiffies * 1000) / OS_HZ));
                TDLS_InitChannelRelatedValue(pAd, pAd->StaCfg.TdlsCurrentChannel, pAd->StaCfg.TdlsCurrentChannelBW);
            }
            else
            {
                pTDLS->bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.bDoingPeriodChannelSwitch = FALSE;
                pAd->StaCfg.TdlsForcePowerSaveWithAP = FALSE;
                pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;

                RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);
                RTMPusecDelay(300);

                if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_ABOVE);
                else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_BELOW);
                else
                    TDLS_InitChannelRelatedValue(pAd, pAd->CommonCfg.Channel, EXTCHA_NONE);
                TDLS_EnablePktChannel(pAd, TDLS_FIFO_ALL);
                RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_TDLS_DOING_CHANNEL_SWITCH);

                RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE);
            }
        }
    }

    DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_PeerChannelSwitchReqAction() \n"));

    return;
}
/*
==========================================================================
	Description:

	IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_MlmeChannelSwitchAction(
    IN PRTMP_ADAPTER pAd,
    IN MLME_QUEUE_ELEM *Elem)
{
    PMLME_TDLS_CH_SWITCH_STRUCT pChSwReq = NULL;
    NDIS_STATUS	NStatus = NDIS_STATUS_SUCCESS;
    int	LinkId = 0xff;

    DBGPRINT(RT_DEBUG_WARN,("TDLS ===> TDLS_MlmeChannelSwitchAction() \n"));

    pChSwReq = (PMLME_TDLS_CH_SWITCH_STRUCT)Elem->Msg;

    if (pAd->StaActive.ExtCapInfo.TDLSChSwitchProhibited == TRUE)
    {
        DBGPRINT(RT_DEBUG_OFF,("%s(%d): AP Prohibite TDLS Channel Switch !!!\n", __FUNCTION__, __LINE__));
        return;
    }

    if (INFRA_ON(pAd))
    {
        // Drop not within my TDLS Table that created before !
        LinkId = TDLS_SearchLinkId(pAd, pChSwReq->PeerMacAddr);

        if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
        {
            DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeChannelSwitchAction() can not find the LinkId!\n"));
            return;
        }

        pAd->StaCfg.TdlsForcePowerSaveWithAP = TRUE;

        if (pAd->StaCfg.bTdlsNoticeAPPowerSave == FALSE)
        {
            pAd->StaCfg.TdlsSendNullFrameCount = 0;
            pAd->StaCfg.bTdlsNoticeAPPowerSave = TRUE;
            RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, TRUE);
        }
        else
        {
            pAd->StaCfg.TdlsSendNullFrameCount++;
            if (pAd->StaCfg.TdlsSendNullFrameCount >= 200)
                pAd->StaCfg.bTdlsNoticeAPPowerSave = FALSE;
        }

        DBGPRINT(RT_DEBUG_ERROR, ("103. %ld !!!\n", (jiffies * 1000) / OS_HZ));

        /* Build TDLS channel switch Request Frame */
        NStatus = TDLS_ChannelSwitchReqAction(pAd, pChSwReq);
        if (NStatus	!= NDIS_STATUS_SUCCESS)
        {
            DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeChannelSwitchAction() Build Channel Switch Request Fail !!!\n"));
        }
        else
        {
            pAd->StaCfg.TdlsChannelSwitchPairCount++;
            DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_MlmeChannelSwitchAction() \n"));
        }
    }
    else
    {
        DBGPRINT(RT_DEBUG_WARN,("TDLS <=== TDLS_MlmeChannelSwitchAction() TDLS only support infra mode !!!\n"));
    }

    return;
}
/*
==========================================================================
	Description:

	IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_BuildChannelSwitchRequest(
    IN PRTMP_ADAPTER pAd,
    OUT PUCHAR pFrameBuf,
    OUT PULONG pFrameLen,
    IN PUCHAR pPeerAddr,
    IN USHORT ChSwitchTime,
    IN USHORT ChSwitchTimeOut,
    IN UCHAR TargetChannel,
    IN UCHAR TargetChannelBW)
{
    PRT_802_11_TDLS	pTDLS = NULL;
    int LinkId = 0xff;

    /* fill action code */
    TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen,
                        CATEGORY_TDLS, TDLS_ACTION_CODE_CHANNEL_SWITCH_REQUEST);

    /* Target Channel */
    TDLS_InsertTargetChannel(pAd, (pFrameBuf + *pFrameLen), pFrameLen, TargetChannel);

    /* Regulatory Class */
    TDLS_InsertRegulatoryClass(pAd, (pFrameBuf + *pFrameLen), pFrameLen, TargetChannel, TargetChannelBW);

    /* Secondary Channel Offset */
    if(TargetChannelBW != EXTCHA_NONE)
    {
        if (TargetChannel > 14)
        {
            if ((TargetChannel == 36) || (TargetChannel == 44) || (TargetChannel == 52) ||
                    (TargetChannel == 60) || (TargetChannel == 100) || (TargetChannel == 108) ||
                    (TargetChannel == 116) || (TargetChannel == 124) || (TargetChannel == 132) ||
                    (TargetChannel == 149) || (TargetChannel == 157))
            {
                TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, EXTCHA_ABOVE);
                pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_ABOVE;

            }
            else if ((TargetChannel == 40) || (TargetChannel == 48) || (TargetChannel == 56) |
                     (TargetChannel == 64) || (TargetChannel == 104) || (TargetChannel == 112) ||
                     (TargetChannel == 120) || (TargetChannel == 128) || (TargetChannel == 136) ||
                     (TargetChannel == 153) || (TargetChannel == 161))
            {
                TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, EXTCHA_BELOW);
                pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_BELOW;
            }
        }
        else
        {
            do
            {
                UCHAR ExtCh;
                UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
                ExtCh = TDLS_GetExtCh(TargetChannel, Dir);
                if (TDLS_IsValidChannel(pAd, ExtCh))
                {
                    TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, Dir);
                    pAd->StaCfg.TdlsCurrentChannelBW = Dir;
                    break;
                }

                Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE;
                ExtCh = TDLS_GetExtCh(TargetChannel, Dir);
                if (TDLS_IsValidChannel(pAd, ExtCh))
                {
                    TDLS_InsertSecondaryChOffsetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, Dir);
                    pAd->StaCfg.TdlsCurrentChannelBW = Dir;
                    break;
                }
            } while(FALSE);
        }
    }
    else
    {
        pAd->StaCfg.TdlsCurrentChannelBW = EXTCHA_NONE;
    }

    /* fill link identifier */
    LinkId = TDLS_SearchLinkId(pAd, pPeerAddr);
    if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
    {
        DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_ChannelSwitchReqAction() can not find the LinkId!\n"));
        return NDIS_STATUS_FAILURE;
    }
    pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];

    if (pTDLS->bInitiator)
        TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pPeerAddr, pAd->CurrentAddress);
    else
        TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pPeerAddr);

    /* Channel Switch Timing */
    TDLS_InsertChannelSwitchTimingIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, ChSwitchTime, ChSwitchTimeOut);
}