/******************************************************************************
 *
 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 *
 ******************************************************************************/
#include <drv_types.h>
#include <rtl8723a_hal.h>


#ifdef bEnable
#undef bEnable
#endif

//#define BT_DEBUG

#define CHECK_BT_EXIST_FROM_REG
#define DIS_PS_RX_BCN
//#define BTCOEX_DECREASE_WIFI_POWER
//#define BTCOEX_CMCC_TEST

#ifdef CONFIG_BT_COEXIST

u32 BTCoexDbgLevel = _bt_dbg_off_;

#define RTPRINT(_Comp, _Level, Fmt)\
do {\
	if((BTCoexDbgLevel ==_bt_dbg_on_)) {\
/*		printk("%s", DRIVER_PREFIX);*/\
		printk Fmt;\
	}\
}while(0)

#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)\
if((BTCoexDbgLevel ==_bt_dbg_on_) ){\
	u32 __i;						\
	u8 *ptr = (u8*)_Ptr;	\
	printk printstr;				\
	printk(" ");					\
	for( __i=0; __i<6; __i++ )		\
		printk("%02X%s", ptr[__i], (__i==5)?"":"-");		\
	printk("\n");							\
}
#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\
if((BTCoexDbgLevel ==_bt_dbg_on_) ){\
	u32 __i;									\
	u8 *ptr = (u8*)_HexData;			\
	printk(_TitleString);					\
	for( __i=0; __i<(u32)_HexDataLen; __i++ )	\
	{										\
		printk("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?"  ":" ");\
		if (((__i + 1) % 16) == 0)	printk("\n");\
	}										\
	printk("\n");							\
}
// Added by Annie, 2005-11-22.
#define MAX_STR_LEN	64
#define PRINTABLE(_ch)	(_ch>=' ' &&_ch<='~')	// I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.
#define RT_PRINT_STR(_Comp, _Level, _TitleString, _Ptr, _Len)					\
{\
/*	if (((_Comp) & GlobalDebugComponents) && (_Level <= GlobalDebugLevel))	*/\
	{									\
		u32 __i;						\
		u8 buffer[MAX_STR_LEN];					\
		u32	length = (_Len<MAX_STR_LEN)? _Len : (MAX_STR_LEN-1) ;	\
		memset(buffer, 0, MAX_STR_LEN);			\
		memcpy(buffer, (u8*)_Ptr, length);		\
		for (__i=0; __i<length; __i++)					\
		{								\
			if (!PRINTABLE(buffer[__i]))	buffer[__i] = '?';	\
		}								\
		buffer[length] = '\0';						\
/*		printk("Rtl819x: ");*/						\
		printk(_TitleString);						\
		printk(": %d, <%s>\n", _Len, buffer);				\
	}\
}

#else // !BT_DEBUG

#define RTPRINT(...)
#define RTPRINT_ADDR(...)
#define RTPRINT_DATA(...)
#define RT_PRINT_STR(...)

#endif // !BT_DEBUG

#define DCMD_Printf(...)
#define RT_ASSERT(...)

#define rsprintf snprintf


#define GetDefaultAdapter(padapter)	padapter

#define PlatformZeroMemory(ptr, sz)	memset(ptr, 0, sz)

#define PlatformProcessHCICommands(...)
#define PlatformTxBTQueuedPackets(...)
#define PlatformIndicateBTACLData(...)	(RT_STATUS_SUCCESS)
#define PlatformAcquireSpinLock(padapter, type)
#define PlatformReleaseSpinLock(padapter, type)

// timer
#define PlatformInitializeTimer(padapter, ptimer, pfunc, cntx, szID) \
	_init_timer(ptimer, padapter->pnetdev, pfunc, padapter)
#define PlatformSetTimer(a, ptimer, delay)	_set_timer(ptimer, delay)
static u8 PlatformCancelTimer(struct rtw_adapter *a, _timer *ptimer)
{
	u8 bcancelled;
	_cancel_timer(ptimer, &bcancelled);
	return bcancelled;
}
#define PlatformReleaseTimer(...)

#define GET_UNDECORATED_AVERAGE_RSSI(padapter)	\
			(GET_HAL_DATA(padapter)->dmpriv.EntryMinUndecoratedSmoothedPWDB)
#define RT_RF_CHANGE_SOURCE u32

typedef enum _RT_JOIN_ACTION{
	RT_JOIN_INFRA   = 1,
	RT_JOIN_IBSS  = 2,
	RT_START_IBSS = 3,
	RT_NO_ACTION  = 4,
} RT_JOIN_ACTION;

// power saving
#ifdef CONFIG_IPS
#define IPSReturn(padapter, b)		ips_enter(padapter)
#define IPSDisable(padapter, b, c)	ips_leave(padapter)
#else
#define IPSReturn(...)
#define IPSDisable(...)
#endif
#ifdef CONFIG_LPS
#define LeisurePSLeave(padapter, b)	LPS_Leave(padapter)
#else
#define LeisurePSLeave(...)
#endif

#ifdef __BT_C__ // COMMOM/BT.c
// ===== Below this line is sync from SD7 driver COMMOM/BT.c =====

static u8 BT_Operation(struct rtw_adapter *padapter)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->BtOperationOn)
		return _TRUE;
	else
		return _FALSE;
}

static u8 BT_IsLegalChannel(struct rtw_adapter *padapter, u8 channel)
{
	PRT_CHANNEL_INFO pChanneList = NULL;
	u8 channelLen, i;


	pChanneList = padapter->mlmeextpriv.channel_set;
	channelLen = padapter->mlmeextpriv.max_chan_nums;

	for (i = 0; i < channelLen; i++)
	{
		RTPRINT(FIOCTL, IOCTL_STATE, ("Check if chnl(%d) in channel plan contains bt target chnl(%d) for BT connection\n", pChanneList[i].ChannelNum, channel));
		if ((channel == pChanneList[i].ChannelNum) ||
			(channel == pChanneList[i].ChannelNum + 2))
		{
			return channel;
		}
	}
	return 0;
}

void BT_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt)
{
	BTDM_SignalCompensation(padapter, rssi_wifi, rssi_bt);
}

void BT_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
{
	BTHCI_WifiScanNotify(padapter, scanType);
	BTDM_CheckAntSelMode(padapter);
	BTDM_WifiScanNotify(padapter, scanType);
}

void BT_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action)
{
	// action :
	// TRUE = associate start
	// FALSE = associate finished
	if (action)
		BTDM_CheckAntSelMode(padapter);

	BTDM_WifiAssociateNotify(padapter, action);
}

void BT_WifiMediaStatusNotify(struct rtw_adapter *padapter, RT_MEDIA_STATUS mstatus)
{
	BTDM_MediaStatusNotify(padapter, mstatus);
}

void BT_SpecialPacketNotify(struct rtw_adapter *padapter)
{
	BTDM_ForDhcp(padapter);
}

void BT_HaltProcess(struct rtw_adapter *padapter)
{
	BTDM_ForHalt(padapter);
}

void BT_LpsLeave(struct rtw_adapter *padapter)
{
	BTDM_LpsLeave(padapter);
}

// ===== End of sync from SD7 driver COMMOM/BT.c =====
#endif

#ifdef __BT_HANDLEPACKET_C__ // COMMOM/bt_handlepacket.c
// ===== Below this line is sync from SD7 driver COMMOM/bt_handlepacket.c =====

static void btpkt_SendBeacon(struct rtw_adapter *padapter)
{
}

static void BTPKT_WPAAuthINITIALIZE(struct rtw_adapter *padapter, u8 EntryNum)
{
}

static void BTPKT_TimerCallbackWPAAuth(PRT_TIMER pTimer)
{
}

static void BTPKT_TimerCallbackBeacon(PRT_TIMER pTimer)
{
	struct rtw_adapter *	padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTinfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("=====> BTPKT_TimerCallbackBeacon\n"));

	if (!pBTinfo->BTBeaconTmrOn)
		return;

	if (pBtMgnt->BtOperationOn)
	{
		RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("btpkt_SendBeacon\n"));
		btpkt_SendBeacon(GetDefaultAdapter(padapter));
		PlatformSetTimer(padapter, &pBTinfo->BTBeaconTimer, 100);
	}
	else
	{
		RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("<===== BTPKT_TimerCallbackBeacon\n"));
	}
}


// ===== End of sync from SD7 driver COMMOM/bt_handlepacket.c =====
#endif

#ifdef __BT_HCI_C__ // COMMOM/bt_hci.c

#define i64fmt		"ll"
#define UINT64_C(v)  (v)

#define FillOctetString(_os,_octet,_len)		\
	(_os).Octet=(u8*)(_octet);			\
	(_os).Length=(_len);

static RT_STATUS PlatformIndicateBTEvent(
	struct rtw_adapter *					padapter,
	void						*pEvntData,
	u32						dataLen
	)
{
	RT_STATUS	rt_status = RT_STATUS_FAILURE;

	RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event start, %d bytes data to Transferred!!\n", dataLen));
	RTPRINT_DATA(FIOCTL, IOCTL_BT_EVENT_DETAIL, "To transfer Hex Data :\n",
		pEvntData, dataLen);

//	if (pGBTDeviceExtension==NULL || pGBTDeviceExtension->padapter!=padapter)
//		return rt_status;

	BT_EventParse(padapter, pEvntData, dataLen);

	printk(KERN_WARNING "%s: Linux has no way to report BT event!!\n", __FUNCTION__);

	RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("BT event end, %s\n",
		(rt_status == RT_STATUS_SUCCESS)? "SUCCESS":"FAIL"));

	return rt_status;
}

// ===== Below this line is sync from SD7 driver COMMOM/bt_hci.c =====

static u8	testPMK[PMK_LEN] = {2,2,3,3,4,4,5,5,6,6,
							7,7,8,8,9,9,2,2,3,3,
							4,4,2,2,8,8,9,9,2,2,
							5,5};

static u8 bthci_GetLocalChannel(struct rtw_adapter *padapter)
{
	return padapter->mlmeextpriv.cur_channel;
}

static u8 bthci_GetCurrentEntryNum(struct rtw_adapter *padapter, u8 PhyHandle)
{
	PBT30Info pBTInfo = GET_BT_INFO(padapter);
	u8 i;

	for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++)
	{
		if ((pBTInfo->BtAsocEntry[i].bUsed == _TRUE) && (pBTInfo->BtAsocEntry[i].PhyLinkCmdData.BtPhyLinkhandle == PhyHandle))
		{
			return i;
		}
	}

	return 0xFF;
}

static void bthci_DecideBTChannel(struct rtw_adapter *padapter, u8 EntryNum)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv;
	PBT30Info pBTInfo;
	PBT_MGNT pBtMgnt;
	PBT_HCI_INFO pBtHciInfo;
	PCHNL_TXPOWER_TRIPLE pTriple_subband = NULL;
	PCOMMON_TRIPLE pTriple;
	u8 i, j, localchnl, firstRemoteLegalChnlInTriplet=0, regulatory_skipLen=0;
	u8 subbandTripletCnt = 0;


	pmlmepriv = &padapter->mlmepriv;
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtHciInfo = &pBTInfo->BtHciInfo;

	pBtMgnt->CheckChnlIsSuit = _TRUE;
	localchnl = bthci_GetLocalChannel(padapter);

	{
		pTriple = (PCOMMON_TRIPLE)&(pBtHciInfo->BTPreChnllist[COUNTRY_STR_LEN]);

		// contains country string, len is 3
		for (i = 0; i < (pBtHciInfo->BtPreChnlListLen-COUNTRY_STR_LEN); i+=3, pTriple++)
		{
			//
			// check every triplet, an triplet may be
			// regulatory extension identifier or sub-band triplet
			//
			if (pTriple->byte_1st == 0xc9)	// Regulatory Extension Identifier, skip it
			{
				RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Find Regulatory ID, regulatory class = %d\n", pTriple->byte_2nd));
				regulatory_skipLen += 3;
				pTriple_subband = NULL;
				continue;
			}
			else							// Sub-band triplet
			{
				RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Find Sub-band triplet \n"));
				subbandTripletCnt++;
				pTriple_subband = (PCHNL_TXPOWER_TRIPLE)pTriple;
				//
				// if remote first legal channel not found, then find first remote channel
				// and it's legal for our channel plan.
				//

				// search the sub-band triplet and find if remote channel is legal to our channel plan.
				for (j = pTriple_subband->FirstChnl; j < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls); j++)
				{
					RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), (" Check if chnl(%d) is legal\n", j));
					if (BT_IsLegalChannel(padapter, j))	// remote channel is legal for our channel plan.
					{
						firstRemoteLegalChnlInTriplet = j;
						RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Find first remote legal channel : %d\n", firstRemoteLegalChnlInTriplet));

						//
						// If we find a remote legal channel in the sub-band triplet
						// and only BT connection is established(local not connect to any AP or IBSS),
						// then we just switch channel to remote channel.
						//
						{
							if (!(check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_ADHOC_STATE|WIFI_AP_STATE) == _TRUE ||
								BTHCI_HsConnectionEstablished(padapter)))
							{
								pBtMgnt->BTChannel = firstRemoteLegalChnlInTriplet;
								RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Remote legal channel (%d) is selected, Local not connect to any!!\n", pBtMgnt->BTChannel));
								return;
							}
							else
							{
								if ((localchnl >= firstRemoteLegalChnlInTriplet) &&
									(localchnl < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls)))
								{
									pBtMgnt->BTChannel = localchnl;
									RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected, wifi or BT connection exists\n", pBtMgnt->BTChannel));
									return;
								}
							}
						}
						break;
					}
				}
			}
		}

		if (subbandTripletCnt)
		{
			//if any preferred channel triplet exists
			RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("There are %d sub band triplet exists, ", subbandTripletCnt));
			if (firstRemoteLegalChnlInTriplet == 0)
			{
				//no legal channel is found, reject the connection.
				RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("no legal channel is found!!\n"));
			}
			else
			{
				// Remote Legal channel is found but not match to local
				//(wifi connection exists), so reject the connection.
				RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Remote Legal channel is found but not match to local(wifi connection exists)!!\n"));
			}
			pBtMgnt->CheckChnlIsSuit = _FALSE;
		}
		else
		{
			// There are not any preferred channel triplet exists
			// Use current legal channel as the bt channel.
			RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("No sub band triplet exists!!\n"));
		}
		pBtMgnt->BTChannel = localchnl;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Local channel (%d) is selected!!\n", pBtMgnt->BTChannel));
	}
}

//Success:return _TRUE
//Fail:return _FALSE
static u8 bthci_GetAssocInfo(struct rtw_adapter *padapter, u8 EntryNum)
{
	PBT30Info		pBTInfo;
	PBT_HCI_INFO	pBtHciInfo;
	u8	tempBuf[256];
	u8	i = 0;
	u8	BaseMemoryShift = 0;
	u16	TotalLen = 0;
	PAMP_ASSOC_STRUCTURE	pAmpAsoc;

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo start\n"));
	pBTInfo = GET_BT_INFO(padapter);
	pBtHciInfo = &pBTInfo->BtHciInfo;

	if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar == 0) {
		if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen < (MAX_AMP_ASSOC_FRAG_LEN))
			TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen;
		else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen == (MAX_AMP_ASSOC_FRAG_LEN))
			TotalLen = MAX_AMP_ASSOC_FRAG_LEN;
	} else if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar > 0)
		TotalLen = pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar;

	while ((pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar >= BaseMemoryShift) || TotalLen > BaseMemoryShift) {
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("GetAssocInfo, TotalLen=%d, BaseMemoryShift=%d\n",TotalLen,BaseMemoryShift));
		memcpy(tempBuf,
			(u8*)pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment+BaseMemoryShift,
			TotalLen-BaseMemoryShift);
		RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, "GetAssocInfo :\n",
			tempBuf, TotalLen-BaseMemoryShift);

		pAmpAsoc = (PAMP_ASSOC_STRUCTURE)tempBuf;
		pAmpAsoc->Length = EF2Byte(pAmpAsoc->Length);
		BaseMemoryShift += 3 + pAmpAsoc->Length;

		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TypeID = 0x%x, ", pAmpAsoc->TypeID));
		RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Hex Data: \n", pAmpAsoc->Data, pAmpAsoc->Length);
		switch (pAmpAsoc->TypeID) {
		case AMP_MAC_ADDR:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_MAC_ADDR\n"));
			if (pAmpAsoc->Length > 6)
				return _FALSE;
			memcpy(pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, pAmpAsoc->Data,6);
			RTPRINT_ADDR(FIOCTL, IOCTL_BT_HCICMD, ("Remote Mac address \n"), pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr);
			break;
		case AMP_PREFERRED_CHANNEL_LIST:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_PREFERRED_CHANNEL_LIST\n"));
			pBtHciInfo->BtPreChnlListLen=pAmpAsoc->Length;
			memcpy(pBtHciInfo->BTPreChnllist,
				pAmpAsoc->Data,
				pBtHciInfo->BtPreChnlListLen);
			RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, "Preferred channel list : \n", pBtHciInfo->BTPreChnllist, pBtHciInfo->BtPreChnlListLen);
			bthci_DecideBTChannel(padapter,EntryNum);
			break;
		case AMP_CONNECTED_CHANNEL:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_CONNECTED_CHANNEL\n"));
			pBtHciInfo->BTConnectChnlListLen=pAmpAsoc->Length;
			memcpy(pBtHciInfo->BTConnectChnllist,
				pAmpAsoc->Data,
				pBtHciInfo->BTConnectChnlListLen);
			break;
		case AMP_80211_PAL_CAP_LIST:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> AMP_80211_PAL_CAP_LIST\n"));
			pBTInfo->BtAsocEntry[EntryNum].BTCapability=*(u32 *)(pAmpAsoc->Data);
			if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000001) {
				// TODO:

				//Signifies PAL capable of utilizing received activity reports.
			}
			if (pBTInfo->BtAsocEntry[EntryNum].BTCapability & 0x00000002) {
				// TODO:
				//Signifies PAL is capable of utilizing scheduling information received in an activity reports.
			}
			break;
		case AMP_80211_PAL_VISION:
			pBtHciInfo->BTPalVersion=*(u8 *)(pAmpAsoc->Data);
			pBtHciInfo->BTPalCompanyID=*(u16 *)(((u8 *)(pAmpAsoc->Data))+1);
			pBtHciInfo->BTPalsubversion=*(u16 *)(((u8 *)(pAmpAsoc->Data))+3);
			RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("==> AMP_80211_PAL_VISION PalVersion  0x%x, PalCompanyID  0x%x, Palsubversion 0x%x\n",
			pBtHciInfo->BTPalVersion,
			pBtHciInfo->BTPalCompanyID,
			pBtHciInfo->BTPalsubversion));
			break;
		default:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("==> Unsupport TypeID !!\n"));
			break;
		}
		i++;
	}
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("GetAssocInfo end\n"));

	return _TRUE;
}

static u8 bthci_AddEntry(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	u8			i;

	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;

	for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++) {
		if (pBTInfo->BtAsocEntry[i].bUsed == _FALSE) {
			pBTInfo->BtAsocEntry[i].bUsed = _TRUE;
			pBtMgnt->CurrentConnectEntryNum = i;
			break;
		}
	}

	if (i == MAX_BT_ASOC_ENTRY_NUM) {
		RTPRINT(FIOCTL, IOCTL_STATE, ("bthci_AddEntry(), Add entry fail!!\n"));
		return _FALSE;
	}
	return _TRUE;
}

static u8 bthci_DiscardTxPackets(struct rtw_adapter *padapter, u16 LLH)
{
	return _FALSE;
}

static u8
bthci_CheckLogLinkBehavior(
	struct rtw_adapter *					padapter,
	HCI_FLOW_SPEC			TxFlowSpec
	)
{
	u8	ID = TxFlowSpec.Identifier;
	u8	ServiceType = TxFlowSpec.ServiceType;
	u16	MaxSDUSize = TxFlowSpec.MaximumSDUSize;
	u32	SDUInterArrivatime = TxFlowSpec.SDUInterArrivalTime;
	u8	match = _FALSE;

	switch (ID) {
	case 1:
		if (ServiceType == BT_LL_BE) {
			match = _TRUE;
			RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  TX best effort flowspec\n"));
		} else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 0xffff)) {
			match = _TRUE;
			RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  RX guaranteed latency flowspec\n"));
		} else if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 2500)) {
			RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  RX guaranteed Large latency flowspec\n"));
		}
		break;
	case 2:
		if (ServiceType == BT_LL_BE) {
			match = _TRUE;
			RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  RX best effort flowspec\n"));

		}
		break;
	case 3:
		if ((ServiceType == BT_LL_GU) && (MaxSDUSize == 1492)) {
			match=_TRUE;
			RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  TX guaranteed latency flowspec\n"));
		} else if ((ServiceType==BT_LL_GU) && (MaxSDUSize==2500)) {
			RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  TX guaranteed Large latency flowspec\n"));
		}
		break;
	case 4:
		if (ServiceType == BT_LL_BE) {
			if ((SDUInterArrivatime == 0xffffffff) && (ServiceType == BT_LL_BE) && (MaxSDUSize == 1492)) {
				match = _TRUE;
				RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  TX/RX aggregated best effort flowspec\n"));
			}
		} else if (ServiceType == BT_LL_GU) {
			if (SDUInterArrivatime == 100) {
				match = _TRUE;
				RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  TX/RX guaranteed bandwidth flowspec\n"));
			}
		}
		break;
	default:
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Logical Link Type =  Unknow Type !!!!!!!!\n"));
		break;
	}

	RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("ID=0x%x, ServiceType=0x%x, MaximumSDUSize=0x%x, SDUInterArrivalTime=0x%x, AccessLatency=0x%x, FlushTimeout=0x%x\n",
	TxFlowSpec.Identifier, TxFlowSpec.ServiceType, MaxSDUSize, SDUInterArrivatime, TxFlowSpec.AccessLatency, TxFlowSpec.FlushTimeout));
	return match;
}

static void
bthci_SelectFlowType(
	struct rtw_adapter *					padapter,
	BT_LL_FLOWSPEC			TxLLFlowSpec,
	BT_LL_FLOWSPEC			RxLLFlowSpec,
	PHCI_FLOW_SPEC		TxFlowSpec,
	PHCI_FLOW_SPEC		RxFlowSpec
	)
{
	switch (TxLLFlowSpec)
	{
		case BT_TX_BE_FS:
		{
			TxFlowSpec->Identifier = 0x1;
			TxFlowSpec->ServiceType = BT_LL_BE;
			TxFlowSpec->MaximumSDUSize = 0xffff;
			TxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			TxFlowSpec->AccessLatency = 0xffffffff;
			TxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_RX_BE_FS:
		{
			RxFlowSpec->Identifier = 0x2;
			RxFlowSpec->ServiceType = BT_LL_BE;
			RxFlowSpec->MaximumSDUSize = 0xffff;
			RxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			RxFlowSpec->AccessLatency = 0xffffffff;
			RxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_TX_GU_FS:
		{
			TxFlowSpec->Identifier = 0x3;
			TxFlowSpec->ServiceType = BT_LL_GU;
			TxFlowSpec->MaximumSDUSize = 1492;
			TxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			TxFlowSpec->AccessLatency = 10000;
			TxFlowSpec->FlushTimeout = 10000;
			break;
		}
		case BT_RX_GU_FS:
		{
			RxFlowSpec->Identifier = 0x1;
			RxFlowSpec->ServiceType = BT_LL_GU;
			RxFlowSpec->MaximumSDUSize = 0xffff;
			RxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			RxFlowSpec->AccessLatency = 10000;
			RxFlowSpec->FlushTimeout = 10000;
			break;
		}
		case BT_TX_BE_AGG_FS:
		{
			TxFlowSpec->Identifier = 0x4;
			TxFlowSpec->ServiceType = BT_LL_BE;
			TxFlowSpec->MaximumSDUSize = 1492;
			TxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			TxFlowSpec->AccessLatency = 0xffffffff;
			TxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_RX_BE_AGG_FS:
		{
			RxFlowSpec->Identifier = 0x4;
			RxFlowSpec->ServiceType = BT_LL_BE;
			RxFlowSpec->MaximumSDUSize = 1492;
			RxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			RxFlowSpec->AccessLatency = 0xffffffff;
			RxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_TX_GU_BW_FS:
		{
			TxFlowSpec->Identifier = 0x4;
			TxFlowSpec->ServiceType = BT_LL_GU;
			TxFlowSpec->MaximumSDUSize = 1492;
			TxFlowSpec->SDUInterArrivalTime = 100;
			TxFlowSpec->AccessLatency = 0xffffffff;
			TxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_RX_GU_BW_FS:
		{
			RxFlowSpec->Identifier = 0x4;
			RxFlowSpec->ServiceType = BT_LL_GU;
			RxFlowSpec->MaximumSDUSize = 1492;
			RxFlowSpec->SDUInterArrivalTime = 100;
			RxFlowSpec->AccessLatency = 0xffffffff;
			RxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_TX_GU_LARGE_FS:
		{
			TxFlowSpec->Identifier = 0x3;
			TxFlowSpec->ServiceType = BT_LL_GU;
			TxFlowSpec->MaximumSDUSize = 2500;
			TxFlowSpec->SDUInterArrivalTime = 0x1;
			TxFlowSpec->AccessLatency = 10000;
			TxFlowSpec->FlushTimeout = 10000;
			break;
		}
		case BT_RX_GU_LARGE_FS:
		{
			RxFlowSpec->Identifier = 0x1;
			RxFlowSpec->ServiceType = BT_LL_GU;
			RxFlowSpec->MaximumSDUSize = 2500;
			RxFlowSpec->SDUInterArrivalTime = 0x1;
			RxFlowSpec->AccessLatency = 10000;
			RxFlowSpec->FlushTimeout = 10000;
			break;
		}
		default:
			break;
	}

	switch (RxLLFlowSpec)
	{
		case BT_TX_BE_FS:
		{
			TxFlowSpec->Identifier = 0x1;
			TxFlowSpec->ServiceType = BT_LL_BE;
			TxFlowSpec->MaximumSDUSize = 0xffff;
			TxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			TxFlowSpec->AccessLatency = 0xffffffff;
			TxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_RX_BE_FS:
		{
			RxFlowSpec->Identifier = 0x2;
			RxFlowSpec->ServiceType = BT_LL_BE;
			RxFlowSpec->MaximumSDUSize = 0xffff;
			RxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			RxFlowSpec->AccessLatency = 0xffffffff;
			RxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_TX_GU_FS:
		{
			TxFlowSpec->Identifier = 0x3;
			TxFlowSpec->ServiceType = BT_LL_GU;
			TxFlowSpec->MaximumSDUSize = 1492;
			TxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			TxFlowSpec->AccessLatency = 10000;
			TxFlowSpec->FlushTimeout = 10000;
			break;
		}
		case BT_RX_GU_FS:
		{
			RxFlowSpec->Identifier = 0x1;
			RxFlowSpec->ServiceType = BT_LL_GU;
			RxFlowSpec->MaximumSDUSize = 0xffff;
			RxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			RxFlowSpec->AccessLatency = 10000;
			RxFlowSpec->FlushTimeout = 10000;
			break;
		}
		case BT_TX_BE_AGG_FS:
		{
			TxFlowSpec->Identifier = 0x4;
			TxFlowSpec->ServiceType = BT_LL_BE;
			TxFlowSpec->MaximumSDUSize = 1492;
			TxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			TxFlowSpec->AccessLatency = 0xffffffff;
			TxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_RX_BE_AGG_FS:
		{
			RxFlowSpec->Identifier = 0x4;
			RxFlowSpec->ServiceType = BT_LL_BE;
			RxFlowSpec->MaximumSDUSize = 1492;
			RxFlowSpec->SDUInterArrivalTime = 0xffffffff;
			RxFlowSpec->AccessLatency = 0xffffffff;
			RxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_TX_GU_BW_FS:
		{
			TxFlowSpec->Identifier = 0x4;
			TxFlowSpec->ServiceType = BT_LL_GU;
			TxFlowSpec->MaximumSDUSize = 1492;
			TxFlowSpec->SDUInterArrivalTime = 100;
			TxFlowSpec->AccessLatency = 0xffffffff;
			TxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_RX_GU_BW_FS:
		{
			RxFlowSpec->Identifier = 0x4;
			RxFlowSpec->ServiceType = BT_LL_GU;
			RxFlowSpec->MaximumSDUSize = 1492;
			RxFlowSpec->SDUInterArrivalTime = 100;
			RxFlowSpec->AccessLatency = 0xffffffff;
			RxFlowSpec->FlushTimeout = 0xffffffff;
			break;
		}
		case BT_TX_GU_LARGE_FS:
		{
			TxFlowSpec->Identifier = 0x3;
			TxFlowSpec->ServiceType = BT_LL_GU;
			TxFlowSpec->MaximumSDUSize = 2500;
			TxFlowSpec->SDUInterArrivalTime = 0x1;
			TxFlowSpec->AccessLatency = 10000;
			TxFlowSpec->FlushTimeout = 10000;
			break;
		}
		case BT_RX_GU_LARGE_FS:
		{
			RxFlowSpec->Identifier = 0x1;
			RxFlowSpec->ServiceType = BT_LL_GU;
			RxFlowSpec->MaximumSDUSize = 2500;
			RxFlowSpec->SDUInterArrivalTime = 0x1;
			RxFlowSpec->AccessLatency = 10000;
			RxFlowSpec->FlushTimeout = 10000;
			break;
		}
		default:
			break;
	}
}

static u16
bthci_AssocMACAddr(
	struct rtw_adapter *	padapter,
	void	*pbuf
	)
{
	PAMP_ASSOC_STRUCTURE pAssoStrc = (PAMP_ASSOC_STRUCTURE)pbuf;
/*
	u8	FakeAddress[6],i;

	for (i=0;i<6;i++)
	{
		FakeAddress[i]=i;
	}
*/
	pAssoStrc->TypeID = AMP_MAC_ADDR;
	pAssoStrc->Length = 0x06;
	//	memcpy(&pAssoStrc->Data[0], Adapter->CurrentAddress, 6);
	memcpy(&pAssoStrc->Data[0], padapter->eeprompriv.mac_addr, 6);
	//memcpy(&pAssoStrc->Data[0], FakeAddress, 6);
	RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("AssocMACAddr : \n"), pAssoStrc, pAssoStrc->Length+3);

	return (pAssoStrc->Length+3);
}

static u16
bthci_PALCapabilities(
	struct rtw_adapter *	padapter,
	void	*pbuf
	)
{
	PAMP_ASSOC_STRUCTURE pAssoStrc = (PAMP_ASSOC_STRUCTURE)pbuf;

	pAssoStrc->TypeID = AMP_80211_PAL_CAP_LIST;
	pAssoStrc->Length = 0x04;

	pAssoStrc->Data[0] = 0x00;
	pAssoStrc->Data[1] = 0x00;

	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("PALCapabilities : \n"), pAssoStrc, pAssoStrc->Length+3);
	RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("PALCapabilities \n"));

	RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n Content =0x0000\n",
		pAssoStrc->TypeID,
		pAssoStrc->Length));

	return (pAssoStrc->Length+3);
}

static u16
bthci_AssocPreferredChannelList(
	struct rtw_adapter *		padapter,
	void	*pbuf,
	u8		EntryNum
	)
{
	PBT30Info				pBTInfo;
	PAMP_ASSOC_STRUCTURE	pAssoStrc;
	PAMP_PREF_CHNL_REGULATORY pReg;
	PCHNL_TXPOWER_TRIPLE pTripleIE, pTriple;
	char	ctrString[3] = {'X', 'X', 'X'};
	u32	len = 0;
	u8	i=0, NumTriples=0, preferredChnl;


	pBTInfo = GET_BT_INFO(padapter);
//	pDot11dInfo = GET_DOT11D_INFO(pMgntInfo);
	pAssoStrc = (PAMP_ASSOC_STRUCTURE)pbuf;
	pReg = (PAMP_PREF_CHNL_REGULATORY)&pAssoStrc->Data[3];

	preferredChnl = bthci_GetLocalChannel(padapter);
	pAssoStrc->TypeID = AMP_PREFERRED_CHANNEL_LIST;
	{
		// locale unknown
		memcpy(&pAssoStrc->Data[0], &ctrString[0], 3);
		pReg->reXId = 201;
		pReg->regulatoryClass = 254;
		pReg->coverageClass = 0;
		len += 6;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("PREFERRED_CHNL_LIST\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("XXX, 201,254,0\n"));
		// at the following, chnl 1~11 should be contained
		pTriple = (PCHNL_TXPOWER_TRIPLE)&pAssoStrc->Data[len];

		// (1) if any wifi or bt HS connection exists
		if ((pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR) ||
			(check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE|WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == _TRUE) ||
			BTHCI_HsConnectionEstablished(padapter))
		{
			pTriple->FirstChnl = preferredChnl;
			pTriple->NumChnls = 1;
			pTriple->MaxTxPowerInDbm = 20;
			len += 3;
			RTPRINT(FIOCTL, (IOCTL_BT_HCICMD | IOCTL_BT_LOGO), ("First Channel = %d, Channel Num = %d, MaxDbm = %d\n",
				pTriple->FirstChnl,
				pTriple->NumChnls,
				pTriple->MaxTxPowerInDbm));

			//pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
		}
	}
	pAssoStrc->Length = (u16)len;
	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD, ("AssocPreferredChannelList : \n"), pAssoStrc, pAssoStrc->Length+3);

	return (pAssoStrc->Length+3);
}

static u16 bthci_AssocPALVer(struct rtw_adapter *padapter, void *pbuf)
{
	PAMP_ASSOC_STRUCTURE pAssoStrc = (PAMP_ASSOC_STRUCTURE)pbuf;
	u8 *pu1Tmp;
	u16	*pu2Tmp;

	pAssoStrc->TypeID = AMP_80211_PAL_VISION;
	pAssoStrc->Length = 0x5;
	pu1Tmp = &pAssoStrc->Data[0];
	*pu1Tmp = 0x1;	// PAL Version
	pu2Tmp = (u16*)&pAssoStrc->Data[1];
	*pu2Tmp = 0x5D;	// SIG Company identifier of 802.11 PAL vendor
	pu2Tmp = (u16*)&pAssoStrc->Data[3];
	*pu2Tmp = 0x1;	// PAL Sub-version specifier

	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("AssocPALVer : \n"), pAssoStrc, pAssoStrc->Length+3);
	RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("AssocPALVer \n"));

	RTPRINT(FIOCTL, IOCTL_BT_LOGO, (" TypeID = 0x%x,\n Length = 0x%x,\n PAL Version = 0x01,\n PAL vendor = 0x01,\n PAL Sub-version specifier = 0x01\n",
		pAssoStrc->TypeID,
		pAssoStrc->Length));
	return (pAssoStrc->Length+3);
}

static u16
bthci_ReservedForTestingPLV(
	struct rtw_adapter *	padapter,
	void	*pbuf
	)
{
	PAMP_ASSOC_STRUCTURE pAssoStrc = (PAMP_ASSOC_STRUCTURE)pbuf;

	pAssoStrc->TypeID = AMP_RESERVED_FOR_TESTING;
	pAssoStrc->Length = 0x10;

	pAssoStrc->Data[0] = 0x00;
	pAssoStrc->Data[1] = 0x01;
	pAssoStrc->Data[2] = 0x02;
	pAssoStrc->Data[3] = 0x03;
	pAssoStrc->Data[4] = 0x04;
	pAssoStrc->Data[5] = 0x05;
	pAssoStrc->Data[6] = 0x06;
	pAssoStrc->Data[7] = 0x07;
	pAssoStrc->Data[8] = 0x08;
	pAssoStrc->Data[9] = 0x09;
	pAssoStrc->Data[10] = 0x0a;
	pAssoStrc->Data[11] = 0x0b;
	pAssoStrc->Data[12] = 0x0c;
	pAssoStrc->Data[13] = 0x0d;
	pAssoStrc->Data[14] = 0x0e;
	pAssoStrc->Data[15] = 0x0f;

	return (pAssoStrc->Length+3);
}

static u8 bthci_CheckRfStateBeforeConnect(struct rtw_adapter *padapter)
{
	PBT30Info				pBTInfo;
	rt_rf_power_state		RfState;


	pBTInfo = GET_BT_INFO(padapter);

//	rtw_hal_get_hwreg(padapter, HW_VAR_RF_STATE, (u8*)(&RfState));
	RfState = padapter->pwrctrlpriv.rf_pwrstate;

	if (RfState != rf_on)
	{
		PlatformSetTimer(padapter, &pBTInfo->BTPsDisableTimer, 50);
		return _FALSE;
	}

	return _TRUE;
}

static u8
bthci_ConstructScanList(
	PBT30Info		pBTInfo,
	u8			*pChannels,
	u8			*pNChannels,
	PRT_SCAN_TYPE	pScanType,
	u16			*pDuration
	)
{
	struct rtw_adapter *				padapter;
	PBT_HCI_INFO				pBtHciInfo;
	PCHNL_TXPOWER_TRIPLE	pTriple_subband;
	PCOMMON_TRIPLE			pTriple;
	u8					chnl, i, j, tripleLetsCnt=0;


	padapter = pBTInfo->padapter;
	pBtHciInfo = &pBTInfo->BtHciInfo;
	*pNChannels = 0;
	*pScanType = SCAN_ACTIVE;
	*pDuration = 200;

	pTriple = (PCOMMON_TRIPLE)&(pBtHciInfo->BTPreChnllist[COUNTRY_STR_LEN]);

	// contains country string, len is 3
	for (i = 0; i < (pBtHciInfo->BtPreChnlListLen-COUNTRY_STR_LEN); i+=3, pTriple++)
	{
		if (pTriple->byte_1st == 0xc9)	// Regulatory Extension Identifier, skip it
			continue;
		else							// Sub-band triplet
		{
			tripleLetsCnt++;
			pTriple_subband = (PCHNL_TXPOWER_TRIPLE)pTriple;

			// search the sub-band triplet and find if remote channel is legal to our channel plan.
			for (chnl = pTriple_subband->FirstChnl; chnl < (pTriple_subband->FirstChnl+pTriple_subband->NumChnls); chnl++)
			{
				if (BT_IsLegalChannel(padapter, chnl))	// remote channel is legal for our channel plan.
				{
					//DbgPrint("cosa insert chnl(%d) into scan list\n", chnl);
					pChannels[*pNChannels] = chnl;
					(*pNChannels)++;
				}
			}
		}
	}

	if (tripleLetsCnt == 0)
	{
		// Fill chnl 1~ chnl 11
		for (chnl=1; chnl<12; chnl++)
		{
			//DbgPrint("cosa insert chnl(%d) into scan list\n", chnl);
			pChannels[*pNChannels] = chnl;
			(*pNChannels)++;
		}
	}

	if (*pNChannels == 0)
		return _FALSE;
	else
		return _TRUE;
}

static void bthci_ResponderStartToScan(struct rtw_adapter *padapter)
{
}

static u8
bthci_PhyLinkConnectionInProgress(
	struct rtw_adapter *	padapter,
	u8		PhyLinkHandle
	)
{
	PBT30Info	pBTInfo;
	PBT_MGNT	pBtMgnt;


	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->bPhyLinkInProgress &&
		(pBtMgnt->BtCurrentPhyLinkhandle == PhyLinkHandle))
	{
		return _TRUE;
	}
	return _FALSE;
}

static void
bthci_ResetFlowSpec(
	struct rtw_adapter *	padapter,
	u8	EntryNum,
	u8	index
	)
{
	PBT30Info	pBTinfo;


	pBTinfo = GET_BT_INFO(padapter);

	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtLogLinkhandle = 0;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtPhyLinkhandle = 0;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCompleteEventIsSet = _FALSE;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].bLLCancelCMDIsSetandComplete = _FALSE;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].BtTxFlowSpecID = 0;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].TxPacketCount = 0;

	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.Identifier = 0x01;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.MaximumSDUSize = 0xffff;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.SDUInterArrivalTime = 0xffffffff;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.AccessLatency = 0xffffffff;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Tx_Flow_Spec.FlushTimeout = 0xffffffff;

	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.Identifier = 0x01;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.ServiceType = SERVICE_BEST_EFFORT;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.MaximumSDUSize = 0xffff;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.SDUInterArrivalTime = 0xffffffff;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.AccessLatency = 0xffffffff;
	pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[index].Rx_Flow_Spec.FlushTimeout = 0xffffffff;
}

static void bthci_ResetEntry(struct rtw_adapter *padapter, u8 EntryNum)
{
	PBT30Info		pBTinfo;
	PBT_MGNT		pBtMgnt;
	u8	j;


	pBTinfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTinfo->BtMgnt;

	pBTinfo->BtAsocEntry[EntryNum].bUsed=_FALSE;
	pBTinfo->BtAsocEntry[EntryNum].BtCurrentState=HCI_STATE_DISCONNECTED;
	pBTinfo->BtAsocEntry[EntryNum].BtNextState=HCI_STATE_DISCONNECTED;

	pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocRemLen=0;
	pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = 0;
	if (pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment != NULL)
	{
		memset(pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment, 0, TOTAL_ALLOCIATE_ASSOC_LEN);
	}
	pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar=0;

	pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType = 0;
	pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = 0;
	memset(pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, 0, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen);
	pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen=0;

	pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout=0x3e80;//0x640; //0.625ms*1600=1000ms, 0.625ms*16000=10000ms

	pBTinfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_NONE;

	pBTinfo->BtAsocEntry[EntryNum].mAssoc=_FALSE;
	pBTinfo->BtAsocEntry[EntryNum].b4waySuccess = _FALSE;

	// Reset BT WPA
	pBTinfo->BtAsocEntry[EntryNum].KeyReplayCounter = 0;
	pBTinfo->BtAsocEntry[EntryNum].BTWPAAuthState = STATE_WPA_AUTH_UNINITIALIZED;

	pBTinfo->BtAsocEntry[EntryNum].bSendSupervisionPacket=_FALSE;
	pBTinfo->BtAsocEntry[EntryNum].NoRxPktCnt=0;
	pBTinfo->BtAsocEntry[EntryNum].ShortRangeMode = 0;
	pBTinfo->BtAsocEntry[EntryNum].rxSuvpPktCnt = 0;

	for (j=0; j<MAX_LOGICAL_LINK_NUM; j++)
	{
		bthci_ResetFlowSpec(padapter, EntryNum, j);
	}

	pBtMgnt->BTAuthCount = 0;
	pBtMgnt->BTAsocCount = 0;
	pBtMgnt->BTCurrentConnectType = BT_DISCONNECT;
	pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT;

	HALBT_RemoveKey(padapter, EntryNum);
}

static void
bthci_RemoveEntryByEntryNum(
	struct rtw_adapter *	padapter,
	u8		EntryNum
	)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	bthci_ResetEntry(padapter, EntryNum);

	if (pBtMgnt->CurrentBTConnectionCnt>0)
		pBtMgnt->CurrentBTConnectionCnt--;

	RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d!!\n",
		pBtMgnt->CurrentBTConnectionCnt));

	if (pBtMgnt->CurrentBTConnectionCnt > 0)
		pBtMgnt->BtOperationOn = _TRUE;
	else
	{
		pBtMgnt->BtOperationOn = _FALSE;
		RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation OFF!!\n"));
	}

	if (pBtMgnt->BtOperationOn == _FALSE)
	{
		PlatformCancelTimer(padapter, &pBTInfo->BTSupervisionPktTimer);
#if (SENDTXMEHTOD == 0)
		PlatformCancelTimer(padapter, &pBTInfo->BTHCISendAclDataTimer);
#endif
		PlatformCancelTimer(padapter, &pBTInfo->BTHCIDiscardAclDataTimer);
		PlatformCancelTimer(padapter, &pBTInfo->BTBeaconTimer);
		pBtMgnt->bStartSendSupervisionPkt = _FALSE;
#if (RTS_CTS_NO_LEN_LIMIT == 1)
		rtw_write32(padapter, 0x4c8, 0xc140402);
#endif
	}
}

static u8
bthci_CommandCompleteHeader(
	u8		*pbuf,
	u16		OGF,
	u16		OCF,
	HCI_STATUS	status
	)
{
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)pbuf;
	u8	NumHCI_Comm = 0x1;


	PPacketIrpEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
	PPacketIrpEvent->Data[0] = NumHCI_Comm;	//packet #
	PPacketIrpEvent->Data[1] = HCIOPCODELOW(OCF, OGF);
	PPacketIrpEvent->Data[2] = HCIOPCODEHIGHT(OCF, OGF);

	if (OGF == OGF_EXTENSION)
	{
		if (OCF == HCI_SET_RSSI_VALUE)
		{
			RTPRINT(FIOCTL,(IOCTL_BT_EVENT_PERIODICAL), ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n",
				NumHCI_Comm,(HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF));
		}
		else
		{
			RTPRINT(FIOCTL,(IOCTL_BT_HCICMD_EXT), ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n",
				NumHCI_Comm,(HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF));
		}
	}
	else
	{
		RTPRINT(FIOCTL,(IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("[BT event], CommandComplete, Num_HCI_Comm = 0x%x, Opcode = 0x%02x%02x, status = 0x%x, OGF = 0x%x, OCF = 0x%x\n",
			NumHCI_Comm,(HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), status, OGF, OCF));
	}
	return 3;
}

static u8 bthci_ExtensionEventHeader(u8 *pbuf, u8 extensionEvent)
{
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)pbuf;
	PPacketIrpEvent->EventCode = HCI_EVENT_EXTENSION_MOTO;
	PPacketIrpEvent->Data[0] = extensionEvent;	//extension event code

	return 1;
}

static u8 bthci_ExtensionEventHeaderRtk(u8 *pbuf, u8 extensionEvent)
{
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)pbuf;
	PPacketIrpEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
	PPacketIrpEvent->Data[0] = extensionEvent;	//extension event code

	return 1;
}

static RT_STATUS
bthci_IndicateEvent(
	struct rtw_adapter *	padapter,
	void		*pEvntData,
	u32		dataLen
	)
{
	RT_STATUS	rt_status;

	rt_status = PlatformIndicateBTEvent(padapter, pEvntData, dataLen);

	return rt_status;
}

static void
bthci_EventWriteRemoteAmpAssoc(
	struct rtw_adapter *	padapter,
	HCI_STATUS	status,
	u8		PLHandle
	)
{
	u8 localBuf[TmpLocalBufSize] = "";
	u8 *pRetPar;
	u8 len = 0;
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

	len += bthci_CommandCompleteHeader(&localBuf[0],
		OGF_STATUS_PARAMETERS,
		HCI_WRITE_REMOTE_AMP_ASSOC,
		status);
	RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("PhyLinkHandle = 0x%x, status = %d\n", PLHandle, status));
	// Return parameters starts from here
	pRetPar = &PPacketIrpEvent->Data[len];
	pRetPar[0] = status;		//status
	pRetPar[1] = PLHandle;
	len += 2;
	PPacketIrpEvent->Length = len;

	bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
}

static void
bthci_EventEnhancedFlushComplete(
	struct rtw_adapter *					padapter,
	u16					LLH
	)
{
	u8	localBuf[4] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("EventEnhancedFlushComplete, LLH = 0x%x\n", LLH));

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_ENHANCED_FLUSH_COMPLETE;
	PPacketIrpEvent->Length=2;
	//Logical link handle
	PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LLH);
	PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LLH);

	bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
}

static void
bthci_EventShortRangeModeChangeComplete(
	struct rtw_adapter *					padapter,
	HCI_STATUS				HciStatus,
	u8					ShortRangeState,
	u8					EntryNum
	)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	u8	localBuf[5] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE))
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Short Range Mode Change Complete, Ignore to send this event due to event mask page 2\n"));
		return;
	}
	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Short Range Mode Change Complete, Status = %d\n , PLH = 0x%x\n, Short_Range_Mode_State = 0x%x\n",
		HciStatus, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle, ShortRangeState));

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_SHORT_RANGE_MODE_CHANGE_COMPLETE;
	PPacketIrpEvent->Length=3;
	PPacketIrpEvent->Data[0] = HciStatus;
	PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
	PPacketIrpEvent->Data[2] = ShortRangeState;
	bthci_IndicateEvent(padapter, PPacketIrpEvent, 5);
}

static void
bthci_EventSendFlowSpecModifyComplete(
	struct rtw_adapter *					padapter,
	HCI_STATUS				HciStatus,
	u16					logicHandle
	)
{
	u8	localBuf[5] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;

	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE))
	{
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("[BT event], Flow Spec Modify Complete, Ignore to send this event due to event mask page 2\n"));
		return;
	}
	RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("[BT event], Flow Spec Modify Complete, status = 0x%x, LLH = 0x%x\n",HciStatus,logicHandle));
	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_FLOW_SPEC_MODIFY_COMPLETE;
	PPacketIrpEvent->Length=3;

	PPacketIrpEvent->Data[0] = HciStatus;
	//Logical link handle
	PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(logicHandle);
	PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(logicHandle);

	bthci_IndicateEvent(padapter, PPacketIrpEvent, 5);
}

static void
bthci_EventExtGetBTRSSI(
	struct rtw_adapter *					padapter,
	u16						ConnectionHandle
	)
{
	u8 len = 0;
	u8	localBuf[7] = "";
	u8 *pRetPar;
	u16	*pu2Temp;
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

	len += bthci_ExtensionEventHeader(&localBuf[0],
			HCI_EVENT_GET_BT_RSSI);

	// Return parameters starts from here
	pRetPar = &PPacketIrpEvent->Data[len];
	pu2Temp = (u16*)&pRetPar[0];
	*pu2Temp = ConnectionHandle;
	len += 2;

	PPacketIrpEvent->Length = len;
	if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS)
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("[BT event], Get BT RSSI, Connection Handle = 0x%x, Extension event code = 0x%x\n",
			ConnectionHandle, HCI_EVENT_GET_BT_RSSI));
	}
}

static void
bthci_EventExtWifiScanNotify(
	struct rtw_adapter *					padapter,
	u8						scanType
	)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	u8 len = 0;
	u8 localBuf[7] = "";
	u8 *pRetPar;
	u8 *pu1Temp;
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	if (!pBtMgnt->BtOperationOn)
		return;

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

	len += bthci_ExtensionEventHeaderRtk(&localBuf[0], HCI_EVENT_EXT_WIFI_SCAN_NOTIFY);

	// Return parameters starts from here
	pRetPar = &PPacketIrpEvent->Data[len];
	pu1Temp = (u8*)&pRetPar[0];
	*pu1Temp = scanType;
	len += 1;

	PPacketIrpEvent->Length = len;

	if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS)
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Wifi scan notify, scan type = %d\n",
			scanType));
	}
}


static void
bthci_EventAMPReceiverReport(
	struct rtw_adapter *	padapter,
	u8		Reason
	)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	if (pBtHciInfo->bTestNeedReport)
	{
		u8 localBuf[20] = "";
		u32	*pu4Temp;
		u16	*pu2Temp;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;


		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_EVENT_AMP_RECEIVER_REPORT \n"));
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
		PPacketIrpEvent->EventCode = HCI_EVENT_AMP_RECEIVER_REPORT;
		PPacketIrpEvent->Length = 2;

		PPacketIrpEvent->Data[0] = pBtHciInfo->TestCtrType;

		PPacketIrpEvent->Data[1] =Reason;

		pu4Temp = (u32*)&PPacketIrpEvent->Data[2];
		*pu4Temp = pBtHciInfo->TestEventType;

		pu2Temp = (u16*)&PPacketIrpEvent->Data[6];
		*pu2Temp = pBtHciInfo->TestNumOfFrame;

		pu2Temp = (u16*)&PPacketIrpEvent->Data[8];
		*pu2Temp = pBtHciInfo->TestNumOfErrFrame;

		pu4Temp = (u32*)&PPacketIrpEvent->Data[10];
		*pu4Temp = pBtHciInfo->TestNumOfBits;

		pu4Temp = (u32*)&PPacketIrpEvent->Data[14];
		*pu4Temp = pBtHciInfo->TestNumOfErrBits;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, 20);

		//Return to Idel state with RX and TX off.

	}

	pBtHciInfo->TestNumOfFrame = 0x00;
}

static void
bthci_EventChannelSelected(
	struct rtw_adapter *				padapter,
	u8				EntryNum
	)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	u8	localBuf[3] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_CHANNEL_SELECT))
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Channel Selected, Ignore to send this event due to event mask page 2\n"));
		return;
	}

	RTPRINT(FIOCTL, IOCTL_BT_EVENT|IOCTL_STATE, ("[BT event], Channel Selected, PhyLinkHandle %d\n",
		pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle));

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_CHANNEL_SELECT;
	PPacketIrpEvent->Length=1;
	PPacketIrpEvent->Data[0] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
	bthci_IndicateEvent(padapter, PPacketIrpEvent, 3);
}

static void
bthci_EventDisconnectPhyLinkComplete(
	struct rtw_adapter *					padapter,
	HCI_STATUS				HciStatus,
	HCI_STATUS				Reason,
	u8					EntryNum
	)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	u8	localBuf[5] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE))
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Physical Link Complete, Ignore to send this event due to event mask page 2\n"));
		return;
	}
	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Physical Link Complete, Status = 0x%x, PLH = 0x%x Reason =0x%x\n",
		HciStatus,pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle,Reason));
	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE;
	PPacketIrpEvent->Length=3;
	PPacketIrpEvent->Data[0] = HciStatus;
	PPacketIrpEvent->Data[1] = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
	PPacketIrpEvent->Data[2] = Reason;
	bthci_IndicateEvent(padapter, PPacketIrpEvent, 5);
}

static void
bthci_EventPhysicalLinkComplete(
	struct rtw_adapter *					padapter,
	HCI_STATUS				HciStatus,
	u8					EntryNum,
	u8					PLHandle
	)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	PBT_DBG			pBtDbg=&pBTInfo->BtDbg;
	u8			localBuf[4] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
	u8			PL_handle;

	pBtMgnt->bPhyLinkInProgress = _FALSE;
	pBtDbg->dbgHciInfo.hciCmdPhyLinkStatus = HciStatus;
	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_PHY_LINK_COMPLETE))
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Physical Link Complete, Ignore to send this event due to event mask page 2\n"));
		return;
	}

	if (EntryNum == 0xff)
	{
		// connection not started yet, just use the input physical link handle to response.
		PL_handle = PLHandle;
	}
	else
	{
		// connection is under progress, use the phy link handle we recorded.
		PL_handle  = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
		pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent=_FALSE;
	}

	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Physical Link Complete, Status = 0x%x PhyLinkHandle = 0x%x\n",HciStatus,
		PL_handle));

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_PHY_LINK_COMPLETE;
	PPacketIrpEvent->Length=2;

	PPacketIrpEvent->Data[0] = HciStatus;
	PPacketIrpEvent->Data[1] = PL_handle;
	bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);

}

static void
bthci_EventCommandStatus(
	struct rtw_adapter *					padapter,
	u8					OGF,
	u16					OCF,
	HCI_STATUS				HciStatus
	)
{

	u8 localBuf[6] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
	u8	Num_Hci_Comm = 0x1;
	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], CommandStatus, Opcode = 0x%02x%02x, OGF=0x%x,  OCF=0x%x, Status = 0x%x, Num_HCI_COMM = 0x%x\n",
		(HCIOPCODEHIGHT(OCF, OGF)), (HCIOPCODELOW(OCF, OGF)), OGF, OCF, HciStatus,Num_Hci_Comm));

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_COMMAND_STATUS;
	PPacketIrpEvent->Length=4;
	PPacketIrpEvent->Data[0] = HciStatus;	//current pending
	PPacketIrpEvent->Data[1] = Num_Hci_Comm;	//packet #
	PPacketIrpEvent->Data[2] = HCIOPCODELOW(OCF, OGF);
	PPacketIrpEvent->Data[3] = HCIOPCODEHIGHT(OCF, OGF);

	bthci_IndicateEvent(padapter, PPacketIrpEvent, 6);

}

static void
bthci_EventLogicalLinkComplete(
	struct rtw_adapter *					padapter,
	HCI_STATUS				HciStatus,
	u8					PhyLinkHandle,
	u16					LogLinkHandle,
	u8					LogLinkIndex,
	u8					EntryNum
	)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	u8	localBuf[7] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_LOGICAL_LINK_COMPLETE))
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Logical Link Complete, Ignore to send this event due to event mask page 2\n"));
		return;
	}
	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Logical Link Complete, PhyLinkHandle = 0x%x,  LogLinkHandle = 0x%x, Status= 0x%x\n",
		PhyLinkHandle, LogLinkHandle, HciStatus));


	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode = HCI_EVENT_LOGICAL_LINK_COMPLETE;
	PPacketIrpEvent->Length = 5;

	PPacketIrpEvent->Data[0] = HciStatus;//status code
	//Logical link handle
	PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle);
	PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle);
	//Physical link handle
	PPacketIrpEvent->Data[3] = TWOBYTE_LOWBYTE(PhyLinkHandle);
	//corresponding Tx flow spec ID
	if (HciStatus == HCI_STATUS_SUCCESS)
	{
		PPacketIrpEvent->Data[4] =
			pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData[LogLinkIndex].Tx_Flow_Spec.Identifier;
	}
	else
		PPacketIrpEvent->Data[4] = 0x0;

	bthci_IndicateEvent(padapter, PPacketIrpEvent, 7);
}

static void
bthci_EventDisconnectLogicalLinkComplete(
	struct rtw_adapter *					padapter,
	HCI_STATUS				HciStatus,
	u16					LogLinkHandle,
	HCI_STATUS				Reason
	)
{
	u8 localBuf[6] = "";
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE))
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Ignore to send this event due to event mask page 2\n"));
		return;
	}
	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Disconnect Logical Link Complete, Status = 0x%x,LLH = 0x%x Reason =0x%x\n",HciStatus,LogLinkHandle,Reason));

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode=HCI_EVENT_DISCONNECT_LOGICAL_LINK_COMPLETE;
	PPacketIrpEvent->Length=4;

	PPacketIrpEvent->Data[0] = HciStatus;
	//Logical link handle
	PPacketIrpEvent->Data[1] = TWOBYTE_LOWBYTE(LogLinkHandle);
	PPacketIrpEvent->Data[2] = TWOBYTE_HIGHTBYTE(LogLinkHandle);
	//Disconnect reason
	PPacketIrpEvent->Data[3] = Reason;

	bthci_IndicateEvent(padapter, PPacketIrpEvent, 6);
}

static void
bthci_EventFlushOccurred(
	struct rtw_adapter *					padapter,
	u16					LogLinkHandle
	)
{
	u8	localBuf[4] = "";
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
	RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("bthci_EventFlushOccurred(), LLH = 0x%x\n", LogLinkHandle));

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	PPacketIrpEvent->EventCode = HCI_EVENT_FLUSH_OCCRUED;
	PPacketIrpEvent->Length = 2;
	//Logical link handle
	PPacketIrpEvent->Data[0] = TWOBYTE_LOWBYTE(LogLinkHandle);
	PPacketIrpEvent->Data[1] = TWOBYTE_HIGHTBYTE(LogLinkHandle);

	bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
}

static HCI_STATUS
bthci_BuildPhysicalLink(
	struct rtw_adapter *						padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd,
	u16							OCF
)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	u8			EntryNum, PLH;

	//Send HCI Command status event to AMP.
	bthci_EventCommandStatus(padapter,
			OGF_LINK_CONTROL_COMMANDS,
			OCF,
			HCI_STATUS_SUCCESS);

	PLH = *((u8*)pHciCmd->Data);

	// Check if resource or bt connection is under progress, if yes, reject the link creation.
	if (bthci_AddEntry(padapter) == _FALSE)
	{
		status = HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE;
		bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH);
		return status;
	}

	EntryNum=pBtMgnt->CurrentConnectEntryNum;
	pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle = PLH;
	pBtMgnt->BtCurrentPhyLinkhandle = PLH;

	if (pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.AMPAssocfragment == NULL)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Create/Accept PhysicalLink, AMP controller is busy\n"));
		status = HCI_STATUS_CONTROLLER_BUSY;
		bthci_EventPhysicalLinkComplete(padapter, status, INVALID_ENTRY_NUM, PLH);
		return status;
	}

	// Record Key and the info
	pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen=(*((u8*)pHciCmd->Data+1));
	pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType=(*((u8*)pHciCmd->Data+2));
	memcpy(pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey,
		(((u8*)pHciCmd->Data+3)), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen);
#if (LOCAL_PMK == 1)
	memcpy(pBTInfo->BtAsocEntry[EntryNum].PMK, testPMK, PMK_LEN);
#else
	memcpy(pBTInfo->BtAsocEntry[EntryNum].PMK, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey, PMK_LEN);
#endif
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildPhysicalLink, EntryNum = %d, PLH = 0x%x  KeyLen = 0x%x, KeyType =0x%x\n",
		EntryNum, pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle,
		pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen,
		pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyType));
	RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("BtAMPKey\n"), pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKey,
		pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtAMPKeyLen);
	RTPRINT_DATA(FIOCTL, (IOCTL_BT_LOGO|IOCTL_BT_HCICMD), ("PMK\n"), pBTInfo->BtAsocEntry[EntryNum].PMK,
		PMK_LEN);

	if (OCF == HCI_CREATE_PHYSICAL_LINK)
	{
		BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_CREATE_PHY_LINK, EntryNum);
	}
	else if (OCF == HCI_ACCEPT_PHYSICAL_LINK)
	{
		BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ACCEPT_PHY_LINK, EntryNum);
	}

	return status;
}

static void
bthci_BuildLogicalLink(
	struct rtw_adapter *						padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd,
	u16						OCF
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTinfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTinfo->BtMgnt;
	u8	PhyLinkHandle, EntryNum;
	static u16 AssignLogHandle = 1;

	HCI_FLOW_SPEC	TxFlowSpec;
	HCI_FLOW_SPEC	RxFlowSpec;
	u32	MaxSDUSize, ArriveTime, Bandwidth;

	PhyLinkHandle = *((u8*)pHciCmd->Data);

	EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);

	memcpy(&TxFlowSpec,
		&pHciCmd->Data[1], sizeof(HCI_FLOW_SPEC));
	memcpy(&RxFlowSpec,
		&pHciCmd->Data[17], sizeof(HCI_FLOW_SPEC));

	MaxSDUSize = TxFlowSpec.MaximumSDUSize;
	ArriveTime = TxFlowSpec.SDUInterArrivalTime;

	if (bthci_CheckLogLinkBehavior(padapter, TxFlowSpec)&& bthci_CheckLogLinkBehavior(padapter, RxFlowSpec))
	{
		Bandwidth = BTTOTALBANDWIDTH;
	}
	else if (MaxSDUSize==0xffff && ArriveTime==0xffffffff)
	{
		Bandwidth = BTTOTALBANDWIDTH;
	}
	else
	{
		Bandwidth = MaxSDUSize*8*1000/(ArriveTime+244);
	}

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildLogicalLink, PhyLinkHandle=0x%x, MaximumSDUSize=0x%x, SDUInterArrivalTime=0x%x, Bandwidth=0x%x\n",
		PhyLinkHandle, MaxSDUSize, ArriveTime, Bandwidth));

	if (EntryNum == 0xff)
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Invalid Physical Link handle = 0x%x, status=HCI_STATUS_UNKNOW_CONNECT_ID, return\n", PhyLinkHandle));
		status = HCI_STATUS_UNKNOW_CONNECT_ID;

		//When we receive Create/Accept logical link command, we should send command status event first.
		bthci_EventCommandStatus(padapter,
			OGF_LINK_CONTROL_COMMANDS,
			OCF,
			status);
		return;
	}

	if (pBtMgnt->bLogLinkInProgress == _FALSE)
	{
		if (bthci_PhyLinkConnectionInProgress(padapter, PhyLinkHandle))
		{
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Physical link connection in progress, status=HCI_STATUS_CMD_DISALLOW, return\n"));
			status = HCI_STATUS_CMD_DISALLOW;

			pBtMgnt->bPhyLinkInProgressStartLL = _TRUE;
			//When we receive Create/Accept logical link command, we should send command status event first.
			bthci_EventCommandStatus(padapter,
				OGF_LINK_CONTROL_COMMANDS,
				OCF,
				status);

			return;
		}

		if (Bandwidth > BTTOTALBANDWIDTH)//BTTOTALBANDWIDTH
		{
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status=HCI_STATUS_QOS_REJECT, Bandwidth=0x%x, return\n", Bandwidth));
			status = HCI_STATUS_QOS_REJECT;

			//When we receive Create/Accept logical link command, we should send command status event first.
			bthci_EventCommandStatus(padapter,
				OGF_LINK_CONTROL_COMMANDS,
				OCF,
				status);
		}
		else
		{
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("status=HCI_STATUS_SUCCESS\n"));
			status = HCI_STATUS_SUCCESS;

			//When we receive Create/Accept logical link command, we should send command status event first.
			bthci_EventCommandStatus(padapter,
				OGF_LINK_CONTROL_COMMANDS,
				OCF,
				status);

		}

		if (pBTinfo->BtAsocEntry[EntryNum].BtCurrentState != HCI_STATE_CONNECTED)
		{
			bthci_EventLogicalLinkComplete(padapter,
				HCI_STATUS_CMD_DISALLOW, 0, 0, 0,EntryNum);
		}
		else
		{
			u8 i, find=0;

			pBtMgnt->bLogLinkInProgress = _TRUE;

			// find an unused logical link index and copy the data
			for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
			{
				if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle == 0)
				{
					HCI_STATUS LogCompEventstatus = HCI_STATUS_SUCCESS;

					pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle = *((u8*)pHciCmd->Data);
					pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle = AssignLogHandle;
					RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("BuildLogicalLink, EntryNum = %d, physical link handle = 0x%x, logical link handle = 0x%x\n",
						EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle,
								  pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle));
					memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Tx_Flow_Spec,
						&TxFlowSpec, sizeof(HCI_FLOW_SPEC));
					memcpy(&pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].Rx_Flow_Spec,
						&RxFlowSpec, sizeof(HCI_FLOW_SPEC));

					pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet=_FALSE;

					if (pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCancelCMDIsSetandComplete)
					{
						LogCompEventstatus = HCI_STATUS_UNKNOW_CONNECT_ID;
					}
					bthci_EventLogicalLinkComplete(padapter,
						LogCompEventstatus,
						pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtPhyLinkhandle,
						pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].BtLogLinkhandle, i,EntryNum);

					pBTinfo->BtAsocEntry[EntryNum].LogLinkCmdData[i].bLLCompleteEventIsSet = _TRUE;

					find = 1;
					pBtMgnt->BtCurrentLogLinkhandle = AssignLogHandle;
					AssignLogHandle++;
					break;
				}
			}

			if (!find)
			{
				bthci_EventLogicalLinkComplete(padapter,
					HCI_STATUS_CONNECT_RJT_LIMIT_RESOURCE, 0, 0, 0,EntryNum);
			}
			pBtMgnt->bLogLinkInProgress = _FALSE;
		}
	}
	else
	{
		bthci_EventLogicalLinkComplete(padapter,
			HCI_STATUS_CONTROLLER_BUSY, 0, 0, 0,EntryNum);
	}

}

static void
bthci_StartBeaconAndConnect(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd,
	u8		CurrentAssocNum
	)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("StartBeaconAndConnect, CurrentAssocNum=%d, AMPRole=%d\n",
		CurrentAssocNum,
		pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole));

	if (pBtMgnt->CheckChnlIsSuit == _FALSE)
	{
		bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONNECT_REJ_NOT_SUIT_CHNL_FOUND, CurrentAssocNum, INVALID_PL_HANDLE);
		bthci_RemoveEntryByEntryNum(padapter, CurrentAssocNum);
		return;
	}

	{
		if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR)
		{
			rsprintf((char*)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf,32,"AMP-%02x-%02x-%02x-%02x-%02x-%02x",
			padapter->eeprompriv.mac_addr[0],
			padapter->eeprompriv.mac_addr[1],
			padapter->eeprompriv.mac_addr[2],
			padapter->eeprompriv.mac_addr[3],
			padapter->eeprompriv.mac_addr[4],
			padapter->eeprompriv.mac_addr[5]);
		}
		else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER)
		{
			rsprintf((char*)pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf,32,"AMP-%02x-%02x-%02x-%02x-%02x-%02x",
			pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[0],
			pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[1],
			pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[2],
			pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[3],
			pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[4],
			pBTInfo->BtAsocEntry[CurrentAssocNum].BTRemoteMACAddr[5]);
		}

		FillOctetString(pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid, pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsidBuf, 21);
		pBTInfo->BtAsocEntry[CurrentAssocNum].BTSsid.Length = 21;

		//To avoid set the start ap or connect twice, or the original connection will be disconnected.
		if (!pBtMgnt->bBTConnectInProgress)
		{
			pBtMgnt->bBTConnectInProgress=_TRUE;
			RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress ON!!\n"));
			BTHCI_SM_WITH_INFO(padapter,HCI_STATE_STARTING,STATE_CMD_MAC_START_COMPLETE,CurrentAssocNum);


			// 20100325 Joseph: Check RF ON/OFF.
			// If RF OFF, it reschedule connecting operation after 50ms.
			if (!bthci_CheckRfStateBeforeConnect(padapter))
				return;

			if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR)
			{
//				BTPKT_StartBeacon(padapter, CurrentAssocNum); // not implement yet
				BTHCI_SM_WITH_INFO(padapter,HCI_STATE_CONNECTING,STATE_CMD_MAC_CONNECT_COMPLETE,CurrentAssocNum);
			}
			else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER)
			{
				bthci_ResponderStartToScan(padapter);
			}
		}
		RT_PRINT_STR(_module_rtl871x_mlme_c_, _drv_notice_, "StartBeaconAndConnect, SSID:\n", pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Octet, pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].BTSsid.Length);
	}
}

static void bthci_ResetBtMgnt(PBT_MGNT pBtMgnt)
{
	pBtMgnt->BtOperationOn = _FALSE;
	pBtMgnt->bBTConnectInProgress = _FALSE;
	pBtMgnt->bLogLinkInProgress = _FALSE;
	pBtMgnt->bPhyLinkInProgress = _FALSE;
	pBtMgnt->bPhyLinkInProgressStartLL = _FALSE;
	pBtMgnt->DisconnectEntryNum = 0xff;
	pBtMgnt->bStartSendSupervisionPkt = _FALSE;
	pBtMgnt->JoinerNeedSendAuth = _FALSE;
	pBtMgnt->CurrentBTConnectionCnt = 0;
	pBtMgnt->BTCurrentConnectType = BT_DISCONNECT;
	pBtMgnt->BTReceiveConnectPkt = BT_DISCONNECT;
	pBtMgnt->BTAuthCount = 0;
	pBtMgnt->btLogoTest = 0;
}

static void bthci_ResetBtHciInfo(PBT_HCI_INFO pBtHciInfo)
{
	pBtHciInfo->BTEventMask = 0;
	pBtHciInfo->BTEventMaskPage2 = 0;
	pBtHciInfo->ConnAcceptTimeout =  10000;
	pBtHciInfo->PageTimeout  =  0x30;
	pBtHciInfo->LocationDomainAware = 0x0;
	pBtHciInfo->LocationDomain = 0x5858;
	pBtHciInfo->LocationDomainOptions = 0x58;
	pBtHciInfo->LocationOptions = 0x0;
	pBtHciInfo->FlowControlMode = 0x1;	// 0:Packet based data flow control mode(BR/EDR), 1: Data block based data flow control mode(AMP).

	pBtHciInfo->enFlush_LLH = 0;
	pBtHciInfo->FLTO_LLH = 0;

	//Test command only
	pBtHciInfo->bTestIsEnd = _TRUE;
	pBtHciInfo->bInTestMode = _FALSE;
	pBtHciInfo->bTestNeedReport = _FALSE;
	pBtHciInfo->TestScenario = 0xff;
	pBtHciInfo->TestReportInterval = 0x01;
	pBtHciInfo->TestCtrType = 0x5d;
	pBtHciInfo->TestEventType = 0x00;
	pBtHciInfo->TestNumOfFrame = 0;
	pBtHciInfo->TestNumOfErrFrame = 0;
	pBtHciInfo->TestNumOfBits = 0;
	pBtHciInfo->TestNumOfErrBits = 0;
}

static void bthci_ResetBtSec(struct rtw_adapter *padapter, PBT_SECURITY pBtSec)
{
//	PMGNT_INFO	pMgntInfo = &padapter->MgntInfo;

	// Set BT used HW or SW encrypt !!
	if (GET_HAL_DATA(padapter)->bBTMode)
		pBtSec->bUsedHwEncrypt = _TRUE;
	else
		pBtSec->bUsedHwEncrypt = _FALSE;
	RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("%s: bUsedHwEncrypt=%d\n", __FUNCTION__, pBtSec->bUsedHwEncrypt));

	pBtSec->RSNIE.Octet = pBtSec->RSNIEBuf;
}

static void bthci_ResetBtExtInfo(PBT_MGNT pBtMgnt)
{
	u8	i;

	for (i=0; i<MAX_BT_ASOC_ENTRY_NUM; i++)
	{
		pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = 0;
		pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = 0;
		pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = 0;
		pBtMgnt->ExtConfig.linkInfo[i].BTProfile = BT_PROFILE_NONE;
		pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = BT_SPEC_2_1_EDR;
		pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = 0;
		pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE;
		pBtMgnt->ExtConfig.linkInfo[i].linkRole = BT_LINK_MASTER;
	}

	pBtMgnt->ExtConfig.CurrentConnectHandle = 0;
	pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = 0;
	pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = 0;
	pBtMgnt->ExtConfig.MIN_BT_RSSI = 0;
	pBtMgnt->ExtConfig.NumberOfHandle = 0;
	pBtMgnt->ExtConfig.NumberOfSCO = 0;
	pBtMgnt->ExtConfig.CurrentBTStatus = 0;
	pBtMgnt->ExtConfig.HCIExtensionVer = 0;

	pBtMgnt->ExtConfig.bManualControl = _FALSE;
	pBtMgnt->ExtConfig.bBTBusy = _FALSE;
	pBtMgnt->ExtConfig.bBTA2DPBusy = _FALSE;
}

static HCI_STATUS bthci_CmdReset(struct rtw_adapter *_padapter, u8 bNeedSendEvent)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	struct rtw_adapter *	padapter;
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_HCI_INFO		pBtHciInfo;
	PBT_SECURITY		pBtSec;
	PBT_DBG			pBtDbg;
	u8	i;


	RTPRINT(FIOCTL,IOCTL_BT_HCICMD, ("bthci_CmdReset()\n"));

	padapter = GetDefaultAdapter(_padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtHciInfo = &pBTInfo->BtHciInfo;
	pBtSec = &pBTInfo->BtSec;
	pBtDbg = &pBTInfo->BtDbg;

	pBTInfo->padapter = padapter;

	for (i=0; i<MAX_BT_ASOC_ENTRY_NUM; i++)
	{
		bthci_ResetEntry(padapter, i);
	}

	bthci_ResetBtMgnt(pBtMgnt);
	bthci_ResetBtHciInfo(pBtHciInfo);
	bthci_ResetBtSec(padapter, pBtSec);

	pBtMgnt->BTChannel = BT_Default_Chnl;
	pBtMgnt->CheckChnlIsSuit = _TRUE;

	pBTInfo->BTBeaconTmrOn = _FALSE;
//	QosInitializeBssDesc(&pBtMgnt->bssDesc.BssQos); // not implement yet

	pBtMgnt->bCreateSpportQos=_TRUE;

	PlatformCancelTimer(padapter, &pBTInfo->BTSupervisionPktTimer);
#if (SENDTXMEHTOD == 0)
	PlatformCancelTimer(padapter, &pBTInfo->BTHCISendAclDataTimer);
#endif
	PlatformCancelTimer(padapter, &pBTInfo->BTHCIDiscardAclDataTimer);
	PlatformCancelTimer(padapter, &pBTInfo->BTBeaconTimer);

	HALBT_SetRtsCtsNoLenLimit(padapter);
	//
	// Maybe we need to take care Group != AES case !!
	// now we Pairwise and Group all used AES !!
//	BTPKT_ConstructRSNIE(padapter); // not implement yet

	bthci_ResetBtExtInfo(pBtMgnt);

	//send command complete event here when all data are received.
	if (bNeedSendEvent)
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_RESET,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdWriteRemoteAMPAssoc(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8			CurrentAssocNum;
	u8			PhyLinkHandle;

	pBtDbg->dbgHciInfo.hciCmdCntWriteRemoteAmpAssoc++;
	PhyLinkHandle = *((u8*)pHciCmd->Data);
	CurrentAssocNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);

	if (CurrentAssocNum == 0xff)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, No such Handle in the Entry\n"));
		status = HCI_STATUS_UNKNOW_CONNECT_ID;
		bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle);
		return status;
	}

	if (pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment == NULL)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, AMP controller is busy\n"));
		status = HCI_STATUS_CONTROLLER_BUSY;
		bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle);
		return status;
	}

	pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.BtPhyLinkhandle = PhyLinkHandle;//*((u8*)pHciCmd->Data);
	pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar = *((u16*)((u8*)pHciCmd->Data+1));
	pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen = *((u16*)((u8*)pHciCmd->Data+3));

	RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc, LenSoFar= 0x%x, AssocRemLen= 0x%x\n",
		pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar,pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen));

	RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("WriteRemoteAMPAssoc fragment \n"), pHciCmd->Data,pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen+5);
	if ((pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen) > MAX_AMP_ASSOC_FRAG_LEN)
	{
		memcpy(((u8*)pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8)))),
			(u8*)pHciCmd->Data+5,
			MAX_AMP_ASSOC_FRAG_LEN);
	}
	else
	{
		memcpy((u8*)(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocfragment)+(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.LenSoFar*(sizeof(u8))),
			((u8*)pHciCmd->Data+5),
			(pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen));

		RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "WriteRemoteAMPAssoc :\n",
			pHciCmd->Data+5, pBTInfo->BtAsocEntry[CurrentAssocNum].AmpAsocCmdData.AMPAssocRemLen);

		if (!bthci_GetAssocInfo(padapter, CurrentAssocNum))
			status=HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;

		bthci_EventWriteRemoteAmpAssoc(padapter, status, PhyLinkHandle);

		bthci_StartBeaconAndConnect(padapter,pHciCmd,CurrentAssocNum);
	}

	return status;
}

//7.3.13
static HCI_STATUS bthci_CmdReadConnectionAcceptTimeout(struct rtw_adapter *padapter)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_READ_CONNECTION_ACCEPT_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pu2Temp = (u16*)&pRetPar[1];		// Conn_Accept_Timeout
		*pu2Temp = pBtHciInfo->ConnAcceptTimeout;
		len += 3;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

//7.3.3
static HCI_STATUS
bthci_CmdSetEventFilter(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	return status;
}

//7.3.14
static HCI_STATUS
bthci_CmdWriteConnectionAcceptTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;
	u16	*pu2Temp;

	pu2Temp = (u16*)&pHciCmd->Data[0];
	pBtHciInfo->ConnAcceptTimeout = *pu2Temp;
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ConnAcceptTimeout = 0x%x",
		pBtHciInfo->ConnAcceptTimeout));

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadPageTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_READ_PAGE_TIMEOUT,
			status);

		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Read PageTimeout = 0x%x\n", pBtHciInfo->PageTimeout));
		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pu2Temp = (u16*)&pRetPar[1];		// Page_Timeout
		*pu2Temp = pBtHciInfo->PageTimeout;
		len+=3;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdWritePageTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;
	u16	*pu2Temp;

	pu2Temp = (u16*)&pHciCmd->Data[0];
	pBtHciInfo->PageTimeout = *pu2Temp;
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Write PageTimeout = 0x%x\n",
		pBtHciInfo->PageTimeout));

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_WRITE_PAGE_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadLinkSupervisionTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTinfo = GET_BT_INFO(padapter);
	u8			physicalLinkHandle, EntryNum;

	physicalLinkHandle = *((u8*)pHciCmd->Data);

	EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle);

	if (EntryNum == 0xff)
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLinkSupervisionTimeout, No such Handle in the Entry\n"));
		status = HCI_STATUS_UNKNOW_CONNECT_ID;
		return status;
	}

	if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle)
		status = HCI_STATUS_UNKNOW_CONNECT_ID;

	{
		u8 localBuf[10] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_READ_LINK_SUPERVISION_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;
		pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
		pRetPar[2] = 0;
		pu2Temp = (u16*)&pRetPar[3];		// Conn_Accept_Timeout
		*pu2Temp = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout;
		len += 5;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdWriteLinkSupervisionTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTinfo = GET_BT_INFO(padapter);
	u8			physicalLinkHandle, EntryNum;

	physicalLinkHandle = *((u8*)pHciCmd->Data);

	EntryNum = bthci_GetCurrentEntryNum(padapter, physicalLinkHandle);

	if (EntryNum == 0xff)
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("WriteLinkSupervisionTimeout, No such Handle in the Entry\n"));
		status=HCI_STATUS_UNKNOW_CONNECT_ID;
	}
	else
	{
		if (pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle != physicalLinkHandle)
			status = HCI_STATUS_UNKNOW_CONNECT_ID;
		else
		{
			pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout=*((u16 *)(((u8*)pHciCmd->Data)+2));
			RTPRINT(FIOCTL, IOCTL_STATE, ("BT Write LinkSuperversionTimeout[%d] = 0x%x\n",
				EntryNum, pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.LinkSuperversionTimeout));
		}
	}

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_WRITE_LINK_SUPERVISION_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;
		pRetPar[1] = pBTinfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;
		pRetPar[2] = 0;
		len += 3;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdEnhancedFlush(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTinfo->BtHciInfo;
	u16		logicHandle;
	u8		Packet_Type;

	logicHandle = *((u16*)&pHciCmd->Data[0]);
	Packet_Type = pHciCmd->Data[2];

	if (Packet_Type != 0)
	{
		status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
	}
	else
		pBtHciInfo->enFlush_LLH = logicHandle;

	if (bthci_DiscardTxPackets(padapter, pBtHciInfo->enFlush_LLH))
	{
		bthci_EventFlushOccurred(padapter, pBtHciInfo->enFlush_LLH);
	}

	// should send command status event
	bthci_EventCommandStatus(padapter,
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_ENHANCED_FLUSH,
			status);

	if (pBtHciInfo->enFlush_LLH)
	{
		bthci_EventEnhancedFlushComplete(padapter, pBtHciInfo->enFlush_LLH);
		pBtHciInfo->enFlush_LLH = 0;
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadLogicalLinkAcceptTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;

		pu2Temp = (u16*)&pRetPar[1];		// Conn_Accept_Timeout
		*pu2Temp = pBtHciInfo->LogicalAcceptTimeout;
		len += 3;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdWriteLogicalLinkAcceptTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	pBtHciInfo->LogicalAcceptTimeout = *((u16*)pHciCmd->Data);

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
	return status;
}

static HCI_STATUS
bthci_CmdSetEventMask(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;
	u8 *pu8Temp;

	pu8Temp = (u8*)&pHciCmd->Data[0];
	pBtHciInfo->BTEventMask = *pu8Temp;
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("BTEventMask = 0x%"i64fmt"x\n",
		pBtHciInfo->BTEventMask));

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_SET_EVENT_MASK,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

// 7.3.69
static HCI_STATUS
bthci_CmdSetEventMaskPage2(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;
	u8	*pu8Temp;

	pu8Temp = (u8*)&pHciCmd->Data[0];
	pBtHciInfo->BTEventMaskPage2 = *pu8Temp;
	RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("BTEventMaskPage2 = 0x%"i64fmt"x\n",
		pBtHciInfo->BTEventMaskPage2));

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_SET_EVENT_MASK_PAGE_2,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadLocationData(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	{
		u8 localBuf[12] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_READ_LOCATION_DATA,
			status);
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions));

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;

		pRetPar[1] = pBtHciInfo->LocationDomainAware;	//0x0;	// Location_Domain_Aware
		pu2Temp = (u16*)&pRetPar[2];					// Location_Domain
		*pu2Temp = pBtHciInfo->LocationDomain;		//0x5858;
		pRetPar[4] = pBtHciInfo->LocationDomainOptions;	//0x58;	//Location_Domain_Options
		pRetPar[5] = pBtHciInfo->LocationOptions;		//0x0;	//Location_Options
		len+=6;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
	return status;
}

static HCI_STATUS
bthci_CmdWriteLocationData(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;
	u16	*pu2Temp;

	pBtHciInfo->LocationDomainAware = pHciCmd->Data[0];
	pu2Temp = (u16*)&pHciCmd->Data[1];
	pBtHciInfo->LocationDomain = *pu2Temp;
	pBtHciInfo->LocationDomainOptions = pHciCmd->Data[3];
	pBtHciInfo->LocationOptions = pHciCmd->Data[4];
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainAware = 0x%x\n", pBtHciInfo->LocationDomainAware));
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Domain = 0x%x\n", pBtHciInfo->LocationDomain));
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DomainOptions = 0x%x\n", pBtHciInfo->LocationDomainOptions));
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Options = 0x%x\n", pBtHciInfo->LocationOptions));

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_WRITE_LOCATION_DATA,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadFlowControlMode(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	{
		u8 localBuf[7] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_READ_FLOW_CONTROL_MODE,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;
		pRetPar[1] = pBtHciInfo->FlowControlMode;	// Flow Control Mode
		len += 2;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
	return status;
}

static HCI_STATUS
bthci_CmdWriteFlowControlMode(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;

	pBtHciInfo->FlowControlMode = pHciCmd->Data[0];

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_WRITE_FLOW_CONTROL_MODE,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadBestEffortFlushTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info pBTinfo = GET_BT_INFO(padapter);
	u16		i, j, logicHandle;
	u32		BestEffortFlushTimeout = 0xffffffff;
	u8		find = 0;

	logicHandle = *((u16*)pHciCmd->Data);
	// find an matched logical link index and copy the data
	for (j=0; j<MAX_BT_ASOC_ENTRY_NUM; j++)
	{
		for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
		{
			if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle)
			{
				BestEffortFlushTimeout = pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout;
				find = 1;
				break;
			}
		}
	}

	if (!find)
		status = HCI_STATUS_UNKNOW_CONNECT_ID;

	{
		u8 localBuf[10] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u32 *pu4Temp;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;
		pu4Temp = (u32*)&pRetPar[1];				// Best_Effort_Flush_Timeout
		*pu4Temp = BestEffortFlushTimeout;
		len += 5;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
	return status;
}

static HCI_STATUS
bthci_CmdWriteBestEffortFlushTimeout(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info pBTinfo = GET_BT_INFO(padapter);
	u16		i, j, logicHandle;
	u32		BestEffortFlushTimeout = 0xffffffff;
	u8		find = 0;

	logicHandle = *((u16*)pHciCmd->Data);
	BestEffortFlushTimeout = *((u32 *)(pHciCmd->Data+1));

	// find an matched logical link index and copy the data
	for (j=0; j<MAX_BT_ASOC_ENTRY_NUM; j++)
	{
		for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
		{
			if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle)
			{
				pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BestEffortFlushTimeout = BestEffortFlushTimeout;
				find = 1;
				break;
			}
		}
	}

	if (!find)
		status = HCI_STATUS_UNKNOW_CONNECT_ID;

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
	return status;
}

static HCI_STATUS
bthci_CmdShortRangeMode(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	u8			PhyLinkHandle, EntryNum, ShortRangeMode;

	PhyLinkHandle = pHciCmd->Data[0];
	ShortRangeMode = pHciCmd->Data[1];
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x, Short_Range_Mode = 0x%x\n", PhyLinkHandle, ShortRangeMode));

	EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);
	if (EntryNum != 0xff)
	{
		pBTInfo->BtAsocEntry[EntryNum].ShortRangeMode = ShortRangeMode;
	}
	else
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PhyLinkHandle));
		status = HCI_STATUS_UNKNOW_CONNECT_ID;
	}

	bthci_EventCommandStatus(padapter,
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_SHORT_RANGE_MODE,
			status);

	bthci_EventShortRangeModeChangeComplete(padapter, status, ShortRangeMode, EntryNum);

	return status;
}

static HCI_STATUS bthci_CmdReadLocalSupportedCommands(struct rtw_adapter *padapter)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	// send command complete event here when all data are received.
	{
		//PVOID buffer = padapter->IrpHCILocalbuf.Ptr;
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar, *pSupportedCmds;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_INFORMATIONAL_PARAMETERS,
			HCI_READ_LOCAL_SUPPORTED_COMMANDS,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		pSupportedCmds = &pRetPar[1];
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[5]=0xc0\nBit [6]=Set Event Mask, [7]=Reset\n"));
		pSupportedCmds[5] = 0xc0;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[6]=0x01\nBit [0]=Set Event Filter\n"));
		pSupportedCmds[6] = 0x01;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[7]=0x0c\nBit [2]=Read Connection Accept Timeout, [3]=Write Connection Accept Timeout\n"));
		pSupportedCmds[7] = 0x0c;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[10]=0x80\nBit [7]=Host Number Of Completed Packets\n"));
		pSupportedCmds[10] = 0x80;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[11]=0x03\nBit [0]=Read Link Supervision Timeout, [1]=Write Link Supervision Timeout\n"));
		pSupportedCmds[11] = 0x03;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[14]=0xa8\nBit [3]=Read Local Version Information, [5]=Read Local Supported Features, [7]=Read Buffer Size\n"));
		pSupportedCmds[14] = 0xa8;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[15]=0x1c\nBit [2]=Read Failed Contact Count, [3]=Reset Failed Contact Count, [4]=Get Link Quality\n"));
		pSupportedCmds[15] = 0x1c;
		//pSupportedCmds[16] = 0x04;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[19]=0x40\nBit [6]=Enhanced Flush\n"));
		pSupportedCmds[19] = 0x40;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[21]=0xff\nBit [0]=Create Physical Link, [1]=Accept Physical Link, [2]=Disconnect Physical Link, [3]=Create Logical Link\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("	[4]=Accept Logical Link, [5]=Disconnect Logical Link, [6]=Logical Link Cancel, [7]=Flow Spec Modify\n"));
		pSupportedCmds[21] = 0xff;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[22]=0xff\nBit [0]=Read Logical Link Accept Timeout, [1]=Write Logical Link Accept Timeout, [2]=Set Event Mask Page 2, [3]=Read Location Data\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("	[4]=Write Location Data, [5]=Read Local AMP Info, [6]=Read Local AMP_ASSOC, [7]=Write Remote AMP_ASSOC\n"));
		pSupportedCmds[22] = 0xff;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[23]=0x07\nBit [0]=Read Flow Control Mode, [1]=Write Flow Control Mode, [2]=Read Data Block Size\n"));
		pSupportedCmds[23] = 0x07;
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD|IOCTL_BT_LOGO), ("Octet[24]=0x1c\nBit [2]=Read Best Effort Flush Timeout, [3]=Write Best Effort Flush Timeout, [4]=Short Range Mode\n"));
		pSupportedCmds[24] = 0x1c;
		len += 64;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS bthci_CmdReadLocalSupportedFeatures(struct rtw_adapter *padapter)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	//send command complete event here when all data are received.
	{
		//PVOID buffer = padapter->IrpHCILocalbuf.Ptr;
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_INFORMATIONAL_PARAMETERS,
			HCI_READ_LOCAL_SUPPORTED_FEATURES,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 9;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
	return status;
}

static HCI_STATUS
bthci_CmdReadLocalAMPAssoc(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;
	u8			PhyLinkHandle, EntryNum;

	pBtDbg->dbgHciInfo.hciCmdCntReadLocalAmpAssoc++;
	PhyLinkHandle = *((u8*)pHciCmd->Data);
	EntryNum = bthci_GetCurrentEntryNum(padapter, PhyLinkHandle);

	if ((EntryNum==0xff) && PhyLinkHandle != 0)
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d  !!!!!, physical link handle = 0x%x\n",
		EntryNum, PhyLinkHandle));
		status = HCI_STATUS_UNKNOW_CONNECT_ID;
	}
	else if (pBtMgnt->bPhyLinkInProgressStartLL)
	{
		status = HCI_STATUS_UNKNOW_CONNECT_ID;
		pBtMgnt->bPhyLinkInProgressStartLL = _FALSE;
	}
	else
	{
		pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle = *((u8*)pHciCmd->Data);
		pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar = *((u16*)((u8*)pHciCmd->Data+1));
		pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen = *((u16*)((u8*)pHciCmd->Data+3));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("ReadLocalAMPAssoc, LenSoFar=%d, MaxRemoteASSOCLen=%d\n",
			pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar,
			pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.MaxRemoteASSOCLen));
	}

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, EntryNum = %d  !!!!!, physical link handle = 0x%x, LengthSoFar = %x  \n",
		EntryNum, PhyLinkHandle, pBTInfo->BtAsocEntry[EntryNum].AmpAsocCmdData.LenSoFar));

	//send command complete event here when all data are received.
	{
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		//PVOID buffer = padapter->IrpHCILocalbuf.Ptr;
		u8 localBuf[TmpLocalBufSize] = "";
		u16	*pRemainLen;
		u32	totalLen = 0;
		u16	typeLen=0, remainLen=0, ret_index=0;
		u8 *pRetPar;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		totalLen += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_STATUS_PARAMETERS,
			HCI_READ_LOCAL_AMP_ASSOC,
			status);
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len=%d  \n", remainLen));
		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[totalLen];
		pRetPar[0] = status;		//status
		pRetPar[1] = *((u8*)pHciCmd->Data);
		pRemainLen = (u16*)&pRetPar[2];		// AMP_ASSOC_Remaining_Length
		totalLen += 4;	//[0]~[3]
		ret_index = 4;

		typeLen = bthci_AssocMACAddr(padapter, &pRetPar[ret_index]);
		totalLen += typeLen;
		remainLen += typeLen;
		ret_index += typeLen;
		typeLen = bthci_AssocPreferredChannelList(padapter, &pRetPar[ret_index], EntryNum);
		totalLen += typeLen;
		remainLen += typeLen;
		ret_index += typeLen;
		typeLen = bthci_PALCapabilities(padapter, &pRetPar[ret_index]);
		totalLen += typeLen;
		remainLen += typeLen;
		ret_index += typeLen;
		typeLen = bthci_AssocPALVer(padapter, &pRetPar[ret_index]);
		totalLen += typeLen;
		remainLen += typeLen;
		PPacketIrpEvent->Length = (u8)totalLen;
		*pRemainLen = remainLen;	// AMP_ASSOC_Remaining_Length
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("ReadLocalAMPAssoc, Remaining_Len=%d  \n", remainLen));
		RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("AMP_ASSOC_fragment : \n"), PPacketIrpEvent->Data, totalLen);

		bthci_IndicateEvent(padapter, PPacketIrpEvent, totalLen+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadFailedContactCounter(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{

	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;
	u16		handle;

	handle=*((u16*)pHciCmd->Data);
	//send command complete event here when all data are received.
	{
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_STATUS_PARAMETERS,
			HCI_READ_FAILED_CONTACT_COUNTER,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pRetPar[1] = TWOBYTE_LOWBYTE(handle);
		pRetPar[2] = TWOBYTE_HIGHTBYTE(handle);
		pRetPar[3] = TWOBYTE_LOWBYTE(pBtHciInfo->FailContactCount);
		pRetPar[4] = TWOBYTE_HIGHTBYTE(pBtHciInfo->FailContactCount);
		len += 5;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdResetFailedContactCounter(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS		status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO	pBtHciInfo = &pBTInfo->BtHciInfo;
	u16		handle;

	handle=*((u16*)pHciCmd->Data);
	pBtHciInfo->FailContactCount=0;

	//send command complete event here when all data are received.
	{
		//PVOID buffer = padapter->IrpHCILocalbuf.Ptr;
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_STATUS_PARAMETERS,
			HCI_RESET_FAILED_CONTACT_COUNTER,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pRetPar[1] = TWOBYTE_LOWBYTE(handle);
		pRetPar[2] = TWOBYTE_HIGHTBYTE(handle);
		len+=3;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
	return status;
}

//
// BT 3.0+HS [Vol 2] 7.4.1
//
static HCI_STATUS
bthci_CmdReadLocalVersionInformation(
	struct rtw_adapter *	padapter
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	//send command complete event here when all data are received.
	{
		//PVOID buffer = padapter->IrpHCILocalbuf.Ptr;
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_INFORMATIONAL_PARAMETERS,
			HCI_READ_LOCAL_VERSION_INFORMATION,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pRetPar[1] = 0x05;					// HCI_Version
		pu2Temp = (u16*)&pRetPar[2];		// HCI_Revision
		*pu2Temp = 0x0001;
		pRetPar[4] = 0x05;					// LMP/PAL_Version
		pu2Temp = (u16*)&pRetPar[5];		// Manufacturer_Name
		*pu2Temp = 0x005d;
		pu2Temp = (u16*)&pRetPar[7];		// LMP/PAL_Subversion
		*pu2Temp = 0x0001;
		len += 9;
		PPacketIrpEvent->Length = len;

		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LOCAL_VERSION_INFORMATION\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Status  %x\n",status));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Version = 0x05\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI_Revision = 0x0001\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Version = 0x05\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("Manufacturer_Name = 0x0001\n"));
		RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("LMP/PAL_Subversion = 0x0001\n"));

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

//7.4.7
static HCI_STATUS bthci_CmdReadDataBlockSize(struct rtw_adapter *padapter)
{
	HCI_STATUS			status = HCI_STATUS_SUCCESS;

	{
		//PVOID buffer = padapter->IrpHCILocalbuf.Ptr;
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_INFORMATIONAL_PARAMETERS,
			HCI_READ_DATA_BLOCK_SIZE,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = HCI_STATUS_SUCCESS;		//status
		pu2Temp = (u16*)&pRetPar[1];		// Max_ACL_Data_Packet_Length
		*pu2Temp = Max80211PALPDUSize;

		pu2Temp = (u16*)&pRetPar[3];		// Data_Block_Length
		*pu2Temp = Max80211PALPDUSize;
		pu2Temp = (u16*)&pRetPar[5];		// Total_Num_Data_Blocks
		*pu2Temp = BTTotalDataBlockNum;
		len += 7;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

// 7.4.5
static HCI_STATUS
bthci_CmdReadBufferSize(
	struct rtw_adapter *					padapter
	)
{
	HCI_STATUS			status = HCI_STATUS_SUCCESS;

	{
		//PVOID buffer = padapter->IrpHCILocalbuf.Ptr;
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_INFORMATIONAL_PARAMETERS,
			HCI_READ_BUFFER_SIZE,
			status);
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Synchronous_Data_Packet_Length = 0x%x\n", BTSynDataPacketLength));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_ACL_Data_Packets = 0x%x\n", BTTotalDataBlockNum));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("Total_Num_Synchronous_Data_Packets = 0x%x\n", BTTotalDataBlockNum));
		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pu2Temp = (u16*)&pRetPar[1];		// HC_ACL_Data_Packet_Length
		*pu2Temp = Max80211PALPDUSize;

		pRetPar[3] = BTSynDataPacketLength;	// HC_Synchronous_Data_Packet_Length
		pu2Temp = (u16*)&pRetPar[4];		// HC_Total_Num_ACL_Data_Packets
		*pu2Temp = BTTotalDataBlockNum;
		pu2Temp = (u16*)&pRetPar[6];		// HC_Total_Num_Synchronous_Data_Packets
		*pu2Temp = BTTotalDataBlockNum;
		len += 8;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdReadLocalAMPInfo(
	struct rtw_adapter *					padapter
	)
{
	HCI_STATUS			status = HCI_STATUS_SUCCESS;

	{
//		PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
		struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;
		u8 localBuf[TmpLocalBufSize] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;
		u32 *pu4Temp;
		u32	TotalBandwidth=BTTOTALBANDWIDTH, MaxBandGUBandwidth=BTMAXBANDGUBANDWIDTH;
		u8	ControlType=0x01, AmpStatus=0x01;
		u32	MaxFlushTimeout=10000, BestEffortFlushTimeout=5000;
		u16 MaxPDUSize=Max80211PALPDUSize, PalCap=0x1, AmpAssocLen=Max80211AMPASSOCLen, MinLatency=20;

		if ((ppwrctrl->rfoff_reason & RF_CHANGE_BY_HW) ||
			(ppwrctrl->rfoff_reason & RF_CHANGE_BY_SW))
		{
			AmpStatus = AMP_STATUS_NO_CAPACITY_FOR_BT;
		}

		PlatformZeroMemory(&localBuf[0], TmpLocalBufSize);
		//PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(buffer);
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_STATUS_PARAMETERS,
			HCI_READ_LOCAL_AMP_INFO,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pRetPar[1] = AmpStatus;						// AMP_Status
		pu4Temp = (u32*)&pRetPar[2];		// Total_Bandwidth
		*pu4Temp = TotalBandwidth;//0x19bfcc00;//0x7530;
		pu4Temp = (u32*)&pRetPar[6];		// Max_Guaranteed_Bandwidth
		*pu4Temp = MaxBandGUBandwidth;//0x19bfcc00;//0x4e20;
		pu4Temp = (u32*)&pRetPar[10];		// Min_Latency
		*pu4Temp = MinLatency;//150;
		pu4Temp = (u32*)&pRetPar[14];		// Max_PDU_Size
		*pu4Temp = MaxPDUSize;
		pRetPar[18] = ControlType;					// Controller_Type
		pu2Temp = (u16*)&pRetPar[19];		// PAL_Capabilities
		*pu2Temp = PalCap;
		pu2Temp = (u16*)&pRetPar[21];		// AMP_ASSOC_Length
		*pu2Temp = AmpAssocLen;
		pu4Temp = (u32*)&pRetPar[23];		// Max_Flush_Timeout
		*pu4Temp = MaxFlushTimeout;
		pu4Temp = (u32*)&pRetPar[27];		// Best_Effort_Flush_Timeout
		*pu4Temp = BestEffortFlushTimeout;
		len += 31;
		PPacketIrpEvent->Length = len;
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("AmpStatus = 0x%x\n",
			AmpStatus));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("TotalBandwidth = 0x%x, MaxBandGUBandwidth = 0x%x, MinLatency = 0x%x, \n MaxPDUSize = 0x%x, ControlType = 0x%x\n",
			TotalBandwidth,MaxBandGUBandwidth,MinLatency,MaxPDUSize,ControlType));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PalCap = 0x%x, AmpAssocLen = 0x%x, MaxFlushTimeout = 0x%x, BestEffortFlushTimeout = 0x%x\n",
			PalCap,AmpAssocLen,MaxFlushTimeout,BestEffortFlushTimeout));
		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdCreatePhysicalLink(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS	status;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	pBtDbg->dbgHciInfo.hciCmdCntCreatePhyLink++;

	status = bthci_BuildPhysicalLink(padapter,
		pHciCmd, HCI_CREATE_PHYSICAL_LINK);

	return status;
}

static HCI_STATUS
bthci_CmdReadLinkQuality(
	struct rtw_adapter *					padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS			status = HCI_STATUS_SUCCESS;
	PBT30Info			pBTInfo = GET_BT_INFO(padapter);
	u16				PLH;
	u8				EntryNum, LinkQuality=0x55;

	PLH = *((u16*)&pHciCmd->Data[0]);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("PLH = 0x%x\n", PLH));

	EntryNum = bthci_GetCurrentEntryNum(padapter, (u8)PLH);
	if (EntryNum == 0xff)
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("No such PLH(0x%x)\n", PLH));
		status=HCI_STATUS_UNKNOW_CONNECT_ID;
	}

	{
		u8 localBuf[11] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_STATUS_PARAMETERS,
			HCI_READ_LINK_QUALITY,
			status);

		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" PLH = 0x%x\n Link Quality = 0x%x\n", PLH, LinkQuality));

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;			//status
		*((u16*)&(pRetPar[1])) = pBTInfo->BtAsocEntry[EntryNum].PhyLinkCmdData.BtPhyLinkhandle;	// Handle
		pRetPar[3] = 0x55;	//Link Quailty
		len += 4;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS bthci_CmdReadRSSI(struct rtw_adapter *padapter)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	return status;
}

static HCI_STATUS
bthci_CmdCreateLogicalLink(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	pBtDbg->dbgHciInfo.hciCmdCntCreateLogLink++;

	bthci_BuildLogicalLink(padapter, pHciCmd,
		HCI_CREATE_LOGICAL_LINK);

	return status;
}

static HCI_STATUS
bthci_CmdAcceptLogicalLink(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	pBtDbg->dbgHciInfo.hciCmdCntAcceptLogLink++;

	bthci_BuildLogicalLink(padapter, pHciCmd,
		HCI_ACCEPT_LOGICAL_LINK);

	return status;
}

static HCI_STATUS
bthci_CmdDisconnectLogicalLink(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTinfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTinfo->BtMgnt;
	PBT_DBG		pBtDbg = &pBTinfo->BtDbg;
	u16	logicHandle;
	u8 i, j, find=0, LogLinkCount=0;

	pBtDbg->dbgHciInfo.hciCmdCntDisconnectLogLink++;

	logicHandle = *((u16*)pHciCmd->Data);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle = 0x%x\n", logicHandle));

	// find an created logical link index and clear the data
	for (j=0; j<MAX_BT_ASOC_ENTRY_NUM;j++)
	{
		for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
		{
			if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle)
			{
				RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectLogicalLink, logicHandle is matched  0x%x\n", logicHandle));
				bthci_ResetFlowSpec(padapter, j, i);
				find = 1;
				pBtMgnt->DisconnectEntryNum = j;
				break;
			}
		}
	}

	if (!find)
		status = HCI_STATUS_UNKNOW_CONNECT_ID;

	// To check each
	for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
	{
		if (pBTinfo->BtAsocEntry[pBtMgnt->DisconnectEntryNum].LogLinkCmdData[i].BtLogLinkhandle !=0)
		{
			LogLinkCount++;
		}
	}

	//When we receive Create logical link command, we should send command status event first.
	bthci_EventCommandStatus(padapter,
			OGF_LINK_CONTROL_COMMANDS,
			HCI_DISCONNECT_LOGICAL_LINK,
			status);
	//
	//When we determines the logical link is established, we should send command complete event.
	//
	if (status == HCI_STATUS_SUCCESS)
	{
		bthci_EventDisconnectLogicalLinkComplete(padapter, status,
			logicHandle, HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST);
	}

	if (LogLinkCount == 0)
		PlatformSetTimer(padapter, &pBTinfo->BTDisconnectPhyLinkTimer, 100);

	return status;
}

static HCI_STATUS
bthci_CmdLogicalLinkCancel(struct rtw_adapter *padapter,
			   PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTinfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTinfo->BtMgnt;
	u8	CurrentEntryNum, CurrentLogEntryNum;

	u8	physicalLinkHandle, TxFlowSpecID,i;
	u16	CurrentLogicalHandle;

	physicalLinkHandle = *((u8*)pHciCmd->Data);
	TxFlowSpecID = *(((u8*)pHciCmd->Data)+1);

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, physicalLinkHandle = 0x%x, TxFlowSpecID = 0x%x\n",
		physicalLinkHandle, TxFlowSpecID));

	CurrentEntryNum=pBtMgnt->CurrentConnectEntryNum;
	CurrentLogicalHandle = pBtMgnt->BtCurrentLogLinkhandle;

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("CurrentEntryNum=0x%x, CurrentLogicalHandle = 0x%x\n",
		CurrentEntryNum, CurrentLogicalHandle));

	CurrentLogEntryNum = 0xff;
	for (i=0; i<MAX_LOGICAL_LINK_NUM; i++) {
		if ((CurrentLogicalHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtLogLinkhandle) &&
			(physicalLinkHandle == pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[i].BtPhyLinkhandle)) {
			CurrentLogEntryNum = i;
			break;
		}
	}

	if (CurrentLogEntryNum == 0xff) {
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, CurrentLogEntryNum==0xff !!!!\n"));
		status=HCI_STATUS_UNKNOW_CONNECT_ID;
		return status;
	} else {
		if (pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCompleteEventIsSet) {
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("LogicalLinkCancel, LLCompleteEventIsSet!!!!\n"));
			status=HCI_STATUS_ACL_CONNECT_EXISTS;
		}
	}

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_LINK_CONTROL_COMMANDS,
			HCI_LOGICAL_LINK_CANCEL,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pRetPar[1] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtPhyLinkhandle;
		pRetPar[2] = pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].BtTxFlowSpecID;
		len += 3;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	pBTinfo->BtAsocEntry[CurrentEntryNum].LogLinkCmdData[CurrentLogEntryNum].bLLCancelCMDIsSetandComplete=_TRUE;

	return status;
}

static HCI_STATUS
bthci_CmdFlowSpecModify(struct rtw_adapter *padapter,
			PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info pBTinfo = GET_BT_INFO(padapter);
	u8 i, j, find=0;
	u16 logicHandle;

	logicHandle = *((u16*)pHciCmd->Data);
	// find an matched logical link index and copy the data
	for (j=0;j<MAX_BT_ASOC_ENTRY_NUM;j++)
	{
		for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
		{
			if (pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle == logicHandle)
			{
				memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec,
					&pHciCmd->Data[2], sizeof(HCI_FLOW_SPEC));
				memcpy(&pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Rx_Flow_Spec,
					&pHciCmd->Data[18], sizeof(HCI_FLOW_SPEC));

				bthci_CheckLogLinkBehavior(padapter, pBTinfo->BtAsocEntry[j].LogLinkCmdData[i].Tx_Flow_Spec);
				find = 1;
				break;
			}
		}
	}
	RTPRINT(FIOCTL, IOCTL_BT_LOGO, ("FlowSpecModify, LLH = 0x%x, \n",logicHandle));

	//When we receive Flow Spec Modify command, we should send command status event first.
	bthci_EventCommandStatus(padapter,
		OGF_LINK_CONTROL_COMMANDS,
		HCI_FLOW_SPEC_MODIFY,
		HCI_STATUS_SUCCESS);

	if (!find)
		status = HCI_STATUS_UNKNOW_CONNECT_ID;

	bthci_EventSendFlowSpecModifyComplete(padapter, status, logicHandle);

	return status;
}

static HCI_STATUS
bthci_CmdAcceptPhysicalLink(struct rtw_adapter *padapter,
			    PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS	status;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	pBtDbg->dbgHciInfo.hciCmdCntAcceptPhyLink++;

	status = bthci_BuildPhysicalLink(padapter,
		pHciCmd, HCI_ACCEPT_PHYSICAL_LINK);

	return status;
}

static HCI_STATUS
bthci_CmdDisconnectPhysicalLink(struct rtw_adapter *padapter,
				PPACKET_IRP_HCICMD_DATA pHciCmd)
{

	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;
	u8		PLH, CurrentEntryNum, PhysLinkDisconnectReason;

	pBtDbg->dbgHciInfo.hciCmdCntDisconnectPhyLink++;

	PLH = *((u8*)pHciCmd->Data);
	PhysLinkDisconnectReason = (*((u8*)pHciCmd->Data+1));
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK  PhyHandle = 0x%x, Reason=0x%x\n",
		PLH, PhysLinkDisconnectReason));

	CurrentEntryNum = bthci_GetCurrentEntryNum(padapter, PLH);

	if (CurrentEntryNum == 0xff)
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("DisconnectPhysicalLink, No such Handle in the Entry\n"));
		status=HCI_STATUS_UNKNOW_CONNECT_ID;
		//return status;
	}

	pBTInfo->BtAsocEntry[CurrentEntryNum].PhyLinkDisconnectReason=(HCI_STATUS)PhysLinkDisconnectReason;
	//Send HCI Command status event to AMP.
	bthci_EventCommandStatus(padapter,
	OGF_LINK_CONTROL_COMMANDS,
	HCI_DISCONNECT_PHYSICAL_LINK,
	status);

	if (status != HCI_STATUS_SUCCESS)
		return status;

	if (pBTInfo->BtAsocEntry[CurrentEntryNum].BtCurrentState == HCI_STATE_DISCONNECTED)
	{
		BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum);
	}
	else
	{
		BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_DISCONNECT_PHY_LINK, CurrentEntryNum);
	}

	return status;
}

static HCI_STATUS
bthci_CmdSetACLLinkDataFlowMode(struct rtw_adapter *padapter,
				PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;

	pBtMgnt->ExtConfig.CurrentConnectHandle = *((u16*)pHciCmd->Data);
	pBtMgnt->ExtConfig.CurrentIncomingTrafficMode = *((u8*)pHciCmd->Data)+2;
	pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode = *((u8*)pHciCmd->Data)+3;
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Connection Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic mode = 0x%x",
		pBtMgnt->ExtConfig.CurrentConnectHandle,
		pBtMgnt->ExtConfig.CurrentIncomingTrafficMode,
		pBtMgnt->ExtConfig.CurrentOutgoingTrafficMode));

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
		u16 *pu2Temp;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_SET_ACL_LINK_DATA_FLOW_MODE,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		pu2Temp = (u16*)&pRetPar[1];
		*pu2Temp = pBtMgnt->ExtConfig.CurrentConnectHandle;
		len += 3;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdSetACLLinkStatus(struct rtw_adapter *padapter,
			  PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;
	u8		i;
	u8		*pTriple;

	pBtDbg->dbgHciInfo.hciCmdCntSetAclLinkStatus++;
	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "SetACLLinkStatus, Hex Data :\n",
			&pHciCmd->Data[0], pHciCmd->Length);

	// Only Core Stack v251 and later version support this command.
	pBtMgnt->bSupportProfile = _TRUE;

	pBtMgnt->ExtConfig.NumberOfHandle= *((u8*)pHciCmd->Data);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle));

	pTriple = &pHciCmd->Data[1];
	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16*)&pTriple[0]);
		pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = pTriple[2];
		pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = pTriple[3];
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT,
			("Connection_Handle = 0x%x, Incoming Traffic mode = 0x%x, Outgoing Traffic Mode = 0x%x\n",
			pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
			pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode,
			pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode));
		pTriple += 4;
	}

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_SET_ACL_LINK_STATUS,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdSetSCOLinkStatus(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	pBtDbg->dbgHciInfo.hciCmdCntSetScoLinkStatus++;
	pBtMgnt->ExtConfig.NumberOfSCO= *((u8*)pHciCmd->Data);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfSCO = 0x%x\n",
		pBtMgnt->ExtConfig.NumberOfSCO));

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_SET_SCO_LINK_STATUS,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdSetRSSIValue(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	s8		min_bt_rssi = 0;
	u8		i;
	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		if (pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle == *((u16*)&pHciCmd->Data[0]))
		{
			pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI = (s8)(pHciCmd->Data[2]);
			RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL,
			("Connection_Handle = 0x%x, RSSI = %d \n",
			pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
			pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI));
		}
		// get the minimum bt rssi value
		if (pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI <= min_bt_rssi)
		{
			min_bt_rssi = pBtMgnt->ExtConfig.linkInfo[i].BT_RSSI;
		}
	}

	{
		pBtMgnt->ExtConfig.MIN_BT_RSSI = min_bt_rssi;
		RTPRINT(FBT, BT_TRACE, ("[bt rssi], the min rssi is %d\n", min_bt_rssi));
	}

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_SET_RSSI_VALUE,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdSetCurrentBluetoothStatus(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO	pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;

	pBtMgnt->ExtConfig.CurrentBTStatus = *((u8*)&pHciCmd->Data[0]);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("SetCurrentBluetoothStatus, CurrentBTStatus = 0x%x\n",
		pBtMgnt->ExtConfig.CurrentBTStatus));

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_SET_CURRENT_BLUETOOTH_STATUS,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;

		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdExtensionVersionNotify(
	struct rtw_adapter *						padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	pBtDbg->dbgHciInfo.hciCmdCntExtensionVersionNotify++;
	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "ExtensionVersionNotify, Hex Data :\n",
			&pHciCmd->Data[0], pHciCmd->Length);

	pBtMgnt->ExtConfig.HCIExtensionVer = *((u16*)&pHciCmd->Data[0]);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = 0x%x\n", pBtMgnt->ExtConfig.HCIExtensionVer));

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_EXTENSION_VERSION_NOTIFY,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdLinkStatusNotify(
	struct rtw_adapter *						padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;
	u8		i;
	u8		*pTriple;

	pBtDbg->dbgHciInfo.hciCmdCntLinkStatusNotify++;
	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "LinkStatusNotify, Hex Data :\n",
			&pHciCmd->Data[0], pHciCmd->Length);

	// Current only RTL8723 support this command.
	pBtMgnt->bSupportProfile = _TRUE;

	pBtMgnt->ExtConfig.NumberOfHandle= *((u8*)pHciCmd->Data);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("NumberOfHandle = 0x%x\n", pBtMgnt->ExtConfig.NumberOfHandle));
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer));

	pTriple = &pHciCmd->Data[1];
	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		if (pBtMgnt->ExtConfig.HCIExtensionVer < 1)
		{
			pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16*)&pTriple[0]);
			pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2];
			pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3];
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT,
			("Connection_Handle = 0x%x, BTProfile=%d, BTSpec=%d\n",
				pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
				pBtMgnt->ExtConfig.linkInfo[i].BTProfile,
				pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec));
		pTriple += 4;
	}
		else if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1)
		{
			pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle = *((u16*)&pTriple[0]);
			pBtMgnt->ExtConfig.linkInfo[i].BTProfile = pTriple[2];
			pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec = pTriple[3];
			pBtMgnt->ExtConfig.linkInfo[i].linkRole = pTriple[4];
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT,
				("Connection_Handle = 0x%x, BTProfile=%d, BTSpec=%d, LinkRole=%d\n",
				pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle,
				pBtMgnt->ExtConfig.linkInfo[i].BTProfile,
				pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec,
				pBtMgnt->ExtConfig.linkInfo[i].linkRole));
			pTriple += 5;
		}

	}
	BTHCI_UpdateBTProfileRTKToMoto(padapter);
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_LINK_STATUS_NOTIFY,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdBtOperationNotify(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Bt Operation notify, Hex Data :\n",
			&pHciCmd->Data[0], pHciCmd->Length);

	pBtMgnt->ExtConfig.btOperationCode = *((u8*)pHciCmd->Data);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("btOperationCode = 0x%x\n", pBtMgnt->ExtConfig.btOperationCode));
	switch (pBtMgnt->ExtConfig.btOperationCode)
	{
		case HCI_BT_OP_NONE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Operation None!!\n"));
			break;
		case HCI_BT_OP_INQUIRY_START:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire start!!\n"));
			break;
		case HCI_BT_OP_INQUIRY_FINISH:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Inquire finished!!\n"));
			break;
		case HCI_BT_OP_PAGING_START:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging is started!!\n"));
			break;
		case HCI_BT_OP_PAGING_SUCCESS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete successfully!!\n"));
			break;
		case HCI_BT_OP_PAGING_UNSUCCESS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Paging complete unsuccessfully!!\n"));
			break;
		case HCI_BT_OP_PAIRING_START:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing start!!\n"));
			break;
		case HCI_BT_OP_PAIRING_FINISH:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Pairing finished!!\n"));
			break;
		case HCI_BT_OP_BT_DEV_ENABLE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is enabled!!\n"));
			break;
		case HCI_BT_OP_BT_DEV_DISABLE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : BT Device is disabled!!\n"));
			break;
		default:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[bt operation] : Unknown, error!!\n"));
			break;
	}
	BTDM_AdjustForBtOperation(padapter);
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_BT_OPERATION_NOTIFY,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdEnableWifiScanNotify(struct rtw_adapter *padapter,
			      PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "Enable Wifi scan notify, Hex Data :\n",
			&pHciCmd->Data[0], pHciCmd->Length);

	pBtMgnt->ExtConfig.bEnableWifiScanNotify = *((u8*)pHciCmd->Data);
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("bEnableWifiScanNotify = %d\n", pBtMgnt->ExtConfig.bEnableWifiScanNotify));

	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_ENABLE_WIFI_SCAN_NOTIFY,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status

		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdWIFICurrentChannel(struct rtw_adapter *padapter,
			    PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
//	u8		chnl = pMgntInfo->dot11CurrentChannelNumber;
	u8		chnl = pmlmeext->cur_channel;

//	if (pMgntInfo->pHTInfo->bCurBW40MHz == HT_CHANNEL_WIDTH_20_40)
	if (pmlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
	{
//		if (pMgntInfo->pHTInfo->CurSTAExtChnlOffset == HT_EXTCHNL_OFFSET_UPPER)
		if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
		{
			chnl += 2;
		}
//		else if (pMgntInfo->pHTInfo->CurSTAExtChnlOffset == HT_EXTCHNL_OFFSET_LOWER)
		else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
		{
			chnl -= 2;
		}
	}

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current Channel  = 0x%x\n", chnl));

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_WIFI_CURRENT_CHANNEL,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pRetPar[1] = chnl;			//current channel
		len += 2;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdWIFICurrentBandwidth(struct rtw_adapter *padapter,
			      PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	HT_CHANNEL_WIDTH bw;
	u8	CurrentBW = 0;


//	rtw_hal_get_hwreg(padapter, HW_VAR_BW_MODE, (u8*)(&bw));
	bw = padapter->mlmeextpriv.cur_bwmode;

	if (bw == HT_CHANNEL_WIDTH_20)
	{
		CurrentBW = 0;
	}
	else if (bw == HT_CHANNEL_WIDTH_40)
	{
		CurrentBW = 1;
	}

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("Current BW = 0x%x\n",
		CurrentBW));

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_WIFI_CURRENT_BANDWIDTH,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		pRetPar[1] = CurrentBW;		//current BW
		len += 2;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdWIFIConnectionStatus(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	struct rtw_adapter *pDefaultAdapter = GetDefaultAdapter(padapter);
	u8		connectStatus = HCI_WIFI_NOT_CONNECTED;

	if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) {
		if (padapter->stapriv.asoc_sta_count >= 3)
			connectStatus = HCI_WIFI_CONNECTED;
		else
			connectStatus = HCI_WIFI_NOT_CONNECTED;
	}
	else if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_ASOC_STATE) == _TRUE)
		connectStatus = HCI_WIFI_CONNECTED;
	else if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING) == _TRUE)
		connectStatus = HCI_WIFI_CONNECT_IN_PROGRESS;
	else
		connectStatus = HCI_WIFI_NOT_CONNECTED;

	{
		u8 localBuf[8] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_EXTENSION,
			HCI_WIFI_CONNECTION_STATUS,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;			//status
		pRetPar[1] = connectStatus;	//connect status
		len += 2;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdEnableDeviceUnderTestMode(
	struct rtw_adapter *	padapter,
	PPACKET_IRP_HCICMD_DATA		pHciCmd
	)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;

	pBtHciInfo->bInTestMode = _TRUE;
	pBtHciInfo->bTestIsEnd = _FALSE;

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_TESTING_COMMANDS,
			HCI_ENABLE_DEVICE_UNDER_TEST_MODE,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdAMPTestEnd(struct rtw_adapter *padapter,
		    PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	u8		bFilterOutNonAssociatedBSSID = _TRUE;

	if (!pBtHciInfo->bInTestMode)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status=HCI_STATUS_CMD_DISALLOW\n"));
		status = HCI_STATUS_CMD_DISALLOW;
		return status;
	}

	pBtHciInfo->bTestIsEnd=_TRUE;

	PlatformCancelTimer(padapter,&pBTInfo->BTTestSendPacketTimer);

	rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_BSSID, (u8*)(&bFilterOutNonAssociatedBSSID));


	//send command complete event here when all data are received.
	{
		u8	localBuf[4] = "";
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n"));
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
		PPacketIrpEvent->EventCode=HCI_EVENT_AMP_TEST_END;
		PPacketIrpEvent->Length=2;

		PPacketIrpEvent->Data[0] = status;
		PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);
	}

	bthci_EventAMPReceiverReport(padapter,0x01);

	return status;
}

static HCI_STATUS
bthci_CmdAMPTestCommand(struct rtw_adapter *padapter,
			PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;

	if (!pBtHciInfo->bInTestMode)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Not in Test mode, return status=HCI_STATUS_CMD_DISALLOW\n"));
		status = HCI_STATUS_CMD_DISALLOW;
		return status;
	}


	pBtHciInfo->TestScenario=*((u8*)pHciCmd->Data);

	if (pBtHciInfo->TestScenario == 0x01)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n"));
	}
	else if (pBtHciInfo->TestScenario == 0x02)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n"));
	}
	else
	{
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("No Such Test !!!!!!!!!!!!!!!!!! \n"));
	}


	if (pBtHciInfo->bTestIsEnd)
	{
		u8	localBuf[5] = "";
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;


		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("AMP Test End Event \n"));
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
		PPacketIrpEvent->EventCode=HCI_EVENT_AMP_TEST_END;
		PPacketIrpEvent->Length=2;

		PPacketIrpEvent->Data[0] = status;
		PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);

		//Return to Idel state with RX and TX off.

		return status;
	}

	// should send command status event
	bthci_EventCommandStatus(padapter,
			OGF_TESTING_COMMANDS,
			HCI_AMP_TEST_COMMAND,
			status);

	//The HCI_AMP_Start Test Event shall be generated when the
	//HCI_AMP_Test_Command has completed and the first data is ready to be sent
	//or received.

	{
		u8	localBuf[5] = "";
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), (" HCI_AMP_Start Test Event \n"));
		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
		PPacketIrpEvent->EventCode=HCI_EVENT_AMP_START_TEST;
		PPacketIrpEvent->Length=2;

		PPacketIrpEvent->Data[0] = status;
		PPacketIrpEvent->Data[1] = pBtHciInfo->TestScenario ;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, 4);

		//Return to Idel state with RX and TX off.
	}

	if (pBtHciInfo->TestScenario == 0x01)
	{
		/*
			When in a transmitter test scenario and the frames/bursts count have been
			transmitted the HCI_AMP_Test_End event shall be sent.
		*/
		PlatformSetTimer(padapter, &pBTInfo->BTTestSendPacketTimer, 50);
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("TX Single Test \n"));
	}
	else if (pBtHciInfo->TestScenario == 0x02)
	{
		u8		bFilterOutNonAssociatedBSSID=_FALSE;
		rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_BSSID, (u8*)(&bFilterOutNonAssociatedBSSID));
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_BT_LOGO), ("Receive Frame Test \n"));
	}

	return status;
}

static HCI_STATUS
bthci_CmdEnableAMPReceiverReports(struct rtw_adapter *padapter,
				  PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;

	if (!pBtHciInfo->bInTestMode)
	{
		status = HCI_STATUS_CMD_DISALLOW;
		//send command complete event here when all data are received.
		{
			u8 localBuf[6] = "";
			u8 *pRetPar;
			u8 len = 0;
			PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

			PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

			len += bthci_CommandCompleteHeader(&localBuf[0],
				OGF_TESTING_COMMANDS,
				HCI_ENABLE_AMP_RECEIVER_REPORTS,
				status);

			// Return parameters starts from here
			pRetPar = &PPacketIrpEvent->Data[len];
			pRetPar[0] = status;		//status
			len += 1;
			PPacketIrpEvent->Length = len;

			bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
		}
		return status;
	}

	pBtHciInfo->bTestNeedReport= *((u8*)pHciCmd->Data);
	pBtHciInfo->TestReportInterval= (*((u8*)pHciCmd->Data+2));

	bthci_EventAMPReceiverReport(padapter,0x00);

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_TESTING_COMMANDS,
			HCI_ENABLE_AMP_RECEIVER_REPORTS,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdHostBufferSize(struct rtw_adapter *padapter,
			PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].ACLPacketsData.ACLDataPacketLen= *((u16*)pHciCmd->Data);
	pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].SyncDataPacketLen= *((u8 *)(pHciCmd->Data+2));
	pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalNumACLDataPackets= *((u16 *)(pHciCmd->Data+3));
	pBTInfo->BtAsocEntry[pBtMgnt->CurrentConnectEntryNum].TotalSyncNumDataPackets= *((u16 *)(pHciCmd->Data+5));

	//send command complete event here when all data are received.
	{
		u8 localBuf[6] = "";
		u8 *pRetPar;
		u8 len = 0;
		PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

		PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

		len += bthci_CommandCompleteHeader(&localBuf[0],
			OGF_SET_EVENT_MASK_COMMAND,
			HCI_HOST_BUFFER_SIZE,
			status);

		// Return parameters starts from here
		pRetPar = &PPacketIrpEvent->Data[len];
		pRetPar[0] = status;		//status
		len += 1;
		PPacketIrpEvent->Length = len;

		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}

	return status;
}

static HCI_STATUS
bthci_CmdHostNumberOfCompletedPackets(struct rtw_adapter *padapter,
				      PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	return status;
}

static HCI_STATUS
bthci_UnknownCMD(struct rtw_adapter *padapter, PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_UNKNOW_HCI_CMD;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	pBtDbg->dbgHciInfo.hciCmdCntUnknown++;
	bthci_EventCommandStatus(padapter,
			(u8)pHciCmd->OGF,
			pHciCmd->OCF,
			status);

	return status;
}

static HCI_STATUS
bthci_HandleOGFInformationalParameters(struct rtw_adapter *padapter,
				       PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	switch (pHciCmd->OCF)
	{
	case HCI_READ_LOCAL_VERSION_INFORMATION:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_VERSION_INFORMATION\n"));
		status = bthci_CmdReadLocalVersionInformation(padapter);
		break;
	case HCI_READ_LOCAL_SUPPORTED_COMMANDS:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_COMMANDS\n"));
		status = bthci_CmdReadLocalSupportedCommands(padapter);
		break;
	case HCI_READ_LOCAL_SUPPORTED_FEATURES:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_SUPPORTED_FEATURES\n"));
		status = bthci_CmdReadLocalSupportedFeatures(padapter);
		break;
	case HCI_READ_BUFFER_SIZE:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BUFFER_SIZE\n"));
		status = bthci_CmdReadBufferSize(padapter);
		break;
	case HCI_READ_DATA_BLOCK_SIZE:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_DATA_BLOCK_SIZE\n"));
		status = bthci_CmdReadDataBlockSize(padapter);
		break;
	default:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFInformationalParameters(), Unknown case = 0x%x\n", pHciCmd->OCF));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
		status = bthci_UnknownCMD(padapter, pHciCmd);
		break;
	}
	return status;
}

static HCI_STATUS
bthci_HandleOGFSetEventMaskCMD(struct rtw_adapter *padapter,
			       PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	switch (pHciCmd->OCF)
	{
	case HCI_SET_EVENT_MASK:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK\n"));
		status = bthci_CmdSetEventMask(padapter, pHciCmd);
		break;
	case HCI_RESET:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET\n"));
		status = bthci_CmdReset(padapter, _TRUE);
		break;
	case HCI_READ_CONNECTION_ACCEPT_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_CONNECTION_ACCEPT_TIMEOUT\n"));
		status = bthci_CmdReadConnectionAcceptTimeout(padapter);
		break;
	case HCI_SET_EVENT_FILTER:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_FILTER\n"));
		status = bthci_CmdSetEventFilter(padapter, pHciCmd);
		break;
	case HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_CONNECTION_ACCEPT_TIMEOUT\n"));
		status = bthci_CmdWriteConnectionAcceptTimeout(padapter, pHciCmd);
		break;
	case HCI_READ_PAGE_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_PAGE_TIMEOUT\n"));
		status = bthci_CmdReadPageTimeout(padapter, pHciCmd);
		break;
	case HCI_WRITE_PAGE_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_PAGE_TIMEOUT\n"));
		status = bthci_CmdWritePageTimeout(padapter, pHciCmd);
		break;
	case HCI_HOST_NUMBER_OF_COMPLETED_PACKETS:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_NUMBER_OF_COMPLETED_PACKETS\n"));
		status = bthci_CmdHostNumberOfCompletedPackets(padapter, pHciCmd);
		break;
	case HCI_READ_LINK_SUPERVISION_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_SUPERVISION_TIMEOUT\n"));
		status = bthci_CmdReadLinkSupervisionTimeout(padapter, pHciCmd);
		break;
	case HCI_WRITE_LINK_SUPERVISION_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LINK_SUPERVISION_TIMEOUT\n"));
		status = bthci_CmdWriteLinkSupervisionTimeout(padapter, pHciCmd);
		break;
	case HCI_ENHANCED_FLUSH:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENHANCED_FLUSH\n"));
		status = bthci_CmdEnhancedFlush(padapter, pHciCmd);
		break;
	case HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOGICAL_LINK_ACCEPT_TIMEOUT\n"));
		status = bthci_CmdReadLogicalLinkAcceptTimeout(padapter, pHciCmd);
		break;
	case HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT\n"));
		status = bthci_CmdWriteLogicalLinkAcceptTimeout(padapter, pHciCmd);
		break;
	case HCI_SET_EVENT_MASK_PAGE_2:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SET_EVENT_MASK_PAGE_2\n"));
		status = bthci_CmdSetEventMaskPage2(padapter, pHciCmd);
		break;
	case HCI_READ_LOCATION_DATA:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCATION_DATA\n"));
		status = bthci_CmdReadLocationData(padapter, pHciCmd);
		break;
	case HCI_WRITE_LOCATION_DATA:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_LOCATION_DATA\n"));
		status = bthci_CmdWriteLocationData(padapter, pHciCmd);
		break;
	case HCI_READ_FLOW_CONTROL_MODE:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FLOW_CONTROL_MODE\n"));
		status = bthci_CmdReadFlowControlMode(padapter, pHciCmd);
		break;
	case HCI_WRITE_FLOW_CONTROL_MODE:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_FLOW_CONTROL_MODE\n"));
		status = bthci_CmdWriteFlowControlMode(padapter, pHciCmd);
		break;
	case HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_BEST_EFFORT_FLUSH_TIMEOUT\n"));
		status = bthci_CmdReadBestEffortFlushTimeout(padapter, pHciCmd);
		break;
	case HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_BEST_EFFORT_FLUSH_TIMEOUT\n"));
		status = bthci_CmdWriteBestEffortFlushTimeout(padapter, pHciCmd);
		break;
	case HCI_SHORT_RANGE_MODE:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_SHORT_RANGE_MODE\n"));
		status = bthci_CmdShortRangeMode(padapter, pHciCmd);
		break;
	case HCI_HOST_BUFFER_SIZE:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_HOST_BUFFER_SIZE\n"));
		status = bthci_CmdHostBufferSize(padapter,pHciCmd);
		break;
	default:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFSetEventMaskCMD(), Unknown case = 0x%x\n", pHciCmd->OCF));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
		status = bthci_UnknownCMD(padapter, pHciCmd);
		break;
	}
	return status;
}

static HCI_STATUS
bthci_HandleOGFStatusParameters(struct rtw_adapter *padapter,
				PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	switch (pHciCmd->OCF)
	{
	case HCI_READ_FAILED_CONTACT_COUNTER:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_FAILED_CONTACT_COUNTER\n"));
		status = bthci_CmdReadFailedContactCounter(padapter,pHciCmd);
		break;
	case HCI_RESET_FAILED_CONTACT_COUNTER:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_RESET_FAILED_CONTACT_COUNTER\n"));
		status = bthci_CmdResetFailedContactCounter(padapter,pHciCmd);
		break;
	case HCI_READ_LINK_QUALITY:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LINK_QUALITY\n"));
		status = bthci_CmdReadLinkQuality(padapter, pHciCmd);
		break;
	case HCI_READ_RSSI:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_RSSI\n"));
		status = bthci_CmdReadRSSI(padapter);
		break;
	case HCI_READ_LOCAL_AMP_INFO:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_INFO\n"));
		status = bthci_CmdReadLocalAMPInfo(padapter);
		break;
	case HCI_READ_LOCAL_AMP_ASSOC:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_READ_LOCAL_AMP_ASSOC\n"));
                status = bthci_CmdReadLocalAMPAssoc(padapter,pHciCmd);
		break;
	case HCI_WRITE_REMOTE_AMP_ASSOC:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_WRITE_REMOTE_AMP_ASSOC\n"));
		status = bthci_CmdWriteRemoteAMPAssoc(padapter,pHciCmd);
		break;
	default:
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFStatusParameters(), Unknown case = 0x%x\n", pHciCmd->OCF));
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
		status = bthci_UnknownCMD(padapter, pHciCmd);
		break;
	}
	return status;
}

static HCI_STATUS
bthci_HandleOGFLinkControlCMD(struct rtw_adapter *padapter,
			      PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;

	switch (pHciCmd->OCF)
	{
		case HCI_CREATE_PHYSICAL_LINK:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_PHYSICAL_LINK\n"));
			status = bthci_CmdCreatePhysicalLink(padapter,pHciCmd);
			break;
		case HCI_ACCEPT_PHYSICAL_LINK:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_PHYSICAL_LINK\n"));
			status = bthci_CmdAcceptPhysicalLink(padapter,pHciCmd);
			break;
		case HCI_DISCONNECT_PHYSICAL_LINK:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_PHYSICAL_LINK\n"));
			status = bthci_CmdDisconnectPhysicalLink(padapter,pHciCmd);
			break;
		case HCI_CREATE_LOGICAL_LINK:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_CREATE_LOGICAL_LINK\n"));
			status = bthci_CmdCreateLogicalLink(padapter,pHciCmd);
			break;
		case HCI_ACCEPT_LOGICAL_LINK:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ACCEPT_LOGICAL_LINK\n"));
			status = bthci_CmdAcceptLogicalLink(padapter,pHciCmd);
			break;
		case HCI_DISCONNECT_LOGICAL_LINK:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_DISCONNECT_LOGICAL_LINK\n"));
			status = bthci_CmdDisconnectLogicalLink(padapter,pHciCmd);
			break;
		case HCI_LOGICAL_LINK_CANCEL:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_LOGICAL_LINK_CANCEL\n"));
			status = bthci_CmdLogicalLinkCancel(padapter,pHciCmd);
			break;
		case HCI_FLOW_SPEC_MODIFY:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_FLOW_SPEC_MODIFY\n"));
			status = bthci_CmdFlowSpecModify(padapter,pHciCmd);
			break;

		default:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("bthci_HandleOGFLinkControlCMD(), Unknown case = 0x%x\n", pHciCmd->OCF));
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
			status = bthci_UnknownCMD(padapter, pHciCmd);
			break;
	}
	return status;
}

static HCI_STATUS
bthci_HandleOGFTestingCMD(struct rtw_adapter *padapter,
			  PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	switch (pHciCmd->OCF)
	{
		case HCI_ENABLE_DEVICE_UNDER_TEST_MODE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_DEVICE_UNDER_TEST_MODE\n"));
			bthci_CmdEnableDeviceUnderTestMode(padapter,pHciCmd);
			break;
		case HCI_AMP_TEST_END:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_END\n"));
			bthci_CmdAMPTestEnd(padapter,pHciCmd);
			break;
		case HCI_AMP_TEST_COMMAND:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_AMP_TEST_COMMAND\n"));
			bthci_CmdAMPTestCommand(padapter,pHciCmd);
			break;
		case HCI_ENABLE_AMP_RECEIVER_REPORTS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_ENABLE_AMP_RECEIVER_REPORTS\n"));
			bthci_CmdEnableAMPReceiverReports(padapter,pHciCmd);
			break;

		default:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
			status = bthci_UnknownCMD(padapter, pHciCmd);
			break;
	}
	return status;
}

static HCI_STATUS
bthci_HandleOGFExtension(struct rtw_adapter *padapter,
			 PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	HCI_STATUS status = HCI_STATUS_SUCCESS;
	switch (pHciCmd->OCF)
	{
		case HCI_SET_ACL_LINK_DATA_FLOW_MODE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_DATA_FLOW_MODE\n"));
			status = bthci_CmdSetACLLinkDataFlowMode(padapter,pHciCmd);
			break;
		case HCI_SET_ACL_LINK_STATUS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_ACL_LINK_STATUS\n"));
			status = bthci_CmdSetACLLinkStatus(padapter,pHciCmd);
			break;
		case HCI_SET_SCO_LINK_STATUS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_SCO_LINK_STATUS\n"));
			status = bthci_CmdSetSCOLinkStatus(padapter,pHciCmd);
			break;
		case HCI_SET_RSSI_VALUE:
			RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("HCI_SET_RSSI_VALUE\n"));
			status = bthci_CmdSetRSSIValue(padapter,pHciCmd);
			break;
		case HCI_SET_CURRENT_BLUETOOTH_STATUS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_SET_CURRENT_BLUETOOTH_STATUS\n"));
			status = bthci_CmdSetCurrentBluetoothStatus(padapter,pHciCmd);
			break;
		//The following is for RTK8723

		case HCI_EXTENSION_VERSION_NOTIFY:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_EXTENSION_VERSION_NOTIFY\n"));
			status = bthci_CmdExtensionVersionNotify(padapter,pHciCmd);
			break;
		case HCI_LINK_STATUS_NOTIFY:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_LINK_STATUS_NOTIFY\n"));
			status = bthci_CmdLinkStatusNotify(padapter,pHciCmd);
			break;
		case HCI_BT_OPERATION_NOTIFY:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_BT_OPERATION_NOTIFY\n"));
			status = bthci_CmdBtOperationNotify(padapter,pHciCmd);
			break;
		case HCI_ENABLE_WIFI_SCAN_NOTIFY:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_ENABLE_WIFI_SCAN_NOTIFY\n"));
			status = bthci_CmdEnableWifiScanNotify(padapter,pHciCmd);
			break;

		//The following is for IVT
		case HCI_WIFI_CURRENT_CHANNEL:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_CHANNEL\n"));
			status = bthci_CmdWIFICurrentChannel(padapter,pHciCmd);
			break;
		case HCI_WIFI_CURRENT_BANDWIDTH:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CURRENT_BANDWIDTH\n"));
			status = bthci_CmdWIFICurrentBandwidth(padapter,pHciCmd);
			break;
		case HCI_WIFI_CONNECTION_STATUS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_WIFI_CONNECTION_STATUS\n"));
			status = bthci_CmdWIFIConnectionStatus(padapter,pHciCmd);
			break;

		default:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCI_UNKNOWN_COMMAND\n"));
			status = bthci_UnknownCMD(padapter, pHciCmd);
			break;
	}
	return status;
}

static void
bthci_FakeCommand(struct rtw_adapter *padapter,	u16 OGF, u16 OCF)
{
#define MAX_TMP_BUF_SIZE	200
	u8	buffer[MAX_TMP_BUF_SIZE];
	PPACKET_IRP_HCICMD_DATA pCmd=(PPACKET_IRP_HCICMD_DATA)buffer;

	PlatformZeroMemory(buffer, MAX_TMP_BUF_SIZE);

	pCmd->OGF = OGF;
	pCmd->OCF = OCF;

	if (OGF == OGF_LINK_CONTROL_COMMANDS && OCF == HCI_LOGICAL_LINK_CANCEL)
	{
		pCmd->Length = 2;
		pCmd->Data[0] = 1;		//physical link handle
		pCmd->Data[1] = 0x16;		//Tx_Flow_Spec_ID
		BTHCI_HandleHCICMD(padapter, (PPACKET_IRP_HCICMD_DATA)buffer);
	}
}

static void
bthci_StateStarting(struct rtw_adapter *padapter,
		    HCI_STATE_WITH_CMD StateCmd, u8 EntryNum)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Starting], "));
	switch (StateCmd)
	{
		case STATE_CMD_CONNECT_ACCEPT_TIMEOUT:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n"));
			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_CONNECT_ACCEPT_TIMEOUT;
			pBtMgnt->bNeedNotifyAMPNoCap = _TRUE;
			BTHCI_DisconnectPeer(padapter,EntryNum);
			break;
		}

		case STATE_CMD_DISCONNECT_PHY_LINK:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));

			bthci_EventDisconnectPhyLinkComplete(padapter,
			HCI_STATUS_SUCCESS,
			pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
			EntryNum);

			PlatformCancelTimer(padapter,&pBTInfo->BTHCIJoinTimeoutTimer);

			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_UNKNOW_CONNECT_ID;

			BTHCI_DisconnectPeer(padapter, EntryNum);
			break;
		}

		case STATE_CMD_MAC_START_COMPLETE:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_START_COMPLETE\n"));
			if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_JOINER)
			{
			}
			else if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_CREATOR)
			{
				bthci_EventChannelSelected(padapter,EntryNum);
			}

			break;
		}

		default:
			RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
			break;
	}
}

static void
bthci_StateConnecting(struct rtw_adapter *padapter,
		      HCI_STATE_WITH_CMD StateCmd, u8 EntryNum)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connecting], "));
	switch (StateCmd)
	{
		case STATE_CMD_CONNECT_ACCEPT_TIMEOUT:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n"));
			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_CONNECT_ACCEPT_TIMEOUT;
			pBtMgnt->bNeedNotifyAMPNoCap = _TRUE;
			BTHCI_DisconnectPeer(padapter, EntryNum);
			break;
		}

		case STATE_CMD_MAC_CONNECT_COMPLETE:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_COMPLETE\n"));

			if (pBTInfo->BtAsocEntry[EntryNum].AMPRole == AMP_BTAP_JOINER)
			{
				RT_TRACE(_module_rtl871x_security_c_, _drv_info_ , ("StateConnecting \n"));
			}
			break;
		}

		case STATE_CMD_DISCONNECT_PHY_LINK:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));

			bthci_EventDisconnectPhyLinkComplete(padapter,
			HCI_STATUS_SUCCESS,
			pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
			EntryNum);

			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_UNKNOW_CONNECT_ID;

			PlatformCancelTimer(padapter,&pBTInfo->BTHCIJoinTimeoutTimer);

			BTHCI_DisconnectPeer(padapter, EntryNum);

			break;
		}

		case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n"));
			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_CONTROLLER_BUSY;
			// Because this state cmd is caused by the BTHCI_EventAMPStatusChange(),
			// we don't need to send event in the following BTHCI_DisconnectPeer() again.
			pBtMgnt->bNeedNotifyAMPNoCap = _FALSE;
			BTHCI_DisconnectPeer(padapter, EntryNum);
			break;
		}

		default:
			RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
			break;
	}
}

static void
bthci_StateConnected(struct rtw_adapter *padapter,
		     HCI_STATE_WITH_CMD StateCmd, u8 EntryNum)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Connected], "));
	switch (StateCmd)
	{
		case STATE_CMD_DISCONNECT_PHY_LINK:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));

			//
			//When we are trying to disconnect the phy link, we should disconnect log link first,
			//
			{
				u8 i;
				u16 logicHandle = 0;
				for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
				{
					if (pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle != 0)
					{
						logicHandle=pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle;

						bthci_EventDisconnectLogicalLinkComplete(padapter, HCI_STATUS_SUCCESS,
							logicHandle, pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason);

						pBTInfo->BtAsocEntry[EntryNum].LogLinkCmdData->BtLogLinkhandle = 0;
					}
				}
			}

			bthci_EventDisconnectPhyLinkComplete(padapter,
			HCI_STATUS_SUCCESS,
			pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
			EntryNum);

			PlatformCancelTimer(padapter, &pBTInfo->BTHCIJoinTimeoutTimer);

			BTHCI_DisconnectPeer(padapter, EntryNum);
			break;
		}

		case STATE_CMD_MAC_DISCONNECT_INDICATE:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_DISCONNECT_INDICATE\n"));

			bthci_EventDisconnectPhyLinkComplete(padapter,
			HCI_STATUS_SUCCESS,
			// TODO: Remote Host not local host
			HCI_STATUS_CONNECT_TERMINATE_LOCAL_HOST,
			EntryNum);
			BTHCI_DisconnectPeer(padapter, EntryNum);

			break;
		}

		case STATE_CMD_ENTER_STATE:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n"));

			if (pBtMgnt->bBTConnectInProgress)
			{
				pBtMgnt->bBTConnectInProgress = _FALSE;
				RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
			}
			pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = HCI_STATE_CONNECTED;
			pBTInfo->BtAsocEntry[EntryNum].b4waySuccess = _TRUE;
			pBtMgnt->bStartSendSupervisionPkt = _TRUE;

			PlatformSetTimer(padapter, &pBTInfo->BTSupervisionPktTimer, 10000);
			// for rate adaptive

			if(padapter->HalFunc.UpdateRAMaskHandler)
				padapter->HalFunc.UpdateRAMaskHandler(padapter, MAX_FW_SUPPORT_MACID_NUM-1-EntryNum, 0);

			rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, padapter->mlmepriv.cur_network.network.SupportedRates);
			BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT);

			break;
		}

		default:
			RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
			break;
	}
}

static void
bthci_StateAuth(struct rtw_adapter *padapter, HCI_STATE_WITH_CMD StateCmd,
		u8 EntryNum)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Authenticating], "));
	switch (StateCmd)
	{
		case STATE_CMD_CONNECT_ACCEPT_TIMEOUT:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CONNECT_ACCEPT_TIMEOUT\n"));
			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_CONNECT_ACCEPT_TIMEOUT;
			pBtMgnt->bNeedNotifyAMPNoCap = _TRUE;
			BTHCI_DisconnectPeer(padapter, EntryNum);
			break;
		}

		case STATE_CMD_DISCONNECT_PHY_LINK:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));
			bthci_EventDisconnectPhyLinkComplete(padapter,
			HCI_STATUS_SUCCESS,
			pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
			EntryNum);

			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_UNKNOW_CONNECT_ID;

			PlatformCancelTimer(padapter,&pBTInfo->BTHCIJoinTimeoutTimer);

			BTHCI_DisconnectPeer(padapter,EntryNum);
			break;
		}

		case STATE_CMD_4WAY_FAILED:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_FAILED\n"));

			pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus=HCI_STATUS_AUTH_FAIL;
			pBtMgnt->bNeedNotifyAMPNoCap = _TRUE;

			BTHCI_DisconnectPeer(padapter,EntryNum);

			PlatformCancelTimer(padapter,&pBTInfo->BTHCIJoinTimeoutTimer);
			break;
		}

		case STATE_CMD_4WAY_SUCCESSED:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_4WAY_SUCCESSED\n"));

			bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_SUCCESS, EntryNum, INVALID_PL_HANDLE);

			PlatformCancelTimer(padapter, &pBTInfo->BTHCIJoinTimeoutTimer);

			BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_ENTER_STATE, EntryNum);
			break;
		}

		default:
			RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
			break;
	}
}

static void
bthci_StateDisconnecting(struct rtw_adapter *padapter,
			 HCI_STATE_WITH_CMD StateCmd, u8 EntryNum)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnecting], "));
	switch (StateCmd)
	{
		case STATE_CMD_MAC_CONNECT_CANCEL_INDICATE:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_MAC_CONNECT_CANCEL_INDICATE\n"));
			if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent)
			{
				bthci_EventPhysicalLinkComplete(padapter,
					pBTInfo->BtAsocEntry[EntryNum].PhysLinkCompleteStatus,
					EntryNum, INVALID_PL_HANDLE);
			}

			if (pBtMgnt->bBTConnectInProgress)
			{
				pBtMgnt->bBTConnectInProgress = _FALSE;
				RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
			}

			BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum);
			break;
		}

		case STATE_CMD_DISCONNECT_PHY_LINK:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));

			bthci_EventDisconnectPhyLinkComplete(padapter,
			HCI_STATUS_SUCCESS,
			pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
			EntryNum);

			PlatformCancelTimer(padapter,&pBTInfo->BTHCIJoinTimeoutTimer);

			BTHCI_DisconnectPeer(padapter, EntryNum);
			break;
		}

		default:
			RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
			break;
	}
}

static void
bthci_StateDisconnected(struct rtw_adapter *padapter,
			HCI_STATE_WITH_CMD StateCmd, u8 EntryNum)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_STATE, ("[BT state], [Disconnected], "));
	switch (StateCmd)
	{
		case STATE_CMD_CREATE_PHY_LINK:
		case STATE_CMD_ACCEPT_PHY_LINK:
		{
			if (StateCmd == STATE_CMD_CREATE_PHY_LINK)
			{
				RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_CREATE_PHY_LINK\n"));
			}
			else
			{
				RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ACCEPT_PHY_LINK\n"));
			}

			RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], Disable IPS and LPS\n"));
			IPSDisable(padapter, _FALSE, IPS_DISABLE_BT_ON);
			LeisurePSLeave(padapter, LPS_DISABLE_BT_HS_CONNECTION);

			pBtMgnt->bPhyLinkInProgress =_TRUE;
			pBtMgnt->BTCurrentConnectType=BT_DISCONNECT;
			if (!pBtMgnt->BtOperationOn)
			{
#if (SENDTXMEHTOD == 0)
				PlatformSetTimer(padapter, &pBTInfo->BTHCISendAclDataTimer, 1);
#endif
#if (RTS_CTS_NO_LEN_LIMIT == 1)
				rtw_write32(padapter, 0x4c8, 0xc140400);
#endif
			}
			pBtMgnt->CurrentBTConnectionCnt++;
			RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], CurrentBTConnectionCnt = %d\n",
				pBtMgnt->CurrentBTConnectionCnt));
			pBtMgnt->BtOperationOn = _TRUE;
			RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], Bt Operation ON!! CurrentConnectEntryNum = %d\n",
				pBtMgnt->CurrentConnectEntryNum));

			if (pBtMgnt->bBTConnectInProgress)
			{
				bthci_EventPhysicalLinkComplete(padapter, HCI_STATUS_CONTROLLER_BUSY, INVALID_ENTRY_NUM, pBtMgnt->BtCurrentPhyLinkhandle);
				bthci_RemoveEntryByEntryNum(padapter, EntryNum);
				return;
			}

			if (StateCmd == STATE_CMD_CREATE_PHY_LINK)
			{
				pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_CREATOR;
			}
			else
			{
				pBTInfo->BtAsocEntry[EntryNum].AMPRole = AMP_BTAP_JOINER;
			}

			// 1. MAC not yet in selected channel
			while (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR) == _TRUE)
			{
				RTPRINT(FIOCTL, IOCTL_STATE, ("Scan/Roaming/Wifi Link is in Progress, wait 200 ms\n"));
				rtw_mdelay_os(200);
			}
			// 2. MAC already in selected channel
			{
				RTPRINT(FIOCTL, IOCTL_STATE, ("Channel is Ready\n"));
				PlatformSetTimer(padapter, &pBTInfo->BTHCIJoinTimeoutTimer, pBtHciInfo->ConnAcceptTimeout);

				pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent = _TRUE;
			}
			break;
		}

		case STATE_CMD_DISCONNECT_PHY_LINK:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_DISCONNECT_PHY_LINK\n"));

			PlatformCancelTimer(padapter,&pBTInfo->BTHCIJoinTimeoutTimer);

			bthci_EventDisconnectPhyLinkComplete(padapter,
			HCI_STATUS_SUCCESS,
			pBTInfo->BtAsocEntry[EntryNum].PhyLinkDisconnectReason,
			EntryNum);

			if (pBTInfo->BtAsocEntry[EntryNum].bNeedPhysLinkCompleteEvent)
			{
				bthci_EventPhysicalLinkComplete(padapter,
					HCI_STATUS_UNKNOW_CONNECT_ID,
					EntryNum, INVALID_PL_HANDLE);
			}

			if (pBtMgnt->bBTConnectInProgress)
			{
				pBtMgnt->bBTConnectInProgress = _FALSE;
				RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
			}
			BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTED, STATE_CMD_ENTER_STATE, EntryNum);
			bthci_RemoveEntryByEntryNum(padapter,EntryNum);
			break;
		}

		case STATE_CMD_ENTER_STATE:
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("STATE_CMD_ENTER_STATE\n"));
			break;
		}

		default:
			RTPRINT(FIOCTL, IOCTL_STATE, ("State command(%d) is Wrong !!!\n", StateCmd));
			break;
	}
}

static void
bthci_UseFakeData(struct rtw_adapter *padapter, PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	if (pHciCmd->OGF == OGF_LINK_CONTROL_COMMANDS && pHciCmd->OCF == HCI_CREATE_LOGICAL_LINK)
	{
		PHCI_FLOW_SPEC	pTxFlowSpec = (PHCI_FLOW_SPEC)&pHciCmd->Data[1];
		PHCI_FLOW_SPEC	pRxFlowSpec = (PHCI_FLOW_SPEC)&pHciCmd->Data[17];
		bthci_SelectFlowType(padapter, BT_TX_BE_FS, BT_RX_BE_FS, pTxFlowSpec, pRxFlowSpec);
		//bthci_SelectFlowType(padapter, BT_TX_be_FS, BT_RX_GU_FS, pTxFlowSpec, pRxFlowSpec);
	}
	else if (pHciCmd->OGF == OGF_LINK_CONTROL_COMMANDS && pHciCmd->OCF == HCI_FLOW_SPEC_MODIFY)
	{
		PHCI_FLOW_SPEC	pTxFlowSpec = (PHCI_FLOW_SPEC)&pHciCmd->Data[2];
		PHCI_FLOW_SPEC	pRxFlowSpec = (PHCI_FLOW_SPEC)&pHciCmd->Data[18];
		//bthci_SelectFlowType(padapter, BT_TX_BE_FS, BT_RX_BE_FS, pTxFlowSpec, pRxFlowSpec);
		bthci_SelectFlowType(padapter, BT_TX_BE_AGG_FS, BT_RX_BE_AGG_FS, pTxFlowSpec, pRxFlowSpec);
	}
}

static void bthci_TimerCallbackHCICmd(PRT_TIMER pTimer)
{
#if (BT_THREAD == 0)
//	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer->padapter;
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackHCICmd() ==>\n"));

	schedule_work(&pBTinfo->HCICmdWorkItem);

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackHCICmd() <==\n"));
#endif
}

static void bthci_TimerCallbackSendAclData(PRT_TIMER pTimer)
{
#if (SENDTXMEHTOD == 0)
//	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer->padapter;
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("HCIAclDataTimerCallback() ==>\n"));
	if (padapter->bDriverIsGoingToUnload)
	{
		return;
	}
	schedule_work(&pBTinfo->HCISendACLDataWorkItem);
	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("HCIAclDataTimerCallback() <==\n"));
#endif
}

static void bthci_TimerCallbackDiscardAclData(PRT_TIMER pTimer)
{
//	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer->padapter;
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackDiscardAclData() ==>\n"));

	RTPRINT(FIOCTL, (IOCTL_CALLBACK_FUN|IOCTL_BT_LOGO), ("Flush Timeout ==>\n"));
	if (bthci_DiscardTxPackets(padapter, pBtHciInfo->FLTO_LLH))
	{
		bthci_EventFlushOccurred(padapter, pBtHciInfo->FLTO_LLH);
	}
	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackDiscardAclData() <==\n"));
}

static void bthci_TimerCallbackPsDisable(PRT_TIMER pTimer)
{
//	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer->padapter;
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackPsDisable() ==>\n"));

	schedule_work(&(pBTinfo->BTPsDisableWorkItem));

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackPsDisable() <==\n"));
}

static void bthci_TimerCallbackJoinTimeout(PRT_TIMER pTimer)
{
//	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer->padapter;
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	u8			CurrentEntry = pBtMgnt->CurrentConnectEntryNum;

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackJoinTimeout() ==> Current State %x\n",pBTInfo->BtAsocEntry[CurrentEntry].BtCurrentState));

	if (pBTInfo->BtAsocEntry[CurrentEntry].BtCurrentState == HCI_STATE_STARTING)
	{
		bthci_StateStarting(padapter, STATE_CMD_CONNECT_ACCEPT_TIMEOUT,CurrentEntry);
	}
	else if (pBTInfo->BtAsocEntry[CurrentEntry].BtCurrentState == HCI_STATE_CONNECTING)
	{
		bthci_StateConnecting(padapter, STATE_CMD_CONNECT_ACCEPT_TIMEOUT,CurrentEntry);
	}
	else if (pBTInfo->BtAsocEntry[CurrentEntry].BtCurrentState == HCI_STATE_AUTHENTICATING)
	{
		bthci_StateAuth(padapter, STATE_CMD_CONNECT_ACCEPT_TIMEOUT,CurrentEntry);
	}
	else
	{
		RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackJoinTimeout() <== No Such state!!!\n"));
	}

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackJoinTimeout() <==\n"));
}

static void bthci_TimerCallbackSendTestPacket(PRT_TIMER pTimer)
{
//	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer->padapter;
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;

	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackSendTestPacket() \n"));
	if (pBtHciInfo->bTestIsEnd || !pBtHciInfo->bInTestMode)
	{
		RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackSendTestPacket() <==bTestIsEnd\n"));
		return;
	}

//	BTPKT_SendTestPacket(padapter); // not porting yet
	PlatformSetTimer(padapter, &pBTInfo->BTTestSendPacketTimer, 50);
	RTPRINT(FIOCTL, IOCTL_CALLBACK_FUN, ("bthci_TimerCallbackSendTestPacket() <==\n"));
}

static void bthci_TimerCallbackBTSupervisionPacket(PRT_TIMER pTimer)
{
}

static void bthci_TimerCallbackBTAuthTimeout(PRT_TIMER pTimer)
{
}

static void bthci_TimerCallbackAsocTimeout(PRT_TIMER pTimer)
{
}

static void bthci_TimerCallbackDisconnectPhysicalLink(PRT_TIMER pTimer)
{
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pTimer;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("===>bthci_TimerCallbackDisconnectPhysicalLink\n"));

	if (pBTInfo->BtAsocEntry[pBtMgnt->DisconnectEntryNum].BtCurrentState == HCI_STATE_CONNECTED)
	{
		BTHCI_SM_WITH_INFO(padapter,HCI_STATE_CONNECTED,STATE_CMD_DISCONNECT_PHY_LINK, pBtMgnt->DisconnectEntryNum);
	}

	BTHCI_EventNumOfCompletedDataBlocks(padapter);
	pBtMgnt->DisconnectEntryNum = 0xff;
	RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("<===bthci_TimerCallbackDisconnectPhysicalLink\n"));

}

static u8 bthci_WaitForRfReady(struct rtw_adapter *padapter)
{
	u8 bRet = _FALSE;

	struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;
	rt_rf_power_state			RfState;
	u32						waitcnt = 0;

	while(1)
	{
		RfState = ppwrctrl->rf_pwrstate;

		if ((RfState != rf_on) || (ppwrctrl->bips_processing))
		{
			rtw_mdelay_os(10);
			if (waitcnt++ >= 200)
			{
				bRet = _FALSE;
				break;
			}
		}
		else
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("bthci_WaitForRfReady(), Rf is on, wait %d times\n", waitcnt));
			bRet = _TRUE;
			break;
		}
	}

	return bRet;
}

static void bthci_WorkItemCallbackPsDisable(void *pContext)
{
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pContext;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	u8			CurrentAssocNum;

	for (CurrentAssocNum=0; CurrentAssocNum<MAX_BT_ASOC_ENTRY_NUM; CurrentAssocNum++)
	{
		if (pBTInfo->BtAsocEntry[CurrentAssocNum].bUsed == _TRUE)
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("WorkItemCallbackPsDisable(): Handle Associate Entry %d\n", CurrentAssocNum));

			if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_CREATOR)
			{
//				BTPKT_StartBeacon(padapter, CurrentAssocNum); // not porting yet
				BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_COMPLETE, CurrentAssocNum);
			}
			else if (pBTInfo->BtAsocEntry[CurrentAssocNum].AMPRole == AMP_BTAP_JOINER)
			{
				bthci_WaitForRfReady(padapter);
				bthci_ResponderStartToScan(padapter);
			}
		}
	}
}

static void bthci_WorkItemCallbackHCICmd(void *pContext)
{
	PlatformProcessHCICommands(pContext);
}

static void bthci_WorkItemCallbackSendACLData(void *pContext)
{
#if (SENDTXMEHTOD == 0)
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pContext;
	PlatformTxBTQueuedPackets(padapter);
#endif
}

static void bthci_WorkItemCallbackConnect(void *pContext)
{
	struct rtw_adapter *		padapter = (struct rtw_adapter *)pContext;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

//	BTPKT_JoinerConnectProcess(padapter, pBtMgnt->CurrentConnectEntryNum); // not porting yet
}

static u8 BTHCI_GetConnectEntryNum(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	return bthci_GetCurrentEntryNum(padapter, pBtMgnt->BtCurrentPhyLinkhandle);
}

static u8 BTHCI_GetCurrentEntryNumByMAC(struct rtw_adapter *padapter, u8 *SA)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	u8	i;

	for (i=0; i<MAX_BT_ASOC_ENTRY_NUM; i++)
	{
		if (pBTInfo->BtAsocEntry[i].bUsed == _TRUE)
		{
			if (!memcmp(pBTInfo->BtAsocEntry[i].BTRemoteMACAddr,
				    SA, 6))
			{
				return i;
			}
		}
	}
	return 0xFF;
}

static void BTHCI_StatusWatchdog(struct rtw_adapter *padapter)
{
//	PMGNT_INFO			pMgntInfo = &padapter->MgntInfo;
	struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;
	PBT30Info			pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT			pBtMgnt = &pBTInfo->BtMgnt;
	PBT_TRAFFIC			pBtTraffic = &pBTInfo->BtTraffic;
	u8				bRfOff=_FALSE, bTxBusy = _FALSE, bRxBusy = _FALSE;


	if ((ppwrctrl->rfoff_reason & RF_CHANGE_BY_HW) ||
		(ppwrctrl->rfoff_reason & RF_CHANGE_BY_SW))
		bRfOff = _TRUE;

	if ((check_fwstate(&padapter->mlmepriv, WIFI_REASOC_STATE|WIFI_UNDER_LINKING|WIFI_SITE_MONITOR) == _FALSE) &&
		!bRfOff)
	{
		static u8 BTwaitcnt=0;
		if (pBtMgnt->BTNeedAMPStatusChg)
		{
			BTwaitcnt++;
			if (BTwaitcnt >= 2)
			{
				BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_FULL_CAPACITY_FOR_BT);
				BTwaitcnt = 0;
			}
		}
	}

	RTPRINT(FIOCTL, IOCTL_BT_TP, ("[BT traffic], TxPktCntInPeriod=%d, TxPktLenInPeriod=%"i64fmt"d\n",
		pBtTraffic->Bt30TrafficStatistics.TxPktCntInPeriod,
		pBtTraffic->Bt30TrafficStatistics.TxPktLenInPeriod));
	RTPRINT(FIOCTL, IOCTL_BT_TP, ("[BT traffic], RxPktCntInPeriod=%d, RxPktLenInPeriod=%"i64fmt"d\n",
		pBtTraffic->Bt30TrafficStatistics.RxPktCntInPeriod,
		pBtTraffic->Bt30TrafficStatistics.RxPktLenInPeriod));
	if (pBtTraffic->Bt30TrafficStatistics.TxPktCntInPeriod > 100 ||
		pBtTraffic->Bt30TrafficStatistics.RxPktCntInPeriod > 100 )
	{
		if (pBtTraffic->Bt30TrafficStatistics.RxPktLenInPeriod > pBtTraffic->Bt30TrafficStatistics.TxPktLenInPeriod)
			bRxBusy = _TRUE;
		else if (pBtTraffic->Bt30TrafficStatistics.TxPktLenInPeriod > pBtTraffic->Bt30TrafficStatistics.RxPktLenInPeriod)
			bTxBusy = _TRUE;
	}

	pBtTraffic->Bt30TrafficStatistics.TxPktCntInPeriod = 0;
	pBtTraffic->Bt30TrafficStatistics.RxPktCntInPeriod = 0;
	pBtTraffic->Bt30TrafficStatistics.TxPktLenInPeriod = 0;
	pBtTraffic->Bt30TrafficStatistics.RxPktLenInPeriod = 0;
	pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic = bTxBusy;
	pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic = bRxBusy;
	RTPRINT(FIOCTL, IOCTL_BT_TP, ("[BT traffic], bTxBusyTraffic=%d, bRxBusyTraffic=%d\n",
		pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic,
		pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic));
}

static void
BTHCI_NotifyRFState(struct rtw_adapter *padapter, rt_rf_power_state StateToSet,
		    RT_RF_CHANGE_SOURCE ChangeSource)
{
	struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;
	RT_RF_CHANGE_SOURCE	RfOffReason = ppwrctrl->rfoff_reason;

	RTPRINT(FIOCTL, IOCTL_STATE, ("BTHCI_NotifyRFState(), Old RfOffReason = 0x%x, ChangeSource = 0x%x\n", RfOffReason, ChangeSource));
	if (ChangeSource < RF_CHANGE_BY_HW)
	{
		RTPRINT(FIOCTL, IOCTL_STATE, ("BTHCI_NotifyRFState(), ChangeSource < RF_CHANGE_BY_HW\n"));
		return;
	}

	//
	// When RF is on/off by HW/SW(IPS/LPS not included), we have to notify
	// core stack the AMP_Status
	//

	// We only have to check RF On/Off by HW/SW
	RfOffReason &= (RF_CHANGE_BY_HW|RF_CHANGE_BY_SW);

	switch (StateToSet)
	{
		case rf_on:
			if (RfOffReason)
			{
				//
				// Previously, HW or SW Rf state is OFF, check if it is turned on by HW/SW
				//
				RfOffReason &= ~ChangeSource;
				if (!RfOffReason)
				{
					// Both HW/SW Rf is turned on
					RTPRINT(FIOCTL, IOCTL_STATE, ("BTHCI_NotifyRFState(), Rf is turned On!\n"));
					BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_FULL_CAPACITY_FOR_BT);
				}
			}
			break;

		case rf_off:
			if (!RfOffReason)
			{
				//
				// Previously, both HW/SW Rf state is ON, check if it is turned off by HW/SW
				//
				RTPRINT(FIOCTL, IOCTL_STATE, ("BTHCI_NotifyRFState(), Rf is turned Off!\n"));
				RTPRINT(FIOCTL, IOCTL_STATE, ("[BT AMPStatus], set to invalid in BTHCI_NotifyRFState()\n"));
				BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_NO_CAPACITY_FOR_BT);
			}
			break;

		default:
			RTPRINT(FIOCTL, IOCTL_STATE, ("Unknown case!! \n"));
			break;
	}
}

static void
BTHCI_IndicateAMPStatus(struct rtw_adapter *padapter, u8 JoinAction, u8 channel)
{
//	PMGNT_INFO	pMgntInfo = &(padapter->MgntInfo);
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	u8		bNeedIndicate = _FALSE;

	RTPRINT(FIOCTL, IOCTL_STATE, ("JoinAction=%d, bssDesc->bdDsParms.ChannelNumber=%d\n",
		JoinAction, channel));

	switch (JoinAction)
	{
		case RT_JOIN_INFRA:
		case RT_JOIN_IBSS:
			//
			// When join infra or ibss, check if bt channel is the current channel,
			// if not, we need to indicate AMPStatus=2
			//
			if (channel != pBtMgnt->BTChannel)
				bNeedIndicate = _TRUE;
			break;
		case RT_START_IBSS:
			//
			// when start IBSS, we need to indicate AMPStatus=2 to
			// reset be hw security
			//
			bNeedIndicate = _TRUE;
			break;
		case RT_NO_ACTION:
			break;
		default:
			break;
	}

	if (bNeedIndicate)
	{
		RTPRINT(FIOCTL, IOCTL_STATE, ("BTHCI_IndicateAMPStatus(), BT channel=%d, bssDesc->bdDsParms.ChannelNumber=%d\n",
			pBtMgnt->BTChannel, channel));

		if (pBtMgnt->BtOperationOn)
		{
			RTPRINT(FIOCTL, IOCTL_STATE, ("[BT AMPStatus], set to invalid in JoinRequest()\n"));
			BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_NO_CAPACITY_FOR_BT);
		}
	}
}

void BTHCI_EventParse(struct rtw_adapter *padapter, void *pEvntData, u32 dataLen)
{
}

static u16
BTHCI_GetPhysicalLinkHandle(struct rtw_adapter *padapter, u8 EntryNum)
{
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);
	u16 handle;

	handle = pBTinfo->BtAsocEntry[EntryNum].AmpAsocCmdData.BtPhyLinkhandle;

	return handle;
}

static RT_STATUS
BTHCI_IndicateRxData(struct rtw_adapter *padapter, void *pData,
		     u32 dataLen, u8 EntryNum)
{
	RT_STATUS	rt_status;

	rt_status = PlatformIndicateBTACLData(padapter, pData, dataLen, EntryNum);

	return rt_status;
}

static void BTHCI_InitializeAllTimer(struct rtw_adapter *padapter)
{
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);
	PBT_SECURITY		pBtSec = &pBTinfo->BtSec;

#if (BT_THREAD == 0)
	PlatformInitializeTimer(padapter, &pBTinfo->BTHCICmdTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackHCICmd, NULL, "BTHCICmdTimer");
#endif
#if (SENDTXMEHTOD == 0)
	PlatformInitializeTimer(padapter, &pBTinfo->BTHCISendAclDataTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackSendAclData, NULL, "BTHCISendAclDataTimer");
#endif
	PlatformInitializeTimer(padapter, &pBTinfo->BTHCIDiscardAclDataTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackDiscardAclData, NULL, "BTHCIDiscardAclDataTimer");
	PlatformInitializeTimer(padapter, &pBTinfo->BTHCIJoinTimeoutTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackJoinTimeout, NULL, "BTHCIJoinTimeoutTimer");
	PlatformInitializeTimer(padapter, &pBTinfo->BTTestSendPacketTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackSendTestPacket, NULL, "BTTestSendPacketTimer");

	PlatformInitializeTimer(padapter, &pBTinfo->BTBeaconTimer, (RT_TIMER_CALL_BACK)BTPKT_TimerCallbackBeacon, NULL, "BTBeaconTimer");
	PlatformInitializeTimer(padapter, &pBtSec->BTWPAAuthTimer, (RT_TIMER_CALL_BACK)BTPKT_TimerCallbackWPAAuth, NULL, "BTWPAAuthTimer");
	PlatformInitializeTimer(padapter, &pBTinfo->BTSupervisionPktTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackBTSupervisionPacket, NULL, "BTGeneralPurposeTimer");
	PlatformInitializeTimer(padapter, &pBTinfo->BTDisconnectPhyLinkTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackDisconnectPhysicalLink, NULL, "BTDisconnectPhyLinkTimer");
	PlatformInitializeTimer(padapter, &pBTinfo->BTPsDisableTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackPsDisable, NULL, "BTPsDisableTimer");
	PlatformInitializeTimer(padapter, &pBTinfo->BTAuthTimeoutTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackBTAuthTimeout, NULL, "BTAuthTimeoutTimer");
	PlatformInitializeTimer(padapter, &pBTinfo->BTAsocTimeoutTimer, (RT_TIMER_CALL_BACK)bthci_TimerCallbackAsocTimeout, NULL, "BTAsocTimeoutTimer");
}

static void BTHCI_CancelAllTimer(struct rtw_adapter *padapter)
{
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);
	PBT_SECURITY		pBtSec = &pBTinfo->BtSec;

	// Note: don't cancel BTHCICmdTimer, if you cancel this timer, there will
	// have posibility to cause irp not completed.
#if (SENDTXMEHTOD == 0)
	PlatformCancelTimer(padapter, &pBTinfo->BTHCISendAclDataTimer);
#endif
	PlatformCancelTimer(padapter, &pBTinfo->BTHCIDiscardAclDataTimer);
	PlatformCancelTimer(padapter, &pBTinfo->BTHCIJoinTimeoutTimer);
	PlatformCancelTimer(padapter, &pBTinfo->BTTestSendPacketTimer);

	PlatformCancelTimer(padapter, &pBTinfo->BTBeaconTimer);
	PlatformCancelTimer(padapter, &pBtSec->BTWPAAuthTimer);
	PlatformCancelTimer(padapter, &pBTinfo->BTSupervisionPktTimer);
	PlatformCancelTimer(padapter, &pBTinfo->BTDisconnectPhyLinkTimer);
	PlatformCancelTimer(padapter, &pBTinfo->BTPsDisableTimer);
	PlatformCancelTimer(padapter, &pBTinfo->BTAuthTimeoutTimer);
	PlatformCancelTimer(padapter, &pBTinfo->BTAsocTimeoutTimer);
}

static void BTHCI_ReleaseAllTimer(struct rtw_adapter *padapter)
{
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);
	PBT_SECURITY		pBtSec = &pBTinfo->BtSec;

#if (BT_THREAD == 0)
	PlatformReleaseTimer(padapter, &pBTinfo->BTHCICmdTimer);
#endif
#if (SENDTXMEHTOD == 0)
	PlatformReleaseTimer(padapter, &pBTinfo->BTHCISendAclDataTimer);
#endif
	PlatformReleaseTimer(padapter, &pBTinfo->BTHCIDiscardAclDataTimer);
	PlatformReleaseTimer(padapter, &pBTinfo->BTHCIJoinTimeoutTimer);
	PlatformReleaseTimer(padapter, &pBTinfo->BTTestSendPacketTimer);

	PlatformReleaseTimer(padapter, &pBTinfo->BTBeaconTimer);
	PlatformReleaseTimer(padapter, &pBtSec->BTWPAAuthTimer);
	PlatformReleaseTimer(padapter, &pBTinfo->BTSupervisionPktTimer);
	PlatformReleaseTimer(padapter, &pBTinfo->BTDisconnectPhyLinkTimer);
	PlatformReleaseTimer(padapter, &pBTinfo->BTAuthTimeoutTimer);
	PlatformReleaseTimer(padapter, &pBTinfo->BTAsocTimeoutTimer);
	PlatformReleaseTimer(padapter, &pBTinfo->BTPsDisableTimer);
}

static void BTHCI_InitializeAllWorkItem(struct rtw_adapter *padapter)
{
	PBT30Info		pBTinfo = GET_BT_INFO(padapter);
#if (BT_THREAD == 0)
	INIT_WORK(&(pBTinfo->HCICmdWorkItem),
		  (RT_WORKITEM_CALL_BACK)bthci_WorkItemCallbackHCICmd);
#endif
#if (SENDTXMEHTOD == 0)
	INIT_WORK(&(pBTinfo->HCISendACLDataWorkItem),
		  (RT_WORKITEM_CALL_BACK)bthci_WorkItemCallbackSendACLData);
#endif
	INIT_WORK(&(pBTinfo->BTPsDisableWorkItem),
		  (RT_WORKITEM_CALL_BACK)bthci_WorkItemCallbackPsDisable);

	INIT_WORK(&(pBTinfo->BTConnectWorkItem),
		  (RT_WORKITEM_CALL_BACK)bthci_WorkItemCallbackConnect);
}

static void BTHCI_Reset(struct rtw_adapter *padapter)
{
	bthci_CmdReset(padapter, _FALSE);
}

u8 BTHCI_HsConnectionEstablished(struct rtw_adapter *padapter)
{
	u8			bBtConnectionExist = _FALSE;
	PBT30Info	pBtinfo = GET_BT_INFO(padapter);
	u8 i;

	for (i=0; i<MAX_BT_ASOC_ENTRY_NUM; i++)
	{
		if (pBtinfo->BtAsocEntry[i].b4waySuccess == _TRUE)
		{
			bBtConnectionExist = _TRUE;
			break;
		}
	}

//	RTPRINT(FIOCTL, IOCTL_STATE, (" BTHCI_HsConnectionEstablished(), connection exist = %d\n", bBtConnectionExist));

	return bBtConnectionExist;
}

static u8
BTHCI_CheckProfileExist(struct rtw_adapter *padapter,
			BT_TRAFFIC_MODE_PROFILE Profile)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	u8		IsPRofile = _FALSE;
	u8		i=0;

	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		if (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile == Profile)
		{
			IsPRofile=_TRUE;
			break;
		}
	}

	return IsPRofile;
}

static u8 BTHCI_GetBTCoreSpecByProf(struct rtw_adapter *padapter, u8 profile)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	u8		btSpec = BT_SPEC_1_2;
	u8		i = 0;

	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		if (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile == profile)
		{
			btSpec = pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec;
			break;
		}
	}

	return btSpec;
}

static void BTHCI_GetProfileNameMoto(struct rtw_adapter *padapter)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	u8		i = 0;
	u8		InCommingMode = 0,OutGoingMode = 0,ScoMode = 0;


	ScoMode = pBtMgnt->ExtConfig.NumberOfSCO;

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], NumberOfHandle = %d, NumberOfSCO = %d\n",
		pBtMgnt->ExtConfig.NumberOfHandle, pBtMgnt->ExtConfig.NumberOfSCO));

	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		InCommingMode=pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode;
		OutGoingMode=pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode;

		if (ScoMode)
		{
			pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_SCO;
		}
		else if ((InCommingMode == BT_MOTOR_EXT_BE) && (OutGoingMode == BT_MOTOR_EXT_BE))
		{
			pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_PAN;
		}
		else if ((InCommingMode == BT_MOTOR_EXT_GULB) && (OutGoingMode == BT_MOTOR_EXT_GULB))
		{
			pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_A2DP;
		}
		else if ((InCommingMode == BT_MOTOR_EXT_GUL) && (OutGoingMode == BT_MOTOR_EXT_BE))
		{
			pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_HID;
		}
		else
		{
			pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE;
		}
	}
}

void BTHCI_UpdateBTProfileRTKToMoto(struct rtw_adapter *padapter)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	u8		i = 0;

	pBtMgnt->ExtConfig.NumberOfSCO = 0;

	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = BT_PROFILE_NONE;

		if (pBtMgnt->ExtConfig.linkInfo[i].BTProfile == BT_PROFILE_SCO)
		{
			pBtMgnt->ExtConfig.NumberOfSCO++;
		}

		pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile = pBtMgnt->ExtConfig.linkInfo[i].BTProfile;
		switch (pBtMgnt->ExtConfig.linkInfo[i].TrafficProfile)
		{
			case BT_PROFILE_SCO:
				break;
			case BT_PROFILE_PAN:
				pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_BE;
				pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE;
				break;
			case BT_PROFILE_A2DP:
				pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GULB;
				pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_GULB;
				break;
			case BT_PROFILE_HID:
				pBtMgnt->ExtConfig.linkInfo[i].IncomingTrafficMode = BT_MOTOR_EXT_GUL;
				pBtMgnt->ExtConfig.linkInfo[i].OutgoingTrafficMode = BT_MOTOR_EXT_BE;
				break;
			default:
				break;
		}
	}

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], RTK, NumberOfHandle = %d, NumberOfSCO = %d\n",
		pBtMgnt->ExtConfig.NumberOfHandle, pBtMgnt->ExtConfig.NumberOfSCO));
}

static void BTHCI_GetBTRSSI(struct rtw_adapter *padapter)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	u8		i = 0;

	//return;

	for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
	{
		bthci_EventExtGetBTRSSI(padapter, pBtMgnt->ExtConfig.linkInfo[i].ConnectHandle);
	}
}

void BTHCI_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bEnableWifiScanNotify)
		bthci_EventExtWifiScanNotify(padapter, scanType);
}

void
BTHCI_StateMachine(
	struct rtw_adapter *					padapter,
	u8					StateToEnter,
	HCI_STATE_WITH_CMD		StateCmd,
	u8					EntryNum
	)
{
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;

	if (EntryNum == 0xff)
	{
		RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, error EntryNum=0x%x \n",EntryNum));
		return;
	}
	RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, EntryNum = 0x%x, CurrentState = 0x%x, BtNextState = 0x%x,  StateCmd = 0x%x ,StateToEnter = 0x%x\n",
		EntryNum,pBTInfo->BtAsocEntry[EntryNum].BtCurrentState,pBTInfo->BtAsocEntry[EntryNum].BtNextState,StateCmd,StateToEnter));

	if (pBTInfo->BtAsocEntry[EntryNum].BtNextState & StateToEnter)
	{
		pBTInfo->BtAsocEntry[EntryNum].BtCurrentState = StateToEnter;

		switch (StateToEnter)
		{
			case HCI_STATE_STARTING:
				{
					pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTING;
					bthci_StateStarting(padapter,StateCmd,EntryNum);
					break;
				}
			case HCI_STATE_CONNECTING:
				{
					pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTING | HCI_STATE_DISCONNECTING | HCI_STATE_AUTHENTICATING;
					bthci_StateConnecting(padapter,StateCmd,EntryNum);
					break;
				}

			case HCI_STATE_AUTHENTICATING:
				{
					pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTING | HCI_STATE_CONNECTED;
					bthci_StateAuth(padapter,StateCmd,EntryNum);
					break;
				}

			case HCI_STATE_CONNECTED:
				{
					pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_CONNECTED | HCI_STATE_DISCONNECTING;
					bthci_StateConnected(padapter,StateCmd,EntryNum);
					break;
				}

			case HCI_STATE_DISCONNECTING:
				{
					pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_DISCONNECTING;
					bthci_StateDisconnecting(padapter,StateCmd,EntryNum);
					break;
				}

			case HCI_STATE_DISCONNECTED:
				{
					pBTInfo->BtAsocEntry[EntryNum].BtNextState = HCI_STATE_DISCONNECTED | HCI_STATE_STARTING | HCI_STATE_CONNECTING;
					bthci_StateDisconnected(padapter,StateCmd,EntryNum);
					break;
				}

			default:
				RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Unknown state to enter!!!\n"));
				break;
		}
	}
	else
	{
		RTPRINT(FIOCTL, IOCTL_STATE, (" StateMachine, Wrong state to enter\n"));
	}

	// 20100325 Joseph: Disable/Enable IPS/LPS according to BT status.
	if (!pBtMgnt->bBTConnectInProgress && !pBtMgnt->BtOperationOn)
	{
		RTPRINT(FIOCTL, IOCTL_STATE, ("[BT PS], IPSReturn()\n"));
		IPSReturn(padapter, IPS_DISABLE_BT_ON);
	}
}

void BTHCI_DisconnectPeer(struct rtw_adapter *padapter, u8 EntryNum)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, (" BTHCI_DisconnectPeer()\n"));

	BTHCI_SM_WITH_INFO(padapter,HCI_STATE_DISCONNECTING,STATE_CMD_MAC_CONNECT_CANCEL_INDICATE,EntryNum);

	if (pBTInfo->BtAsocEntry[EntryNum].bUsed)
	{
//		BTPKT_SendDeauthentication(padapter, pBTInfo->BtAsocEntry[EntryNum].BTRemoteMACAddr, unspec_reason); // not porting yet
	}

	if (pBtMgnt->bBTConnectInProgress)
	{
		pBtMgnt->bBTConnectInProgress = _FALSE;
		RTPRINT(FIOCTL, IOCTL_STATE, ("[BT Flag], BT Connect in progress OFF!!\n"));
	}

	bthci_RemoveEntryByEntryNum(padapter,EntryNum);

	if (pBtMgnt->bNeedNotifyAMPNoCap)
	{
		RTPRINT(FIOCTL, IOCTL_STATE, ("[BT AMPStatus], set to invalid in BTHCI_DisconnectPeer()\n"));
		BTHCI_EventAMPStatusChange(padapter, AMP_STATUS_NO_CAPACITY_FOR_BT);
	}
}

void BTHCI_EventNumOfCompletedDataBlocks(struct rtw_adapter *padapter)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_HCI_INFO		pBtHciInfo = &pBTInfo->BtHciInfo;
	u8 localBuf[TmpLocalBufSize] = "";
	u8 *pRetPar, *pTriple;
	u8 len=0, i, j, handleNum=0;
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
	u16 *pu2Temp, *pPackets, *pHandle, *pDblocks;
	u8 sent = 0;

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);

	if (!(pBtHciInfo->BTEventMaskPage2 & EMP2_HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS))
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("[BT event], Num Of Completed DataBlocks, Ignore to send NumOfCompletedDataBlocksEvent due to event mask page 2\n"));
		return;
	}

	// Return parameters starts from here
	pRetPar = &PPacketIrpEvent->Data[0];
	pTriple = &pRetPar[3];
	for (j=0; j<MAX_BT_ASOC_ENTRY_NUM; j++)
	{

		for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
		{
			if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle)
			{
				handleNum++;
				pHandle = (u16*)&pTriple[0];	// Handle[i]
				pPackets = (u16*)&pTriple[2];	// Num_Of_Completed_Packets[i]
				pDblocks = (u16*)&pTriple[4];	// Num_Of_Completed_Blocks[i]
#if (SENDTXMEHTOD == 0 || SENDTXMEHTOD == 2)
				PlatformAcquireSpinLock(padapter, RT_TX_SPINLOCK);
#endif
				*pHandle = pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle;
				*pPackets = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount;
				*pDblocks = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount;
				if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount)
				{
					sent = 1;
					RTPRINT(FIOCTL, IOCTL_BT_EVENT_DETAIL, ("[BT event], Num Of Completed DataBlocks, Handle = 0x%x, Num_Of_Completed_Packets = 0x%x, Num_Of_Completed_Blocks = 0x%x\n",
					*pHandle, *pPackets, *pDblocks));
				}
				pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount = 0;
#if (SENDTXMEHTOD == 0 || SENDTXMEHTOD == 2)
				PlatformReleaseSpinLock(padapter, RT_TX_SPINLOCK);
#endif
				len += 6;
				pTriple += len;
			}
		}
	}

	pRetPar[2] = handleNum;				// Number_of_Handles
	len += 1;
	pu2Temp = (u16*)&pRetPar[0];
	*pu2Temp = BTTotalDataBlockNum;
	len += 2;

	PPacketIrpEvent->EventCode = HCI_EVENT_NUM_OF_COMPLETE_DATA_BLOCKS;
	PPacketIrpEvent->Length = len;
	if (handleNum && sent)
	{
		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
}

static void BTHCI_EventNumOfCompletedPackets(struct rtw_adapter *padapter)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	u8 localBuf[TmpLocalBufSize] = "";
	u8 *pRetPar, *pDouble;
	u8 len=0, i, j, handleNum=0;
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;
	u16 *pPackets, *pHandle;
	u8 sent = 0;

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	// Return parameters starts from here
	pRetPar = &PPacketIrpEvent->Data[0];
	pDouble = &pRetPar[1];
	for (j=0; j<MAX_BT_ASOC_ENTRY_NUM; j++)
	{
		for (i=0; i<MAX_LOGICAL_LINK_NUM; i++)
		{
			if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle)
			{
				handleNum++;
				pHandle = (u16*)&pDouble[0];	// Handle[i]
				pPackets = (u16*)&pDouble[2];	// Num_Of_Completed_Packets[i]
				PlatformAcquireSpinLock(padapter, RT_TX_SPINLOCK);
				*pHandle = pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].BtLogLinkhandle;
				*pPackets = (u16)pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount;
				if (pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount)
					sent = 1;
				pBTInfo->BtAsocEntry[j].LogLinkCmdData[i].TxPacketCount = 0;
				PlatformReleaseSpinLock(padapter, RT_TX_SPINLOCK);
				len += 4;
				pDouble += len;
			}
		}
	}

	pRetPar[0] = handleNum;				// Number_of_Handles
	len += 1;

	PPacketIrpEvent->EventCode = HCI_EVENT_NUMBER_OF_COMPLETE_PACKETS;
	PPacketIrpEvent->Length = len;
	if (handleNum && sent)
	{
		RTPRINT(FIOCTL, IOCTL_BT_EVENT, ("BTHCI_EventNumOfCompletedPackets \n"));
		bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2);
	}
}

void
BTHCI_EventAMPStatusChange(
	struct rtw_adapter *					padapter,
	u8						AMP_Status
	)
{
//	PMGNT_INFO pMgntInfo = &padapter->MgntInfo;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	u8 len = 0;
	u8 localBuf[7] = "";
	u8 *pRetPar;
	PPACKET_IRP_HCIEVENT_DATA PPacketIrpEvent;

	if (AMP_Status==AMP_STATUS_NO_CAPACITY_FOR_BT)
	{
		pBtMgnt->BTNeedAMPStatusChg = _TRUE;
		pBtMgnt->bNeedNotifyAMPNoCap = _FALSE;

		BTHCI_DisconnectAll(padapter);
	}
	else if (AMP_Status == AMP_STATUS_FULL_CAPACITY_FOR_BT)
	{
		pBtMgnt->BTNeedAMPStatusChg = _FALSE;
	}

	PPacketIrpEvent = (PPACKET_IRP_HCIEVENT_DATA)(&localBuf[0]);
	// Return parameters starts from here
	pRetPar = &PPacketIrpEvent->Data[0];

	pRetPar[0] = 0;	// Status
	len += 1;
	pRetPar[1] = AMP_Status;	// AMP_Status
	len += 1;

	PPacketIrpEvent->EventCode = HCI_EVENT_AMP_STATUS_CHANGE;
	PPacketIrpEvent->Length = len;
	if (bthci_IndicateEvent(padapter, PPacketIrpEvent, len+2) == RT_STATUS_SUCCESS)
	{
		RTPRINT(FIOCTL, (IOCTL_BT_EVENT|IOCTL_STATE), ("[BT event], AMP Status Change, AMP_Status = %d\n", AMP_Status));
	}
}

void BTHCI_DisconnectAll(struct rtw_adapter *padapter)
{
	struct rtw_adapter *		pDefaultAdapter = GetDefaultAdapter(padapter);
//	PMGNT_INFO		pMgntInfo = &(pDefaultAdapter->MgntInfo);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);

	u8 i;

	RTPRINT(FIOCTL, IOCTL_STATE, (" DisconnectALL()\n"));

	for (i=0; i<MAX_BT_ASOC_ENTRY_NUM; i++)
	{
		if (pBTInfo->BtAsocEntry[i].b4waySuccess == _TRUE)
		{
			BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTED, STATE_CMD_DISCONNECT_PHY_LINK, i);
		}
		else if (pBTInfo->BtAsocEntry[i].bUsed == _TRUE)
		{
			if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_CONNECTING)
			{
				BTHCI_SM_WITH_INFO(padapter, HCI_STATE_CONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i);
			}
			else if (pBTInfo->BtAsocEntry[i].BtCurrentState == HCI_STATE_DISCONNECTING)
			{
				BTHCI_SM_WITH_INFO(padapter, HCI_STATE_DISCONNECTING, STATE_CMD_MAC_CONNECT_CANCEL_INDICATE, i);
			}
		}
	}
}

HCI_STATUS
BTHCI_HandleHCICMD(
	struct rtw_adapter *					padapter,
	PPACKET_IRP_HCICMD_DATA	pHciCmd
	)
{
	HCI_STATUS	status = HCI_STATUS_SUCCESS;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG		pBtDbg = &pBTInfo->BtDbg;

	RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("\n"));
	RTPRINT(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), ("HCI Command start, OGF=0x%x, OCF=0x%x, Length=0x%x\n",
		pHciCmd->OGF, pHciCmd->OCF, pHciCmd->Length));
	if (pHciCmd->Length)
	{
		RTPRINT_DATA(FIOCTL, (IOCTL_BT_HCICMD_DETAIL|IOCTL_BT_LOGO), "HCI Command, Hex Data :\n",
			&pHciCmd->Data[0], pHciCmd->Length);
	}
	if (pHciCmd->OGF == OGF_EXTENSION)
	{
		if (pHciCmd->OCF == HCI_SET_RSSI_VALUE)
		{
			RTPRINT(FIOCTL, IOCTL_BT_EVENT_PERIODICAL, ("[BT cmd], "));
		}
		else
		{
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT cmd], "));
		}
	}
	else
	{
		RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("[BT cmd], "));
	}

	pBtDbg->dbgHciInfo.hciCmdCnt++;

	switch (pHciCmd->OGF)
	{
		case OGF_LINK_CONTROL_COMMANDS:
			status = bthci_HandleOGFLinkControlCMD(padapter, pHciCmd);
			break;
		case OGF_HOLD_MODE_COMMAND:
			break;
		case OGF_SET_EVENT_MASK_COMMAND:
			status = bthci_HandleOGFSetEventMaskCMD(padapter, pHciCmd);
			break;
		case OGF_INFORMATIONAL_PARAMETERS:
			status = bthci_HandleOGFInformationalParameters(padapter, pHciCmd);
			break;
		case OGF_STATUS_PARAMETERS:
			status = bthci_HandleOGFStatusParameters(padapter, pHciCmd);
			break;
		case OGF_TESTING_COMMANDS:
			status = bthci_HandleOGFTestingCMD(padapter, pHciCmd);
			break;
		case OGF_EXTENSION:
			status = bthci_HandleOGFExtension(padapter,pHciCmd);
			break;
		default:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI Command(), Unknown OGF = 0x%x\n", pHciCmd->OGF));
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD, ("HCI_UNKNOWN_COMMAND\n"));
			status = bthci_UnknownCMD(padapter, pHciCmd);
			break;
	}
	RTPRINT(FIOCTL, IOCTL_BT_HCICMD_DETAIL, ("HCI Command execution end!!\n"));

	return status;
}

static void
BTHCI_SetLinkStatusNotify(struct rtw_adapter *padapter,
			  PPACKET_IRP_HCICMD_DATA pHciCmd)
{
	bthci_CmdLinkStatusNotify(padapter, pHciCmd);
}

// ===== End of sync from SD7 driver COMMOM/bt_hci.c =====
#endif

#ifdef __HALBTC87231ANT_C__ // HAL/BTCoexist/HalBtc87231Ant.c

static const char *const BtStateString[] =
{
	"BT_DISABLED",
	"BT_NO_CONNECTION",
	"BT_CONNECT_IDLE",
	"BT_INQ_OR_PAG",
	"BT_ACL_ONLY_BUSY",
	"BT_SCO_ONLY_BUSY",
	"BT_ACL_SCO_BUSY",
	"BT_ACL_INQ_OR_PAG",
	"BT_STATE_NOT_DEFINED"
};

extern s32 FillH2CCmd(struct rtw_adapter *padapter, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer);

// ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c =====

static void
btdm_SetFw50(struct rtw_adapter *padapter, u8 byte1, u8 byte2, u8 byte3)
{
	u8			H2C_Parameter[3] = {0};

	H2C_Parameter[0] = byte1;
	H2C_Parameter[1] = byte2;
	H2C_Parameter[2] = byte3;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x50=0x%06x\n",
		H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));

	FillH2CCmd(padapter, 0x50, 3, H2C_Parameter);
}

static void btdm_SetFwIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			H2C_Parameter[1] = {0};

	if (bEnable)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Ignore Wlan_Act !!\n"));
		H2C_Parameter[0] |= BIT(0);		// function enable
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT don't ignore Wlan_Act !!\n"));
	}

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25=0x%02x\n",
		H2C_Parameter[0]));

	FillH2CCmd(padapter, BT_IGNORE_WLAN_ACT_EID, 1, H2C_Parameter);
}

static void btdm_NotifyFwScan(struct rtw_adapter *padapter, u8 scanType)
{
	u8			H2C_Parameter[1] = {0};

	if (scanType == _TRUE)
		H2C_Parameter[0] = 0x1;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], Notify FW for wifi scan, write 0x3b=0x%02x\n",
		H2C_Parameter[0]));

	FillH2CCmd(padapter, 0x3b, 1, H2C_Parameter);
}

static void btdm_1AntSetPSMode(struct rtw_adapter *padapter,
			       u8 enable, u8 smartps, u8 mode)
{
	struct pwrctrl_priv *pwrctrl;


	RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current LPS(%s, %d), smartps=%d\n", enable==_TRUE?"ON":"OFF", mode, smartps));

	pwrctrl = &padapter->pwrctrlpriv;

	if (enable == _TRUE) {
		rtw_set_ps_mode(padapter, PS_MODE_MIN, smartps, mode);
	} else {
		rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0);
		LPS_RF_ON_check(padapter, 100);
	}
}

static void btdm_1AntTSFSwitch(struct rtw_adapter *padapter, u8 enable)
{
	u8 oldVal, newVal;


	oldVal = rtw_read8(padapter, 0x550);

	if (enable)
		newVal = oldVal | EN_BCN_FUNCTION;
	else
		newVal = oldVal & ~EN_BCN_FUNCTION;

	if (oldVal != newVal)
		rtw_write8(padapter, 0x550, newVal);
}

static u8 btdm_Is1AntPsTdmaStateChange(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_1ANT	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;


	if ((pBtdm8723->bPrePsTdmaOn != pBtdm8723->bCurPsTdmaOn) ||
		(pBtdm8723->prePsTdma != pBtdm8723->curPsTdma))
	{
		return _TRUE;
	}
	else
	{
		return _FALSE;
	}
}

// Before enter TDMA, make sure Power Saving is enable!
static void
btdm_1AntPsTdma(
	struct rtw_adapter *	padapter,
	u8		bTurnOn,
	u8		type
	)
{
	PHAL_DATA_TYPE		pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_1ANT	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;


//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], TDMA(%s, %d)\n", (bTurnOn? "ON":"OFF"), type));
	pBtdm8723->bCurPsTdmaOn = bTurnOn;
	pBtdm8723->curPsTdma = type;
	if (bTurnOn)
	{
		switch (type)
		{
			case 1:	// A2DP Level-1 or FTP/OPP
			default:
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// wide duration for WiFi
					BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x0, 0x58);
				}
				break;
			case 2:	// A2DP Level-2
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// normal duration for WiFi
					BTDM_SetFw3a(padapter, 0xd3, 0x12, 0x12, 0x0, 0x58);
				}
				break;
			case 3:	// BT FTP/OPP
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// normal duration for WiFi
					BTDM_SetFw3a(padapter, 0xd3, 0x30, 0x03, 0x10, 0x58);

				}
				break;
			case 4:	// for wifi scan & BT is connected
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// protect 3 beacons in 3-beacon period & no Tx pause at BT slot
					BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x0);
				}
				break;
			case 5:	// for WiFi connected-busy & BT is Non-Connected-Idle
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// SCO mode, Ant fixed at WiFi, WLAN_Act toggle
					BTDM_SetFw3a(padapter, 0x61, 0x15, 0x03, 0x31, 0x00);
				}
				break;
			case 9:	// ACL high-retry type - 2
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// narrow duration for WiFi
					BTDM_SetFw3a(padapter, 0xd3, 0xa, 0xa, 0x0, 0x58); //narrow duration for WiFi
				}
				break;
			case 10: // for WiFi connect idle & BT ACL busy or WiFi Connected-Busy & BT is Inquiry
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0x13, 0xa, 0xa, 0x0, 0x40);
				}
				break;
			case 11: // ACL high-retry type - 3
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// narrow duration for WiFi
					BTDM_SetFw3a(padapter, 0xd3, 0x05, 0x05, 0x00, 0x58);
				}
				break;
			case 12: // for WiFi Connected-Busy & BT is Connected-Idle
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// Allow High-Pri BT
					BTDM_SetFw3a(padapter, 0xeb, 0x0a, 0x03, 0x31, 0x18);
				}
				break;
			case 20: // WiFi only busy ,TDMA mode for power saving
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0x13, 0x25, 0x25, 0x00, 0x00);
				}
				break;
			case 27: // WiFi DHCP/Site Survey & BT SCO busy
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x31, 0x98);
				}
				break;
			case 28: // WiFi DHCP/Site Survey & BT idle
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0x69, 0x25, 0x03, 0x31, 0x00);
				}
				break;
			case 29: // WiFi DHCP/Site Survey & BT ACL busy
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0xeb, 0x1a, 0x1a, 0x01, 0x18);
					rtw_write32(padapter, 0x6c0, 0x5afa5afa);
					rtw_write32(padapter, 0x6c4, 0x5afa5afa);
				}
				break;
			case 30: // WiFi idle & BT Inquiry
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0x93, 0x15, 0x03, 0x14, 0x00);
				}
				break;
			case 31:  // BT HID
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x58);
				}
				break;
			case 32:  // BT SCO & Inquiry
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0xab, 0x0a, 0x03, 0x11, 0x98);
				}
				break;
			case 33:  // BT SCO & WiFi site survey
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0xa3, 0x25, 0x03, 0x30, 0x98);
				}
				break;
			case 34:  // BT HID & WiFi site survey
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0xd3, 0x1a, 0x1a, 0x00, 0x18);
				}
				break;
			case 35:  // BT HID & WiFi Connecting
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					BTDM_SetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x00, 0x18);
				}
				break;
		}
	}
	else
	{
		// disable PS-TDMA
		switch (type)
		{
			case 8:
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// Antenna control by PTA, 0x870 = 0x310
					BTDM_SetFw3a(padapter, 0x8, 0x0, 0x0, 0x0, 0x0);
				}
				break;
			case 0:
			default:
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// Antenna control by PTA, 0x870 = 0x310
					BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
				}
				rtw_write16(padapter, 0x860, 0x210); // Switch Antenna to BT
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860=0x210, Switch Antenna to BT\n"));
				break;
			case 9:
				if (btdm_Is1AntPsTdmaStateChange(padapter))
				{
					// Antenna control by PTA, 0x870 = 0x310
					BTDM_SetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
				}
				rtw_write16(padapter, 0x860, 0x110); // Switch Antenna to WiFi
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], 0x860=0x110, Switch Antenna to WiFi\n"));
				break;
		}
	}

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], Current TDMA(%s, %d)\n",
		pBtdm8723->bCurPsTdmaOn?"ON":"OFF", pBtdm8723->curPsTdma));

	// update pre state
	pBtdm8723->bPrePsTdmaOn = pBtdm8723->bCurPsTdmaOn;
	pBtdm8723->prePsTdma = pBtdm8723->curPsTdma;
}

static void
_btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn, u8 smartps,
		    u8 psOption, u8 bTDMAOn, u8 tdmaType)
{
	struct pwrctrl_priv *pwrctrl;
	PHAL_DATA_TYPE pHalData;
	PBTDM_8723A_1ANT pBtdm8723;
	u8 psMode;
	u8 bSwitchPS;


	if ((check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _FALSE) &&
		(get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE))
	{
		btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType);
		return;
	}

#ifdef DIS_PS_RX_BCN
	psOption &= ~BIT(0);
#endif

	RTPRINT(FBT, BT_TRACE,
			("[BTCoex], Set LPS(%s, %d) TDMA(%s, %d)\n",
			 bPSEn==_TRUE?"ON":"OFF", psOption,
			 bTDMAOn==_TRUE?"ON":"OFF", tdmaType));

	pwrctrl = &padapter->pwrctrlpriv;
	pHalData = GET_HAL_DATA(padapter);
	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;

	if (bPSEn == _TRUE)
	{
		if (_TRUE == pBtdm8723->bWiFiHalt) {
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Halt!!\n"));
			return;
		}

		if (_TRUE == pwrctrl->bInSuspend) {
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi in Suspend!!\n"));
			return;
		}

		if (_TRUE == padapter->bDriverStopped) {
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi driver stopped!!\n"));
			return;
		}

		if (_TRUE == padapter->bSurpriseRemoved) {
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], Enable PS Fail, WiFi Surprise Removed!!\n"));
			return;
		}

		psMode = PS_MODE_MIN;
	}
	else
	{
		psMode = PS_MODE_ACTIVE;
		psOption = 0;
	}

	if (psMode != pwrctrl->pwr_mode)
		bSwitchPS = _TRUE;
	else if (psMode != PS_MODE_ACTIVE)
	{
		if (psOption != pwrctrl->bcn_ant_mode)
			bSwitchPS = _TRUE;
		else if (smartps != pwrctrl->smart_ps)
			bSwitchPS = _TRUE;
		else
			bSwitchPS = _FALSE;
	}
	else
		bSwitchPS = _FALSE;

	if (_TRUE == bSwitchPS)
	{
		// disable TDMA
		if (pBtdm8723->bCurPsTdmaOn == _TRUE)
		{
			if (bTDMAOn == _FALSE)
				btdm_1AntPsTdma(padapter, _FALSE, tdmaType);
			else
			{
				if ((BT_IsBtDisabled(padapter) == _TRUE) ||
					(pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_NO_CONNECTION) ||
					(pHalData->bt_coexist.halCoex8723.c2hBtInfo == BT_INFO_STATE_CONNECT_IDLE)
				|| (tdmaType == 29))
					btdm_1AntPsTdma(padapter, _FALSE, 9);
				else
					btdm_1AntPsTdma(padapter, _FALSE, 0);
			}
		}

		// change Power Save State
		btdm_1AntSetPSMode(padapter, bPSEn, smartps, psOption);
	}

	btdm_1AntPsTdma(padapter, bTDMAOn, tdmaType);
}

static void
btdm_1AntSetPSTDMA(struct rtw_adapter *padapter, u8 bPSEn,
		   u8 psOption, u8 bTDMAOn, u8 tdmaType)
{
	_btdm_1AntSetPSTDMA(padapter, bPSEn, 0, psOption, bTDMAOn, tdmaType);
}

static void btdm_1AntWifiParaAdjust(struct rtw_adapter *padapter, u8 bEnable)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_1ANT	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;

	if (bEnable)
	{
//		RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi para adjust enable!!\n"));
		pBtdm8723->curWifiPara = 1;
		if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara)
		{
			BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_LOW_PENALTY);
		}
	}
	else
	{
//		RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi para adjust disable!!\n"));
		pBtdm8723->curWifiPara = 2;
		if (pBtdm8723->preWifiPara != pBtdm8723->curWifiPara)
		{
			BTDM_SetSwPenaltyTxRateAdaptive(padapter, BT_TX_RATE_ADAPTIVE_NORMAL);
		}
	}

//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], preWifiPara = %d, curWifiPara = %d!!\n",
//		pBtdm8723->preWifiPara, pBtdm8723->curWifiPara));
//	pBtdm8723->preWifiPara = pBtdm8723->curWifiPara;
}

static void btdm_1AntPtaParaReload(struct rtw_adapter *padapter)
{
	// PTA parameter
	rtw_write8(padapter, 0x6cc, 0x0);			// 1-Ant coex
	rtw_write32(padapter, 0x6c8, 0xffff);		// wifi break table
	rtw_write32(padapter, 0x6c4, 0x55555555);	// coex table

	// Antenna switch control parameter
	rtw_write32(padapter, 0x858, 0xaaaaaaaa);
	if (IS_8723A_A_CUT(GET_HAL_DATA(padapter)->VersionID))
	{
		rtw_write32(padapter, 0x870, 0x0);	// SPDT(connected with TRSW) control by hardware PTA
		rtw_write8(padapter, 0x40, 0x24);
	}
	else
	{
		rtw_write8(padapter, 0x40, 0x20);
		rtw_write16(padapter, 0x860, 0x210);	// set antenna at bt side if ANTSW is software control
		rtw_write32(padapter, 0x870, 0x300);	// SPDT(connected with TRSW) control by hardware PTA
		rtw_write32(padapter, 0x874, 0x22804000);	// ANTSW keep by GNT_BT
	}

	// coexistence parameters
	rtw_write8(padapter, 0x778, 0x1);	// enable RTK mode PTA

	// BT don't ignore WLAN_Act
	btdm_SetFwIgnoreWlanAct(padapter, _FALSE);
}

/*
 * Return
 *	1: upgrade (add WiFi duration time)
 *	0: keep
 *	-1: downgrade (add BT duration time)
 */
static s8 btdm_1AntTdmaJudgement(struct rtw_adapter *padapter, u8 retry)
{
	PHAL_DATA_TYPE		pHalData;
	PBTDM_8723A_1ANT	pBtdm8723;
	static s8 up = 0, dn = 0, m = 1, n = 3, WaitCount= 0;
	s8 ret;


	pHalData = GET_HAL_DATA(padapter);
	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
	ret = 0;

	if (pBtdm8723->psTdmaMonitorCnt == 0)
	{
		up = 0;
		dn = 0;
		m = 1;
		n = 3;
		WaitCount = 0;
	}
	else
	{
		WaitCount++;
	}

	if (retry == 0)  // no retry in the last 2-second duration
	{
		up++;
		dn--;
		if (dn < 0) dn = 0;

		if (up >= 3*m)
		{
			// retry=0 in consecutive 3m*(2s), add WiFi duration
			ret = 1;

			n = 3;
			up = 0;
			dn = 0;
			WaitCount = 0;
		}
	}
	else if (retry <= 3)  // retry<=3 in the last 2-second duration
	{
		up--;
		dn++;
		if (up < 0) up = 0;

		if (dn == 2)
		{
			// retry<=3 in consecutive 2*(2s), minus WiFi duration (add BT duration)
			ret = -1;

			// record how many time downgrad WiFi duration
			if (WaitCount <= 2)
				m++;
			else
				m = 1;
			// the max number of m is 20
			// the longest time of upgrade WiFi duration is 20*3*2s = 120s
			if (m >= 20) m = 20;

			up = 0;
			dn = 0;
			WaitCount = 0;
		}
	}
	else  // retry count > 3
	{
		// retry>3, minus WiFi duration (add BT duration)
		ret = -1;

		// record how many time downgrad WiFi duration
		if (WaitCount == 1)
			m++;
		else
			m = 1;
		if (m >= 20) m = 20;

		up = 0;
		dn = 0;
		WaitCount = 0;
	}

	return ret;
}

static void btdm_1AntTdmaDurationAdjustForACL(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE		pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_1ANT	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;


//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s\n", __FUNCTION__));
	if (pBtdm8723->psTdmaGlobalCnt != pBtdm8723->psTdmaMonitorCnt)
	{
		pBtdm8723->psTdmaMonitorCnt = 0;
		pBtdm8723->psTdmaGlobalCnt = 0;
	}
	if (pBtdm8723->psTdmaMonitorCnt == 0)
	{
//		RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjACL, first time execute!!\n"));
		btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 2);
		pBtdm8723->psTdmaDuAdjType = 2;
	}
	else
	{
		// Now we only have 4 level Ps Tdma,
		// if that's not the following 4 level(will changed by wifi scan, dhcp...),
		// then we have to adjust it back to the previous record one.
		if ((pBtdm8723->curPsTdma != 1) &&
			(pBtdm8723->curPsTdma != 2) &&
			(pBtdm8723->curPsTdma != 9) &&
			(pBtdm8723->curPsTdma != 11))
		{
//			RTPRINT(FBT, BT_TRACE, ("[BTCoex], tdma adjust type can only be 1/2/9/11 !!!\n"));
//			RTPRINT(FBT, BT_TRACE, ("[BTCoex], the latest adjust type = %d\n", pBtdm8723->psTdmaDuAdjType));

			btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, pBtdm8723->psTdmaDuAdjType);
		}
		else
		{
			s32 judge = 0;

			judge = btdm_1AntTdmaJudgement(padapter, pHalData->bt_coexist.halCoex8723.btRetryCnt);
			if (judge == -1)
			{
//				RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjACL, Upgrade WiFi duration\n"));
				if (pBtdm8723->curPsTdma == 1)
				{
					// Decrease WiFi duration for high BT retry
					if(pHalData->bt_coexist.halCoex8723.btInfoExt){
						pBtdm8723->psTdmaDuAdjType = 9;
//						RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjACL,  limit to type9 \n"));
					}
					else
						pBtdm8723->psTdmaDuAdjType = 2;
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, pBtdm8723->psTdmaDuAdjType);

				}
				else if (pBtdm8723->curPsTdma == 2)
				{
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 9);
					pBtdm8723->psTdmaDuAdjType = 9;
				}
				else if (pBtdm8723->curPsTdma == 9)
				{
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 11);
					pBtdm8723->psTdmaDuAdjType = 11;
				}
			}
			else if (judge == 1)
			{
//				RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjACL, Downgrade WiFi duration!!\n"));

				if (pBtdm8723->curPsTdma == 11)
				{
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 9);
					pBtdm8723->psTdmaDuAdjType = 9;
				}
				else if (pBtdm8723->curPsTdma == 9)
				{
					if (pHalData->bt_coexist.halCoex8723.btInfoExt){
						pBtdm8723->psTdmaDuAdjType = 9;
//						RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjACL,  limit to type9 \n"));
					}
					else
						pBtdm8723->psTdmaDuAdjType = 2;
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, pBtdm8723->psTdmaDuAdjType);
				}
				else if (pBtdm8723->curPsTdma == 2)
				{
					if (pHalData->bt_coexist.halCoex8723.btInfoExt){
						pBtdm8723->psTdmaDuAdjType = 9;
//						RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjACL,  limit to type9 \n"));
					}
					else
						pBtdm8723->psTdmaDuAdjType = 1;
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, pBtdm8723->psTdmaDuAdjType);
				}
			}
			else
			{
//				RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjACL, no need to change\n"));
			}
		}

		RTPRINT(FBT, BT_TRACE, ("[BTCoex], ACL current TDMA(%s, %d)\n",
			(pBtdm8723->bCurPsTdmaOn? "ON":"OFF"), pBtdm8723->curPsTdma));
	}

	pBtdm8723->psTdmaMonitorCnt++;
}

static u8 btdm_1AntAdjustbyWiFiRSSI(u8 RSSI_Now, u8 RSSI_Last, u8 RSSI_Th)
{
	u8 type;

	if (RSSI_Now>RSSI_Last)
	{
		if (RSSI_Now > (RSSI_Th + 5))
			type = 26;
		else
			type = 25;
	}
	else
	{
		if (RSSI_Now > RSSI_Th)
			type = 26;
		else
			type = 25;
	}

	return type;
}

static void btdm_1AntTdmaDurationAdjustForSCO(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData;
	PBTDM_8723A_1ANT pBtdm8723;
	PDM_ODM_T podm;
	pDIG_T pDigTable;
	u8 RSSITh_WiFi, RSSITh12_BT, RSSITh23_BT;
	u8 Type, RSSIOffset;
	u8 RSSI_WiFi_Now, RSSI_BT_Now;


//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s\n", __FUNCTION__));
	pHalData = GET_HAL_DATA(padapter);
	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
	podm = &pHalData->odmpriv;
	pDigTable = &podm->DM_DigTable;
	RSSITh_WiFi = 47;
	RSSITh12_BT = 36;
	RSSITh23_BT = 30;
	RSSIOffset = 22;
	RSSI_WiFi_Now = pDigTable->Rssi_val_min;
	RSSI_BT_Now = pHalData->bt_coexist.halCoex8723.btRssi;

	if (pBtdm8723->psTdmaGlobalCnt != pBtdm8723->psTdmaMonitorCntForSCO)
	{
		pBtdm8723->psTdmaMonitorCntForSCO = 0;
		pBtdm8723->psTdmaGlobalCnt = 0;
	}

	if (pBtdm8723->psTdmaMonitorCntForSCO == 0)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjSCO, first time execute!!\n"));
		pBtdm8723->RSSI_WiFi_Last = 0;
		pBtdm8723->RSSI_BT_Last = 0;
	}
	else
	{
		if ((pBtdm8723->curPsTdma != 23) &&
				(pBtdm8723->curPsTdma != 24) &&
				(pBtdm8723->curPsTdma != 25) &&
				(pBtdm8723->curPsTdma != 26))
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjSCO, tdma adjust type can only be 23/24/25/26 !!!\n"));
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjSCO, the latest adjust type=%d\n", pBtdm8723->psTdmaDuAdjTypeForSCO));

			Type = pBtdm8723->psTdmaDuAdjTypeForSCO;

			goto _exit_1AntTdmaDurationAdjustForSCO;
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntTdmaAdjSCO, pre curPsTdma=%d\n", pBtdm8723->curPsTdma));
		}
	}

	BTDM_1AntSignalCompensation(padapter, &RSSI_WiFi_Now, &RSSI_BT_Now);

	if (!BTDM_IsWifiBusy(padapter)) // WiFi LPS
	{
		//Type = btdm_1AntAdjustbyWiFiRSSI(RSSI_WiFi_Now, pBtdm8723->RSSI_WiFi_Last, RSSITh_WiFi);
		if (Type == 26)
		{
		if(RSSI_BT_Now >=  RSSITh12_BT + 4)
			Type = 23;
		else
			Type = 26;
		}
		else
		{
		if (RSSI_BT_Now >=  RSSITh12_BT)
			Type = 23;
		else
			Type = 26;
		}

	}
	else // WiFi busy
	{
		//if (RSSI_BT_Now > pBtdm8723->RSSI_BT_Last)
		if (Type !=23)
		{
			if (RSSI_BT_Now >= RSSITh12_BT + 4)
				Type = 23;
			else if (RSSI_BT_Now >= RSSITh23_BT + 4)
				Type = 24;
			else
				Type = btdm_1AntAdjustbyWiFiRSSI(RSSI_WiFi_Now, pBtdm8723->RSSI_WiFi_Last, RSSITh_WiFi);
		}
		else
		{
			if (RSSI_BT_Now >= RSSITh12_BT)
				Type = 23;
			else if  (RSSI_BT_Now >= RSSITh23_BT)
				Type = 24;
			else
				Type = btdm_1AntAdjustbyWiFiRSSI(RSSI_WiFi_Now, pBtdm8723->RSSI_WiFi_Last, RSSITh_WiFi);
		}
	}

_exit_1AntTdmaDurationAdjustForSCO:

	pBtdm8723->RSSI_WiFi_Last = RSSI_WiFi_Now;
	pBtdm8723->RSSI_BT_Last = RSSI_BT_Now;

	if (Type != pBtdm8723->curPsTdma)
		btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, Type);

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO current TDMA(ON, %d), RSSI_WiFi=%d, RSSI_BT=%d\n",
			Type, RSSI_WiFi_Now, RSSI_BT_Now));

	pBtdm8723->psTdmaDuAdjTypeForSCO = Type;

	pBtdm8723->psTdmaMonitorCntForSCO++;
}

static void btdm_1AntCoexProcessForWifiConnect(struct rtw_adapter *padapter)
{
	struct mlme_priv *pmlmepriv;
	PHAL_DATA_TYPE pHalData;
	PBT_COEXIST_8723A pBtCoex;
	PBTDM_8723A_1ANT pBtdm8723;
	u8 BtState;


//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntCoexProcessForWifiConnect!!\n"));

	pmlmepriv = &padapter->mlmepriv;
	pHalData = GET_HAL_DATA(padapter);
	pBtCoex = &pHalData->bt_coexist.halCoex8723;
	pBtdm8723 = &pBtCoex->btdm1Ant;
	BtState = pBtCoex->c2hBtInfo;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], WiFi is %s\n", BTDM_IsWifiBusy(padapter)?"Busy":"IDLE"));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is %s\n", BtStateString[BtState]));

	padapter->pwrctrlpriv.btcoex_rfon = _FALSE;

	if ((!BTDM_IsWifiBusy(padapter)) &&(check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) != _TRUE)&&
		((BtState == BT_INFO_STATE_NO_CONNECTION) || (BtState == BT_INFO_STATE_CONNECT_IDLE)))
	{
		switch (BtState)
		{
			case BT_INFO_STATE_NO_CONNECTION:
				_btdm_1AntSetPSTDMA(padapter, _TRUE, 2, 0x26, _FALSE, 9);
				break;
			case BT_INFO_STATE_CONNECT_IDLE:
				_btdm_1AntSetPSTDMA(padapter, _TRUE, 2, 0x26, _FALSE, 0);
				break;
		}
	}
	else
	{
#ifdef BTCOEX_DECREASE_WIFI_POWER
		u8 val8;

		val8 = rtw_read8(padapter, 0x883);
		val8 &= 0x07;
		if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
			(BtState == BT_INFO_STATE_ACL_SCO_BUSY))
		{
			if (BTDM_IsHT40(padapter) == _TRUE)
				val8 |= 0x80; //0x880[31:27] = 10000;
			else
				val8 |= 0x60; //0x880[31:27] = 01100;
		}
		else
		{
			val8 |= 0xC0; // 0x880[31:27] = 11000;
		}
		rtw_write8(padapter, 0x883, val8);
#endif // BTCOEX_DECREASE_WIFI_POWER

		switch (BtState)
		{
			case BT_INFO_STATE_NO_CONNECTION:
			case BT_INFO_STATE_CONNECT_IDLE:
				// WiFi is Busy
				btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 5);
				rtw_write32(padapter, 0x6c0, 0x5a5a5a5a);
				rtw_write32(padapter, 0x6c4, 0x5a5a5a5a);
				break;
			case BT_INFO_STATE_ACL_INQ_OR_PAG:
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is BT_INFO_STATE_ACL_INQ_OR_PAG\n"));
			case BT_INFO_STATE_INQ_OR_PAG:
				padapter->pwrctrlpriv.btcoex_rfon = _TRUE;
				btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 30);
				break;
			case BT_INFO_STATE_SCO_ONLY_BUSY:
			case BT_INFO_STATE_ACL_SCO_BUSY:
				if (_TRUE == pBtCoex->bC2hBtInquiryPage)
					btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 32);
				else
				{
#ifdef BTCOEX_CMCC_TEST
					btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 23);
#else // !BTCOEX_CMCC_TEST
					btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 8);
					rtw_write32(padapter, 0x6c0, 0x5a5a5a5a);
					rtw_write32(padapter, 0x6c4, 0x5a5a5a5a);
#endif // !BTCOEX_CMCC_TEST
				}
				break;
			case BT_INFO_STATE_ACL_ONLY_BUSY:
				padapter->pwrctrlpriv.btcoex_rfon = _TRUE;
				if (pBtCoex->c2hBtProfile == BT_INFO_HID)
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is HID\n"));
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 31);
				}
				else if (pBtCoex->c2hBtProfile == BT_INFO_FTP)
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is FTP/OPP\n"));
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 3);
				}
				else if (pBtCoex->c2hBtProfile == (BT_INFO_A2DP|BT_INFO_FTP))
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is A2DP_FTP\n"));
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 11);
				}
				else
				{
					if (pBtCoex->c2hBtProfile == BT_INFO_A2DP)
					{
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is A2DP\n"));
					}
					else
					{
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT PROFILE is UNKNOWN(0x%02X)! Use A2DP Profile\n", pBtCoex->c2hBtProfile));
					}
					btdm_1AntTdmaDurationAdjustForACL(padapter);
				}
				break;
		}
	}

	pBtdm8723->psTdmaGlobalCnt++;
}

static void btdm_1AntUpdateHalRAMask(struct rtw_adapter *padapter, u32 mac_id, u32 filter)
{
	u8 init_rate = 0;
	u8 raid;
	u32 mask;
	u8 shortGIrate = _FALSE;
	int	supportRateNum = 0;
	struct sta_info	*psta;
	PHAL_DATA_TYPE pHalData;
	struct dm_priv *pdmpriv;
	struct mlme_ext_priv *pmlmeext;
	struct mlme_ext_info *pmlmeinfo;
	WLAN_BSSID_EX *cur_network;


	RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID=%d, filter=0x%08x!!\n", __FUNCTION__, mac_id, filter));

	pHalData = GET_HAL_DATA(padapter);
	pdmpriv = &pHalData->dmpriv;
	pmlmeext = &padapter->mlmeextpriv;
	pmlmeinfo = &pmlmeext->mlmext_info;
	cur_network = &pmlmeinfo->network;

	if (mac_id >= NUM_STA) //CAM_SIZE
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, MACID=%d illegal!!\n", __FUNCTION__, mac_id));
		return;
	}

	psta = pmlmeinfo->FW_sta_info[mac_id].psta;
	if (psta == NULL)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s, Can't find station!!\n", __FUNCTION__));
		return;
	}

	raid = psta->raid;

	switch (mac_id)
	{
		case 0:// for infra mode
			supportRateNum = rtw_get_rateset_len(cur_network->SupportedRates);
			mask = update_supported_rate(cur_network->SupportedRates, supportRateNum);
			mask |= (pmlmeinfo->HT_enable) ? update_MSC_rate(&(pmlmeinfo->HT_caps)):0;
			if (support_short_GI(padapter, &(pmlmeinfo->HT_caps)))
			{
				shortGIrate = _TRUE;
			}
			break;

		case 1://for broadcast/multicast
			supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
			mask = update_basic_rate(cur_network->SupportedRates, supportRateNum);
			break;

		default: //for each sta in IBSS
			supportRateNum = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[mac_id].SupportedRates);
			mask = update_supported_rate(cur_network->SupportedRates, supportRateNum);
			break;
	}
	mask |= ((raid<<28)&0xf0000000);
	mask &= 0xffffffff;
	mask &= ~filter;
	init_rate = get_highest_rate_idx(mask)&0x3f;

	if (pHalData->fw_ractrl == _TRUE)
	{
		u8 arg = 0;

		arg = mac_id&0x1f;//MACID
		arg |= BIT(7);
		if (_TRUE == shortGIrate)
			arg |= BIT(5);

		RTPRINT(FBT, BT_TRACE, ("[BTCoex], Update FW RAID entry, MASK=0x%08x, arg=0x%02x\n", mask, arg));

		rtl8192c_set_raid_cmd(padapter, mask, arg);
	}
	else
	{
		if (_TRUE == shortGIrate)
			init_rate |= BIT(6);

		rtw_write8(padapter, (REG_INIDATA_RATE_SEL+mac_id), init_rate);
	}

	psta->init_rate = init_rate;
	pdmpriv->INIDATA_RATE[mac_id] = init_rate;
}

static void btdm_1AntUpdateHalRAMaskForSCO(struct rtw_adapter *padapter, u8 forceUpdate)
{
	PBTDM_8723A_1ANT pBtdm8723;
	struct sta_priv *pstapriv;
	WLAN_BSSID_EX *cur_network;
	struct sta_info *psta;
	u32 macid;
	u32 filter = 0;


	pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant;

	if ((pBtdm8723->bRAChanged == _TRUE) && (forceUpdate == _FALSE))
		return;

	pstapriv = &padapter->stapriv;
	cur_network = &padapter->mlmeextpriv.mlmext_info.network;
	psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
	macid = psta->mac_id;

	filter |= BIT(_1M_RATE_);
	filter |= BIT(_2M_RATE_);
	filter |= BIT(_5M_RATE_);
	filter |= BIT(_11M_RATE_);
	filter |= BIT(_6M_RATE_);
	filter |= BIT(_9M_RATE_);

	btdm_1AntUpdateHalRAMask(padapter, macid, filter);

	pBtdm8723->bRAChanged = _TRUE;
}

static void btdm_1AntRecoverHalRAMask(struct rtw_adapter *padapter)
{
	PBTDM_8723A_1ANT pBtdm8723;
	struct sta_priv *pstapriv;
	WLAN_BSSID_EX *cur_network;
	struct sta_info *psta;
	u32 macid;


	pBtdm8723 = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant;

	if (pBtdm8723->bRAChanged == _FALSE)
		return;

	pstapriv = &padapter->stapriv;
	cur_network = &padapter->mlmeextpriv.mlmext_info.network;
	psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);

	Update_RA_Entry(padapter, psta);

	pBtdm8723->bRAChanged = _FALSE;
}

static void
btdm_1AntBTStateChangeHandler(struct rtw_adapter *padapter,
			      BT_STATE_1ANT oldState, BT_STATE_1ANT newState)
{
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT state change, %s => %s\n", BtStateString[oldState], BtStateString[newState]));

	// BT default ignore wlan active,
	// WiFi MUST disable this when BT is enable
	if (newState > BT_INFO_STATE_DISABLED)
	{
		btdm_SetFwIgnoreWlanAct(padapter, _FALSE);
	}

	if ((check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE) &&
		(BTDM_IsWifiConnectionExist(padapter) == _TRUE))
	{
		if ((newState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
			(newState == BT_INFO_STATE_ACL_SCO_BUSY))
		{
			btdm_1AntUpdateHalRAMaskForSCO(padapter, _FALSE);
		}
		else
		{
			// Recover original RA setting
			btdm_1AntRecoverHalRAMask(padapter);
		}
	}
	else
	{
		GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bRAChanged = _FALSE;
	}

	if (oldState == newState)
		return;

	if (oldState == BT_INFO_STATE_ACL_ONLY_BUSY)
	{
		PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
		pHalData->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCnt = 0;
		pHalData->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0;
	}

	if ((oldState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
		(oldState == BT_INFO_STATE_ACL_SCO_BUSY))
	{
		PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
		pHalData->bt_coexist.halCoex8723.btdm1Ant.psTdmaMonitorCntForSCO = 0;
	}

	// Active 2Ant mechanism when BT Connected
	if ((oldState == BT_INFO_STATE_DISABLED) ||
		(oldState == BT_INFO_STATE_NO_CONNECTION))
	{
		if ((newState != BT_INFO_STATE_DISABLED) &&
			(newState != BT_INFO_STATE_NO_CONNECTION))
		{
			BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_SHRINK);
			BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
		}
	}
	else
	{
		if ((newState == BT_INFO_STATE_DISABLED) ||
			(newState == BT_INFO_STATE_NO_CONNECTION))
		{
			BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_RESUME);
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
		}
	}
}

static void btdm_1AntBtCoexistHandler(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE		pHalData;
	PBT_COEXIST_8723A	pBtCoex8723;
	PBTDM_8723A_1ANT	pBtdm8723;
	u8			u1tmp;


	pHalData = GET_HAL_DATA(padapter);
	pBtCoex8723 = &pHalData->bt_coexist.halCoex8723;
	pBtdm8723 = &pBtCoex8723->btdm1Ant;
	padapter->pwrctrlpriv.btcoex_rfon = _FALSE;
	if (BT_IsBtDisabled(padapter) == _TRUE)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is disabled\n"));

		if (BTDM_IsWifiConnectionExist(padapter) == _TRUE)
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is connected\n"));

			if (BTDM_IsWifiBusy(padapter) == _TRUE)
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Wifi is busy\n"));
				btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 9);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Wifi is idle\n"));
				_btdm_1AntSetPSTDMA(padapter, _TRUE, 2, 1, _FALSE, 9);
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is disconnected\n"));

			btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 9);
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT is enabled\n"));

		if (BTDM_IsWifiConnectionExist(padapter) == _TRUE)
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is connected\n"));

			btdm_1AntWifiParaAdjust(padapter, _TRUE);
			btdm_1AntCoexProcessForWifiConnect(padapter);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is disconnected\n"));

			// Antenna switch at BT side(0x870 = 0x300, 0x860 = 0x210) after PSTDMA off
			btdm_1AntWifiParaAdjust(padapter, _FALSE);
			btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 0);
		}
	}

	btdm_1AntBTStateChangeHandler(padapter, pBtCoex8723->prec2hBtInfo, pBtCoex8723->c2hBtInfo);
	pBtCoex8723->prec2hBtInfo = pBtCoex8723->c2hBtInfo;
}

void BTDM_1AntSignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt)
{
	PHAL_DATA_TYPE pHalData;
	PBTDM_8723A_1ANT pBtdm8723;
	u8 RSSI_WiFi_Cmpnstn, RSSI_BT_Cmpnstn;


//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s\n", __FUNCTION__));
	pHalData = GET_HAL_DATA(padapter);
	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;
	RSSI_WiFi_Cmpnstn = 0;
	RSSI_BT_Cmpnstn = 0;

	switch (pBtdm8723->curPsTdma)
	{
		case 1: // WiFi 52ms
			RSSI_WiFi_Cmpnstn = 11; // 22*0.48
			break;
		case 2: // WiFi 36ms
			RSSI_WiFi_Cmpnstn = 14; // 22*0.64
			break;
		case 9: // WiFi 20ms
			RSSI_WiFi_Cmpnstn = 18; // 22*0.80
			break;
		case 11: // WiFi 10ms
			RSSI_WiFi_Cmpnstn = 20; // 22*0.90
			break;
		case 4: // WiFi 21ms
			RSSI_WiFi_Cmpnstn = 17; // 22*0.79
			break;
		case 16: // WiFi 24ms
			RSSI_WiFi_Cmpnstn = 18; // 22*0.76
			break;
		case 18: // WiFi 37ms
			RSSI_WiFi_Cmpnstn = 14; // 22*0.64
			break;
		case 23: //Level-1, Antenna switch to BT at all time
		case 24: //Level-2, Antenna switch to BT at all time
		case 25: //Level-3a, Antenna switch to BT at all time
		case 26: //Level-3b, Antenna switch to BT at all time
		case 27: //Level-3b, Antenna switch to BT at all time
		case 33: //BT SCO & WiFi site survey
			RSSI_WiFi_Cmpnstn = 22;
			break;
		default:
			break;
	}

	if (rssi_wifi && RSSI_WiFi_Cmpnstn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntSgnlCmpnstn, case %d, WiFiCmpnstn=%d(%d => %d)\n",
				pBtdm8723->curPsTdma, RSSI_WiFi_Cmpnstn, *rssi_wifi, *rssi_wifi+RSSI_WiFi_Cmpnstn));
		*rssi_wifi += RSSI_WiFi_Cmpnstn;
	}

	if (rssi_bt && RSSI_BT_Cmpnstn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1AntSgnlCmpnstn, case %d, BTCmpnstn=%d(%d => %d)\n",
				pBtdm8723->curPsTdma, RSSI_BT_Cmpnstn, *rssi_bt, *rssi_bt+RSSI_BT_Cmpnstn));
		*rssi_bt += RSSI_BT_Cmpnstn;
	}
}

static void
BTDM_1AntSetWifiRssiThresh(struct rtw_adapter *padapter, u8 rssiThresh)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_1ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm1Ant;

	pBtdm8723->wifiRssiThresh = rssiThresh;
	DBG_8723A("cosa set rssi thresh = %d\n", pBtdm8723->wifiRssiThresh);
}

static void BTDM_1AntParaInit(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData;
	PBT_COEXIST_8723A pBtCoex;
	PBTDM_8723A_1ANT pBtdm8723;


	pHalData = GET_HAL_DATA(padapter);
	pBtCoex = &pHalData->bt_coexist.halCoex8723;
	pBtdm8723 = &pBtCoex->btdm1Ant;

	// Enable counter statistics
	rtw_write8(padapter, 0x76e, 0x4);
	btdm_1AntPtaParaReload(padapter);

	pBtdm8723->wifiRssiThresh = 48;

	pBtdm8723->bWiFiHalt = _FALSE;
	pBtdm8723->bRAChanged = _FALSE;

	if ((pBtCoex->c2hBtInfo != BT_INFO_STATE_DISABLED) &&
		(pBtCoex->c2hBtInfo != BT_INFO_STATE_NO_CONNECTION))
	{
		BTDM_SetSwRfRxLpfCorner(padapter, BT_RF_RX_LPF_CORNER_SHRINK);
		BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
		BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
	}
}

static void BTDM_1AntForHalt(struct rtw_adapter *padapter)
{
	RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for halt\n"));

	GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = _TRUE;

	btdm_1AntWifiParaAdjust(padapter, _FALSE);

	// don't use btdm_1AntSetPSTDMA() here
	// it will call rtw_set_ps_mode() and request pwrpriv->lock.
	// This will lead to deadlock, if this function is called in IPS
	// Lucas@20130205
	btdm_1AntPsTdma(padapter, _FALSE, 0);

	btdm_SetFwIgnoreWlanAct(padapter, _TRUE);
}

static void BTDM_1AntLpsLeave(struct rtw_adapter *padapter)
{
	RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for LPS Leave\n"));

	// Prevent from entering LPS again
	GET_HAL_DATA(padapter)->bt_coexist.halCoex8723.btdm1Ant.bWiFiHalt = _TRUE;

	btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 8);
//	btdm_1AntPsTdma(padapter, _FALSE, 8);
}

static void BTDM_1AntWifiAssociateNotify(struct rtw_adapter *padapter, u8 type)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);


	RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for associate, type=%d\n", type));

	if (type)
	{
		rtl8723a_CheckAntenna_Selection(padapter);
		if (BT_IsBtDisabled(padapter) == _TRUE)
		{
			btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 9);
		}
		else
		{
			PBT_COEXIST_8723A pBtCoex;
			u8 BtState;

			pBtCoex = &pHalData->bt_coexist.halCoex8723;
			BtState = pBtCoex->c2hBtInfo;

			btdm_1AntTSFSwitch(padapter, _TRUE);

			if ((BtState == BT_INFO_STATE_NO_CONNECTION) ||
				 (BtState == BT_INFO_STATE_CONNECT_IDLE))
			{
				btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 28);
			}
			else if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
					(BtState == BT_INFO_STATE_ACL_SCO_BUSY))
			{
				btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 8);
				rtw_write32(padapter, 0x6c0, 0x5a5a5a5a);
				rtw_write32(padapter, 0x6c4, 0x5a5a5a5a);
			}
			else if ((BtState == BT_INFO_STATE_ACL_ONLY_BUSY) ||
					(BtState == BT_INFO_STATE_ACL_INQ_OR_PAG))
			{
				if (pBtCoex->c2hBtProfile == BT_INFO_HID)
					btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 35);
				else
					btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 29);
			}
		}
	}
	else
	{
		if (BT_IsBtDisabled(padapter) == _FALSE)
		{
			if (BTDM_IsWifiConnectionExist(padapter) == _FALSE)
			{
				btdm_1AntPsTdma(padapter, _FALSE, 0);
				btdm_1AntTSFSwitch(padapter, _FALSE);
			}
		}

		btdm_1AntBtCoexistHandler(padapter);
	}
}

static void
BTDM_1AntMediaStatusNotify(struct rtw_adapter *padapter,
			   RT_MEDIA_STATUS mstatus)
{
	PBT_COEXIST_8723A pBtCoex;


	pBtCoex = &GET_HAL_DATA(padapter)->bt_coexist.halCoex8723;

	RTPRINT(FBT, BT_TRACE, ("\n\n[BTCoex]******************************\n"));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatus, WiFi %s !!\n",
			mstatus==RT_MEDIA_CONNECT?"CONNECT":"DISCONNECT"));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex]******************************\n"));

	if (RT_MEDIA_CONNECT == mstatus)
	{
		if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE)
		{
			if ((pBtCoex->c2hBtInfo == BT_INFO_STATE_SCO_ONLY_BUSY) ||
				(pBtCoex->c2hBtInfo == BT_INFO_STATE_ACL_SCO_BUSY))
			{
				btdm_1AntUpdateHalRAMaskForSCO(padapter, _TRUE);
			}
		}

		padapter->pwrctrlpriv.DelayLPSLastTimeStamp = rtw_get_current_time();
		BTDM_1AntForDhcp(padapter);
	}
	else
	{
		//DBG_8723A("%s rtl8723a_DeinitAntenna_Selection\n",__func__);
		rtl8723a_DeinitAntenna_Selection(padapter);
		btdm_1AntBtCoexistHandler(padapter);
		pBtCoex->btdm1Ant.bRAChanged = _FALSE;
	}
}

void BTDM_1AntForDhcp(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData;
	u8 u1tmp;
	u8 BtState;
	PBT_COEXIST_8723A pBtCoex;
	PBTDM_8723A_1ANT pBtdm8723;


	pHalData = GET_HAL_DATA(padapter);
	pBtCoex = &pHalData->bt_coexist.halCoex8723;
	BtState = pBtCoex->c2hBtInfo;
	pBtdm8723 = &pBtCoex->btdm1Ant;

	RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for DHCP\n"));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, WiFi is %s\n", BTDM_IsWifiBusy(padapter)?"Busy":"IDLE"));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, %s\n", BtStateString[BtState]));

#if 1

	BTDM_1AntWifiAssociateNotify(padapter, _TRUE);

#else

//	rtl8723a_set_lowpwr_lps_cmd(padapter, _FALSE);

	if (BT_IsBtDisabled(padapter) == _TRUE)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for DHCP, BT is disabled\n"));
			btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 9);
	}
	else
	{
		if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
			(BtState == BT_INFO_STATE_ACL_SCO_BUSY))
		{
			if (_TRUE == pBtCoex->bC2hBtInquiryPage)
				btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 32);
			else
				btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 27);
		}
		else if (BtState == BT_INFO_STATE_ACL_ONLY_BUSY)
		{
			padapter->pwrctrlpriv.btcoex_rfon = _TRUE;
			if(padapter->securitypriv.ndisencryptstatus != Ndis802_11EncryptionDisabled)
			{
				btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 18);
				RTPRINT(FBT, BT_TRACE,
						("[BTCoex], 1Ant for DHCP, Encrypted AP, set TDMA(%s, %d)\n",
						pBtdm8723->bCurPsTdmaOn?"ON":"OFF", pBtdm8723->curPsTdma));
			}
			else
			{
				switch (pBtdm8723->curPsTdma)
				{
					case 1:
					case 2:
						RTPRINT(FBT, BT_TRACE,
								("[BTCoex], 1Ant for DHCP, Keep TDMA(%s, %d)\n",
								pBtdm8723->bCurPsTdmaOn?"ON":"OFF", pBtdm8723->curPsTdma));
						break;
					default:
						btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 16);
						break;
				}
			}
		}
		else
		{
			btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 28);
		}
	}
#endif
}

static void BTDM_1AntWifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
{
	PHAL_DATA_TYPE	pHalData;
	u8 u1tmp;
	u8 BtState;
	PBT_COEXIST_8723A pBtCoex;
	PBTDM_8723A_1ANT pBtdm8723;


	pHalData = GET_HAL_DATA(padapter);
	BtState = pHalData->bt_coexist.halCoex8723.c2hBtInfo;
	pBtCoex = &pHalData->bt_coexist.halCoex8723;
	pBtdm8723 = &pBtCoex->btdm1Ant;

	RTPRINT(FBT, BT_TRACE, ("\n[BTCoex], 1Ant for wifi scan=%d!!\n", scanType));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, WiFi is %s\n", BTDM_IsWifiBusy(padapter)?"Busy":"IDLE"));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1Ant for wifi scan, %s\n", BtStateString[BtState]));

	if (scanType)
	{
		rtl8723a_CheckAntenna_Selection(padapter);
		if (BT_IsBtDisabled(padapter) == _TRUE)
		{
			btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _FALSE, 9);
		}
		else if (BTDM_IsWifiConnectionExist(padapter) == _FALSE)
		{
			BTDM_1AntWifiAssociateNotify(padapter, _TRUE);
		}
		else
		{
			if ((BtState == BT_INFO_STATE_SCO_ONLY_BUSY) ||
				(BtState == BT_INFO_STATE_ACL_SCO_BUSY))
			{
				if (_TRUE == pBtCoex->bC2hBtInquiryPage)
					btdm_1AntSetPSTDMA(padapter, _FALSE, 0, _TRUE, 32);
				else
				{
					padapter->pwrctrlpriv.btcoex_rfon = _TRUE;
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 33);
				}
			}
			else if (_TRUE == pBtCoex->bC2hBtInquiryPage)
			{
				padapter->pwrctrlpriv.btcoex_rfon = _TRUE;
				btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 30);
			}
			else if (BtState == BT_INFO_STATE_ACL_ONLY_BUSY)
			{
				padapter->pwrctrlpriv.btcoex_rfon = _TRUE;
				if (pBtCoex->c2hBtProfile == BT_INFO_HID)
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 34);
				else
					btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 4);
			}
			else
			{
				padapter->pwrctrlpriv.btcoex_rfon = _TRUE;
				btdm_1AntSetPSTDMA(padapter, _TRUE, 0, _TRUE, 5);
			}
		}

		btdm_NotifyFwScan(padapter, 1);
	}
	else // WiFi_Finish_Scan
	{
		btdm_NotifyFwScan(padapter, 0);
		btdm_1AntBtCoexistHandler(padapter);
	}
}

static void BTDM_1AntFwC2hBtInfo8723A(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_COEXIST_8723A pBtCoex;
	u8	u1tmp, btState;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtCoex = &pHalData->bt_coexist.halCoex8723;

	u1tmp = pBtCoex->c2hBtInfoOriginal;
	// sco BUSY bit is not used on voice over PCM platform
	btState = u1tmp & 0xF;
	pBtCoex->c2hBtProfile = u1tmp & 0xE0;

	// default set bt to idle state.
	pBtMgnt->ExtConfig.bBTBusy = _FALSE;
	pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;

	// check BIT2 first ==> check if bt is under inquiry or page scan
	if (btState & BIT(2))
	{
		pBtCoex->bC2hBtInquiryPage = _TRUE;
	}
	else
	{
		pBtCoex->bC2hBtInquiryPage = _FALSE;
	}
	btState &= ~BIT(2);

	if (!(btState & BIT(0)))
	{
		pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION;
	}
	else
	{
		if (btState == 0x1)
		{
			pBtCoex->c2hBtInfo = BT_INFO_STATE_CONNECT_IDLE;
		}
		else if (btState == 0x9)
		{
			if(pBtCoex->bC2hBtInquiryPage == _TRUE)
				pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_INQ_OR_PAG;
			else
				pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_ONLY_BUSY;
			pBtMgnt->ExtConfig.bBTBusy = _TRUE;
		}
		else if (btState == 0x3)
		{
			pBtCoex->c2hBtInfo = BT_INFO_STATE_SCO_ONLY_BUSY;
			pBtMgnt->ExtConfig.bBTBusy = _TRUE;
		}
		else if (btState == 0xb)
		{
			pBtCoex->c2hBtInfo = BT_INFO_STATE_ACL_SCO_BUSY;
			pBtMgnt->ExtConfig.bBTBusy = _TRUE;
		}
		else
		{
			pBtCoex->c2hBtInfo = BT_INFO_STATE_MAX;
		}
		if (_TRUE == pBtMgnt->ExtConfig.bBTBusy)
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE;
	}

	if ((BT_INFO_STATE_NO_CONNECTION == pBtCoex->c2hBtInfo) ||
		(BT_INFO_STATE_CONNECT_IDLE == pBtCoex->c2hBtInfo))
	{
		if (pBtCoex->bC2hBtInquiryPage)
			pBtCoex->c2hBtInfo = BT_INFO_STATE_INQ_OR_PAG;
	}

	RTPRINT(FBT, BT_TRACE, ("[BTC2H], %s(%d)\n",
			BtStateString[pBtCoex->c2hBtInfo], pBtCoex->c2hBtInfo));

	if(pBtCoex->c2hBtProfile != BT_INFO_HID)
		pBtCoex->c2hBtProfile &= ~BT_INFO_HID;
}

void BTDM_1AntBtCoexist8723A(struct rtw_adapter *padapter)
{
	struct mlme_priv *pmlmepriv;
	PHAL_DATA_TYPE	pHalData;
	u32 curr_time, delta_time;


	pmlmepriv = &padapter->mlmepriv;
	pHalData = GET_HAL_DATA(padapter);

	if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR) == _TRUE)
	{
		// already done in BTDM_1AntForScan()
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under scan progress!!\n"));
		return;
	}

	if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING) == _TRUE)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under link progress!!\n"));
		return;
	}

	// under DHCP(Special packet)
	curr_time = rtw_get_current_time();
	delta_time = curr_time - padapter->pwrctrlpriv.DelayLPSLastTimeStamp;
	delta_time = rtw_systime_to_ms(delta_time);
	if (delta_time < 500) // 500ms
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], wifi is under DHCP progress(%d ms)!!\n", delta_time));
		return;
	}

	BTDM_CheckWiFiState(padapter);

	btdm_1AntBtCoexistHandler(padapter);
}

// ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87231Ant.c =====
#endif

#ifdef __HALBTC87232ANT_C__ // HAL/BTCoexist/HalBtc87232Ant.c
// ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c =====

//============================================================
// local function proto type if needed
//============================================================
//============================================================
// local function start with btdm_
//============================================================
static u8 btdm_ActionAlgorithm(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
	u8			bScoExist=_FALSE, bBtLinkExist=_FALSE, bBtHsModeExist=_FALSE;
	u8			algorithm=BT_2ANT_COEX_ALGO_UNDEFINED;

	if(pBtMgnt->ExtConfig.NumberOfHandle)
	{
		bBtLinkExist = _TRUE;
	}
	if(pBtMgnt->ExtConfig.NumberOfSCO)
		{
		bScoExist = _TRUE;
		}
	if(BT_HsConnectionEstablished(padapter))
	{
		bBtHsModeExist = _TRUE;
	}

	//======================
	// here we get BT status first
	//======================
	// 1) initialize
	pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE;

	if( (bScoExist) ||(bBtHsModeExist) ||
		(BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID)))
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO or HID or HS exists, set BT non-idle !!!\n"));
		pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
	}
	else
		{
		// A2dp profile
		if( (pBtMgnt->ExtConfig.NumberOfHandle == 1) &&
			(BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) )
		{
			if(BTDM_BtTxRxCounterL(padapter) < 100)
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx < 100, set BT connected-idle!!!\n"));
				pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
		}
	else
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP, low priority tx+rx >= 100, set BT non-idle!!!\n"));
				pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
	}
}
		// Pan profile
		if( (pBtMgnt->ExtConfig.NumberOfHandle == 1) &&
			(BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) )
{
			if(BTDM_BtTxRxCounterL(padapter) < 600)
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority tx+rx < 600, set BT connected-idle!!!\n"));
				pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
}
			else
{
				if(pHalData->bt_coexist.halCoex8723.lowPriorityTx)
				{
					if((pHalData->bt_coexist.halCoex8723.lowPriorityRx /pHalData->bt_coexist.halCoex8723.lowPriorityTx)>9 )
					{
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, low priority rx/tx > 9, set BT connected-idle!!!\n"));
						pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
}
				}
			}
			if(BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus)
{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN, set BT non-idle!!!\n"));
				pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
}
		}
		// Pan+A2dp profile
		if( (pBtMgnt->ExtConfig.NumberOfHandle == 2) &&
			(BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP)) &&
			(BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN)) )
{
			if(BTDM_BtTxRxCounterL(padapter) < 600)
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority tx+rx < 600, set BT connected-idle!!!\n"));
				pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
	}
	else
	{
				if(pHalData->bt_coexist.halCoex8723.lowPriorityTx)
				{
					if((pHalData->bt_coexist.halCoex8723.lowPriorityRx /pHalData->bt_coexist.halCoex8723.lowPriorityTx)>9 )
					{
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, low priority rx/tx > 9, set BT connected-idle!!!\n"));
						pBtdm8723->btStatus = BT_2ANT_BT_STATUS_CONNECTED_IDLE;
	}
}
			}
			if(BT_2ANT_BT_STATUS_CONNECTED_IDLE != pBtdm8723->btStatus)
{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN+A2DP, set BT non-idle!!!\n"));
				pBtdm8723->btStatus = BT_2ANT_BT_STATUS_NON_IDLE;
}
		}
	}
	if(BT_2ANT_BT_STATUS_IDLE != pBtdm8723->btStatus)
{
		pBtMgnt->ExtConfig.bBTBusy = _TRUE;
	}
	else
	{
		pBtMgnt->ExtConfig.bBTBusy = _FALSE;
}
	//======================

	if(!bBtLinkExist)
{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], No profile exists!!!\n"));
		return algorithm;
	}

	if(pBtMgnt->ExtConfig.NumberOfHandle == 1)
	{
		if(bScoExist)
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n"));
			algorithm = BT_2ANT_COEX_ALGO_SCO;
	}
		else
	{
			if(BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID))
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID only\n"));
				algorithm = BT_2ANT_COEX_ALGO_HID;
	}
			else if(BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP only\n"));
				algorithm = BT_2ANT_COEX_ALGO_A2DP;
	}
			else if(BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN))
	{
				if(bBtHsModeExist)
		{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(HS) only\n"));
					algorithm = BT_2ANT_COEX_ALGO_PANHS;
		}
		else
		{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR) only\n"));
					algorithm = BT_2ANT_COEX_ALGO_PANEDR;
		}
	}
			else
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle=%d \n",
					pBtMgnt->ExtConfig.NumberOfHandle));
	}
		}
	}
	else if(pBtMgnt->ExtConfig.NumberOfHandle == 2)
	{
		if(bScoExist)
		{
			if(BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID))
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n"));
				algorithm = BT_2ANT_COEX_ALGO_HID;
	}
			else if(BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n"));
	}
			else if(BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN))
			{
				if(bBtHsModeExist)
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n"));
					algorithm = BT_2ANT_COEX_ALGO_SCO;
}
				else
{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n"));
					algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
				}
			}
			else
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched ACL profile for NumberOfHandle=%d\n",
					pBtMgnt->ExtConfig.NumberOfHandle));
			}
	}
	else
	{
			if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) )
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n"));
				algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
	}
			else if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) )
			{
				if(bBtHsModeExist)
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n"));
					algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
}
				else
{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n"));
					algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
				}
			}
			else if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) )
	{
				if(bBtHsModeExist)
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n"));
					algorithm = BT_2ANT_COEX_ALGO_A2DP;
	}
				else
	{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n"));
					algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP;
	}
}
			else
{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle=%d\n",
					pBtMgnt->ExtConfig.NumberOfHandle));
			}
		}
	}
	else if(pBtMgnt->ExtConfig.NumberOfHandle == 3)
	{
		if(bScoExist)
		{
			if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) )
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP\n"));
		}
			else if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) )
			{
				if(bBtHsModeExist)
		{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(HS)\n"));
					algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
		}
		else
		{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID + PAN(EDR)\n"));
					algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
		}
		}
			else if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) )
			{
				if(bBtHsModeExist)
		{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(HS)\n"));
					algorithm = BT_2ANT_COEX_ALGO_SCO;
		}
				else
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP + PAN(EDR)\n"));

				}
			}
			else
		{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle=%d\n",
					pBtMgnt->ExtConfig.NumberOfHandle));
			}
		}
		else
		{
			if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) )
			{
				if(bBtHsModeExist)
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n"));
					algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANHS;
		}
				else
		{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n"));
					algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
		}
	}
	else
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle=%d\n",
					pBtMgnt->ExtConfig.NumberOfHandle));
	}
		}
	}
	else if(pBtMgnt->ExtConfig.NumberOfHandle >= 3)
	{
		if(bScoExist)
		{
			if( BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) &&
				BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) )
			{
				if(bBtHsModeExist)
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"));

				}
				else
				{
					RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + HID + A2DP + PAN(EDR)\n"));

				}
			}
			else
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO exists but why NO matched profile for NumberOfHandle=%d\n",
					pBtMgnt->ExtConfig.NumberOfHandle));
	}
}
		else
{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! NO matched profile for NumberOfHandle=%d\n",
				pBtMgnt->ExtConfig.NumberOfHandle));
		}
	}

	return algorithm;
}

static u8 btdm_NeedToDecBtPwr(struct rtw_adapter *padapter)
	{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	struct rtw_adapter *pDefaultAdapter = GetDefaultAdapter(padapter);
	u8 bRet = _FALSE;

	if (BT_Operation(padapter)) {
		if (pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB > 47) {
			RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for HS mode!!\n"));
			bRet = _TRUE;
		} else {
			RTPRINT(FBT, BT_TRACE, ("NO Need to decrease bt power for HS mode!!\n"));
		}
	} else {
		if (BTDM_IsWifiConnectionExist(padapter)) {
			RTPRINT(FBT, BT_TRACE, ("Need to decrease bt power for Wifi is connected!!\n"));
			bRet = _TRUE;
		}
	}
	return bRet;
}

static void
btdm_SetCoexTable(struct rtw_adapter *padapter, u32 val0x6c0,
		  u32 val0x6c8, u8 val0x6cc)
{
	RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c0=0x%x\n", val0x6c0));
	rtw_write32(padapter, 0x6c0, val0x6c0);

	RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6c8=0x%x\n", val0x6c8));
	rtw_write32(padapter, 0x6c8, val0x6c8);

	RTPRINT(FBT, BT_TRACE, ("set coex table, set 0x6cc=0x%x\n", val0x6cc));
	rtw_write8(padapter, 0x6cc, val0x6cc);
}


static void
btdm_SetSwFullTimeDacSwing(struct rtw_adapter *	padapter, u8 bSwDacSwingOn,
			   u32 swDacSwingLvl)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if(bSwDacSwingOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing = 0x%x\n", swDacSwingLvl));
		PHY_SetBBReg(padapter, 0x880, 0xff000000, swDacSwingLvl);
		pHalData->bt_coexist.bSWCoexistAllOff = _FALSE;
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], SwDacSwing Off!\n"));
		PHY_SetBBReg(padapter, 0x880, 0xff000000, 0xc0);
	}
}


static void
btdm_SetFwDacSwingLevel(struct rtw_adapter *padapter, u8 dacSwingLvl)
{
	u8			H2C_Parameter[1] ={0};

	H2C_Parameter[0] = dacSwingLvl;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], Set Dac Swing Level=0x%x\n", dacSwingLvl));
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], write 0x29=0x%x\n", H2C_Parameter[0]));

	FillH2CCmd(padapter, 0x29, 1, H2C_Parameter);
}

static void btdm_2AntDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], Dec BT power = %s\n",  ((bDecBtPwr)? "ON":"OFF")));
	pBtdm8723->bCurDecBtPwr = bDecBtPwr;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreDecBtPwr=%d, bCurDecBtPwr=%d\n",
	//	pBtdm8723->bPreDecBtPwr, pBtdm8723->bCurDecBtPwr));

	if (pBtdm8723->bPreDecBtPwr == pBtdm8723->bCurDecBtPwr)
		return;

	BTDM_SetFwDecBtPwr(padapter, pBtdm8723->bCurDecBtPwr);

	pBtdm8723->bPreDecBtPwr = pBtdm8723->bCurDecBtPwr;
}

static void
btdm_2AntFwDacSwingLvl(struct rtw_adapter *padapter, u8 fwDacSwingLvl)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], set FW Dac Swing level = %d\n",  fwDacSwingLvl));
	pBtdm8723->curFwDacSwingLvl = fwDacSwingLvl;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], preFwDacSwingLvl=%d, curFwDacSwingLvl=%d\n",
	//	pBtdm8723->preFwDacSwingLvl, pBtdm8723->curFwDacSwingLvl));

	if(pBtdm8723->preFwDacSwingLvl == pBtdm8723->curFwDacSwingLvl)
		return;

	btdm_SetFwDacSwingLevel(padapter, pBtdm8723->curFwDacSwingLvl);

	pBtdm8723->preFwDacSwingLvl = pBtdm8723->curFwDacSwingLvl;
}

static void
btdm_2AntRfShrink(struct rtw_adapter *padapter, u8 bRxRfShrinkOn)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], turn Rx RF Shrink = %s\n",  ((bRxRfShrinkOn)? "ON":"OFF")));
	pBtdm8723->bCurRfRxLpfShrink = bRxRfShrinkOn;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreRfRxLpfShrink=%d, bCurRfRxLpfShrink=%d\n",
	//	pBtdm8723->bPreRfRxLpfShrink, pBtdm8723->bCurRfRxLpfShrink));

	if(pBtdm8723->bPreRfRxLpfShrink == pBtdm8723->bCurRfRxLpfShrink)
		return;

	BTDM_SetSwRfRxLpfCorner(padapter, (u8)pBtdm8723->bCurRfRxLpfShrink);

	pBtdm8723->bPreRfRxLpfShrink = pBtdm8723->bCurRfRxLpfShrink;
}

static void
btdm_2AntLowPenaltyRa(struct rtw_adapter *padapter, u8 bLowPenaltyRa)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], turn LowPenaltyRA = %s\n",  ((bLowPenaltyRa)? "ON":"OFF")));
	pBtdm8723->bCurLowPenaltyRa = bLowPenaltyRa;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreLowPenaltyRa=%d, bCurLowPenaltyRa=%d\n",
	//	pBtdm8723->bPreLowPenaltyRa, pBtdm8723->bCurLowPenaltyRa));

	if(pBtdm8723->bPreLowPenaltyRa == pBtdm8723->bCurLowPenaltyRa)
		return;

	BTDM_SetSwPenaltyTxRateAdaptive(padapter, (u8)pBtdm8723->bCurLowPenaltyRa);

	pBtdm8723->bPreLowPenaltyRa = pBtdm8723->bCurLowPenaltyRa;
}

static void
btdm_2AntDacSwing(struct rtw_adapter *padapter,
		  u8 bDacSwingOn, u32 dacSwingLvl)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], turn DacSwing=%s, dacSwingLvl=0x%x\n",
		((bDacSwingOn)? "ON":"OFF"), dacSwingLvl));
	pBtdm8723->bCurDacSwingOn = bDacSwingOn;
	pBtdm8723->curDacSwingLvl = dacSwingLvl;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl=0x%x, bCurDacSwingOn=%d, curDacSwingLvl=0x%x\n",
	//	pBtdm8723->bPreDacSwingOn, pBtdm8723->preDacSwingLvl,
	//	pBtdm8723->bCurDacSwingOn, pBtdm8723->curDacSwingLvl));

	if ((pBtdm8723->bPreDacSwingOn == pBtdm8723->bCurDacSwingOn) &&
	    (pBtdm8723->preDacSwingLvl == pBtdm8723->curDacSwingLvl))
		return;

	rtw_mdelay_os(30);
	btdm_SetSwFullTimeDacSwing(padapter, bDacSwingOn, dacSwingLvl);

	pBtdm8723->bPreDacSwingOn = pBtdm8723->bCurDacSwingOn;
	pBtdm8723->preDacSwingLvl = pBtdm8723->curDacSwingLvl;
}

static void btdm_2AntAdcBackOff(struct rtw_adapter *padapter, u8 bAdcBackOff)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], turn AdcBackOff = %s\n",  ((bAdcBackOff)? "ON":"OFF")));
	pBtdm8723->bCurAdcBackOff = bAdcBackOff;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreAdcBackOff=%d, bCurAdcBackOff=%d\n",
	//	pBtdm8723->bPreAdcBackOff, pBtdm8723->bCurAdcBackOff));

	if (pBtdm8723->bPreAdcBackOff == pBtdm8723->bCurAdcBackOff)
		return;

	BTDM_BBBackOffLevel(padapter, (u8)pBtdm8723->bCurAdcBackOff);

	pBtdm8723->bPreAdcBackOff = pBtdm8723->bCurAdcBackOff;
}

static void btdm_2AntAgcTable(struct rtw_adapter *padapter, u8 bAgcTableEn)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], %s Agc Table\n",  ((bAgcTableEn)? "Enable":"Disable")));
	pBtdm8723->bCurAgcTableEn = bAgcTableEn;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n",
	//	pBtdm8723->bPreAgcTableEn, pBtdm8723->bCurAgcTableEn));

	if (pBtdm8723->bPreAgcTableEn == pBtdm8723->bCurAgcTableEn)
		return;

	BTDM_AGCTable(padapter, (u8)bAgcTableEn);

	pBtdm8723->bPreAgcTableEn = pBtdm8723->bCurAgcTableEn;
}

static void
btdm_2AntCoexTable(struct rtw_adapter *padapter,
		   u32 val0x6c0, u32 val0x6c8, u8 val0x6cc)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], write Coex Table 0x6c0=0x%x, 0x6c8=0x%x, 0x6cc=0x%x\n",
		val0x6c0, val0x6c8, val0x6cc));
	pBtdm8723->curVal0x6c0 = val0x6c0;
	pBtdm8723->curVal0x6c8 = val0x6c8;
	pBtdm8723->curVal0x6cc = val0x6cc;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], preVal0x6c0=0x%x, preVal0x6c8=0x%x, preVal0x6cc=0x%x !!\n",
	//	pBtdm8723->preVal0x6c0, pBtdm8723->preVal0x6c8, pBtdm8723->preVal0x6cc));
	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], curVal0x6c0=0x%x, curVal0x6c8=0x%x, curVal0x6cc=0x%x !!\n",
	//	pBtdm8723->curVal0x6c0, pBtdm8723->curVal0x6c8, pBtdm8723->curVal0x6cc));

	if ((pBtdm8723->preVal0x6c0 == pBtdm8723->curVal0x6c0) &&
	    (pBtdm8723->preVal0x6c8 == pBtdm8723->curVal0x6c8) &&
	    (pBtdm8723->preVal0x6cc == pBtdm8723->curVal0x6cc))
		return;

	btdm_SetCoexTable(padapter, val0x6c0, val0x6c8, val0x6cc);

	pBtdm8723->preVal0x6c0 = pBtdm8723->curVal0x6c0;
	pBtdm8723->preVal0x6c8 = pBtdm8723->curVal0x6c8;
	pBtdm8723->preVal0x6cc = pBtdm8723->curVal0x6cc;
}

static void btdm_2AntIgnoreWlanAct(struct rtw_adapter *padapter, u8 bEnable)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], turn Ignore WlanAct %s\n", (bEnable? "ON":"OFF")));
	pBtdm8723->bCurIgnoreWlanAct = bEnable;

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n",
	//	pBtdm8723->bPreIgnoreWlanAct, pBtdm8723->bCurIgnoreWlanAct));

	if (pBtdm8723->bPreIgnoreWlanAct == pBtdm8723->bCurIgnoreWlanAct)
		return;

	btdm_SetFwIgnoreWlanAct(padapter,bEnable);
	pBtdm8723->bPreIgnoreWlanAct = pBtdm8723->bCurIgnoreWlanAct;
}

static void
btdm_2AntSetFw3a(struct rtw_adapter *padapter, u8 byte1, u8 byte2,
		 u8 byte3, u8 byte4, u8 byte5)
{
	u8 H2C_Parameter[5] ={0};

	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	// byte1[1:0] != 0 means enable pstdma
	// for 2Ant bt coexist, if byte1 != 0 means enable pstdma
	if (byte1)
	{
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}
	H2C_Parameter[0] = byte1;
	H2C_Parameter[1] = byte2;
	H2C_Parameter[2] = byte3;
	H2C_Parameter[3] = byte4;
	H2C_Parameter[4] = byte5;

	pHalData->bt_coexist.fw3aVal[0] = byte1;
	pHalData->bt_coexist.fw3aVal[1] = byte2;
	pHalData->bt_coexist.fw3aVal[2] = byte3;
	pHalData->bt_coexist.fw3aVal[3] = byte4;
	pHalData->bt_coexist.fw3aVal[4] = byte5;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes)=0x%x%08x\n",
		H2C_Parameter[0],
		H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4]));

	FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter);
	}

static void btdm_2AntPsTdma(struct rtw_adapter *padapter, u8 bTurnOn, u8 type)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
	u32			btTxRxCnt=0;
	u8			bTurnOnByCnt=_FALSE;
	u8			psTdmaTypeByCnt=0;

	btTxRxCnt = BTDM_BtTxRxCounterH(padapter)+BTDM_BtTxRxCounterL(padapter);
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT TxRx Counters = %d\n", btTxRxCnt));
	if(btTxRxCnt > 3000)
	{
		bTurnOnByCnt = _TRUE;
		psTdmaTypeByCnt = 8;

		RTPRINT(FBT, BT_TRACE, ("[BTCoex], For BTTxRxCounters, turn %s PS TDMA, type=%d\n", (bTurnOnByCnt? "ON":"OFF"), psTdmaTypeByCnt));
		pBtdm8723->bCurPsTdmaOn = bTurnOnByCnt;
		pBtdm8723->curPsTdma = psTdmaTypeByCnt;
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], turn %s PS TDMA, type=%d\n", (bTurnOn? "ON":"OFF"), type));
		pBtdm8723->bCurPsTdmaOn = bTurnOn;
		pBtdm8723->curPsTdma = type;
	}

	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n",
	//	pBtdm8723->bPrePsTdmaOn, pBtdm8723->bCurPsTdmaOn));
	//RTPRINT(FBT, BT_TRACE, ("[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n",
	//	pBtdm8723->prePsTdma, pBtdm8723->curPsTdma));

	if ((pBtdm8723->bPrePsTdmaOn == pBtdm8723->bCurPsTdmaOn) &&
	    (pBtdm8723->prePsTdma == pBtdm8723->curPsTdma))
		return;

	if (bTurnOn)
	{
		switch(type)
		{
			case 1:
			default:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98);
				break;
			case 2:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98);
				break;
			case 3:
				btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98);
				break;
			case 4:
				btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0xa1, 0x80);
				break;
			case 5:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98);
				break;
			case 6:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98);
				break;
			case 7:
				btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98);
				break;
			case 8:
				btdm_2AntSetFw3a(padapter, 0xa3, 0x5, 0x5, 0x20, 0x80);
				break;
			case 9:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0xa1, 0x98);
				break;
			case 10:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0xa1, 0x98);
				break;
			case 11:
				btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0xa1, 0x98);
				break;
			case 12:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98);
				break;
			case 13:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x1a, 0x1a, 0x20, 0x98);
				break;
			case 14:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x12, 0x12, 0x20, 0x98);
				break;
			case 15:
				btdm_2AntSetFw3a(padapter, 0xe3, 0xa, 0xa, 0x20, 0x98);
				break;
			case 16:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0x20, 0x98);
				break;
			case 17:
				btdm_2AntSetFw3a(padapter, 0xa3, 0x2f, 0x2f, 0x20, 0x80);
				break;
			case 18:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x5, 0x5, 0xa1, 0x98);
				break;
			case 19:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0xa1, 0x98);
				break;
			case 20:
				btdm_2AntSetFw3a(padapter, 0xe3, 0x25, 0x25, 0x20, 0x98);
				break;
		}
		}
		else
		{
		// disable PS tdma
		switch(type)
		{
			case 0:
				btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
				break;
			case 1:
				btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x0, 0x0);
				break;
			default:
				btdm_2AntSetFw3a(padapter, 0x0, 0x0, 0x0, 0x8, 0x0);
				break;
		}
		}

	// update pre state
	pBtdm8723->bPrePsTdmaOn =  pBtdm8723->bCurPsTdmaOn;
	pBtdm8723->prePsTdma = pBtdm8723->curPsTdma;
	}



static void btdm_2AntBtInquiryPage(struct rtw_adapter *padapter)
{
	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);
	btdm_2AntPsTdma(padapter, _TRUE, 8);
}


static u8 btdm_HoldForBtInqPage( struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	u32 curTime = rtw_get_current_time();

	if (pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage)
	{
		// bt inquiry or page is started.
		if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime == 0)
		{
			pHalData->bt_coexist.halCoex8723.btInqPageStartTime = curTime;
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page is started at time : 0x%"i64fmt"x \n",
			pHalData->bt_coexist.halCoex8723.btInqPageStartTime));
		}
	}
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page started time : 0x%"i64fmt"x, curTime : 0x%x \n",
		pHalData->bt_coexist.halCoex8723.btInqPageStartTime, curTime));

	if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime)
	{
		if(( (curTime - pHalData->bt_coexist.halCoex8723.btInqPageStartTime)/1000000) >= 10)
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], BT Inquiry/page >= 10sec!!!"));
			pHalData->bt_coexist.halCoex8723.btInqPageStartTime = 0;
		}
		}

	if (pHalData->bt_coexist.halCoex8723.btInqPageStartTime)
		{
		btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
		btdm_2AntIgnoreWlanAct(padapter, _FALSE);
		btdm_2AntPsTdma(padapter, _TRUE, 8);
		return _TRUE;
		}
		else
		return _FALSE;
		}


static u8 btdm_Is2Ant8723ACommonAction(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
	u8			bCommon=_FALSE;

	RTPRINT(FBT, BT_TRACE, ("%s :BTDM_IsWifiConnectionExist =%x check_fwstate=%x pmlmepriv->fw_state=0x%x\n",__func__,BTDM_IsWifiConnectionExist(padapter),check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING)),padapter->mlmepriv.fw_state));


//	if(!BTDM_IsWifiBusy(padapter) &&
	if((BTDM_IsWifiConnectionExist(padapter) == _FALSE)&&(check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))== _FALSE)&&
		(BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus) )
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt idle!!\n"));

		btdm_2AntLowPenaltyRa(padapter, _FALSE);
		btdm_2AntRfShrink(padapter, _FALSE);
		btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);

		btdm_2AntIgnoreWlanAct(padapter, _FALSE);
		btdm_2AntPsTdma(padapter, _FALSE, 0);
		btdm_2AntFwDacSwingLvl(padapter, 0x20);
		btdm_2AntDecBtPwr(padapter, _FALSE);

		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _FALSE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);

		bCommon = _TRUE;
	}
//	else if( BTDM_IsWifiBusy(padapter) &&
	else if(((BTDM_IsWifiConnectionExist(padapter) == _TRUE)||(check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))== _TRUE))&&
			(BT_2ANT_BT_STATUS_IDLE == pBtdm8723->btStatus) )
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT idle!!\n"));

		btdm_2AntLowPenaltyRa(padapter, _TRUE);
		btdm_2AntRfShrink(padapter, _FALSE);
		btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);

		btdm_2AntIgnoreWlanAct(padapter, _FALSE);
		btdm_2AntPsTdma(padapter, _FALSE, 0);
		btdm_2AntFwDacSwingLvl(padapter, 0x20);
		btdm_2AntDecBtPwr(padapter, _TRUE);

		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _FALSE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);

		bCommon = _TRUE;
}
//	else if(!BTDM_IsWifiBusy(padapter) &&
	else if((BTDM_IsWifiConnectionExist(padapter) == _FALSE)&&(check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))== _FALSE)&&
		(BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus) )
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi idle + Bt connected idle!!\n"));

		btdm_2AntLowPenaltyRa(padapter, _TRUE);
		btdm_2AntRfShrink(padapter, _TRUE);
		btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);

		btdm_2AntIgnoreWlanAct(padapter, _FALSE);
		btdm_2AntPsTdma(padapter, _FALSE, 0);
		btdm_2AntFwDacSwingLvl(padapter, 0x20);
		btdm_2AntDecBtPwr(padapter, _FALSE);

		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _FALSE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);

		bCommon = _TRUE;
	}
//	else if(BTDM_IsWifiBusy(padapter) &&
	else if(((BTDM_IsWifiConnectionExist(padapter) == _TRUE)||(check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))== _TRUE))&&
		(BT_2ANT_BT_STATUS_CONNECTED_IDLE == pBtdm8723->btStatus) )
{
		RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + Bt connected idle!!\n"));

		btdm_2AntLowPenaltyRa(padapter, _TRUE);
		btdm_2AntRfShrink(padapter, _TRUE);
		btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);

		btdm_2AntIgnoreWlanAct(padapter, _FALSE);
		btdm_2AntPsTdma(padapter, _FALSE, 0);
		btdm_2AntFwDacSwingLvl(padapter, 0x20);
		btdm_2AntDecBtPwr(padapter, _TRUE);

		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _FALSE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);

		bCommon = _TRUE;
	}
//	else if(!BTDM_IsWifiBusy(padapter) &&
	else if((BTDM_IsWifiConnectionExist(padapter) == _FALSE)&&(check_fwstate(&padapter->mlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))== _FALSE)&&
			(BT_2ANT_BT_STATUS_NON_IDLE == pBtdm8723->btStatus) )
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi idle + BT non-idle!!\n"));

		btdm_2AntLowPenaltyRa(padapter, _TRUE);
		btdm_2AntRfShrink(padapter, _TRUE);
		btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);

		btdm_2AntIgnoreWlanAct(padapter, _FALSE);
		btdm_2AntPsTdma(padapter, _FALSE, 0);
		btdm_2AntFwDacSwingLvl(padapter, 0x20);
		btdm_2AntDecBtPwr(padapter, _FALSE);

		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _FALSE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);

		bCommon = _TRUE;
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi non-idle + BT non-idle!!\n"));
		btdm_2AntLowPenaltyRa(padapter, _TRUE);
		btdm_2AntRfShrink(padapter, _TRUE);
		btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
		btdm_2AntIgnoreWlanAct(padapter, _FALSE);
		btdm_2AntFwDacSwingLvl(padapter, 0x20);

		bCommon = _FALSE;
	}

	return bCommon;
}


static void
btdm_2AntTdmaDurationAdjust(struct rtw_adapter *padapter, u8 bScoHid,
			    u8 bTxPause, u8 maxInterval)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT_MGNT		pBtMgnt = &pHalData->BtInfo.BtMgnt;
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
	static s32		up,dn,m,n,WaitCount;
	s32			result;   //0: no change, +1: increase WiFi duration, -1: decrease WiFi duration
	u8			retryCount=0;
//	u8			BtState;

//	BtState = pHalData->bt_coexist.halCoex8723.c2hBtInfo;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], TdmaDurationAdjust()\n"));

	if(pBtdm8723->bResetTdmaAdjust)
	{
		pBtdm8723->bResetTdmaAdjust = _FALSE;
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], first run TdmaDurationAdjust()!!\n"));
		{
			if(bScoHid)
			{
				if(bTxPause)
				{
					if(maxInterval == 1)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
}
					else if(maxInterval == 2)
{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
					else if(maxInterval == 3)
	{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
	}
	else
	{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
	}
}
				else
{
					if(maxInterval == 1)
	{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(maxInterval == 2)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
		}
					else if(maxInterval == 3)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else
			{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
			}
		}
	}
	else
	{
				if(bTxPause)
		{
					if(maxInterval == 1)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
		}
					else if(maxInterval == 2)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(maxInterval == 3)
			{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
			}
					else
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
		}
	}
				else
	{
					if(maxInterval == 1)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(maxInterval == 2)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(maxInterval == 3)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
	}
	else
	{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
	}
}
			}
		}
		//============
		up = 0;
		dn = 0;
		m = 1;
		n= 3;
		result = 0;
		WaitCount = 0;
	}
	else
	{
		//accquire the BT TRx retry count from BT_Info byte2
		retryCount = pHalData->bt_coexist.halCoex8723.btRetryCnt;
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], retryCount = %d\n", retryCount));
		result = 0;
		WaitCount++;

		if(retryCount == 0)  // no retry in the last 2-second duration
{
			up++;
			dn--;

			if (dn <= 0)
				dn = 0;

			if(up >= n)	// if ³sÄò n ­Ó2¬í retry count¬°0, «h½Õ¼eWiFi duration
{
				WaitCount = 0;
				n = 3;
				up = 0;
				dn = 0;
				result = 1;
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Increase wifi duration!!\n"));
}
		}
		else if (retryCount <= 3)	// <=3 retry in the last 2-second duration
{
			up--;
			dn++;

			if (up <= 0)
				up = 0;

			if (dn == 2)	// if ³sÄò 2 ­Ó2¬í retry count< 3, «h½Õ¯¶WiFi duration
	{
				if (WaitCount <= 2)
					m++; // Á×§K¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^
	else
					m = 1;

				if ( m >= 20) //m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration.
					m = 20;

				n = 3*m;
				up = 0;
				dn = 0;
				WaitCount = 0;
				result = -1;
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter<3!!\n"));
	}
}
		else  //retry count > 3, ¥u­n1¦¸ retry count > 3, «h½Õ¯¶WiFi duration
{
			if (WaitCount == 1)
				m++; // Á×§K¤@ª½¦b¨â­Ólevel¤¤¨Ó¦^
			else
				m = 1;

			if ( m >= 20) //m ³Ì¤j­È = 20 ' ³Ì¤j120¬í recheck¬O§_½Õ¾ã WiFi duration.
				m = 20;

			n = 3*m;
			up = 0;
			dn = 0;
			WaitCount = 0;
			result = -1;
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], Decrease wifi duration for retryCounter>3!!\n"));
		}

		RTPRINT(FBT, BT_TRACE, ("[BTCoex], max Interval = %d\n", maxInterval));
		if(maxInterval == 1)
		{
			if(bTxPause)
	{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n"));
				if(pBtdm8723->curPsTdma == 1)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 5);
					pBtdm8723->psTdmaDuAdjType = 5;
	}
				else if(pBtdm8723->curPsTdma == 2)
	{
					btdm_2AntPsTdma(padapter, _TRUE, 6);
					pBtdm8723->psTdmaDuAdjType = 6;
	}
				else if(pBtdm8723->curPsTdma == 3)
	{
					btdm_2AntPsTdma(padapter, _TRUE, 7);
					pBtdm8723->psTdmaDuAdjType = 7;
	}
				else if(pBtdm8723->curPsTdma == 4)
	{
					btdm_2AntPsTdma(padapter, _TRUE, 8);
					pBtdm8723->psTdmaDuAdjType = 8;
	}
				if(pBtdm8723->curPsTdma == 9)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 13);
					pBtdm8723->psTdmaDuAdjType = 13;
}
				else if(pBtdm8723->curPsTdma == 10)
{
					btdm_2AntPsTdma(padapter, _TRUE, 14);
					pBtdm8723->psTdmaDuAdjType = 14;
}
				else if(pBtdm8723->curPsTdma == 11)
{
					btdm_2AntPsTdma(padapter, _TRUE, 15);
					pBtdm8723->psTdmaDuAdjType = 15;
				}
				else if(pBtdm8723->curPsTdma == 12)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 16);
					pBtdm8723->psTdmaDuAdjType = 16;
				}

				if(result == -1)
	{
					if(pBtdm8723->curPsTdma == 5)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 6);
						pBtdm8723->psTdmaDuAdjType = 6;
	}
					else if(pBtdm8723->curPsTdma == 6)
	{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 7)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 8);
						pBtdm8723->psTdmaDuAdjType = 8;
		}
					else if(pBtdm8723->curPsTdma == 13)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 14);
						pBtdm8723->psTdmaDuAdjType = 14;
		}
					else if(pBtdm8723->curPsTdma == 14)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
	}
					else if(pBtdm8723->curPsTdma == 15)
	{
						btdm_2AntPsTdma(padapter, _TRUE, 16);
						pBtdm8723->psTdmaDuAdjType = 16;
	}
				}
				else if (result == 1)
	{
					if(pBtdm8723->curPsTdma == 8)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
	}
					else if(pBtdm8723->curPsTdma == 7)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 6);
						pBtdm8723->psTdmaDuAdjType = 6;
}
					else if(pBtdm8723->curPsTdma == 6)
{
						btdm_2AntPsTdma(padapter, _TRUE, 5);
						pBtdm8723->psTdmaDuAdjType = 5;
					}
					else if(pBtdm8723->curPsTdma == 16)
	{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
	}
					else if(pBtdm8723->curPsTdma == 15)
	{
						btdm_2AntPsTdma(padapter, _TRUE, 14);
						pBtdm8723->psTdmaDuAdjType = 14;
					}
					else if(pBtdm8723->curPsTdma == 14)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 13);
						pBtdm8723->psTdmaDuAdjType = 13;
					}
				}
		}
		else
		{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n"));
				if(pBtdm8723->curPsTdma == 5)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 1);
					pBtdm8723->psTdmaDuAdjType = 1;
		}
				else if(pBtdm8723->curPsTdma == 6)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 2);
					pBtdm8723->psTdmaDuAdjType = 2;
	}
				else if(pBtdm8723->curPsTdma == 7)
	{
					btdm_2AntPsTdma(padapter, _TRUE, 3);
					pBtdm8723->psTdmaDuAdjType = 3;
	}
				else if(pBtdm8723->curPsTdma == 8)
	{
					btdm_2AntPsTdma(padapter, _TRUE, 4);
					pBtdm8723->psTdmaDuAdjType = 4;
	}
				if(pBtdm8723->curPsTdma == 13)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 9);
					pBtdm8723->psTdmaDuAdjType = 9;
}
				else if(pBtdm8723->curPsTdma == 14)
{
					btdm_2AntPsTdma(padapter, _TRUE, 10);
					pBtdm8723->psTdmaDuAdjType = 10;
				}
				else if(pBtdm8723->curPsTdma == 15)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 11);
					pBtdm8723->psTdmaDuAdjType = 11;
				}
				else if(pBtdm8723->curPsTdma == 16)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 12);
					pBtdm8723->psTdmaDuAdjType = 12;
				}

				if(result == -1)
	{
					if(pBtdm8723->curPsTdma == 1)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 2);
						pBtdm8723->psTdmaDuAdjType = 2;
					}
					else if(pBtdm8723->curPsTdma == 2)
			{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
			}
					else if(pBtdm8723->curPsTdma == 3)
			{
						btdm_2AntPsTdma(padapter, _TRUE, 4);
						pBtdm8723->psTdmaDuAdjType = 4;
			}
					else if(pBtdm8723->curPsTdma == 9)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 10);
						pBtdm8723->psTdmaDuAdjType = 10;
		}
					else if(pBtdm8723->curPsTdma == 10)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 11)
			{
						btdm_2AntPsTdma(padapter, _TRUE, 12);
						pBtdm8723->psTdmaDuAdjType = 12;
			}
				}
				else if (result == 1)
				{
					if(pBtdm8723->curPsTdma == 4)
			{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
			}
					else if(pBtdm8723->curPsTdma == 3)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 2);
						pBtdm8723->psTdmaDuAdjType = 2;
		}
					else if(pBtdm8723->curPsTdma == 2)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 1);
						pBtdm8723->psTdmaDuAdjType = 1;
	}
					else if(pBtdm8723->curPsTdma == 12)
	{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 11)
		{
						btdm_2AntPsTdma(padapter, _TRUE, 10);
						pBtdm8723->psTdmaDuAdjType = 10;
					}
					else if(pBtdm8723->curPsTdma == 10)
			{
						btdm_2AntPsTdma(padapter, _TRUE, 9);
						pBtdm8723->psTdmaDuAdjType = 9;
			}
				}
			}
		}
		else if(maxInterval == 2)
			{
			if(bTxPause)
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n"));
				if(pBtdm8723->curPsTdma == 1)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 6);
					pBtdm8723->psTdmaDuAdjType = 6;
			}
				else if(pBtdm8723->curPsTdma == 2)
			{
					btdm_2AntPsTdma(padapter, _TRUE, 6);
					pBtdm8723->psTdmaDuAdjType = 6;
			}
				else if(pBtdm8723->curPsTdma == 3)
			{
					btdm_2AntPsTdma(padapter, _TRUE, 7);
					pBtdm8723->psTdmaDuAdjType = 7;
			}
				else if(pBtdm8723->curPsTdma == 4)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 8);
					pBtdm8723->psTdmaDuAdjType = 8;
		}
				if(pBtdm8723->curPsTdma == 9)
		{
					btdm_2AntPsTdma(padapter, _TRUE, 14);
					pBtdm8723->psTdmaDuAdjType = 14;
				}
				else if(pBtdm8723->curPsTdma == 10)
			{
					btdm_2AntPsTdma(padapter, _TRUE, 14);
					pBtdm8723->psTdmaDuAdjType = 14;
				}
				else if(pBtdm8723->curPsTdma == 11)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 15);
					pBtdm8723->psTdmaDuAdjType = 15;
				}
				else if(pBtdm8723->curPsTdma == 12)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 16);
					pBtdm8723->psTdmaDuAdjType = 16;
				}
				if(result == -1)
				{
					if(pBtdm8723->curPsTdma == 5)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 6);
						pBtdm8723->psTdmaDuAdjType = 6;
					}
					else if(pBtdm8723->curPsTdma == 6)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 7)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 8);
						pBtdm8723->psTdmaDuAdjType = 8;
					}
					else if(pBtdm8723->curPsTdma == 13)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 14);
						pBtdm8723->psTdmaDuAdjType = 14;
					}
					else if(pBtdm8723->curPsTdma == 14)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
					else if(pBtdm8723->curPsTdma == 15)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 16);
						pBtdm8723->psTdmaDuAdjType = 16;
					}
				}
				else if (result == 1)
				{
					if(pBtdm8723->curPsTdma == 8)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 7)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 6);
						pBtdm8723->psTdmaDuAdjType = 6;
					}
					else if(pBtdm8723->curPsTdma == 6)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 6);
						pBtdm8723->psTdmaDuAdjType = 6;
					}
					else if(pBtdm8723->curPsTdma == 16)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
					else if(pBtdm8723->curPsTdma == 15)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 14);
						pBtdm8723->psTdmaDuAdjType = 14;
					}
					else if(pBtdm8723->curPsTdma == 14)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 14);
						pBtdm8723->psTdmaDuAdjType = 14;
					}
				}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n"));
				if(pBtdm8723->curPsTdma == 5)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 2);
					pBtdm8723->psTdmaDuAdjType = 2;
			}
				else if(pBtdm8723->curPsTdma == 6)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 2);
					pBtdm8723->psTdmaDuAdjType = 2;
				}
				else if(pBtdm8723->curPsTdma == 7)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 3);
					pBtdm8723->psTdmaDuAdjType = 3;
				}
				else if(pBtdm8723->curPsTdma == 8)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 4);
					pBtdm8723->psTdmaDuAdjType = 4;
				}
				if(pBtdm8723->curPsTdma == 13)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 10);
					pBtdm8723->psTdmaDuAdjType = 10;
				}
				else if(pBtdm8723->curPsTdma == 14)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 10);
					pBtdm8723->psTdmaDuAdjType = 10;
				}
				else if(pBtdm8723->curPsTdma == 15)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 11);
					pBtdm8723->psTdmaDuAdjType = 11;
				}
				else if(pBtdm8723->curPsTdma == 16)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 12);
					pBtdm8723->psTdmaDuAdjType = 12;
				}
				if(result == -1)
				{
					if(pBtdm8723->curPsTdma == 1)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 2);
						pBtdm8723->psTdmaDuAdjType = 2;
					}
					else if(pBtdm8723->curPsTdma == 2)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(pBtdm8723->curPsTdma == 3)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 4);
						pBtdm8723->psTdmaDuAdjType = 4;
					}
					else if(pBtdm8723->curPsTdma == 9)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 10);
						pBtdm8723->psTdmaDuAdjType = 10;
					}
					else if(pBtdm8723->curPsTdma == 10)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 11)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 12);
						pBtdm8723->psTdmaDuAdjType = 12;
					}
				}
				else if (result == 1)
				{
					if(pBtdm8723->curPsTdma == 4)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(pBtdm8723->curPsTdma == 3)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 2);
						pBtdm8723->psTdmaDuAdjType = 2;
					}
					else if(pBtdm8723->curPsTdma == 2)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 2);
						pBtdm8723->psTdmaDuAdjType = 2;
					}
					else if(pBtdm8723->curPsTdma == 12)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 11)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 10);
						pBtdm8723->psTdmaDuAdjType = 10;
					}
					else if(pBtdm8723->curPsTdma == 10)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 10);
						pBtdm8723->psTdmaDuAdjType = 10;
					}
				}
			}
		}
		else if(maxInterval == 3)
		{
			if(bTxPause)
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 1\n"));
				if(pBtdm8723->curPsTdma == 1)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 7);
					pBtdm8723->psTdmaDuAdjType = 7;
				}
				else if(pBtdm8723->curPsTdma == 2)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 7);
					pBtdm8723->psTdmaDuAdjType = 7;
				}
				else if(pBtdm8723->curPsTdma == 3)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 7);
					pBtdm8723->psTdmaDuAdjType = 7;
				}
				else if(pBtdm8723->curPsTdma == 4)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 8);
					pBtdm8723->psTdmaDuAdjType = 8;
				}
				if(pBtdm8723->curPsTdma == 9)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 15);
					pBtdm8723->psTdmaDuAdjType = 15;
				}
				else if(pBtdm8723->curPsTdma == 10)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 15);
					pBtdm8723->psTdmaDuAdjType = 15;
				}
				else if(pBtdm8723->curPsTdma == 11)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 15);
					pBtdm8723->psTdmaDuAdjType = 15;
				}
				else if(pBtdm8723->curPsTdma == 12)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 16);
					pBtdm8723->psTdmaDuAdjType = 16;
				}
				if(result == -1)
				{
					if(pBtdm8723->curPsTdma == 5)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 6)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 7)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 8);
						pBtdm8723->psTdmaDuAdjType = 8;
					}
					else if(pBtdm8723->curPsTdma == 13)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
					else if(pBtdm8723->curPsTdma == 14)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
					else if(pBtdm8723->curPsTdma == 15)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 16);
						pBtdm8723->psTdmaDuAdjType = 16;
					}
				}
				else if (result == 1)
				{
					if(pBtdm8723->curPsTdma == 8)
			{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 7)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 6)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 7);
						pBtdm8723->psTdmaDuAdjType = 7;
					}
					else if(pBtdm8723->curPsTdma == 16)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
					else if(pBtdm8723->curPsTdma == 15)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
					else if(pBtdm8723->curPsTdma == 14)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 15);
						pBtdm8723->psTdmaDuAdjType = 15;
					}
				}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], TxPause = 0\n"));
				if(pBtdm8723->curPsTdma == 5)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 3);
					pBtdm8723->psTdmaDuAdjType = 3;
			}
				else if(pBtdm8723->curPsTdma == 6)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 3);
					pBtdm8723->psTdmaDuAdjType = 3;
		}
				else if(pBtdm8723->curPsTdma == 7)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 3);
					pBtdm8723->psTdmaDuAdjType = 3;
	}
				else if(pBtdm8723->curPsTdma == 8)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 4);
					pBtdm8723->psTdmaDuAdjType = 4;
				}
				if(pBtdm8723->curPsTdma == 13)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 11);
					pBtdm8723->psTdmaDuAdjType = 11;
				}
				else if(pBtdm8723->curPsTdma == 14)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 11);
					pBtdm8723->psTdmaDuAdjType = 11;
				}
				else if(pBtdm8723->curPsTdma == 15)
				{
					btdm_2AntPsTdma(padapter, _TRUE, 11);
					pBtdm8723->psTdmaDuAdjType = 11;
				}
				else if(pBtdm8723->curPsTdma == 16)
	{
					btdm_2AntPsTdma(padapter, _TRUE, 12);
					pBtdm8723->psTdmaDuAdjType = 12;
				}
				if(result == -1)
				{
					if(pBtdm8723->curPsTdma == 1)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(pBtdm8723->curPsTdma == 2)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(pBtdm8723->curPsTdma == 3)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 4);
						pBtdm8723->psTdmaDuAdjType = 4;
					}
					else if(pBtdm8723->curPsTdma == 9)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 10)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 11)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 12);
						pBtdm8723->psTdmaDuAdjType = 12;
					}
				}
				else if (result == 1)
				{
					if(pBtdm8723->curPsTdma == 4)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(pBtdm8723->curPsTdma == 3)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(pBtdm8723->curPsTdma == 2)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 3);
						pBtdm8723->psTdmaDuAdjType = 3;
					}
					else if(pBtdm8723->curPsTdma == 12)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 11)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
					else if(pBtdm8723->curPsTdma == 10)
					{
						btdm_2AntPsTdma(padapter, _TRUE, 11);
						pBtdm8723->psTdmaDuAdjType = 11;
					}
				}
			}
		}
	}
        RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type : recordPsTdma=%d\n",pBtdm8723->psTdmaDuAdjType));
	// if current PsTdma not match with the recorded one (when scan, dhcp...),
	// then we have to adjust it back to the previous record one.
	if(pBtdm8723->curPsTdma != pBtdm8723->psTdmaDuAdjType)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], PsTdma type dismatch!!!, curPsTdma=%d, recordPsTdma=%d\n",
			pBtdm8723->curPsTdma, pBtdm8723->psTdmaDuAdjType));

		if( check_fwstate(&padapter->mlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _FALSE )
		{
			btdm_2AntPsTdma(padapter, _TRUE, pBtdm8723->psTdmaDuAdjType);
		}
		else
	{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"));
		}
	}
}

// default Action
static void btdm_2Ant8723AAction0(struct rtw_adapter *padapter)
{
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);
	btdm_2AntPsTdma(padapter, _FALSE, 0);
	btdm_2AntDecBtPwr(padapter, _FALSE);

	btdm_2AntAgcTable(padapter, _FALSE);
	btdm_2AntAdcBackOff(padapter, _FALSE);
	btdm_2AntLowPenaltyRa(padapter, _FALSE);
	btdm_2AntRfShrink(padapter, _FALSE);
	btdm_2AntDacSwing(padapter, _FALSE, 0xc0);

	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
}

// SCO only or SCO+PAN(HS)
static void btdm_2Ant8723ASCOAction(struct rtw_adapter *padapter)
{
	u8	btRssiState, btRssiState1;


	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);

	if (BTDM_IsHT40(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		// fw mechanism
		if ((btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH))
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 11);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 15);
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 11);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 15);
		}


		// sw mechanism
		if ((btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH))
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
	}
	}


static void btdm_2Ant8723AHIDAction(struct rtw_adapter *padapter)
{
	u8		btRssiState, btRssiState1;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);

	if (BTDM_IsHT40(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
			// fw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 9);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 13);
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _FALSE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 9);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 13);
		}

			// sw mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
			}
		}

//A2DP only / PAN(EDR) only/ A2DP+PAN(HS)
static void btdm_2Ant8723AA2DPAction(struct rtw_adapter *padapter)
{
	u8		btRssiState, btRssiState1;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8		btInfoExt=pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
		else
		btdm_2AntDecBtPwr(padapter, _FALSE);

	if(BTDM_IsHT40(padapter))
		{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);

		// fw mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);

			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _FALSE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _FALSE, 1);
		}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _TRUE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _TRUE, 1);
		}
	}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _FALSE, 3);
	}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _FALSE, 1);
}
		}
		else
{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _TRUE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _TRUE, 1);
		}
		}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
	}
}


static void btdm_2Ant8723APANEDRAction(struct rtw_adapter *padapter)
{
	u8		btRssiState, btRssiState1;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);

		if(BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);

			// fw mechanism
			if( (btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 2);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 6);
			}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
			btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 2);
			}
			else
{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 6);
			}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
		}
	}



//PAN(HS) only
static void btdm_2Ant8723APANHSAction(struct rtw_adapter *padapter)
{
	u8		btRssiState, btRssiState1;

	if (BTDM_IsHT40(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
		// fw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntDecBtPwr(padapter, _TRUE);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntDecBtPwr(padapter, _FALSE);
		}
		btdm_2AntPsTdma(padapter, _FALSE, 0);

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);

		if ((btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH))
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high\n"));
			// fw mechanism
			btdm_2AntDecBtPwr(padapter, _TRUE);
			btdm_2AntPsTdma(padapter, _FALSE, 0);

			// sw mechanism
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low\n"));
			// fw mechanism
			btdm_2AntDecBtPwr(padapter, _FALSE);
			btdm_2AntPsTdma(padapter, _FALSE, 0);

			// sw mechanism
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	}
}


//PAN(EDR)+A2DP
static void btdm_2Ant8723APANEDRA2DPAction(struct rtw_adapter *padapter)
{
	u8		btRssiState, btRssiState1, btInfoExt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);

		if(BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);

			if( (btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
				// fw mechanism
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);

			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 4);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 2);
			}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
				// fw mechanism
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 8);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 6);
			}
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			// fw mechanism
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 4);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 2);
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			// fw mechanism
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 8);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 6);
			}
		}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
	}
}


static void btdm_2Ant8723APANEDRHIDAction(struct rtw_adapter *padapter)
{
	u8 btRssiState, btRssiState1;

	if (btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);

	if (BTDM_IsHT40(padapter)) {
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		// fw mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 10);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 14);
		}

				// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 10);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 14);
	}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
		else
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
	}
}

// HID+A2DP+PAN(EDR)
static void btdm_2Ant8723AHIDA2DPPANEDRAction(struct rtw_adapter *padapter)
{
	u8		btRssiState, btRssiState1, btInfoExt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);

		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
			if( (btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);

			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 12);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 10);
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 16);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 14);
			}
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 37, 0);
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0);
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);

			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 12);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 10);
			}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 16);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntPsTdma(padapter, _TRUE, 14);
			}
			}

			// sw mechanism
			if ((btRssiState1 == BT_RSSI_STATE_HIGH) ||
				(btRssiState1 == BT_RSSI_STATE_STAY_HIGH))
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
			else
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
		}
	}


static void btdm_2Ant8723AHIDA2DPAction(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8		btRssiState, btRssiState1, btInfoExt;

	btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);

		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
			if( (btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);

			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 1);
			}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 1);
			}
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0);

			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);

			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 1);
			}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 1);
		}
	}
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			// sw mechanism
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
		else
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			// sw mechanism
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
	}
}


static void btdm_2Ant8723AHidScoEsco(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8		btRssiState, btRssiState1, btInfoExt;

	btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);
	// coex table
	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);

	if(BTDM_IsHT40(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		// fw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
		{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 3);
		}
		else
		{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 2);
		}
	}
	else
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
		{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 3);
		}
		else
		{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 2);
			}
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _FALSE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _FALSE, 2);
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			if(btInfoExt&BIT(0))	//a2dp rate, 1:basic /0:edr
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp basic rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 3);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("a2dp edr rate \n"));
				btdm_2AntTdmaDurationAdjust(padapter, _TRUE, _TRUE, 2);
		}
	}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
		else
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	}
}

static void btdm_2Ant8723AFtpA2dp(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8		btRssiState, btRssiState1, btInfoExt;

	btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);
	// coex table
	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);

	if(BTDM_IsHT40(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 27, 0);
		// fw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 3);
			}
			else
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 7);
			}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
		else
		{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 3);
		}
		else
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter,  _TRUE, 7);
			}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
			else
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
		}
	}


static void btdm_2Ant8723AA2dp(struct rtw_adapter *padapter)
	{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8		btRssiState, btRssiState1, btInfoExt;

	btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);
		// coex table
	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);

	if(BTDM_IsHT40(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		// fw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _FALSE, 1);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _TRUE, 1);
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _FALSE, 1);
		}
		else
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntTdmaDurationAdjust(padapter, _FALSE, _TRUE, 1);
			}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
			else
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
			}
		}
}


static void btdm_2Ant8723Ftp(struct rtw_adapter *padapter)
		{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8		btRssiState, btRssiState1, btInfoExt;

	btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;

	if(btdm_NeedToDecBtPwr(padapter))
		btdm_2AntDecBtPwr(padapter, _TRUE);
	else
		btdm_2AntDecBtPwr(padapter, _FALSE);
	// coex table
	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);

	if(BTDM_IsHT40(padapter))
			{
		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 37, 0);
		// fw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 1);
			}
			else
			{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 5);
		}

		// sw mechanism
		btdm_2AntAgcTable(padapter, _FALSE);
		btdm_2AntAdcBackOff(padapter, _TRUE);
		btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, 47, 0);
		btRssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, 27, 0);

		// fw mechanism
		if( (btRssiState1 == BT_RSSI_STATE_HIGH) ||
			(btRssiState1 == BT_RSSI_STATE_STAY_HIGH) )
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 high \n"));
			PlatformEFIOWrite1Byte(padapter, 0x883, 0x40);
			btdm_2AntPsTdma(padapter, _TRUE, 1);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi-1 low \n"));
			btdm_2AntPsTdma(padapter, _TRUE, 5);
	}

		// sw mechanism
		if( (btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH) )
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi high \n"));
			btdm_2AntAgcTable(padapter, _TRUE);
			btdm_2AntAdcBackOff(padapter, _TRUE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
	}
		else
	{
			RTPRINT(FBT, BT_TRACE, ("Wifi rssi low \n"));
			btdm_2AntAgcTable(padapter, _FALSE);
			btdm_2AntAdcBackOff(padapter, _FALSE);
			btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
		}
	}
}

//============================================================
// extern function start with BTDM_
//============================================================
static void BTDM_2AntParaInit(struct rtw_adapter *padapter)
{

	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2Ant Parameter Init!!\n"));

	// Enable counter statistics
	rtw_write8(padapter, 0x76e, 0x4);
	rtw_write8(padapter, 0x778, 0x3);
	rtw_write8(padapter, 0x40, 0x20);

	// force to reset coex mechanism
	pBtdm8723->preVal0x6c0 = 0x0;
	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);

	pBtdm8723->bPrePsTdmaOn = _TRUE;
	btdm_2AntPsTdma(padapter, _FALSE, 0);

	pBtdm8723->preFwDacSwingLvl = 0x10;
	btdm_2AntFwDacSwingLvl(padapter, 0x20);

	pBtdm8723->bPreDecBtPwr = _TRUE;
	btdm_2AntDecBtPwr(padapter, _FALSE);

	pBtdm8723->bPreAgcTableEn = _TRUE;
	btdm_2AntAgcTable(padapter, _FALSE);

	pBtdm8723->bPreAdcBackOff = _TRUE;
	btdm_2AntAdcBackOff(padapter, _FALSE);

	pBtdm8723->bPreLowPenaltyRa = _TRUE;
	btdm_2AntLowPenaltyRa(padapter, _FALSE);

	pBtdm8723->bPreRfRxLpfShrink = _TRUE;
	btdm_2AntRfShrink(padapter, _FALSE);

	pBtdm8723->bPreDacSwingOn = _TRUE;
	btdm_2AntDacSwing(padapter, _FALSE, 0xc0);

	pBtdm8723->bPreIgnoreWlanAct = _TRUE;
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);
}

static void BTDM_2AntHwCoexAllOff8723A(struct rtw_adapter *padapter)
{
	btdm_2AntCoexTable(padapter, 0x55555555, 0xffff, 0x3);
}

static void BTDM_2AntFwCoexAllOff8723A(struct rtw_adapter *padapter)
{
	btdm_2AntIgnoreWlanAct(padapter, _FALSE);
	btdm_2AntPsTdma(padapter, _FALSE, 0);
	btdm_2AntFwDacSwingLvl(padapter, 0x20);
	btdm_2AntDecBtPwr(padapter, _FALSE);
}

static void BTDM_2AntSwCoexAllOff8723A(struct rtw_adapter *padapter)
{
	btdm_2AntAgcTable(padapter, _FALSE);
	btdm_2AntAdcBackOff(padapter, _FALSE);
	btdm_2AntLowPenaltyRa(padapter, _FALSE);
	btdm_2AntRfShrink(padapter, _FALSE);
	btdm_2AntDacSwing(padapter, _FALSE, 0xc0);
}


static void BTDM_2AntIpsNotify8723A(struct rtw_adapter *padapter, u8 type)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt=&pBTInfo->BtMgnt;

	if(pBtMgnt->bSupportProfile && (rf_off==type))
	{
		RTPRINT(FBT, BT_TRACE, ("[BT][DM], enter IPS, turn off all BT Coexist DM\n"));
		BTDM_CoexAllOff(padapter);
	}
}


static void BTDM_2AntNotifyBtOperation8723(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	switch (pBtMgnt->ExtConfig.btOperationCode)
	{
		case HCI_BT_OP_NONE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for operation None!!\n"));
			break;
		case HCI_BT_OP_INQUIRY_START:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for Inquiry start!!\n"));
			pBtMgnt->ExtConfig.bHoldForBtOperation = _TRUE;
			pBtMgnt->ExtConfig.bHoldPeriodCnt = 1;
			btdm_2AntBtInquiryPage(padapter);
			break;
		case HCI_BT_OP_INQUIRY_FINISH:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for Inquiry finished!!\n"));
			pBtMgnt->ExtConfig.bHoldForBtOperation = _FALSE;
			break;
		case HCI_BT_OP_PAGING_START:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for paging start!!\n"));
			pBtMgnt->ExtConfig.bHoldForBtOperation = _TRUE;
			pBtMgnt->ExtConfig.bHoldPeriodCnt = 1;
			btdm_2AntBtInquiryPage(padapter);
			break;
		case HCI_BT_OP_PAGING_SUCCESS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for paging successfully!!\n"));
			pBtMgnt->ExtConfig.bHoldForBtOperation = _FALSE;
			break;
		case HCI_BT_OP_PAGING_UNSUCCESS:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for paging unsuccessfully!!\n"));
			pBtMgnt->ExtConfig.bHoldForBtOperation = _FALSE;
			break;
		case HCI_BT_OP_PAIRING_START:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for Pairing start!!\n"));
			pBtMgnt->ExtConfig.bHoldForBtOperation = _TRUE;
			pBtMgnt->ExtConfig.bHoldPeriodCnt = 1;
			btdm_2AntBtInquiryPage(padapter);
			break;
		case HCI_BT_OP_PAIRING_FINISH:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for Pairing finished!!\n"));
			pBtMgnt->ExtConfig.bHoldForBtOperation = _FALSE;
			break;

		case HCI_BT_OP_BT_DEV_ENABLE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for BT Device enable!!\n"));
			break;
		case HCI_BT_OP_BT_DEV_DISABLE:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for BT Device disable!!\n"));
			break;
		default:
			RTPRINT(FIOCTL, IOCTL_BT_HCICMD_EXT, ("[BT OP] : Adjust for Unknown, error!!\n"));
			break;
	}
}


static void
BTDM_2AntFwC2hBtInfo8723A(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;
	u8	btInfo=0;
	u8			algorithm=BT_2ANT_COEX_ALGO_UNDEFINED;
	u8			bScoExist=_FALSE, bBtLinkExist=_FALSE, bBtHsModeExist=_FALSE;
	btInfo = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal;


	pBtdm8723->btStatus = BT_2ANT_BT_STATUS_IDLE;

	// check BIT2 first ==> check if bt is under inquiry or page scan
	if(btInfo & BIT(2))
	{
		if(pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage == _FALSE){
			pBtMgnt->ExtConfig.bHoldForBtOperation = _TRUE;
			pBtMgnt->ExtConfig.bHoldPeriodCnt = 1;
			btdm_2AntBtInquiryPage(padapter);
		}
		else{
			pBtMgnt->ExtConfig.bHoldPeriodCnt++;
			btdm_HoldForBtInqPage(padapter);
		}
		pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = _TRUE;

	}
	else
	{
		pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage = _FALSE;
		pBtMgnt->ExtConfig.bHoldForBtOperation = _FALSE;
		pBtMgnt->ExtConfig.bHoldPeriodCnt = 0;


	}
	RTPRINT(FBT, BT_TRACE, ("[BTC2H], pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage=%x pBtMgnt->ExtConfig.bHoldPeriodCnt=%x pBtMgnt->ExtConfig.bHoldForBtOperation=%x\n",pHalData->bt_coexist.halCoex8723.bC2hBtInquiryPage,pBtMgnt->ExtConfig.bHoldPeriodCnt,pBtMgnt->ExtConfig.bHoldForBtOperation));

	RTPRINT(FBT, BT_TRACE, ("[BTC2H],   btInfo=%x   pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal=%x\n",btInfo,pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal));
	if(btInfo&BT_INFO_ACL)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect=TRUE   btInfo=%x\n",btInfo));
		//pBtMgnt->ExtConfig.bBTBusy = _TRUE;
		bBtLinkExist = _TRUE;
		if(((btInfo&(BT_INFO_FTP|BT_INFO_A2DP|BT_INFO_HID|BT_INFO_SCO_BUSY))!=0) || pHalData->bt_coexist.halCoex8723.btRetryCnt>0){
			pBtdm8723->btStatus =BT_2ANT_BT_STATUS_NON_IDLE;
		}
		else
			pBtdm8723->btStatus =BT_2ANT_BT_STATUS_CONNECTED_IDLE;


		if(btInfo&BT_INFO_SCO|| btInfo&BT_INFO_SCO_BUSY){
			if(btInfo&BT_INFO_FTP|| btInfo&BT_INFO_A2DP||btInfo&BT_INFO_HID){
				switch(btInfo&0xe0){
					case BT_INFO_HID :
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + HID\n"));
						algorithm = BT_2ANT_COEX_ALGO_HID;
						break;
					case BT_INFO_A2DP :
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], Error!!! SCO + A2DP\n"));
						break;
					case BT_INFO_FTP :
						if(bBtHsModeExist)
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(HS)\n"));
							algorithm = BT_2ANT_COEX_ALGO_SCO;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO + PAN(EDR)\n"));
							algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
						}
						break;
					case (BT_INFO_HID|BT_INFO_A2DP) :
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n"));
						algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
						break;
					case (BT_INFO_HID|BT_INFO_FTP) :
						if(bBtHsModeExist)
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n"));
							algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n"));
							algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
						}
						break;
					case (BT_INFO_A2DP|BT_INFO_FTP) :
						if(bBtHsModeExist)
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n"));
							algorithm = BT_2ANT_COEX_ALGO_A2DP;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n"));
							algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP;
						}
						break;
					case (BT_INFO_HID|BT_INFO_A2DP|BT_INFO_FTP) :
						if(bBtHsModeExist)
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n"));
							algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n"));
							algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
						}
						break;

				}
			}
			else{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], SCO only\n"));
				algorithm = BT_2ANT_COEX_ALGO_SCO;
			}
		}
		else{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], non SCO\n"));
				switch(btInfo&0xe0){
					case BT_INFO_HID :
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID\n"));
						algorithm = BT_2ANT_COEX_ALGO_HID;
						break;
					case BT_INFO_A2DP :
						RTPRINT(FBT, BT_TRACE, ("[BTCoex],  A2DP\n"));
						algorithm = BT_2ANT_COEX_ALGO_A2DP;
						break;
					case BT_INFO_FTP :
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], PAN(EDR)\n"));
						algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
						break;
					case (BT_INFO_HID|BT_INFO_A2DP) :
						RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP\n"));
						algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
						break;
					case (BT_INFO_HID|BT_INFO_FTP) :
						if(bBtHsModeExist)
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(HS)\n"));
							algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + PAN(EDR)\n"));
							algorithm = BT_2ANT_COEX_ALGO_PANEDR_HID;
						}
						break;
					case (BT_INFO_A2DP|BT_INFO_FTP) :
						if(bBtHsModeExist)
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(HS)\n"));
							algorithm = BT_2ANT_COEX_ALGO_A2DP;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], A2DP + PAN(EDR)\n"));
							algorithm = BT_2ANT_COEX_ALGO_PANEDR_A2DP;
						}
						break;
					case (BT_INFO_HID|BT_INFO_A2DP|BT_INFO_FTP) :
						if(bBtHsModeExist)
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(HS)\n"));
							algorithm = BT_2ANT_COEX_ALGO_HID_A2DP;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("[BTCoex], HID + A2DP + PAN(EDR)\n"));
							algorithm = BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR;
						}
						break;

				}

		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BTC2H], BTInfo: bConnect=FALSE\n"));
		//pBtMgnt->ExtConfig.bBTBusy = _FALSE;
		pBtdm8723->btStatus =BT_2ANT_BT_STATUS_IDLE;
	}

	pBtdm8723->curAlgorithm =algorithm;
	RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm));

//From
	BTDM_CheckWiFiState(padapter);
	if(pBtMgnt->ExtConfig.bManualControl)
	{
		RTPRINT(FBT, BT_TRACE, ("Action Manual control, won't execute bt coexist mechanism!!\n"));
		return;
	}

}


void BTDM_2AntBtCoexist8723A(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8				BtState = 0, btInfoOriginal=0, btRetryCnt=0;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBTDM_8723A_2ANT	pBtdm8723 = &pHalData->bt_coexist.halCoex8723.btdm2Ant;

	if (BTDM_BtProfileSupport(padapter))
	{
		if (pBtMgnt->ExtConfig.bHoldForBtOperation)
		{
			RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n"));
			return;
		}
		if(pBtMgnt->ExtConfig.bHoldPeriodCnt)
		{
			RTPRINT(FBT, BT_TRACE, ("Hold BT inquiry/page scan setting (cnt = %d)!!\n",
				pBtMgnt->ExtConfig.bHoldPeriodCnt));
			if(pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11)
			{
				pBtMgnt->ExtConfig.bHoldPeriodCnt = 0;
				// next time the coexist parameters should be reset again.
			}
			else
				pBtMgnt->ExtConfig.bHoldPeriodCnt++;
			return;
		}

		if(pBtDbg->dbgCtrl)
		{
			RTPRINT(FBT, BT_TRACE, ("[Dbg control], "));
		}

		pBtdm8723->curAlgorithm = btdm_ActionAlgorithm(padapter);
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], Algorithm = %d \n", pBtdm8723->curAlgorithm));

		if (btdm_Is2Ant8723ACommonAction(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n"));
			pBtdm8723->bResetTdmaAdjust = _TRUE;
		}
		else
		{
			if(pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm)
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], preAlgorithm=%d, curAlgorithm=%d\n",
				pBtdm8723->preAlgorithm, pBtdm8723->curAlgorithm));
				pBtdm8723->bResetTdmaAdjust = _TRUE;
			}
			switch(pBtdm8723->curAlgorithm)
			{
				case BT_2ANT_COEX_ALGO_SCO:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n"));
					btdm_2Ant8723ASCOAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_HID:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n"));
					btdm_2Ant8723AHIDAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_A2DP:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n"));
					btdm_2Ant8723AA2DPAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANEDR:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n"));
					btdm_2Ant8723APANEDRAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANHS:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n"));
					btdm_2Ant8723APANHSAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANEDR_A2DP:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n"));
					btdm_2Ant8723APANEDRA2DPAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANEDR_HID:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n"));
					btdm_2Ant8723APANEDRHIDAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n"));
					btdm_2Ant8723AHIDA2DPPANEDRAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_HID_A2DP:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n"));
					btdm_2Ant8723AHIDA2DPAction(padapter);
					break;
				default:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n"));
					btdm_2Ant8723AA2DPAction(padapter);
					break;
			}
			pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm;
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex] Get bt info by fw!!\n"));
		//msg shows c2h rsp for bt_info is received or not.
		if (pHalData->bt_coexist.halCoex8723.bC2hBtInfoReqSent)
		{
			RTPRINT(FBT, BT_TRACE, ("[BTCoex] c2h for btInfo not rcvd yet!!\n"));
		}

		//btRetryCnt = pHalData->bt_coexist.halCoex8723.btRetryCnt;
		btInfoOriginal = pHalData->bt_coexist.halCoex8723.c2hBtInfoOriginal;

		if(pBtMgnt->ExtConfig.bHoldForBtOperation)
		{
			RTPRINT(FBT, BT_TRACE, ("Action for BT Operation adjust!!\n"));
			return;
		}
		if(pBtMgnt->ExtConfig.bHoldPeriodCnt)
		{
			RTPRINT(FBT, BT_TRACE, ("Hold BT inquiry/page scan setting (cnt = %d)!!\n", pBtMgnt->ExtConfig.bHoldPeriodCnt));
			if(pBtMgnt->ExtConfig.bHoldPeriodCnt >= 11)
			{
				pBtMgnt->ExtConfig.bHoldPeriodCnt = 0;
				// next time the coexist parameters should be reset again.
			}
			else
				pBtMgnt->ExtConfig.bHoldPeriodCnt++;
			return;
		}

		if(pBtDbg->dbgCtrl)
		{
			RTPRINT(FBT, BT_TRACE, ("[Dbg control], "));
		}
		if (btdm_Is2Ant8723ACommonAction(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action 2-Ant common.\n"));
			pBtdm8723->bResetTdmaAdjust = _TRUE;
		}
		else
		{
			if(pBtdm8723->curAlgorithm != pBtdm8723->preAlgorithm)
			{
				RTPRINT(FBT, BT_TRACE, ("[BTCoex], preAlgorithm=%d, curAlgorithm=%d\n", pBtdm8723->preAlgorithm, pBtdm8723->curAlgorithm));
				pBtdm8723->bResetTdmaAdjust = _TRUE;
			}
			switch(pBtdm8723->curAlgorithm)
			{
				case BT_2ANT_COEX_ALGO_SCO:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = SCO.\n"));
					btdm_2Ant8723ASCOAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_HID:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID.\n"));
					btdm_2Ant8723AHIDAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_A2DP:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = A2DP.\n"));
					btdm_2Ant8723AA2dp(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANEDR:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR).\n"));
					btdm_2Ant8723APANEDRAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANHS:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HS mode.\n"));
					btdm_2Ant8723APANHSAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANEDR_A2DP:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN+A2DP.\n"));
					btdm_2Ant8723APANEDRA2DPAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_PANEDR_HID:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = PAN(EDR)+HID.\n"));
					btdm_2Ant8723APANEDRHIDAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_HID_A2DP_PANEDR:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP+PAN.\n"));
					btdm_2Ant8723AHIDA2DPPANEDRAction(padapter);
					break;
				case BT_2ANT_COEX_ALGO_HID_A2DP:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = HID+A2DP.\n"));
					btdm_2Ant8723AHIDA2DPAction(padapter);
					break;
				default:
					RTPRINT(FBT, BT_TRACE, ("Action 2-Ant, algorithm = 0.\n"));
					//btdm_2Ant8723AAction0(padapter);
                                        btdm_2Ant8723AA2DPAction(padapter);
					break;
			}
			pBtdm8723->preAlgorithm = pBtdm8723->curAlgorithm;
		}

	}
}

// ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc87232Ant.c =====
#endif

#ifdef __HALBTC8723_C__ // HAL/BTCoexist/HalBtc8723.c
// ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtc8723.c =====

static u8 btCoexDbgBuf[BT_TMP_BUF_SIZE];
static const char *const BtProfileString[]={
	"NONE",
	"A2DP",
	"PAN",
	"HID",
	"SCO",
};
static const char *const BtSpecString[]={
	"1.0b",
	"1.1",
	"1.2",
	"2.0+EDR",
	"2.1+EDR",
	"3.0+HS",
	"4.0",
};
static const char *const BtLinkRoleString[]={
	"Master",
	"Slave",
};

static u8 btdm_BtWifiAntNum(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT_COEXIST_8723A	pBtCoex = &pHalData->bt_coexist.halCoex8723;

//	RTPRINT(FBT, BT_TRACE, ("%s pHalData->bt_coexist.BluetoothCoexist =%x pHalData->EEPROMBluetoothCoexist=%x \n",
//		__func__,pHalData->bt_coexist.BluetoothCoexist,pHalData->EEPROMBluetoothCoexist));
//	RTPRINT(FBT, BT_TRACE, ("%s pHalData->bt_coexist.BT_Ant_Num =%x pHalData->EEPROMBluetoothAntNum=%x \n",
//		__func__,pHalData->bt_coexist.BT_Ant_Num,pHalData->EEPROMBluetoothAntNum));
	if (Ant_x2 == pHalData->bt_coexist.BT_Ant_Num)
	{
		if (Ant_x2 == pBtCoex->TotalAntNum)
			return Ant_x2;
		else
			return Ant_x1;
	}
	else
	{
		return Ant_x1;
	}

	return Ant_x2;
}

static void btdm_BtHwCountersMonitor(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u32				regHPTxRx, regLPTxRx, u4Tmp;
	u32				regHPTx=0, regHPRx=0, regLPTx=0, regLPRx=0;
//	u8				u1Tmp;


	regHPTxRx = REG_HIGH_PRIORITY_TXRX;
	regLPTxRx = REG_LOW_PRIORITY_TXRX;

	u4Tmp = rtw_read32(padapter, regHPTxRx);
	regHPTx = u4Tmp & bMaskLWord;
	regHPRx = (u4Tmp & bMaskHWord)>>16;

	u4Tmp = rtw_read32(padapter, regLPTxRx);
	regLPTx = u4Tmp & bMaskLWord;
	regLPRx = (u4Tmp & bMaskHWord)>>16;

	pHalData->bt_coexist.halCoex8723.highPriorityTx = regHPTx;
	pHalData->bt_coexist.halCoex8723.highPriorityRx = regHPRx;
	pHalData->bt_coexist.halCoex8723.lowPriorityTx = regLPTx;
	pHalData->bt_coexist.halCoex8723.lowPriorityRx = regLPRx;

	RTPRINT(FBT, BT_TRACE, ("High Priority Tx/Rx= %d / %d\n", regHPTx, regHPRx));
	RTPRINT(FBT, BT_TRACE, ("Low Priority Tx/Rx= %d / %d\n", regLPTx, regLPRx));

	// reset counter
	//u1Tmp = rtw_read8(padapter, 0x76e);
	//DbgPrint("read 2 back 0x76e= 0x%x\n", u1Tmp);
	//u4Tmp |= BIT3;
	rtw_write8(padapter, 0x76e, 0xc);
}

// This function check if 8723 bt is disabled
static void btdm_BtEnableDisableCheck8723A(struct rtw_adapter *padapter)
{
	u8		btAlife = _TRUE;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);


#ifdef CHECK_BT_EXIST_FROM_REG
	u8		val8;

	// ox68[28]=1 => BT enable; otherwise disable
	val8 = rtw_read8(padapter, 0x6B);
	if (!(val8 & BIT(4))) btAlife = _FALSE;

	if (btAlife)
	{
		pHalData->bt_coexist.bCurBtDisabled = _FALSE;
//		RTPRINT(FBT, BT_TRACE, ("8723A BT is enabled !!\n"));
	}
	else
	{
		pHalData->bt_coexist.bCurBtDisabled = _TRUE;
//		RTPRINT(FBT, BT_TRACE, ("8723A BT is disabled !!\n"));
	}
#else
	if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0 &&
		pHalData->bt_coexist.halCoex8723.highPriorityRx == 0 &&
		pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0 &&
		pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0)
	{
		btAlife = _FALSE;
	}
	if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xeaea &&
		pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xeaea &&
		pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xeaea &&
		pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xeaea)
	{
		btAlife = _FALSE;
	}
	if (pHalData->bt_coexist.halCoex8723.highPriorityTx == 0xffff &&
		pHalData->bt_coexist.halCoex8723.highPriorityRx == 0xffff &&
		pHalData->bt_coexist.halCoex8723.lowPriorityTx == 0xffff &&
		pHalData->bt_coexist.halCoex8723.lowPriorityRx == 0xffff)
	{
		btAlife = _FALSE;
	}
	if (btAlife)
	{
		pHalData->bt_coexist.btActiveZeroCnt = 0;
		pHalData->bt_coexist.bCurBtDisabled = _FALSE;
		RTPRINT(FBT, BT_TRACE, ("8723A BT is enabled !!\n"));
	}
	else
	{
		pHalData->bt_coexist.btActiveZeroCnt++;
		RTPRINT(FBT, BT_TRACE, ("8723A bt all counters=0, %d times!!\n",
				pHalData->bt_coexist.btActiveZeroCnt));
		if (pHalData->bt_coexist.btActiveZeroCnt >= 2)
		{
			pHalData->bt_coexist.bCurBtDisabled = _TRUE;
			RTPRINT(FBT, BT_TRACE, ("8723A BT is disabled !!\n"));
		}
	}
#endif

	if (pHalData->bt_coexist.bCurBtDisabled == _FALSE) {
		if (BTDM_IsWifiConnectionExist(padapter) == _TRUE)
			BTDM_SetFwChnlInfo(padapter, RT_MEDIA_CONNECT);
		else
			BTDM_SetFwChnlInfo(padapter, RT_MEDIA_DISCONNECT);
	}

	if (pHalData->bt_coexist.bPreBtDisabled !=
		pHalData->bt_coexist.bCurBtDisabled)
	{
		RTPRINT(FBT, BT_TRACE, ("8723A BT is from %s to %s!!\n",
			(pHalData->bt_coexist.bPreBtDisabled ? "disabled":"enabled"),
			(pHalData->bt_coexist.bCurBtDisabled ? "disabled":"enabled")));
		pHalData->bt_coexist.bPreBtDisabled = pHalData->bt_coexist.bCurBtDisabled;
	}
}

static void btdm_BTCoexist8723AHandler(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;


	pHalData = GET_HAL_DATA(padapter);

	if (btdm_BtWifiAntNum(padapter) == Ant_x2)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], 2 Ant mechanism\n"));
		BTDM_2AntBtCoexist8723A(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], 1 Ant mechanism\n"));
		BTDM_1AntBtCoexist8723A(padapter);
	}

	if (!BTDM_IsSameCoexistState(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x\n",
			pHalData->bt_coexist.PreviousState,
			pHalData->bt_coexist.CurrentState));
		pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState;

		RTPRINT(FBT, BT_TRACE, ("["));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT30)
			RTPRINT(FBT, BT_TRACE, ("BT 3.0, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT20)
			RTPRINT(FBT, BT_TRACE, ("HT20, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT40)
			RTPRINT(FBT, BT_TRACE, ("HT40, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_LEGACY)
			RTPRINT(FBT, BT_TRACE, ("Legacy, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_LOW)
			RTPRINT(FBT, BT_TRACE, ("Rssi_Low, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_MEDIUM)
			RTPRINT(FBT, BT_TRACE, ("Rssi_Mid, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_HIGH)
			RTPRINT(FBT, BT_TRACE, ("Rssi_High, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_IDLE)
			RTPRINT(FBT, BT_TRACE, ("Wifi_Idle, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_UPLINK)
			RTPRINT(FBT, BT_TRACE, ("Wifi_Uplink, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_DOWNLINK)
			RTPRINT(FBT, BT_TRACE, ("Wifi_Downlink, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE)
			RTPRINT(FBT, BT_TRACE, ("BT_idle, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_HID)
			RTPRINT(FBT, BT_TRACE, ("PRO_HID, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_A2DP)
			RTPRINT(FBT, BT_TRACE, ("PRO_A2DP, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_PAN)
			RTPRINT(FBT, BT_TRACE, ("PRO_PAN, "));
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_SCO)
			RTPRINT(FBT, BT_TRACE, ("PRO_SCO, "));
		RTPRINT(FBT, BT_TRACE, ("]\n"));
	}
}

//============================================================
// extern function start with BTDM_
//============================================================
u32 BTDM_BtTxRxCounterH(	struct rtw_adapter *	padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u32	counters=0;

	counters = pHalData->bt_coexist.halCoex8723.highPriorityTx+
		pHalData->bt_coexist.halCoex8723.highPriorityRx ;
	return counters;
}

u32 BTDM_BtTxRxCounterL(	struct rtw_adapter *	padapter	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u32	counters=0;

	counters = pHalData->bt_coexist.halCoex8723.lowPriorityTx+
		pHalData->bt_coexist.halCoex8723.lowPriorityRx ;
	return counters;
}

void BTDM_SetFwChnlInfo(struct rtw_adapter *padapter, RT_MEDIA_STATUS mstatus)
{
//	PMGNT_INFO	pMgntInfo = &padapter->MgntInfo;
	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
	PBT30Info	pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT	pBtMgnt = &pBTInfo->BtMgnt;
	u8		H2C_Parameter[3] ={0};
	u8		chnl;


	// opMode
	if (RT_MEDIA_CONNECT == mstatus)
	{
		H2C_Parameter[0] = 0x1;	// 0: disconnected, 1:connected
	}

	if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == _TRUE)
	{
		// channel
		chnl = pmlmeext->cur_channel;
		if (BTDM_IsHT40(padapter))
		{
			if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
			{
				chnl -= 2;
			}
			else if (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
			{
				chnl += 2;
			}
		}
		H2C_Parameter[1] = chnl;
//		RTPRINT(FBT, BT_TRACE, ("[BTCoex], pmlmeext->cur_channel=0x%x  pmlmeext->cur_ch_offset=0x%x chnl=0x%x\n",pmlmeext->cur_channel,pmlmeext->cur_ch_offset,chnl ));
	}
	else	// check if HS link is exists
	{
		// channel
		if (BT_Operation(padapter))
			H2C_Parameter[1] = pBtMgnt->BTChannel;
		else
			H2C_Parameter[1] = pmlmeext->cur_channel;
	}

	if (BTDM_IsHT40(padapter))
	{
		H2C_Parameter[2] = 0x30;
	}
	else
	{
		H2C_Parameter[2] = 0x20;
	}

//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x19=0x%x\n",
//		H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));

	FillH2CCmd(padapter, 0x19, 3, H2C_Parameter);
}

u8 BTDM_IsWifiConnectionExist(struct rtw_adapter *padapter)
{
	u8 bRet = _FALSE;


	if (BTHCI_HsConnectionEstablished(padapter))
		bRet = _TRUE;

	if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == _TRUE)
		bRet = _TRUE;

	return bRet;
}

void BTDM_SetFw3a(
	struct rtw_adapter *	padapter,
	u8		byte1,
	u8		byte2,
	u8		byte3,
	u8		byte4,
	u8		byte5
	)
{
	u8			H2C_Parameter[5] = {0};

	if (BTDM_1Ant8723A(padapter) == _TRUE)
	{
		if ((check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _FALSE) &&
			(get_fwstate(&padapter->mlmepriv) != WIFI_NULL_STATE)) // for softap mode
		{
			PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
			PBT_COEXIST_8723A pBtCoex = &pHalData->bt_coexist.halCoex8723;
			u8 BtState = pBtCoex->c2hBtInfo;

			if ((BtState != BT_INFO_STATE_NO_CONNECTION) &&
				(BtState != BT_INFO_STATE_CONNECT_IDLE))
			{
				if (byte1 & BIT(4))
				{
					byte1 &= ~BIT(4);
					byte1 |= BIT(5);
				}

				byte5 |= BIT(5);
				if (byte5 & BIT(6))
				{
					byte5 &= ~BIT(6);
				}
			}
		}
	}

	H2C_Parameter[0] = byte1;
	H2C_Parameter[1] = byte2;
	H2C_Parameter[2] = byte3;
	H2C_Parameter[3] = byte4;
	H2C_Parameter[4] = byte5;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], FW write 0x3a(5bytes)=0x%02x%08x\n",
		H2C_Parameter[0],
		H2C_Parameter[1]<<24|H2C_Parameter[2]<<16|H2C_Parameter[3]<<8|H2C_Parameter[4]));

	FillH2CCmd(padapter, 0x3a, 5, H2C_Parameter);
}

static void BTDM_ForceBtCoexMechanism(struct rtw_adapter *padapter, u8 type)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);


	pHalData->bt_coexist.halCoex8723.bForceFwBtInfo = type;

	if (pHalData->bt_coexist.halCoex8723.bForceFwBtInfo)
	{
		DbgPrint("cosa force bt info from wifi fw !!!\n");
	}
	else
	{
		DbgPrint("cosa force bt coexist bt info from bt stack\n");
	}
}

void BTDM_QueryBtInformation(struct rtw_adapter *padapter)
{
	u8 H2C_Parameter[1] = {0};
	PHAL_DATA_TYPE pHalData;
	PBT_COEXIST_8723A pBtCoex;


	pHalData = GET_HAL_DATA(padapter);
	pBtCoex = &pHalData->bt_coexist.halCoex8723;

	if (BT_IsBtDisabled(padapter) == _TRUE)
	{
		pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED;
		pBtCoex->bC2hBtInfoReqSent = _FALSE;
		return;
	}

	if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED)
		pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION;

	if (pBtCoex->bC2hBtInfoReqSent == _TRUE)
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], didn't recv previous BtInfo report!\n"));
	}
	else
	{
		pBtCoex->bC2hBtInfoReqSent = _TRUE;
	}

	H2C_Parameter[0] |= BIT(0);	// trigger

//	RTPRINT(FBT, BT_TRACE, ("[BTCoex], Query Bt information, write 0x38=0x%x\n",
//		H2C_Parameter[0]));

	FillH2CCmd(padapter, 0x38, 1, H2C_Parameter);
}

void BTDM_SetSwRfRxLpfCorner(struct rtw_adapter *padapter, u8 type)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (BT_RF_RX_LPF_CORNER_SHRINK == type)
	{
		//Shrink RF Rx LPF corner
		RTPRINT(FBT, BT_TRACE, ("Shrink RF Rx LPF corner!!\n"));
		PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, 0xf0ff7);
		pHalData->bt_coexist.bSWCoexistAllOff = _FALSE;
	}
	else if (BT_RF_RX_LPF_CORNER_RESUME == type)
	{
		//Resume RF Rx LPF corner
		RTPRINT(FBT, BT_TRACE, ("Resume RF Rx LPF corner!!\n"));
		PHY_SetRFReg(padapter, PathA, 0x1e, bRFRegOffsetMask, pHalData->bt_coexist.BtRfRegOrigin1E);
	}
}

void
BTDM_SetSwPenaltyTxRateAdaptive(
	struct rtw_adapter *	padapter,
	u8		raType
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8	tmpU1;

	tmpU1 = rtw_read8(padapter, 0x4fd);
	tmpU1 |= BIT(0);
	if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == raType)
	{
//		RTPRINT(FBT, BT_TRACE, ("Tx rate adaptive, set low penalty!!\n"));
		tmpU1 &= ~BIT(2);
		pHalData->bt_coexist.bSWCoexistAllOff = _FALSE;
	}
	else if (BT_TX_RATE_ADAPTIVE_NORMAL == raType)
	{
//		RTPRINT(FBT, BT_TRACE, ("Tx rate adaptive, set normal!!\n"));
		tmpU1 |= BIT(2);
	}

	rtw_write8(padapter, 0x4fd, tmpU1);
}

void BTDM_SetFwDecBtPwr(struct rtw_adapter *padapter, u8 bDecBtPwr)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			H2C_Parameter[1] = {0};


	H2C_Parameter[0] = 0;

	if (bDecBtPwr)
	{
		H2C_Parameter[0] |= BIT(1);
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], decrease Bt Power : %s, write 0x21=0x%x\n",
		(bDecBtPwr? "Yes!!":"No!!"), H2C_Parameter[0]));

	FillH2CCmd(padapter, 0x21, 1, H2C_Parameter);
}

u8 BTDM_BtProfileSupport(struct rtw_adapter *padapter)
{
	u8			bRet = _FALSE;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);


	if (pBtMgnt->bSupportProfile &&
		!pHalData->bt_coexist.halCoex8723.bForceFwBtInfo)
	{
		bRet = _TRUE;
	}

	return bRet;
}

static void BTDM_AdjustForBtOperation8723A(struct rtw_adapter *padapter)
{
	//BTDM_2AntAdjustForBtOperation8723(padapter);
}

static void BTDM_FwC2hBtRssi8723A(struct rtw_adapter *padapter, u8 *tmpBuf)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			percent=0, u1tmp=0;

	u1tmp = tmpBuf[0];
	percent = u1tmp*2+10;

	pHalData->bt_coexist.halCoex8723.btRssi = percent;
//	RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI=%d\n", percent));
}

static void
BTDM_FwC2hBtInfo8723A(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_COEXIST_8723A pBtCoex;
	u8	i;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtCoex = &pHalData->bt_coexist.halCoex8723;

	pBtCoex->bC2hBtInfoReqSent = _FALSE;

	RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT info[%d]=[", length));

	pBtCoex->btRetryCnt = 0;
	for (i=0; i<length; i++)
	{
		switch (i)
		{
			case 0:
				pBtCoex->c2hBtInfoOriginal = tmpBuf[i];
				break;
			case 1:
				pBtCoex->btRetryCnt = tmpBuf[i];
				break;
			case 2:
				BTDM_FwC2hBtRssi8723A(padapter, &tmpBuf[i]);
				break;
			case 3:
				pBtCoex->btInfoExt=tmpBuf[i]&BIT(0);
				break;
		}

		if (i == length-1)
		{
			RTPRINT(FBT, BT_TRACE, ("0x%02x]\n", tmpBuf[i]));
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("0x%02x, ", tmpBuf[i]));
		}
	}
	RTPRINT(FBT, BT_TRACE, ("[BTC2H], BT RSSI=%d\n", pBtCoex->btRssi));
	if (pBtCoex->btInfoExt)
		RTPRINT(FBT, BT_TRACE, ("[BTC2H], pBtCoex->btInfoExt=%x\n", pBtCoex->btInfoExt));

	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntFwC2hBtInfo8723A(padapter);
	else
		BTDM_2AntFwC2hBtInfo8723A(padapter);

	if (pBtMgnt->ExtConfig.bManualControl)
	{
		RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __FUNCTION__));
		return;
	}

	btdm_BTCoexist8723AHandler(padapter);
}

static void BTDM_Display8723ABtCoexInfo(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT_COEXIST_8723A	pBtCoex = &pHalData->bt_coexist.halCoex8723;
	PBT30Info			pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT			pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG				pBtDbg = &pBTInfo->BtDbg;
	u8			u1Tmp, u1Tmp1, u1Tmp2, i, btInfoExt, psTdmaCase=0;
	u32			u4Tmp[4];
	u8			antNum=Ant_x2;

	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n ============[BT Coexist info]============");
	DCMD_Printf(btCoexDbgBuf);

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n BT not exists !!!");
		DCMD_Printf(btCoexDbgBuf);
		return;
	}

	antNum = btdm_BtWifiAntNum(padapter);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d/%d ", "Ant mechanism PG/Now run :", \
		((pHalData->bt_coexist.BT_Ant_Num==Ant_x2)? 2:1), ((antNum==Ant_x2)? 2:1));
	DCMD_Printf(btCoexDbgBuf);

	if (pBtMgnt->ExtConfig.bManualControl)
	{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "[Action Manual control]!!");
		DCMD_Printf(btCoexDbgBuf);
	}
	else
	{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", \
			((pBtMgnt->bSupportProfile)? "Yes":"No"), pBtMgnt->ExtConfig.HCIExtensionVer);
		DCMD_Printf(btCoexDbgBuf);
	}

	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = / %d", "Dot11 channel / BT channel", \
		pBtMgnt->BTChannel);
		DCMD_Printf(btCoexDbgBuf);

	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d / %d", "Wifi/BT/HS rssi", \
		BTDM_GetRxSS(padapter),
		pHalData->bt_coexist.halCoex8723.btRssi,
		pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB);
			DCMD_Printf(btCoexDbgBuf);

	if(!pBtMgnt->ExtConfig.bManualControl)
		{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s / %s ", "WIfi status", \
			((BTDM_Legacy(padapter))? "Legacy": (((BTDM_IsHT40(padapter))? "HT40":"HT20"))),
			((!BTDM_IsWifiBusy(padapter))? "idle": ((BTDM_IsWifiUplink(padapter))? "uplink":"downlink")));
		DCMD_Printf(btCoexDbgBuf);

		if(pBtMgnt->bSupportProfile)
		{
			rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", \
				((BTHCI_CheckProfileExist(padapter, BT_PROFILE_SCO))? 1: 0),
				((BTHCI_CheckProfileExist(padapter, BT_PROFILE_HID))? 1: 0),
				((BTHCI_CheckProfileExist(padapter, BT_PROFILE_PAN))? 1: 0),
				((BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP))? 1: 0) );
		DCMD_Printf(btCoexDbgBuf);

			for (i=0; i<pBtMgnt->ExtConfig.NumberOfHandle; i++)
			{
				if (pBtMgnt->ExtConfig.HCIExtensionVer >= 1)
				{
					rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s/ %s", "Bt link type/spec/role", \
						BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile],
						BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec],
						BtLinkRoleString[pBtMgnt->ExtConfig.linkInfo[i].linkRole]);
					DCMD_Printf(btCoexDbgBuf);

					btInfoExt = pHalData->bt_coexist.halCoex8723.btInfoExt;
					rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s", "A2DP rate", \
						(btInfoExt&BIT0)? "Basic rate":"EDR rate");
					DCMD_Printf(btCoexDbgBuf);
				}
				else
				{
					rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %s/ %s", "Bt link type/spec", \
						BtProfileString[pBtMgnt->ExtConfig.linkInfo[i].BTProfile],
						BtSpecString[pBtMgnt->ExtConfig.linkInfo[i].BTCoreSpec]);
					DCMD_Printf(btCoexDbgBuf);
				}
			}
		}
	}

	// Sw mechanism
	if (!pBtMgnt->ExtConfig.bManualControl)
	{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Sw BT Coex mechanism]============");
		DCMD_Printf(btCoexDbgBuf);
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "AGC Table", \
			pBtCoex->btdm2Ant.bCurAgcTableEn);
		DCMD_Printf(btCoexDbgBuf);
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "ADC Backoff", \
			pBtCoex->btdm2Ant.bCurAdcBackOff);
		DCMD_Printf(btCoexDbgBuf);
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Low penalty RA", \
			pBtCoex->btdm2Ant.bCurLowPenaltyRa);
		DCMD_Printf(btCoexDbgBuf);
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "RF Rx LPF Shrink", \
			pBtCoex->btdm2Ant.bCurRfRxLpfShrink);
		DCMD_Printf(btCoexDbgBuf);
	}
	u4Tmp[0] = PHY_QueryRFReg(padapter, PathA, 0x1e, 0xff0);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x", "RF-A, 0x1e[11:4]/original val", \
		u4Tmp[0], pHalData->bt_coexist.BtRfRegOrigin1E);
	DCMD_Printf(btCoexDbgBuf);

	// Fw mechanism
	if (!pBtMgnt->ExtConfig.bManualControl)
	{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Fw BT Coex mechanism]============");
		DCMD_Printf(btCoexDbgBuf);
	}
	if (!pBtMgnt->ExtConfig.bManualControl)
	{
		if(btdm_BtWifiAntNum(padapter) == Ant_x1)
			psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm1Ant.curPsTdma;
		else
			psTdmaCase = pHalData->bt_coexist.halCoex8723.btdm2Ant.curPsTdma;
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %02x %02x %02x %02x %02x case-%d", "PS TDMA(0x3a)", \
			pHalData->bt_coexist.fw3aVal[0], pHalData->bt_coexist.fw3aVal[1],
			pHalData->bt_coexist.fw3aVal[2], pHalData->bt_coexist.fw3aVal[3],
			pHalData->bt_coexist.fw3aVal[4], psTdmaCase);
		DCMD_Printf(btCoexDbgBuf);

		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d ", "Decrease Bt Power", \
			pBtCoex->btdm2Ant.bCurDecBtPwr);
		DCMD_Printf(btCoexDbgBuf);
	}
	u1Tmp = rtw_read8(padapter, 0x778);
	u1Tmp1 = rtw_read8(padapter, 0x783);
	u1Tmp2 = rtw_read8(padapter, 0x796);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", "0x778/ 0x783/ 0x796", \
		u1Tmp, u1Tmp1, u1Tmp2);
	DCMD_Printf(btCoexDbgBuf);

	if (!pBtMgnt->ExtConfig.bManualControl)
	{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x / 0x%x", "Sw DacSwing Ctrl/Val", \
			pBtCoex->btdm2Ant.bCurDacSwingOn, pBtCoex->btdm2Ant.curDacSwingLvl);
		DCMD_Printf(btCoexDbgBuf);
	}
	u4Tmp[0] =  rtw_read32(padapter, 0x880);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x880", \
		u4Tmp[0]);
	DCMD_Printf(btCoexDbgBuf);

	// Hw mechanism
	if (!pBtMgnt->ExtConfig.bManualControl)
	{
		rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s", "============[Hw BT Coex mechanism]============");
		DCMD_Printf(btCoexDbgBuf);
	}

	u1Tmp = rtw_read8(padapter, 0x40);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x40", \
		u1Tmp);
	DCMD_Printf(btCoexDbgBuf);

	u4Tmp[0] = rtw_read32(padapter, 0x550);
	u1Tmp = rtw_read8(padapter, 0x522);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/0x%x", "0x550(bcn contrl)/0x522", \
		u4Tmp[0], u1Tmp);
	DCMD_Printf(btCoexDbgBuf);

	u4Tmp[0] = rtw_read32(padapter, 0x484);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x484(rate adaptive)", \
		u4Tmp[0]);
	DCMD_Printf(btCoexDbgBuf);

	u4Tmp[0] = rtw_read32(padapter, 0x50);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0xc50(dig)", \
		u4Tmp[0]);
	DCMD_Printf(btCoexDbgBuf);

	u4Tmp[0] = rtw_read32(padapter, 0xda0);
	u4Tmp[1] = rtw_read32(padapter, 0xda4);
	u4Tmp[2] = rtw_read32(padapter, 0xda8);
	u4Tmp[3] = rtw_read32(padapter, 0xdac);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0xda0/0xda4/0xda8/0xdac(FA cnt)", \
		u4Tmp[0], u4Tmp[1], u4Tmp[2], u4Tmp[3]);
	DCMD_Printf(btCoexDbgBuf);

	u4Tmp[0] = rtw_read32(padapter, 0x6c0);
	u4Tmp[1] = rtw_read32(padapter, 0x6c4);
	u4Tmp[2] = rtw_read32(padapter, 0x6c8);
	u1Tmp = rtw_read8(padapter, 0x6cc);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", \
		u4Tmp[0], u4Tmp[1], u4Tmp[2], u1Tmp);
	DCMD_Printf(btCoexDbgBuf);

	//u4Tmp = rtw_read32(padapter, 0x770);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x770(Hi pri Rx[31:16]/Tx[15:0])", \
		pHalData->bt_coexist.halCoex8723.highPriorityRx,
		pHalData->bt_coexist.halCoex8723.highPriorityTx);
	DCMD_Printf(btCoexDbgBuf);
	//u4Tmp = rtw_read32(padapter, 0x774);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = %d / %d", "0x774(Lo pri Rx[31:16]/Tx[15:0])", \
		pHalData->bt_coexist.halCoex8723.lowPriorityRx,
		pHalData->bt_coexist.halCoex8723.lowPriorityTx);
	DCMD_Printf(btCoexDbgBuf);

	// Tx mgnt queue hang or not, 0x41b should = 0xf, ex: 0xd ==>hang
	u1Tmp = rtw_read8(padapter, 0x41b);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "0x41b (hang chk == 0xf)", \
		u1Tmp);
	DCMD_Printf(btCoexDbgBuf);
	rsprintf(btCoexDbgBuf, BT_TMP_BUF_SIZE, "\r\n %-35s = 0x%x", "lastHMEBoxNum", \
		pHalData->LastHMEBoxNum);
	DCMD_Printf(btCoexDbgBuf);
}

static void
BTDM_8723ASignalCompensation(struct rtw_adapter *padapter,
			     u8 *rssi_wifi, u8 *rssi_bt)
{
	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntSignalCompensation(padapter, rssi_wifi, rssi_bt);
}

static void BTDM_8723AInit(struct rtw_adapter *padapter)
{
	if (btdm_BtWifiAntNum(padapter) == Ant_x2)
		BTDM_2AntParaInit(padapter);
	else
		BTDM_1AntParaInit(padapter);
}

static void BTDM_HWCoexAllOff8723A(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x2)
		BTDM_2AntHwCoexAllOff8723A(padapter);
}

static void BTDM_FWCoexAllOff8723A(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x2)
		BTDM_2AntFwCoexAllOff8723A(padapter);
}

static void BTDM_SWCoexAllOff8723A(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x2)
		BTDM_2AntSwCoexAllOff8723A(padapter);
}

static void
BTDM_Set8723ABtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT_COEXIST_8723A	pBtCoex = &pHalData->bt_coexist.halCoex8723;

	if (antNum == 1)
	{
		pBtCoex->TotalAntNum = Ant_x1;
	}
	else if (antNum == 2)
	{
		pBtCoex->TotalAntNum = Ant_x2;
	}
}

void BTDM_LpsLeave(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntLpsLeave(padapter);
}

static void BTDM_ForHalt8723A(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntForHalt(padapter);
}

static void BTDM_WifiScanNotify8723A(struct rtw_adapter *padapter, u8 scanType)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntWifiScanNotify(padapter, scanType);
}

static void
BTDM_WifiAssociateNotify8723A(struct rtw_adapter *padapter, u8 action)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntWifiAssociateNotify(padapter, action);
}

static void
BTDM_MediaStatusNotify8723A(struct rtw_adapter *padapter,
			    RT_MEDIA_STATUS mstatus)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;


	RTPRINT(FBT, BT_TRACE, ("[BTCoex], MediaStatusNotify, %s\n", mstatus?"connect":"disconnect"));

	BTDM_SetFwChnlInfo(padapter, mstatus);

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntMediaStatusNotify(padapter, mstatus);
}

static void BTDM_ForDhcp8723A(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		BTDM_1AntForDhcp(padapter);
}

u8 BTDM_1Ant8723A(struct rtw_adapter *padapter)
{
	if (btdm_BtWifiAntNum(padapter) == Ant_x1)
		return _TRUE;
	else
		return _FALSE;
}

static void BTDM_BTCoexist8723A(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_COEXIST_8723A pBtCoex;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtCoex = &pHalData->bt_coexist.halCoex8723;

	RTPRINT(FBT, BT_TRACE, ("[BTCoex], beacon RSSI=0x%x(%d)\n",
		pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB,
		pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB));

	btdm_BtHwCountersMonitor(padapter);
	btdm_BtEnableDisableCheck8723A(padapter);

	if (pBtMgnt->ExtConfig.bManualControl)
	{
		RTPRINT(FBT, BT_TRACE, ("%s: Action Manual control!!\n", __FUNCTION__));
		return;
	}

	if (pBtCoex->bC2hBtInfoReqSent == _TRUE)
	{
		if (BT_IsBtDisabled(padapter) == _TRUE)
		{
			pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED;
		}
		else
		{
			if (pBtCoex->c2hBtInfo == BT_INFO_STATE_DISABLED)
				pBtCoex->c2hBtInfo = BT_INFO_STATE_NO_CONNECTION;
		}

		btdm_BTCoexist8723AHandler(padapter);
	}
	else if (BT_IsBtDisabled(padapter) == _TRUE)
	{
		pBtCoex->c2hBtInfo = BT_INFO_STATE_DISABLED;
		btdm_BTCoexist8723AHandler(padapter);
	}

	BTDM_QueryBtInformation(padapter);
}

// ===== End of sync from SD7 driver HAL/BTCoexist/HalBtc8723.c =====
#endif

#ifdef __HALBTCCSR1ANT_C__ // HAL/BTCoexist/HalBtcCsr1Ant.c
// ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c =====

//============================================================
// local function start with btdm_
//============================================================
static void btdm_WriteReg860(struct rtw_adapter *padapter, u16 value)
{
	RTPRINT(FBT, BT_TRACE, ("btdm_WriteReg860(), value = 0x%x\n", value));
	PHY_SetBBReg(padapter, 0x860, bMaskLWord, value);
}

static void btdm_CheckCounterOnly1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	u32			BT_Polling, Ratio_Act, Ratio_STA;
	u32			BT_Active, BT_State;
	u32			regBTActive = 0, regBTState = 0, regBTPolling=0;

	if (!pHalData->bt_coexist.BluetoothCoexist)
		return;
	if (pHalData->bt_coexist.BT_CoexistType != BT_CSR_BC8)
		return;
	if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1)
		return;

	//
	// The following we only consider CSR BC8 and fw version should be >= 62
	//
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], FirmwareVersion = 0x%x(%d)\n",
		pHalData->FirmwareVersion, pHalData->FirmwareVersion));
	{
		regBTActive = REG_BT_ACTIVE;
		regBTState = REG_BT_STATE;
		if (pHalData->FirmwareVersion >= FW_VER_BT_REG1)
			regBTPolling = REG_BT_POLLING1;
		else
			regBTPolling = REG_BT_POLLING;
	}

	BT_Active = rtw_read32(padapter, regBTActive);
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Active(0x%x)=%x\n", regBTActive, BT_Active));
	BT_Active = BT_Active & 0x00ffffff;

	BT_State = rtw_read32(padapter, regBTState);
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_State(0x%x)=%x\n", regBTState, BT_State));
	BT_State = BT_State & 0x00ffffff;

	BT_Polling = rtw_read32(padapter, regBTPolling);
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Polling(0x%x)=%x\n", regBTPolling, BT_Polling));

	Ratio_Act = BT_Active*1000/BT_Polling;
	Ratio_STA = BT_State*1000/BT_Polling;

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_Act=%d\n", Ratio_Act));
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_STA=%d\n", Ratio_STA));
}

static u8
btdm_IsSingleAnt(
	struct rtw_adapter *	padapter,
	u8		bSingleAntOn,
	u8		bInterruptOn,
	u8		bMultiNAVOn
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8 bRet = _FALSE;

	if ((pHalData->bt_coexist.bInterruptOn == bInterruptOn) &&
		(pHalData->bt_coexist.bSingleAntOn == bSingleAntOn) &&
		(pHalData->bt_coexist.bMultiNAVOn == bMultiNAVOn))
	{
		bRet = _TRUE;
	}

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], current SingleAntenna = [%s:%s:%s]\n",
		pHalData->bt_coexist.bSingleAntOn?"ON":"OFF",
		pHalData->bt_coexist.bInterruptOn?"ON":"OFF",
		pHalData->bt_coexist.bMultiNAVOn?"ON":"OFF"));

	return bRet;
}

static u8 btdm_IsBalance(struct rtw_adapter *padapter, u8 bBalanceOn)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_IsBalance(), bBalanceOn=%s\n",
		bBalanceOn?"ON":"OFF"));

	if (pHalData->bt_coexist.bBalanceOn == bBalanceOn)
	{
		return _TRUE;
	}
	return _FALSE;
}

static u8 btdm_EarphoneSpecDetect(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	switch (pHalData->bt_coexist.A2DPState)
	{
		case BT_A2DP_STATE_NOT_ENTERED:
			{
				RTPRINT(FBT, BT_TRACE, (" set default balance = ON, for WLANActH=12, WLANActL=24!!\n"));
				pHalData->bt_coexist.PreWLANActH = 12;
				pHalData->bt_coexist.PreWLANActL = 24;
				pHalData->bt_coexist.WLANActH = 12;
				pHalData->bt_coexist.WLANActL = 24;
				BTDM_Balance(padapter, _TRUE, pHalData->bt_coexist.WLANActH, pHalData->bt_coexist.WLANActL);
				BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
				pHalData->bt_coexist.A2DPState = BT_A2DP_STATE_DETECTING;
			}
			break;

		case BT_A2DP_STATE_DETECTING:
			{
				// 32,12; the most critical for BT
				// 12,24
				// 0,0
				if (btdm_IsSingleAnt(padapter, _TRUE, _FALSE, _FALSE))
				{
					if ((pHalData->bt_coexist.PreWLANActH == 0) &&
						(pHalData->bt_coexist.PreWLANActL == 0))
					{
						RTPRINT(FBT, BT_TRACE, ("[WLANActH, WLANActL] = [0,0]\n"));
						pHalData->bt_coexist.WLANActH = 12;
						pHalData->bt_coexist.WLANActL = 24;
					}
					else if ((pHalData->bt_coexist.PreWLANActH == 12) &&
						(pHalData->bt_coexist.PreWLANActL == 24))
					{
						RTPRINT(FBT, BT_TRACE, ("[WLANActH, WLANActL] = [12,24]\n"));
						if (((pHalData->bt_coexist.Ratio_Tx>600) &&
							(pHalData->bt_coexist.Ratio_PRI>500)) ||
							((pHalData->bt_coexist.Ratio_Tx*10 ) >
							(pHalData->bt_coexist.Ratio_PRI*15)))
						{
							RTPRINT(FBT, BT_TRACE, ("Ratio_Act > 600 && Ratio_STA > 500 or "));
							RTPRINT(FBT, BT_TRACE, ("Ratio_Act/Ratio_STA > 1.5\n"));
							pHalData->bt_coexist.WLANActH = 12;
							pHalData->bt_coexist.WLANActL = 24;
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, (" cosa set to 32/12\n "));
							pHalData->bt_coexist.WLANActH = 32;
							pHalData->bt_coexist.WLANActL = 12;
						}
					}
					else if ((pHalData->bt_coexist.PreWLANActH == 32) &&
							(pHalData->bt_coexist.PreWLANActL == 12))
					{
						RTPRINT(FBT, BT_TRACE, ("[WLANActH, WLANActL] = [32,12]\n"));
						if (((pHalData->bt_coexist.Ratio_Tx>650) &&
							(pHalData->bt_coexist.Ratio_PRI>550)) ||
							((pHalData->bt_coexist.Ratio_Tx*10 ) >
							(pHalData->bt_coexist.Ratio_PRI*15)))
						{
							RTPRINT(FBT, BT_TRACE, ("Ratio_Act > 650 && Ratio_STA > 550 or "));
							RTPRINT(FBT, BT_TRACE, ("Ratio_Act/Ratio_STA > 1.5\n"));
							pHalData->bt_coexist.WLANActH = 12;
							pHalData->bt_coexist.WLANActL = 24;
						}
					}
					if ((pHalData->bt_coexist.PreWLANActH != pHalData->bt_coexist.WLANActH) ||
						(pHalData->bt_coexist.PreWLANActL != pHalData->bt_coexist.WLANActL))
					{
						BTDM_Balance(padapter, _TRUE, pHalData->bt_coexist.WLANActH, pHalData->bt_coexist.WLANActL);
						pHalData->bt_coexist.PreWLANActH = pHalData->bt_coexist.WLANActH;
						pHalData->bt_coexist.PreWLANActL = pHalData->bt_coexist.WLANActL;
					}
				}

				RTPRINT(FBT, BT_TRACE, ("earphone detected result: WLANActH=%d, WLANActL=%d\n",
					pHalData->bt_coexist.WLANActH, pHalData->bt_coexist.WLANActL));
			}
			break;

		case BT_A2DP_STATE_DETECTED:
			break;

		default:
			RT_ASSERT(_FALSE, ("btdm_EarphoneSpecDetect(), unknown case\n"));
			break;
	}
	return _TRUE;
}

//==============================================================
//
// Note:
// In the following, FW should be done before SW mechanism.
//
//==============================================================

static void btdm_SCOActionBC81Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	u8	btRssiState;

	if ((pmlmepriv->LinkDetectInfo.bTxBusyTraffic) ||
		!(pmlmepriv->LinkDetectInfo.bBusyTraffic))
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi Uplink or Wifi is idle\n"));
		if (BTDM_IsSameCoexistState(padapter))
				return;
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
	}
	else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));

		if (btdm_IsSingleAnt(padapter, _FALSE, _FALSE, _FALSE))
		{
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_20, 0);
			if (BTDM_IsSameCoexistState(padapter))
				return;
			if ((btRssiState == BT_RSSI_STATE_LOW) ||
				(btRssiState == BT_RSSI_STATE_STAY_LOW))
			{
				BTDM_Balance(padapter, _FALSE, 0, 0);
				BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
			}
		}
		else
		{
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_45, 0);
			if (BTDM_IsSameCoexistState(padapter))
				return;
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_Balance(padapter, _FALSE, 0, 0);
				BTDM_SingleAnt(padapter, _FALSE, _FALSE, _FALSE);
			}
			else
			{
				BTDM_Balance(padapter, _FALSE, 0, 0);
				BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
			}
		}
	}
}

static u8 btdm_SCOAction1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.NumberOfSCO > 0)
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO;
		btdm_SCOActionBC81Ant(padapter);
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_SCO;
		return _FALSE;
	}
}

static void btdm_HIDActionBC81Ant(struct rtw_adapter *padapter)
{
	BTDM_Balance(padapter, _FALSE, 0, 0);
	BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
}

static u8 btdm_HIDAction1Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && pBtMgnt->ExtConfig.NumberOfHandle==1)
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_PAN;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_A2DP;
		btdm_HIDActionBC81Ant(padapter);
		return _TRUE;
	}
	else
	{
		return _FALSE;
	}
}

static void btdm_A2DPActionBC81Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pBtMgnt->ExtConfig.bBTBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));

		// We have to detect BT earphone spec first.
		btdm_EarphoneSpecDetect(padapter);

		if (!BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			if (btdm_IsSingleAnt(padapter, _FALSE, _FALSE, _FALSE))
			{
				btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_30, 0);
				if (BTDM_IsSameCoexistState(padapter))
					return;

				if ((btRssiState == BT_RSSI_STATE_LOW) ||
					(btRssiState == BT_RSSI_STATE_STAY_LOW))
				{
					BTDM_Balance(padapter, _TRUE, pHalData->bt_coexist.WLANActH, pHalData->bt_coexist.WLANActL);
					BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
				}
			}
			else
			{
				btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_55, 0);
				if (BTDM_IsSameCoexistState(padapter))
					return;

				if ((btRssiState == BT_RSSI_STATE_HIGH) ||
					(btRssiState == BT_RSSI_STATE_STAY_HIGH))
				{
					BTDM_Balance(padapter, _FALSE, 0, 0);
					BTDM_SingleAnt(padapter, _FALSE, _FALSE, _FALSE);
				}
				else
				{
					BTDM_Balance(padapter, _TRUE, pHalData->bt_coexist.WLANActH, pHalData->bt_coexist.WLANActL);
					BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
				}
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			if (BTDM_IsSameCoexistState(padapter))
				return;
			BTDM_Balance(padapter, _TRUE, pHalData->bt_coexist.WLANActH, pHalData->bt_coexist.WLANActL);
			BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle!\n"));
		pHalData->bt_coexist.A2DPState = BT_A2DP_STATE_NOT_ENTERED;
		if (pHalData->bt_coexist.Ratio_PRI > 3)
		{
			RTPRINT(FBT, BT_TRACE, ("Ratio_STA > 3\n"));
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
	}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("Ratio_STA <= 3\n"));
			BTDM_Balance(padapter, _TRUE, 32, 5);
			BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
		}
	}
}

static u8 btdm_A2DPAction1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (BTHCI_CheckProfileExist(padapter, BT_PROFILE_A2DP) && pBtMgnt->ExtConfig.NumberOfHandle==1)
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_HID;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_PAN;
		btdm_A2DPActionBC81Ant(padapter);
		return _TRUE;
	}
	else
	{
		return _FALSE;
	}
}

static void btdm_PANActionBC81Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pBtMgnt->ExtConfig.bBTBusy && !pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && [BT 2.1]\n"));

		if (!BTDM_IsHT40(padapter))
			{
				RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
				if (btdm_IsSingleAnt(padapter, _FALSE, _FALSE, _FALSE))
				{
				btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_20, 0);
					if (BTDM_IsSameCoexistState(padapter))
						return;

					if ((btRssiState == BT_RSSI_STATE_LOW) ||
						(btRssiState == BT_RSSI_STATE_STAY_LOW))
					{
					BTDM_Balance(padapter, _TRUE, 0x1c, 0x20);
					BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
					}
				}
				else
				{
					btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_50, 0);
					if (BTDM_IsSameCoexistState(padapter))
						return;
					if ((btRssiState == BT_RSSI_STATE_HIGH) ||
						(btRssiState == BT_RSSI_STATE_STAY_HIGH))
					{
						BTDM_Balance(padapter, _FALSE, 0, 0);
						BTDM_SingleAnt(padapter, _FALSE, _FALSE, _FALSE);
					}
					else
					{
					BTDM_Balance(padapter, _TRUE, 0x1c, 0x20);
					BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
				}
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			if ((pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic) &&
				(pmlmepriv->LinkDetectInfo.bTxBusyTraffic))
			{
				RTPRINT(FBT, BT_TRACE, ("BT is Downlink and Wifi is Uplink\n"));
				if (btdm_IsSingleAnt(padapter, _FALSE, _FALSE, _FALSE))
				{
					btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_20, 0);
					if (BTDM_IsSameCoexistState(padapter))
						return;
					if ((btRssiState == BT_RSSI_STATE_LOW) ||
						(btRssiState == BT_RSSI_STATE_STAY_LOW))
					{
						BTDM_Balance(padapter, _TRUE, 0x1c, 0x20);
						BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
					}
				}
				else
				{
					btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_45, 0);
					if (BTDM_IsSameCoexistState(padapter))
						return;
					if ((btRssiState == BT_RSSI_STATE_HIGH) ||
						(btRssiState == BT_RSSI_STATE_STAY_HIGH))
					{
						BTDM_Balance(padapter, _FALSE, 0, 0);
						BTDM_SingleAnt(padapter, _FALSE, _FALSE, _FALSE);
					}
					else
					{
						BTDM_Balance(padapter, _TRUE, 0x1c, 0x20);
						BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
					}
				}
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("BT Uplink or BTdownlink+Wifi downlink\n"));
				BTDM_Balance(padapter, _TRUE, 0x1c, 0x20);
				BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
			}
		}
	}
	else if (pBtMgnt->ExtConfig.bBTBusy && pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && [BT 3.0]\n"));
		BTDM_FWCoexAllOff(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle\n"));
		BTDM_Balance(padapter, _TRUE, 32, 5);
		BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
	}
}

static u8 btdm_PANAction1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) && pBtMgnt->ExtConfig.NumberOfHandle==1)
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_HID;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_A2DP;
		btdm_PANActionBC81Ant(padapter);
		return _TRUE;
	}
	else
	{
		return _FALSE;
	}
}

static void btdm_HIDA2DPActionBC81Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bBTBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));
		BTDM_Balance(padapter, _TRUE, 0x5, 0x1a);
		BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle!\n"));
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
	}
}

static u8 btdm_HIDA2DPAction1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
	{
		pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);
		btdm_HIDA2DPActionBC81Ant(padapter);
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~(BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);
		return _FALSE;
	}
}

static void btdm_HIDPANActionBC81Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if ((pBtMgnt->ExtConfig.bBTBusy && !pBtMgnt->BtOperationOn))
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && [BT 2.1]\n"));
		BTDM_Balance(padapter, _TRUE, 0x5, 0x1a);
		BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle or [BT 3.0]\n"));
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
	}
}

static u8 btdm_HIDPANAction1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN))
	{
		pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);
		btdm_HIDPANActionBC81Ant(padapter);
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~(BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);
		return _FALSE;
	}
}

static void btdm_PANA2DPActionBC81Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if ((pBtMgnt->ExtConfig.bBTBusy && !pBtMgnt->BtOperationOn))
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && [BT 2.1]\n"));
		BTDM_Balance(padapter, _TRUE, 0x5, 0x1a);
		BTDM_SingleAnt(padapter, _TRUE, _FALSE, _FALSE);
	}
	else if ((pBtMgnt->ExtConfig.bBTBusy && pBtMgnt->BtOperationOn))
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && [BT 3.0]\n"));
		btdm_A2DPActionBC81Ant(padapter);
	}
	else
	{
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_SingleAnt(padapter, _TRUE, _TRUE, _FALSE);
	}
}

static u8 btdm_PANA2DPAction1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
	{
		pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);
		btdm_PANA2DPActionBC81Ant(padapter);
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~(BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);
		return _FALSE;
	}
}

//============================================================
// extern function start with BTDM_
//============================================================

static void BTDM_SetAntenna(struct rtw_adapter *padapter, u8 who)
{
}

void
BTDM_SingleAnt(
	struct rtw_adapter *	padapter,
	u8		bSingleAntOn,
	u8		bInterruptOn,
	u8		bMultiNAVOn
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			H2C_Parameter[3] = {0};

	if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1)
		return;

	H2C_Parameter[2] = 0;
	H2C_Parameter[1] = 0;
	H2C_Parameter[0] = 0;

	if (bInterruptOn)
	{
		H2C_Parameter[2] |= 0x02;	//BIT1
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}
	pHalData->bt_coexist.bInterruptOn = bInterruptOn;

	if (bSingleAntOn)
	{
		H2C_Parameter[2] |= 0x10;	//BIT4
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}
	pHalData->bt_coexist.bSingleAntOn = bSingleAntOn;

	if (bMultiNAVOn)
	{
		H2C_Parameter[2] |= 0x20;	//BIT5
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}
	pHalData->bt_coexist.bMultiNAVOn = bMultiNAVOn;

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], SingleAntenna=[%s:%s:%s], write 0xe = 0x%x\n",
		bSingleAntOn?"ON":"OFF", bInterruptOn?"ON":"OFF", bMultiNAVOn?"ON":"OFF",
		H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));
}

void BTDM_CheckBTIdleChange1Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	u8				stateChange = _FALSE;
	u32			BT_Polling, Ratio_Act, Ratio_STA;
	u32				BT_Active, BT_State;
	u32				regBTActive=0, regBTState=0, regBTPolling=0;

	if (!pHalData->bt_coexist.BluetoothCoexist)
		return;
	if (pBtMgnt->ExtConfig.bManualControl)
		return;
	if (pHalData->bt_coexist.BT_CoexistType != BT_CSR_BC8)
		return;
	if (pHalData->bt_coexist.BT_Ant_Num != Ant_x1)
		return;

	//
	// The following we only consider CSR BC8 and fw version should be >= 62
	//
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], FirmwareVersion = 0x%x(%d)\n",
	pHalData->FirmwareVersion, pHalData->FirmwareVersion));
	{
		regBTActive = REG_BT_ACTIVE;
		regBTState = REG_BT_STATE;
		if (pHalData->FirmwareVersion >= FW_VER_BT_REG1)
			regBTPolling = REG_BT_POLLING1;
		else
			regBTPolling = REG_BT_POLLING;
	}

	BT_Active = rtw_read32(padapter, regBTActive);
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Active(0x%x)=%x\n", regBTActive, BT_Active));
	BT_Active = BT_Active & 0x00ffffff;

	BT_State = rtw_read32(padapter, regBTState);
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_State(0x%x)=%x\n", regBTState, BT_State));
	BT_State = BT_State & 0x00ffffff;

	BT_Polling = rtw_read32(padapter, regBTPolling);
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT_Polling(0x%x)=%x\n", regBTPolling, BT_Polling));

	if (BT_Active==0xffffffff && BT_State==0xffffffff && BT_Polling==0xffffffff )
		return;
	if (BT_Polling == 0)
		return;

	Ratio_Act = BT_Active*1000/BT_Polling;
	Ratio_STA = BT_State*1000/BT_Polling;

	pHalData->bt_coexist.Ratio_Tx = Ratio_Act;
	pHalData->bt_coexist.Ratio_PRI = Ratio_STA;

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_Act=%d\n", Ratio_Act));
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], Ratio_STA=%d\n", Ratio_STA));

	if (Ratio_STA<60 && Ratio_Act<500)	// BT PAN idle
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_IDLE;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_IDLE;

		if (Ratio_STA)
		{
			// Check if BT PAN (under BT 2.1) is uplink or downlink
			if ((Ratio_Act/Ratio_STA) < 2)
			{
				// BT PAN Uplink
				pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = _TRUE;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_UPLINK;
				pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = _FALSE;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK;
			}
			else
			{
				// BT PAN downlink
				pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = _FALSE;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
				pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = _TRUE;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK;
			}
		}
		else
		{
			// BT PAN downlink
			pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = _FALSE;
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
			pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = _TRUE;
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK;
		}
	}

	// Check BT is idle or not
	if (pBtMgnt->ExtConfig.NumberOfHandle==0 &&
		pBtMgnt->ExtConfig.NumberOfSCO==0)
	{
		pBtMgnt->ExtConfig.bBTBusy = _FALSE;
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
	}
	else
	{
		if (Ratio_STA<60)
		{
			pBtMgnt->ExtConfig.bBTBusy = _FALSE;
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
		}
		else
		{
			pBtMgnt->ExtConfig.bBTBusy = _TRUE;
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE;
		}
	}

	if (pBtMgnt->ExtConfig.NumberOfHandle==0 &&
		pBtMgnt->ExtConfig.NumberOfSCO==0)
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW;
		pBtMgnt->ExtConfig.MIN_BT_RSSI = 0;
		BTDM_SetAntenna(padapter, BTDM_ANT_BT_IDLE);
	}
	else
	{
		if (pBtMgnt->ExtConfig.MIN_BT_RSSI <= -5)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_RSSI_LOW;
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Low\n"));
		}
		else
		{
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW;
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], core stack notify bt rssi Normal\n"));
		}
	}

	if (pHalData->bt_coexist.bBTBusyTraffic !=
		pBtMgnt->ExtConfig.bBTBusy)
	{	// BT idle or BT non-idle
		pHalData->bt_coexist.bBTBusyTraffic = pBtMgnt->ExtConfig.bBTBusy;
		stateChange = _TRUE;
	}

	if (stateChange)
	{
		if (!pBtMgnt->ExtConfig.bBTBusy)
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n"));
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is non-idle\n"));
		}
	}
	if (!pBtMgnt->ExtConfig.bBTBusy) {
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT is idle or disable\n"));
		if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING|WIFI_SITE_MONITOR) == _TRUE)
			BTDM_SetAntenna(padapter, BTDM_ANT_WIFI);
	}
}

static void BTDM_BTCoexistWithProfile1Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
	{
		btdm_CheckCounterOnly1Ant(padapter);
		return;
	}

	RTPRINT(FIOCTL, IOCTL_BT_FLAG_MON, ("CurrentBTConnectionCnt=%d, BtOperationOn=%d, bBTConnectInProgress=%d !!\n",
		pBtMgnt->CurrentBTConnectionCnt, pBtMgnt->BtOperationOn, pBtMgnt->bBTConnectInProgress));

	if ((pHalData->bt_coexist.BluetoothCoexist) &&
		(pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8))
	{
		BTHCI_GetProfileNameMoto(padapter);
		BTHCI_GetBTRSSI(padapter);
		BTDM_CheckBTIdleChange1Ant(padapter);
		BTDM_CheckWiFiState(padapter);

		if (btdm_SCOAction1Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Action SCO\n"));
		}
		else if (btdm_HIDAction1Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Action HID\n"));
		}
		else if (btdm_A2DPAction1Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Action A2DP\n"));
		}
		else if (btdm_PANAction1Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Action PAN\n"));
		}
		else if (btdm_HIDA2DPAction1Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Action HID_A2DP\n"));
		}
		else if (btdm_HIDPANAction1Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Action HID_PAN\n"));
		}
		else if (btdm_PANA2DPAction1Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Action PAN_A2DP\n"));
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], No Action case!!!\n"));
		}

		if (!BTDM_IsSameCoexistState(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x\n",
				pHalData->bt_coexist.PreviousState,
				pHalData->bt_coexist.CurrentState));
			pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState;

			RTPRINT(FBT, BT_TRACE, ("["));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT30)
				RTPRINT(FBT, BT_TRACE, ("BT 3.0, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT20)
				RTPRINT(FBT, BT_TRACE, ("HT20, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT40)
				RTPRINT(FBT, BT_TRACE, ("HT40, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_LEGACY)
				RTPRINT(FBT, BT_TRACE, ("Legacy, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_LOW)
				RTPRINT(FBT, BT_TRACE, ("Rssi_Low, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_MEDIUM)
				RTPRINT(FBT, BT_TRACE, ("Rssi_Mid, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_HIGH)
				RTPRINT(FBT, BT_TRACE, ("Rssi_High, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_IDLE)
				RTPRINT(FBT, BT_TRACE, ("Wifi_Idle, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_UPLINK)
				RTPRINT(FBT, BT_TRACE, ("Wifi_Uplink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_DOWNLINK)
				RTPRINT(FBT, BT_TRACE, ("Wifi_Downlink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE)
				RTPRINT(FBT, BT_TRACE, ("BT_idle, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_PAN_IDLE)
				RTPRINT(FBT, BT_TRACE, ("BT_PAN_idle, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_PAN_UPLINK)
				RTPRINT(FBT, BT_TRACE, ("BT_PAN_uplink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_PAN_DOWNLINK)
				RTPRINT(FBT, BT_TRACE, ("BT_PAN_downlink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_HID)
				RTPRINT(FBT, BT_TRACE, ("PRO_HID, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_A2DP)
				RTPRINT(FBT, BT_TRACE, ("PRO_A2DP, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_PAN)
				RTPRINT(FBT, BT_TRACE, ("PRO_PAN, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_SCO)
				RTPRINT(FBT, BT_TRACE, ("PRO_SCO, "));
			RTPRINT(FBT, BT_TRACE, ("]\n"));
		}
	}
}

// ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr1Ant.c =====
#endif

#ifdef __HALBTCCSR2ANT_C__ // HAL/BTCoexist/HalBtcCsr2Ant.c
// ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c =====

//============================================================
// local function start with btdm_
//============================================================
static void
btdm_BtEnableDisableCheck(struct rtw_adapter *padapter, u32 BT_Active)
{
}

static void btdm_CheckBTState2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
//	PRT_HIGH_THROUGHPUT	pHTInfo = GET_HT_INFO(pMgntInfo);
	u8			stateChange = _FALSE;
	u32			BT_Polling, Ratio_Act, Ratio_STA;
	u32			BT_Active, BT_State;
	u32			regBTActive = 0, regBTState = 0, regBTPolling=0;
	u32			btBusyThresh = 0;

	RTPRINT(FBT, BT_TRACE, ("FirmwareVersion = 0x%x(%d)\n",
	pHalData->FirmwareVersion, pHalData->FirmwareVersion));

	btBusyThresh = 60;

	BT_Active = rtw_read32(padapter, regBTActive);
	RTPRINT(FBT, BT_TRACE, ("BT_Active(0x%x)=%x\n", regBTActive, BT_Active));
	BT_Active = BT_Active & 0x00ffffff;

	BT_State = rtw_read32(padapter, regBTState);
	RTPRINT(FBT, BT_TRACE, ("BT_State(0x%x)=%x\n", regBTState, BT_State));
	BT_State = BT_State & 0x00ffffff;

	BT_Polling = rtw_read32(padapter, regBTPolling);
	RTPRINT(FBT, BT_TRACE, ("BT_Polling(0x%x)=%x\n", regBTPolling, BT_Polling));

	if (BT_Active==0xffffffff && BT_State==0xffffffff && BT_Polling==0xffffffff )
		return;

	// 2011/05/04 MH For Slim combo test meet a problem. Surprise remove and WLAN is running
	// DHCP process. At the same time, the register read value might be zero. And cause BSOD 0x7f
	// EXCEPTION_DIVIDED_BY_ZERO. In This case, the stack content may always be wrong due to
	// HW divide trap.
	if (BT_Polling==0)
		return;

	btdm_BtEnableDisableCheck(padapter, BT_Active);

	Ratio_Act = BT_Active*1000/BT_Polling;
	Ratio_STA = BT_State*1000/BT_Polling;

	pHalData->bt_coexist.Ratio_Tx = Ratio_Act;
	pHalData->bt_coexist.Ratio_PRI = Ratio_STA;

	RTPRINT(FBT, BT_TRACE, ("Ratio_Act=%d\n", Ratio_Act));
	RTPRINT(FBT, BT_TRACE, ("Ratio_STA=%d\n", Ratio_STA));

	if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
	{
		if (Ratio_STA < 60)	// BT PAN idle
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_IDLE;
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK;
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
		}
		else
		{
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_IDLE;

			// Check if BT PAN (under BT 2.1) is uplink or downlink
			if ((Ratio_Act/Ratio_STA) < 2)
			{	// BT PAN Uplink
				pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = _TRUE;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_UPLINK;
				pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = _FALSE;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK;
			}
			else
			{	// BT PAN downlink
				pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic = _FALSE;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
				pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic = _TRUE;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_DOWNLINK;
			}
		}
	}
	else
	{
		// BC4, doesn't use the following variables.
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_PAN_IDLE;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_DOWNLINK;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_PAN_UPLINK;
	}


	// Check BT is idle or not
	if (pBtMgnt->ExtConfig.NumberOfHandle==0 &&
		pBtMgnt->ExtConfig.NumberOfSCO==0)
	{
		pBtMgnt->ExtConfig.bBTBusy = _FALSE;
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
	}
	else
	{
		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			if (Ratio_Act < 20)
			{
				pBtMgnt->ExtConfig.bBTBusy = _FALSE;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
			}
			else
			{
				pBtMgnt->ExtConfig.bBTBusy = _TRUE;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE;
			}
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			if (Ratio_STA < btBusyThresh)
			{
				pBtMgnt->ExtConfig.bBTBusy = _FALSE;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_IDLE;
			}
			else
			{
				pBtMgnt->ExtConfig.bBTBusy = _TRUE;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_IDLE;
			}

			if ((Ratio_STA < btBusyThresh) ||
				(Ratio_Act<180 && Ratio_STA<130))
			{
				pBtMgnt->ExtConfig.bBTA2DPBusy = _FALSE;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_A2DP_IDLE;
			}
			else
			{
				pBtMgnt->ExtConfig.bBTA2DPBusy =_TRUE;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_A2DP_IDLE;
			}
		}
	}

	if (pBtMgnt->ExtConfig.NumberOfHandle==0 &&
		pBtMgnt->ExtConfig.NumberOfSCO==0)
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW;
		pBtMgnt->ExtConfig.MIN_BT_RSSI = 0;
	}
	else
	{
		if (pBtMgnt->ExtConfig.MIN_BT_RSSI <= -5)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT_RSSI_LOW;
			RTPRINT(FBT, BT_TRACE, ("[bt rssi], Low\n"));
		}
		else
		{
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT_RSSI_LOW;
			RTPRINT(FBT, BT_TRACE, ("[bt rssi], Normal\n"));
		}
	}

	if (pHalData->bt_coexist.bBTBusyTraffic !=
		pBtMgnt->ExtConfig.bBTBusy)
	{	// BT idle or BT non-idle
		pHalData->bt_coexist.bBTBusyTraffic = pBtMgnt->ExtConfig.bBTBusy;
		stateChange = _TRUE;
	}

	if (stateChange)
	{
		if (!pBtMgnt->ExtConfig.bBTBusy)
		{
			u8	tempu1Byte;
			RTPRINT(FBT, BT_TRACE, ("[BT] BT is idle or disable\n"));

			tempu1Byte = rtw_read8(padapter, 0x4fd);
			tempu1Byte |= BIT(2);

			rtw_write8(padapter, 0x4fd, tempu1Byte);

			//Resume RF Rx LPF corner
			PHY_SetRFReg(padapter, PathA, 0x1e, 0xf0, pHalData->bt_coexist.BtRfRegOrigin1E);
			BTDM_CoexAllOff(padapter);

			RTPRINT(FBT, BT_TRACE, ("BT_Turn OFF Coexist bt is off \n"));

			rtw_write8(padapter, REG_GPIO_MUXCFG, 0x0);
		}
		else
		{
			u8	tempu1Byte;
			RTPRINT(FBT, BT_TRACE, ("[BT] BT is non-idle\n"));

			tempu1Byte = rtw_read8(padapter, 0x4fd);
			tempu1Byte &=~ BIT(2);
			rtw_write8(padapter, 0x4fd, tempu1Byte);

			//Shrink RF Rx LPF corner, 0x1e[7:4]=1111
			PHY_SetRFReg(padapter, PathA, 0x1e, 0xf0, 0xf);
		}
	}

	if (stateChange)
	{
		if (pBtMgnt->ExtConfig.bBTBusy)
		{
			BTDM_RejectAPAggregatedPacket(padapter, _TRUE);
		}
		else
		{
			BTDM_RejectAPAggregatedPacket(padapter, _FALSE);
		}
	}
}

static void btdm_WLANActOff(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	//Only used in BC4 setting
	rtw_write8(padapter, REG_GPIO_MUXCFG, 0x0);
	BTDM_Balance(padapter, _FALSE, 0, 0);
	BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x0, BT_FW_NAV_OFF);
}

static void btdm_WLANActBTPrecedence(struct rtw_adapter *padapter)
{
	BTDM_Balance(padapter, _FALSE, 0, 0);
	BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x0, BT_FW_NAV_OFF);

	rtw_write32(padapter, 0x6c4,0x55555555);
	rtw_write32(padapter, 0x6c8,0x000000f0);
	rtw_write32(padapter, 0x6cc,0x40000010);
	rtw_write8(padapter, REG_GPIO_MUXCFG, 0xa0);
}

//==============================================================
//
// Note:
// In the following, FW should be done before SW mechanism.
// BTDM_Balance(), BTDM_DiminishWiFi(), BT_NAV() should be done
// before BTDM_AGCTable(), BTDM_BBBackOffLevel(), btdm_DacSwing().
//
//==============================================================

static void btdm_DacSwing(struct rtw_adapter *padapter, u8 type)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.BT_Ant_Num != Ant_x2)
		return;

	if (type == BT_DACSWING_OFF)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]DACSwing Off!\n"));
		PHY_SetBBReg(padapter, 0x880, 0xfc000000, 0x30);
	}
	else if (type == BT_DACSWING_M4)
	{
		if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_RSSI_LOW)
		{
			RTPRINT(FBT, BT_TRACE, ("[BT]DACSwing -4 original, but Low RSSI!\n"));
			PHY_SetBBReg(padapter, 0x880, 0xfc000000, 0x18);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("[BT]DACSwing -4!\n"));
			PHY_SetBBReg(padapter, 0x880, 0xfc000000, 0x20);
		}
	}
	else if (type == BT_DACSWING_M7)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]DACSwing -7!\n"));
		PHY_SetBBReg(padapter, 0x880, 0xfc000000, 0x18);
	}
	else if (type == BT_DACSWING_M10)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]DACSwing -10!\n"));
		PHY_SetBBReg(padapter, 0x880, 0xfc000000, 0x10);
	}

	if (type != BT_DACSWING_OFF)
		pHalData->bt_coexist.bSWCoexistAllOff = _FALSE;
}

static void btdm_A2DPActionBC42Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	rtw_write8(padapter, REG_GPIO_MUXCFG, 0x0);

	if (pBtMgnt->ExtConfig.bBTBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));

		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;
			// Do the FW mechanism first
			if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
				BTDM_Balance(padapter, _TRUE, 0xc, 0x18);
				BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x20, BT_FW_NAV_OFF);
			}
			else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
				BTDM_FWCoexAllOff(padapter);
			}
			// Then do the SW mechanism
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_M4);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;
			if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
				BTDM_Balance(padapter, _TRUE, 0xc, 0x18);
				BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x20, BT_FW_NAV_OFF);
			}
			else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
				BTDM_FWCoexAllOff(padapter);
			}
			// Then do the SW mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_M4);
			}
			else
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
				btdm_DacSwing(padapter, BT_DACSWING_M4);
			}
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static void btdm_A2DPActionBC82Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pBtMgnt->ExtConfig.bBTA2DPBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		// Do the FW mechanism first
		if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
			BTDM_Balance(padapter, _TRUE, 0xc, 0x18);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
		}
		else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
			BTDM_Balance(padapter, _TRUE, 0x10, 0x18);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
		}

		// Then do the SW mechanism
		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_OFF);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_OFF);
			}
			else
			{
				BTDM_SWCoexAllOff(padapter);
			}
		}
	}
	else if (pBtMgnt->ExtConfig.bBTA2DPBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		// Do the FW mechanism first
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_DiminishWiFi(padapter, _TRUE, _TRUE, 0x18, BT_FW_NAV_OFF);

		// Then do the SW mechanism
		BTDM_SWCoexAllOff(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle and Wifi is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static void btdm_A2DPActionBC82Ant92d(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState, rssiState1;

	if (pBtMgnt->ExtConfig.bBTA2DPBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));
		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			rssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, BT_FW_COEX_THRESH_47, 0);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			if (BTDM_IsWifiUplink(padapter))
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
				rssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, BT_FW_COEX_THRESH_25, 0);
			}
			else if (BTDM_IsWifiDownlink(padapter))
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
				rssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, BT_FW_COEX_THRESH_40, 0);
			}
		}
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
		if (!BTDM_IsCoexistStateChanged(padapter))
			return;

		// Do the FW mechanism first
		if (BTDM_IsWifiUplink(padapter))
		{
			BTDM_Balance(padapter, _TRUE, 0xc, 0x18);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
		}
		else if (BTDM_IsWifiDownlink(padapter))
		{
			BTDM_Balance(padapter, _TRUE, 0x10, 0x18);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
		}

		// Then do the SW mechanism
		if ((rssiState1 == BT_RSSI_STATE_HIGH) ||
			(rssiState1 == BT_RSSI_STATE_STAY_HIGH))
		{
			BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
		}
		else
		{
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
		}

		if (BTDM_IsHT40(padapter))
		{
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_OFF);
		}
		else
		{
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_OFF);
			}
			else
			{
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
				btdm_DacSwing(padapter, BT_DACSWING_OFF);
			}
		}
	}
	else if (pBtMgnt->ExtConfig.bBTA2DPBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		// Do the FW mechanism first
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_DiminishWiFi(padapter, _TRUE, _TRUE, 0x18, BT_FW_NAV_OFF);

		// Then do the SW mechanism
		BTDM_SWCoexAllOff(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle and Wifi is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static u8 btdm_A2DPAction2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8			bEnter = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_A2DP)
			bEnter = _TRUE;
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) && pBtMgnt->ExtConfig.NumberOfHandle==1)
			bEnter = _TRUE;
	}

	if (bEnter)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_A2DPAction2Ant(), "));
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_HID;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_PAN;

		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC4]\n"));
			btdm_A2DPActionBC42Ant(padapter);
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC8]\n"));
			btdm_A2DPActionBC82Ant(padapter);
		}
		return _TRUE;
	}
	else
	{
		return _FALSE;
	}
}

static void btdm_PANActionBC42Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return;

	rtw_write8(padapter, REG_GPIO_MUXCFG, 0x0);

	if (pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 3.0]\n"));
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x0, BT_FW_NAV_OFF);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 2.1]\n"));
		if (pBtMgnt->ExtConfig.bBTBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));
			BTDM_Balance(padapter, _TRUE, 0x20, 0x10);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
			BTDM_Balance(padapter, _FALSE, 0, 0);
			BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x0, BT_FW_NAV_OFF);
		}
	}
	BTDM_SWCoexAllOff(padapter);
}

static void btdm_PANActionBC82Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 3.0]\n"));
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		BTDM_CoexAllOff(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 2.1]\n"));
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 3, BT_FW_COEX_THRESH_25, BT_FW_COEX_THRESH_50);
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		if (pBtMgnt->ExtConfig.bBTBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));

			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				RTPRINT(FBT, BT_TRACE, ("RSSI stay HIGH or High \n"));
				// Do the FW mechanism first
				if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
					BTDM_Balance(padapter, _TRUE, 0x20, 0x20);
					BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
					BTDM_FWCoexAllOff(padapter);
				}
				// Then do the SW mechanism
				if (BTDM_IsHT40(padapter))
				{
					RTPRINT(FBT, BT_TRACE, ("HT40\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				}
				else
				{
					RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				}
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
					btdm_DacSwing(padapter, BT_DACSWING_OFF);
				}
				else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
					btdm_DacSwing(padapter, BT_DACSWING_M4);
				}
			}
			else if ((btRssiState == BT_RSSI_STATE_MEDIUM) ||
				(btRssiState == BT_RSSI_STATE_STAY_MEDIUM))
			{
				RTPRINT(FBT, BT_TRACE, ("RSSI stay Medium or Medium \n"));
				// Do the FW mechanism first
				BTDM_Balance(padapter, _TRUE, 0x20, 0x20);

				if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
					BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
					if (BTDM_IsHT40(padapter))
						BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);//BT_FW_NAV_ON);
					else
						BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				// Then do the SW mechanism
				if (BTDM_IsHT40(padapter))
				{
					RTPRINT(FBT, BT_TRACE, ("HT40\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				}
				else
				{
					RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				}
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_OFF);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("RSSI stay LOW or LOW \n"));
				// Do the FW mechanism first
				BTDM_Balance(padapter, _TRUE, 0x20, 0x20);

				if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
					BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
					if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
					{
						RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
						if (BTDM_IsHT40(padapter))
						{
							RTPRINT(FBT, BT_TRACE, ("HT40\n"));
							BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);//BT_FW_NAV_ON);
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
							BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
						}
					}
					else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
					{
						RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
						BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
					}
				}
				// Then do the SW mechanism
				BTDM_SWCoexAllOff(padapter);
			}
		}
		else if (pBtMgnt->ExtConfig.bBTBusy &&
				!pmlmepriv->LinkDetectInfo.bBusyTraffic &&
				(BTDM_GetRxSS(padapter) < 30))
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is idle!\n"));
			RTPRINT(FBT, BT_TRACE, ("RSSI < 30\n"));
			// Do the FW mechanism first
			BTDM_Balance(padapter, _TRUE, 0x0a, 0x20);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
			// Then do the SW mechanism
			BTDM_SWCoexAllOff(padapter);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
			BTDM_CoexAllOff(padapter);
		}
	}
}

static void btdm_PANActionBC82Ant92d(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState, rssiState1;

	if (pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 3.0]\n"));
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		BTDM_CoexAllOff(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 2.1]\n"));
		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			rssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, BT_FW_COEX_THRESH_47, 0);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			rssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, BT_FW_COEX_THRESH_25, 0);
		}
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 3, BT_FW_COEX_THRESH_25, BT_FW_COEX_THRESH_50);
		if (!BTDM_IsCoexistStateChanged(padapter))
			return;

		if (pBtMgnt->ExtConfig.bBTBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));

			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				RTPRINT(FBT, BT_TRACE, ("RSSI stay HIGH or High \n"));
				// Do the FW mechanism first
				if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
					BTDM_Balance(padapter, _TRUE, 0x20, 0x20);
					BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
					BTDM_FWCoexAllOff(padapter);
				}
				// Then do the SW mechanism
				if ((rssiState1 == BT_RSSI_STATE_HIGH) ||
					(rssiState1 == BT_RSSI_STATE_STAY_HIGH))
				{
					BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				}
				else
				{
					BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				}
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
					btdm_DacSwing(padapter, BT_DACSWING_OFF);
				}
				else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
					btdm_DacSwing(padapter, BT_DACSWING_M4);
				}
			}
			else if ((btRssiState == BT_RSSI_STATE_MEDIUM) ||
				(btRssiState == BT_RSSI_STATE_STAY_MEDIUM))
			{
				RTPRINT(FBT, BT_TRACE, ("RSSI stay Medium or Medium \n"));
				// Do the FW mechanism first
				BTDM_Balance(padapter, _TRUE, 0x20, 0x20);

				if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
					BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
					if (BTDM_IsHT40(padapter))
						BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);//BT_FW_NAV_ON);
					else
						BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				// Then do the SW mechanism
				if ((rssiState1 == BT_RSSI_STATE_HIGH) ||
					(rssiState1 == BT_RSSI_STATE_STAY_HIGH))
				{
					BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				}
				else
				{
					BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				}
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_OFF);
			}
			else
			{
				RTPRINT(FBT, BT_TRACE, ("RSSI stay LOW or LOW \n"));
				// Do the FW mechanism first
				BTDM_Balance(padapter, _TRUE, 0x20, 0x20);

				if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
					BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
				}
				else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
				{
					RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
					if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
					{
						RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
						if (BTDM_IsHT40(padapter))
						{
							RTPRINT(FBT, BT_TRACE, ("HT40\n"));
							BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);//BT_FW_NAV_ON);
						}
						else
						{
							RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
							BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
						}
					}
					else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
					{
						RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
						BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
					}
				}
				// Then do the SW mechanism
				if ((rssiState1 == BT_RSSI_STATE_HIGH) ||
					(rssiState1 == BT_RSSI_STATE_STAY_HIGH))
				{
					BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				}
				else
				{
					BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				}
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
				btdm_DacSwing(padapter, BT_DACSWING_OFF);
			}
		}
		else if (pBtMgnt->ExtConfig.bBTBusy &&
				!pmlmepriv->LinkDetectInfo.bBusyTraffic &&
				(BTDM_GetRxSS(padapter) < 30))
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is idle!\n"));
			RTPRINT(FBT, BT_TRACE, ("RSSI < 30\n"));
			// Do the FW mechanism first
			BTDM_Balance(padapter, _TRUE, 0x0a, 0x20);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
			// Then do the SW mechanism
			BTDM_SWCoexAllOff(padapter);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
			BTDM_CoexAllOff(padapter);
		}
	}
}

static u8 btdm_PANAction2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8			bEnter = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN)
			bEnter = _TRUE;
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) && pBtMgnt->ExtConfig.NumberOfHandle==1)
			bEnter = _TRUE;
	}

	if (bEnter)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_PANAction2Ant(), "));
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_HID;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_A2DP;

		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC4]\n"));
			btdm_PANActionBC42Ant(padapter);
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC8]\n"));
			btdm_PANActionBC82Ant(padapter);
		}
		return _TRUE;
	}
	else
	{
		return _FALSE;
	}
}

static void btdm_HIDActionBC42Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return;

	if (BTDM_Legacy(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("Current Wireless Mode is B/G\n"));
		btdm_WLANActBTPrecedence(padapter);
	}
	else if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
		btdm_WLANActBTPrecedence(padapter);
	}
	else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
		btdm_WLANActOff(padapter);
	}
	else if (!pmlmepriv->LinkDetectInfo.bBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("Wifi Idel \n"));
		btdm_WLANActOff(padapter);
	}
	BTDM_SWCoexAllOff(padapter);
}

static void btdm_HIDActionBC82Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pHalData->CustomerID == RT_CID_PLANEX)
	{
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;
		btdm_HIDActionBC42Ant(padapter);
		return;
	}

	if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
	{
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_45, 0);
	}
	else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
	{
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_20, 0);
	}

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return;

	if (pBtMgnt->ExtConfig.bBTBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));
		// Do the FW mechanism first
		if ((btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH))
		{
			BTDM_FWCoexAllOff(padapter);
		}
		else
		{
			if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
				BTDM_Balance(padapter, _FALSE, 0, 0);
				BTDM_DiminishWiFi(padapter, _TRUE, _TRUE, 0x18, BT_FW_NAV_OFF);
			}
			else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
				BTDM_Balance(padapter, _TRUE, 0x15, 0x15);
				BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x30, BT_FW_NAV_OFF);
			}
		}
		// Then do the SW mechanism
		BTDM_SWCoexAllOff(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static void btdm_HIDActionBC82Ant92d(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
	{
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_45, 0);
	}
	else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
	{
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_20, 0);
	}

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return;

	if (pBtMgnt->ExtConfig.bBTBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));
		if ((btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH))
		{
			// Do the FW mechanism first
			BTDM_FWCoexAllOff(padapter);

			// Then do the SW mechanism
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
			btdm_DacSwing(padapter, BT_DACSWING_M4);
		}
		else
		{
			// Do the FW mechanism first
			if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
				BTDM_Balance(padapter, _FALSE, 0, 0);
				BTDM_DiminishWiFi(padapter, _TRUE, _TRUE, 0x18, BT_FW_NAV_OFF);
			}
			else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
				BTDM_Balance(padapter, _TRUE, 0x15, 0x15);
				BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x30, BT_FW_NAV_OFF);
			}
			// Then do the SW mechanism
			BTDM_SWCoexAllOff(padapter);
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static u8 btdm_HIDAction2Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter)	;
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			bEnter = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID)
			bEnter = _TRUE;
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && pBtMgnt->ExtConfig.NumberOfHandle==1)
			bEnter = _TRUE;
	}

	if (bEnter)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_HIDAction2Ant(), "));
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_PAN;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_A2DP;

		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC4]\n"));
			btdm_HIDActionBC42Ant(padapter);
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC8]\n"));
			btdm_HIDActionBC42Ant(padapter);
		}
		return _TRUE;
	}
	else
	{
		return _FALSE;
	}
}

static void btdm_SCOActionBC42Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return;

	btdm_WLANActOff(padapter);
	BTDM_SWCoexAllOff(padapter);
}

static void btdm_SCOActionBC82Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8	btRssiState;

	if (BTDM_IsHT40(padapter))
	{
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		// Do the FW mechanism first
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0, BT_FW_NAV_OFF);

		// Then do the SW mechanism
		BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
		BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
		btdm_DacSwing(padapter, BT_DACSWING_OFF);
	}
	else
	{
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		// Do the FW mechanism first
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0, BT_FW_NAV_OFF);

		// Then do the SW mechanism
		if ((btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH))
		{
			BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_OFF);
		}
		else
		{
			BTDM_SWCoexAllOff(padapter);
		}
	}
}

static void btdm_SCOActionBC82Ant92d(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8	btRssiState, rssiState1;

	rssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, BT_FW_COEX_THRESH_47, 0);
	if (BTDM_IsHT40(padapter))
	{
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		RTPRINT(FBT, BT_TRACE, ("HT40\n"));
		// Do the FW mechanism first
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0, BT_FW_NAV_OFF);

		// Then do the SW mechanism
		BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
		BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
		btdm_DacSwing(padapter, BT_DACSWING_OFF);
	}
	else
	{
		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
		// Do the FW mechanism first
		BTDM_Balance(padapter, _FALSE, 0, 0);
		BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0, BT_FW_NAV_OFF);

		// Then do the SW mechanism
		if ((rssiState1 == BT_RSSI_STATE_HIGH) ||
			(rssiState1 == BT_RSSI_STATE_STAY_HIGH))
		{
			BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
		}
		else
		{
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
		}
		if ((btRssiState == BT_RSSI_STATE_HIGH) ||
			(btRssiState == BT_RSSI_STATE_STAY_HIGH))
		{
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_OFF);
		}
		else
		{
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
			btdm_DacSwing(padapter, BT_DACSWING_OFF);
		}
	}
}

static u8 btdm_SCOAction2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8			bEnter = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_SCO)
			bEnter = _TRUE;
	}
	else
	{
		if (pBtMgnt->ExtConfig.NumberOfSCO > 0)
			bEnter = _TRUE;
	}
	if (bEnter)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_SCOAction2Ant(), "));
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO;

		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC4]\n"));
			btdm_SCOActionBC42Ant(padapter);
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC8]\n"));
			btdm_SCOActionBC82Ant(padapter);
		}
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_PROFILE_SCO;
		return _FALSE;
	}
}

static void btdm_HIDA2DPActionBC42Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pBtMgnt->ExtConfig.bBTBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));

		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;
			// Do the FW mechanism first
			if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
				BTDM_Balance(padapter, _TRUE, 0x7, 0x20);
				BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x20, BT_FW_NAV_OFF);
			}
			else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
				BTDM_FWCoexAllOff(padapter);
			}
			// Then do the SW mechanism
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_M7);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;
			// Do the FW mechanism first
			if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
				BTDM_Balance(padapter, _TRUE, 0x7, 0x20);
				BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x20, BT_FW_NAV_OFF);
			}
			else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
				BTDM_FWCoexAllOff(padapter);
			}

			// Then do the SW mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_M7);
			}
			else
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
				btdm_DacSwing(padapter, BT_DACSWING_M7);
			}
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static void btdm_HIDA2DPActionBC82Ant(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (pBtMgnt->ExtConfig.bBTBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));

		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;

			// Do the FW mechanism first
			BTDM_FWCoexAllOff(padapter);

			// Then do the SW mechanism
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_M7);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;

			BTDM_FWCoexAllOff(padapter);

			// Then do the SW mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_M7);
			}
			else
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
				btdm_DacSwing(padapter, BT_DACSWING_M7);
			}
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static void btdm_HIDA2DPActionBC82Ant92d(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState, rssiState1;

	rssiState1 = BTDM_CheckCoexRSSIState1(padapter, 2, BT_FW_COEX_THRESH_35, 0);
	if (pBtMgnt->ExtConfig.bBTBusy)
	{
		RTPRINT(FBT, BT_TRACE, ("BT is non-idle!\n"));

		if (BTDM_IsHT40(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("HT40\n"));
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;

			// Do the FW mechanism first
			BTDM_FWCoexAllOff(padapter);

			// Then do the SW mechanism
			if ((rssiState1 == BT_RSSI_STATE_HIGH) ||
				(rssiState1 == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
			}
			else
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			}
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
			btdm_DacSwing(padapter, BT_DACSWING_M7);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
			btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_47, 0);
			if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
				return;

			BTDM_FWCoexAllOff(padapter);

			// Then do the SW mechanism
			if ((rssiState1 == BT_RSSI_STATE_HIGH) ||
				(rssiState1 == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
			}
			else
			{
				BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			}
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
				btdm_DacSwing(padapter, BT_DACSWING_M7);
			}
			else
			{
				BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
				btdm_DacSwing(padapter, BT_DACSWING_M7);
			}
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT is idle!\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static u8 btdm_HIDA2DPAction2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8			bEnter = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_A2DP)
			bEnter = _TRUE;
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
			bEnter = _TRUE;
	}

	if (bEnter)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_HIDA2DPAction2Ant(), "));
		pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);

		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC4]\n"));
			btdm_HIDA2DPActionBC42Ant(padapter);
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC8]\n"));
			btdm_HIDA2DPActionBC82Ant(padapter);
		}
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~(BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);
		return _FALSE;
	}
}

static void btdm_HIDPANActionBC42Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return;

	if (pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 3.0]\n"));
			btdm_WLANActBTPrecedence(padapter);
		}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 2.1]\n"));
		if (BTDM_Legacy(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("B/G mode \n"));
			btdm_WLANActBTPrecedence(padapter);
		}
		else if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi Uplink \n"));
			btdm_WLANActBTPrecedence(padapter);
		}
		else if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi Downlink \n"));
			rtw_write8(padapter, REG_GPIO_MUXCFG, 0x0);
			BTDM_Balance(padapter, _TRUE, 0x20, 0x10);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
		}
		else if (!pmlmepriv->LinkDetectInfo.bBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi Idel \n"));
			btdm_WLANActOff(padapter);
		}
	}
	BTDM_SWCoexAllOff(padapter);
}

static void btdm_HIDPANActionBC82Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (!pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 2.1]\n"));

		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_25, 0);
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		if ((pBtMgnt->ExtConfig.bBTBusy && padapter->mlmepriv.LinkDetectInfo.bBusyTraffic))
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle, "));

			// Do the FW mechanism first
			if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
				BTDM_Balance(padapter, _TRUE, 0x15, 0x20);
			}
			else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
				BTDM_Balance(padapter, _TRUE, 0x10, 0x20);
			}
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);

			// Then do the SW mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				if (BTDM_IsHT40(padapter))
				{
					RTPRINT(FBT, BT_TRACE, ("HT40\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
					BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
					btdm_DacSwing(padapter, BT_DACSWING_OFF);
				}
				else
				{
					RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
					BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
					btdm_DacSwing(padapter, BT_DACSWING_OFF);
				}
			}
			else
			{
				BTDM_SWCoexAllOff(padapter);
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
			BTDM_CoexAllOff(padapter);
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 3.0]\n"));
		if (BTDM_IsWifiUplink(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi Uplink\n"));
			btdm_WLANActBTPrecedence(padapter);
			if (pHalData->CustomerID == RT_CID_PLANEX)
				btdm_DacSwing(padapter, BT_DACSWING_M10);
			else
				btdm_DacSwing(padapter, BT_DACSWING_M7);
		}
		else if (BTDM_IsWifiDownlink(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Wifi Downlink\n"));
			if (pHalData->CustomerID == RT_CID_PLANEX)
				btdm_DacSwing(padapter, BT_DACSWING_M10);
			else
				btdm_DacSwing(padapter, BT_DACSWING_M7);
		}
	}
}

static u8 btdm_HIDPANAction2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8			bEnter = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_PAN)
			bEnter = _TRUE;
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN))
			bEnter = _TRUE;
	}

	if (bEnter)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_HIDPANAction2Ant(), "));
		pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);

		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC4]\n"));
			btdm_HIDPANActionBC42Ant(padapter);
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC8]\n"));
			btdm_HIDPANActionBC82Ant(padapter);
		}
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~(BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);
		return _FALSE;
	}

}

static void btdm_PANA2DPActionBC42Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return;

	rtw_write8(padapter, REG_GPIO_MUXCFG, 0x0);
	if (pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 3.0]\n"));

		if (pBtMgnt->ExtConfig.bBTBusy)
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle\n"));
			BTDM_FWCoexAllOff(padapter);

			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
			btdm_DacSwing(padapter, BT_DACSWING_M4);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle\n"));
			BTDM_CoexAllOff(padapter);
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 2.1]\n"));
		if (pBtMgnt->ExtConfig.bBTBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic)
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle!\n"));
			BTDM_Balance(padapter, _TRUE, 0x20, 0x10);
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
			BTDM_Balance(padapter, _FALSE, 0, 0);
			BTDM_DiminishWiFi(padapter, _FALSE, _FALSE, 0x0, BT_FW_NAV_OFF);
		}
		BTDM_SWCoexAllOff(padapter);
	}
}

static void btdm_PANA2DPActionBC82Ant(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			btRssiState;

	if (!pBtMgnt->BtOperationOn)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 2.1]\n"));

		btRssiState = BTDM_CheckCoexRSSIState(padapter, 2, BT_FW_COEX_THRESH_25, 0);
		if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
			return;

		if ((pBtMgnt->ExtConfig.bBTBusy && pmlmepriv->LinkDetectInfo.bBusyTraffic))
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle && Wifi is non-idle, "));

			// Do the FW mechanism first
			if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("BT Uplink\n"));
				BTDM_Balance(padapter, _TRUE, 0x15, 0x20);
			}
			else if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
			{
				RTPRINT(FBT, BT_TRACE, ("BT Downlink\n"));
				BTDM_Balance(padapter, _TRUE, 0x10, 0x20);
			}
			BTDM_DiminishWiFi(padapter, _TRUE, _FALSE, 0x20, BT_FW_NAV_OFF);

			// Then do the SW mechanism
			if ((btRssiState == BT_RSSI_STATE_HIGH) ||
				(btRssiState == BT_RSSI_STATE_STAY_HIGH))
			{
				if (BTDM_IsHT40(padapter))
				{
					RTPRINT(FBT, BT_TRACE, ("HT40\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
					BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
					btdm_DacSwing(padapter, BT_DACSWING_OFF);
				}
				else
				{
					RTPRINT(FBT, BT_TRACE, ("HT20 or Legacy\n"));
					BTDM_AGCTable(padapter, BT_AGCTABLE_ON);
					BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_ON);
					btdm_DacSwing(padapter, BT_DACSWING_OFF);
				}
			}
			else
			{
				BTDM_SWCoexAllOff(padapter);
			}
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle or Wifi is idle!\n"));
			BTDM_CoexAllOff(padapter);
		}
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[BT 3.0]\n"));
		if (pBtMgnt->ExtConfig.bBTBusy)
		{
			RTPRINT(FBT, BT_TRACE, ("BT is non-idle\n"));
			BTDM_FWCoexAllOff(padapter);
			BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
			BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
			btdm_DacSwing(padapter, BT_DACSWING_M4);
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("BT is idle\n"));
			btdm_DacSwing(padapter, BT_DACSWING_OFF);
		}
	}
}

static u8 btdm_PANA2DPAction2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_DBG			pBtDbg = &pBTInfo->BtDbg;
	u8			bEnter = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN_A2DP)
			bEnter = _TRUE;
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
			bEnter = _TRUE;
	}

	if (bEnter)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_PANA2DPAction2Ant(), "));
		pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);

		if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC4]\n"));
			btdm_PANA2DPActionBC42Ant(padapter);
		}
		else if (pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)
		{
			RTPRINT(FBT, BT_TRACE, ("[BC8]\n"));
			btdm_PANA2DPActionBC82Ant(padapter);
		}
		return _TRUE;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~(BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);
		return _FALSE;
	}
}

//============================================================
// extern function start with BTDM_
//============================================================

static void BTDM_SwCoexAllOff92C(struct rtw_adapter *padapter)
{
	BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
	BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
	btdm_DacSwing(padapter, BT_DACSWING_OFF);
}

static void BTDM_SwCoexAllOff92D(struct rtw_adapter *padapter)
{
	BTDM_AGCTable(padapter, BT_AGCTABLE_OFF);
	BTDM_BBBackOffLevel(padapter, BT_BB_BACKOFF_OFF);
	btdm_DacSwing(padapter, BT_DACSWING_OFF);
}

void
BTDM_DiminishWiFi(
	struct rtw_adapter *	padapter,
	u8			bDACOn,
	u8			bInterruptOn,
	u8			DACSwingLevel,
	u8			bNAVOn
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			H2C_Parameter[3] = {0};

	if (pHalData->bt_coexist.BT_Ant_Num != Ant_x2)
		return;

	if ((pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_RSSI_LOW) &&
		(DACSwingLevel == 0x20))
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]DiminishWiFi 0x20 original, but set 0x18 for Low RSSI!\n"));
		DACSwingLevel = 0x18;
	}

	H2C_Parameter[2] = 0;
	H2C_Parameter[1] = DACSwingLevel;
	H2C_Parameter[0] = 0;
	if (bDACOn)
	{
		H2C_Parameter[2] |= 0x01;	//BIT0
		if (bInterruptOn)
		{
			H2C_Parameter[2] |= 0x02;	//BIT1
		}
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}
	if (bNAVOn)
	{
		H2C_Parameter[2] |= 0x08;	//BIT3
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], bDACOn = %s, bInterruptOn = %s, write 0xe = 0x%x\n",
		bDACOn?"ON":"OFF", bInterruptOn?"ON":"OFF",
		H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], bNAVOn = %s\n",
		bNAVOn?"ON":"OFF"));
}

static void BTDM_BTCoexistWithProfile2Ant(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bManualControl)
		return;

	RTPRINT(FIOCTL, IOCTL_BT_FLAG_MON, ("CurrentBTConnectionCnt=%d, BtOperationOn=%d, bBTConnectInProgress=%d !!\n",
		pBtMgnt->CurrentBTConnectionCnt, pBtMgnt->BtOperationOn, pBtMgnt->bBTConnectInProgress));

	if ((pHalData->bt_coexist.BluetoothCoexist) &&
		((pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC4) ||
		(pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)))
	{
		BTHCI_GetProfileNameMoto(padapter);
		BTHCI_GetBTRSSI(padapter);
		btdm_CheckBTState2Ant(padapter);
		BTDM_CheckWiFiState(padapter);

		if (btdm_SCOAction2Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action SCO\n"));
		}
		else if (btdm_HIDAction2Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action HID\n"));
		}
		else if (btdm_A2DPAction2Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action A2DP\n"));
		}
		else if (btdm_PANAction2Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action PAN\n"));
		}
		else if (btdm_HIDA2DPAction2Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action HID_A2DP\n"));
		}
		else if (btdm_HIDPANAction2Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action HID_PAN\n"));
		}
		else if (btdm_PANA2DPAction2Ant(padapter))
		{
			RTPRINT(FBT, BT_TRACE, ("Action PAN_A2DP\n"));
		}
		else
		{
			RTPRINT(FBT, BT_TRACE, ("No Action Matched \n"));
		}

		if (pHalData->bt_coexist.PreviousState != pHalData->bt_coexist.CurrentState)
		{
			RTPRINT(FBT, BT_TRACE, ("Coexist State change from 0x%"i64fmt"x to 0x%"i64fmt"x\n",
				pHalData->bt_coexist.PreviousState,
				pHalData->bt_coexist.CurrentState));
			pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState;

			RTPRINT(FBT, BT_TRACE, ("["));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT30)
				RTPRINT(FBT, BT_TRACE, ("BT 3.0, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT20)
				RTPRINT(FBT, BT_TRACE, ("HT20, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_HT40)
				RTPRINT(FBT, BT_TRACE, ("HT40, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_LEGACY)
				RTPRINT(FBT, BT_TRACE, ("Legacy, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_LOW)
				RTPRINT(FBT, BT_TRACE, ("Rssi_Low, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_MEDIUM)
				RTPRINT(FBT, BT_TRACE, ("Rssi_Mid, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_RSSI_HIGH)
				RTPRINT(FBT, BT_TRACE, ("Rssi_High, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_IDLE)
				RTPRINT(FBT, BT_TRACE, ("Wifi_Idle, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_UPLINK)
				RTPRINT(FBT, BT_TRACE, ("Wifi_Uplink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_WIFI_DOWNLINK)
				RTPRINT(FBT, BT_TRACE, ("Wifi_Downlink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE)
				RTPRINT(FBT, BT_TRACE, ("BT_idle, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_PAN_IDLE)
				RTPRINT(FBT, BT_TRACE, ("BT_PAN_idle, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_PAN_UPLINK)
				RTPRINT(FBT, BT_TRACE, ("BT_PAN_uplink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_PAN_DOWNLINK)
				RTPRINT(FBT, BT_TRACE, ("BT_PAN_downlink, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_HID)
				RTPRINT(FBT, BT_TRACE, ("PRO_HID, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_A2DP)
				RTPRINT(FBT, BT_TRACE, ("PRO_A2DP, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_PAN)
				RTPRINT(FBT, BT_TRACE, ("PRO_PAN, "));
			if (pHalData->bt_coexist.CurrentState & BT_COEX_STATE_PROFILE_SCO)
				RTPRINT(FBT, BT_TRACE, ("PRO_SCO, "));
			RTPRINT(FBT, BT_TRACE, ("]\n"));
		}
	}
}

// ===== End of sync from SD7 driver HAL/BTCoexist/HalBtcCsr2Ant.c =====
#endif

#ifdef __HALBTCOEXIST_C__ // HAL/BTCoexist/HalBtCoexist.c
// ===== Below this line is sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c =====

//============================================================
// local function
//============================================================
static void btdm_BTCoexistWithProfile(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.BT_Ant_Num == Ant_x2)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], 2 Ant mechanism\n"));
		BTDM_BTCoexistWithProfile2Ant(padapter);
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], 1 Ant mechanism\n"));
		BTDM_BTCoexistWithProfile1Ant(padapter);
	}
}

static void btdm_ResetFWCoexState(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	pHalData->bt_coexist.CurrentState = 0;
	pHalData->bt_coexist.PreviousState = 0;
}

static void btdm_InitBtCoexistDM(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);

	// 20100415 Joseph: Restore RF register 0x1E and 0x1F value for further usage.
	pHalData->bt_coexist.BtRfRegOrigin1E = PHY_QueryRFReg(padapter, PathA, RF_RCK1, bRFRegOffsetMask);
	pHalData->bt_coexist.BtRfRegOrigin1F = PHY_QueryRFReg(padapter, PathA, RF_RCK2, 0xf0);

	pHalData->bt_coexist.CurrentState = 0;
	pHalData->bt_coexist.PreviousState = 0;

	BTDM_8723AInit(padapter);
	pHalData->bt_coexist.bInitlized = _TRUE;
}

//============================================================
// extern function
//============================================================
void BTDM_CheckAntSelMode(struct rtw_adapter *padapter)
{
}

static u8 BTDM_NeedToRoamForBtEnableDisable(struct rtw_adapter *padapter)
{
	return _FALSE;
}

void BTDM_FwC2hBtRssi(struct rtw_adapter *padapter, u8 *tmpBuf)
{
	BTDM_FwC2hBtRssi8723A(padapter, tmpBuf);
}

void BTDM_FwC2hBtInfo(struct rtw_adapter *padapter, u8 *tmpBuf, u8 length)
{
	BTDM_FwC2hBtInfo8723A(padapter, tmpBuf, length);
}

void BTDM_DisplayBtCoexInfo(struct rtw_adapter *padapter)
{
	BTDM_Display8723ABtCoexInfo(padapter);
}

void BTDM_RejectAPAggregatedPacket(struct rtw_adapter *padapter, u8 bReject)
{
}

u8 BTDM_IsHT40(struct rtw_adapter *padapter)
{
	u8 isHT40 = _TRUE;
	HT_CHANNEL_WIDTH bw;

	bw = padapter->mlmeextpriv.cur_bwmode;

	if (bw == HT_CHANNEL_WIDTH_20)
	{
		isHT40 = _FALSE;
	}
	else if (bw == HT_CHANNEL_WIDTH_40)
	{
		isHT40 = _TRUE;
	}

	return isHT40;
}

u8 BTDM_Legacy(struct rtw_adapter *padapter)
{
	struct mlme_ext_priv *pmlmeext;
	u8			isLegacy = _FALSE;

	pmlmeext = &padapter->mlmeextpriv;
	if ((pmlmeext->cur_wireless_mode == WIRELESS_11B) ||
		(pmlmeext->cur_wireless_mode == WIRELESS_11G) ||
		(pmlmeext->cur_wireless_mode == WIRELESS_11BG))
		isLegacy = _TRUE;

	return isLegacy;
}

void BTDM_CheckWiFiState(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	struct mlme_priv *pmlmepriv;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;


	pHalData = GET_HAL_DATA(padapter);
	pmlmepriv = &padapter->mlmepriv;
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;

	if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_IDLE;

		if (pmlmepriv->LinkDetectInfo.bTxBusyTraffic)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_UPLINK;
		}
		else
		{
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK;
		}

		if (pmlmepriv->LinkDetectInfo.bRxBusyTraffic)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_DOWNLINK;
		}
		else
		{
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK;
		}
	}
	else
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_IDLE;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_UPLINK;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_DOWNLINK;
	}

	if (BTDM_Legacy(padapter))
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_LEGACY;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20;
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_LEGACY;
		if (BTDM_IsHT40(padapter))
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT40;
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT20;
		}
		else
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_HT20;
			pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_HT40;
		}
	}

	if (pBtMgnt->BtOperationOn)
	{
		pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_BT30;
	}
	else
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_BT30;
	}
}

s32 BTDM_GetRxSS(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv;
	PHAL_DATA_TYPE	pHalData;
	s32			UndecoratedSmoothedPWDB = 0;


	pmlmepriv = &padapter->mlmepriv;
	pHalData = GET_HAL_DATA(padapter);

//	if (pMgntInfo->bMediaConnect)	// Default port
	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
	{
		UndecoratedSmoothedPWDB = GET_UNDECORATED_AVERAGE_RSSI(padapter);
	}
	else // associated entry pwdb
	{
		UndecoratedSmoothedPWDB = pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB;
		//pHalData->BT_EntryMinUndecoratedSmoothedPWDB
	}
	RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxSS() = %d\n", UndecoratedSmoothedPWDB));
	return UndecoratedSmoothedPWDB;
}

static s32 BTDM_GetRxBeaconSS(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	struct mlme_priv *pmlmepriv;
	PHAL_DATA_TYPE	pHalData;
	s32			pwdbBeacon = 0;


	pmlmepriv = &padapter->mlmepriv;
	pHalData = GET_HAL_DATA(padapter);

//	if (pMgntInfo->bMediaConnect)	// Default port
	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
	{
		//pwdbBeacon = pHalData->dmpriv.UndecoratedSmoothedBeacon;
		pwdbBeacon= pHalData->dmpriv.EntryMinUndecoratedSmoothedPWDB;
	}
	RTPRINT(FBT, BT_TRACE, ("BTDM_GetRxBeaconSS() = %d\n", pwdbBeacon));
	return pwdbBeacon;
}

// Get beacon rssi state
u8
BTDM_CheckCoexBcnRssiState(
	struct rtw_adapter *	padapter,
	u8			levelNum,
	u8			RssiThresh,
	u8			RssiThresh1
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	s32			pwdbBeacon = 0;
	u8			bcnRssiState;

	pwdbBeacon = BTDM_GetRxBeaconSS(padapter);

	if (levelNum == 2)
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;

		if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) ||
			(pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW))
		{
			if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL))
			{
				bcnRssiState = BT_RSSI_STATE_HIGH;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n"));
			}
			else
			{
				bcnRssiState = BT_RSSI_STATE_STAY_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n"));
			}
		}
		else
		{
			if (pwdbBeacon < RssiThresh)
			{
				bcnRssiState = BT_RSSI_STATE_LOW;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n"));
			}
			else
			{
				bcnRssiState = BT_RSSI_STATE_STAY_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n"));
			}
		}
	}
	else if (levelNum == 3)
	{
		if (RssiThresh > RssiThresh1)
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON thresh error!!\n"));
			return pHalData->bt_coexist.preRssiStateBeacon;
		}

		if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_LOW) ||
			(pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_LOW))
		{
			if (pwdbBeacon >= (RssiThresh+BT_FW_COEX_THRESH_TOL))
			{
				bcnRssiState = BT_RSSI_STATE_MEDIUM;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n"));
			}
			else
			{
				bcnRssiState = BT_RSSI_STATE_STAY_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Low\n"));
			}
		}
		else if ((pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_MEDIUM) ||
			(pHalData->bt_coexist.preRssiStateBeacon == BT_RSSI_STATE_STAY_MEDIUM))
		{
			if (pwdbBeacon >= (RssiThresh1+BT_FW_COEX_THRESH_TOL))
			{
				bcnRssiState = BT_RSSI_STATE_HIGH;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to High\n"));
			}
			else if (pwdbBeacon < RssiThresh)
			{
				bcnRssiState = BT_RSSI_STATE_LOW;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Low\n"));
			}
			else
			{
				bcnRssiState = BT_RSSI_STATE_STAY_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at Medium\n"));
			}
		}
		else
		{
			if (pwdbBeacon < RssiThresh1)
			{
				bcnRssiState = BT_RSSI_STATE_MEDIUM;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_BEACON_MEDIUM;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_BEACON_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state switch to Medium\n"));
			}
			else
			{
				bcnRssiState = BT_RSSI_STATE_STAY_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_BEACON state stay at High\n"));
			}
		}
	}

	pHalData->bt_coexist.preRssiStateBeacon = bcnRssiState;

	return bcnRssiState;
}

u8
BTDM_CheckCoexRSSIState1(
	struct rtw_adapter *	padapter,
	u8			levelNum,
	u8			RssiThresh,
	u8			RssiThresh1
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	s32			UndecoratedSmoothedPWDB = 0;
	u8			btRssiState;

	UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter);

	if (levelNum == 2)
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;

		if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) ||
			(pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW))
		{
			if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL))
			{
				btRssiState = BT_RSSI_STATE_HIGH;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n"));
			}
		}
		else
		{
			if (UndecoratedSmoothedPWDB < RssiThresh)
			{
				btRssiState = BT_RSSI_STATE_LOW;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n"));
			}
		}
	}
	else if (levelNum == 3)
	{
		if (RssiThresh > RssiThresh1)
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 thresh error!!\n"));
			return pHalData->bt_coexist.preRssiState1;
		}

		if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_LOW) ||
			(pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_LOW))
		{
			if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL))
			{
				btRssiState = BT_RSSI_STATE_MEDIUM;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Low\n"));
			}
		}
		else if ((pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_MEDIUM) ||
			(pHalData->bt_coexist.preRssiState1 == BT_RSSI_STATE_STAY_MEDIUM))
		{
			if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL))
			{
				btRssiState = BT_RSSI_STATE_HIGH;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to High\n"));
			}
			else if (UndecoratedSmoothedPWDB < RssiThresh)
			{
				btRssiState = BT_RSSI_STATE_LOW;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Low\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at Medium\n"));
			}
		}
		else
		{
			if (UndecoratedSmoothedPWDB < RssiThresh1)
			{
				btRssiState = BT_RSSI_STATE_MEDIUM;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state switch to Medium\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI_1 state stay at High\n"));
			}
		}
	}

	pHalData->bt_coexist.preRssiState1 = btRssiState;

	return btRssiState;
}

u8
BTDM_CheckCoexRSSIState(
	struct rtw_adapter *	padapter,
	u8			levelNum,
	u8			RssiThresh,
	u8			RssiThresh1
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	s32			UndecoratedSmoothedPWDB = 0;
	u8			btRssiState;

	UndecoratedSmoothedPWDB = BTDM_GetRxSS(padapter);

	if (levelNum == 2)
	{
		pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;

		if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) ||
			(pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW))
		{
			if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL))
			{
				btRssiState = BT_RSSI_STATE_HIGH;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n"));
			}
		}
		else
		{
			if (UndecoratedSmoothedPWDB < RssiThresh)
			{
				btRssiState = BT_RSSI_STATE_LOW;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n"));
			}
		}
	}
	else if (levelNum == 3)
	{
		if (RssiThresh > RssiThresh1)
		{
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI thresh error!!\n"));
			return pHalData->bt_coexist.preRssiState;
		}

		if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_LOW) ||
			(pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_LOW))
		{
			if (UndecoratedSmoothedPWDB >= (RssiThresh+BT_FW_COEX_THRESH_TOL))
			{
				btRssiState = BT_RSSI_STATE_MEDIUM;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Low\n"));
			}
		}
		else if ((pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_MEDIUM) ||
			(pHalData->bt_coexist.preRssiState == BT_RSSI_STATE_STAY_MEDIUM))
		{
			if (UndecoratedSmoothedPWDB >= (RssiThresh1+BT_FW_COEX_THRESH_TOL))
			{
				btRssiState = BT_RSSI_STATE_HIGH;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to High\n"));
			}
			else if (UndecoratedSmoothedPWDB < RssiThresh)
			{
				btRssiState = BT_RSSI_STATE_LOW;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_LOW;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
			RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Low\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_MEDIUM;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at Medium\n"));
			}
		}
		else
		{
			if (UndecoratedSmoothedPWDB < RssiThresh1)
			{
				btRssiState = BT_RSSI_STATE_MEDIUM;
				pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
				pHalData->bt_coexist.CurrentState &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state switch to Medium\n"));
			}
			else
			{
				btRssiState = BT_RSSI_STATE_STAY_HIGH;
				RTPRINT(FBT, BT_TRACE, ("[DM][BT], RSSI state stay at High\n"));
			}
		}
	}

	pHalData->bt_coexist.preRssiState = btRssiState;

	return btRssiState;
}

u8 BTDM_DisableEDCATurbo(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &padapter->MgntInfo;
	PBT_MGNT		pBtMgnt;
	PHAL_DATA_TYPE	pHalData;
	u8			bBtChangeEDCA = _FALSE;
	u32			EDCA_BT_BE = 0x5ea42b, cur_EDCA_reg;
	u16			aggr_num;
	u8			bRet = _FALSE;


	pHalData = GET_HAL_DATA(padapter);
	pBtMgnt = &pHalData->BtInfo.BtMgnt;

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		bRet = _FALSE;
		pHalData->bt_coexist.lastBtEdca = 0;
		return bRet;
	}
	if (!((pBtMgnt->bSupportProfile) ||
		(pHalData->bt_coexist.BT_CoexistType == BT_CSR_BC8)))
	{
		bRet = _FALSE;
		pHalData->bt_coexist.lastBtEdca = 0;
		return bRet;
	}

	if (BT_1Ant(padapter))
	{
		bRet = _FALSE;
		pHalData->bt_coexist.lastBtEdca = 0;
		return bRet;
	}

	if (pHalData->bt_coexist.exec_cnt < 3)
		pHalData->bt_coexist.exec_cnt++;
	else
		pHalData->bt_coexist.bEDCAInitialized = _TRUE;

	// When BT is non idle
	if (!(pHalData->bt_coexist.CurrentState & BT_COEX_STATE_BT_IDLE))
	{
		RTPRINT(FBT, BT_TRACE, ("BT state non idle, set bt EDCA\n"));

		//aggr_num = 0x0909;
		if (pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA == _TRUE)
		{
			bBtChangeEDCA = _TRUE;
			pHalData->odmpriv.DM_EDCA_Table.bCurrentTurboEDCA = _FALSE;
//			pHalData->bIsCurRDLState = _FALSE;
			pHalData->dmpriv.prv_traffic_idx = 3;
		}
		cur_EDCA_reg = rtw_read32(padapter, REG_EDCA_BE_PARAM);

		if (cur_EDCA_reg != EDCA_BT_BE)
		{
			bBtChangeEDCA = _TRUE;
		}
		if (bBtChangeEDCA || !pHalData->bt_coexist.bEDCAInitialized)
		{
			rtw_write32(padapter, REG_EDCA_BE_PARAM, EDCA_BT_BE);
			pHalData->bt_coexist.lastBtEdca = EDCA_BT_BE;
		}
		bRet = _TRUE;
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("BT state idle, set original EDCA\n"));
		pHalData->bt_coexist.lastBtEdca = 0;
		bRet = _FALSE;
	}
	return bRet;
}

void
BTDM_Balance(
	struct rtw_adapter *	padapter,
	u8			bBalanceOn,
	u8			ms0,
	u8			ms1
	)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8	H2C_Parameter[3] = {0};

	if (bBalanceOn)
	{
		H2C_Parameter[2] = 1;
		H2C_Parameter[1] = ms1;
		H2C_Parameter[0] = ms0;
		pHalData->bt_coexist.bFWCoexistAllOff = _FALSE;
	}
	else
	{
		H2C_Parameter[2] = 0;
		H2C_Parameter[1] = 0;
		H2C_Parameter[0] = 0;
	}
	pHalData->bt_coexist.bBalanceOn = bBalanceOn;

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], Balance=[%s:%dms:%dms], write 0xc=0x%x\n",
		bBalanceOn?"ON":"OFF", ms0, ms1,
		H2C_Parameter[0]<<16|H2C_Parameter[1]<<8|H2C_Parameter[2]));

	FillH2CCmd(padapter, 0xc, 3, H2C_Parameter);
}

void BTDM_AGCTable(struct rtw_adapter *padapter, u8 type)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
	if (type == BT_AGCTABLE_OFF)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable Off!\n"));
		rtw_write32(padapter, 0xc78,0x641c0001);
		rtw_write32(padapter, 0xc78,0x631d0001);
		rtw_write32(padapter, 0xc78,0x621e0001);
		rtw_write32(padapter, 0xc78,0x611f0001);
		rtw_write32(padapter, 0xc78,0x60200001);

		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x32000);
		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x71000);
		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xb0000);
		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xfc000);
		PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x30355);

		pHalData->bt_coexist.b8723aAgcTableOn = _FALSE;
	}
	else if (type == BT_AGCTABLE_ON)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]AGCTable On!\n"));
		rtw_write32(padapter, 0xc78,0x4e1c0001);
		rtw_write32(padapter, 0xc78,0x4d1d0001);
		rtw_write32(padapter, 0xc78,0x4c1e0001);
		rtw_write32(padapter, 0xc78,0x4b1f0001);
		rtw_write32(padapter, 0xc78,0x4a200001);

		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0xdc000);
		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x90000);
		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x51000);
		PHY_SetRFReg(padapter, PathA, RF_RX_AGC_HP, bRFRegOffsetMask, 0x12000);
		PHY_SetRFReg(padapter, PathA, RF_RX_G1, bRFRegOffsetMask, 0x00355);

		pHalData->bt_coexist.b8723aAgcTableOn = _TRUE;

		pHalData->bt_coexist.bSWCoexistAllOff = _FALSE;
	}
}

void BTDM_BBBackOffLevel(struct rtw_adapter *padapter, u8 type)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (type == BT_BB_BACKOFF_OFF)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel Off!\n"));
		rtw_write32(padapter, 0xc04,0x3a05611);
	}
	else if (type == BT_BB_BACKOFF_ON)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT]BBBackOffLevel On!\n"));
		rtw_write32(padapter, 0xc04,0x3a07611);
		pHalData->bt_coexist.bSWCoexistAllOff = _FALSE;
	}
}

void BTDM_FWCoexAllOff(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);;


	RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff()\n"));
	if (pHalData->bt_coexist.bFWCoexistAllOff)
		return;
	RTPRINT(FBT, BT_TRACE, ("BTDM_FWCoexAllOff(), real Do\n"));

	BTDM_FWCoexAllOff8723A(padapter);

	pHalData->bt_coexist.bFWCoexistAllOff = _TRUE;
}

void BTDM_SWCoexAllOff(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);;


	RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff()\n"));
	if (pHalData->bt_coexist.bSWCoexistAllOff)
		return;
	RTPRINT(FBT, BT_TRACE, ("BTDM_SWCoexAllOff(), real Do\n"));
	BTDM_SWCoexAllOff8723A(padapter);

	pHalData->bt_coexist.bSWCoexistAllOff = _TRUE;
}

void BTDM_HWCoexAllOff(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);;


	RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff()\n"));
	if (pHalData->bt_coexist.bHWCoexistAllOff)
		return;
	RTPRINT(FBT, BT_TRACE, ("BTDM_HWCoexAllOff(), real Do\n"));

	BTDM_HWCoexAllOff8723A(padapter);

	pHalData->bt_coexist.bHWCoexistAllOff = _TRUE;
}

void BTDM_CoexAllOff(struct rtw_adapter *padapter)
{
	BTDM_FWCoexAllOff(padapter);
	BTDM_SWCoexAllOff(padapter);
	BTDM_HWCoexAllOff(padapter);
}

static void BTDM_TurnOffBtCoexistBeforeEnterLPS(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;


	// Add temporarily.
	if ((!pHalData->bt_coexist.BluetoothCoexist) ||(!pBtMgnt->bSupportProfile))
		return;

	// 8723 1Ant doesn't need to turn off bt coexist mechanism.
	if (BTDM_1Ant8723A(padapter))
		return;

	//
	// Before enter LPS, turn off FW BT Co-exist mechanism
	//
	if (ppwrctrl->bLeisurePs)
	{
		RTPRINT(FBT, BT_TRACE, ("[BT][DM], Before enter LPS, turn off all Coexist DM\n"));
		btdm_ResetFWCoexState(padapter);
		BTDM_CoexAllOff(padapter);
		BTDM_SetAntenna(padapter, BTDM_ANT_BT);
	}
}

void BTDM_TurnOffBtCoexistBeforeEnterIPS(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
//	PRT_POWER_SAVE_CONTROL	pPSC = GET_POWER_SAVE_CONTROL(pMgntInfo);
	struct pwrctrl_priv *ppwrctrl = &padapter->pwrctrlpriv;

	if (!pHalData->bt_coexist.BluetoothCoexist)
		return;

	// 8723 1Ant doesn't need to turn off bt coexist mechanism.
	if (BTDM_1Ant8723A(padapter))
		return;

	//
	// Before enter IPS, turn off FW BT Co-exist mechanism
	//
	if (ppwrctrl->reg_rfoff == rf_on) {
		RTPRINT(FBT, BT_TRACE, ("[BT][DM], Before enter IPS, turn off all Coexist DM\n"));
		btdm_ResetFWCoexState(padapter);
		BTDM_CoexAllOff(padapter);
		BTDM_SetAntenna(padapter, BTDM_ANT_BT);
	}
}

void BTDM_SignalCompensation(struct rtw_adapter *padapter, u8 *rssi_wifi, u8 *rssi_bt)
{
	BTDM_8723ASignalCompensation(padapter, rssi_wifi, rssi_bt);
}
#if defined(CONFIG_CHECK_BT_HANG) && defined(CONFIG_BT_COEXIST)
/*
0. write 0xa3 = 0x05

1. 0xa0 == 0x04
	write 0xF6?1:0] = 0x01
	write 0x3A[7:0] = 0x31

2. read 0xC0[31:0] == 0
	write 0xcc{2]= 1

3. read X=0x6b[4]
	if X== 1
	{
		write 0x6b[4] = 0
		write 0xcc{2]= 0
	}
	else if X == 0
	{
		write 0x6b[4] = 1
		write 0xcc{2]= 0
	}

*/
void dm_CheckBTState(struct rtw_adapter *pAdapter)
{
	u8 value=0,regValue8=0;
	u32 regvalue32=0;
	//_adapter *pAdapter = (struct rtw_adapter*)context;

//	if (pAdapter->drv_in_test == CMCC_TEST)
//		return;

	rtw_write8(pAdapter, 0xa3, 5);

	//DBG_8723A("------>%s,get 0xa3=%0x\n",__func__,rtw_read8(pAdapter, 0xa3));

	regValue8 = rtw_read8(pAdapter, 0xa0);
	//DBG_8723A("Get 0xa0 = 0x%x\n",regValue8);
	if(regValue8 == 0x4){
		value = rtw_read8(pAdapter, 0xf6);
		value &= ~3;
		value |= 1;
		rtw_write8(pAdapter, 0xf6, value);
		rtw_write8(pAdapter, 0x3A, 0x31);
	}

	regvalue32 = rtw_read32(pAdapter, 0xc0);
	//DBG_8723A("Get 0xc0 = 0x%x\n",regvalue32);
	if(rtw_read32(pAdapter, 0xc0) == 0x0){
		value = rtw_read8(pAdapter, 0xcc);
		value |= 0x4;
		rtw_write8(pAdapter, 0xcc, value);
	}

	regValue8 = rtw_read8(pAdapter, 0x6b); //0x6b[28]
	//DBG_8723A("Get 0x6b = 0x%x\n",regValue8);

	if((regValue8 & 0x10) == 0x10){
		regValue8 &= 0xEF;
		rtw_write8(pAdapter, 0x6b, regValue8);
		value = rtw_read8(pAdapter, 0xcc);
		value &= 0xfb;
		rtw_write8(pAdapter, 0xcc, value);
	}
	else if ((regValue8 & 0x10) == 0){
		regValue8 |= 0x10;
		rtw_write8(pAdapter, 0x6b, regValue8);
		value = rtw_read8(pAdapter, 0xcc);
		value &= 0xfb;
		rtw_write8(pAdapter, 0xcc, value);
	}

	//DBG_8723A("<------%s,get 0x6b=0x%0x,0xcc=0x%x\n",__func__,rtw_read8(pAdapter, 0x6b),rtw_read8(pAdapter, 0xcc));
}

void check_bt_status_work(void *data)
{
	struct delayed_work *dwork;
	struct rtw_adapter *padapter;

	dwork = container_of(data, struct delayed_work, work);
	padapter = container_of(dwork, struct _ADAPTER, checkbt_work);
	if(!padapter)
	{
		DBG_8723A("%s padapter == NULL\n", __func__);
		return;
	};

	dm_CheckBTState(padapter);
}
#endif
void BTDM_Coexist(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);

#if defined(CONFIG_CONCURRENT_MODE)
	if (padapter->adapter_type != PRIMARY_ADAPTER)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], CONFIG_CONCURRENT_MODE  !!\n"));
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], padapter->adapter_type != PRIMARY_ADAPTER  !!\n"));
		return;
	}
#endif

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], BT not exists!!\n"));
		return;
	}

	if (!pHalData->bt_coexist.bInitlized)
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], btdm_InitBtCoexistDM()\n"));
		btdm_InitBtCoexistDM(padapter);
	}

	RTPRINT(FBT, BT_TRACE, ("\n\n[DM][BT], BTDM start!!\n"));

	BTDM_PWDBMonitor(padapter);

	RTPRINT(FBT, BT_TRACE, ("[DM][BT], HW type is 8723\n"));
	BTDM_BTCoexist8723A(padapter);
	RTPRINT(FBT, BT_TRACE, ("[DM][BT], BTDM end!!\n\n"));
}

void BTDM_UpdateCoexState(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);

	if (!BTDM_IsSameCoexistState(padapter))
	{
		RTPRINT(FBT, BT_TRACE, ("[BTCoex], Coexist State[bitMap] change from 0x%"i64fmt"x to 0x%"i64fmt"x,  changeBits=0x%"i64fmt"x\n",
			pHalData->bt_coexist.PreviousState,
			pHalData->bt_coexist.CurrentState,
			(pHalData->bt_coexist.PreviousState^pHalData->bt_coexist.CurrentState)));
		pHalData->bt_coexist.PreviousState = pHalData->bt_coexist.CurrentState;
	}
}

u8 BTDM_IsSameCoexistState(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
	{
		return _TRUE;
	}
	else
	{
		RTPRINT(FBT, BT_TRACE, ("[DM][BT], Coexist state changed!!\n"));
		return _FALSE;
	}
}

void BTDM_PWDBMonitor(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &(GetDefaultAdapter(padapter)->MgntInfo);
	PBT30Info		pBTInfo = GET_BT_INFO(GetDefaultAdapter(padapter));
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8			H2C_Parameter[3] = {0};
	s32			tmpBTEntryMaxPWDB=0, tmpBTEntryMinPWDB=0xff;
	u8			i;

	if (pBtMgnt->BtOperationOn)
	{
		for (i = 0; i < MAX_BT_ASOC_ENTRY_NUM; i++)
		{
			if (pBTInfo->BtAsocEntry[i].bUsed)
			{
				if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB < tmpBTEntryMinPWDB)
					tmpBTEntryMinPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB;
				if (pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB > tmpBTEntryMaxPWDB)
					tmpBTEntryMaxPWDB = pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB;

				//
				// Report every BT connection (HS mode) RSSI to FW
				//
				H2C_Parameter[2] = (u8)(pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB & 0xFF);
				H2C_Parameter[0] = (MAX_FW_SUPPORT_MACID_NUM-1-i);
				RTPRINT(FDM, DM_BT30, ("RSSI report for BT[%d], H2C_Par = 0x%x\n", i, H2C_Parameter[0]));
				FillH2CCmd(padapter, RSSI_SETTING_EID, 3, H2C_Parameter);
				RTPRINT_ADDR(FDM, (DM_PWDB|DM_BT30), ("BT_Entry Mac :"), pBTInfo->BtAsocEntry[i].BTRemoteMACAddr)
				RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT rx pwdb[%d] = 0x%x(%d)\n", i, pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB,
					pBTInfo->BtAsocEntry[i].UndecoratedSmoothedPWDB));
			}
		}
		if (tmpBTEntryMaxPWDB != 0)	// If associated entry is found
		{
			pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = tmpBTEntryMaxPWDB;
			RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMaxPWDB = 0x%x(%d)\n",
				tmpBTEntryMaxPWDB, tmpBTEntryMaxPWDB));
		}
		else
		{
			pHalData->dmpriv.BT_EntryMaxUndecoratedSmoothedPWDB = 0;
		}
		if (tmpBTEntryMinPWDB != 0xff) // If associated entry is found
		{
			pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = tmpBTEntryMinPWDB;
			RTPRINT(FDM, (DM_PWDB|DM_BT30), ("BT_EntryMinPWDB = 0x%x(%d)\n",
				tmpBTEntryMinPWDB, tmpBTEntryMinPWDB));
		}
		else
		{
			pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB = 0;
		}
	}
}

static u8 BTDM_DigByBtRssi(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &(GetDefaultAdapter(padapter)->MgntInfo);
	PBT30Info		pBTInfo = GET_BT_INFO(GetDefaultAdapter(padapter));
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
	u8				bRet = _FALSE;
	PDM_ODM_T		pDM_OutSrc = &pHalData->odmpriv;
	u8				digForBtHs=0, cckCcaThres=0;


	//
	// When running under HS mode, use bt related Dig and cck threshold.
	//
	if (pBtMgnt->BtOperationOn)
	{
		if (pBtMgnt->bBTConnectInProgress) {
			digForBtHs = 0x28;
		} else {
			//
			// Decide DIG value by BT RSSI.
			//
			digForBtHs = (u8)pHalData->dmpriv.BT_EntryMinUndecoratedSmoothedPWDB;

			digForBtHs += 0x04;

			if (digForBtHs > DM_DIG_MAX_NIC)
				digForBtHs = DM_DIG_MAX_NIC;
			if (digForBtHs < DM_DIG_MIN_NIC)
				digForBtHs = DM_DIG_MIN_NIC;

			RTPRINT(FDM, DM_BT30, ("BTDM_DigByBtRssi(), digForBtHs=0x%x\n",
					digForBtHs));
		}
		ODM_Write_DIG(pDM_OutSrc, digForBtHs);

		//
		// Decide cck packet threshold
		//
		cckCcaThres = 0xcd;
		ODM_Write_CCK_CCA_Thres(pDM_OutSrc, cckCcaThres);

		bRet = _TRUE;
	}

	return bRet;
}

u8 BTDM_IsBTBusy(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_MGNT		pBtMgnt = &pBTInfo->BtMgnt;

	if (pBtMgnt->ExtConfig.bBTBusy)
		return _TRUE;
	else
		return _FALSE;
}

u8 BTDM_IsWifiBusy(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &(GetDefaultAdapter(padapter)->MgntInfo);
	struct mlme_priv *pmlmepriv = &(GetDefaultAdapter(padapter)->mlmepriv);
	PBT30Info		pBTInfo = GET_BT_INFO(padapter);
	PBT_TRAFFIC	pBtTraffic = &pBTInfo->BtTraffic;


	if (pmlmepriv->LinkDetectInfo.bBusyTraffic ||
		pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic ||
		pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic)
		return _TRUE;
	else
		return _FALSE;
}

u8 BTDM_IsCoexistStateChanged(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.PreviousState == pHalData->bt_coexist.CurrentState)
		return _FALSE;
	else
		return _TRUE;
}

u8 BTDM_IsWifiUplink(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &(GetDefaultAdapter(padapter)->MgntInfo);
	struct mlme_priv *pmlmepriv;
	PBT30Info		pBTInfo;
	PBT_TRAFFIC		pBtTraffic;


	pmlmepriv = &padapter->mlmepriv;
	pBTInfo = GET_BT_INFO(padapter);
	pBtTraffic = &pBTInfo->BtTraffic;

	if ((pmlmepriv->LinkDetectInfo.bTxBusyTraffic) ||
		(pBtTraffic->Bt30TrafficStatistics.bTxBusyTraffic))
		return _TRUE;
	else
		return _FALSE;
}

u8 BTDM_IsWifiDownlink(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &(GetDefaultAdapter(padapter)->MgntInfo);
	struct mlme_priv *pmlmepriv;
	PBT30Info		pBTInfo;
	PBT_TRAFFIC		pBtTraffic;


	pmlmepriv = &padapter->mlmepriv;
	pBTInfo = GET_BT_INFO(padapter);
	pBtTraffic = &pBTInfo->BtTraffic;

	if ((pmlmepriv->LinkDetectInfo.bRxBusyTraffic) ||
		(pBtTraffic->Bt30TrafficStatistics.bRxBusyTraffic))
		return _TRUE;
	else
		return _FALSE;
}

u8 BTDM_IsBTHSMode(struct rtw_adapter *padapter)
{
//	PMGNT_INFO		pMgntInfo = &(GetDefaultAdapter(padapter)->MgntInfo);
	PHAL_DATA_TYPE	pHalData;
	PBT_MGNT		pBtMgnt;


	pHalData = GET_HAL_DATA(padapter);
	pBtMgnt = &pHalData->BtInfo.BtMgnt;

	if (pBtMgnt->BtOperationOn)
		return _TRUE;
	else
		return _FALSE;
}

u8 BTDM_IsBTUplink(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.BT21TrafficStatistics.bTxBusyTraffic)
		return _TRUE;
	else
		return _FALSE;
}

u8 BTDM_IsBTDownlink(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.BT21TrafficStatistics.bRxBusyTraffic)
		return _TRUE;
	else
		return _FALSE;
}

void BTDM_AdjustForBtOperation(struct rtw_adapter *padapter)
{
	RTPRINT(FBT, BT_TRACE, ("[BT][DM], BTDM_AdjustForBtOperation()\n"));
	BTDM_AdjustForBtOperation8723A(padapter);
}

static u8 BTDM_AdjustRssiForAgcTableOn(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.b92DAgcTableOn)
		return 12;

	if (pHalData->bt_coexist.b8723aAgcTableOn)
		return 6;

	return 0;
}

void BTDM_SetBtCoexCurrAntNum(struct rtw_adapter *padapter, u8 antNum)
{
	BTDM_Set8723ABtCoexCurrAntNum(padapter, antNum);
}

void BTDM_ForHalt(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		return;
	}

	BTDM_ForHalt8723A(padapter);
	GET_HAL_DATA(padapter)->bt_coexist.bInitlized = _FALSE;
}

void BTDM_WifiScanNotify(struct rtw_adapter *padapter, u8 scanType)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		return;
	}

	BTDM_WifiScanNotify8723A(padapter, scanType);
}

void BTDM_WifiAssociateNotify(struct rtw_adapter *padapter, u8 action)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		return;
	}

	BTDM_WifiAssociateNotify8723A(padapter, action);
}

void BTDM_MediaStatusNotify(struct rtw_adapter *padapter, RT_MEDIA_STATUS mstatus)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		return;
	}

	BTDM_MediaStatusNotify8723A(padapter, mstatus);
}

void BTDM_ForDhcp(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (!pHalData->bt_coexist.BluetoothCoexist)
	{
		return;
	}

	BTDM_ForDhcp8723A(padapter);
}

void BTDM_ResetActionProfileState(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	pHalData->bt_coexist.CurrentState &= ~\
		(BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP|
		BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_SCO);
}

u8 BTDM_IsActionSCO(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_DBG			pBtDbg;
	u8			bRet;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtDbg = &pBTInfo->BtDbg;
	bRet = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE)
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_SCO)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO;
			bRet = _TRUE;
		}
	}
	else
	{
		if (pBtMgnt->ExtConfig.NumberOfSCO > 0)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_SCO;
			bRet = _TRUE;
		}
	}
	return bRet;
}

u8 BTDM_IsActionHID(struct rtw_adapter *padapter)
{
	PBT30Info		pBTInfo;
	PHAL_DATA_TYPE	pHalData;
	PBT_MGNT		pBtMgnt;
	PBT_DBG			pBtDbg;
	u8			bRet;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtDbg = &pBTInfo->BtDbg;
	bRet = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID;
			bRet = _TRUE;
		}
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && pBtMgnt->ExtConfig.NumberOfHandle==1)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_HID;
			bRet = _TRUE;
		}
	}
	return bRet;
}

u8 BTDM_IsActionA2DP(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_DBG			pBtDbg;
	u8			bRet;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtDbg = &pBTInfo->BtDbg;
	bRet = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_A2DP)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP;
			bRet = _TRUE;
		}
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP) && pBtMgnt->ExtConfig.NumberOfHandle==1)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_A2DP;
			bRet = _TRUE;
		}
	}
	return bRet;
}

u8 BTDM_IsActionPAN(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_DBG			pBtDbg;
	u8			bRet;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtDbg = &pBTInfo->BtDbg;
	bRet = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE)
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN;
			bRet = _TRUE;
		}
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) && pBtMgnt->ExtConfig.NumberOfHandle==1)
		{
			pHalData->bt_coexist.CurrentState |= BT_COEX_STATE_PROFILE_PAN;
			bRet = _TRUE;
		}
	}
	return bRet;
}

u8 BTDM_IsActionHIDA2DP(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_MGNT		pBtMgnt;
	PBT_DBG			pBtDbg;
	u8			bRet;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTInfo->BtMgnt;
	pBtDbg = &pBTInfo->BtDbg;
	bRet = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE)
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_A2DP)
		{
			pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);
			bRet = _TRUE;
		}
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
		{
			pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_A2DP);
			bRet = _TRUE;
		}
	}
	return bRet;
}

u8 BTDM_IsActionHIDPAN(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_DBG			pBtDbg;
	u8			bRet;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtDbg = &pBTInfo->BtDbg;
	bRet = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_HID_PAN)
		{
			pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);
			bRet = _TRUE;
		}
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_HID) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN))
		{
			pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_HID|BT_COEX_STATE_PROFILE_PAN);
			bRet = _TRUE;
		}
	}
	return bRet;
}

u8 BTDM_IsActionPANA2DP(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;
	PBT30Info		pBTInfo;
	PBT_DBG			pBtDbg;
	u8			bRet;


	pHalData = GET_HAL_DATA(padapter);
	pBTInfo = GET_BT_INFO(padapter);
	pBtDbg = &pBTInfo->BtDbg;
	bRet = _FALSE;

	if (pBtDbg->dbgCtrl == _TRUE )
	{
		if (pBtDbg->dbgProfile == BT_DBG_PROFILE_PAN_A2DP)
		{
			pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);
			bRet = _TRUE;
		}
	}
	else
	{
		if (BTHCI_CheckProfileExist(padapter,BT_PROFILE_PAN) && BTHCI_CheckProfileExist(padapter,BT_PROFILE_A2DP))
		{
			pHalData->bt_coexist.CurrentState |= (BT_COEX_STATE_PROFILE_PAN|BT_COEX_STATE_PROFILE_A2DP);
			bRet = _TRUE;
		}
	}
	return bRet;
}

u8 BTDM_IsBtDisabled(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.bCurBtDisabled)
		return _TRUE;
	else
		return _FALSE;
}

//============================================
// Started with "WA_" means this is a work around function.
// Because fw need to count bt HW counters
//(BT_ACTIVE/BT_STATE/BT_POLLING)
// in beacon related interrupt, so we have to write beacon control
// register now.
//============================================
static void WA_BTDM_EnableBTFwCounterPolling(struct rtw_adapter *padapter)
{
}

// ===== End of sync from SD7 driver HAL/BTCoexist/HalBtCoexist.c =====
#endif

#ifdef __HALBT_C__ // HAL/HalBT.c
// ===== Below this line is sync from SD7 driver HAL/HalBT.c =====

//==================================================
//	local function
//==================================================

static void halbt_InitHwConfig8723A(struct rtw_adapter *padapter)
{
}

//==================================================
//	extern function
//==================================================
u8 HALBT_GetPGAntNum(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	return pHalData->bt_coexist.BT_Ant_Num;
}

void HALBT_SetKey(struct rtw_adapter *padapter, u8 EntryNum)
{
	PBT30Info		pBTinfo;
	PBT_ASOC_ENTRY	pBtAssocEntry;
	u16				usConfig = 0;


	pBTinfo = GET_BT_INFO(padapter);
	pBtAssocEntry = &(pBTinfo->BtAsocEntry[EntryNum]);

	pBtAssocEntry->HwCAMIndex = BT_HWCAM_STAR + EntryNum;

	usConfig = CAM_VALID | (CAM_AES << 2);
	write_cam(padapter, pBtAssocEntry->HwCAMIndex, usConfig, pBtAssocEntry->BTRemoteMACAddr, pBtAssocEntry->PTK + TKIP_ENC_KEY_POS);
}

void HALBT_RemoveKey(struct rtw_adapter *padapter, u8 EntryNum)
{
	PBT30Info		pBTinfo;
	PBT_ASOC_ENTRY	pBtAssocEntry;

	pBTinfo = GET_BT_INFO(padapter);
	pBtAssocEntry = &(pBTinfo->BtAsocEntry[EntryNum]);

	if (pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex != 0) {
		// ToDo : add New HALBT_RemoveKey function !!
		if (pBtAssocEntry->HwCAMIndex >= BT_HWCAM_STAR && pBtAssocEntry->HwCAMIndex < HALF_CAM_ENTRY)
			CAM_empty_entry(padapter, pBtAssocEntry->HwCAMIndex);
		pBTinfo->BtAsocEntry[EntryNum].HwCAMIndex = 0;
	}
}

void HALBT_InitBTVars8723A(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData;


	pHalData = GET_HAL_DATA(padapter);

	pHalData->bt_coexist.BluetoothCoexist = pHalData->EEPROMBluetoothCoexist;
	pHalData->bt_coexist.BT_Ant_Num = pHalData->EEPROMBluetoothAntNum;
	pHalData->bt_coexist.BT_CoexistType = pHalData->EEPROMBluetoothType;
	pHalData->bt_coexist.BT_Ant_isolation = pHalData->EEPROMBluetoothAntIsolation;
	pHalData->bt_coexist.BT_RadioSharedType = pHalData->EEPROMBluetoothRadioShared;

	RT_TRACE(_module_hal_init_c_, _drv_info_, ("BT Coexistance = 0x%x\n", pHalData->bt_coexist.BluetoothCoexist));
	if (pHalData->bt_coexist.BluetoothCoexist)
	{
		if (pHalData->bt_coexist.BT_Ant_Num == Ant_x2)
		{
			BTDM_SetBtCoexCurrAntNum(padapter, 2);
			RT_TRACE(_module_hal_init_c_, _drv_info_,("BlueTooth BT_Ant_Num = Antx2\n"));
//			DBG_8723A("%s WiFi BT coexist Ant_Num = Antx2\n",__func__);
		}
		else if (pHalData->bt_coexist.BT_Ant_Num == Ant_x1)
		{
			BTDM_SetBtCoexCurrAntNum(padapter, 1);
			RT_TRACE(_module_hal_init_c_, _drv_info_,("BlueTooth BT_Ant_Num = Antx1\n"));
//			DBG_8723A("%s WiFi BT coexist Ant_Num Ant_Num = Antx1\n",__func__);
		}
		pHalData->bt_coexist.bBTBusyTraffic = _FALSE;
		pHalData->bt_coexist.bBTTrafficModeSet = _FALSE;
		pHalData->bt_coexist.bBTNonTrafficModeSet = _FALSE;
		pHalData->bt_coexist.CurrentState = 0;
		pHalData->bt_coexist.PreviousState = 0;

		RT_TRACE(_module_hal_init_c_, _drv_info_,("BT_RadioSharedType = 0x%x\n", pHalData->bt_coexist.BT_RadioSharedType));
	}
}

u8 HALBT_IsBTExist(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	if (pHalData->bt_coexist.BluetoothCoexist)
		return _TRUE;
	else
		return _FALSE;
}

u8 HALBT_BTChipType(struct rtw_adapter *padapter)
{
	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);

	return pHalData->bt_coexist.BT_CoexistType;
}

void HALBT_InitHwConfig(struct rtw_adapter *padapter)
{
	halbt_InitHwConfig8723A(padapter);
	BTDM_Coexist(padapter);
}

static void HALBT_IPSRFOffCheck(struct rtw_adapter *padapter)
{
	PBT30Info		pBTinfo;
	PBT_MGNT		pBtMgnt;
	PHAL_DATA_TYPE	pHalData;


	pBTinfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTinfo->BtMgnt;
	pHalData = GET_HAL_DATA(padapter);

	if ((pHalData->bt_coexist.BluetoothCoexist) &&
		(pBtMgnt->bSupportProfile)) {
		RTPRINT(FBT, BT_TRACE, ("[BT][DM], HALBT_IPSRFOffCheck(), turn off all Coexist DM\n"));
		BTDM_CoexAllOff(padapter);
	}
}

static void HALBT_LPSRFOffCheck(struct rtw_adapter *padapter)
{
	PBT30Info		pBTinfo;
	PBT_MGNT		pBtMgnt;
	PHAL_DATA_TYPE	pHalData;


	pBTinfo = GET_BT_INFO(padapter);
	pBtMgnt = &pBTinfo->BtMgnt;
	pHalData = GET_HAL_DATA(padapter);

	if ((pHalData->bt_coexist.BluetoothCoexist) &&
		(pBtMgnt->bSupportProfile)) {
		RTPRINT(FBT, BT_TRACE, ("[BT][DM], HALBT_LPSRFOffCheck(), turn off all Coexist DM\n"));
		BTDM_CoexAllOff(padapter);
	}
}

void HALBT_SetRtsCtsNoLenLimit(struct rtw_adapter *padapter)
{
#if (RTS_CTS_NO_LEN_LIMIT == 1)
	rtw_write32(padapter, 0x4c8, 0xc140402);
#endif
}

static u8 HALBT_OnlySupport1T(struct rtw_adapter *padapter)
{
	return _FALSE;
}

static u8
HALBT_BtRegAccess(struct rtw_adapter *padapter, u32 accessType, u32 regType,
		  u32 regOffset, u32 wValue, u32 *pRetVal)
{
	*pRetVal = 0x223;
	return _TRUE;
}

static void HALBT_SwitchWirelessMode(struct rtw_adapter *padapter,
				     u8 targetWirelessMode)
{
}

// ===== End of sync from SD7 driver HAL/HalBT.c =====
#endif
