// BeaconsDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Beacons.h"
#include "BeaconsDlg.h"
#include <cmath>

#include "..\..\..\..\Source\Bluetooth\wclUUIDs.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CString FloatToStr(const double f)
{
	CString s;
	s.Format(_T("%f"), f);
	return s;
}

CString IntToStr(const char i)
{
	CString s;
	s.Format(_T("%d"), i);
	return s;
}

CString IntToStr(const size_t i)
{
	CString s;
	s.Format(_T("%d"), i);
	return s;
}

CString IntToStr(const unsigned char i)
{
	CString s;
	s.Format(_T("%d"), i);
	return s;
}

CString IntToStr(const unsigned short i)
{
	CString s;
	s.Format(_T("%d"), i);
	return s;
}

CString IntToStr(const unsigned long i)
{
	CString s;
	s.Format(_T("%d"), i);
	return s;
}

CString IntToHex(const unsigned char i)
{
	CString s;
	s.Format(_T("%.2X"), i);
	return s;
}

CString IntToHex(const int i)
{
	CString s;
	s.Format(_T("%.8X"), i);
	return s;
}

CString IntToHex(const unsigned long i)
{
	CString s;
	s.Format(_T("%.8X"), i);
	return s;
}

CString IntToHex(const unsigned short i)
{
	CString s;
	s.Format(_T("%.4X"), i);
	return s;
}

CString IntToHex(const __int64 i)
{
	CString s;
	s.Format(_T("%.4X%.8X"), static_cast<INT32>((i >> 32) & 0x00000FFFF),
		static_cast<INT32>(i) & 0xFFFFFFFF);
	return s;
}

CString GUIDToString(const GUID& Uuid)
{
	LPOLESTR Guid;
	StringFromCLSID(Uuid, &Guid);
	CString Res(Guid);
	CoTaskMemFree(Guid);
	return Res;
}

CString BoolToStr(const bool Value)
{
	if (Value)
		return _T("true");
	return _T("false");
}

/* CFrameStorage */

CFrameStorage::CFrameStorage(const AdvertisementFrame Frame, const __int64 Address,
	const __int64 Timestamp, const char Rssi)
{
	FAddress = Address;
	FFrame = Frame;
	FTimestamp = Timestamp;
	FRssi = Rssi;
}

CFrameStorage::~CFrameStorage()
{
}

__int64 CFrameStorage::GetAddress() const
{
	return FAddress;
}

AdvertisementFrame CFrameStorage::GetFrame() const
{
	return FFrame;
}

__int64 CFrameStorage::GetTimestamp() const
{
	return FTimestamp;
}

char CFrameStorage::GetRssi() const
{
	return FRssi;
}

/* CGuidFrameStorage */

CGuidFrameStorage::CGuidFrameStorage(const AdvertisementFrame Frame, const __int64 Address,
	const __int64 Timestamp, const char Rssi, const GUID& Uuid)
	: CFrameStorage(Frame, Address, Timestamp, Rssi)
{
	FUuid = Uuid;
}

GUID CGuidFrameStorage::GetUuid() const
{
	return FUuid;
}

/* CDataFrameStorage */

CDataFrameStorage::CDataFrameStorage(const AdvertisementFrame Frame, const __int64 Address,
	const __int64 Timestamp, const char Rssi,
	const wclBluetoothLeAdvertisementFrameRawData& Data)
	: CFrameStorage(Frame, Address, Timestamp, Rssi)
{
	FData = Data;
}

wclBluetoothLeAdvertisementFrameRawData CDataFrameStorage::GetData() const
{
	return FData;
}

/* CGuidDataFrameStorage */

CGuidDataFrameStorage::CGuidDataFrameStorage(const AdvertisementFrame Frame,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const GUID& Uuid, const wclBluetoothLeAdvertisementFrameRawData& Data)
	: CDataFrameStorage(Frame, Address, Timestamp, Rssi, Data)
{
	FUuid = Uuid;
}

GUID CGuidDataFrameStorage::GetUuid() const
{
	return FUuid;
}

/* CAppearanceFrame */

CAppearanceFrame::CAppearanceFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const unsigned short Appearance)
	: CFrameStorage(afAppearance, Address, Timestamp, Rssi)
{
	FAppearance = Appearance;
}

unsigned short CAppearanceFrame::GetAppearance() const
{
	return FAppearance;
}

/* CExtInformationFrame */

CExtInformationFrame::CExtInformationFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothAddressType AddressType,
	const wclBluetoothLeExtendedFrameFlags& Flags, const char TxPower)
	: CFrameStorage(afExtInformation, Address, Timestamp, Rssi)
{
	FAddressType = AddressType;
	FFlags = Flags;
	FTxPower = TxPower;
}

wclBluetoothAddressType CExtInformationFrame::GetAddressType() const
{
	return FAddressType;
}

wclBluetoothLeExtendedFrameFlags CExtInformationFrame::GetFlags() const
{
	return FFlags;
}

char CExtInformationFrame::GetTxPower() const
{
	return FTxPower;
}

/* CInformationFrame */

CInformationFrame::CInformationFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFlags& Flags,
	const tstring& Name, const wclBluetoothLeAdvertisementType PacketType)
	: CFrameStorage(afInformation, Address, Timestamp, Rssi)
{
	FFlags = Flags;
	FName = Name;
	FPacketType = PacketType;
}

wclBluetoothLeAdvertisementFlags CInformationFrame::GetFlags() const
{
	return FFlags;
}

tstring CInformationFrame::GetName() const
{
	return FName;
}

wclBluetoothLeAdvertisementType CInformationFrame::GetPacketType() const
{
	return FPacketType;
}

/* CRawFrame */

CRawFrame::CRawFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data,
	const unsigned char DataType)
	: CDataFrameStorage(afRaw, Address, Timestamp, Rssi, Data)
{
	FDataType = DataType;
}

unsigned char CRawFrame::GetDataType() const
{
	return FDataType;
}

/* CDetailsFrame */

CDetailsFrame::CDetailsFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data)
	: CDataFrameStorage(afDetails, Address, Timestamp, Rssi, Data)
{
}

/* CService16DataFrame */

CService16DataFrame::CService16DataFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data,
	const unsigned short Uuid)
	: CDataFrameStorage(afService16Data, Address, Timestamp, Rssi, Data)
{
	FUuid = Uuid;
}

unsigned short CService16DataFrame::GetUuid() const
{
	return FUuid;
}

/* CService32DataFrame */

CService32DataFrame::CService32DataFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data,
	const unsigned long Uuid)
	: CDataFrameStorage(afService32Data, Address, Timestamp, Rssi, Data)
{
	FUuid = Uuid;
}

unsigned long CService32DataFrame::GetUuid() const
{
	return FUuid;
}

/* CService128DataFrame */


CService128DataFrame::CService128DataFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const GUID& Uuid,
	const wclBluetoothLeAdvertisementFrameRawData& Data)
	: CGuidDataFrameStorage(afService128Data, Address, Timestamp, Rssi, Uuid, Data)
{
}

/* CSol16Frame */

CSol16Frame::CSol16Frame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const unsigned short Uuid)
	: CFrameStorage(afSol16, Address, Timestamp, Rssi)
{
	FUuid = Uuid;
}

unsigned short CSol16Frame::GetUuid() const
{
	return FUuid;
}

/* CSol32Frame */

CSol32Frame::CSol32Frame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const unsigned long Uuid)
	: CFrameStorage(afSol32, Address, Timestamp, Rssi)
{
	FUuid = Uuid;
}

unsigned long CSol32Frame::GetUuid() const
{
	return FUuid;
}

/* CSol128Frame */

CSol128Frame::CSol128Frame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const GUID& Uuid)
	: CGuidFrameStorage(afSol128, Address, Timestamp, Rssi, Uuid)
{
}

/* CTxPowerFrame */

CTxPowerFrame::CTxPowerFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const char TxPower)
	: CFrameStorage(afTxPower, Address, Timestamp, Rssi)
{
	FTxPower = TxPower;
}

char CTxPowerFrame::GetTxPower() const
{
	return FTxPower;
}

/* CUuidFrame */

CUuidFrame::CUuidFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const GUID& Uuid)
	: CGuidFrameStorage(afUuid, Address, Timestamp, Rssi, Uuid)
{
}

/* CBeaconFrame */

CBeaconFrame::CBeaconFrame(const AdvertisementFrame Frame, const __int64 Address,
	const __int64 Timestamp, const char Rssi,
	const wclBluetoothLeAdvertisementFrameRawData& Data,
	const GUID& Uuid, const unsigned short CompanyId, const unsigned short Major,
	const unsigned short Minor, const char TxRssi)
	: CGuidDataFrameStorage(Frame, Address, Timestamp, Rssi, Uuid, Data)
{
	FCompanyId = CompanyId;
	FMajor = Major;
	FMinor = Minor;
	FTxRssi = TxRssi;
}

unsigned short CBeaconFrame::GetCompanyId() const
{
	return FCompanyId;
}

unsigned short CBeaconFrame::GetMajor() const
{
	return FMajor;
}

unsigned short CBeaconFrame::GetMinor() const
{
	return FMinor;
}

char CBeaconFrame::GetTxRssi() const
{
	return FTxRssi;
}

/* CAltBeaconFrame */

CAltBeaconFrame::CAltBeaconFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data,
	const GUID& Uuid, const unsigned short CompanyId, const unsigned short Major,
	const unsigned short Minor, const char TxRssi, const unsigned char Reserved)
	: CBeaconFrame(afAltBeacon, Address, Timestamp, Rssi, Data, Uuid, CompanyId,
	Major, Minor, TxRssi)
{
	FReserved = Reserved;
}

unsigned char CAltBeaconFrame::GetReserved() const
{
	return FReserved;
}

/* CMicrosoftCdpBeaconFrame */

CMicrosoftCdpBeaconFrame::CMicrosoftCdpBeaconFrame(const __int64 Address,
	const __int64 Timestamp, const char Rssi, const bool AddressAsDeviceId,
	const wclBluetoothLeCdpBeaconDeviceType DeviceType,
	const wclBluetoothLeCdpBeaconExtendedDeviceStatuses& ExtendedDeviceStatus,
	const wclBluetoothLeCdpBeaconHash& Hash, const wclBluetoothLeCdpBeaconSalt& Salt,
	const wclBluetoothLeCdpBeaconScenarioType ScenarioType,
	const bool ShareNearBy, const unsigned char SubVersion,
	const unsigned char Version)
	: CFrameStorage(afMicrosoftCdpBeacon, Address, Timestamp, Rssi)
{
	FAddressAsDeviceId = AddressAsDeviceId;
	FDeviceType = DeviceType;
	FExtendedDeviceStatus = ExtendedDeviceStatus;
	FHash = Hash;
	FSalt = Salt;
	FScenarioType = ScenarioType;
	FShareNearBy = ShareNearBy;
	FSubVersion  = SubVersion;
	FVersion = Version;
}

bool CMicrosoftCdpBeaconFrame::GetAddressAsDeviceId() const
{
	return FAddressAsDeviceId;
}

wclBluetoothLeCdpBeaconDeviceType CMicrosoftCdpBeaconFrame::GetDeviceType() const
{
	return FDeviceType;
}

wclBluetoothLeCdpBeaconExtendedDeviceStatuses CMicrosoftCdpBeaconFrame::GetExtendedDeviceStatus() const
{
	return FExtendedDeviceStatus;
}

wclBluetoothLeCdpBeaconHash CMicrosoftCdpBeaconFrame::GetHash() const
{
	return FHash;
}

wclBluetoothLeCdpBeaconSalt CMicrosoftCdpBeaconFrame::GetSalt() const
{
	return FSalt;
}

wclBluetoothLeCdpBeaconScenarioType CMicrosoftCdpBeaconFrame::GetScenarioType() const
{
	return FScenarioType;
}

bool CMicrosoftCdpBeaconFrame::GetShareNearBy() const
{
	return FShareNearBy;
}

unsigned char CMicrosoftCdpBeaconFrame::GetSubVersion() const
{
	return FSubVersion;
}

unsigned char CMicrosoftCdpBeaconFrame::GetVersion() const
{
	return FVersion;
}

/* CAppleFrame */

CAppleFrame::CAppleFrame(const AdvertisementFrame Frame,
	const wclBluetoothLeAdvertisementInfo& Info)
	: CFrameStorage(Frame, Info.Address, Info.Timestamp, Info.Rssi)
{
}

/* CAppleAirdropFrame */

CAppleAirdropFrame::CAppleAirdropFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirdropFrameData& Data)
	: CAppleFrame(afAppleAirdrop, Info)
{
	FData = Data;
}

wclBluetoothLeAppleAirdropFrameData CAppleAirdropFrame::GetData() const
{
	return FData;
}

/* CAppleAirplaySourceFrame */

CAppleAirplaySourceFrame::CAppleAirplaySourceFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirplaySourceFrameData& Data)
	: CAppleFrame(afAppleAirplaySource, Info)
{
	FData = Data;
}

wclBluetoothLeAppleAirplaySourceFrameData CAppleAirplaySourceFrame::GetData() const
{
	return FData;
}

/* CAppleAirplayTargetFrame */

CAppleAirplayTargetFrame::CAppleAirplayTargetFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirplayTargetFrameData& Data)
	: CAppleFrame(afAppleAirplayTarget, Info)
{
	FData = Data;
}

wclBluetoothLeAppleAirplayTargetFrameData CAppleAirplayTargetFrame::GetData() const
{
	return FData;
}

/* CAppleAirprintFrame */

CAppleAirprintFrame::CAppleAirprintFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirprintFrameData& Data)
	: CAppleFrame(afAppleAirprint, Info)
{
	FData = Data;
}

wclBluetoothLeAppleAirprintFrameData CAppleAirprintFrame::GetData() const
{
	return FData;
}

/* CAppleHomeKitFrame */

CAppleHomeKitFrame::CAppleHomeKitFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleHomeKitFrameData& Data)
	: CAppleFrame(afAppleHomeKit, Info)
{
	FData = Data;
}

wclBluetoothLeAppleHomeKitFrameData CAppleHomeKitFrame::GetData() const
{
	return FData;
}

/* CAppleiBeaconFrame */

CAppleiBeaconFrame::CAppleiBeaconFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleiBeaconFrameData& Data)
	: CAppleFrame(afAppleiBeacon, Info)
{
	FData = Data;
}

wclBluetoothLeAppleiBeaconFrameData CAppleiBeaconFrame::GetData() const
{
	return FData;
};

/* CAppleNearbyActionFrame */

CAppleNearbyActionFrame::CAppleNearbyActionFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleNearbyActionFrameData& Data)
	: CAppleFrame(afAppleNearbyAction, Info)
{
	FData = Data;
}

wclBluetoothLeAppleNearbyActionFrameData CAppleNearbyActionFrame::GetData() const
{
	return FData;
}

/* CAppleNearbyInfoFrame */

CAppleNearbyInfoFrame::CAppleNearbyInfoFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleNearbyInfoFrameData& Data)
	: CAppleFrame(afAppleNearbyInfo, Info)
{
	FData = Data;
}

wclBluetoothLeAppleNearbyInfoFrameData CAppleNearbyInfoFrame::GetData() const
{
	return FData;
}

/* CAppleProximityPairingFrame */

CAppleProximityPairingFrame::CAppleProximityPairingFrame(
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleProximityPairingFrameData& Data)
	: CAppleFrame(afAppleProximityPairing, Info)
{
	FData = Data;
}

wclBluetoothLeAppleProximityPairingFrameData CAppleProximityPairingFrame::GetData() const
{
	return FData;
}

/* CAppleUnknownFrame */

CAppleUnknownFrame::CAppleUnknownFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleUnknownFrameData& Data)
	: CAppleFrame(afAppleUnknown, Info)
{
	FData = Data;
}

wclBluetoothLeAppleUnknownFrameData CAppleUnknownFrame::GetData() const
{
	return FData;
}

/* CAppleFindMyFrame */

CAppleFindMyFrame::CAppleFindMyFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleFindMyFrameData& Data)
	: CAppleFrame(afAppleFindMy, Info)
{
	FData = Data;
}

wclBluetoothLeAppleFindMyFrameData CAppleFindMyFrame::GetData() const
{
	return FData;
}

/* CAppleHandoffFrame */

CAppleHandoffFrame::CAppleHandoffFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleHandoffFrameData& Data)
	: CAppleFrame(afAppleHandoff, Info)
{
	FData = Data;
}

wclBluetoothLeAppleHandoffFrameData CAppleHandoffFrame::GetData() const
{
	return FData;
}

/* CAppleHeySiriFrame */

CAppleHeySiriFrame::CAppleHeySiriFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleHeySiriFrameData& Data)
	: CAppleFrame(afAppleHeySiri, Info)
{
	FData = Data;
}

wclBluetoothLeAppleHeySiriFrameData CAppleHeySiriFrame::GetData() const
{
	return FData;
}

/* CAppleMagicSwitchFrame */

CAppleMagicSwitchFrame::CAppleMagicSwitchFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleMagicSwitchFrameData& Data)
	: CAppleFrame(afAppleMagicSwitch, Info)
{
	FData = Data;
}

wclBluetoothLeAppleMagicSwitchFrameData CAppleMagicSwitchFrame::GetData() const
{
	return FData;
}

/* CAppleTetheringSourceFrame */

CAppleTetheringSourceFrame::CAppleTetheringSourceFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleTetheringSourceFrameData& Data)
	: CAppleFrame(afAppleTetheringSource, Info)
{
	FData = Data;
}

wclBluetoothLeAppleTetheringSourceFrameData CAppleTetheringSourceFrame::GetData() const
{
	return FData;
}

/* CAppleTetheringTargetFrame */

CAppleTetheringTargetFrame::CAppleTetheringTargetFrame(const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleTetheringTargetFrameData& Data)
	: CAppleFrame(afAppleTetheringTarget, Info)
{
	FData = Data;
}

wclBluetoothLeAppleTetheringTargetFrameData CAppleTetheringTargetFrame::GetData() const
{
	return FData;
}

/* CEddystoneTlmFrame */

CEddystoneTlmFrame::CEddystoneTlmFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data,
	const unsigned long AdvCnt, const unsigned short Batt, const unsigned long SecCnt,
	const double Temp)
	: CDataFrameStorage(afEddystoneTlm, Address, Timestamp, Rssi, Data)
{
	FAdvCnt = AdvCnt;
	FBatt = Batt;
	FSecCnt = SecCnt;
	FTemp = Temp;
}

unsigned long CEddystoneTlmFrame::GetAdvCnt() const
{
	return FAdvCnt;
}

unsigned short CEddystoneTlmFrame::GetBatt() const
{
	return FBatt;
}

unsigned long CEddystoneTlmFrame::GetSecCnt() const
{
	return FSecCnt;
}

double CEddystoneTlmFrame::GetTemp() const
{
	return FTemp;
}

/* CEddystoneUidFrame */

CEddystoneUidFrame::CEddystoneUidFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclBluetoothLeAdvertisementFrameRawData& Data,
	const GUID& Uuid, const char TxRssi)
	: CGuidDataFrameStorage(afEddystoneUid, Address, Timestamp, Rssi, Uuid, Data)
{
	FTxRssi = TxRssi;
}

char CEddystoneUidFrame::GetTxRssi() const
{
	return FTxRssi;
}

/* CEddystoneUrlFrame */

CEddystoneUrlFrame::CEddystoneUrlFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const char TxRssi, const tstring& Url)
	: CFrameStorage(afEddystoneUrl, Address, Timestamp, Rssi)
{
	FTxRssi = TxRssi;
	FUrl = Url;
}

char CEddystoneUrlFrame::GetTxRssi() const
{
	return FTxRssi;
}

tstring CEddystoneUrlFrame::GetUrl() const
{
	return FUrl;
}

/* CManufacturerFrame */

CManufacturerFrame::CManufacturerFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const unsigned short CompanyId,
	const wclBluetoothLeAdvertisementFrameRawData& Data)
	: CDataFrameStorage(afManufacturerRaw, Address, Timestamp, Rssi, Data)
{
	FCompanyId = CompanyId;
}

unsigned short CManufacturerFrame::GetCompanyId() const
{
	return FCompanyId;
}

/* CDriAsdFrame */

CDriAsdFrame::CDriAsdFrame(const __int64 Address, const __int64 Timestamp,
	const char Rssi, const wclDriRawData& Raw)
	: CFrameStorage(afDriAsd, Address, Timestamp, Rssi)
{
	FRaw = Raw;
}

wclDriRawData CDriAsdFrame::GetRaw() const
{
	return FRaw;
}





// CBeaconsDlg dialog




CBeaconsDlg::CBeaconsDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CBeaconsDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CBeaconsDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_COMBO_WATCHER_SCAN_MODE, cbWatcherScanMode);
	DDX_Control(pDX, IDC_EDIT_WATCHER_SCAN_INTERVAL, edWatcherScanInterval);
	DDX_Control(pDX, IDC_EDIT_WATCHER_SCAN_WINDOW, edWatcherScanWindow);
	DDX_Control(pDX, IDC_CHECK_WATCHER_ENABLE_EXTENDED, cbWatcherEnableExtended);
	DDX_Control(pDX, IDC_BUTTON_WATCHER_DEFAULT, btWatcherDefault);
	DDX_Control(pDX, IDC_BUTTON_WATCHER_START, btWatcherStart);
	DDX_Control(pDX, IDC_BUTTON_WATCHER_STOP, btWatcherStop);
	DDX_Control(pDX, IDC_LIST_DEVICES, lvDevices);
	DDX_Control(pDX, IDC_LIST_FRAME_DETAILS, lvFrameDetails);
	DDX_Control(pDX, IDC_EDIT_ADVERTISER_INTERVAL, edAdvertiserInterval);
	DDX_Control(pDX, IDC_BUTTON_ADVERTISER_DEFAULT, btAdvertiserDefault);
	DDX_Control(pDX, IDC_BUTTON_ADVERTISER_START, btAdvertiserStart);
	DDX_Control(pDX, IDC_BUTTON_ADVERTISER_STOP, btAdvertiserStop);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_BEACON, cbAdvertiserBeacon);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_PROXIMITY_BEACON, cbAdvertiserProximityBeacon);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_ALT_BEACON, cbAdvertiserAltBeacon);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_EDDYSTONE_UID, cbAdvertiserEddystoneUid);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_EDDYSTONE_URL, cbAdvertiserEddystoneUrl);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_MANUFACTURER, cbAdvertiserManufacturer);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_16_UUID, cbAdvertiser16Uuid);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_32_UUID, cbAdvertiser32Uuid);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_128_UUID, cbAdvertiser128Uuid);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_16_UUID_DATA, cbAdvertiser16UuidData);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_32_UUID_DATA, cbAdvertiser32UuidData);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_128_UUID_DATA, cbAdvertiser128UuidData);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_128_SOL_UUID, cbAdvertiser128SolUuid);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_CUSTOM, cbAdvertiserCustom);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_EXTENDED, cbAdvertiserExtended);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_ANONYMOUS, cbAdvertiserAnonymous);
	DDX_Control(pDX, IDC_CHECK_ADVERTISER_TX_RSSI, cbAdvertiserTxRssi);
	DDX_Control(pDX, IDC_CHECK_AUTOSCROLL, cbAutoScroll);
	DDX_Control(pDX, IDC_LIST_LOG, lbLog);
}

BEGIN_MESSAGE_MAP(CBeaconsDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_DEVICES, &CBeaconsDlg::OnLvnItemchangedListDevices)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_CLEAR_LOG, &CBeaconsDlg::OnBnClickedButtonClearLog)
	ON_BN_CLICKED(IDC_BUTTON_WATCHER_DEFAULT, &CBeaconsDlg::OnBnClickedButtonWatcherDefault)
	ON_BN_CLICKED(IDC_BUTTON_ADVERTISER_DEFAULT, &CBeaconsDlg::OnBnClickedButtonAdvertiserDefault)
	ON_BN_CLICKED(IDC_CHECK_ADVERTISER_EXTENDED, &CBeaconsDlg::OnBnClickedCheckAdvertiserExtended)
	ON_BN_CLICKED(IDC_BUTTON_WATCHER_START, &CBeaconsDlg::OnBnClickedButtonWatcherStart)
	ON_BN_CLICKED(IDC_BUTTON_WATCHER_STOP, &CBeaconsDlg::OnBnClickedButtonWatcherStop)
	ON_BN_CLICKED(IDC_BUTTON_ADVERTISER_START, &CBeaconsDlg::OnBnClickedButtonAdvertiserStart)
	ON_BN_CLICKED(IDC_BUTTON_ADVERTISER_STOP, &CBeaconsDlg::OnBnClickedButtonAdvertiserStop)
END_MESSAGE_MAP()


// CBeaconsDlg message handlers

void CBeaconsDlg::MakeBold(int Id)
{
	CWnd* Wnd = GetDlgItem(Id);
	CFont* Font = Wnd->GetFont();
	LOGFONT LF;
	Font->GetLogFont(&LF);
	LF.lfWeight = FW_BOLD;
	Font = new CFont();
	Font->CreateFontIndirect(&LF);
	Wnd->SetFont(Font);
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CBeaconsDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CBeaconsDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CBeaconsDlg::AdvertiserDefaults()
{
	LeAdvertiser.RestoreDefaults();
	edAdvertiserInterval.SetWindowText(IntToStr(LeAdvertiser.Interval));
	
	cbAdvertiserBeacon.SetCheck(TRUE);
	cbAdvertiserProximityBeacon.SetCheck(FALSE);
	cbAdvertiserAltBeacon.SetCheck(FALSE);
	cbAdvertiserEddystoneUid.SetCheck(FALSE);
	cbAdvertiserEddystoneUrl.SetCheck(FALSE);
	cbAdvertiser128SolUuid.SetCheck(FALSE);
	cbAdvertiserManufacturer.SetCheck(FALSE);
	cbAdvertiser16Uuid.SetCheck(FALSE);
	cbAdvertiser32Uuid.SetCheck(FALSE);
	cbAdvertiser128Uuid.SetCheck(FALSE);
	cbAdvertiser16UuidData.SetCheck(FALSE);
	cbAdvertiser32UuidData.SetCheck(FALSE);
	cbAdvertiser128UuidData.SetCheck(FALSE);
	cbAdvertiserCustom.SetCheck(FALSE);
	
	cbAdvertiserExtended.SetCheck(FALSE);
	cbAdvertiserAnonymous.SetCheck(FALSE);
	cbAdvertiserTxRssi.SetCheck(FALSE);
	
	cbAdvertiserAnonymous.EnableWindow(FALSE);
	cbAdvertiserTxRssi.EnableWindow(FALSE);
}

void CBeaconsDlg::WatcherDefaults()
{
	BeaconWatcher.RestoreDefaults();
	if (BeaconWatcher.ScanningMode == smActive)
		cbWatcherScanMode.SetCurSel(0);
	else
		cbWatcherScanMode.SetCurSel(1);
	edWatcherScanInterval.SetWindowText(IntToStr(BeaconWatcher.ScanInterval));
	edWatcherScanWindow.SetWindowText(IntToStr(BeaconWatcher.ScanWindow));
	cbWatcherEnableExtended.SetCheck(BeaconWatcher.AllowExtendedAdvertisements);
}

void CBeaconsDlg::AdvertiserEnableControls(const BOOL Stopped)
{
	btAdvertiserStart.EnableWindow(Stopped);
	btAdvertiserStop.EnableWindow(!Stopped);
	btAdvertiserDefault.EnableWindow(Stopped);
	
	edAdvertiserInterval.EnableWindow(Stopped);
	
	cbAdvertiserBeacon.EnableWindow(Stopped);
	cbAdvertiserProximityBeacon.EnableWindow(Stopped);
	cbAdvertiserAltBeacon.EnableWindow(Stopped);
	cbAdvertiserEddystoneUid.EnableWindow(Stopped);
	cbAdvertiserEddystoneUrl.EnableWindow(Stopped);
	cbAdvertiser128SolUuid.EnableWindow(Stopped);
	cbAdvertiserManufacturer.EnableWindow(Stopped);
	cbAdvertiser16Uuid.EnableWindow(Stopped);
	cbAdvertiser32Uuid.EnableWindow(Stopped);
	cbAdvertiser128Uuid.EnableWindow(Stopped);
	cbAdvertiser16UuidData.EnableWindow(Stopped);
	cbAdvertiser32UuidData.EnableWindow(Stopped);
	cbAdvertiser128UuidData.EnableWindow(Stopped);
	cbAdvertiserCustom.EnableWindow(Stopped);
	
	cbAdvertiserExtended.EnableWindow(Stopped);
	cbAdvertiserAnonymous.EnableWindow(Stopped && cbAdvertiserExtended.GetCheck());
	cbAdvertiserTxRssi.EnableWindow(Stopped && cbAdvertiserExtended.GetCheck());
}

void CBeaconsDlg::WatcherEnableControls(const BOOL Stopped)
{
	cbWatcherScanMode.EnableWindow(Stopped);
	edWatcherScanInterval.EnableWindow(Stopped);
	edWatcherScanWindow.EnableWindow(Stopped);
	cbWatcherEnableExtended.EnableWindow(Stopped);
	
	btWatcherDefault.EnableWindow(Stopped);
	
	btWatcherStart.EnableWindow(Stopped);
	btWatcherStop.EnableWindow(!Stopped);
}

void CBeaconsDlg::Trace(const CString& Msg)
{
	lbLog.AddString(Msg);
	if (cbAutoScroll.GetCheck())
		lbLog.SetTopIndex(lbLog.GetCount() - 1);
}

void CBeaconsDlg::Trace(const CString& Msg, const int Res)
{
	Trace(Msg + _T(" failed: 0x") + IntToHex(Res));
}

CwclBluetoothRadio* CBeaconsDlg::GetRadio()
{
	int Res = WCL_E_SUCCESS;
	if (!BluetoothManager.Active)
		Res = BluetoothManager.Open();
	
	if (Res != WCL_E_SUCCESS)
	{
		Trace(_T("Bluetooth Manager open"), Res);
		return NULL;
	}
	
	CwclBluetoothRadio* Radio;
	Res = BluetoothManager.GetLeRadio(Radio);
	if (Res != WCL_E_SUCCESS)
	{
		Trace(_T("Get working radio"), Res);
		return NULL;
	}
	
	Trace(_T("Use ") + CString(Radio->ApiName.c_str()) + _T(" radio"));
	return Radio;
}

BOOL CBeaconsDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application"s main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	cbWatcherScanMode.AddString(_T("Active"));
	cbWatcherScanMode.AddString(_T("Passive"));

	lvDevices.InsertColumn(0, _T("Device"), 0, 100);
	lvDevices.InsertColumn(1, _T("Field type"), 0, 100);
	lvDevices.SetExtendedStyle(LVS_EX_FULLROWSELECT);

	lvFrameDetails.InsertColumn(0, _T("Field"), 0, 150);
	lvFrameDetails.InsertColumn(1, _T("Value"), 0, 350);
	lvFrameDetails.SetExtendedStyle(LVS_EX_FULLROWSELECT);

	MakeBold(IDC_STATIC_BEACON_WATCHER);
	MakeBold(IDC_STATIC_LE_ADVERTISER);
	MakeBold(IDC_STATIC_LOG);

	AdvertiserDefaults();
	WatcherDefaults();
	
	btAdvertiserStop.EnableWindow(FALSE);
	btWatcherStop.EnableWindow(FALSE);
	
	cbAutoScroll.SetCheck(TRUE);

	__hook(&CwclBluetoothManager::AfterOpen, &BluetoothManager, &CBeaconsDlg::BluetoothManagerAfterOpen);
	__hook(&CwclBluetoothManager::BeforeClose, &BluetoothManager, &CBeaconsDlg::BluetoothManagerBeforeClose);
	__hook(&CwclBluetoothManager::OnClosed, &BluetoothManager, &CBeaconsDlg::BluetoothManagerClosed);

	__hook(&CwclBluetoothLeBeaconWatcher::OnStarted, &BeaconWatcher, &CBeaconsDlg::BeaconWatcherStarted);
	__hook(&CwclBluetoothLeBeaconWatcher::OnStopped, &BeaconWatcher, &CBeaconsDlg::BeaconWatcherStopped);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementAppearanceFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementAppearanceFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementExtFrameInformation, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementExtFrameInformation);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementFrameInformation, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementFrameInformation);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementRawFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementRawFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementReceived, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementReceived);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementService128DataFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementService128DataFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementService16DataFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementService16DataFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementService32DataFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementService32DataFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementServiceSol128Frame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementServiceSol128Frame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementServiceSol16Frame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementServiceSol16Frame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementServiceSol32Frame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementServiceSol32Frame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementTxPowerLevelFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementTxPowerLevelFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAdvertisementUuidFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAdvertisementUuidFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAltBeaconFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAltBeaconFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnEddystoneTlmFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherEddystoneTlmFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnEddystoneUidFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherEddystoneUidFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnEddystoneUrlFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherEddystoneUrlFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnManufacturerRawFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherManufacturerRawFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnMicrosoftCdpBeaconFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherMicrosoftCdpBeaconFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleiBeaconFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleiBeaconFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleNearbyActionFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleNearbyActionFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleNearbyInfoFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleNearbyInfoFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnDriAsdMessage, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherDriAsdMessage);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleHomeKitFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleHomeKitFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleUnknownFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleUnknownFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleAirplaySourceFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleAirplaySourceFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleAirplayTargetFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleAirplayTargetFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleAirdropFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleAirdropFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleAirprintFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleAirprintFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleProximityPairingFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleProximityPairingFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleFindMyFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleFindMyFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleHandoffFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleHandoffFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleHeySiriFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleHeySiriFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleMagicSwitchFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleMagicSwitchFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleTetheringSourceFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleTetheringSourceFrame);
	__hook(&CwclBluetoothLeBeaconWatcher::OnAppleTetheringTargetFrame, &BeaconWatcher,
		&CBeaconsDlg::BeaconWatcherAppleTetheringTargetFrame);

	__hook(&CwclBluetoothLeAdvertiser::OnStarted, &LeAdvertiser, &CBeaconsDlg::LeAdvertiserStarted);
	__hook(&CwclBluetoothLeAdvertiser::OnStopped, &LeAdvertiser, &CBeaconsDlg::LeAdvertiserStopped);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

int CBeaconsDlg::AddDevice(const __int64 Address)
{
	CString AddrStr = IntToHex(Address);
	
	if (lvDevices.GetItemCount() > 0)
	{
		for (int i = 0; i < lvDevices.GetItemCount(); i++)
		{
			if (AddrStr == lvDevices.GetItemText(i, 0))
				return i;
		}
	}

	int Item = lvDevices.GetItemCount();
	lvDevices.InsertItem(Item, AddrStr);
	lvDevices.SetItemText(Item, 1, _T(""));
	lvDevices.SetItemData(Item, NULL);
	return Item;
}

void CBeaconsDlg::AddFrame(CFrameStorage* const Frame)
{
	int FrameItem = -1;
	
	int Device = AddDevice(Frame->Address);
	if (Device < lvDevices.GetItemCount() - 1)
	{
		for (int i = Device + 1; i < lvDevices.GetItemCount(); i++)
		{
			if (lvDevices.GetItemData(i) == NULL)
				break;
			
			if (((CFrameStorage*)lvDevices.GetItemData(i))->Frame == Frame->Frame)
			{
				FrameItem = i;
				break;
			}
		}
	}
	
	if (FrameItem == -1)
	{
		FrameItem = Device + 1;
		lvDevices.InsertItem(FrameItem, _T(""));
		lvDevices.SetItemData(FrameItem, NULL);
		
		switch (Frame->Frame)
		{
			case afAppearance:
				lvDevices.SetItemText(FrameItem, 1, _T("Appearance"));
				break;
			case afExtInformation:
				lvDevices.SetItemText(FrameItem, 1, _T("Ext Information"));
				break;
			case afInformation:
				lvDevices.SetItemText(FrameItem, 1, _T("Information"));
				break;
			case afRaw:
				lvDevices.SetItemText(FrameItem, 1, _T("Raw"));
				break;
			case afDetails:
				lvDevices.SetItemText(FrameItem, 1, _T("Details"));
				break;
			case afService16Data:
				lvDevices.SetItemText(FrameItem, 1, _T("Service 16"));
				break;
			case afService32Data:
				lvDevices.SetItemText(FrameItem, 1, _T("Service 32"));
				break;
			case afService128Data:
				lvDevices.SetItemText(FrameItem, 1, _T("Service 128"));
				break;
			case afSol16:
				lvDevices.SetItemText(FrameItem, 1, _T("16 SOL"));
				break;
			case afSol32:
				lvDevices.SetItemText(FrameItem, 1, _T("32 SOL"));
				break;
			case afSol128:
				lvDevices.SetItemText(FrameItem, 1, _T("128 SOL"));
				break;
			case afTxPower:
				lvDevices.SetItemText(FrameItem, 1, _T("Tx Power"));
				break;
			case afUuid:
				lvDevices.SetItemText(FrameItem, 1, _T("UUID"));
				break;
			case afAltBeacon:
				lvDevices.SetItemText(FrameItem, 1, _T("Alt Beacon"));
				break;
			case afEddystoneTlm:
				lvDevices.SetItemText(FrameItem, 1, _T("Eddystone TLM"));
				break;
			case afEddystoneUid:
				lvDevices.SetItemText(FrameItem, 1, _T("Eddystone UID"));
				break;
			case afEddystoneUrl:
				lvDevices.SetItemText(FrameItem, 1, _T("Eddystone URL"));
				break;
			case afManufacturerRaw:
				lvDevices.SetItemText(FrameItem, 1, _T("Manufacturer"));
				break;
			case afMicrosoftCdpBeacon:
				lvDevices.SetItemText(FrameItem, 1, _T("Microsoft CDP"));
				break;
			case afAppleAirdrop:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple AirDrop"));
				break;
			case afAppleAirplaySource:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Airplay Source"));
				break;
			case afAppleAirplayTarget:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Airplay Target"));
				break;
			case afAppleAirprint:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple AirPrint"));
				break;
			case afAppleHomeKit:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Home Kit"));
				break;
			case afAppleiBeacon:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple iBeacon"));
				break;
			case afAppleNearbyAction:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Nearby Action"));
				break;
			case afAppleNearbyInfo:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Nearby Info"));
				break;
			case afAppleProximityPairing:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Proximity Pairing"));
				break;
			case afAppleUnknown:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Unknown"));
				break;
			case afAppleFindMy:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Find My"));
				break;
			case afAppleHandoff:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Handoff"));
				break;
			case afAppleHeySiri:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Hey Siri"));
				break;
			case afAppleMagicSwitch:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Magic Switch"));
				break;
			case afAppleTetheringSource:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Tethering Source"));
				break;
			case afAppleTetheringTarget:
				lvDevices.SetItemText(FrameItem, 1, _T("Apple Tethering Target"));
			case afDriAsd:
				lvDevices.SetItemText(FrameItem, 1, _T("DRI ASD"));
				break;
			default:
				lvDevices.SetItemText(FrameItem, 1, _T("Unknown"));
				break;
		}
	}
	
	if (lvDevices.GetItemData(FrameItem) != NULL)
		delete (CFrameStorage*)lvDevices.GetItemData(FrameItem);
	lvDevices.SetItemData(FrameItem, (DWORD_PTR)Frame);
	
	if (Frame->Frame == afInformation)
	{
		if (((CInformationFrame*)Frame)->Name != _T(""))
			lvDevices.SetItemText(Device, 1, ((CInformationFrame*)Frame)->Name.c_str());
	}
	
	POSITION Pos = lvDevices.GetFirstSelectedItemPosition();
	if (Pos != NULL)
	{
		int Sel = lvDevices.GetNextSelectedItem(Pos);
		if (FrameItem == Sel)
			ShowFrameData(Frame);
	}
}

CString CBeaconsDlg::ConvertTime(const __int64 Timestamp)
{
	ULARGE_INTEGER li;
	FILETIME ft;
	SYSTEMTIME st;

	li.QuadPart = Timestamp;
	ft.dwLowDateTime = li.LowPart;
	ft.dwHighDateTime = li.HighPart;
	FileTimeToLocalFileTime(&ft, &ft);
	FileTimeToSystemTime(&ft, &st);
	CString DateTimeStr;
	DateTimeStr.Format(_T("%d-%02d-%02d %02d:%02d:%02d.%03d"),
		st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute,
		st.wSecond, st.wMilliseconds);
	return DateTimeStr;
}

void CBeaconsDlg::ShowData(const CString& Name, const CString& Value)
{
	int Item = lvFrameDetails.GetItemCount();
	lvFrameDetails.InsertItem(Item, Name);
	lvFrameDetails.SetItemText(Item, 1, Value);
}

void CBeaconsDlg::ShowFrameBaseData(CFrameStorage* const Frame)
{
	ShowData(_T("Address"), IntToHex(Frame->Address));
	ShowData(_T("Timestamp"), ConvertTime(Frame->Timestamp));
	ShowData(_T("RSSI"), IntToStr(Frame->Rssi));
}

void CBeaconsDlg::ShowFrameRawData(const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	CString First = _T("Data");
	
	if (Data.size() > 0)
	{
		CString Str = _T("");
		unsigned char c = 0;
		for (wclBluetoothLeAdvertisementFrameRawData::const_iterator i = Data.begin(); i != Data.end(); i++)
		{
			Str = Str + IntToHex(*i) + _T(" ");
			if (c == 15)
			{
				ShowData(First, Str);
				
				First = _T("");
				Str = _T("");
				c = 0;
			}
			else
				c++;
		}
		
		if (Str != _T(""))
			ShowData(First, Str);
	}
}

void CBeaconsDlg::ShowDriFrameRawData(const wclDriRawData& Raw)
{
	if (Raw.size() > 0)
	{
		wclBluetoothLeAdvertisementFrameRawData Data;
		for (wclDriRawData::const_iterator i = Raw.begin(); i != Raw.end(); i++)
			Data.push_back(*i);
		ShowFrameRawData(Data);
	}
}

void CBeaconsDlg::ShowAppearanceFrame(CAppearanceFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Appearance"), IntToHex(Frame->Appearance));
}

void CBeaconsDlg::ShowExtInformationFrame(CExtInformationFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	CString Str;
	switch (Frame->AddressType)
	{
		case atClassic:
			Str = _T("Classic");
			break;
		case atPublic:
			Str = _T("Public");
			break;
		case atRandom:
			Str = _T("Random");
			break;
		case atUnspecified:
			Str = _T("Unpecified");
			break;
		default:
			Str = _T("Unknonw");
			break;
	}
	ShowData(_T("Address type"), Str);
	
	Str = _T("");
	wclBluetoothLeExtendedFrameFlags Flags = Frame->Flags;
	if (Flags.find(efAnonymous) != Flags.end())
		Str = Str + _T(" [Anonymous]");
	if (Flags.find(efConnectable) != Flags.end())
		Str = Str + _T(" [Connectable]");
	if (Flags.find(efDirected) != Flags.end())
		Str = Str + _T(" [Directed]");
	if (Flags.find(efScannable) != Flags.end())
		Str = Str + _T(" [Scannable]");
	if (Flags.find(efScanResponse) != Flags.end())
		Str = Str + _T(" [Scan Response]");
	Str = Str + _T(" ");
	ShowData(_T("Flags"), Str);
	
	ShowData(_T("TX Power"), IntToStr(Frame->TxPower));
}

void CBeaconsDlg::ShowInformationFrame(CInformationFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	CString Str = _T("");
	wclBluetoothLeAdvertisementFlags Flags = Frame->Flags;
	if (Flags.find(afLimitedDiscoverableMode) != Flags.end())
		Str = Str + _T(" [General Discoverable Mode]");
	if (Flags.find(afClassicNotSupported) != Flags.end())
		Str = Str + _T(" [Classic Not Supported]");
	if (Flags.find(afDualModeControllerCapable) != Flags.end())
		Str = Str + _T(" [Dual Mode Controller Capable]");
	if (Flags.find(afDualModeHostCapable) != Flags.end())
		Str = Str + _T(" [Dual Mode Host Capable]");
	Str = Str + _T(" ");
	ShowData(_T("Flags"), Str);
	
	ShowData(_T("Name"), Frame->Name.c_str());
	
	switch (Frame->PacketType)
	{
		case atConnectableUndirected:
			Str = _T("Connectable Undirected");
			break;
		case atConnectableDirected:
			Str = _T("Connectable Directed");
			break;
		case atScannableUndirected:
			Str = _T("Scannable Undirected");
			break;
		case atNonConnectableUndirected:
			Str = _T("Non Connectable Undirected");
			break;
		case atScanResponse:
			Str = _T("Scan Response");
			break;
		case atExtended:
			Str = _T("Extended");
			break;
		default:
			Str = _T("Unknown");
			break;
	}
	ShowData(_T("Packet Type"), Str);
}

void CBeaconsDlg::ShowRawFrame(CRawFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Data Type"), IntToHex(Frame->DataType));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowDetailsFrame(CDetailsFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowService16DataFrame(CService16DataFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), IntToHex(Frame->Uuid));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowService32DataFrame(CService32DataFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), IntToHex(Frame->Uuid));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowService128DataFrame(CService128DataFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), GUIDToString(Frame->Uuid));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowSol16Frame(CSol16Frame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), IntToHex(Frame->Uuid));
}

void CBeaconsDlg::ShowSol32Frame(CSol32Frame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), IntToHex(Frame->Uuid));
}

void CBeaconsDlg::ShowSol128Frame(CSol128Frame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), GUIDToString(Frame->Uuid));
}

void CBeaconsDlg::ShowTxPowerFrame(CTxPowerFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("TX Power"), IntToStr(Frame->TxPower));
}

void CBeaconsDlg::ShowUuidFrame(CUuidFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), GUIDToString(Frame->Uuid));
}

void CBeaconsDlg::ShowAltBeaconFrame(CAltBeaconFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), GUIDToString(Frame->Uuid));
	ShowData(_T("CompanyId"), IntToHex(Frame->CompanyId));
	ShowData(_T("Major"), IntToHex(Frame->Major));
	ShowData(_T("Minor"), IntToHex(Frame->Minor));
	ShowData(_T("TX RSSI"), IntToStr(Frame->TxRssi));
	ShowData(_T("Reserved"), IntToHex(Frame->Reserved));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowEddystoneTlmFrame(CEddystoneTlmFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Advertisements Counter"), IntToStr(Frame->AdvCnt));
	ShowData(_T("Battery status"), IntToStr(Frame->Batt));
	ShowData(_T("Seconds"), IntToStr(Frame->SecCnt));
	ShowData(_T("Temperature"), FloatToStr(Frame->Temp));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowEddystoneUidFrame(CEddystoneUidFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), GUIDToString(Frame->Uuid));
	ShowData(_T("TX RSSI"), IntToStr(Frame->TxRssi));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowEddystoneUrlFrame(CEddystoneUrlFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("TX RSSI"), IntToStr(Frame->TxRssi));
	ShowData(_T("URL"), Frame->Url.c_str());
}

void CBeaconsDlg::ShowManufacturerFrame(CManufacturerFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Company ID"), IntToHex(Frame->CompanyId));
	
	ShowFrameRawData(Frame->Data);
}

void CBeaconsDlg::ShowMicrosoftCdpBeaconFrame(CMicrosoftCdpBeaconFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Address As Device ID"), BoolToStr(Frame->AddressAsDeviceId));
	switch (Frame->DeviceType)
	{
		case dtXboxOne:
			ShowData(_T("Device Type"), _T("Xbox one"));
			break;
		case dtiPhone:
			ShowData(_T("Device Type"), _T("iPhone"));
			break;
		case dtiPad:
			ShowData(_T("Device Type"), _T("iPad"));
			break;
		case dtAndroid:
			ShowData(_T("Device Type"), _T("Android"));
			break;
		case dtWindowsDesktop:
			ShowData(_T("Device Type"), _T("Windows Desktop"));
			break;
		case dtWindowsPhone:
			ShowData(_T("Device Type"), _T("Windows Phone"));
			break;
		case dtLinux:
			ShowData(_T("Device Type"), _T("Linux"));
			break;
		case dtWindowsIoT:
			ShowData(_T("Device Type"), _T("Windows IoT"));
			break;
		case dtSurfaceHub:
			ShowData(_T("Device Type"), _T("Surface Hub"));
			break;
		case dtWindowsLaptop:
			ShowData(_T("Device Type"), _T("Windows Laptop"));
			break;
		case dtWindowsTablet:
			ShowData(_T("Device Type"), _T("Windows Tablet"));
			break;
		default:
			ShowData(_T("Device Type"), IntToHex((unsigned char)Frame->DeviceType));
			break;
	}
	
	CString Str = _T("");
	
	wclBluetoothLeCdpBeaconExtendedDeviceStatuses ExtendedDeviceStatus = Frame->ExtendedDeviceStatus;
	if (ExtendedDeviceStatus.find(edsRemoteSessionsHosted) != ExtendedDeviceStatus.end())
		Str = Str + _T(" [Remote Sessions Hosted]");
	if (ExtendedDeviceStatus.find(edsRemoteSessionsNotHosted) != ExtendedDeviceStatus.end())
		Str = Str + _T(" [Remote Sessions Not Hosted]");
	if (ExtendedDeviceStatus.find(edsNearShareAuthPolicySameUser) != ExtendedDeviceStatus.end())
		Str = Str + _T(" [Near Share Auth Policy Same User]");
	if (ExtendedDeviceStatus.find(edsNearShareAuthPolicyPermissive) != ExtendedDeviceStatus.end())
		Str = Str + _T(" [Near Share Auth Policy Permissive]");
	Str = Str + _T(" ");
	ShowData(_T("Extended Device Status"), Str);
	
	Str = _T("");
	wclBluetoothLeCdpBeaconHash Hash = Frame->Hash;
	if (Hash.size() > 0)
	{
		for (wclBluetoothLeCdpBeaconHash::iterator i = Hash.begin(); i != Hash.end(); i++)
			Str = Str + IntToHex(*i) + _T(" ");
	}
	ShowData(_T("Hash"), Str);
	
	Str = _T("");
	wclBluetoothLeCdpBeaconSalt Salt = Frame->Salt;
	if (Salt.size() > 0)
	{
		for (wclBluetoothLeCdpBeaconSalt::iterator i = Salt.begin(); i != Salt.end(); i++)
			Str = Str + IntToHex(*i) + _T(" ");
	}
	ShowData(_T("Salt"), Str);
	
	switch (Frame->ScenarioType)
	{
		case stBluetooth:
			ShowData(_T("Scenario Type"), _T("Bluetooth"));
			break;
		default:
			ShowData(_T("Scenario Type"), IntToHex((unsigned char)Frame->ScenarioType));
			break;
	}
	
	ShowData(_T("Share Near By"), BoolToStr(Frame->ShareNearBy));
	ShowData(_T("Subversion"), IntToHex(Frame->SubVersion));
	ShowData(_T("Version"), IntToHex(Frame->Version));
}

void CBeaconsDlg::ShowAppleiBeaconFrame(CAppleiBeaconFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("UUID"), GUIDToString(Frame->Data.Uuid));
	ShowData(_T("Major"), IntToHex(Frame->Data.Major));
	ShowData(_T("Minor"), IntToHex(Frame->Data.Minor));
	ShowData(_T("TX RSSI"), IntToStr(Frame->Data.TxRssi));
}

void CBeaconsDlg::ShowAppleNearbyActionFrame(CAppleNearbyActionFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Flags"), IntToHex(Frame->Data.Flags));
	
	switch (Frame->Data.Action)
	{
		case 0x01:
			ShowData(_T("Action"), _T("Apple TV Setup"));
			break;
		case 0x04:
			ShowData(_T("Action"), _T("Mobile Backup"));
			break;
		case 0x05:
			ShowData(_T("Action"), _T("Watch Setup"));
			break;
		case 0x06:
			ShowData(_T("Action"), _T("Apple TV Pair"));
			break;
		case 0x07:
			ShowData(_T("Action"), _T("Internet Relay"));
			break;
		case 0x08:
			ShowData(_T("Action"), _T("WiFi Password"));
			break;
		case 0x09:
			ShowData(_T("Action"), _T("iOS Setup"));
			break;
		case 0x0A:
			ShowData(_T("Action"), _T("Repair"));
			break;
		case 0x0B:
			ShowData(_T("Action"), _T("Speaker Setupd"));
			break;
		case 0x0C:
			ShowData(_T("Action"), _T("Apple Pay"));
			break;
		case 0x0D:
			ShowData(_T("Action"), _T("Whole Home Audio Setup"));
			break;
		case 0x0E:
			ShowData(_T("Action"), _T("Developer Tools Pairing Request"));
			break;
		case 0x0F:
			ShowData(_T("Action"), _T("Answered Call"));
			break;
		case 0x10:
			ShowData(_T("Action"), _T("Ended Call"));
			break;
		case 0x11:
			ShowData(_T("Action"), _T("DD Ping"));
			break;
		case 0x12:
			ShowData(_T("Action"), _T("DD Pong"));
			break;
		case 0x13:
			ShowData(_T("Action"), _T("Remote Auto Fill"));
			break;
		case 0x14:
			ShowData(_T("Action"), _T("Companion Link Proximity"));
			break;
		case 0x15:
			ShowData(_T("Action"), _T("Remote Management"));
			break;
		case 0x16:
			ShowData(_T("Action"), _T("Remote Auto Fill Pong"));
			break;
		case 0x17:
			ShowData(_T("Action"), _T("Remote Display"));
			break;
		default:
			ShowData(_T("Action"), _T("Unknown: 0x") + IntToHex(Frame->Data.Action));
			break;
	}
	
	ShowData(_T("Tag"), IntToHex(Frame->Data.Tag));
	
	switch (Frame->Data.Device)
	{
		case 0x02:
			ShowData(_T("Device"), _T("iPhone"));
			break;
		case 0x04:
			ShowData(_T("Device"), _T("iPod"));
			break;
		case 0x06:
			ShowData(_T("Device"), _T("iPad"));
			break;
		case 0x08:
			ShowData(_T("Device"), _T("Audio accessory (HomePod)"));
			break;
		case 0x0A:
			ShowData(_T("Device"), _T("Mac"));
			break;
		case 0x0C:
			ShowData(_T("Device"), _T("AppleTV"));
			break;
		case 0x0E:
			ShowData(_T("Device"), _T("Watch"));
			break;
		default:
			ShowData(_T("Device"), _T("Unknown: 0x") + IntToHex(Frame->Data.Device));
			break;
	}
	
	wclBluetoothLeAdvertisementFrameRawData Params = Frame->Data.Params;
	if (Params.size() > 0)
	{
		CString Str = _T("");
		for (wclBluetoothLeAdvertisementFrameRawData::iterator i = Params.begin(); i != Params.end(); i++)
			Str += IntToHex(*i);
		ShowData(_T("Params"), Str);
	}
}

void CBeaconsDlg::ShowAppleNearbyInfoFrame(CAppleNearbyInfoFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	if ((Frame->Data.Status & 0x01) != 0)
			ShowData(_T("Primary device"), _T("YES"));
	else
			ShowData(_T("Primary device"), _T("NO"));
	if ((Frame->Data.Status & 0x04) != 0)
			ShowData(_T("AirDrop"), _T("RECEIVING"));
	else
			ShowData(_T("AirDrop"), _T("NOT ACTIVE"));
	
	switch (Frame->Data.Action)
	{
		case 0x00:
			ShowData(_T("Action"), _T("None"));
			break;
		case 0x01:
			ShowData(_T("Action"), _T("Activity reporting disabled"));
			break;
		case 0x03:
			ShowData(_T("Action"), _T("Idle user"));
			break;
		case 0x05:
			ShowData(_T("Action"), _T("Audio playing while screen locked"));
			break;
		case 0x07:
			ShowData(_T("Action"), _T("Active user (screen on)"));
			break;
		case 0x09:
			ShowData(_T("Action"), _T("Screen on with video playing"));
			break;
		case 0x0A:
			ShowData(_T("Action"), _T("Watch on wrist and unlocked"));
			break;
		case 0x0B:
			ShowData(_T("Action"), _T("Recent user interaction"));
			break;
		case 0x0D:
			ShowData(_T("Action"), _T("User is driving a vehicle"));
			break;
		case 0x0E:
			ShowData(_T("Action"), _T("Phone or Facetime Call"));
			break;
		default:
			ShowData(_T("Action"), _T("Unknown: 0x") + IntToHex(Frame->Data.Action));
			break;
	}
	
	if ((Frame->Data.Flags & 0x01) != 0)
		ShowData(_T("AirDrop state"), _T("Connected and Screen ON"));
	else
		ShowData(_T("AirDrop state"), _T("Disconnected"));
	
	if ((Frame->Data.Flags & 0x02) != 0)
		ShowData(_T("Auth tag length"), _T("4 bytes"));
	else
		ShowData(_T("Auth tag length"), _T("3 bytes"));
	
	if ((Frame->Data.Flags & 0x04) != 0)
		ShowData(_T("WiFi"), _T("ON"));
	else
		ShowData(_T("WiFi"), _T("OFF"));
	
	if ((Frame->Data.Flags & 0x10) != 0)
		ShowData(_T("Auth Tag Present"), _T("YES"));
	else
		ShowData(_T("Auth Tag Present"), _T("NO"));
	
	if ((Frame->Data.Flags & 0x20) != 0)
		ShowData(_T("Apple Watch"), _T("LOCKED"));
	else
		ShowData(_T("Apple Watch"), _T("UNLOCKED"));
	
	if ((Frame->Data.Flags & 0x40) != 0)
		ShowData(_T("Apple Watch AutoLock"), _T("ENABLED"));
	else
		ShowData(_T("Apple Watch AutoLock"), _T("DISABLED"));
	
	if ((Frame->Data.Flags & 0x80) != 0)
		ShowData(_T("AutoLock"), _T("ENABLED"));
	else
		ShowData(_T("AutoLock"), _T("DISABLED"));
	
	if ((Frame->Data.Flags & 0x10) != 0)
	{
		if ((Frame->Data.Flags & 0x02) != 0)
			ShowData(_T("Auth Tag"), IntToHex(Frame->Data.Tag));
		else
			ShowData(_T("Auth Tag"), IntToHex(Frame->Data.Tag));
	}
}

void CBeaconsDlg::ShowAppleProximityPairingFrame(CAppleProximityPairingFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Prefix"), IntToHex(Frame->Data.Prefix));
	
	switch (Frame->Data.DeviceModel)
	{
		case 0x2002:
			ShowData(_T("Device mode"), _T("AirPods"));
			break;
		case 0x2003:
			ShowData(_T("Device mode"), _T("Powerbeats 3"));
			break;
		case 0x2005:
			ShowData(_T("Device mode"), _T("BeatsX"));
			break;
		case 0x2006:
			ShowData(_T("Device mode"), _T("Beats Solo 3"));
			break;
		case 0x2007:
			ShowData(_T("Device mode"), _T("Beats Studio 3"));
			break;
		case 0x2009:
			ShowData(_T("Device mode"), _T("Beats Studio 3"));
			break;
		case 0x200A:
			ShowData(_T("Device mode"), _T("AirPods Max"));
			break;
		case 0x200B:
			ShowData(_T("Device mode"), _T("Powerbeats Pro"));
			break;
		case 0x200C:
			ShowData(_T("Device mode"), _T("Beats Solo Pro"));
			break;
		case 0x200D:
			ShowData(_T("Device mode"), _T("Powerbeats 4"));
			break;
		case 0x200E:
			ShowData(_T("Device mode"), _T("AirPods Pro"));
			break;
		case 0x200F:
			ShowData(_T("Device mode"), _T("AirPods 2"));
			break;
		case 0x2010:
			ShowData(_T("Device mode"), _T("Beats Flex"));
			break;
		case 0x2011:
			ShowData(_T("Device mode"), _T("Beats Studio Buds"));
			break;
		case 0x2012:
			ShowData(_T("Device mode"), _T("Beats Fit Pro"));
			break;
		case 0x2013:
			ShowData(_T("Device mode"), _T("AirPods 3"));
			break;
		case 0x2014:
			ShowData(_T("Device mode"), _T("AirPods Pro 2"));
			break;
		default:
			ShowData(_T("Device mode"), _T("Unknown: 0x") + IntToHex(Frame->Data.DeviceModel));
			break;
	}
	
	switch (Frame->Data.Status)
	{
		case 0x01:
			ShowData(_T("Status"), _T("AirPods: Both out of case, not in ear"));
			break;
		case 0x02:
			ShowData(_T("Status"), _T("Right in ear, Left in case"));
			break;
		case 0x03:
			ShowData(_T("Status"), _T("AirPods: Right in ear, Left out of case"));
			break;
		case 0x0B:
			ShowData(_T("Status"), _T("Both AirPods in ear"));
			break;
		case 0x11:
			ShowData(_T("Status"), _T("AirPods: Right out of case, Left in case"));
			break;
		case 0x13:
			ShowData(_T("Status"), _T("AirPods: Right in ear, Left in case"));
			break;
		case 0x21:
			ShowData(_T("Status"), _T("Both taken out of ears, Pause Audio"));
			break;
		case 0x22:
			ShowData(_T("Status"), _T("Left in ear, Right in case"));
			break;
		case 0x23:
			ShowData(_T("Status"), _T("AirPods: Left in ear, Right out of case"));
			break;
		case 0x2B:
			ShowData(_T("Status"), _T("Both AirPods in ear"));
			break;
		case 0x31:
			ShowData(_T("Status"), _T("AirPods: Left out of case, Right in case"));
			break;
		case 0x33:
			ShowData(_T("Status"), _T("AirPods: Left in ear, Right in case"));
			break;
		case 0x51:
			ShowData(_T("Status"), _T("Case: Left out of case, Right in case"));
			break;
		case 0x53:
			ShowData(_T("Status"), _T("Case: Left in ear, Right in case"));
			break;
		case 0x55:
			ShowData(_T("Status"), _T("Case: Both AirPods in case"));
			break;
		case 0x71:
			ShowData(_T("Status"), _T("Case: Right out of case, Left in case"));
			break;
		case 0x73:
			ShowData(_T("Status"), _T("Case: Right in ear, Left in case"));
			break;
		case 0x75:
			ShowData(_T("Status"), _T("Case: Both AirPods in case"));
			break;
		default:
			ShowData(_T("Status"), _T("Unknown: 0x") + IntToHex(Frame->Data.Status));
			break;
	}
	
	ShowData(_T("Left Battery"), IntToStr(Frame->Data.LeftBattery));
	ShowData(_T("Right Battery"), IntToStr(Frame->Data.RightBattery));
	
	if (Frame->Data.CaseCharging)
		ShowData(_T("Case charging"), _T("Yes"));
	else
		ShowData(_T("Case charging"), _T("No"));
	if (Frame->Data.RightCharging)
		ShowData(_T("Right charging"), _T("Yes"));
	else
			ShowData(_T("Right charging"), _T("No"));
	if (Frame->Data.LeftCharging)
		ShowData(_T("Left charging"), _T("Yes"));
	else
		ShowData(_T("Left charging"), _T("No"));
	
	ShowData(_T("Case Battery"), IntToStr(Frame->Data.CaseBattery));
	ShowData(_T("Lid open counter"), IntToStr(Frame->Data.Counter));
	
	switch (Frame->Data.Color)
	{
		case 0x00:
			ShowData(_T("Color"), _T("White"));
			break;
		case 0x01:
			ShowData(_T("Color"), _T("Black"));
			break;
		case 0x02:
			ShowData(_T("Color"), _T("Red"));
			break;
		case 0x03:
			ShowData(_T("Color"), _T("Blue"));
			break;
		case 0x04:
			ShowData(_T("Color"), _T("Pink"));
			break;
		case 0x05:
			ShowData(_T("Color"), _T("Gray"));
			break;
		case 0x06:
			ShowData(_T("Color"), _T("Silver"));
			break;
		case 0x07:
			ShowData(_T("Color"), _T("Gold"));
			break;
		case 0x08:
			ShowData(_T("Color"), _T("Rose Gold"));
			break;
		case 0x09:
			ShowData(_T("Color"), _T("Space Gray"));
			break;
		case 0x0A:
			ShowData(_T("Color"), _T("Dark Blue"));
			break;
		case 0x0B:
			ShowData(_T("Color"), _T("Light Blue"));
			break;
		case 0x0C:
			ShowData(_T("Color"), _T("Yellow"));
			break;
		default:
			ShowData(_T("Color"), _T("Unknown: 0x") + IntToHex(Frame->Data.Color));
	}
	
	ShowData(_T("Suffix"), IntToHex(Frame->Data.Suffix));
	
	CString Str = _T("");
	for (unsigned char i = 0; i < 16; i++)
		Str += IntToHex(Frame->Data.Data[i]);
	ShowData(_T("Encrypted"), Str);
}

void CBeaconsDlg::ShowDriAsdFrame(CDriAsdFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowDriFrameRawData(Frame->Raw);
}

void CBeaconsDlg::ShowFrameData(CFrameStorage* const Frame)
{
	lvFrameDetails.DeleteAllItems();
	
	switch (Frame->Frame)
	{
		case afAppearance:
			ShowAppearanceFrame((CAppearanceFrame*)Frame);
			break;
		case afExtInformation:
			ShowExtInformationFrame((CExtInformationFrame*)Frame);
			break;
		case afInformation:
			ShowInformationFrame((CInformationFrame*)Frame);
			break;
		case afRaw:
			ShowRawFrame((CRawFrame*)Frame);
			break;
		case afDetails:
			ShowDetailsFrame((CDetailsFrame*)Frame);
			break;
		case afService16Data:
			ShowService16DataFrame((CService16DataFrame*)Frame);
			break;
		case afService32Data:
			ShowService32DataFrame((CService32DataFrame*)Frame);
			break;
		case afService128Data:
			ShowService128DataFrame((CService128DataFrame*)Frame);
			break;
		case afSol16:
			ShowSol16Frame((CSol16Frame*)Frame);
			break;
		case afSol32:
			ShowSol32Frame((CSol32Frame*)Frame);
			break;
		case afSol128:
			ShowSol128Frame((CSol128Frame*)Frame);
			break;
		case afTxPower:
			ShowTxPowerFrame((CTxPowerFrame*)Frame);
			break;
		case afUuid:
			ShowUuidFrame((CUuidFrame*)Frame);
			break;
		case afAltBeacon:
			ShowAltBeaconFrame((CAltBeaconFrame*)Frame);
			break;
		case afEddystoneTlm:
			ShowEddystoneTlmFrame((CEddystoneTlmFrame*)Frame);
			break;
		case afEddystoneUid:
			ShowEddystoneUidFrame((CEddystoneUidFrame*)Frame);
			break;
		case afEddystoneUrl:
			ShowEddystoneUrlFrame((CEddystoneUrlFrame*)Frame);
			break;
		case afManufacturerRaw:
			ShowManufacturerFrame((CManufacturerFrame*)Frame);
			break;
		case afMicrosoftCdpBeacon:
			ShowMicrosoftCdpBeaconFrame((CMicrosoftCdpBeaconFrame*)Frame);
			break;
		case afAppleAirdrop:
			ShowAppleAirdropFrame((CAppleAirdropFrame*)Frame);
			break;
		case afAppleAirplaySource:
			ShowAppleAirplaySourceFrame((CAppleAirplaySourceFrame*)Frame);
			break;
		case afAppleAirplayTarget:
			ShowAppleAirplayTargetFrame((CAppleAirplayTargetFrame*)Frame);
			break;
		case afAppleAirprint:
			ShowAppleAirprintFrame((CAppleAirprintFrame*)Frame);
			break;
		case afAppleHomeKit:
			ShowAppleHomeKitFrame((CAppleHomeKitFrame*)Frame);
			break;
		case afAppleiBeacon:
			ShowAppleiBeaconFrame((CAppleiBeaconFrame*)Frame);
			break;
		case afAppleNearbyAction:
			ShowAppleNearbyActionFrame((CAppleNearbyActionFrame*)Frame);
			break;
		case afAppleNearbyInfo:
			ShowAppleNearbyInfoFrame((CAppleNearbyInfoFrame*)Frame);
			break;
		case afAppleProximityPairing:
			ShowAppleProximityPairingFrame((CAppleProximityPairingFrame*)Frame);
			break;
		case afAppleUnknown:
			ShowAppleUnknownFrame((CAppleUnknownFrame*)Frame);
			break;
		case afAppleFindMy:
			ShowAppleFindMyFrame((CAppleFindMyFrame*)Frame);
			break;
		case afAppleHandoff:
			ShowAppleHandoffFrame((CAppleHandoffFrame*)Frame);
			break;
		case afAppleHeySiri:
			ShowAppleHeySiriFrame((CAppleHeySiriFrame*)Frame);
			break;
		case afAppleMagicSwitch:
			ShowAppleMagicSwitchFrame((CAppleMagicSwitchFrame*)Frame);
			break;
		case afAppleTetheringSource:
			ShowAppleTetheringSourceFrame((CAppleTetheringSourceFrame*)Frame);
			break;
		case afAppleTetheringTarget:
			ShowAppleTetheringTargetFrame((CAppleTetheringTargetFrame*)Frame);
			break;
		case afDriAsd:
			ShowDriAsdFrame((CDriAsdFrame*)Frame);
			break;
	}
}

void CBeaconsDlg::AddAdvertisement(CwclBluetoothLeAdvertisement* const Adv)
{
	int Res = LeAdvertiser.Add(Adv);
	if (Res != WCL_E_SUCCESS)
	{
		Trace(_T("Add advertisement"), Res);
		delete Adv;
	}
}

void CBeaconsDlg::OnDestroy()
{
	CDialog::OnDestroy();

	BluetoothManager.Close();

	__unhook(&BluetoothManager);
	__unhook(&LeAdvertiser);
	__unhook(&BeaconWatcher);
}

void CBeaconsDlg::OnBnClickedButtonClearLog()
{
	lbLog.ResetContent();
}

void CBeaconsDlg::OnBnClickedButtonWatcherDefault()
{
	WatcherDefaults();
}

void CBeaconsDlg::OnBnClickedButtonAdvertiserDefault()
{
	AdvertiserDefaults();
}

void CBeaconsDlg::OnBnClickedCheckAdvertiserExtended()
{
	cbAdvertiserAnonymous.EnableWindow(cbAdvertiserExtended.GetCheck());
	cbAdvertiserTxRssi.EnableWindow(cbAdvertiserExtended.GetCheck());
}

BOOL CBeaconsDlg::PreTranslateMessage(MSG* pMsg)
{
	if (pMsg->message == WM_CHAR &&
		(GetFocus() == &edAdvertiserInterval || GetFocus() == &edWatcherScanInterval || GetFocus() == &edWatcherScanWindow))
	{
		if ((pMsg->wParam >= '0' && pMsg->wParam <= '9') || pMsg->wParam == 8)
			return CDialog::PreTranslateMessage(pMsg);
		return TRUE;
	}

	return CDialog::PreTranslateMessage(pMsg);
}

void CBeaconsDlg::BluetoothManagerAfterOpen(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	Trace(_T("Bluetooth Manager opened"));
}

void CBeaconsDlg::BluetoothManagerBeforeClose(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	Trace(_T("Bluetooth Manager is closing"));
	
	LeAdvertiser.Stop();
	BeaconWatcher.Stop();
}

void CBeaconsDlg::BluetoothManagerClosed(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	Trace(_T("Bluetooth Manager closed"));
}

void CBeaconsDlg::OnBnClickedButtonWatcherStart()
{
	CwclBluetoothRadio* Radio = GetRadio();
	if (Radio != NULL)
	{
		BeaconWatcher.AllowExtendedAdvertisements =
			(cbWatcherEnableExtended.GetCheck() != FALSE);
		if (cbWatcherScanMode.GetCurSel() == 0)
			BeaconWatcher.ScanningMode = smActive;
		else
			BeaconWatcher.ScanningMode = smPassive;

		CString s;
		edWatcherScanInterval.GetWindowText(s);
		BeaconWatcher.ScanInterval = LOWORD(_ttoi(s.GetBuffer()));
		edWatcherScanWindow.GetWindowText(s);
		BeaconWatcher.ScanWindow = LOWORD(_ttoi(s.GetBuffer()));

		int Res = BeaconWatcher.Start(Radio);
		if (Res != WCL_E_SUCCESS)
			Trace(_T("Start Watched"), Res);
	}
}

void CBeaconsDlg::OnBnClickedButtonWatcherStop()
{
	int Res = BeaconWatcher.Stop();
	if (Res != WCL_E_SUCCESS)
		Trace(_T("Beacon Watcher stop"), Res);
}


void CBeaconsDlg::BeaconWatcherStarted(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	Trace(_T("Beacon Watcher started"));
	
	WatcherEnableControls(FALSE);
}

void CBeaconsDlg::BeaconWatcherStopped(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	Trace(_T("Beacon Watcher stopped"));
	
	WatcherEnableControls(TRUE);
	
	lvFrameDetails.DeleteAllItems();
	
	if (lvDevices.GetItemCount() > 0)
	{
		for (int i = 0; i < lvDevices.GetItemCount(); i++)
		{
			CFrameStorage* Data = (CFrameStorage*)lvDevices.GetItemData(i);
			if (Data != NULL)
				delete Data;
		}
		
		lvDevices.DeleteAllItems();
	}
}

void CBeaconsDlg::BeaconWatcherAdvertisementAppearanceFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const unsigned short Appearance)
{
	UNREFERENCED_PARAMETER(Sender);

	CAppearanceFrame* Frame = new CAppearanceFrame(Address, Timestamp, Rssi, Appearance);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementExtFrameInformation(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const wclBluetoothAddressType AddressType, const char TxPower,
	const wclBluetoothLeExtendedFrameFlags& Flags)
{
	UNREFERENCED_PARAMETER(Sender);

	CExtInformationFrame* Frame = new CExtInformationFrame(Address, Timestamp, Rssi, AddressType,
		Flags, TxPower);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementFrameInformation(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const tstring& Name, const wclBluetoothLeAdvertisementType PacketType,
	const wclBluetoothLeAdvertisementFlags& Flags)
{
	UNREFERENCED_PARAMETER(Sender);

	CInformationFrame* Frame = new CInformationFrame(Address, Timestamp, Rssi, Flags, Name,
		PacketType);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementRawFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const unsigned char DataType, const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CRawFrame* Frame = new CRawFrame(Address, Timestamp, Rssi, Data, DataType);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementReceived(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CDetailsFrame* Frame = new CDetailsFrame(Address, Timestamp, Rssi, Data);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementService128DataFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const GUID& Uuid, const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CService128DataFrame* Frame = new CService128DataFrame(Address, Timestamp, Rssi, Uuid, Data);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementService16DataFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const unsigned short Uuid, const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CService16DataFrame* Frame = new CService16DataFrame(Address, Timestamp, Rssi, Data, Uuid);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementService32DataFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const unsigned long Uuid, const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CService32DataFrame* Frame = new CService32DataFrame(Address, Timestamp, Rssi, Data, Uuid);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementServiceSol128Frame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi, const GUID& Uuid)
{
	UNREFERENCED_PARAMETER(Sender);

	CSol128Frame* Frame = new CSol128Frame(Address, Timestamp, Rssi, Uuid);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementServiceSol16Frame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const unsigned short Uuid)
{
	UNREFERENCED_PARAMETER(Sender);

	CSol16Frame* Frame = new CSol16Frame(Address, Timestamp, Rssi, Uuid);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementServiceSol32Frame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const unsigned long Uuid)
{
	UNREFERENCED_PARAMETER(Sender);

	CSol32Frame* Frame = new CSol32Frame(Address, Timestamp, Rssi, Uuid);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementTxPowerLevelFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const char TxPower)
{
	UNREFERENCED_PARAMETER(Sender);

	CTxPowerFrame* Frame = new CTxPowerFrame(Address, Timestamp, Rssi, TxPower);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAdvertisementUuidFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const GUID& Uuid)
{
	UNREFERENCED_PARAMETER(Sender);

	CUuidFrame* Frame = new CUuidFrame(Address, Timestamp, Rssi, Uuid);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherAltBeaconFrame(void* Sender, const __int64 Address,
	const __int64 Timestamp, const char Rssi, const unsigned short CompanyId,
	const unsigned short Major, const unsigned short Minor, const GUID& Uuid,
	const char TxRssi, const unsigned char Reserved,
	const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CAltBeaconFrame* Frame = new CAltBeaconFrame(Address, Timestamp, Rssi, Data, Uuid,
		CompanyId, Major, Minor, TxRssi, Reserved);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherEddystoneTlmFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const unsigned long AdvCnt, const unsigned short Batt, const unsigned long SecCnt,
	const double Temp, const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CEddystoneTlmFrame* Frame = new CEddystoneTlmFrame(Address, Timestamp, Rssi, Data, AdvCnt,
		Batt, SecCnt, Temp);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherEddystoneUidFrame(void* Sender, const __int64 Address,
	const __int64 Timestamp, const char Rssi, const char TxRssi, const GUID& Uuid,
	const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CEddystoneUidFrame* Frame = new CEddystoneUidFrame(Address, Timestamp, Rssi, Data, Uuid,
		TxRssi);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherEddystoneUrlFrame(void* Sender, const __int64 Address,
	const __int64 Timestamp, const char Rssi, const char TxRssi, const tstring& Url)
{
	UNREFERENCED_PARAMETER(Sender);

	CEddystoneUrlFrame* Frame = new CEddystoneUrlFrame(Address, Timestamp, Rssi, TxRssi, Url);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherManufacturerRawFrame(void* Sender, const __int64 Address,
	const __int64 Timestamp, const char Rssi, const unsigned short CompanyId,
	const wclBluetoothLeAdvertisementFrameRawData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	CManufacturerFrame* Frame = new CManufacturerFrame(Address, Timestamp, Rssi, CompanyId, Data);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherMicrosoftCdpBeaconFrame(void* Sender,
	const __int64 Address, const __int64 Timestamp, const char Rssi,
	const wclBluetoothLeCdpBeaconScenarioType ScenarioType,
	const unsigned char Version, const wclBluetoothLeCdpBeaconDeviceType DeviceType,
	const unsigned char SubVersion, const bool ShareNearBy, const bool AddressAsDeviceId,
	const wclBluetoothLeCdpBeaconExtendedDeviceStatuses& ExtendedDeviceStatus,
	const wclBluetoothLeCdpBeaconSalt& Salt, const wclBluetoothLeCdpBeaconHash& Hash)
{
	UNREFERENCED_PARAMETER(Sender);

	CMicrosoftCdpBeaconFrame* Frame = new CMicrosoftCdpBeaconFrame(Address, Timestamp, Rssi,
		AddressAsDeviceId, DeviceType, ExtendedDeviceStatus, Hash, Salt,
		ScenarioType, ShareNearBy, SubVersion, Version);
	AddFrame(Frame);
}

void CBeaconsDlg::BeaconWatcherDriAsdMessage(void* Sender, const __int64 Address,
	const __int64 Timestamp, const char Rssi, const wclDriRawData& Raw)
{
	UNREFERENCED_PARAMETER(Sender);

	CFrameStorage* Frame = new CDriAsdFrame(Address, Timestamp, Rssi, Raw);
	AddFrame(Frame);
}

void CBeaconsDlg::OnBnClickedButtonAdvertiserStart()
{
	static const GUID BEACON_UUID = { 0x09039835, 0x4A80, 0x443B, { 0x87, 0xAA, 0xDC, 0x56, 0x5D, 0x09, 0xEA, 0x61 } };

	CwclBluetoothRadio* Radio = GetRadio();
	if (Radio != NULL)
	{
		LeAdvertiser.Clear();

		CwclBluetoothLeAdvertisement* Adv;

		// Create and add iBeacon advdertisement.
		if (cbAdvertiserBeacon.GetCheck())
		{
			Adv = new CwclBluetoothLeiBeaconAdvertisement(-5, 0x0101, 0x0202,
				BEACON_UUID);
			AddAdvertisement(Adv);
		}
		
		// Create and add Proximity Beacon advertisement.
		if (cbAdvertiserProximityBeacon.GetCheck())
		{
			Adv = new CwclBluetoothLeProximityBeaconAdvertisement(-5, 0x0101, 0x0202,
				BEACON_UUID, 0xFFFE);
			AddAdvertisement(Adv);
		}
		
		// Create and add Alt Beacon advertisement.
		if (cbAdvertiserAltBeacon.GetCheck())
		{
			Adv = new CwclBluetoothLeAltBeaconAdvertisement(-5, 0x0101, 0x0202,
				BEACON_UUID, 0xFFFE, 0x11);
			AddAdvertisement(Adv);
		}
		
		// Create and add Eddystone UID advertisement.
		if (cbAdvertiserEddystoneUid.GetCheck())
		{
			Adv = new CwclBluetoothLeEddystoneUidBeaconAdvertisement(-5,
				BEACON_UUID);
			AddAdvertisement(Adv);
		}
		
		// Create and add Eddystone URL.
		if (cbAdvertiserEddystoneUrl.GetCheck())
		{
			Adv = new CwclBluetoothLeEddystoneUrlBeaconAdvertisement(-5, _T("https://www.btframework.com"));
			AddAdvertisement(Adv);
		}
		
		// Create and add custom advertisement.
		wclBluetoothLeAdvertisementFrameRawData Data;

		if (cbAdvertiser128SolUuid.GetCheck())
		{
			Data.resize(16);
			Data[0] = 0xD0;
			Data[1] = 0x00;
			Data[2] = 0x2D;
			Data[3] = 0x12;
			Data[4] = 0x1E;
			Data[5] = 0x4B;
			Data[6] = 0x0F;
			Data[7] = 0xA4;
			Data[8] = 0x99;
			Data[9] = 0x4E;
			Data[10] = 0xCE;
			Data[11] = 0xB5;
			Data[12] = 0x31;
			Data[13] = 0xF4;
			Data[14] = 0x05;
			Data[15] = 0x79;
			Adv = new CwclBluetoothLeCustomAdvertisement(LE_GAP_AD_TYPE_SERVICE_SOL_UUIDS_128, Data);
			AddAdvertisement(Adv);
		}
		
		// Create and add manufacturer specific advertisement.
		if (cbAdvertiserManufacturer.GetCheck())
		{
			Data.resize(2);
			Data[0] = 0x12;
			Data[1] = 0x34;
			Adv = new CwclBluetoothLeManufacturerAdvertisement(0x010E, Data);
			AddAdvertisement(Adv);
		}

		if (cbAdvertiser16Uuid.GetCheck())
		{
			Adv = new CwclBluetoothLe16ServiceAdvertisement(0x9835);
			AddAdvertisement(Adv);
		}
		
		if (cbAdvertiser32Uuid.GetCheck())
		{
			Adv = new CwclBluetoothLe32ServiceAdvertisement(0x09039835);
			AddAdvertisement(Adv);
		}
		
		if (cbAdvertiser128Uuid.GetCheck())
		{
			Adv = new CwclBluetoothLe128ServiceAdvertisement(BEACON_UUID);
			AddAdvertisement(Adv);
		}
		
		if (cbAdvertiser16UuidData.GetCheck())
		{
			Data.resize(2);
			Data[0] = 0x12;
			Data[1] = 0x34;
			Adv = new CwclBluetoothLe16ServiceDataAdvertisement(0x9835, Data);
			AddAdvertisement(Adv);
		}
		
		if (cbAdvertiser32UuidData.GetCheck())
		{
			Data.resize(2);
			Data[0] = 0x12;
			Data[1] = 0x34;
			Adv = new CwclBluetoothLe32ServiceDataAdvertisement(0x09039835, Data);
			AddAdvertisement(Adv);
		}
		
		if (cbAdvertiser128UuidData.GetCheck())
		{
			Data.resize(2);
			Data[0] = 0x12;
			Data[1] = 0x34;
			Adv = new CwclBluetoothLe128ServiceDataAdvertisement(BEACON_UUID,
				Data);
			AddAdvertisement(Adv);
		}

		if (cbAdvertiserCustom.GetCheck())
		{
			Data.resize(20);
			
			// 16 bit Service Data
			Data[0] = 0x09; // Length.
			Data[1] = LE_GAP_AD_TYPE_SERVICE_DATA_16; // Data type.
			Data[2] = 0x12; // 16 UUID LO BYTE
			Data[3] = 0x34; // 16 UUID HI BYTE
			Data[4] = 0xFF; // Data 1st byte
			Data[5] = 0xFE; // Data 2st byte
			Data[6] = 0xFD; // Data 3st byte
			Data[7] = 0xFC; // Data 4st byte
			Data[8] = 0xFB; // Data 5st byte
			Data[9] = 0xFA; // Data 6st byte
			// Manufacturer specific data.
			Data[10] = 0x09; // Length.
			Data[11] = LE_GAP_AD_TYPE_MANUFACTURER; // Data type.
			Data[12] = 0x10; // Company ID.
			Data[13] = 0x12; // Company ID.
			Data[14] = 0x01; // Data 1st byte
			Data[15] = 0x02; // Data 2st byte
			Data[16] = 0x03; // Data 3st byte
			Data[17] = 0x04; // Data 4st byte
			Data[18] = 0x05; // Data 5st byte
			Data[19] = 0x06; // Data 6st byte
			
			Adv = new CwclBluetoothLeRawAdvertisement(Data);
			AddAdvertisement(Adv);
		}

		if (LeAdvertiser.Count == 0)
			AfxMessageBox(_T("Select at least one advertisement type."));
		else
		{
			CString s;
			edAdvertiserInterval.GetWindowText(s);
			LeAdvertiser.Interval = LOWORD(_ttoi(s.GetBuffer()));

			LeAdvertiser.UseExtendedAdvertisement = (cbAdvertiserExtended.GetCheck() != FALSE);
			LeAdvertiser.Anonymous = (cbAdvertiserAnonymous.GetCheck() != FALSE);
			LeAdvertiser.IncludeTxRssi = (cbAdvertiserTxRssi.GetCheck() != FALSE);
			LeAdvertiser.PreferredTxRssi = 10;

			int Res = LeAdvertiser.Start(Radio);
			if (Res != WCL_E_SUCCESS)
				Trace(_T("Start advertiser"), Res);
		}
	}
}

void CBeaconsDlg::OnBnClickedButtonAdvertiserStop()
{
	int Res = LeAdvertiser.Stop();
	if (Res != WCL_E_SUCCESS)
		Trace(_T("Advertiser stop"), Res);
}

void CBeaconsDlg::LeAdvertiserStarted(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	Trace(_T("LE Advertiser started"));
	
	AdvertiserEnableControls(FALSE);
}

void CBeaconsDlg::LeAdvertiserStopped(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	Trace(_T("LE Advertiser stopped"));
	
	AdvertiserEnableControls(TRUE);
}

void CBeaconsDlg::OnLvnItemchangedListDevices(NMHDR *pNMHDR, LRESULT *pResult)
{
	UNREFERENCED_PARAMETER(pNMHDR);

	*pResult = 0;
	
	POSITION Pos = lvDevices.GetFirstSelectedItemPosition();
	if (Pos != NULL)
	{
		int Item = lvDevices.GetNextSelectedItem(Pos);
		if (lvDevices.GetItemData(Item) != NULL)
		{
			ShowFrameData((CFrameStorage*)lvDevices.GetItemData(Item));
			return;
		}
	}
	
	lvFrameDetails.DeleteAllItems();
}

void CBeaconsDlg::BeaconWatcherAppleiBeaconFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleiBeaconFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleiBeaconFrame(Info, Data));
}


void CBeaconsDlg::BeaconWatcherAppleNearbyInfoFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleNearbyInfoFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleNearbyInfoFrame(Info, Data));
}

void CBeaconsDlg::BeaconWatcherAppleNearbyActionFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleNearbyActionFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleNearbyActionFrame(Info, Data));
}

void CBeaconsDlg::BeaconWatcherAppleHomeKitFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleHomeKitFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleHomeKitFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleHomeKitFrame(CAppleHomeKitFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Status"), IntToHex(Frame->Data.Status));
	
	CString Str = _T("");
	for (unsigned char i = 0; i < 6; i++)
		Str += IntToHex(Frame->Data.DeviceId[i]);
	ShowData(_T("Device ID"), Str);
	
	switch (Frame->Data.Category)
	{
		case 0x0000:
			ShowData(_T("Category"), _T("Unknown"));
			break;
		case 0x0001:
			ShowData(_T("Category"), _T("Other"));
			break;
		case 0x0002:
			ShowData(_T("Category"), _T("Bridge"));
			break;
		case 0x0003:
			ShowData(_T("Category"), _T("Fan"));
			break;
		case 0x0004:
			ShowData(_T("Category"), _T("Garage Door Opener"));
			break;
		case 0x0005:
			ShowData(_T("Category"), _T("Lightbulb"));
			break;
		case 0x0006:
			ShowData(_T("Category"), _T("Door Lock"));
			break;
		case 0x0007:
			ShowData(_T("Category"), _T("Outlet"));
			break;
		case 0x0008:
			ShowData(_T("Category"), _T("Switch"));
			break;
		case 0x0009:
			ShowData(_T("Category"), _T("Thermostat"));
			break;
		case 0x000A:
			ShowData(_T("Category"), _T("Sensor"));
			break;
		case 0x000B:
			ShowData(_T("Category"), _T("Security System"));
			break;
		case 0x000C:
			ShowData(_T("Category"), _T("Door"));
			break;
		case 0x000D:
			ShowData(_T("Category"), _T("Window"));
			break;
		case 0x000E:
			ShowData(_T("Category"), _T("Window Covering"));
			break;
		case 0x000F:
			ShowData(_T("Category"), _T("Programmable Switch"));
			break;
		case 0x0010:
			ShowData(_T("Category"), _T("Range Extender"));
			break;
		case 0x0011:
			ShowData(_T("Category"), _T("IP Camera"));
			break;
		case 0x0012:
			ShowData(_T("Category"), _T("Video Doorbell"));
			break;
		case 0x0013:
			ShowData(_T("Category"), _T("Air Purifier"));
			break;
		case 0x0014:
			ShowData(_T("Category"), _T("Heater"));
			break;
		case 0x0015:
			ShowData(_T("Category"), _T("Air Conditioner"));
			break;
		case 0x0016:
			ShowData(_T("Category"), _T("Humidifier"));
			break;
		case 0x0017:
			ShowData(_T("Category"), _T("Dehumidifier"));
			break;
		case 0x001C:
			ShowData(_T("Category"), _T("Sprinklers"));
			break;
		case 0x001D:
			ShowData(_T("Category"), _T("Faucets"));
			break;
		case 0x001E:
			ShowData(_T("Category"), _T("Shower Systems"));
			break;
		default:
			ShowData(_T("Category"), _T("Unknown: 0x") + IntToHex(Frame->Data.Category));
			break;
	}
	
	ShowData(_T("State Number"), IntToHex(Frame->Data.StateNumber));
	ShowData(_T("Config Number"), IntToHex(Frame->Data.ConfigNumber));
	ShowData(_T("Version"), IntToHex(Frame->Data.Version));
}

void CBeaconsDlg::ShowAppleUnknownFrame(CAppleUnknownFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Message ID"), IntToHex(Frame->Data.Id));
	
	wclBluetoothLeAdvertisementFrameRawData Payload = Frame->Data.Payload;
	if (Payload.size() > 0)
	{
		CString Str = _T("");
		
		for (wclBluetoothLeAdvertisementFrameRawData::iterator i = Payload.begin(); i != Payload.end(); i++)
			Str += IntToHex(*i);
		ShowData(_T("Payload"), Str);
	}
}

void CBeaconsDlg::BeaconWatcherAppleUnknownFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleUnknownFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleUnknownFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleAirplaySourceFrame(CAppleAirplaySourceFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Data byte"), IntToHex(Frame->Data.Data));
}

void CBeaconsDlg::ShowAppleAirplayTargetFrame(CAppleAirplayTargetFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Flags"), IntToHex(Frame->Data.Flags));
	ShowData(_T("Seed"), IntToHex(Frame->Data.Seed));
	
	CString Str = IntToStr(Frame->Data.Address >> 24) + _T(".");
	Str += IntToStr((Frame->Data.Address & 0x00FF0000) >> 16) + _T(".");
	Str += IntToStr((Frame->Data.Address & 0x0000FF00) >> 8) + _T(".");
	Str += IntToStr(Frame->Data.Address & 0x000000FF);
	ShowData(_T("IPv4 address"), Str);
}

void CBeaconsDlg::BeaconWatcherAppleAirplaySourceFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirplaySourceFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);
	
	AddFrame(new CAppleAirplaySourceFrame(Info, Data));
}

void CBeaconsDlg::BeaconWatcherAppleAirplayTargetFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirplayTargetFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleAirplayTargetFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleAirdropFrame(CAppleAirdropFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	CString Str = _T("");
	for (unsigned char i = 0; i < 8; i++)
		Str += IntToHex(Frame->Data.Prefix[i]);
	ShowData(_T("Prefix"), Str);
	
	ShowData(_T("Version"), IntToHex(Frame->Data.Version));
	ShowData(_T("Apple ID"), IntToHex(Frame->Data.AppleId));
	ShowData(_T("Phone"), IntToHex(Frame->Data.PhoneNumber));
	ShowData(_T("E-Mail"), IntToHex(Frame->Data.Email));
	ShowData(_T("E-Mail 2"), IntToHex(Frame->Data.Email2));
	ShowData(_T("Suffix"), IntToHex(Frame->Data.Suffix));
}

void CBeaconsDlg::ShowAppleAirprintFrame(CAppleAirprintFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Address type"), IntToHex(Frame->Data.AddressType));
	ShowData(_T("Resource type"), IntToHex(Frame->Data.ResourceType));
	ShowData(_T("Security type"), IntToHex(Frame->Data.SecurityType));
	ShowData(_T("Port"), IntToStr(Frame->Data.Port));
	
	CString Str = _T("");
	for (unsigned char i = 0; i < 15; i++)
		Str += IntToStr(Frame->Data.Address[i]) + _T(".");
	Str += IntToStr(Frame->Data.Address[15]);
	ShowData(_T("Address"), Str);
	
	ShowData(_T("Power"), IntToStr(Frame->Data.Power));
}

void CBeaconsDlg::BeaconWatcherAppleAirdropFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirdropFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);
	
	AddFrame(new CAppleAirdropFrame(Info, Data));
}

void CBeaconsDlg::BeaconWatcherAppleAirprintFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleAirprintFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleAirprintFrame(Info, Data));
}

void CBeaconsDlg::BeaconWatcherAppleProximityPairingFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleProximityPairingFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);
	
	AddFrame(new CAppleProximityPairingFrame(Info, Data));
}

void CBeaconsDlg::BeaconWatcherAppleFindMyFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleFindMyFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleFindMyFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleFindMyFrame(CAppleFindMyFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	switch (Frame->Data.Status)
	{
		case 0x00:
			ShowData(_T("Status"), _T("Owner did not connect within key rotation period (15 min.)"));
			break;
		case 0x24:
			ShowData(_T("Status"), _T("Owner connected with key roation period, Battery Full"));
			break;
		case 0x64:
			ShowData(_T("Status"), _T("Owner connected with key roation period, Battery Medium"));
			break;
		case 0xA4:
			ShowData(_T("Status"), _T("Owner connected with key roation period, Battery Low"));
			break;
		case 0xE4:
			ShowData(_T("Status"), _T("Owner connected with key roation period, Battery Critically Low"));
			break;
		default:
			ShowData(_T("Status"), IntToHex(Frame->Data.Status));
			break;
	}

	CString Str = _T("");
	for (int i = 0; i < 22; i++)
		Str += IntToHex(Frame->Data.Key[i]);
	ShowData(_T("Key"), Str);
	
	switch (Frame->Data.KeyBits)
	{
		case 0x00:
			ShowData(_T("Key bits"), _T("bits 6 and 7 not set in public key"));
			break;
		case 0x01:
			ShowData(_T("Key bits"), _T("bit 6 set in public key"));
			break;
		case 0x02:
			ShowData(_T("Key bits"), _T("bit 7 set in public key"));
			break;
		case 0x03:
			ShowData(_T("Key bits"), _T("bits 6 and 7 set in public key"));
			break;
		default:
			ShowData(_T("Key bits"), IntToHex(Frame->Data.KeyBits));
			break;
	}
	
	ShowData(_T("Hint"), IntToHex(Frame->Data.Hint));
}

void CBeaconsDlg::ShowAppleHandoffFrame(CAppleHandoffFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	if (Frame->Data.Clipboard)
		ShowData(_T("Clipboard"), _T("Yes"));
	else
		ShowData(_T("Clipboard"), _T("No"));
	
	ShowData(_T("Sequence"), IntToStr(Frame->Data.Sequence));
	ShowData(_T("Auth tag"), IntToHex(Frame->Data.AuthTag));

	CString Str = _T("");
	for (int i = 0; i < 10; i++)
		Str += IntToHex(Frame->Data.Data[i]);
	ShowData(_T("Data"), Str);
}

void CBeaconsDlg::BeaconWatcherAppleHandoffFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleHandoffFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);
	
	AddFrame(new CAppleHandoffFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleHeySiriFrame(CAppleHeySiriFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Hash"), IntToHex(Frame->Data.Hash));
	ShowData(_T("Snr"), IntToStr(Frame->Data.Snr));
	
	switch (Frame->Data.Confidence)
	{
		case 0x03:
			ShowData(_T("Confidence"), _T("Not on Wrist"));
			break;
		case 0x1F:
			ShowData(_T("Confidence"), _T("Wrist detection disabled"));
			break;
		case 0x3F:
			ShowData(_T("Confidence"), _T("On Wrist"));
			break;
		default:
			ShowData(_T("Confidence"), IntToHex(Frame->Data.Confidence));
			break;
	}
	
	switch (Frame->Data.DeviceClass)
	{
		case 0x0002:
			ShowData(_T("Device class"), _T("iPhone"));
			break;
		case 0x0003:
			ShowData(_T("Device class"), _T("iPad"));
			break;
		case 0x0007:
			ShowData(_T("Device class"), _T("HomePod"));
			break;
		case 0x0009:
			ShowData(_T("Device class"), _T("MacBook"));
			break;
		case 0x000A:
			ShowData(_T("Device class"), _T("Watch"));
			break;
		default:
			ShowData(_T("Device class"), IntToHex(Frame->Data.DeviceClass));
			break;
	}
	
	ShowData(_T("Rand"), IntToHex(Frame->Data.Rand));
}

void CBeaconsDlg::BeaconWatcherAppleHeySiriFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleHeySiriFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleHeySiriFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleMagicSwitchFrame(CAppleMagicSwitchFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Data"), IntToHex(Frame->Data.Data));
	
	switch (Frame->Data.Confidence)
	{
		case 0x03:
			ShowData(_T("Confidence"), _T("Not on Wrist"));
			break;
		case 0x1F:
			ShowData(_T("Confidence"), _T("Wrist detection disabled"));
			break;
		case 0x3F:
			ShowData(_T("Confidence"), _T("On Wrist"));
			break;
		default:
			ShowData(_T("Confidence"), IntToHex(Frame->Data.Confidence));
			break;
	}
}

void CBeaconsDlg::BeaconWatcherAppleMagicSwitchFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleMagicSwitchFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleMagicSwitchFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleTetheringSourceFrame(CAppleTetheringSourceFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Version"), IntToHex(Frame->Data.Version));
	ShowData(_T("Flags"), IntToHex(Frame->Data.Flags));
	ShowData(_T("Battery"), IntToStr(Frame->Data.Battery));
	
	switch (Frame->Data.CellType)
	{
		case 0x0000:
			ShowData(_T("Cell type"), _T("4G (GSM)"));
			break;
		case 0x0001:
			ShowData(_T("Cell type"), _T("1xRTT"));
			break;
		case 0x0002:
			ShowData(_T("Cell type"), _T("GPRS"));
			break;
		case 0x0003:
			ShowData(_T("Cell type"), _T("EDGE"));
			break;
		case 0x0004:
			ShowData(_T("Cell type"), _T("3G (EV-DO)"));
			break;
		case 0x0005:
			ShowData(_T("Cell type"), _T("3G"));
			break;
		case 0x0006:
			ShowData(_T("Cell type"), _T("4G"));
			break;
		case 0x0007:
			ShowData(_T("Cell type"), _T("LTE"));
			break;
		default:
			ShowData(_T("Cell type"), IntToHex(Frame->Data.CellType));
			break;
	}
	
	ShowData(_T("Bars"), IntToStr(Frame->Data.Bars));
}

void CBeaconsDlg::BeaconWatcherAppleTetheringSourceFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleTetheringSourceFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleTetheringSourceFrame(Info, Data));
}

void CBeaconsDlg::ShowAppleTetheringTargetFrame(CAppleTetheringTargetFrame* const Frame)
{
	ShowFrameBaseData(Frame);
	
	ShowData(_T("Id"), IntToHex(Frame->Data.Id));
}

void CBeaconsDlg::BeaconWatcherAppleTetheringTargetFrame(void* Sender,
	const wclBluetoothLeAdvertisementInfo& Info,
	const wclBluetoothLeAppleTetheringTargetFrameData& Data)
{
	UNREFERENCED_PARAMETER(Sender);

	AddFrame(new CAppleTetheringTargetFrame(Info, Data));
}