⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bt_hci.cpp

📁 用VC++实现在PC平台的主从蓝牙HCI层数据传输
💻 CPP
字号:
#include "StdAfx.h"
#include ".\bt_hci.h"

CBT_HCI::CBT_HCI(void)
{
	m_dwDeviceMode = BT_DEVICE_RS232;
	
	m_HCI_LAP[0] = 0x33;
	m_HCI_LAP[1] = 0x8B;
	m_HCI_LAP[2] = 0x9E;
}
/*
struct SA
{
	char aa[10];
	char ab[10];
}sa;
queue<SA> qa;

void fa(void)
{
	SA sb;

	sb.aa[0] = 1;
	sb.ab[1] = 2;

	sa = sb;

	qa.push(sa);
}
*/
CBT_HCI::~CBT_HCI(void)
{
}
// Response from HCI_EVT_COMAND_COMMPLETE
// Status Num_Current_IAC IAC_LAP   (Response)
// 1 Byte     1 Byte      3 Bytes
DWORD CBT_HCI::cmd_HCI_Read_Current_IAC_LAP()
{	
	BYTE	bParameter[HCI_CMD_READ_CURRENT_ICA_LAP];
	BYTE	bCmdGroup,bEvtCode,bEventLen;
	BYTE	bEvent[256];
	DWORD	dwResult = HCI_COMMANDERROR_OK;

	SendCommand(HCI_COMMAND_GROUPING,
			HCI_CMD_READ_CURRENT_ICA_LAP,HCI_CMD_READ_CURRENT_ICA_LAP_LEN,
			bParameter);
	do
	{
		dwResult = GetResponse(bCmdGroup,bEvtCode,bEventLen,bEvent,500);
		if (HCI_COMMANDERROR_OK != dwResult )
		{
			break;
		}
		dwResult = evt_HCI_Event_Grouping(HCI_CMD_READ_CURRENT_ICA_LAP,bEvtCode,bEvent);
		if (HCI_COMMANDERROR_OK != dwResult )
		{
			break;
		}
	}while (HCI_EVT_COMMAND_COMPLETE != bEvtCode );

	return dwResult;
}
// LAP	    Inquiry_Len Num_Response
// 3 Byte       1 Byte     1 Byte
DWORD CBT_HCI::cmd_HCI_Inquiry()
{
	BYTE	bParameter[HCI_CMD_INQUIRY] = {0x33,0x8B,0x9E,0x0A,0x40};
	BYTE	bCmdGroup,bEvtCode,bEventLen;
	BYTE	bEvent[256];
	DWORD	dwResult = HCI_COMMANDERROR_OK;

	m_vBT_Slaver_Device.clear();

	dwResult = cmd_HCI_Read_Current_IAC_LAP();	
	if (HCI_COMMANDERROR_OK == dwResult)
	{
		memcpy(bParameter,m_HCI_LAP,HCI_LAP_LEN);
		SendCommand(HCI_COMMAND_GROUPING,HCI_CMD_INQUIRY,HCI_CMD_INQUIRY_LEN,bParameter);
		do
		{			
			dwResult = GetResponse(bCmdGroup,bEvtCode,bEventLen,bEvent,0x0A*1280);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
			dwResult = evt_HCI_Event_Grouping(HCI_CMD_INQUIRY,bEvtCode,bEvent);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
		}while (HCI_EVT_INQUIRY_COMPLETE != bEvtCode );
	}
	
	return dwResult;
}
// BD_ADDR	Packet_Type Page_Scan_Repetition_Mode PS_Mode  Clock_Offset Allow_Role_Switch
// 6 Byte	  2 Byte    	1 Byte			       1 Byte      2 Byte      1 Byte
DWORD CBT_HCI::cmd_HCI_Create_Connection(BYTE bDeviceIndex)
{
	BYTE	bParameter[HCI_CMD_CREATE_CONNECTION_LEN] = {0};
	BYTE	bCmdGroup,bEvtCode,bEventLen;
	BYTE	bEvent[256];
	DWORD	dwResult = HCI_COMMANDERROR_OK;
	BT_SLAVER_DEVICE	SDevice;

	if (bDeviceIndex>=0 && bDeviceIndex<m_vBT_Slaver_Device.size())
	{ 
		SDevice = m_vBT_Slaver_Device[bDeviceIndex];

		memcpy(bParameter+00,SDevice.s_BD_ADDR,BT_BD_ADDR_LEN);
		memcpy(bParameter+10,SDevice.s_bClosck_Offset,2);
		bParameter[ 8] = SDevice.s_bPage_Scan_Repetition;
		bParameter[ 9] = SDevice.s_bPage_Scan_Mode;
		bParameter[ 6] = 0x18;
		bParameter[ 7] = 0xCC;
		bParameter[12] = 0x00;

		SendCommand(HCI_COMMAND_GROUPING,HCI_CMD_CREATE_CONNECTION,HCI_CMD_CREATE_CONNECTION_LEN,bParameter);
		do
		{
			dwResult = GetResponse(bCmdGroup,bEvtCode,bEventLen,bEvent,5000);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
			dwResult = evt_HCI_Event_Grouping(HCI_CMD_CREATE_CONNECTION,bEvtCode,bEvent,bDeviceIndex);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
		}while (HCI_EVT_CONNECTION_COMPLETE_EVENT != bEvtCode );
	}
	else
	{
		dwResult = ERROR_INDEX;
	}
	
	return dwResult;
}
// Connnection_Handle	Reason
// 2 Byte				1 Byte   
DWORD CBT_HCI::cmd_HCI_Disconnection(BYTE bDeviceIndex)
{
	BYTE	bParameter[HCI_CMD_CREATE_CONNECTION_LEN] = {0};
	BYTE	bCmdGroup,bEvtCode,bEventLen;
	BYTE	bEvent[256];
	DWORD	dwResult = HCI_COMMANDERROR_OK;
	BT_SLAVER_DEVICE	SDevice;

	if (bDeviceIndex>=0 && bDeviceIndex<m_vBT_Slaver_Device.size())
	{ 
		SDevice = m_vBT_Slaver_Device[bDeviceIndex];

		memcpy(bParameter+00,SDevice.s_bConnection_Handle,2);
		bParameter[2] = 0x13;

		SendCommand(HCI_COMMAND_GROUPING,HCI_CMD_DISCONNECT,HCI_CMD_DISCONNECT_LEN,bParameter);
		do
		{
			dwResult = GetResponse(bCmdGroup,bEvtCode,bEventLen,bEvent,5000);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
			dwResult = evt_HCI_Event_Grouping(HCI_CMD_DISCONNECT,bEvtCode,bEvent,bDeviceIndex);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
		}while (HCI_EVT_DISCONNECTION_COMPLETE_EVENT != bEvtCode );
	}
	else
	{
		dwResult = ERROR_INDEX;
	}
	
	return dwResult;
}
// BD_ADDR	Page_Scan_Repetition_Mode PS_Mode  Clock_Offset
// 6 Byte		1 Byte			       1 Byte      2 Byte   
DWORD CBT_HCI::cmd_HCI_Remote_Name_Request(BYTE bDeviceIndex)
{
	BYTE	bParameter[HCI_CMD_REMOTE_NAME_REQUEST_LEN] = {0};
	BYTE	bCmdGroup,bEvtCode,bEventLen;
	BYTE	bEvent[256];
	DWORD	dwResult = HCI_COMMANDERROR_OK;
	BT_SLAVER_DEVICE	SDevice;

	if (bDeviceIndex>=0 && bDeviceIndex<m_vBT_Slaver_Device.size())
	{ 
		SDevice = m_vBT_Slaver_Device[bDeviceIndex];

		memcpy(bParameter+0,SDevice.s_BD_ADDR,BT_BD_ADDR_LEN);
		memcpy(bParameter+8,SDevice.s_bClosck_Offset,2);
		bParameter[ 6] = SDevice.s_bPage_Scan_Repetition;
		bParameter[ 7] = SDevice.s_bPage_Scan_Mode;
		SendCommand(HCI_COMMAND_GROUPING,HCI_CMD_REMOTE_NAME_REQUEST,HCI_CMD_REMOTE_NAME_REQUEST_LEN,bParameter);
		do
		{
			dwResult = GetResponse(bCmdGroup,bEvtCode,bEventLen,bEvent,5000);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
			dwResult = evt_HCI_Event_Grouping(HCI_CMD_REMOTE_NAME_REQUEST,bEvtCode,bEvent,bDeviceIndex);
			if (HCI_COMMANDERROR_OK != dwResult )
			{
				break;
			}
		}while (HCI_EVT_REMOTE_NAME_REQUEST_COMPLETE_EVENT != bEvtCode);
	}
	else
	{
		dwResult = ERROR_INDEX;
	}
	
	return dwResult;
}
// HCI_COMMAND
// Command OpCode   Lenght
//    2 Byte		1 Byte
DWORD CBT_HCI::SendCommand(BYTE  bCmdGroup,WORD wOpCode,BYTE  bCmdLen,BYTE* pCmd)	
{
	UINT	uExternLen	= 0;
	BYTE*	pBuffer = new BYTE[256];

	if (BT_DEVICE_RS232 == m_dwDeviceMode || BT_DEVICE_UART == m_dwDeviceMode)	// RS232 OR UART
	{
		uExternLen	= 4;

		pBuffer[0]	= bCmdGroup;
		pBuffer[1]	= wOpCode & 0xFF;	
		pBuffer[2]	= (wOpCode >> 8) & 0xFF;
		pBuffer[3]	= bCmdLen;
	}
	else if (BT_DEVICE_USB == m_dwDeviceMode)									// USB
	{
		uExternLen	= 3;

		pBuffer[0]	= wOpCode & 0xFF;	
		pBuffer[1]	= (wOpCode >> 8) & 0xFF;
		pBuffer[2]	= bCmdLen;
	}
	memcpy(pBuffer+uExternLen,pCmd,bCmdLen);

	Send(pBuffer,uExternLen+bCmdLen);
	delete []pBuffer;

	return 0;
}
// HCI EVENT
// EVENT Code	 Length
//   1 Byte		 1 Byte
DWORD CBT_HCI::GetResponse(BYTE& bCmdGroup,BYTE& bEventCode,BYTE& bEventLen, BYTE* pEvent,DWORD dwMillisecond)
{
	BYTE*	pBuffer = NULL;
	BYTE	bTemp[3];
	UINT	uReceiveLen(0);
	DWORD	dwResult = HCI_COMMANDERROR_OK;

	if (BT_DEVICE_RS232 == m_dwDeviceMode || BT_DEVICE_UART == m_dwDeviceMode)	// RS232 OR UART
	{
		uReceiveLen = 3;
	}
	else if (BT_DEVICE_USB == m_dwDeviceMode)									// USB
	{
		uReceiveLen = 2;
	}
	dwResult = Receive(bTemp,uReceiveLen,dwMillisecond);
	if (TRUE == dwResult)
	{	
		if (BT_DEVICE_RS232 == m_dwDeviceMode || BT_DEVICE_UART == m_dwDeviceMode)	// RS232 OR UART
		{
			bCmdGroup	= bTemp[0];
			bEventCode	= bTemp[1];
			uReceiveLen	= bEventLen	= bTemp[2];
		}
		else if (BT_DEVICE_USB == m_dwDeviceMode)									// USB
		{
			bEventCode	= bTemp[0];
			uReceiveLen	= bEventLen	= bTemp[1];
		}
		dwResult = Receive(pEvent,uReceiveLen,100 * bEventLen);
		if (FALSE == dwResult)
		{
			dwResult = HCI_COMMANDERROR_TIMEOUTS;
		}
		else
		{
			dwResult = HCI_COMMANDERROR_OK;
		}
	}
	else
	{
		dwResult = HCI_COMMANDERROR_TIMEOUTS;
	}

	return dwResult;
}

DWORD CBT_HCI::evt_HCI_Event_Grouping(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
	DWORD dwResult = HCI_COMMANDERROR_OK;

	switch(bEvtCode)
	{
		case HCI_EVT_INQUIRY_COMPLETE:
			evt_HCI_Inquiry_Complete(wOpCode,bEvtCode,pEvent,bIndex);
			break;

		case HCI_EVT_INQUIRY_RESULT_EVENT:
			evt_HCI_Inquiry_Result_Event(wOpCode,bEvtCode,pEvent,bIndex);
			break;

		case HCI_EVT_CONNECTION_COMPLETE_EVENT:
			evt_HCI_Connection_Complete_Event(wOpCode,bEvtCode,pEvent,bIndex);
			break;

		case HCI_EVT_CONNECTION_REQUEST_EVENT:
			break;

		case HCI_EVT_DISCONNECTION_COMPLETE_EVENT:
			evt_HCI_Disconnection_Complete_Event(wOpCode,bEvtCode,pEvent,bIndex);
			break;

		case HCI_EVT_AUTHENTICATION_COMPLETE_EVENT:
			break;

		case HCI_EVT_REMOTE_NAME_REQUEST_COMPLETE_EVENT:
			evt_HCI_Remote_Name_Request_Complete_Event(wOpCode,bEvtCode,pEvent,bIndex);

			break;

		case HCI_EVT_ENCRYPTION_CHANGE_EVENT:
			break;

		case HCI_EVT_CHANGE_CONNECTION_LINK_COMPLETE:
			break;

		case HCI_EVT_MASTER_LINK_KEY_COMPLETE_EVENT:
			break;

		case HCI_EVT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE_EVENT:
			break;

		case HCI_EVT_READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT:
			break;

		case HCI_EVT_QOS_SETUP_COMPLETE_EVENT:
			break;

		case HCI_EVT_COMMAND_COMPLETE:
			evt_HCI_Command_Complete(wOpCode,bEvtCode,pEvent,bIndex);
			break;

		case HCI_EVT_COMMAND_STATUS_EVENT:
			evt_HCI_Command_Status_Event(wOpCode,bEvtCode,pEvent,bIndex);
			break;

		default:
			break;	
	}	
	return dwResult;
}
//  Status
//  1 Byte
DWORD CBT_HCI::evt_HCI_Inquiry_Complete(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
//	DWORD dwResult = HCI_COMMANDERROR_OK;
	return pEvent[0];//dwResult;
}
//  Num_Responses  BD_ADDR	Page_Scan_Repetition_Mode PS_Period_Mode PS_Mode Class_Of_Device Clock_Offset
//    1 Byte		6 Byte		1 Byte					1 Byte		 1 Byte     3 Byte         2 Byte
DWORD CBT_HCI::evt_HCI_Inquiry_Result_Event(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
	DWORD				dwResult	= HCI_COMMANDERROR_OK;
	BT_SLAVER_DEVICE	SDevice;

	memset(&SDevice,0,sizeof(BT_SLAVER_DEVICE));

	memcpy(SDevice.s_BD_ADDR,		pEvent+1 ,BT_BD_ADDR_LEN);
	memcpy(SDevice.s_bClosck_Offset,pEvent+13,2);
	SDevice.s_bPage_Scan_Repetition		= *(pEvent+7);
	SDevice.s_bPage_Scan_Period_Mode	= *(pEvent+8);
	SDevice.s_bPage_Scan_Mode			= *(pEvent+9);

	m_vBT_Slaver_Device.push_back(SDevice);

	return dwResult;
}
// Status  Connection_Handle BD_ADDR Link_Type Encrypton_mode
// 1 Byte    2 Byte(12 bits) 6 Byte    1 Byte    1 Byte
DWORD CBT_HCI::evt_HCI_Connection_Complete_Event(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
	DWORD				dwResult	= HCI_COMMANDERROR_OK;
	BT_SLAVER_DEVICE*	pSDevice;

	if (bIndex >= 0 && bIndex < m_vBT_Slaver_Device.size())
	{
		pSDevice = &(m_vBT_Slaver_Device[bIndex]);
		if (memcmp(pSDevice->s_BD_ADDR,pEvent+3,BT_BD_ADDR_LEN) == 0)
		{
			if (HCI_COMMANDERROR_OK == pEvent[0] || HCI_COMMANDERROR_ACL_CONNECTION_ALREADY_EXISTS == pEvent[0])
			{
				memcpy(pSDevice->s_bConnection_Handle,		pEvent+1 ,2);
				pSDevice->s_bLink_Type		= *(pEvent+9);

				pSDevice->s_fConnection = TRUE;
			}
			else
			{
				dwResult = pEvent[0];
			}
		}
		else
		{
			dwResult = HCI_COMMANDERROR_NOT_MATCH_ADDRESS;
		}
	}
	else
	{
		dwResult = ERROR_INDEX;
	}
	return dwResult;
}
// Status  Connection_Handle Reason
// 1 Byte    2 Byte(12 bits) 1 Byte
DWORD CBT_HCI::evt_HCI_Disconnection_Complete_Event(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
	DWORD				dwResult	= HCI_COMMANDERROR_OK;
	BT_SLAVER_DEVICE*	pSDevice;

	if (bIndex >= 0 && bIndex < m_vBT_Slaver_Device.size())
	{
		pSDevice = &(m_vBT_Slaver_Device[bIndex]);
		if (memcmp(pSDevice->s_bConnection_Handle,pEvent+1,2) == 0)
		{
			if (HCI_COMMANDERROR_OK == pEvent[0])
			{
				pSDevice->s_fConnection = FALSE;
			}
			else
			{
				dwResult = pEvent[3] << 8 || pEvent[0];
			}
		}
		else
		{
			dwResult = HCI_COMMANDERROR_NOT_MATCH_CONNECTION_HANDLE;
		}
	}
	else
	{
		dwResult = ERROR_INDEX;
	}
	return dwResult;
}
// Num_HCI_Command_Packets	Command_OpCode	Return_Parameter
//    1 Byte					2 Byte			... ...
DWORD CBT_HCI::evt_HCI_Command_Complete(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
	DWORD dwResult = HCI_COMMANDERROR_OK;

	if (wOpCode == (pEvent[1] | (pEvent[2] << 8)))
	{	
		switch(wOpCode)
		{
			case HCI_CMD_READ_CURRENT_ICA_LAP:
				if (HCI_COMMANDERROR_OK == pEvent[3])
				{
					memcpy(m_HCI_LAP,pEvent+5,HCI_LAP_LEN);
				}
				else
				{
					dwResult = pEvent[3];
				}	
				break;

			default:
				break;
		}
	}
	else //don't match command
	{
		dwResult = HCI_COMMANDERROR_NOT_MATCH;
	}
	return dwResult;
}
//  Status BD_ADDR  Remote_Name  	
//  1 Byte 6 Byte	248 Byte 
DWORD CBT_HCI::evt_HCI_Remote_Name_Request_Complete_Event(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
	DWORD				dwResult	= HCI_COMMANDERROR_OK;
	BT_SLAVER_DEVICE*	pSDevice;

	if (bIndex >= 0 && bIndex < m_vBT_Slaver_Device.size())
	{
		pSDevice = &(m_vBT_Slaver_Device[bIndex]);
		if (memcmp(pSDevice->s_BD_ADDR,pEvent+1,BT_BD_ADDR_LEN) == 0)
		{
			if (HCI_COMMANDERROR_OK == pEvent[0])
			{
				memcpy(pSDevice->s_bRemote_Name,		pEvent+7 ,REMOTE_NAME_LEN);
			}
			else
			{
				dwResult = pEvent[0];
			}
		}
		else
		{
			dwResult = HCI_COMMANDERROR_NOT_MATCH_ADDRESS;
		}
	}
	else
	{
		dwResult = ERROR_INDEX;
	}
	return dwResult;
}
//  Status Num_Responses  Command_OpCode  	
//  1 Byte   1 Byte		     2 Byte 
DWORD CBT_HCI::evt_HCI_Command_Status_Event(WORD wOpCode,BYTE bEvtCode,BYTE* pEvent,BYTE bIndex)
{
	DWORD dwResult = HCI_COMMANDERROR_OK;

	if (wOpCode == (pEvent[2] | (pEvent[3] << 8)))
	{	
		switch(wOpCode)
		{
			case HCI_CMD_CREATE_CONNECTION:
				dwResult = pEvent[0];
				break;

			default:
				break;
		}
	}
	else //don't match command
	{
		dwResult = HCI_COMMANDERROR_NOT_MATCH;
	}
	return dwResult;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -