www.pudn.com > fbt-a3-20041206.zip > hciroundtrip.cpp, change:2004-03-06,size:10684b
// 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 <winioctl.h>
#include <tchar.h>
#include "fbtutil.h"
#include "fbtHciRoundTrip.h"
CHciRoundTrip::CHciRoundTrip() : CHciLocal()
{
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::CHciRoundTrip: Enter"));
// Used to signal the arrival of an event
m_hEventSignal=CreateEvent(NULL, FALSE, FALSE, NULL);
fbtLog(fbtLog_Exit, _T("CHciRoundTrip::CHciRoundTrip: Exit"));
}
CHciRoundTrip::~CHciRoundTrip()
{
CloseHandle(m_hEventSignal);
}
DWORD CHciRoundTrip::OnEvent(PFBT_HCI_EVENT_HEADER pEvent, DWORD Length)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::OnEvent: Enter"));
if (pEvent->EventCode==m_PendingEvent)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::OnEvent: Handling queued event 0x%02x"), m_PendingEvent);
if (Length>m_dwEventParameterLength)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::OnEvent: Parameter buffer provided for event 0x%02x too short %d vs %d"), m_PendingEvent, m_dwEventParameterLength, Length);
m_dwEventParameterLength=0;
SetEvent(m_hEventSignal);
return ERROR_INTERNAL_ERROR;
}
m_dwEventParameterLength=Length;
if (Length>0)
CopyMemory(m_pEventParameters, pEvent, Length);
SetEvent(m_hEventSignal);
}
else
CHciLocal::OnEvent(pEvent, Length);
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::OnEvent: Exit"));
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::QueueEvent(BYTE EventCode, LPVOID pParameters, DWORD dwParameterLength)
{
FBT_TRY
ResetEvent(m_hEventSignal);
m_PendingEvent=EventCode;
m_pEventParameters=pParameters;
m_dwEventParameterLength=dwParameterLength;
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::WaitForEvent()
{
FBT_TRY
if (WaitForSingleObject(m_hEventSignal, INFINITE)!=WAIT_OBJECT_0)
{
DWORD dwLastError=GetLastError();
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::WaitForEvent: WaitForSingleObject failed, error %d"), dwLastError);
return dwLastError;
}
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::ReadClassOfDevice(BYTE *ClassOfDevice)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::ReadClassOfDevice: Enter"));
BYTE nStatus=0;
int nSlot=QueueCommand(FBT_HCI_CMD_INQUIRY, &nStatus, sizeof(nStatus));
DWORD dwResult=SendReadClassOfDevice();
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadClassOfDevice: SendReadClassOfDevice failed, error %d"), dwResult);
DeQueueCommand(nSlot);
return dwResult;
}
dwResult=WaitForCommandComplete(nSlot);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadClassOfDevice: WaitForCommandComplete failed, error %d"), dwResult);
DeQueueCommand(nSlot);
return dwResult;
}
if (nStatus!=0)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadClassOfDevice: HCI_Read_Class_of_Device failed, status %s (0x%02x)"), GetStatusText(nStatus), nStatus);
DeQueueCommand(nSlot);
return nStatus;
}
PQueuedCommand pQueuedCommand=GetQueuedCommand(nSlot);
CopyMemory(ClassOfDevice, pQueuedCommand->pResultBuffer+1, FBT_HCI_DEVICE_CLASS_SIZE);
DeQueueCommand(nSlot);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::CreateConnection(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], USHORT PacketType, BYTE PageScanRepetitionMode, BYTE PageScanMode, USHORT ClockOffset, BYTE AllowRoleSwitch, USHORT &ConnectionHandle)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::CreateConnection: Enter"));
FBT_HCI_CONNECTION_COMPLETE ConnectionComplete;
QueueEvent(FBT_HCI_EVENT_CONNECTION_COMPLETE, &ConnectionComplete, sizeof(ConnectionComplete));
DWORD dwResult=SendCreateConnection(BD_ADDR, PacketType, PageScanRepetitionMode, PageScanMode, ClockOffset, AllowRoleSwitch);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::CreateConnection: SendCreateConnection failed, error %d"), dwResult);
return dwResult;
}
dwResult=WaitForEvent();
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::CreateConnection: WaitForEvent failed, error %d"), dwResult);
return dwResult;
}
ConnectionHandle=ConnectionComplete.ConnectionHandle;
fbtLog(fbtLog_Exit, _T("CHciRoundTrip::CreateConnection: Complete, status %s (0x%02x)"), GetStatusText(ConnectionComplete.Status), ConnectionComplete.Status);
return ConnectionComplete.Status;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::Disconnect(USHORT ConnectionHandle, BYTE Reason)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::Disconnect: Enter"));
FBT_HCI_CONNECTION_COMPLETE DisconnectionComplete;
QueueEvent(FBT_HCI_EVENT_DISCONNECTION_COMPLETE, &DisconnectionComplete, sizeof(DisconnectionComplete));
DWORD dwResult=SendDisconnect(ConnectionHandle, Reason);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::Disconnect: SendCreateConnection failed, error %d"), dwResult);
return dwResult;
}
dwResult=WaitForEvent();
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::Disconnect: WaitForEvent failed, error %d"), dwResult);
return dwResult;
}
fbtLog(fbtLog_Exit, _T("CHciRoundTrip::Disconnect: Complete, status %s (0x%02x)"), GetStatusText(DisconnectionComplete.Status), DisconnectionComplete.Status);
return DisconnectionComplete.Status;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::SwitchRole(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE Role)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::SwitchRole: Enter"));
FBT_HCI_ROLE_CHANGE RoleChange;
QueueEvent(FBT_HCI_EVENT_ROLE_CHANGE, &RoleChange, sizeof(RoleChange));
DWORD dwResult=SendSwitchRole(BD_ADDR, Role);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::SwitchRole: SendSwitchRole failed, error %d"), dwResult);
return dwResult;
}
dwResult=WaitForEvent();
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::SwitchRole: WaitForEvent failed, error %d"), dwResult);
return dwResult;
}
fbtLog(fbtLog_Exit, _T("CHciRoundTrip::SwitchRole: Complete, status %s (0x%02x)"), GetStatusText(RoleChange.Status), RoleChange.Status);
return RoleChange.Status;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::ReadBDADDR(BYTE *BD_ADDR)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::ReadBDADDR: Enter"));
struct _Result
{
BYTE nStatus;
BYTE BDADDR[FBT_HCI_BDADDR_SIZE];
} Result;
int nSlot=QueueCommand(FBT_HCI_CMD_READ_BD_ADDR, (BYTE*)&Result, sizeof(Result));
DWORD dwResult=SendReadBDADDR();
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadBDADDR: SendReadBDADDR failed, error %d"), dwResult);
DeQueueCommand(nSlot);
return dwResult;
}
dwResult=WaitForCommandComplete(nSlot);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadBDADDR: WaitForCommandComplete failed, error %d"), dwResult);
DeQueueCommand(nSlot);
return dwResult;
}
if (Result.nStatus!=0)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadBDADDR: HCI_Read_BD_ADDR failed, status %s (0x%02x)"), GetStatusText(Result.nStatus), Result.nStatus);
DeQueueCommand(nSlot);
return Result.nStatus;
}
CopyMemory(BD_ADDR, Result.BDADDR, FBT_HCI_BDADDR_SIZE);
DeQueueCommand(nSlot);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::ReadLocalName(BYTE *Name)
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::ReadLocalName: Enter"));
struct _Result
{
BYTE nStatus;
BYTE LocalName[FBT_HCI_NAME_SIZE];
} Result;
int nSlot=QueueCommand(FBT_HCI_CMD_READ_LOCAL_NAME, (BYTE*)&Result, sizeof(Result));
DWORD dwResult=SendReadLocalName();
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadLocalName: SendReadLocalName failed, error %d"), dwResult);
DeQueueCommand(nSlot);
return dwResult;
}
dwResult=WaitForCommandComplete(nSlot);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadLocalName: WaitForCommandComplete failed, error %d"), dwResult);
DeQueueCommand(nSlot);
return dwResult;
}
if (Result.nStatus!=0)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::ReadLocalName: HCI_Read_Local_Name failed, status %s (0x%02x)"), GetStatusText(Result.nStatus), Result.nStatus);
DeQueueCommand(nSlot);
return Result.nStatus;
}
CopyMemory(Name, Result.LocalName, FBT_HCI_NAME_SIZE);
DeQueueCommand(nSlot);
fbtLog(fbtLog_Exit, _T("CHciRoundTrip::ReadLocalName: Name=%s"), Name);
return ERROR_SUCCESS;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}
DWORD CHciRoundTrip::RemoteNameRequest(BYTE BD_ADDR[FBT_HCI_BDADDR_SIZE], BYTE PageScanRepetitionMode, BYTE PageScanMode, USHORT ClockOffset, BYTE Name[FBT_HCI_NAME_SIZE])
{
FBT_TRY
fbtLog(fbtLog_Enter, _T("CHciRoundTrip::RemoteNameRequest: Enter"));
FBT_HCI_REMOTE_NAME_REQUEST_COMPLETE RemoteNameComplete;
ZeroMemory(&RemoteNameComplete, sizeof(RemoteNameComplete));
QueueEvent(FBT_HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE, &RemoteNameComplete, sizeof(RemoteNameComplete));
DWORD dwResult=SendRemoteNameRequest(BD_ADDR, PageScanRepetitionMode, PageScanMode, ClockOffset);
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::RemoteNameRequest: SendRemoteNameRequest failed, error %d"), dwResult);
return dwResult;
}
fbtLog(fbtLog_Notice, _T("CHciRoundTrip::RemoteNameRequest: Command sent successfully"));
dwResult=WaitForEvent();
if (dwResult!=ERROR_SUCCESS)
{
fbtLog(fbtLog_Failure, _T("CHciRoundTrip::RemoteNameRequest: WaitForEvent failed"));
return ERROR_INTERNAL_ERROR;
}
if (RemoteNameComplete.Status==0)
CopyMemory(Name, RemoteNameComplete.RemoteName, FBT_HCI_NAME_SIZE);
fbtLog(fbtLog_Exit, _T("CHciRoundTrip::RemoteNameRequest: Exit (Status 0x%02x)"), RemoteNameComplete.Status);
return RemoteNameComplete.Status;
FBT_CATCH_RETURN(ERROR_INTERNAL_ERROR)
}