www.pudn.com > fbt-a3-20041206.zip > hci.cpp, change:2004-03-08,size:50262b
// Copyright (c) 2004, Antony C. Roberts
// Use of this file is subject to the terms
// described in the LICENSE.TXT file that
// accompanies this file.
//
// Your use of this file indicates your
// acceptance of the terms described in
// LICENSE.TXT.
//
// http://www.freebt.net
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include "fbtutil.h"
#include "fbtusr.h"
#include "fbthci.h"
LPCTSTR g_fbt_hci_Status[] =
{
_T("Success"),
_T("Unknown HCI Command"),
_T("No Connection"),
_T("Hardware Failure"),
_T("Page Timeout"),
_T("Authentication Failure"),
_T("Key Missing"),
_T("Memory Full"),
_T("Connection Timeout"),
_T("Max Number Of Connections"),
_T("Max Number Of SCO Connections To A Device"),
_T("ACL connection already exists"),
_T("Command Disallowed"),
_T("Host Rejected due to limited resources"),
_T("Host Rejected due to security reasons"),
_T("Host Rejected due to remote device is only a personal device"),
_T("Host Timeout"),
_T("Unsupported Feature or Parameter Value"),
_T("Invalid HCI Command Parameters"),
_T("Other End Terminated Connection: User Ended Connection"),
_T("Other End Terminated Connection: Low Resources"),
_T("Other End Terminated Connection: About to Power Off"),
_T("Connection Terminated by Local Host"),
_T("Repeated Attempts"),
_T("Pairing Not Allowed"),
_T("Unknown LMP PDU"),
_T("Unsupported Remote Feature"),
_T("SCO Offset Rejected"),
_T("SCO Interval Rejected"),
_T("SCO Air Mode Rejected"),
_T("Invalid LMP Parameters"),
_T("Unspecified Error"),
_T("Unsupported LMP Parameter Value")
};
LPCTSTR g_fbt_hci_Event[] =
{
_T("<Invalid Event>"),
_T("Inquiry Complete"),
_T("Inquiry Result"),
_T("Connection Complete"),
_T("Connection Request"),
_T("Disconnection Complete"),
_T("Authentication Complete"),
_T("Remote Name Request Complete"),
_T("Encryption Change"),
_T("Change Connection Link Key Complete"),
_T("Master Link Key Complete"),
_T("Read Remote Supported Features Complete"),
_T("Read Remote Version Information"),
_T("QoS Setup Complete"),
_T("Command Complete"),
_T("Command Status"),
_T("Hardware Error"),
_T("Flush Occurred"),
_T("Role Change"),
_T("Number Of Completed Packets"),
_T("Mode Change"),
_T("Return Link Keys"),
_T("PIN Code Request"),
_T("Link Key Request"),
_T("Link Key Notification"),
_T("Loopback Command"),
_T("Data Buffer Overflow"),
_T("Max Slots Change"),
_T("Read Clock Offset Complete"),
_T("Connection Packet Type Changed"),
_T("QoS Violation"),
_T("Page Scan Mode Change"),
_T("Page Scan Repetition Mode Change")
};
LPCTSTR g_fbt_hci_Company[] =
{
_T("Ericsson Technology Licensing"),
_T("Nokia Mobile Phones"),
_T("Intel Corp."),
_T("IBM Corp."),
_T("Toshiba Corp."),
_T("3Com"),
_T("Microsoft"),
_T("Lucent"),
_T("Motorola"),
_T("Infineon Technologies AG"),
_T("Cambridge Silicon Radio"),
_T("Silicon Wave"),
_T("Digianswer A/S"),
_T("Texas Instruments Inc."),
_T("Parthus Technologies Inc."),
_T("Broadcom Corporation"),
_T("Mitel Semiconductor"),
_T("Widcomm, Inc."),
_T("Zeevo, Inc."),
_T("Atmel Corporation"),
_T("Mitsubishi Electric Corporation"),
_T("RTX Telecom A/S"),
_T("KC Technology Inc."),
_T("Newlogic"),
_T("Transilica, Inc."),
_T("Rohde & Schwarz GmbH & Co. KG"),
_T("TTPCom Limited"),
_T("Signia Technologies, Inc."),
_T("Conexant Systems Inc."),
_T("Qualcomm"),
_T("Inventel"),
_T("AVM Berlin"),
_T("BandSpeed, Inc."),
_T("Mansella Ltd"),
_T("NEC Corporation"),
_T("WavePlus Technology Co., Ltd."),
_T("Alcatel"),
_T("Philips Semiconductors"),
_T("C Technologies"),
_T("Open Interface"),
_T("R F Micro Devices"),
_T("Hitachi Ltd"),
_T("Symbol Technologies, Inc."),
_T("Tenovis"),
_T("Macronix International Co. Ltd."),
_T("GCT Semiconductor"),
_T("Norwood Systems"),
_T("MewTel Technology Inc."),
_T("ST Microelectronics"),
_T("Synopsys"),
_T("Red-M (Communications) Ltd"),
_T("Commil Ltd"),
_T("Computer Access Technology Corporation (CATC)"),
_T("Eclipse (HQ Espana) S.L."),
_T("Renesas Technology Corp."),
_T("Mobilian Corporation"),
_T("Terax"),
_T("Integrated System Solution Corp."),
_T("Matsushita Electric Industrial Co., Ltd."),
_T("Gennum Corporation"),
_T("Research In Motion")
};
CHci::CHci() : CBTHW()
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::CHci: Enter"));
m_hListenerThread=NULL;
m_hStopListeningEvent=CreateEvent(NULL, FALSE, FALSE, NULL);
fbtLog(fbtLog_Exit, _T("CHci::CHci: Exit"));
FBT_CATCH_NORETURN
}
CHci::~CHci()
{
FBT_TRY
StopEventListener();
Detach();
FBT_CATCH_NORETURN
}
DWORD CHci::StartEventListener()
{
FBT_TRY
if (m_hListenerThread!=NULL)
{
fbtLog(fbtLog_Failure, _T("CHci:StartEventListener: Listener already running"));
return ERROR_INTERNAL_ERROR;
}
m_hListenerReadyEvent=CreateEvent(NULL, FALSE, FALSE, NULL);
m_hListenerThread=CreateThread(NULL, 0, Listener, this, 0, &m_dwListenerThreadId);
if (m_hListenerThread==NULL)
{
DWORD dwLastError=GetLastError();
CloseHandle(m_hListenerReadyEvent);
fbtLog(fbtLog_Failure, _T("CHci::StartEventListener: Failed to create listener thread, error %d"), dwLastError);
return dwLastError;
}
WaitForSingleObject(m_hListenerReadyEvent, INFINITE);
CloseHandle(m_hListenerReadyEvent);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::StopEventListener()
{
FBT_TRY
SetEvent(m_hStopListeningEvent);
DWORD dwResult=WaitForSingleObject(m_hListenerThread, INFINITE);
m_hListenerThread=NULL;
// Must detach in order to cancel pending listener IRPs
// (implicitly calls CancelIO
Detach();
return dwResult;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
// Event handler thread routine
DWORD CALLBACK EventHandler(LPVOID pContext)
{
FBT_TRY
PHCI_EVENT pEvent=(PHCI_EVENT)pContext;
CHci *pThis=(CHci*)pEvent->pThis;
DWORD dwResult=pThis->OnEvent(pEvent->pEvent, pEvent->dwLength);
if (dwResult!=ERROR_SUCCESS)
fbtLog(fbtLog_Failure, _T("CHci::EventHandler: OnEvent failed, error %d"), dwResult);
fbtLog(fbtLog_Notice, _T("CHci::EventHandler: Event handling complete"));
free(pEvent->pEvent);
free(pEvent);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CALLBACK Listener(LPVOID pContext)
{
FBT_TRY
CHci *pThis=(CHci*)pContext;
HANDLE hEvents[HCI_NUMBER_OF_OVERLAPPED_LISTENS+1];
hEvents[0]=pThis->m_hStopListeningEvent;
// Start the listeners. Each call will 'hang' in the driver
// until an event arrives, which causes it to be completed
for (int i=0; i<HCI_NUMBER_OF_OVERLAPPED_LISTENS; i++)
{
ZeroMemory(pThis->m_pEventBuffers[i], FBT_HCI_EVENT_MAX_SIZE);
ZeroMemory(&pThis->m_Overlappeds[i], sizeof(OVERLAPPED));
pThis->m_Overlappeds[i].hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
if (pThis->m_Overlappeds[i].hEvent==NULL)
fbtLog(fbtLog_Failure, _T("CHci::Listener: Failed to create event %d"), i);
else
{
hEvents[i+1]=pThis->m_Overlappeds[i].hEvent;
if (pThis->SendCommand(
IOCTL_FREEBT_HCI_GET_EVENT,
NULL,
0,
pThis->m_pEventBuffers[i],
FBT_HCI_EVENT_MAX_SIZE,
&pThis->m_Overlappeds[i])!=ERROR_SUCCESS)
fbtLog(fbtLog_Failure, _T("CHci::Listener: Failed to send listen request %d"), i);
}
}
SetEvent(pThis->m_hListenerReadyEvent);
BOOL bListen=TRUE;
while (bListen)
{
// Wait for Listens to complete
DWORD dwWaitResult=WaitForMultipleObjects(HCI_NUMBER_OF_OVERLAPPED_LISTENS+1,
hEvents,
FALSE,
INFINITE);
DWORD dwLastError;
if (dwWaitResult==WAIT_FAILED)
{
dwLastError=GetLastError();
fbtLog(fbtLog_Failure, _T("CHci::Listener: WaitForMultipleObjects failed, error %d"), dwLastError);
return dwLastError;
}
if (dwWaitResult==WAIT_TIMEOUT)
{
fbtLog(fbtLog_Failure, _T("CHci::Listener: WaitForMultipleObjects timed out"));
return ERROR_TIMEOUT;
}
// Find out which listener got complete
ULONG nEventIndex=dwWaitResult-WAIT_OBJECT_0;
if (nEventIndex>0)
{
nEventIndex--;
fbtLog(fbtLog_Notice, _T("CHci::Listener: Event signalled on listener %d"), nEventIndex);
DWORD dwLength;
if (!GetOverlappedResult(pThis->GetDriverHandle(), &pThis->m_Overlappeds[nEventIndex], &dwLength, TRUE))
{
dwLastError=GetLastError();
fbtLog(fbtLog_Failure, _T("CHci::Listener: GetOverlappedResult failed, error %d"), dwLastError);
return dwLastError;
}
// Handle the event
PFBT_HCI_EVENT_HEADER pEvent=(PFBT_HCI_EVENT_HEADER)pThis->m_pEventBuffers[nEventIndex];
fbtLog(fbtLog_Notice, _T("CHci::Listener: Received %s event (0x%02x)"), pThis->GetEventText(pEvent->EventCode), pEvent->EventCode);
// Filter for must-handle events (OnEvent can be overridden)
PHCI_EVENT pEventParameters=(PHCI_EVENT)malloc(sizeof(HCI_EVENT));
pEventParameters->pEvent=(PFBT_HCI_EVENT_HEADER)malloc(dwLength);
CopyMemory(pEventParameters->pEvent, pEvent, dwLength);
pEventParameters->dwLength=dwLength;
pEventParameters->pThis=pThis;
// Spin handling off in a thread in order to reduce turnaround time
HANDLE hThread=CreateThread(NULL, 0, ::EventHandler, pEventParameters, 0, NULL);
if (hThread==NULL)
{
DWORD dwLastError=GetLastError();
CloseHandle(hThread);
fbtLog(fbtLog_Failure, _T("CHci::StartEventListener: Failed to create listener thread, error %d"), dwLastError);
return dwLastError;
}
CloseHandle(hThread);
// Send the listen for events request back down to the driver
ZeroMemory(pThis->m_pEventBuffers[nEventIndex], FBT_HCI_EVENT_MAX_SIZE);
ResetEvent(pThis->m_Overlappeds[nEventIndex].hEvent);
if (pThis->SendCommand(
IOCTL_FREEBT_HCI_GET_EVENT,
NULL,
0,
pThis->m_pEventBuffers[nEventIndex],
FBT_HCI_EVENT_MAX_SIZE,
&pThis->m_Overlappeds[nEventIndex])!=ERROR_SUCCESS)
fbtLog(fbtLog_Failure, _T("CHci::Listener: Failed to resend listen request %d"), nEventIndex);
}
else
bListen=FALSE;
}
fbtLog(fbtLog_Notice, _T("CHci::Listener: Stop signalled, exitting"));
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
// Get the description that corresponds to an HCI status code
LPCTSTR CHci::GetStatusText(BYTE Status)
{
FBT_TRY
if (Status>32)
return (LPTSTR)NULL;
return g_fbt_hci_Status[Status];
FBT_CATCH_RETURN(NULL)
}
// Get the name of an HCI event
LPCTSTR CHci::GetEventText(BYTE Event)
{
FBT_TRY
if (Event>32)
return (LPTSTR)NULL;
return g_fbt_hci_Event[Event];
FBT_CATCH_RETURN(NULL)
}
// Get the name of a Manufacturer
LPCTSTR CHci::GetManufacturerName(USHORT Company)
{
FBT_TRY
if (Company>60)
return (LPTSTR)NULL;
return g_fbt_hci_Company[Company];
FBT_CATCH_RETURN(NULL)
}
// Compare two BDADDRs
DWORD CHci::CompareBDADDRs(BYTE BD_ADDR1[FBT_HCI_BDADDR_SIZE], BYTE BD_ADDR2[FBT_HCI_BDADDR_SIZE])
{
FBT_TRY
for (int i=0; i<FBT_HCI_BDADDR_SIZE; i++)
{
if (BD_ADDR1[i]!=BD_ADDR2[i])
{
return 1;
}
}
return ERROR_SUCCESS;
FBT_CATCH_RETURN(0)
}
// Commands
DWORD CHci::SendHciCommand(PFBT_HCI_CMD_HEADER lpCommand, DWORD dwBufferSize)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendHciCommand: Enter(lpCommand=%X, dwBufferSize=%d"), lpCommand, dwBufferSize);
if (GetCurrentThreadId()==m_dwListenerThreadId)
{
fbtLog(fbtLog_Failure, _T("CHci::SendHciCommand: ERROR: Command dispatch sent from Listener thread context!"));
return ERROR_INTERNAL_ERROR;
}
fbtLog(fbtLog_Notice, _T("CHci::SendHciCommand: Sending command OGF=0x%02x OCF=0x%02x"), lpCommand->OpCode>>10, lpCommand->OpCode&0x3FF);
if (dwBufferSize-sizeof(FBT_HCI_CMD_HEADER)>0 && fbtLogGetLevel()>=fbtLog_Verbose)
{
fbtLog(fbtLog_Notice, _T("CHci::SendHciCommand: Command paramemters: "));
byte *lpBuffer=(byte*)lpCommand;
char szDebugBite[4];
char *szDebugString=(char*)malloc((dwBufferSize*3)+1);
szDebugString[0]=0;
for (UINT i=0; i<dwBufferSize; i++)
{
_snprintf(szDebugBite, 4, "%02X ", lpBuffer[i]);
szDebugBite[3]=0;
strcat(szDebugString, szDebugBite);
}
fbtLog(fbtLog_Verbose, "CHci::SendHciCommand: HCI Command buffer contents: %s", szDebugString);
free(szDebugString);
}
DWORD dwResult=SendCommand(IOCTL_FREEBT_HCI_SEND_CMD, lpCommand, dwBufferSize, NULL, 0);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHci::SendHciCommand: SendCommand failed, last error=%d"), dwResult);
return dwResult;
}
fbtLog(fbtLog_Exit, _T("CHci::SendHciCommand: Exit"));
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendReset()
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendReset: Enter"));
FBT_HCI_RESET commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_RESET;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_RESET) - sizeof(FBT_HCI_CMD_HEADER);
DWORD dwReturnCode=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("CHci::SendHciReset: Exit"));
return dwReturnCode;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendInquiry(ULONG LAP, BYTE InquiryLength, BYTE NumResponses)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendInquiry: Enter(LAP=%d, InquiryLength=%d, NumResponses=%d)"), LAP, InquiryLength, NumResponses);
FBT_HCI_INQUIRY commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_INQUIRY;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_INQUIRY) - sizeof(FBT_HCI_CMD_HEADER);
PBYTE pBuffer=(PBYTE)&LAP;
commandBuffer.LAP[0] = pBuffer[0]; //(BYTE)(LAP & 0x000000FF);
commandBuffer.LAP[1] = pBuffer[1]; //(BYTE)((LAP & 0x0000FF00) >> 8);
commandBuffer.LAP[2] = pBuffer[2]; //(BYTE)((LAP & 0x00FF0000) >> 16);
commandBuffer.InquiryLength = InquiryLength;
commandBuffer.NumResponses = NumResponses;
DWORD dwReturnCode=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("CHci::SendInquiry: Exit"));
return dwReturnCode;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendInquiryCancel()
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendInquiryCancel: Enter"));
FBT_HCI_INQUIRY_CANCEL commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_INQUIRY_CANCEL;
commandBuffer.CommandHeader.ParameterLength = 0;
DWORD dwReturnCode=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("CHci::SendInquiryCancel: Exit"));
return dwReturnCode;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendReadBDADDR()
{
FBT_TRY
FBT_HCI_READ_BD_ADDR commandBuffer;
commandBuffer.CommandHeader.OpCode=FBT_HCI_CMD_READ_BD_ADDR;
commandBuffer.CommandHeader.ParameterLength=sizeof(FBT_HCI_READ_BD_ADDR) - sizeof(FBT_HCI_CMD_HEADER);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendWriteScanEnable(BYTE ScanEnable)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendWriteScanEnable: Enter, ScanEnable=%d"), ScanEnable);
FBT_HCI_WRITE_SCAN_ENABLE commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_WRITE_SCAN_ENABLE;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_WRITE_SCAN_ENABLE) - sizeof(FBT_HCI_CMD_HEADER);
commandBuffer.ScanEnable = ScanEnable;
DWORD dwResult=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("CHci::SendWriteScanEnable: Exit, result %d"), dwResult);
return dwResult;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendWriteAuthenticationEnable(BYTE AuthenticationEnable)
{
FBT_TRY
FBT_HCI_WRITE_AUTHENTICATION_ENABLE commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_WRITE_AUTHENTICATION_ENABLE;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_WRITE_AUTHENTICATION_ENABLE) - sizeof(FBT_HCI_CMD_HEADER);
commandBuffer.AuthenticationEnable = AuthenticationEnable;
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendSetEventFilter(BYTE FilterType, BYTE FilterConditionType, BYTE Condition[FBT_HCI_MAX_CONDITION_SIZE], BYTE ConditionBytes)
{
FBT_TRY
FBT_HCI_SET_EVENT_FILTER commandBuffer;
BYTE BufSize=sizeof(commandBuffer)-(FBT_HCI_MAX_CONDITION_SIZE-ConditionBytes);
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_SET_EVENT_FILTER;
commandBuffer.CommandHeader.ParameterLength = BufSize - sizeof(FBT_HCI_CMD_HEADER);
commandBuffer.FilterType = FilterType;
commandBuffer.FilterConditionType = FilterConditionType;
// Initialise the buffer (not all bytes are used for all conditions)
memset(commandBuffer.Condition, 0, sizeof(commandBuffer.Condition));
CopyMemory(commandBuffer.Condition, Condition, ConditionBytes);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, BufSize);
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendReadClassOfDevice()
{
FBT_TRY
FBT_HCI_READ_CLASS_OF_DEVICE commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_READ_CLASS_OF_DEVICE;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_READ_CLASS_OF_DEVICE) - sizeof(FBT_HCI_CMD_HEADER);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
// Set the class of device bits which indicate what type of device this is
// to inquirying devices
DWORD CHci::SendWriteClassOfDevice(BYTE ClassOfDevice[FBT_HCI_DEVICE_CLASS_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("SendWriteClassOfDevice: Enter, ClassOfDevice=%02x %02x %02x"), ClassOfDevice[0], ClassOfDevice[1], ClassOfDevice[2]);
FBT_HCI_WRITE_CLASS_OF_DEVICE commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_WRITE_CLASS_OF_DEVICE;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_WRITE_CLASS_OF_DEVICE) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.ClassOfDevice, ClassOfDevice, FBT_HCI_DEVICE_CLASS_SIZE);
DWORD dwResult=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("SendWriteClassOfDevice: Exit, dwResult=%d"), dwResult);
return dwResult;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendCreateConnection(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE],
USHORT PacketType,
BYTE PageScanRepetitionMode,
BYTE PageScanMode,
USHORT ClockOffset,
BYTE AllowRoleSwitch)
{
FBT_TRY
FBT_HCI_CREATE_CONNECTION commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_CREATE_CONNECTION;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_CREATE_CONNECTION) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
commandBuffer.PacketType = PacketType;
commandBuffer.PageScanRepetitionMode = PageScanRepetitionMode;
commandBuffer.PageScanMode = PageScanMode;
commandBuffer.ClockOffset = ClockOffset;
commandBuffer.AllowRoleSwitch = AllowRoleSwitch;
DWORD dwResult=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Notice, _T("CHci::SendCreateConnection: Create_Connection sent"));
return dwResult;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendAcceptConnectionRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE Role)
{
FBT_TRY
FBT_HCI_ACCEPT_CONNECTION_REQUEST commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_CREATE_CONNECTION;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_CREATE_CONNECTION) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
commandBuffer.Role = Role;
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendDisconnect(USHORT ConnectionHandle, BYTE Reason)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendDisconnect: Enter(ConnectionHandle=%02x, Reason=0x%x)"), ConnectionHandle, Reason);
FBT_HCI_DISCONNECT commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_DISCONNECT;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_DISCONNECT) - sizeof(FBT_HCI_CMD_HEADER);
commandBuffer.ConnectionHandle = ConnectionHandle;
commandBuffer.Reason = Reason;
DWORD dwResult=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("CHci::SendDisconnect: Exit"));
return dwResult;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
// Max timeout betweem packets. Used for determining link loss
DWORD CHci::SendWriteLinkSupervisionTimeout(USHORT ConnectionHandle, USHORT LinkSupervisionTimeout)
{
FBT_TRY
FBT_HCI_WRITE_LINK_SUPERVISION_TIMEOUT commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_WRITE_LINK_SUPERVISION_TIMEOUT) - sizeof(FBT_HCI_CMD_HEADER);
commandBuffer.ConnectionHandle = ConnectionHandle;
commandBuffer.LinkSupervisionTimeout = LinkSupervisionTimeout;
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
// Timeout within which a connection should be established
DWORD CHci::SendWritePageTimeout(USHORT PageTimeout)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendWritePageTimeout: Enter, PageTimeout=%d"), PageTimeout);
FBT_HCI_WRITE_PAGE_TIMEOUT commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_WRITE_PAGE_TIMEOUT;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_WRITE_PAGE_TIMEOUT) - sizeof(FBT_HCI_CMD_HEADER);
commandBuffer.PageTimeout = PageTimeout;
DWORD dwResult=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("CHci::SendWritePageTimeout: Exit, dwResult=%d"), dwResult);
return dwResult;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendRemoteNameRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE PageScanRepetitionMode, BYTE PageScanMode, USHORT ClockOffset)
{
FBT_TRY
TCHAR szAddress[40];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Enter, _T("CHci::SendRemoteNameRequest: Enter(Address=%s, PageScanRepetitionMode=%d, PageScanMode=%d, ClockOffset=%d)"), szAddress, PageScanRepetitionMode, PageScanMode, ClockOffset);
FBT_HCI_REMOTE_NAME_REQUEST commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_REMOTE_NAME_REQUEST;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_REMOTE_NAME_REQUEST) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
commandBuffer.PageScanRepetitionMode=PageScanRepetitionMode;
commandBuffer.PageScanMode=PageScanMode;
commandBuffer.ClockOffset=ClockOffset;
DWORD dwReturnCode=SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
fbtLog(fbtLog_Exit, _T("CHci::SendRemoteNameRequest: Exit"));
return dwReturnCode;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendReadLocalName()
{
FBT_TRY
FBT_HCI_READ_LOCAL_NAME commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_READ_LOCAL_NAME;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_READ_LOCAL_NAME) - sizeof(FBT_HCI_CMD_HEADER);
SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendChangeLocalName(BYTE Name[FBT_HCI_NAME_SIZE])
{
FBT_TRY
FBT_HCI_CHANGE_LOCAL_NAME commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_CHANGE_LOCAL_NAME;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_CHANGE_LOCAL_NAME) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.Name, Name, FBT_HCI_NAME_SIZE);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendSwitchRole(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE Role)
{
FBT_TRY
TCHAR szAddress[40];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Enter, _T("CHci::SendSwitchRole: Enter(BD_ADDR=%S, Role=%d"), szAddress, Role);
FBT_HCI_SWITCH_ROLE commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_SWITCH_ROLE;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_SWITCH_ROLE) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
commandBuffer.Role=Role;
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendPINCodeRequestReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE PINCodeLength, BYTE PINCode[FBT_HCI_PIN_CODE_SIZE])
{
FBT_TRY
TCHAR szAddress[40];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Enter, _T("CHci::SendPINCodeRequestReply: Enter(BD_ADDR=%S, PINCodeLength=%d"), szAddress, PINCodeLength);
FBT_HCI_PIN_CODE_REQUEST_REPLY commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_PIN_CODE_REQUEST_REPLY;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_PIN_CODE_REQUEST_REPLY) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
commandBuffer.PINCodeLength=PINCodeLength;
CopyMemory(commandBuffer.PINCode, PINCode, FBT_HCI_PIN_CODE_SIZE);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendPINCodeRequestNegativeReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE])
{
FBT_TRY
TCHAR szAddress[40];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Enter, _T("CHci::SendPINCodeRequestNegativeReply: Enter(BD_ADDR=%S"), szAddress);
FBT_HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_PIN_CODE_REQUEST_NEGATIVE_REPLY;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_PIN_CODE_REQUEST_NEGATIVE_REPLY) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendLinkKeyRequestReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE LinkKey[FBT_HCI_LINK_KEY_SIZE])
{
FBT_TRY
TCHAR szAddress[40];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Enter, _T("CHci::SendLinkKeyRequestReply: Enter(BD_ADDR=%S"), szAddress);
FBT_HCI_LINK_KEY_REQUEST_REPLY commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_LINK_KEY_REQUEST_REPLY;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_LINK_KEY_REQUEST_REPLY) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
CopyMemory(commandBuffer.LinkKey, LinkKey, FBT_HCI_LINK_KEY_SIZE);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendLinkKeyRequestNegativeReply(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE])
{
FBT_TRY
TCHAR szAddress[40];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Enter, _T("CHci::SendLinkKeyRequestNegativeReply: Enter(BD_ADDR=%S"), szAddress);
FBT_HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_LINK_KEY_REQUEST_NEGATIVE_REPLY;
commandBuffer.CommandHeader.ParameterLength = sizeof(FBT_HCI_LINK_KEY_REQUEST_NEGATIVE_REPLY) - sizeof(FBT_HCI_CMD_HEADER);
CopyMemory(commandBuffer.BD_ADDR, BD_ADDR, FBT_HCI_BDADDR_SIZE);
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::SendReadLocalVersionInformation(void)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHci::SendReadLocalVersionInformation: Enter"));
FBT_HCI_READ_LOCAL_VERSION_INFORMATION commandBuffer;
commandBuffer.CommandHeader.OpCode = FBT_HCI_CMD_READ_LOCAL_VERSION_INFORMATION;
commandBuffer.CommandHeader.ParameterLength = 0;
return SendHciCommand((PFBT_HCI_CMD_HEADER)&commandBuffer, sizeof(commandBuffer));
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
// Events
DWORD CHci::OnEvent(PFBT_HCI_EVENT_HEADER pEvent, DWORD Length)
{
FBT_TRY
DWORD returnCode=0;
fbtLog(fbtLog_Notice, _T("CHci::OnEvent: Received event 0x%02X"), pEvent->EventCode);
switch (pEvent->EventCode)
{
case FBT_HCI_EVENT_INQUIRY_COMPLETE:
returnCode = OnInquiryComplete(
((PFBT_HCI_INQUIRY_COMPLETE)pEvent)->Status,
((PFBT_HCI_INQUIRY_COMPLETE)pEvent)->NumResponses);
break;
case FBT_HCI_EVENT_INQUIRY_RESULT:
{
PFBT_HCI_INQUIRY_RESULT pInquiryResult=(PFBT_HCI_INQUIRY_RESULT)pEvent;
returnCode = OnInquiryResult(
pInquiryResult->NumResponses,
pInquiryResult->BD_ADDR,
pInquiryResult->PageScanRepetitionMode,
pInquiryResult->PageScanPeriodMode,
pInquiryResult->PageScanMode,
pInquiryResult->ClassOfDevice,
pInquiryResult->ClockOffset);
}
break;
case FBT_HCI_EVENT_COMMAND_COMPLETE:
returnCode = OnCommandComplete(
((PFBT_HCI_COMMAND_COMPLETE)pEvent)->NumHCICommandPackets,
((PFBT_HCI_COMMAND_COMPLETE)pEvent)->OpCode,
((PFBT_HCI_COMMAND_COMPLETE)pEvent)->Parameters,
((PFBT_HCI_COMMAND_COMPLETE)pEvent)->EventHeader.ParameterLength - (sizeof(PFBT_HCI_COMMAND_COMPLETE) - sizeof(FBT_HCI_EVENT_HEADER) - 1));
break;
case FBT_HCI_EVENT_COMMAND_STATUS:
returnCode = OnCommandStatus(
((PFBT_HCI_COMMAND_STATUS)pEvent)->Status,
((PFBT_HCI_COMMAND_STATUS)pEvent)->NumHCICommandPackets,
((PFBT_HCI_COMMAND_STATUS)pEvent)->OpCode);
break;
case FBT_HCI_EVENT_CONNECTION_REQUEST:
returnCode = OnConnectionRequest(
((PFBT_HCI_CONNECTION_REQUEST)pEvent)->BD_ADDR,
((PFBT_HCI_CONNECTION_REQUEST)pEvent)->ClassOfDevice,
((PFBT_HCI_CONNECTION_REQUEST)pEvent)->LinkType);
break;
case FBT_HCI_EVENT_CONNECTION_COMPLETE:
returnCode = OnConnectionComplete(
((PFBT_HCI_CONNECTION_COMPLETE)pEvent)->Status,
((PFBT_HCI_CONNECTION_COMPLETE)pEvent)->ConnectionHandle,
((PFBT_HCI_CONNECTION_COMPLETE)pEvent)->BD_ADDR,
((PFBT_HCI_CONNECTION_COMPLETE)pEvent)->LinkType,
((PFBT_HCI_CONNECTION_COMPLETE)pEvent)->EncryptionMode);
break;
case FBT_HCI_EVENT_DISCONNECTION_COMPLETE:
returnCode = OnDisconnectionComplete(
((PFBT_HCI_DISCONNECTION_COMPLETE)pEvent)->Status,
((PFBT_HCI_DISCONNECTION_COMPLETE)pEvent)->ConnectionHandle,
((PFBT_HCI_DISCONNECTION_COMPLETE)pEvent)->Reason);
break;
case FBT_HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
returnCode=OnRemoteNameRequestComplete(
((PFBT_HCI_REMOTE_NAME_REQUEST_COMPLETE)pEvent)->Status,
((PFBT_HCI_REMOTE_NAME_REQUEST_COMPLETE)pEvent)->BD_ADDR,
((PFBT_HCI_REMOTE_NAME_REQUEST_COMPLETE)pEvent)->RemoteName);
break;
case FBT_HCI_EVENT_ROLE_CHANGE:
returnCode=OnRoleChange(
((PFBT_HCI_ROLE_CHANGE)pEvent)->Status,
((PFBT_HCI_ROLE_CHANGE)pEvent)->BD_ADDR,
((PFBT_HCI_ROLE_CHANGE)pEvent)->NewRole);
break;
case FBT_HCI_EVENT_PIN_CODE_REQUEST:
returnCode=OnPINCodeRequest(((PFBT_HCI_PIN_CODE_REQUEST)pEvent)->BD_ADDR);
break;
case FBT_HCI_EVENT_LINK_KEY_NOTIFICATION:
returnCode=OnLinkKeyNotification(
((PFBT_HCI_LINK_KEY_NOTIFICATION)pEvent)->BD_ADDR,
((PFBT_HCI_LINK_KEY_NOTIFICATION)pEvent)->LinkKey);
break;
case FBT_HCI_EVENT_AUTHENTICATION_COMPLETE:
returnCode=OnAuthenticationComplete(
((PFBT_HCI_AUTHENTICATION_COMPLETE)pEvent)->Status,
((PFBT_HCI_AUTHENTICATION_COMPLETE)pEvent)->ConnectionHandle);
break;
case FBT_HCI_EVENT_LINK_KEY_REQUEST:
returnCode=OnLinkKeyRequest(((PFBT_HCI_LINK_KEY_REQUEST)pEvent)->BD_ADDR);
break;
default:
fbtLog(fbtLog_Notice, _T("CHci::OnEvent: Event 0x%02X unhandled"), pEvent->EventCode);
returnCode = OnUnknown(pEvent, Length);
break;
}
return returnCode;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnCommandComplete(BYTE NumHCICommandPackets, USHORT CommandOpcode, BYTE *Parameters, DWORD ParameterLength)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnCommandComplete: Command Complete Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnCommandComplete: NumHCICommandPackets: 0x%02X"), NumHCICommandPackets);
fbtLog(fbtLog_Notice, _T("CHci::OnCommandComplete: CommandOpcode: 0x%02X"), CommandOpcode);
fbtLog(fbtLog_Notice, _T("CHci::OnCommandComplete: Parameters: "));
ULONG fixedParameterLength = (sizeof(FBT_HCI_COMMAND_COMPLETE) - sizeof(FBT_HCI_EVENT_HEADER) - 1 /* variable sized array */);
for (ULONG ii = 0; ii ParameterLength; ii++)
fbtLog(fbtLog_Notice, _T("%02X "), Parameters[ii]);
if (CommandOpcode==FBT_HCI_CMD_READ_LOCAL_NAME)
OnReadLocalNameComplete(Parameters[0], &Parameters[1]);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnCommandStatus(BYTE Status, BYTE NumHCICommandPackets, USHORT CommandOpcode)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnCommandStatus: Command Status Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnCommandStatus: Status: 0x%02X (%s)"), Status, GetStatusText(Status));
fbtLog(fbtLog_Notice, _T("CHci::OnCommandStatus: NumHCICommandPackets: 0x%02X"), NumHCICommandPackets);
fbtLog(fbtLog_Notice, _T("CHci::OnCommandStatus: CommandOpcode: 0x%02X"), CommandOpcode);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnInquiryResult(BYTE NumResponses, BYTE BD_ADDR[FBT_HCI_VARIABLE_SIZE][FBT_HCI_BDADDR_SIZE], BYTE PageScanRepetitionMode[FBT_HCI_VARIABLE_SIZE], BYTE PageScanPeriodMode[FBT_HCI_VARIABLE_SIZE], BYTE PageScanMode[FBT_HCI_VARIABLE_SIZE], BYTE ClassOfDevice[FBT_HCI_VARIABLE_SIZE][FBT_HCI_DEVICE_CLASS_SIZE], USHORT ClockOffset[FBT_HCI_VARIABLE_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: Inquiry Result Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: Responses: 0x%02X"), NumResponses);
if (NumResponses==0)
return ERROR_SUCCESS;
for (int i=0; i<NumResponses; i++)
{
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: Response %02d:"), i+1);
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: Addresses:"));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: BD_ADDR: 0x%02X"), &(BD_ADDR[i]));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: PageScanRepetitionMode: 0x%02X"), &(PageScanRepetitionMode[i]));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: PageScanPeriodMode: 0x%02X"), &(PageScanPeriodMode[i]));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: PageScanMode: 0x%02X"), &(PageScanMode[i]));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: ClassOfDevice: 0x%02X"), &(ClassOfDevice[i]));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: ClockOffset: 0x%02X"), &(ClockOffset[i]));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: BD_ADDR: %02X %02X %02X %02X %02X %02X"),
BD_ADDR[i][5],
BD_ADDR[i][4],
BD_ADDR[i][3],
BD_ADDR[i][2],
BD_ADDR[i][1],
BD_ADDR[i][0]);
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: PageScanRepetitionMode: 0x%02X"), PageScanRepetitionMode[i]);
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: PageScanPeriodMode: 0x%02X"), PageScanPeriodMode[i]);
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: PageScanMode: 0x%02X"), PageScanMode[i]);
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: ClassOfDevice: %02X %02X %02X"), ClassOfDevice[i][0], ClassOfDevice[i][1], ClassOfDevice[i][2]);
USHORT TempClockOffset;
CopyMemory(&TempClockOffset, &(ClockOffset[i]), sizeof(TempClockOffset));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryResult: ClockOffset: 0x%02X"), TempClockOffset);
fbtLog(fbtLog_Notice, _T(""));
}
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnInquiryComplete(BYTE Status, BYTE NumResponses)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryComplete: Inquiry Complete Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryComplete: Status: 0x%02X (%s)"), Status, GetStatusText(Status));
fbtLog(fbtLog_Notice, _T("CHci::OnInquiryComplete: NumResponses: 0x%02X"), NumResponses);
fbtLog(fbtLog_Notice, _T(""));
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnConnectionRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], ULONG ClassOfDevice[FBT_HCI_DEVICE_CLASS_SIZE], BYTE LinkType)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionRequest: Connection Request Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionRequest: BD_ADDR: %02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionRequest: ClassOfDevice: 0x%02X"), ClassOfDevice);
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionRequest: LinkType: 0x%02X"), LinkType);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnConnectionComplete(BYTE Status, USHORT ConnectionHandle, BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE LinkType, BYTE EncryptionMode)
{
FBT_TRY
// it was a create connection, see if we timed out
if (Status!=0)
{
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionComplete: Failed, status %d (%s)"), Status, GetStatusText(Status));
return Status;
}
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionComplete: Connection Complete Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionComplete: Status: 0x%02X %s"), Status, GetStatusText(Status));
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionComplete: Connection Handle: 0x%04X"), ConnectionHandle);
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionComplete: BD_ADDR: %02X-%02X-%02X-%02X-%02X-%02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionComplete: Link Type: 0x%02X"), LinkType);
fbtLog(fbtLog_Notice, _T("CHci::OnConnectionComplete: Encryption Mode: 0x%02X"), EncryptionMode);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnDisconnectionComplete(BYTE Status, USHORT ConnectionHandle, BYTE Reason)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnDisconnectionComplete: Disconnection Complete Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnDisconnectionComplete: Status: 0x%02X (%s)"), Status, GetStatusText(Status));
fbtLog(fbtLog_Notice, _T("CHci::OnDisconnectionComplete: Connection Handle: 0x%04X"), ConnectionHandle);
fbtLog(fbtLog_Notice, _T("CHci::OnDisconnectionComplete: Reason: 0x%02X (%s)"), Reason, GetStatusText(Reason));
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnRemoteNameRequestComplete(BYTE Status, BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE RemoteName[FBT_HCI_NAME_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnRemoteNameRequestComplete: Remote Name Request Complete Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnRemoteNameRequestComplete: Status: %02X (%s)"), Status, GetStatusText(Status));
if (Status==0)
{
fbtLog(fbtLog_Notice, _T("CHci::OnRemoteNameRequestComplete: BD_ADDR: %02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Notice, _T("CHci::OnRemoteNameRequestComplete: Name: %s"), RemoteName);
}
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnRoleChange(BYTE Status, BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE Role)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnRoleChange: Roll Change Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnRoleChange: Status: 0x%02X"), Status);
fbtLog(fbtLog_Notice, _T("CHci::OnRoleChange: BD_ADDR: %02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Notice, _T("CHci::OnRoleChange: Role: 0x%02X"), Role);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnPINCodeRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnPINCodeRequest: PIN Code Request Event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnPINCodeRequest: BD_ADDR: %02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnLinkKeyNotification(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE LinkKey[FBT_HCI_LINK_KEY_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnLinkKeyNotification: Link Key Notification Event:"));
TCHAR szAddress[32];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Notice, _T("CHci::OnLinkKeyNotification: BD_ADDR: %s"), szAddress);
if (fbtLogGetLevel()>=fbtLog_Verbose)
{
fbtLog(fbtLog_Verbose, _T("\tLink Key: "));
for (UINT i=0; i<FBT_HCI_LINK_KEY_SIZE; i++)
fbtLog(fbtLog_Verbose, _T("%02X "), ((PBYTE)LinkKey)[i]);
fbtLog(fbtLog_Verbose, _T("\n"));
}
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnLinkKeyRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnLinkKeyRequest: Link Key Request Event:"));
TCHAR szAddress[32];
_stprintf(szAddress, _T("%02X %02X %02X %02X %02X %02X"),
BD_ADDR[5],
BD_ADDR[4],
BD_ADDR[3],
BD_ADDR[2],
BD_ADDR[1],
BD_ADDR[0]);
fbtLog(fbtLog_Notice, _T("CHci::OnLinkKeyRequest: BD_ADDR: %s"), szAddress);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnAuthenticationComplete(BYTE Status, USHORT ConnectionHandle)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnAuthenticationComplete: Authentication Complete Event"));
fbtLog(fbtLog_Notice, _T("CHci::OnAuthenticationComplete: Status: 0x%0x (%s)"), Status, GetStatusText(Status));
fbtLog(fbtLog_Notice, _T("CHci::OnAuthenticationComplete: ConnectionHandle: 0x%02x"), ConnectionHandle);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHci::OnReadLocalNameComplete(BYTE Status, BYTE Name[FBT_HCI_NAME_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnReadLocalNameComplete: Read Local Name Complete Event"));
fbtLog(fbtLog_Notice, _T("CHci::OnReadLocalNameComplete: Status: 0x%0x (%s)"), Status, GetStatusText(Status));
fbtLog(fbtLog_Notice, _T("CHci::OnReadLocalNameComplete: Name: %s"), Name);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
// Handler for events that are not explicitly handled by the other On... event
// handlers
DWORD CHci::OnUnknown(PFBT_HCI_EVENT_HEADER pEvent, DWORD Length)
{
FBT_TRY
fbtLog(fbtLog_Notice, _T("CHci::OnUnknown: Unhandled event:"));
fbtLog(fbtLog_Notice, _T("CHci::OnUnknown: EventCode: 0x%02X"), pEvent->EventCode);
fbtLog(fbtLog_Notice, _T("CHci::OnUnknown: ParameterLength: 0x%02X"), pEvent->ParameterLength);
if (fbtLogGetLevel()>fbtLog_Verbose)
{
char szLog[1024]={0};
char szBuf[50]={0};
sprintf(szLog, "CHci::OnUnknown: Event data: ");
for (DWORD i=0; i<(pEvent->ParameterLength + sizeof(FBT_HCI_EVENT_HEADER)); i++)
{
sprintf(szBuf, "%02x ", ((PBYTE)pEvent)[i]);
strcat(szLog, szBuf);
}
fbtLog(fbtLog_Verbose, "%s", szLog);
}
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}